Glue42 Platform Features

Service Windows

Service windows are hidden windows which perform a specific supporting role for your apps. They can be configured as any normal window (name, URL, etc.), the difference being that UI configuration isn't necessary, as it is assumed that the purpose of these windows is to provide some background service to your apps. Therefore, the user doesn't need to see them or interact with them.

Service windows may be useful in many scenarios. For instance, you may have a number of apps that will receive and process data from several different providers. Instead of setting up each app to receive and then process the data from every provider, you can create a hidden service window which will communicate with the providers, collect the data, pre-process it and route it to the respective apps. This way, your apps will handle communication with only one end point, all the necessary data is consolidated, processed and filtered at one central data hub from where it can be sent to any window. Depending on your needs and goals, you can configure your service windows to auto start on system startup, or to start when an app requests that service. The service windows approach offers you additional flexibility and versatility in designing solutions for the app services you need.

There are different ways to configure a service window, depending on whether you want the window to be automatically started when Glue42 Enterprise is initiated. Use a combination of the following app configuration properties to specify whether the window should be automatically started, invisible, or hidden from the Glue42 Toolbar:

Property Type Description
"service" boolean If true, both the "autoStart" top-level key and the "hidden" property of the "details" object will be overridden and set to true. The window will be invisible and will start automatically on Glue42 Enterprise startup.
"hidden" boolean If true, the app won't be available in the Glue42 Toolbar.
"autoStart" boolean If true, the window will be started automatically on Glue42 Enterprise startup.
"details" object Use the "hidden" Boolean property of the "details" object to set the window visibility. If true, the window will be invisible.

Note that when using the "service" property, it's pointless to use the "autoStart" top-level key and the "hidden" property of the "details" object, because the "service" key will override any values you may set for them.

The following example demonstrates how to use the "service" and "hidden" top-level keys to configure a service window that will start automatically, will be invisible and hidden from the Glue42 Toolbar:

{
    "name": "service-window",
    "type": "window",
    "service": true,
    "hidden": true,
    "details": {
        "url": "https://example.com/my-service-window",
    }
}

The following example demonstrates how to use the "hidden" and "autoStart" top-level keys and the "hidden" property of the "details" top-level key to configure a service window that will be hidden from the Glue42 Toolbar, won't start automatically and will be invisible:

{
    "name": "service-window",
    "type": "window",
    "hidden": true,
    "autoStart": false,
    "details": {
        "url": "https://example.com/my-service-window",
        "hidden": true
    }
}

Note that service windows aren't closed when restoring a Layout.

For more details, see the Developers > Configuration > Application section and the app configuration schema.

Citrix Apps

Available since Glue42 Enterprise 3.12

Glue42 Enterprise provides experimental support for Citrix Virtual Apps. Citrix apps can participate in the Glue42 environment as first-class citizens - they can be configured and added to the Glue42 Toolbar, saved in Layouts and Workspaces, and can use all Glue42 functionalities like Interop, Channels, etc.

Additionally, Glue42 Enterprise can be run as a Citrix Virtual App itself, in which case any other Virtual Apps from the same VDA can be configured as normal apps. See Dynamic Gateway Port for configuration specifics.

For more details on configuring a Citrix app, see the Developers > Configuration > Application section. For details on configuring the system-wide Citrix Virtual Apps support, see the System Configuration section.

Note that this feature is experimental – although it has been properly tested, additional tests and adjustments might be necessary for your specific Citrix environment.

Note that in order for Glue42 Enterprise to run Citrix Virtual Apps, Citrix Workspace must be installed on the user's machine and the user must be logged into it using their Citrix StoreFront URL and credentials. If you have access to a web-based StoreFront, you can configure your local Citrix Workspace by clicking on the "Activate" link in the settings or user preferences menu and running the downloaded file. The StoreFront SSL certificate must be trusted by the user's machine.

.NET Citrix Apps

To Glue42 enable a .NET Citrix app:

  1. In your Visual Studio project, reference the Glue42.dll available in the Glue42 NuGet package.

  2. Follow the standard procedure for Glue42 enabling .NET apps.

  3. After initializing Glue42, you can check whether your app is connected to Glue42 in the following manner:

using Tick42.StartingContext;
if (InitializeOptions.IsCitrixGD)
{
    // Running in Citrix, connected to Glue42 Enterprise.
}
else if (InitializeOptions.IsCitrixVirtualApp)
{
    // Running in Citrix, not connected to Glue42 Enterprise.
}

When your Citrix app is connected to Glue42 Enterprise, you may want to remove any custom window decorations, since the top-level window chrome will be handled by Glue42 Enterprise.

  1. Add %** to the app arguments in the Citrix Application Settings:

Citrix Application Settings

  1. Configure your app as a Glue42 Citrix app.

You will now be able to run your .NET Citrix app from Glue42 Enterprise and interoperate with it using the various Glue42 APIs.

Java Citrix Apps

To Glue42 enable a Java Citrix app:

  1. Follow the standard procedure for Glue42 enabling Java apps.

  2. In the Citrix Application Settings, set the path to a javaw.exe or java.exe file, use standard VM arguments to launch your Java app, and add %** at the end of the app arguments:

Citrix Application Settings

  1. Configure your app as a Glue42 Citrix app.

You will now be able to run your Java Citrix app from Glue42 Enterprise and interoperate with it using the various Glue42 APIs.

Preload Scripts

Available since Glue42 Enterprise 3.13

The app configuration file allows you to specify preload scripts for an app. The preload scripts will be executed before the actual web app is loaded and before each <iframe> on the page. Use the "preloadScripts" array of the "details" top-level key in the app configuration file to define the scripts and they will be executed in the specified order. This allows for easily injecting Glue42 functionality into third-party web apps over which you have little to no control.

The following example demonstrates defining two preload scripts by providing their respective URLs:

