Client Messaging

Application extensions and the Onshape JavaScript web client need to communicate directly, calling across the iframe containing the application extension using post message.

image alt text

Onshape Client Messaging examples can be split into those that are initiated from the application extension and those that are initiated from the Onshape client.

Messages from the Extension

These Client Messaging examples can be initiated from the application extension:

  • Click/close flyouts events: Notify the Onshape client that the user has clicked in the application extension, which should cause Onshape flyouts (versions, history, uploads, etc.) and dropdown menus (profile dropdown menu, document menu) to close. Without this, flyouts and menus might remain open over the application extension.
  • Shortcut keyboard events: Shortcut keys (such as ?, which opens the Onshape Help dialog), can be handled by the application extension by posting a message to the Onshape client to open the dialog.
  • keepAlive: Notify the Onshape client that the user is actively working in the application extension, which triggers the Onshape client to send a message to the server to keep the browser session alive. Without this, the Onshape browser session will timeout and ask the user to sign in again.
  • Standard Onshape dialogs: Request from the application extension to the Onshape client to open one of the Onshape standard dialogs and send the user’s choices back to the application extension. For example, if the application extension needs the user to choose a part or assembly to be operated on, the application extension can post a message to the Onshape client requesting that dialog be opened and the selected part or assembly information sent back to the application extension.
  • UI customization": Request from the application extension to the Onshape client to customize the Onshape UI (e.g., add commands to menus, add buttons to the toolbars, etc). When these commands or toolbar buttons are clicked, the Onshape client posts a message to the application extension with the available context.
    • Note: This is limited to cases where the application extension is made active by the user; application extensions are not automatically loaded when a document is opened. Most UI customizations should be done when you register the application with Onshape, as those change the Onshape client automatically without needing to load the application extension first.
  • Content/material insertion: Request from the application extension to insert content into the Onshape document. For example, insert a part into a new or existing Part Studio, apply a material to a part, add a material to a material library, etc.

Messages from Onshape

The following examples can be initiated from the Onshape client:

  • User action notification: The Onshape client can notify an application extension when various user actions occur. For example, the Onshape client might notify when the user has made the application extension active or inactive (when the user clicks on document tabs). When an application extension is made inactive, it is moved off the edges of the browser, so it cannot be seen, but is still active, preserving its state.
  • Printing: The Onshape client can notify an application extension when the user has chosen the Print command from the main Onshape document menu, enabling the application extension to perform a print operation.

Security Considerations

To ensure security, an application extension must:

  • Parse for document, workspace, and element IDs: Parse for the documentId, workspaceId, and elementId that were passed as query parameters within the application extension’s iframe src URL. You must post these back in each POST message.
  • Parse for the server: Parse for the server that was passed as a query parameter within the application extension’s iframe src URL. You must use this to validate messages received.
    • If the application extension uses a JavaScript library or framework (e.g., BackboneJS or AngularJS), it can parse the query parameters and maintain state in other ways.
  • Not redirect to another base URL: The browser tells the Onshape client the origin base URL from which a POST message is received. The Onshape client ignores messages posted from an origin URL that doesn’t match the original iframe src URL. It is extremely important to the security of your application that you verify that the origin of all messages you receive is the same as the original server query parameter in the iframe src (i.e., if (server === e.origin)). In production operation especially, the message IS NOT SAFE if the message origin does not match the iframe src server query parameter. Application extensions should not redirect to another base URL after the iframe has been opened, or the messages will be ignored.
  • Post a message on startup: Onshape will not post messages until a newly started application extension has first posted a valid message to Onshape. This constraint is in effect anytime an application extension is (re)started and exists to avoid posting messages to application extensions that are not ready to handle them, are not fully loaded, etc. After your application extension is fully loaded and ready to receive messages, post a message to Onshape. A keepAlive message is a great first message to send to Onshape. Once Onshape receives a valid message, Onshape will start posting messages to the application extension. If the application extension later sends an invalid message Onshape will stop sending messages until a valid message is posted to Onshape.

POST messages submitted by application extensions to Onshape will be ignored if any of the following are true:

  • The documentId, workspaceId, or elementId are missing or not valid.
  • The message name is missing or not recognized.
  • The origin of the POST message does not match the original iframe src URL.

Element Tab

Messages may be sent and received by element tab application extensions.

The following messages can be sent by Element tab application extensions:

