Platform API

A Platform and its content can be launched both programmatically and via a Platform manifest. Here we will explain the mechanisms that allow Application Providers to start a Platform and launch content into that Platform. As a best practice, we recommend leveraging a custom Platform Provider rather than in a snapshot on the Platform manifest.

Use the Platform API to:

  • Launch a platform, create a window and add a view
  • Launch content in a view
  • Configure a layout
  • Save and restore a snapshot

System requirements

  • OpenFin CLI installed
  • Windows 7 or 10+, Mac can be used for developer purposes

Launch a Platform

In order to use the API, your window must be a part of a manifest-launched platform. Let's launch one.
Copy the following manifest and save as app.json locally:

{
  "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"
  }
}

Now let's launch it!

openfin -l -c app.json

Create a platform window

Now that we have our platform, let's create a new platform window, along with a platform view, using Platform.createWindow.
Open your developer console from a platform view and enter the following code:

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
        }
      }]
    }]
  }
});

Add a view to an existing window

From the same view (and console), lets add an additional view to that window using Platform.createView():

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

The Platform.createView leverages two arguments:

  • View configuration options: the name, URL of the window and any other view options
  • Target identity: the identity of the window to which the view will be attached.

You do not need to set a name for a view. Views that are not passed a name get a randomly generated one.

Launch content in a view

Content can be launched via manifest by calling the launchContentManifest() method on a wrapped platform instance. If the manifest to be launched contains a snapshot object, that snapshot is launched.

API calls

Once a platform is launched and 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 is launched. Any view specified in the snapshot is assigned a randomly generated name to avoid collisions.

applySnapshot(): A snapshot creates any windows and views that are not running in the snapshot object.

// Get a wrapped layout platform instance
const platform = await fin.Platform.getCurrent();

const snapshot = {
  windows: [
    {
      layout: {
        content: [
          {
            type: 'stack',
            content: [
              {
                type: 'component',
                componentName: 'view',
                componentState: {
                  name: 'component_X',
                  url: 'https://www.openfin.co'
                }
              },
              {
                type: 'component',
                componentName: 'view',
                componentState: {
                  name: 'component_Y',
                  url: 'https://cdn.openfin.co/embed-web/chart.html'
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

platform.applySnapshot(snapshot);

createWindow(): creates a new platform window with default window UI

const platform = fin.Platform.getCurrentSync();
platform.createWindow({
  layout: {
    content: [
      {
        type: 'stack',
        content: [
          {
            type: 'component',
            componentName: 'view',
            componentState: {
              name: 'test_view_1',
              url: 'https://developer.openfin.co/docs/javascript/stable/classes/OpenFin.Platform.html'
            }
          },
          {
            type: 'component',
            componentName: 'view',
            componentState: {
              name: 'test_view_2',
              url: 'https://developer.openfin.co/docs/javascript/stable/classes/OpenFin.Platform.html'
            }
          }
        ]
      }
    ]
  }
}).then(console.log);

createView(): Creates a new platform view and attaches it to a specified target window.

let windowIdentity;
if (fin.me.isWindow) {
    windowIdentity = fin.me.identity;
} else if (fin.me.isView) {
    windowIdentity = (await fin.me.getCurrentWindow()).identity;
} else {
    throw new Error('Not running in a platform View or Window');
}

const platform = fin.Platform.getCurrentSync();

platform.createView({
    name: 'test_view',
    url: 'https://developers.openfin.co/docs/platform-api'
}, windowIdentity).then(console.log);

Deep linking (fin / 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 use a fins link to both start a platform and to launch content into a platform. A link that targets a single platform manifest starts the platform, if the platform is not already running, and launches a snapshot into the platform, if present in the manifest.

You can also designate a separate content manifest to be launched into the platform by targeting the platform manifest and adding an $$appManifestUrl parameter. This starts the platform, if not already running, but launches the content in the second manifest at the $$appManifestUrl location. If an $$appManifestUrl parameter is included, any snapshot that exists on the platform manifest is ignored and only the content designated at the appManifestUrl is launched.

Like the launchContentManifest() method, if the manifest at the $$appManifestUrl location contains a snapshot object, that snapshot is launched. If instead it is a legacy manifest without a snapshot, the startup_app is launched as a single View in the Layout of a new OpenFin Window.

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

If both snapshot and startup_app object are present in the $$appManifestUrl location, the following hierarchy of which of these is used applies:

  • startup_app is always used if you are launching the manifest in a traditional way through the RVM.
  • snapshot is used only if the manifest is passed via the $$appManifestUrl.

Changes to $$appManifestUrl

As part of OpenFin's effort to provide a secure and more controlled development environment, starting in Runtime version 36, behavior of the $$appManifestUrl parameter changes from earlier versions.

Starting in version 36, using the $$appManifestUrl parameter causes warning messages to appear in the Platform provider window console unless you specifically opt-in or opt-out of the allowLaunchIntoPlatform manifest property.

To opt-in, set the allowLaunchIntoPlatform property value to true as shown below. To opt-out, set the allowLaunchIntoPlatform property value to false.

{
  ...
  "platform": {
    "allowLaunchIntoPlatform": true
  }
}

If the allowLaunchIntoPlatform property does not exist in the manifest file, the warnings appears at each launch that uses $$appManifestUrl.

Starting in Runtime version 38, use of the $$appManifestUrl parameter is disabled by default (opt-out behavior).
The warning messages appear in the Platform provider window console. However, the platform does not launch the new content.

To enable the $$appManifestUrl parameter for Runtime versions 38 and later, set the allowLaunchIntoPlatform manifest property to true as shown above.

Configure a layout

OpenFin platforms allow 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. Here we cover three basic layout configurations for tabs, columns and rows and a grid.

Image outlining a possible layout

Tabs

//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"
          }
        }
      ]
    }
  ]
}

Columns and rows

//A window object within a layout that has three views arranged as columns.
"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"
        }
      }
    ]
  }
]

Grid

//A window object within a snapshot that has four views arranged as a 2x2 grid.
{
  "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"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Snapshots

Earlier, we loaded a brand-new Platform Window with two Views in it. Here we will retrieve getSnapshot a Platform Layout and apply applySnapshot a previously saved Platform layout.

Get snapshot

Use the following code in the same console you were using in the Add a View to an Existing Window. Platform.getSnapshot returns a snapshot object and can be used to return the desktop back to this current state. You can store this object wherever you'd like, and use it later to apply this Snapshot.

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

Apply snapshot

Now let’s use our snapshot object to recreate our desktop using applySnapshot. First, rearrange your platform windows on your desktop.

  1. Close the window you created earlier (the one filled with www.example.com Views), move your windows to different locations.
  2. Move the views in their platform windows to different locations.
  3. Execute the code below to get your desktop back to the way it was before.
// The `platform` here is the object we captured
platform.applySnapshot(mySnapshot, {closeExistingWindows: true});

How a window can opt out of snapshots

There are some occasions where you may not want a window to be included in snapshots.

To make a window opt out of snapshots, set the window.includeInSnapshots property to false. To include the window in snapshots again, set the window.includeInSnapshots property to true.

Platform manifest

Here we will breakdown the various pieces of the OpenFin platform manifest file.

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": "full-url-to-css-sheet",
      "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 launches 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: Defines 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.

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

componentState: Defines the componentState property to provide the OpenFin view options. The URL of a manifest that contains View Options can additionally be added as a manifestUrl property. Properties in the manifest take precedence if there is any collision.

{
  "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"
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}