{
    "details": {
        "preloadScripts": [
            "https://my-domain.com/my-script.js",
            "https://my-domain.com/my-other-script.js"
        ]
    }
}

Available since Glue42 Enterprise 3.15

Preload scripts can be defined globally in the system configuration of Glue42 Enterprise. Use the "preloadScripts" property of the "windows" top-level key in the system.json file:

{
    "windows": {
        "preloadScripts": [
            "https://my-domain.com/my-script.js",
            "https://my-domain.com/my-other-script.js"
        ]
    }
}

Global Protocol Handler

Available since Glue42 Enterprise 3.12

When you install Glue42 Enterprise, it is registered as the default handler of the Glue42 global protocol. The protocol is in the following format:

glue42://<option>/<identifier>[?args&args]

To pass arguments when employing the different options of the Glue42 global protocol, use a single ? after the identifier, except with url - use double ?? when passing arguments for the url protocol option. Use & between the arguments when specifying more than one argument.

The Glue42 global protocol allows you to create and send links which will open a URL in a Glue42 Window. You can also create links that will start a Glue42 enabled app, load a specified Workspace or Layout and even invoke Interop methods with custom arguments.

When the link is clicked, Glue42 Enterprise will be started in order to handle it. If an instance of Glue42 Enterprise is already running, it will be reused. If multiple instances are running (e.g., in different environments), then the user will be presented with a dialog from which to choose the Glue42 instance that will handle the link:

Protocol Dialog

Configuration

The Glue42 global protocol can be configured from the system.json file of Glue42 Enterprise using the "potocolHandler" top-level key:

{
    "protocolHandler": {
        "enabled": true,
        "allowOpeningURLs": {
            "allowed": ["https://glue42.com"],
            "forbidden": ["https://youtube.com/.*", "https://facebook.com/.*"]
        }
    }
}

The "protocolHandler" key has the following properties:

Property Type Description
"enabled" boolean If true (default), will enable the Glue42 global protocol handler.
"protocol" string Custom name for the protocol prefix. Defaults to "glue42".
"startNewInstance" object If enabled, a new instance of Glue42 will be started when opening links with the Glue42 protocol handler.
"allowOpeningURLs" boolean | object If true, will allow handling all URLs. Can also be set to an object containing a list of allowed or forbidden URLs for the Glue42 global protocol handler.

The "startNewInstance" object has the following properties:

Property Type Description
"enabled" boolean If true (default), will allow starting a new instance of Glue42 when opening links with the Glue42 protocol handler.
"defaultExecutable" object An object with two properties - "path" and "args". The "path" property accepts a string path to an executable file that will be started if no other Glue42 instance is running. Defaults to the Glue42 executable file. The "args" property accepts a string array with items, each item representing a command line argument. Defaults to an empty array. Note that if you point the "path" property to a script file that in turn will launch Glue42 Enterprise, then you must pass the startup arguments from the script to Glue42 Enterprise.
"errorMessage" string Message that will override the default error message displayed when starting a new Glue42 instance is disabled.

The "allowOpeningURLs" property can be set to an object with the following properties:

Property Type Description
"allowed" string[] List of allowed URLs. All other URLs will be forbidden.
"forbidden" string[] List of forbidden URLs. All other URLs will be allowed.

You can use exact URL values or regular expressions to specify allowed and forbidden URLs.

Protocol Options

The Glue42 global protocol can be used in different formats depending on what you want to do.

Apps

To start a Glue42 enabled app, use the app protocol option and pass the app name:

glue42://app/clientlist

To pass startup options for a Glue42 enabled app, use ? after the app identifier and & before each settings. The following example demonstrates passing a location and context for the started app:

glue42://app/clientlist?left=100&context.clientID=1

To specify a property of an object as an option, use the standard dot notation - e.g., context.clientID=42.

Layouts

To restore a Global Layout, use the layout protocol option and pass the name of the Layout:

glue42://layout/StartOfDay

Workspaces

To open a Workspace, use the workspace protocol option and pass the Workspace name:

glue42://workspace/StartOfDay

To pass context for the Workspace, use context:

glue42://workspace/StartOfDay?context.clientID=1

To specify a property of an object as an option, use the standard dot notation - e.g., context.clientID=42.

Glue42 Windows

To open a URL in a Glue42 Window, use the url protocol option and pass the URL:

glue42://url/https://google.com 

To specify Glue42 Window settings when opening a URL, use ?? after the URL and & before each setting. The following example demonstrates passing a location for the newly opened window:

glue42://url/https://google.com??left=100&top=200

To specify a property of an object as a setting, use the standard dot notation - e.g., downloadSettings.autoSave=false.

Interop Methods

To invoke an Interop method, use the invoke protocol option and pass the method name:

glue42://invoke/Shutdown

To pass arguments and/or target when invoking an Interop method, use args and target:

glue42://invoke/ShowClient?args.clientId=1&target=best

Downloading Files

Glue42 Enterprise allows for files to be downloaded by clicking on a link in the web page or by invoking an Interop method.

Downloading Files

Configuration

The file download behavior is controlled by the system configuration. It can be alternatively overridden by the app configuration. The system download behavior configuration can be set in the system.json file of Glue42 Enterprise from the "downloadSettings" property of the "windows" top-level key:

System configuration example:

{
    "windows": {
        "downloadSettings": {
            "autoSave": true,
            "autoOpenPath": false,
            "autoOpenDownload": false,
            "enable": true,
            "enableDownloadBar": true,
            "path": "%DownloadsFolder%"
        }
    }
}

The "downloadSettings" object has the following properties:

Property Type Description
"autoSave" boolean If true, will auto save the file (without asking the user where to save it). If false, a system save dialog will appear.
"autoOpenPath" boolean If true, will open the folder that contains the downloaded file after the download is completed.
"autoOpenDownload" boolean If true, will open the download file after the download is completed.
"enable" boolean If true, enables the window to download files.
"enableDownloadBar" boolean If true, a download bar tracking the progress will appear at the bottom of the window when downloading. If false, the download process will be invisible.
"path" string Path where the downloaded file will be saved. Due to security reasons, it is only possible to provide two download paths: the Windows "Temp" or "Downloads" folder.

You can also override the default system download behavior in the app configuration JSON file:

{
    "title": "Download Test Files",
    "type": "window",
    "name": "download-test-files",
    "details": {
        "url": "https://downloadtestfiles.com/",
        "top": 100,
        "left": 400,
        "width": 800,
        "height": 800,
        "allowCollapse": false,
        "startLocation": "center",
        "downloadSettings": {
            "autoSave": false
        }
    }
}

Clicking on a Link in the Web Page

When a user clicks on a download link in the website, the download will start and Glue42 Enterprise will show the download bar in the page.

The user has options to:

  • cancel the download;
  • pause and later resume the download;
  • open the downloaded file in the containing folder;

Invoking an Interop Method

On startup, Glue42 Enterprise registers an Interop method "T42.Wnd.DownloadFile" which you can invoke with the following arguments in order to download files programmatically:

Parameter Type Description
url string Required. Download link.
name string Optional. File name.
path string Optional. Location for the file.
autoOpenDownload boolean Optional. If true, will open the file after download. Defaults to false.
autoOpenPath boolean Optional. If true, will open the location of the file. Defaults to false.

When downloading the selected file, the cookies for that domain are taken and sent together with the request.

Note that if the file name already exists, the downloaded file will be saved with an incremented number in the name (e.g., my-docs(2).pdf).

Using the Window Management API

