Skip to main content

Extensions

Introduction

Webfuse Extensions are a way to add new functionality to spaces, tabs and browsed websites. Extensions give you access to the source code of the original website, user interface of the webfuse session and even possibility to run code on a separate browser thread by letting you create a service worker.

Format

We aim to follow well-known browser's extensions format. You can read more about extensions here and here.

In a nutshell, extensions are a collection of files that can be loaded into a space session. Each file has a specific role and is loaded in different ways.

The entry point of the extension is the manifest.json file which is a JSON file that contains information about the extension.

Let's take a look at an example of a simple manifest.json file which allows you to load 4 different components of the extension: a worker script, a content script, a popup window and a custom new tab page.

{
// Manifest version. We only support version 3
"manifest_version": 3,

// The name of the extension
"name": "example-extension",

// The version of the extension
"version": "1.0",

"action": {
// This is the popup window which will be opened when the user clicks on a button in the extension. It is available for all session participants.
"default_popup": "popup.html"
},
"background": {
// The service worker which runs in a separate thread. It is available for all session participants.
"service_worker": "background.js"
},
"content_scripts": [
{
// List of content scripts which will be loaded in all tabs. It is loaded only on the tab's owner side.
// Please note, content script is not loaded in the custom new tab page.
"js": ["content.js"],

// Coming soon. List of tabs' URLs which will be matched by the content script.
"matches": ["<all_urls>"]
}
],
// The new tab page which will be opened when the user clicks on a button in the extension. It is available for all session participants.
"chrome_url_overrides": {
"newtab": "newtab.html"
}
}

How to Install an Extension

Extensions are only available for space sessions. So, in order to load an extension in a space session, you need to follow these steps:

  1. Create a space or join an existing space with admin privileges in Chrome browser.
  2. Start a space session.
  3. Open the space editor panel.
  4. Click on the "Extensions" button.
  5. Click on the "Add new" button.
  6. Select the folder containing the extension you want to load.
  7. Click on the "Load extension" button.
  8. The extension will be loaded in the space session.

How to Update an Extension

To update an extension, follow the same steps as for loading an extension, only select the extension which you want to update in the list of installed extensions and click on the "Refresh extension" button.

Communication beetween components

All components of the extension can communicate with each other. Messaging between components is implemented similar to the Extension Messaging API.

There are 2 ways to send messages between components:

Sending messages

Sending a message from any component to popup, service worker, and new tab page:

surflyExtension.runtime.sendMessage(message);

Sending message from popup, service worker, and new tab to the tab content script:

NB: Currently, tabId parameter is ignored and the message is sent to all content scripts of all the tabs in the session.

surflyExtension.tabs.sendMessage(tabId, message);

Listening for extension messages

surflyExtension.runtime.onMessage.addListener((message, sender) => {});

Message API

In addition to traditional messaging, we provide a message API which allows you to send messages to all extensions in the session. This functionality can be used to communicate with extensions loaded on other participants' side.

There are 2 ways to send messages to all extensions in the session:

JS API:

surflyExtension.surflySession.broadcastMessage(message);

REST API:

Message API

Using JS API

Using Javascript API

Webfuse Javascript API is available in all components of the extension.

surflyExtension.surflySession.apiRequest({cmd: <cmd_to_execute>, ...params});

List of available commands match Javascript API methods. However, currently instead of using the method directly you need to pass the command name to the cmd parameter.

Available commands:

end, relocate, log, open_tab, make_host, pause_tabs, request_control, request_to_host, request_tab_control, transfer_tab_control, get_session_participants, get_session_tabs, activate_tab, revoke_tab_control, return_tab_control, pause_tabs, resume_tabs, toggle_videochat_fullscreen, toggle_videochat_mode, toggle_videochat_microphone, start_screensharing, toggle_drawing, upload_file, send_chat_message, broadcast_message

Parameters of the commands correspond to API methods defined in Surfly Session Object.

NB: We are currently working on implementing Chrome-like API for the extension. In the future, cmd method will be removed.

Listening for session events

All session events are also delivered to all components of the extension.

surflyExtension.surflySession.onMessage.addListener(messageData => {
if (messageData.event_type === 'relocated') {
console.log('Session relocated to: ', messageData.url);
}
});

Example extension

Here is an example of a simple extension that allows you to load 4 different components of the extension: an extension service worker script, a content script, a popup window and a custom new tab page.

This extension listens for relocated session events in the service worker, propagates the event to the popup window, content script and new tab page. Also, it implements the relocate command which allows you to change the session location from the custom new tab page.

Full source code of the example extension can be found here.

manifest.json

{
"manifest_version": 3,
"name": "Surfly Extension",
"version": "0.1",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"chrome_url_overrides": {
"newtab": "newtab.html"
},
"action": {
"default_popup": "popup.html"
}
}

newtab.html

<form id="url-form" onsubmit="goTo(); return false">
<input type="url" name="url" id="url" placeholder="Enter URL" />
</form>

<script>
function goTo() {
const url = document.getElementById('url').value;
surflyExtension.surflySession.apiRequest({
cmd: 'relocate',
url,
newTab: false,
});
}

surflyExtension.runtime.onMessage.addListener((message, sender) => {
if (message?.event_type === 'relocated_propagated') {
console.log('newtab received relocated propagated message', message);
}
});
</script>

popup.html

<html>
<head>
<title>Popup</title>
</head>
<body>
<script>
surflyExtension.runtime.onMessage.addListener((message, sender) => {
if (message?.event_type === 'relocated_propagated') {
console.log('popup received relocated propagated message', message);
}
});
</script>
</body>
</html>

background.js

surflyExtension.surflySession.onMessage.addListener((message, sender) => {
if (message?.event_type === 'relocated') {
console.log('background received relocated message', message);

surflyExtension.runtime.sendMessage({
event_type: 'relocated_propagated',
from: 'background',
});

surflyExtension.tabs.sendMessage(null, {
event_type: 'relocated_propagated',
from: 'background',
});
}
});

content.js:

surflyExtension.runtime.onMessage.addListener((message, sender) => {
if (message?.event_type === 'relocated_propagated') {
console.log('content received relocated propagated message', message);
}
});

How to Uninstall an Extension

To uninstall an extension, follow the same steps as for loading an extension, only select the extension which you want to uninstall in the list of installed extensions and click on the "Delete" button.