messageName (case sensitive)other message properties?comment
applicationInityes
notifyWhenSaveRequired: whether Onshape should send a notification to save pending changes during certain operations
(default is false)
Send once on application startup.
closeFlyoutsAndMenusnoSend when a mouse click or other event happens in the application extension. Closes Onshape flyouts and dropdown menus.
closeSelectItemDialognoCloses the select item dialog.
connectionLostnoDisplays the standard Onshape connection lost message in a message bubble, forcing the user to either reload the document or return to the documents page.
errorReloadyes
message: your message
Similar to the connectionLost message, but enables an application to specify the first part of the message, which will be used instead of "Onshape is not connected." The user must reload the document or return to the documents page.
finishedSavingyes
messageId: the id sent in the corresponding 'saveChanges' message
Response to a 'saveChanges' message sent from Onshape. Should be sent after application has cleaned up any pending edits.
keepAlivenoSend periodically while while the user is actively working to avoid the session from timing out.
saveAVersionnoSend when the user types “Shift-S” in the application extension, the keyboard shortcut for save a version.
showKeyboardShortcutsHelpnoSend when the user types “?” (Shift-? on most keyboards) in the application extension, the keyboard shortcut for the keyboard shortcuts help dialog.
showMessageBubbleyes
message: your message
Send when you want to show a string in the blue message bubble at the top of the Onshape app.
startLoadingSpinneryes
message: your message
Send to start a large spinner in the middle of the browser window with your message underneath it.
stopLoadingSpinnernoSend to stop the large spinner.
startWorkingSpinnernoSend to start a small spinner in the middle bottom of the browser window.
stopWorkingSpinnernoSend to stop the small spinner.
openSelectItemDialogyes
dialogTitle: your dialog title
 (default is no title),
selectBlobs: true or false
 (default is false),
selectParts: true or false
 (default is false),
selectPartStudios: true or false
 (default is false),
selectAssemblies: true or false
 (default is false),
selectMultiple: true or false
 (default is false),
selectBlobMimeTypes: ‘comma-delimited string of blob mime types to show in dialog (e.g. “application/dwt,application/dwg”)’
 (default is an empty string)
showBrowseDocuments: true or false - controls whether ‘Other documents’ choice should be available
 (default is true)
showStandardContent: true or false - controls whether ‘Standard content’ choice should be available
 (default is false)
Send when your application wants to open a dialog in which the user will select one or multiple items - blobs, parts, part studios or assemblies.
requestCameraPropertiesyes
graphicsElementId: string , Element ID of the part studio or assembly
Send to request camera properties of a specific part studio or assembly element. Note: The element should have been opened at least once in the current session. The messageName of the response is cameraProperties

The following messages can be received by Element tab application extensions:

messageName (case sensitive)other message properties?comment
shownoSent when an element tab application extension is shown (made active) within the Onshape client. This message is NOT sent when the element tab application extension is created.
hidenoSent when an element tab application extension is made inactive within the Onshape client. This message is NOT sent when an element tab application extension is deleted.
itemSelectedInSelectItemDialogyes
documentId: id of selected item’s document,
workspaceId: id of selected item’s workspace, empty if versionId not empty,
versionId: id of selected item’s version, empty if workspaceId not empty,
elementId: id of element selected or containing the selected part,
elementName: name of element selected or containing the selected part,
elementType: type of element selected or containing the selected part - ‘partstudio’, ‘assembly’ or ‘blob’,
elementMicroversionId: microversion id of the element,
itemType: type of item selected: ‘part’,‘partStudio’ or ‘assembly’,
partName: name of part selected, empty if itemType is not ‘part’,
idTag: id of part, empty if no part selected
Sent when the user selects an item (blob, part, part studio or assembly) in the select item dialog that was opened due to an openSelectItemDialog message sent earlier. When a part is not selected, the partXxx message properties will be empty strings.
printnoSent when the user chooses the Print command while the application is the active element. The application can choose to handle this as either a print or an export to a PDF or other format.
selectItemDialogClosednoSent when the select item dialog closes, either because the user selected an item and selectMultiple is false, or the user changed the active element or the user closed the dialog with the "X" button.
startFirstViewCommandyes
documentId: id of selected item’s document,
workspaceId: id of selected item’s workspace, empty if versionId not empty,
versionId: id of selected item’s version, empty if workspaceId not empty,
elementId: id of element selected or containing the selected part,
elementName: name of element selected or containing the selected part,
elementType: type of element selected or containing the selected part - ‘partstudio’, ‘assembly’ or ‘blob’,
elementMicroversionId: microversion id of the element,
itemType: type of item selected: ‘part’,‘partstudio’ or ‘assembly’,
partName: name of part selected, empty if itemType is not ‘part’,
idTag: id of part
Sent to a drawings application extension when the drawing is created with zero views.