Download settings can also be specified using the Window Management API (for more details, see Downloads.

Opening URLs in the Default Browser

Available since Glue42 Enterprise 3.13

Glue42 Enterprise comes with a predefined app which can be used to open a URL in the default browser using the App Management API. The following example shows how to open a URL in the default browser by using the JavaScript App Management API.

Get the Application instance by passing the name of the app - "open-browser", invoke the start method to start the app and pass a starting context with a url property holding the URL:

const url = "https://glue42.com";

await glue.appManager.application("open-browser").start({ url });

Note that only URLs with HTTP or HTTPS protocols can be opened.

Available since Glue42 Enterprise 3.11

Search in web apps opened in Glue42 Windows just like in a browser with the CTRL + F command:

Search

Use ENTER and SHIFT + ENTER to scroll through the results. Click ESC to close the search bar.

Context Menu

Glue42 Enterprise has a right-click context menu available in all Glue42 apps for which it has been enabled. It offers standard cut/copy/paste actions, zoom and spelling controls:

Context menu

Enable the context menu:

  • globally for all apps, under the "windows" top-level key in the system.json file:
{
    "windows": {
        "contextMenuEnabled": true
    }
}
  • per app, under the "details" top-level key of the app configuration file:
[
    {
        "details": {
            "contextMenuEnabled": true
        }
    }
]

Telemetry Data

Available since Glue42 Enterprise 3.17

Glue42 Enterprise exposes telemetry data containing info related to the system environment and the running web apps.

On a system level, you can gather data about:

  • Focus duration, start and stop events for apps.
  • Step-by-step system startup flow events. Can be used to investigate slow startups.
  • All system log entries.
  • System CPU and memory usage.

For web apps, you can gather data about:

  • All network request per app.
  • All app console logs.
  • Web page exceptions caught by the window "error" event.
  • CPU and memory usage per process.

Telemetry data events can also be cleared. To get or clear telemetry data, you must invoke the "T42.Telemetry" Interop method passing the respective command and configuration for getting or clearing telemetry data entries.

Configuration

To enable or disable telemetry data, use the "telemetry" top-level key of the system.json configuration file of Glue42 Enterprise:

{
    "telemetry": {
        "enabled": false
    }
}

Getting Data

To get telemetry data, invoke the "T42.Telemetry" Interop method. As a second argument for the invocation, pass an object with command and config properties. For the command property, use "GetEvents" as a value to specify that the method should get telemetry data. Use the config property to specify what type of telemetry data you want to receive - for the system environment, for the running web apps, or for both:

// Name of the Interop method.
const methodName = "T42.Telemetry";
// Settings for the method invocation.
const args = {
    command: "GetEvents",
    config: { system: true, apps: true }
};
// Invoking the "T42.Telemetry" method to get telemetry data.
const result = await glue.interop.invoke(methodName, args);
// Extracting the returned data object.
const data = result.returned;

console.log(data);

The object passed as an argument for the method invocation has the following properties:

Property Type Description
command "GetEvents" | "ClearEvents" Specifies the action to execute - get or clear telemetry data.
config object Specifies what type of telemetry data to get or clear.

The config object for requesting telemetry data has the following properties:

Property Type Description
system boolean | object Specifies whether to get system data. Pass an object to refine the data request (see Refining Telemetry Requests).
apps boolean | object Specifies whether to get web app data. Pass an object to refine the data request (see Refining Telemetry Requests).

Data Shape

The object returned from the invocation of the "T42.Telemetry" Interop method when requesting telemetry data, has the following shape:

const data = {
    type: "gd",
    data: {
        system: {},
        apps: [],
        stores : {}
    }
};

The system object has the following properties:

Property Type Description
logErrors object[] Each item of the array holds an error entry from the system logs.
startupEvents object[] Each item of the array holds information about a single startup flow event.
journeyEvents object[] Each item of the array holds information about focus duration, start and stop events for a specific web app.
perfData object Holds information about overall and per app CPU and memory usage.

The apps property is an array of objects with the following properties:

Property Type Description
app string The app name as defined in its configuration file.
instance string Unique ID within the Glue42 environment.
info object Contains specific data about the app - instance ID, API version, window type, URL and more.
requests object[] Each item of the array holds information about a specific network request made by the app.
console object[] Each item of the array holds information about a message logged to the console.
errors object[] Each item of the array holds information about a web page exception caught by the window "error" event.

The stores object has the following properties:

Property Type Description
logs object Contains information about the number of items in the store, the total store size and the time of the last update.
journeyEvents object Contains information about the number of items in the store, the total store size and the time of the last update.
requests object Contains information about the number of items in the store, the total store size and the time of the last update.
console object Contains information about the number of items in the store, the total store size and the time of the last update.

Refining Telemetry Requests

When requesting telemetry data, you can specify what type of system and web app data entries you want to receive. Use the system and apps properties of the config object refine your telemetry request:

const methodName = "T42.Telemetry";
const args = {
    command: "GetEvents",
    config: {
        // Omit data about startup flow events and CPU and memory usage.
        system: { withStartupEvents: false, withPerfData: false },
        // Omit data about console messages logged by web apps.
        apps: { withConsole: false }
    }
};
const result = await glue.interop.invoke(methodName, args);
const data = result.returned;

console.log(data);

The system property of the config object accepts an object with the following properties:

Property Type Description
withStartupEvents boolean Whether to receive data about the system startup flow events.
withPerfData boolean Whether to receive data about system CPU and memory usage.
withJourneyEvents boolean Whether to receive data about focus duration, start and stop events for web apps.
withLog boolean Whether to receive data about system log entries.

The apps property of the config object accepts an object with the following properties:

Property Type Description
withConsole boolean Whether to receive data about console messages logged by web apps.
withRequests boolean Whether to receive data about network requests made by web apps.
withErrors boolean Whether to receive data about web page exceptions caught by the window "error" event.

Clearing Data

To clear telemetry data, invoke the "T42.Telemetry" Interop method and pass "ClearEvents" as a value to the command property of the argument object for the method invocation. Use the config object to specify what type of telemetry data entries to clear:

// Name of the Interop method.
const methodName = "T42.Telemetry";
// Settings for the method invocation.
const args = {
    command: "ClearEvents",
    config: {
        requests: true,
        journeyEvents: true,
        logs: true,
        console: true
    };
};
// Invoking the "T42.Telemetry" method to clear telemetry data.
const result = await glue.interop.invoke(methodName, args);
// Extracting the returned data object.
const data = result.returned;

// Will print an empty object, as all entries have been cleared.
console.log(data);

The config object for clearing telemetry data has the following properties:

Property Type Description
requests boolean Whether to clear data about network requests made by web apps.
journeyEvents boolean Whether to clear data about focus duration, start and stop events for web apps.
logs boolean Whether to clear data about system log entries.
console boolean Whether to clear data about console messages logged by web apps.

Jump List

Available since Glue42 Enterprise 3.15

The jump list is a configurable categorized list of actions that can be shown in the context menu when the user right-clicks on a taskbar icon of a Glue42 enabled app or a group of such icons:

Jump List

Note that currently the jump list isn't available for web groups.

Configuration

The jump list can be enabled, disabled and configured globally and per app. The app configuration will override the global system configuration.

Note that the jump list configuration allows you to enable or disable the jump list and configure the predefined actions (e.g., change their names or icons), but in order to add custom jump list categories and actions for your apps, you must use the jump list API.

To configure the jump list system-wide, use the "jumpList" property of the "windows" top-level key in the system.json file of Glue42 Enterprise. The following is the default system jump list configuration:

{
    "windows": {
        "jumpList": {
            "enabled": true,
            "categories": [
                {
                    "title": "Tasks",
                    "actions": [
                        {
                            "icon": "%GDDIR%/assets/images/center.ico",
                            "type": "centerScreen",
                            "singleInstanceTitle": "Center on Primary Screen",
                            "multiInstanceTitle": "Center all on Primary Screen"
                        }
                    ]
                }
            ]
        }
    }
}

The "jumpList" object has the following properties:

Property Type Description
"enabled" boolean If true (default), will enable the jump list.
"categories" object[] Categorized lists with actions to execute when the user clicks on them.

Each object in the "categories" array has the following properties:

Property Type Description
"title" string Title of the category to be displayed in the context menu.
"actions" object[] List of actions contained in the category.

Each object in the "actions" array has the following properties:

Property Type Description
"icon" string Icon for the action to be displayed in the context menu. Must point to a local file.
"type" string Type of the predefined action to execute.
"singleInstanceTitle" string Title of the action to be displayed in the context menu when there is a single instance with a single taskbar icon.
"multiInstanceTitle" string Title of the action to be displayed in the context menu when there are multiple instances with grouped taskbar icons.

To override the system configuration per app, use the "jumpList" property of the "details" top-level key in the app configuration file. The following example demonstrates how to disable the jump list for an app:

{
    "title": "My App",
    "type": "window",
    "name": "my-app",
    "details": {
        "url": "https://downloadtestfiles.com/",
        "jumpList": {
            "enabled": false
        }
    }
}

Predefined Actions

To use a predefined action, set the "type" property of the action object to the respective value (see Jump List > Configuration). The following are the currently supported predefined actions:

  • "centerScreen" - centers an app or a group of app instances on the primary screen. This action is extremely useful when you have many windows open on multiple displays and can't find the app you need. Use this action to find an app that: you may have moved to another screen or outside the screen bounds altogether; may be hidden behind other windows; may have been resized and become too small to notice; or may have simply blended visually with other apps:

Center on Primary

  • "newWorkspace" - opens a new Workspace. This action by default is part of the jump list for the Workspaces App. Clicking on the action opens a new empty Workspace in the last opened instance of the Workspaces App. If this action is part of the jump list for another app and the Workspaces App isn't currently open when the user clicks on the action, it will be started:

New Workspace

Jump List API

Available since Glue42 Enterprise 3.17

The jump list API is accessible through the GDWindow object which describes an instance of a Glue42 Window:

const myWindow = glue.windows.my();
// Check whether the jump list is enabled for the current window.
const isJumpListEnabled = await myWindow.jumpList.isEnabled();

Enable or Disable the Jump List

To enable or disable the jump list dynamically, use the setEnabled() method and pass a Boolean value as an argument:

const myWindow = glue.windows.my();

// Checking whether the jump list is enabled for the current window.
const isJumpListEnabled = await myWindow.jumpList.isEnabled();

if (!isJumpListEnabled) {
    // Enabling the jump list.
    await myWindow.jumpList.setEnabled(true);
};

Categories

Jump list categories are used for grouping actions in a section under a common name. You can find a category by name, get a list of all available categories, create a new category or remove an existing one. The categories API is accessible through the jumpList.categories object.

To find a category by name, use the find() method:

const myCategory = await myWindow.jumpList.categories.find("My Category");

To get a list of all available categories, use the list() method:

const categoryList = await myWindow.jumpList.categories.list();

To create a category, use the create() method. Pass a title for the category and a list of JumpListActionSettings objects describing the actions in the category:

// Category settings.
const title = "My Category";
const actions = [
   {
        // Icon for the action. Must point to a local file.
        icon: "../images/action-one.ico",
        // Callback that will be executed when the user clicks on the action.
        callback: () => console.log("Action 1"),
        // Title of the action when there is a single instance with a single taskbar icon.
        singleInstanceTitle: "Execute Action 1",
        // Title of the action when there are multiple instances with grouped taskbar icons.
        multiInstanceTitle: "Execute Action 1 for All"
    },
    {
        icon: "../images/action-two.ico",
        callback: () => console.log("Action 2"),
        singleInstanceTitle: "Execute Action 2",
        multiInstanceTitle: "Execute Action 2 for All"
    }
];

// Creating a category.
await myWindow.jumpList.categories.create(title, actions);

To remove a category, use the remove() method and pass the category title as an argument:

await myWindow.jumpList.categories.remove("My Category");

Actions

Each JumpListCategory object has an actions property through which you can access the actions API. You can create, remove or list all available actions in the current category.

To get a list of all available actions in a category, use the list() method:

const myCategory = await myWindow.jumpList.categories.find("My Category");

const actions = await myCategory.actions.list();

To create an action in a category, use the create() method. Pass a list of JumpListActionSettings objects describing the actions.

The following example demonstrates creating an action in the "Tasks" category that will toggle the Glue42 theme:

// Finding a category.
const category = await myWindow.jumpList.categories.find("Tasks");
// Action settings.
const actions = [
    {
        icon: "../images/toggle-theme.ico",
        // This action will toggle the Glue42 theme.
        callback: async () => {
            const currentTheme = await glue.themes.getCurrent();
            if (currentTheme.name === "dark") {
                glue.themes.select("light");
            } else {
                glue.themes.select("dark");
            };
        },
        singleInstanceTitle: "Toggle Theme",
        multiInstanceTitle: "Toggle Theme"
    }
];

// Creating actions for an existing category.
await category.actions.create(actions);

Jump List Action

To remove one or more actions from a category, use the remove() method and pass a list of JumpListActionSettings objects to remove:

const actions = [
   {
        icon: "../images/action-one.ico",
        callback: () => console.log("Action 1"),
        singleInstanceTitle: "Execute Action 1",
        multiInstanceTitle: "Execute Action 1 for All"
    },
    {
        icon: "../images/action-two.ico",
        callback: () => console.log("Action 2"),
        singleInstanceTitle: "Execute Action 2",
        multiInstanceTitle: "Execute Action 2 for All"
    }
];

// Removing actions from a category.
await category.actions.remove(actions);

Hotkeys

The Hotkeys API allows apps to register key combinations and receive notifications when a key combination is pressed by the user irrespective of whether the app is on focus or not. Hotkeys is useful for web apps that don't have access to system resources and can't register global shortcuts.

Configuration

You can control the hotkeys behavior from the system.json file under the "hotkeys" top-level key. You can find the system.json in the %LocalAppData%\Tick42\GlueDesktop\config folder.

Hotkeys configuration example:

{
    "hotkeys": {
        "enabled": true,
        "blacklist": ["appManager"],
        "reservedHotkeys": ["ctrl+c", "ctrl+p", "ctrl+s"]
    }
}

The hotkeys object has the following properties:

Property Type Description
"enabled" boolean If true, hotkeys will be enabled.
"whitelist" string[] List of apps that can register hotkeys. Any app not on the list won't be able to register hotkeys.
"blacklist" string[] List of apps that can't register hotkeys. Any app not on the list will be able to register hotkeys.
"reservedHotkeys" string[] List of reserved (system or other) hotkeys that can't be overridden by other apps.

Hotkeys API

The Hotkeys API is accessible through the glue.hotkeys object. To register a hotkey, your app must be using a Glue42 JavaScript version newer than 4.3.5.

To register a hotkey, use the register() method:

// Define a hotkey object.
const hotkeyDefinition = {
    hotkey: "shift+alt+c",
    description: "Open Client Details"
};

// This function will be invoked when the hotkey is pressed.
const hotkeyHandler = () => {
    glue.appManager.application("Client Details").start();
};

// Register the hotkey.
await glue.hotkeys.register(hotkeyDefinition, hotkeyHandler);

To remove a hotkey, use the unregister() and pass the value of the hotkey combination as an argument:

await glue.hotkeys.unregister("shift+alt+c");

To remove all hotkeys registered by your app, use the unregisterAll() method:

await glue.hotkeys.unregisterAll();

To check if your app has registered a specific hotkey, use the isRegistered() method:

// Returns a Boolean value.
const isRegistered = glue.hotkeys.isRegistered("shift+alt+c");

Hotkeys View

There is a utility view that allows you to see all hotkeys registered by different apps. You can open it from the Glue42 Enterprise tray icon menu - right-click on the tray icon to display the menu. When you click on the Hotkeys item you will see a list of the hotkeys registered by your app:

Hotkeys

For a complete list of the available Hotkeys API methods and properties, see the Hotkeys API Reference Documentation.

Zooming

Glue42 Enterprise supports zooming in and out of windows of JavaScript apps. Zooming can be controlled via configuration (system-wide or per app) or programmatically via the available methods/properties of a window instance.

You can zoom in and out of windows in several ways:

  • CTRL + = (zoom in) and CTRL + - (zoom out);
  • CTRL + MOUSE SCROLL;
  • CTRL + 0 - resets to the default zoom factor;
  • mouse pad gestures;
  • using the right-click context menu (if enabled);

Note that zooming is based on domain - i.e., if you open two apps with the same domain and change the zoom factor of one of them, the zoom factor of the other will change accordingly.

Zooming

Configuration

You can configure window zooming system-wide from the system.json file in the %LocalAppData%\Tick42\GlueDesktop\config folder. Use the "zoom" property under the "windows" top-level key:

{
    "windows": {
        "zoom": {
            "enabled": true,
            "mouseWheelZoom": true,
            "factors": [25, 33, 50, 67, 75, 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500],
            "defaultFactor": 100
        }
    }
}
Property Type Description
"enabled" boolean If true, zooming will be enabled.
"mouseWheelZoom" boolean If true, will enable zooming with CTRL + mouse scroll.
"factors" number[] List of zoom factors to be used when the user zooms in or out of the window. The factors must be in ascending order and may have integer or floating point values. Zooming will only work with factor values within the range of 25 to 500. Avoid passing negative values when setting the zoom factor (via configuration or programmatically), as this will cause unexpected behavior.
"defaultFactor" number Default zoom factor within the range of 25 to 500. Avoid negative values.

You can also enable zooming per app which will override the system-wide zoom configuration. Use the "zoom" property under the "details" top-level key of the app configuration file:

[
    {
        "title": "MyApp",
        "type": "window",
        "name": "myApp",
        "details": {
            "url": "http://localhost:22080/my-app/index.html",
            "zoom": {
                "enabled": true,
                "mouseWheelZoom": true,
                "factors": [25, 33, 50, 67, 75, 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500],
                "defaultFactor": 100
            }
        }
    }
]

Using Zoom Programmatically

There are several methods and properties exposed on the window instance, which you can use to control zoom behavior.

Get the current zoom factor:

const win = glue.windows.my();

console.log(win.zoomFactor);

Zoom in:

// Will zoom in the window to the next factor in the "factors" array.
await win.zoomIn();

Zoom out:

// Will zoom out the window to the previous factor in the "factors" array
await win.zoomOut();

Set a desired zoom factor:

await win.setZoomFactor(number);

Carefully consider all cases if you intend to pass a zoom factor value based on a logic in your app. Negative values will cause unexpected behavior. Passing positive values lower than 25 will cause zoom out with a factor of 25, positive values higher than 500 will cause zoom in with a factor of 500 and passing zero as a factor will preserve the previous zoom factor.

Listening for zoom factor changes:

// Returns a function which you can use to unsubscribe from events for zoom factor changes.
const unsubscribe = win.onZoomFactorChanged(w => {
    console.log(`Zoom factor changed to ${w.zoomFactor}`)
});

unsubscribe();

Displays

Available since Glue42 Enterprise 3.9

Glue42 Enterprise provides a way for apps to programmatically capture screenshots of the available monitors. Based on custom logic you can capture one or all monitors in order to save a snapshot of the visual state at a given moment.

Configuration

To enable display capturing you must add the "allowCapture" property to your app configuration file and set it to true.

{
    "name": "MyApp",
    "type": "window",
    "allowCapture": true,
    "details": {
        "url": "http://localhost:3000"
    }
}

Displays API

The Displays API is accessible through the glue.displays object.

All Displays

To get all displays, use the all() method. It returns an array of all available Display objects:

const allDsiplays = await glue.displays.all();

Primary Display

You can get the primary display with the getPrimary() method:

// Returns the primary display.
const primaryDisplay =  await glue.displays.getPrimary();

Example of finding and capturing the primary display:

const display = await glue.displays.getPrimary();
const screenshot = await display.capture({ scale:0.5 });

Specific Display

To get a specific display, use the get() method. It accepts a display ID as an argument and resolves with a Display object:

const displayID = 2528732444;

// returns a display by ID
const display = await glue.displays.get(displayID);

The Display Object

The Display object has the following properties:

Property Description
id Unique identifier associated with the display.
bounds A Bounds object with height, width, left and top properties, describing the bounds of the display.
workArea A Bounds object describing the working area of the display (the desktop area, excluding taskbars, docked windows and toolbars).
dpi Dots per inch resolution of the display.
isPrimary A boolean value specifying whether this is the primary display.
index Index assigned to the display by the operating system.
name Name assigned to the display by the operating system.
aspectRatio Display aspect ratio (e.g., 16:9).
scaleFactor The scale factor of the returned display (e.g., 1.25 = 125%).

Capturing All Displays

To capture all displays, use the captureAll() method. It accepts a CaptureAllOptions object and returns a Base64 encoded string or an array of Base64 encoded strings depending on the specified combined option.

The following example demonstrates how to capture all available displays and combine the screenshots into a single image with width set to 2000 pixels. The aspect ratio of the combined images will be preserved (the omitted keepAspectRatio property in the size object defaults to true) and the images will be arranged the way you have arranged your displays from your operating system settings:

const screenshot = await glue.displays.captureAll({ combined: true, size: { width: 2000 } });

The CaptureAllOptions object has the following properties:

Property Type Description
combined boolean Required. If true, will return a single image of all captured displays. If false, will return separate images for all captured displays.
size object Optional. Accepts either a ScaleOptions or an AbsoluteSizeOptions object, specifying the size of the output image.

Capturing a Single Display

To capture a single display, use the capture() method at top level of the API or on a Display instance.

When you use the capture() method at top level of the API, pass a CaptureOptions object. The following example demonstrates how to use the display ID to find and capture the desired display and also how to specify capturing options. The width and height of the output image will be half the width and height of the captured monitor. The captured image is returned as a Base64 encoded string:

const displayID = 2528732444;
const captureOptions = {
    id: displayID,
    size: { scale: 0.5 }
}

const screenshot = await glue.displays.capture(captureOptions);

The CaptureOptions object has the following properties:

Property Type Description
id number Required. ID of the targeted display.
size object Optional. Accepts either a ScaleOptions or an AbsoluteSizeOptions object, specifying the size of the output image.

The ScaleOptions object has only one property - scale, which accepts a number. The value you pass to it specifies the size of the output image relative to the actual screen size. For instance, if you use scale: 0.5 the height and width of the output image will be half the height and width of the captured screen.

The AbsoluteSizeOptions object has the following properties, all of which are optional:

Property Type Description
width number Specifies the width of the output image. Defaults to the captured display width.
height number Specifies the height of the output image. Defaults to the captured display height.
keepAspectRatio boolean Whether to keep the aspect ratio of the output image when you specify width and/or height of the output image. If true and both width and height are set, then the specified width will be used as a basis for the output image aspect ratio.

When you use the capture() method of a Display instance, pass either a ScaleOptions or an AbsoluteSizeOptions object, specifying the size of the output image. The following example demonstrates how to find and capture all non-primary displays:

const screenshots = await Promise.all(
            // Get all displays.
            (await glue.displays.all())
            // Filter out the primary display.
            .filter(display => !display.isPrimary)
            .map(display => display.capture({ scale: 0.5 })));

Capturing Windows and Window Groups

You can use the capture() method of a Glue42 Window instance or a Glue42 Window group to capture the respective window or window group. This method works also for minimized windows and window groups but doesn't work for hidden windows.

// Capture the current window.
const windowScreenshot = await glue.windows.my().capture();

// Capture the current group.
const groupScreenshot = await glue.windows.groups.my.capture();

Events

Available since Glue42 Enterprise 3.13

The onDisplayChanged() method allows you to handle the event that fires when a display has been modified - its resolution or position has changed, a display has been connected or disconnected, etc. Pass a handler that will be invoked each time a display changes and use the list of Display objects that it receives as an argument to react to the changes:

const handler = (displays) => {
    // React to DPI changes, display connected or disconnected, monitor position changed, etc.
    console.log(displays);
};

glue.displays.onDisplayChanged(handler);

For a complete list of the available Displays API methods and properties, see the Displays API Reference Documentation.

Logging

Available since Glue42 Enterprise 3.9

Glue42 Enterprise offers a Logger API which enables JavaScript apps to create a hierarchy of sub-loggers mapped to app components where you can control the level of logging for each component. You can also route the output of log messages (depending on the logging level) to a variety of targets - the developer console or an external output (usually a rolling file on the desktop, but actually any target the log4net library supports).

Note that you can also customize the logging mechanism of Glue42 Enterprise through its logging configuration.

Adding logging to files to your JavaScript apps can be helpful in a variety of ways. Having a well-designed and meaningful logging structure in your apps and their components can save a lot of time when debugging an app during development or troubleshooting problems with an app in production.

Configuration

Logging for apps in Glue42 Enterprise is disabled by default. To allow it, use the "allowLogging" top-level key in the app configuration file:

{
    "allowLogging": true
}

Logger API

The Logger API is accessible through the glue.logger object.

Logger instances have a subLogger() method that creates a new sub-logger of the current logger. The name of each logger instance is a dot delimited string containing all names of the loggers constituting an hierarchy line from the base logger (the app name) down to the current logger. This allows an effective and intuitive logging structure which can be easily adjusted to the component hierarchy in your app. For instance, a structure like app-name.main-component.sub-component gives you a clear idea from where the respective log entry originates and helps you find the necessary information much faster in a log file that may (and usually does) contain thousands of entries.

To use a logger in your Glue42 enabled apps, create a logger instance with the subLogger() method and assign the logger a name:

const logger = glue.logger.subLogger("main-component");

Next, set the logging level at which to publish log entries to the file. Use the publishLevel() method of the logger instance:

logger.publishLevel("info");

Everything at and above the specified logging level will be logged, all else will be skipped. The available logging levels are "trace", "debug", "info", "warn" and "error".

To log messages, either use the log() method of the logger instance, or the respective logging level methods - error(), trace(), etc.

// The log() method accepts a message and logging level as arguments.
logger.log("Couldn't load component!", "error");

// or

// Each logging level method accepts only a message as an argument.
logger.error("Couldn't load component!");

Location and Output

User app log files are located in the %LocalAppData%\Tick42\UserData\<ENV>-<REG>\logs\applications folder, where <ENV>-<REG> must be replaced with the environment and region of your Glue42 Enterprise copy (e.g., T42-DEMO). A separate log file is created for each app that has logging enabled. The file is named after the app and is created after the app starts to output log entries. All instances of an app log to the same file.

The log file entries are in the following format:

[<DATE>T<TIME>] [<LOGGING_LEVEL>] [<INSTANCE_ID>] [<LOGGER_NAME>] - <LOG_MESAGE>

Here is how an actual entry in a log file looks like:

[2020-03-11T14:27:58.087] [ERROR] [30760_11] [client-list.test-logger] - test-error
    at t.error (http://localhost:22080/client-list/desktop-4.8.0.js:1:39269)
    at <anonymous>:1:8

For a complete list of the available Logger API methods and properties, see the Logger API Reference Documentation.

Cookies

Available since Glue42 Enterprise 3.16

Web apps can retrieve, filter, set and remove cookies programmatically by using the Glue42 Cookies API.

Configuration

By default, Glue42 enabled web apps aren't allowed to manipulate cookies. To allow an app to manipulate cookies, use the "allowCookiesManipulation" property of the "details" top-level key in the app configuration file:

{
    "details": {
        "allowCookiesManipulation": true
    }
}

Cookies API

The Cookies API is accessible through the glue.cookies object.

Get

To retrieve all cookies, use the get() method:

const allCookies = await glue.cookies.get();

The get() method returns a list of Cookie objects.

To filter the cookies, pass a CookiesGetFilter object with the properties which you want to use as a filter.

The following example demonstrates filtering cookies by domain:

const filter = { domain: "glue42.com" };

// Get a list of cookies for the same domain.
const filteredCookies = await glue.cookies.get(filter);

The CookiesGetFilter object has the following optional properties, which you can use in any combination to filter the cookies:

Property Type Description
url string Retrieves the cookies which are associated with the specified URL. If not specified, will retrieve the cookies for all URLs.
name string Filters the cookies by name.
domain string Retrieves the cookies whose domains match or are subdomains of the specified domain.
path string Retrieves the cookies whose path matches the specified path.
secure boolean Filters cookies by their Secure attribute.
session boolean If true, will return only the session cookies. If false, will return only the persistent cookies.

Set

To create a cookie, use the set() method. It accepts as a required argument a CookiesSetDetails object with a required url property:

const cookie = {
    url: "https://example.com",
    name: "MyCookie",
    value: "42"
};

await glue.cookies.set(cookie);

The CookiesSetDetails object has the following properties:

Property Type Description
url string Required. URL to associate with the cookie.
name string Name for the cookie.
value string Value for the cookie.
domain string Domain for the cookie. Will be normalized with a preceding dot in order to be valid for subdomains too.
path string Path for the cookie.
secure boolean If true, the cookie will be marked with a Secure attribute. Default is false, unless the SameSite attribute has been set to None.
httpOnly boolean If true, the cookie will be marked with an HttpOnly attribute. Default is false.
expirationDate number The expiration date of the cookie as a number of seconds since the UNIX epoch. If not specified, the cookie will become a session cookie and won't be persisted between sessions.
sameSite "unspecified" | "no_restriction" | "lax" | "strict" The value to be applied to the SameSite attribute. If set to "no_restriction", the secure property will be set automatically to true. Default is "lax".

Remove

To remove a cookie, use the remove() method and pass the cookie URL and name:

const url = "https://example.com";
const name = "MyCookie";

await glue.cookies.remove(url, name);

Accessing OS Info

Available since Glue42 Enterprise 3.13

You can allow apps to access OS information (list of running processes, OS version, Glue42 start time) through their app configuration. The information can then be retrieved through the glue42gd object injected in the global window object when the app is started.

Configuration

Set the "allowOSInfo" property to true in the "details" top-level key to allow an app to access OS information:

{
    "details": {
        "allowOSInfo": true
    }
}

Retrieving Info

Use the glue42gd object injected in the global window object to retrieve the necessary information:

// Returns a list of all running processes.
const processes = await glue42gd.os.getProscesses();

// Extracting the PID, name and start time of the first process from the list.
const { pid, name, startTime } = processes[0];

// Returns the OS version as a string.
const version = glue42gd.os.getVersion();

// Returns the Glue42 start time as a string - e.g., "2021-10-20T06:54:49.411Z".
const startTime = glue42gd.glue42StartTime;

Clearing DNS & HTTP Cache

Available since Glue42 Enterprise 3.17

To allow an app to clear the DNS or HTTP cache, use the "allowClearingCache" top-level key of the app configuration file. Methods for clearing the cache are available on the glue42gd object attached to the global window object.

Allowing an app to clear cache:

{
    "allowClearingCache": true
}

Clearing HTTP and DNS cache:

// Clearing the HTTP cache.
await glue42gd.clearCache();
// Clearing the DNS cache.
await glue42gd.clearHostResolverCache();

Adding DevTools Extensions

You can extend the Chrome DevTools in Glue42 Enterprise with additional extensions. To add a DevTools Extension supported by Electron, you need to have the extension installed and add a configuration for it in the system.json file of Glue42 Enterprise and in the configuration file of your app. The example below demonstrates adding the React DevTools Extension to Glue42 Enterprise:

  1. Install the React DevTools Chrome extension.

  2. Locate the extension on your local machine - the default location for the React DevTools Extension is %LocalAppData%\Google\Chrome\User Data\Default\Extensions\fmkadmapgofadopljbjfkapdkoienihi. (You can move the extension installation folder wherever you like.)

  3. Open the system.json configuration file of Glue42 Enterprise located in %LocalAppData%\Tick42\GlueDesktop\config and add the path to the React DevTools Extension under the "devToolsExtensions" top-level array:

{
    "devToolsExtensions": [
        "C:\\Users\\<username>\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Extensions\\fmkadmapgofadopljbjfkapdkoienihi\\4.23.0_0"
    ]
}

Replace <username> with your local username. The path must point to the version folder of the extension containing the manifest.json file. Remember to escape the backslash characters.

  1. Open the JSON configuration file of your app and add the following configuration under the "details" top-level key:
{
    "security": {
        "sandbox": false
    }
}

For instance:

{
    "name": "My App",
    "details": {
        "url": "http://localhost:3000",
        "security": {
            "sandbox": false
        }
    }
}
  1. Start Glue42 Enterprise, open your Glue42 enabled app and you should be able to see the added extension to the Chrome DevTools when you open the developer console. In this case, you will need a React app in order to be able to see the React DevTools Extension.