Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed-screensharing-firefox-addon.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Bauch <bauch@struktur.de>2017-01-27 17:56:47 +0300
committerJoachim Bauch <bauch@struktur.de>2017-01-27 17:56:47 +0300
commitf6aca585b45384a296f77b46c025b4211bb65309 (patch)
tree85a152358922d9da0c693f81b8e33b3f383443e4 /extension
Added initial version of Firefox screensharing addon.
This is required to support screensharing in Firefox for the Nextcloud Spreed app (see nextcloud/spreed#227). Signed-off-by: Joachim Bauch <bauch@struktur.de>
Diffstat (limited to 'extension')
-rw-r--r--extension/bootstrap.js231
-rw-r--r--extension/chrome.manifest5
-rw-r--r--extension/chrome/framescript.js153
-rw-r--r--extension/install.rdf27
4 files changed, 416 insertions, 0 deletions
diff --git a/extension/bootstrap.js b/extension/bootstrap.js
new file mode 100644
index 0000000..0033b43
--- /dev/null
+++ b/extension/bootstrap.js
@@ -0,0 +1,231 @@
+/**
+ * Nextcloud Firefox extension.
+ *
+ * @author Joachim Bauch <bauch@struktur.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* https://developer.mozilla.org/en-US/Add-ons/Bootstrapped_extensions */
+/* https://developer.mozilla.org/en-US/docs/Extensions/bootstrap.js */
+/* https://github.com/HenrikJoreteg/getScreenMedia/blob/master/firefox-extension-sample/bootstrap.js */
+
+/* https://developer.mozilla.org/en-US/Add-ons/Bootstrapped_extensions#Reason_constants */
+var APP_STARTUP = 1;
+var APP_SHUTDOWN = 2;
+var ADDON_ENABLE = 3;
+var ADDON_DISABLE = 4;
+var ADDON_INSTALL = 5;
+var ADDON_UNINSTALL = 6;
+var ADDON_UPGRADE = 7;
+var ADDON_DOWNGRADE = 8;
+var NAMESPACE = 'nextcloud-spreed';
+
+var START_SCREENSHARING_MESSAGE = 'webrtcStartScreensharing';
+var STOP_SCREENSHARING_MESSAGE = 'webrtcStopScreensharing';
+
+/**
+ * Extension api
+ * @returns {object}
+ */
+var api = (function() {
+ var SCREENSHARING_ADD_DOMAIN_EVENT = 'ExtensionAddDomain';
+ var SCREENSHARING_REMOVE_DOMAIN_EVENT = 'ExtensionRemoveDomain';
+ var SCREENSHARING_ALLOWED_DOMAINS_PREF = 'media.getusermedia.screensharing.allowed_domains';
+
+ /* https://developer.mozilla.org/en-US/Add-ons/Working_with_multiprocess_Firefox#Porting_to_the_message_manager */
+ /* https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages/ported-message-manager/src/chrome/content */
+ var globalMM = Components.classes["@mozilla.org/globalmessagemanager;1"].getService(Components.interfaces.nsIMessageListenerManager);
+
+ var preferences = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
+ var hasBootstrapped = false;
+
+ var registeredDomains = {};
+
+ var unique_id = Date.now();
+
+ var extensionData = {
+ id: null,
+ version: null
+ };
+ /**
+ * @param {Object} data Object holding extension information
+ * @param {String} data.id The extension id
+ * @param {String} data.version The current extension version
+ */
+ var setExtensionData = function(data) {
+ if (data.id && data.version) {
+ extensionData.id = data.id;
+ extensionData.version = data.version;
+ } else {
+ throw new Error('Data object invalid and without relevant properties.');
+ }
+ };
+ var getExtensionData = function() {
+ return extensionData;
+ };
+ /**
+ * Append domains to the Firefox list of allowed screensharing domains
+ * @param {array} domains List of domains to append to allowed screensharing domains
+ * @param {boolean} force If a domain already exists append it anyway to current domain list
+ */
+ var insertDomains = function(addDomains, force) {
+ var domainsToAppend = [];
+ var domains = preferences.getCharPref(SCREENSHARING_ALLOWED_DOMAINS_PREF).split(',');
+ // Prevent inserting a domain that is already part of the list
+ for (var i = 0; i < addDomains.length; i++) {
+ if (force || domains.indexOf(addDomains[i]) < 0) {
+ domainsToAppend.push(addDomains[i]);
+ console.log(NAMESPACE,'Adding domain', addDomains[i]);
+ } else {
+ console.log(NAMESPACE,'Domain exists', addDomains[i]);
+ }
+ }
+ if (domains.length > 0 || domainsToAppend.length > 0) {
+ preferences.setCharPref(SCREENSHARING_ALLOWED_DOMAINS_PREF, domains.concat(domainsToAppend).join(','));
+ } else {
+ throw new Error('No screensharing domains');
+ }
+ };
+ /**
+ * Remove domains from the Firefox list of allowed screensharing domains
+ * @param {array} domains List of domains to remove from allowed screensharing domains
+ */
+ var removeDomains = function(deleteDomains) {
+ var domains = preferences.getCharPref(SCREENSHARING_ALLOWED_DOMAINS_PREF).split(',');
+ var modified = false;
+ for (var i = 0; i < deleteDomains.length; i++) {
+ var x = domains.lastIndexOf(deleteDomains[i]);
+ if (x >= 0) {
+ console.log(NAMESPACE,'Removed domain', deleteDomains[i], 'at index', x);
+ domains.splice(x, 1);
+ modified = true;
+ }
+ }
+ if (modified) {
+ preferences.setCharPref(SCREENSHARING_ALLOWED_DOMAINS_PREF, domains.join(','));
+ }
+ };
+ var insertDynamicDomain = function(domain) {
+ if (domain) {
+ if (registeredDomains.hasOwnProperty(domain)) {
+ registeredDomains[domain] += 1;
+ return;
+ }
+ registeredDomains[domain] = 1;
+ console.log(NAMESPACE, "Insert", domain);
+ insertDomains([domain], true);
+ } else {
+ throw new Error('Domain argument undefined.');
+ }
+ };
+ var removeDynamicDomain = function(domain) {
+ if (domain) {
+ if (!registeredDomains.hasOwnProperty(domain)) {
+ return;
+ }
+ registeredDomains[domain] -= 1;
+ if (registeredDomains[domain] > 0) {
+ return;
+ }
+ delete registeredDomains[domain];
+ console.log(NAMESPACE, "Remove", domain);
+ removeDomains([domain]);
+ } else {
+ throw new Error('Domain argument undefined.');
+ }
+ };
+
+ var addDomainListener = function(event) {
+ if (!event || !event.data || !event.data.host) {
+ return;
+ }
+
+ console.log(NAMESPACE, "Add domain", event.data.host);
+ insertDynamicDomain(event.data.host);
+ };
+
+ var removeDomainListener = function(event) {
+ if (!event || !event.data || !event.data.host) {
+ return;
+ }
+
+ console.log(NAMESPACE, "Remove domain", event.data.host);
+ removeDynamicDomain(event.data.host);
+ };
+
+ var syncExtensionData = function() {
+ return getExtensionData();
+ };
+
+ var logMessage = function(event) {
+ var args = event.data || [];
+ args.splice(0, 0, NAMESPACE);
+ console.log.apply(console, args);
+ };
+
+ var bootstrap = function(data) {
+ if (hasBootstrapped) {
+ // Ensure we are not loading scripts more than once into a tab.
+ return;
+ }
+
+ console.log(NAMESPACE, "bootstrap");
+ setExtensionData({id: data.id, version: data.version});
+ globalMM.addMessageListener(NAMESPACE + ':ExtensionDataSync', syncExtensionData);
+ globalMM.addMessageListener(NAMESPACE + ':log', logMessage);
+ globalMM.addMessageListener(NAMESPACE + ':' + START_SCREENSHARING_MESSAGE, addDomainListener);
+ globalMM.addMessageListener(NAMESPACE + ':' + STOP_SCREENSHARING_MESSAGE, removeDomainListener, true);
+ globalMM.loadFrameScript("chrome://nextcloud-screensharing/content/framescript.js", true);
+ globalMM.broadcastAsyncMessage(NAMESPACE + ':startup', {'unique_id': unique_id});
+ hasBootstrapped = true;
+ console.log(NAMESPACE, "bootstrap done");
+ };
+
+ var teardown = function() {
+ if (!hasBootstrapped) {
+ return;
+ }
+
+ console.log(NAMESPACE, "teardown");
+ globalMM.broadcastAsyncMessage(NAMESPACE + ':teardown', {'unique_id': unique_id});
+ globalMM.removeDelayedFrameScript('chrome://nextcloud-screensharing/content/framescript.js');
+ globalMM.removeMessageListener(NAMESPACE + ':ExtensionDataSync', syncExtensionData);
+ globalMM.removeMessageListener(NAMESPACE + ':log', logMessage);
+ globalMM.removeMessageListener(NAMESPACE + ':' + START_SCREENSHARING_MESSAGE, addDomainListener);
+ globalMM.removeMessageListener(NAMESPACE + ':' + STOP_SCREENSHARING_MESSAGE, removeDomainListener, true);
+ hasBootstrapped = false;
+ console.log(NAMESPACE, "teardown done");
+ };
+
+ return {
+ bootstrap: bootstrap,
+ teardown: teardown
+ };
+})();
+
+function startup(data, reason) {
+ api.bootstrap(data);
+}
+
+function shutdown(data, reason) {
+ api.teardown();
+}
+
+function install(data, reason) {}
+
+function uninstall(data, reason) {}
diff --git a/extension/chrome.manifest b/extension/chrome.manifest
new file mode 100644
index 0000000..9e157dd
--- /dev/null
+++ b/extension/chrome.manifest
@@ -0,0 +1,5 @@
+# Only certain instructions are supported in bootstrapped extensions
+# See https://developer.mozilla.org/en/docs/Chrome_Registration#Instructions_supported_in_bootstrapped_add_ons
+
+# https://developer.mozilla.org/en/docs/Chrome_Registration#content-instruction
+content nextcloud-screensharing chrome/
diff --git a/extension/chrome/framescript.js b/extension/chrome/framescript.js
new file mode 100644
index 0000000..29ed3e3
--- /dev/null
+++ b/extension/chrome/framescript.js
@@ -0,0 +1,153 @@
+/**
+ * Nextcloud Firefox extension.
+ *
+ * Script that will be loaded in all frames (i.e. tabs and windows).
+ *
+ * @author Joachim Bauch <bauch@struktur.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+(function(cfmm) {
+
+ var START_SCREENSHARING_MESSAGE = 'webrtcStartScreensharing';
+ var STOP_SCREENSHARING_MESSAGE = 'webrtcStopScreensharing';
+
+ var NAMESPACE = 'nextcloud-spreed';
+
+ var initialized = false;
+ var unique_id;
+
+ var extensionData = {
+ id: null,
+ version: null
+ };
+
+ var logMessage = function() {
+ sendSyncMessage(NAMESPACE + ':log', Array.prototype.slice.call(arguments));
+ };
+
+ (function(data) {
+ var d = data && data[0];
+ if (d && d.version && d.id) {
+ extensionData.id = d.id;
+ extensionData.version = d.version;
+ } else {
+ throw new Error('Extension information not found.');
+ }
+ })(cfmm.sendSyncMessage(NAMESPACE + ':ExtensionDataSync'));
+
+ var hasClass = function(element, cls) {
+ return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
+ };
+
+ var isNextcloudSpreedApp = function(document) {
+ if (!document) {
+ return false;
+ }
+
+ var nc = document.getElementById('app');
+ if (!nc || !hasClass(nc, 'nc-enable-screensharing-extension')) {
+ return false;
+ }
+
+ return true;
+ };
+
+ var messageHandler = function(event) {
+ var window = cfmm.content;
+ if (!initialized || event.origin != window.location.origin || !event.data) {
+ return;
+ }
+
+ var host = window.location.hostname;
+ var data = event.data;
+ switch (data.type) {
+ case 'webrtcStartScreensharing':
+ logMessage("start screensharing", host);
+ sendSyncMessage(NAMESPACE + ':' + START_SCREENSHARING_MESSAGE, {"host": host});
+ window.postMessage({'type': 'webrtcScreensharingWhitelisted', 'id': data.id}, event.origin);
+ break;
+
+ case 'webrtcStopScreensharing':
+ logMessage("stop screensharing", host);
+ sendSyncMessage(NAMESPACE + ':' + STOP_SCREENSHARING_MESSAGE, {"host": host});
+ break;
+ }
+ };
+
+ var removeHandlers = function(window, document) {
+ if (!initialized) {
+ return;
+ }
+
+ window.removeEventListener('message', messageHandler);
+ initialized = false;
+ };
+
+ var showAvailability = function(document) {
+ var nc = document.getElementById('app');
+ nc.setAttribute('data-firefoxExtensionData', JSON.stringify(extensionData));
+ };
+
+ var installHandlers = function(window, document) {
+ // Only add extension if the page is running the Nextcloud Spreed -app.
+ if (!isNextcloudSpreedApp(document)) {
+ removeHandlers(document);
+ return;
+ }
+
+ removeHandlers(document);
+ logMessage('Detected Nextcloud Spreed app.');
+ window.addEventListener('message', messageHandler);
+ showAvailability(document);
+ initialized = true;
+ };
+
+ var loaded = function() {
+ if (!cfmm.content) {
+ return;
+ }
+ installHandlers(cfmm.content, cfmm.content.document);
+ };
+
+ var init = function(msg) {
+ if (msg.data) {
+ unique_id = msg.data.unique_id;
+ }
+ loaded();
+ cfmm.removeMessageListener(NAMESPACE + ':startup', init);
+ };
+
+ var teardown = function(msg) {
+ if (unique_id !== msg.data.unique_id) {
+ return;
+ }
+
+ cfmm.removeMessageListener(NAMESPACE + ':startup', init);
+ cfmm.removeMessageListener(NAMESPACE + ':teardown', teardown);
+ removeHandlers(cfmm.content, cfmm.content.document);
+ unique_id = null;
+ };
+
+ cfmm.addEventListener('DOMContentLoaded', loaded);
+ cfmm.addEventListener('load', loaded);
+ cfmm.addMessageListener(NAMESPACE + ':startup', init);
+ cfmm.addMessageListener(NAMESPACE + ':teardown', teardown);
+
+ // logMessage('Loaded framescript.js');
+})(this);
diff --git a/extension/install.rdf b/extension/install.rdf
new file mode 100644
index 0000000..e5d3bb2
--- /dev/null
+++ b/extension/install.rdf
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <!-- https://developer.mozilla.org/en-US/Add-ons/Install_Manifests -->
+ <em:id>spreed-screensharing@nextcloud.com</em:id>
+ <em:version>0.0.1</em:version>
+ <em:type>2</em:type>
+ <em:bootstrap>true</em:bootstrap>
+
+ <em:targetApplication>
+ <Description>
+ <!--Firefox-->
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>36.0</em:minVersion>
+ <em:maxVersion>*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+
+ <em:name>Nextcloud Screensharing</em:name>
+ <em:description>Screensharing utility for the Nextcloud Spreed app.</em:description>
+ <em:creator>Nextcloud</em:creator>
+ <em:developer>Joachim Bauch</em:developer>
+ <em:homepageURL>https://nextcloud.com</em:homepageURL>
+ <em:multiprocessCompatible>true</em:multiprocessCompatible>
+ </Description>
+</RDF>