OpenFin

Platform API

Overview

We are pleased to introduce the experimental release of OpenFin Platforms. Our approach addresses several key concerns and improvements that were identified through the use of our Layouts V1 API. Improvements include:

  • Platform APIs are included in the OpenFin JavaScript API, removing the need to call a separate Service.
  • The introduction of OpenFin Views allows the separation of concerns between content and windowing via the creation of view Layouts. Layouts give application providers the ability to embed multiple views within a single window.

Key points

  • The Platform API is included in OpenFin’s JavaScript API
  • Layouts give app providers the ability to embed multiple views in a single window
  • Support for tabbed, grid, and fixed Layout configuration of Views within the window
  • Support for a custom platform manager to provide end-user ability to create layouts for each window
  • Applications have the ability to customize windows

Dependencies

  • OpenFin Runtime 14.78.48.15+ [Experimental]

Getting Started

  • This Getting Started guide will take you through 5 essential components of OpenFin Platforms:
  • The Platform API is injected into OpenFin’s JavaScript API and available via the fin object.
  • Currently in an experimental state with new methods to be added in the future. APIs and functionality are subject to change.
  • In order to utilize the Platform API, you must be in a window that is part of a manifest-launched Platform. By definition, a "Platform" is a collection of Windows and their Layouts under a specific namespace.
  • It is important that you utilize these APIs in place of other fin APIs wherever possible. We have custom logic in these APIs to ensure that all Platforms functionality runs smoothly.

Requirements


1. Launching a Platform

In order to use the API, your window must be a part of a manifest-launched Platform. Let's launch one.

First, copy the JSON below, paste it into your IDE of choice, and save it as app.json.

Next, open your terminal, navigate to the folder containing your app.json file, and run the following command to launch your Platform.

openfin -l -c app.json

Try dragging the tabs within a window to reposition the views, or drag onto another window's tabset to move the view to a new window.

Click on JSON and copy the code shown.

Save it as app.json, and launch that app.json with the following command:

openfin -l -c app.json
{
    "platform": {
        "uuid": "example_platform",
        "applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico",
        "autoShow": false,
        "defaultWindowOptions": {
            "cornerRounding": {
                "height": 10,
                "width": 10
            },
            "contextMenu": true
        }
    },
    "snapshot": {
        "windows": [
            {
                "defaultWidth": 600,
                "defaultHeight": 600,
                "layout": {
                    "content": [
                        {
                            "type": "stack",
                            "content": [
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        "name": "component_A1",
                                        "processAffinity": "ps_1",
                                        "url": "https://www.example.com"
                                    }
                                },
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        "name": "component_A2",
                                        "url": "https://cdn.openfin.co/embed-web/chart.html"
                                    }
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "defaultWidth": 600,
                "defaultHeight": 600,
                "defaultLeft": 200,
                "defaultTop": 200,
                "layout": {
                    "content": [
                        {
                            "type": "stack",
                            "content": [
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        "name": "component_B1",
                                        "url": "https://openfin.co"
                                    }
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    },
    "runtime": {
        "arguments": "--v=1 --inspect",
        "version": "stable"
    },
    "shortcut": {
        "company": "OpenFin",
        "description": "OpenFin Platforms Prototype",
        "icon": "https://openfin.github.io/golden-prototype/favicon.ico",
        "name": "OpenFin Platforms Prototype"
    }
}

For more details on the Platform Manifest structure (such as the difference between a platform and a snapshot), navigate here.


2. Creating a New Platform Window

Now we have our Platform. Let's create a new Window, along with a View, using the Platform API.

Open up the developer console from one of your Platform Views. Paste the following code into your console and hit enter. You should see a new Platform Window appear, with http://www.example.com displayed within it.

let platform = await fin.Platform.getCurrent();
let myWinIdentity = await platform.createWindow({
    contextMenu: true,
    layout: {
        content: [{
            type: 'stack',
            content:[{
                type: 'component',
                componentName: 'view',
                componentState: {
                    name: 'my-new-test-view',
                    url: 'http://www.example.com' // The URL of the View
                }
            }]
        }]
    }
});

3. Adding a New View to an Existing Platform Window

Now that we have a new Platform Window, let's add an additional View to that Window.

Paste the following code into the same console you were previously using. The createView function takes two arguments: View Configuration Options and Target Identity. The Target Identity is the identity of the window that the View will be attached to.

You should see an additional View appear in the Window you just created.

// The `platform`and `myWinIdentity` here are the objects we captured in step 2
platform.createView(
    { // View Configuration Options
        name: 'my-new-test-view-2',
        url:'http://www.example.com'
    }, 
    myWinIdentity // Target Identity
);

4. Getting and Applying Snapshots

Now we have our brand-new Platform Window with two Views loaded into it. If we like the way our Platform looks at this point in time, it would be nice to be able to jump back to it whenever we like. That's where Snapshots come in. Here's how they work.

Getting a Snapshot

Paste the following code into the same console you were using before and hit enter. In the console, you should see a returned Snapshot Object. This is the object that Platforms uses to return the desktop back to this current state. You can store this object wherever you'd like, and use it later on to apply this Snapshot.

// The `platform` here is the object we captured in step 2
const mySnapshot = await platform.getSnapshot();
console.log(mySnapshot);

Applying a Snapshot

Now that we have generated our Snapshot Object, let's use it to recreate our desktop. First, let's shuffle our desktop around a bit. Close the window you created earlier (the one filled with www.example.com Views), move your windows to different locations, and move the Views in those windows to different locations. Execute the code below to get your desktop back to the way it was before.

// The `platform` here is the object we captured in step 2
platform.applySnapshot(mySnapshot, {closeExistingWindows: true});

There are other APIs currently in development, but this should be enough to get you started playing around with the new Platform API.


5. Window Customization

Windows created using OpenFin Platforms act as a host (or container) for Views. If your content is rendered in Views, your window can instead be used to display UI controllers, and acts as a “frame” on top of which views are drawn.

5.1. Standard Window

OpenFin Platforms comes packaged with OpenFin’s Standard Window by default, which has standard window controls (close, minimize, maximize) and some style customizability. As the name suggests, the Standard Window is used as the default window you get if you don’t specify the window’s URL upon creation.

OpenFin’s Standard Window

OpenFin’s Standard Window

Standard Window Customization

You can easily apply your own stylesheet to the standard window by specifying the stylesheetUrl prop within defaultWindowOptions in your manifest:

{
    "platform": {
        "uuid": "example_platform",
        "defaultWindowOptions": {
            "stylesheetUrl": "url-to-css-stylesheet"
        }
    },
    "snapshot": {
        ...
    }
}

Overriding Standard Frame CSS selectors

To get an idea of the selectors that are available for you to override, take a look at the layouts v2 style examples or simply inspect the window using Chrome Developer Tools

5.2. Complete Window Customization

You can also optionally overwrite OpenFin's Standard Window and bring your own window instead. To do so, specify the url property as a window option in your manifest. This HTML file must specify a div component with the ID layout-container where you want the layout to be rendered. This will ensure that the window has a target to render the layout in. A url can also be specified in windowOptions in a snapshot, or when launching a snapshot via other methods.

{
    "platform": {
        "uuid": "example_platform",
        "defaultWindowOptions": {
            "url": "url-to-html-file"
        }
    },
    "snapshot": {
        ...
    }
}

defaultWindowOptions.stylesheetUrl and Custom Window

Note that defaultWindowOptions.stylesheetUrl is only supported for overriding standard window styles. If you are providing a custom window, simply include your stylesheets in your custom html document.

5.3. Using Keyboard Commands

(COMING IN v15.80.49.x) OpenFin defines and implements a set of optional commands and behaviors specific to Platforms. You can configure keyboard shortcuts for the commands you will be using in the commands property of the platform object in your manifest. For the list and details of the properties of command items, see the hotkeys option on Window.

{
    "platform": {
        "uuid": "example_platform",
        "defaultWindowOptions": {
            ...
        },
        "commands": [
            {
                "command": "stack.nextTab",
                "keys": "Ctrl+T"
            }
        ]
    },
    "snapshot": {
        ...
    }
}

Currently provided commands:

  • stack.nextTab - switches to the next tab in the stack
  • stack.previousTab - switches to the previous tab in the current stack

Diving deeper

OpenFin Views

At the core of Platforms is a separation of concerns between content and windowing. Content (a web application) is loaded into an OpenFin View which is then attached to a window. Views have their own JavaScript context that is distinct and unconnected to the window’s context, and thus they have no DOM representation within the window. This allows views to move between windows without refreshing or otherwise destroying the context. However, views have no windowing functionality of their own. They must be attached to a window, and given bounds relative to that window, in order to display their content. Unlike IFrames, Views can be moved between windows without refreshing, and can be used to display non-embeddable content.

Views are accessed via the fin.View API. However, when using OpenFin Platforms, please utilize the fin.Platform API as much as possible.

Note:

Native JavaScript window.open is not currently supported in views.

Architecture

A Platforms application has the following architecture:

  • A Platform Controller that exposes functionality for coordinating views and windows.
  • One or more child windows of the controller, which may or may not have a layout of views. A collection of windows is referred to as a snapshot.
  • One or more views, which provide content. These can be split into as many render processes as needed. They reside as part of a window's layout.

All of the child windows of a Platforms application share a single renderer process. The views of an app share a process based on same-origin policy. Views can be separated into further processes by providing a processAffinity option. If you would like to have two or more views share a process separate from other views, you can give them the same processAffinity string. If you’ve architected your platform into multiple apps in order to manage render processes, it is now possible to have multiple processes in a single app.

Launching Platform and Snapshots

Let's take a closer look at the Platform Configuration that we covered in Launching a Platform. To launch the Platform, use a manifest that has a top-level platform object instead of a startup_app object. This configuration object lets you define platform-level options such as defaultWindowOptions and defaultViewOptions.

A Snapshot can optionally be added as a top-level property to any manifest. If a Platform is launched without a Snapshot, it will launch just a headless controller. Once running, applications and Snapshots can be launched into the Platform using the following methods:

API calls

Once a Platform has been launched and is running, Snapshots can be launched into the Platform using applySnapshot. Content can also be launched into the Platform by manifest using startFromManifest. If that manifest also contains a snapshot object, that Snapshot will be launched. If you are launching a legacy manifest without a Snapshot, the startup_app will be launched as a single view in a new window.

Deep Linking (fins link)

The RVM permits deep linking to an OpenFin application from anywhere that can invoke a “link” like a browser, email client, or another OpenFin application. The RVM uses a custom protocol handler to invoke an application, if not already running, and pass context to a specific location within an OpenFin application via a uniform resource identifier (URI).

You can designate a snapshot manifest or legacy app manifest to be launched into the platform using deep linking by adding a appManifestUrl parameter that points at the manifest url. If an appManifestUrl parameter is included and the platform is not running, any snapshot that exists on the platform manifest will be ignored and instead the content designated at the appManifestUrl will be launched. If the content manifest designated in the parameter does not have a snapshot property but does have a startup_app property, then the platform will attempt to launch a single window with a single view that takes the applicable startup_app options in the manifest (similar to the launchLegacyManifest API).

Example Deep Link launching content:
fins://mydomain.com/path-to-platform-manifest/app.json?$$appManifestUrl=https://mydomain.com/path-to-content-manifest/

Manifest JSON Structure

platform

Defines the Platform as a targetable unique entity. Requires a top-level platform property and a uuid. If you are previous accustomed to OpenFin manifest structure, platform acts in the same way as your startup_app field.

{
    "runtime": {
      ...
    },
    "shortcut": {
      ...
    },
    "platform": {
        "uuid": "platform-example",
        "defaultWindowOptions": {
            "stylesheetUrl": "css-sheet-url",
            "cornerRounding": {
                "height": 10,
                "width": 10
            }
        }
    }
}
snapshot

Defines the window and view configurations to be launched into a platform. If a snapshot is defined as a top-level option in your Platform manifest, the Platform will launch with that Snapshot by default. It has a windows property that contains an array of OpenFin Window objects. Windows should not be given names, because they can be destroyed and re-created by the user at any time.

{
    "snapshot": {
       "windows": [
            {
                "defaultWidth": 600,
                "defaultHeight": 600,
                "layout": {
                    ...
                }
            }
        ]
    }
}
layout

Contains the layout configuration for a window. To position an OpenFin View within a window, your layout must contain a content declaration with a componentName of view. Content items have a "type" property, which can have the following values: "row", "column", "stack", or "component". Arrays of content items can be nested within other content items as well. Because of the complexity of this object, we recommend that you use our config generation tool to generate it, instead of writing this object yourself. Please include the scheme in the URL (http:/ or https://). See example layouts below for further explanation of the type.

{
    "snapshot": {
        "windows": [
            {
                "defaultWidth": 600,
                "defaultHeight": 600,
                "layout": {
                    "content": [
                        {
                            "type": "stack",
                            "content": [
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        ...
                                    }
                                },
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        ...
                                    }
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
}
componentState

We leverage the componentState property to provide the OpenFin View Options.

{
    "snapshot": {
        "windows": [
            {
                "defaultWidth": 600,
                "defaultHeight": 600,
                "layout": {
                    "content": [
                        {
                            "type": "stack",
                            "content": [
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        "name": "component_A1",
                                        "processAffinity": "ps_1",
                                        "url": "https://www.example.com"
                                    }
                                },
                                {
                                    "type": "component",
                                    "componentName": "view",
                                    "componentState": {
                                        "name": "component_A2",
                                        "url": "https://cdn.openfin.co/embed-web/chart.html"
                                    }
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
}

Example Layouts

Platforms allows end-users the freedom to easily move views within an OpenFin window to create their own customized workspace. Application providers may also wish to have presets that launch multiple views in a pre-configured window arrangement. These JSON objects can become large and complicated. Because of the complexity of this object, we recommend that you use our config generation tool to generate it. With this tool, you can create Platforms-ready JSON files by dragging and dropping views, instead of composing the object manually. Below are some examples of pre-configured view arrangements:

Note: Top-level content item cannot contain more than one element.

Columns or Rows
In the JSON tab, you will find an example JSON of a window object
within a layout that has three views arranged as columns.  Please
note that components inside a row will show up as columns.  There is
no need to nest the components in a “stack” item to create the header
and tab indicator, this will be created automatically.  To arrange
them as rows instead, please swap the `type` below from `row` to 
`column` and vice versa.
"content": [
  {
    "type": "row",
    "content": [
      {
        "type": "component",
        "componentName": "view",
        "componentState": {
          "name": "component_C",
          "url": "https://cdn.openfin.co/embed-web/chart.html"
        }
      },
      {
        "type": "component",
        "componentName": "view",
        "componentState": {
          "name": "component_D",
          "url": "https://openfin.co"
        }
      },
      {
        "type": "component",
        "componentName": "view",
        "componentState": {
          "name": "component_E",
          "url": "https://www.example.com"
        }
      }
    ]
  }
]
Tabs
In the JSON tab, you will find an example JSON of a window object
within a snapshot that has one tabset (or “stack”) with three views
represented as tabs.
{
  "content": [
    {
      "type": "stack",
      "content": [
        {
          "type": "component",
          "componentName": "view",
          "componentState": {
            "name": "component_E",
            "url": "https://cdn.openfin.co/embed-web/chart.html"
          }
        },
        {
          "type": "component",
          "componentName": "view",
          "componentState": {
            "name": "component_F",
            "url": "https://openfin.co"
          }
        },
        {
          "type": "component",
          "componentName": "view",
          "componentState": {
            "name": "component_G",
            "url": "https://www.example.com"
          }
        }
      ]
    }
  ]
}

Grid (“the Quad”)

In the JSON tab, you will find an example JSON of a window object 
within a snapshot that has four views arranged as a 2x2 grid, or
a "quad".
{
  "content": [
    {
      "type": "row",
      "content": [
        {
          "type": "row",
          "content": [
            {
              "type": "column",
              "content": [
                {
                  "type": "component",
                  "componentName": "view",
                  "componentState": {
                    "name": "component_A",
                    "url": "https://cdn.openfin.co/embed-web/chart.html"
                  }
                },
                {
                  "type": "component",
                  "componentName": "view",
                  "componentState": {
                    "name": "component_B",
                    "url": "https://cdn.openfin.co/embed-web/chart.html"
                  }
                }
              ]
            }
          ]
        },
        {
          "type": "row",
          "content": [
            {
              "type": "column",
              "content": [
                {
                  "type": "component",
                  "componentName": "view",
                  "componentState": {
                    "name": "component_C",
                    "url": "https://www.example.com"
                  }
                },
                {
                  "type": "component",
                  "componentName": "view",
                  "componentState": {
                    "name": "component_D",
                    "url": "https://www.openfin.co"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Known issues

  • Drag regions exhibit erratic behavior in Mac
  • Network errors encountered during page load can cause error messages to flash if page loads successfully

RoadMap

Feature Set
ETA / Delivered
OF Version
  • Snapshot restoration improvements
  • Window to View context events
  • Default View Options

14.78.48.*

  • API Logic Customization
  • Layout customization / APIs
  • Platform Eventing
  • Hotkeys & Commands
  • Window.open / fin.Window.create support

Beta Late Feb 2020

15.80.49.*

  • Multi-instance Views
  • Layouts Eventing
  • Additional Commands
  • Branding Support / Window Titles

Beta Late March 2020

15.80.50.*

  • Multi-Runtime
  • Platform-Defined Dialogs & Menus
  • FDC3 Support

TBD

TBD

Updated 5 days ago

Platform API


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.