If other types of applications need a message posted to them with creation context, contact Onshape and we can discuss using this sort of message for your application also.

exportyes
fileExtension: the file extension of the export type the user chose - “.dwg”, “.dxf” are the types currently supported.
baseFileName: the base portion of the expected output file.  This is currently set to “<document name> - <element name>”
Sent when the user chooses a command to export the contents of the application to a file.
cameraPropertiesyes
graphicsElementId: string , Element ID of the part studio or assembly
isValid: boolean, Indicates if the properties are valid or not. false if element ID is invalid or element has not been open in the current session
projectionType: string, Denotes the projection method. Values are ‘orthographic’, ‘perspective’ . Empty string ‘’ if isValid is false
viewMatrix: 16 element numeric matrix with elements at index 13, 14, 15 corresponding to position of the camera
projectionMatrix: 16 element numeric matrix
verticalFieldOfView: number, 0 in case of orthographic projection
viewportHeight:      number, eight of the viewport
viewportWidth:       number, width of the viewport
Sent when application posts a requestCameraProperties message
takeFocusnoSent when the Onshape client sets focus on the content window of the element tab application extension.
saveChangesyes
messageId: a unique identifier for this message. Should be passed back in the 'finishedSaving' message.
Sent if the application specified 'notifyWhenSaveRequired' in the 'applicationInit' message. Indicates that the application should cleanup any pending edits before an Onshape process continues (i.e. version save).

Element Right Panel

Most client messaging functionality had been limited to that occurring between the Onshape client and application elements (the Element tab location). Limited functionality in now also available for client messaging to work with application extensions in the Element right panel location.

Enabled messaging to Element right panel extensions includes the communication of selections that the user makes for the following application extension contexts:

  • Part Studio
  • Assembly
  • Document

All Security Considerations above apply to both Element tab and Element right panel extensions, with the following notes:

  • Initial message from the application extension to the Onshape client, in the form of an applicationInit message (or one of any other messages supported by the element right panel extensions), is required to ensure the Onshape client does not send messages to the extension until it is ready.
  • Once a valid applicationInit message is received by the Onshape client, it will start sending messages with the messageName value SELECTION upon user selection interactions.
  • Prior to accepting any message from the Onshape client as secure, the origin attribute value included in incoming messages must be validated as equal to the original server query parameter value used to load the application extension.

Code Snippets

Parse query parameters

This JavaScript code parses the iframe src query parameters and uses them to post a message:

  var documentId;
  var workspaceId;
  var elementId;
  var server;

  // Parse query parameters
  var queryParameters = decodeURIComponent(window.location.search.substr(1));
  var queryParametersArray = queryParameters.split('&');
  for (var i = 0; i < queryParametersArray.length; i++) {
    var parameterArray = queryParametersArray[i].split('=');
    if (parameterArray.length === 2) {
      switch (parameterArray[0]) {
        case 'documentId':
          documentId = parameterArray[1];
          break;
        case 'workspaceId':
          workspaceId = parameterArray[1];
          break;
        case 'elementId':
          elementId = parameterArray[1];
          break;
        case 'server':
          server = parameterArray[1];
          break;
      }
    }
  }

  // Listen for clicks and post a message to the Onshape client
  document.getElementById('<id of your topmost element>').
    addEventListener('click', function() {
      var message = {documentId: documentId,
                     workspaceId: workspaceId,
                     elementId: elementId,
                     messageName: 'closeFlyoutsAndMenus'};
      window.parent.postMessage(message, '*');
    }, true);

Create a message object

The message object posted to the Onshape client is of the form:

{
    documentId: documentId,
     workspaceId: workspaceId,
     elementId: elementId,
     messageName: '<message name>',
    // … other properties as needed for other message types …
}

The message data object posted to the application extension is of the form:

{
    messageName: '<message name>',
 //    … other properties as needed for other message types …
}

The message will always have a messageName property.

Listen for messages

To listen for messages from the Onshape client:

  // server is one of the iframe src query parameters - see above

  var handlePostMessage = function(e) {
    console.log("Post message received in application extension.");
    console.log("e.origin = " + e.origin);

    // Verify the origin matches the server iframe src query parameter
    if (server === e.origin) {
      console.log("Message safe and can be handled as it is from origin '"
                  + e.origin +
                  "', which matches server query parameter '"
                  + server + "'.");
      if (e.data && e.data.messageName) {
        console.log("Message name = '" + e.data.messageName + "'");
      } else {
        console.log("Message name not found. Ignoring message.");
      }
    } else {
      console.log("Message NOT safe and should be ignored.");
    }
  };

  window.addEventListener('message', handlePostMessage, false);

Send and handle messages

The following is an example of how one might send an initialization message to, and handle post messages from, the Onshape client.

Note: Proper clean-up of event listeners is not included in the snippet

function handlePostMessage(event) {
  // ensure that the event data is from a legit source:
  if(theServerStringFromActionUrl !== event.origin) {
    console.error('origin of message is not legitimate');
    return;
  }

  // branch based on messageName attribute
  switch(event.data.messageName) {
    case 'SELECTION':
      console.debug('SELECTION event data: %o', event.data);
      break;
    default:
      console.debug(`${event.data.messageName} not handled`);
    }
}

window.addEventListener('message', handlePostMessage);

const initMessage = {
  documentId:  theDocumentId,    // required - parsed from action url
  workspaceId: theWorkspaceId,   // required - parsed from action url
  elementId:   theElementId,     // required - parsed from action url
  messageName: 'applicationInit' // required
};

window.parent.postMessage(initMessage, '*');

Right panel interaction sequence

The sequence diagram below illustrates the interaction between an Element right panel application extension and the Onshape client:

%%{
  init: {
    "theme": "default",
    "sequence": {
      "mirrorActors": false,
      "showSequenceNumbers": false,
      "width": 75,
      "height": 60,
      "actorMargin": 25,
      "messageFontSize": 13,
      "messageFontFamily": "monospace",
      "messageFontWeight": 2
    }
  }
}%%
sequenceDiagram
  actor user
  participant OSC AS Onshape Client
  participant AE AS Application Extension
  user->>+OSC: start element right panel extension
  Note right of user: via configured button
  OSC->>+AE: invoke action url (with query params)
  AE->>OSC: postMessage(messageName: 'applicationInit')
  loop selection interactions
    user->>OSC: select
    OSC->>AE: postMessage(messageName: 'SELECTION')
  end
  user->>OSC: stop element right panel extension
    Note right of user: via configured button
  deactivate AE
  OSC-XAE: destroy
  deactivate OSC

Right panel message exchange

The following messages are exchanged for application extensions located in the element right panel and configured for Part Studio, Assembly, or Document contexts.

The first message with messageName attribute set to applicationInit is sent to the Onshape client by an application extension once it is loaded and ready to receive and process incoming messages:

    {
        documentId: '<document id>',
        workspaceId: '<workspace id>',
        elementId: '<element id>',
        messageName: 'applicationInit'
    }

The values <document id>, <workspace id>, <element id>, and <server id>:

  • Are originally included as query parameters in the action URL used to request the content of the application extension
  • Must be included in messages sent to the Onshape client

While initialization is the specific intent of the applicationInit message, other supported messageName attributes have the same initialization effect upon their first receipt by the Onshape client.

Next, as the user interacts with Onshape by selecting various parts of the model, messages with the messageName attribute set to SELECTION are sent to the application extension:

{
    messageName: 'SELECTION',
    selections: [
        {
            selectionType: 'ENTITY',
            selectionId: 'KRiB',
            entityType: 'FACE',
            occurrencePath: [
                'MfOieM8xKIDGHe37c'
            ],
            workspaceMicroversionId: 'a781c53fbd1095e3462d2b70'
        },
        {
            selectionType: 'ENTITY',
            selectionId: 'KRdC',
            entityType: 'EDGE',
            occurrencePath: [
                'MfOieM8xKIDGHe37c'
            ],
            workspaceMicroversionId: 'a781c53fbd1095e3462d2b70'
        }
    ]
}

Notes

Keyboard focus

Keyboard focus will not be transferred to an application until the user clicks in the application or the application programmatically takes focus. An application should programmatically take focus when it is first loaded and when it receives a show message from Onshape. Shortcut keys will work immediately when the application is shown.

Future work

  • New message types will be added as needed. If your application extension needs a message not listed in this document, please notify us, and we’ll work with you on it.
  • Mobile client support is unclear at this time.
  • Onshape is considering using promises to wrap POST messages, which would make the application extension’s JavaScript simpler and enable chaining POSTs with other operations. Promises would make some interactions with multiple responses difficult (e.g., when you open a dialog, like the Select Item dialog, and want to receive multiple POST messages back due to the user clicking on multiple items in the dialog).