Skip to content

Commit

Permalink
Added initial version of Chrome screensharing extension.
Browse files Browse the repository at this point in the history
This is required to support screensharing in Chrome for the Nextcloud Spreed
app (see nextcloud/spreed#227).

Signed-off-by: Joachim Bauch <bauch@struktur.de>
  • Loading branch information
fancycode committed Jan 27, 2017
0 parents commit 8322906
Show file tree
Hide file tree
Showing 8 changed files with 962 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
nextcloud-spreed-screensharing-*.zip
661 changes: 661 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
VERSION := $(shell node -e "fs=require('fs');console.log(JSON.parse(fs.readFileSync(process.argv[1])).version)" ./extension/manifest.json)

all:
@echo "Version: $(VERSION) - use \"make zip\" to build ..."

dist:
@mkdir -p dist
@cp -r extension dist

zip: dist
cd dist && zip ../nextcloud-spreed-screensharing-$(VERSION).zip extension/*

.PHONY: dist
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Chrome extension to support screensharing in the Nextcloud Spreed app

Based on the getScreenMedia example from
https://github.com/HenrikJoreteg/getScreenMedia/tree/master/chrome-extension-sample


## Installation

See https://developer.chrome.com/extensions/getstarted#unpacked for further
information on how to load the unpacked extension.
151 changes: 151 additions & 0 deletions extension/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* global chrome, Promise */

/**
* @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() {

var priority = 100;

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
switch (msg.type) {
case 'init-nc-screensharing':
var data = msg.data;
var details = chrome.app.getDetails();
if (data.extension) {
// Existing extension data. Checking id.
if (details.id !== data.extension.id) {
// Different extension. Check prio.
if (data.extension.priority && data.extension.priority >= priority) {
// Existing extension has same or higher priority - skip ourselves.
console.log('Refusing to initialize as other extension with same or higher priority found.', data.extension);
return;
} else {
console.log('Refusing to initialize as other extension is already initialized', data.extension);
return;
}
}
}
console.log('Initializing screensharing extension ...', sender.tab.id, data);
sendResponse({
id: details.id,
version: details.version,
priority: priority
});
// Embed our script.
chrome.tabs.executeScript(sender.tab.id, {
file: 'content.js',
runAt: 'document_end'
});
break;
}
});

var ExtensionApi = function(port) {
this.port = port;
};

ExtensionApi.prototype.getScreen = function(resolve, reject, msg) {
var pending = chrome.desktopCapture.chooseDesktopMedia(['screen', 'window'], this.port.sender.tab, function(id) {
var response = {
'type': 'gotScreen',
'id': msg.id
};
if (chrome.runtime.lastError) {
response.sourceId = '';
response.error = chrome.runtime.lastError;
} else {
response.sourceId = id;
}
resolve(response);
});
if (!pending) {
return;
}

return {
'type': 'getScreenPending',
'id': msg.id
};
};

ExtensionApi.prototype.call = function(msg) {
var api = this;
var promise = new Promise(function(resolve, reject) {
var f = api[msg.type];
if (!f) {
reject('action ' + msg.type + ' not found');
return;
}
var response = f.bind(api)(resolve, reject, msg);
if (response) {
response.answer = true;
api.port.postMessage(response);
}
});
promise.then(function(result) {
result.answer = true;
api.port.postMessage(result);
}, function(err) {
if (typeof(err) === 'string') {
err = {
'error': err
};
}
api.port.postMessage(err);
});
};

chrome.runtime.onConnect.addListener(function(port) {
var tab = port.sender.tab;
var api = new ExtensionApi(port);
console.log('Extension connected:', tab.id);
port.onMessage.addListener(function(msg) {
if (msg.answer) {
return;
}

msg.answer = true;
api.call(msg);
});
});

// Bootstrap directly after install so pages need not be refreshed.
chrome.runtime.onInstalled.addListener(function(details) {
switch (details.reason) {
case 'install':
case 'update':
console.log('Extension updated or installed', details);
chrome.windows.getAll({populate: true}, function(windows) {
windows.forEach(function(window) {
window.tabs.forEach(function(tab) {
if (tab.url.match(/https:\/\//gi)) {
chrome.tabs.executeScript(tab.id, {
file: 'detector.js',
runAt: 'document_end'
});
}
});
});
});
}
});

})();
40 changes: 40 additions & 0 deletions extension/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* global chrome */

/**
* @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() {

var port = chrome.runtime.connect();

// Forward message from Nextcloud Spreed app to the extension.
window.addEventListener('message', function(event) {
var msg = event.data;
if (event.source === window && !msg.answer) {
port.postMessage(msg);
}
});

// Forward message from the extension to the Nextcloud Spreed app.
port.onMessage.addListener(function(msg) {
window.postMessage(msg, window.document.URL);
});

})();
57 changes: 57 additions & 0 deletions extension/detector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* global chrome */

/**
* @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(document) {

function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}

// Only add extension if the page is running the Nextcloud Spreed app.
var nc = document.getElementById('app');
if (!nc || !hasClass(nc, 'nc-enable-screensharing-extension')) {
return;
}

var extension = nc.getAttribute('data-chromeExtensionData');
if (extension) {
try {
extension = JSON.parse(extension);
} catch (e) {
return;
}
}

console.log('Detected Nextcloud Spreed app.');
var msg = {
type: 'init-nc-screensharing',
data: {
extension: extension || null
}
};

chrome.runtime.sendMessage(null, msg, null, function(data) {
console.log('Initialized extension', data);
nc.setAttribute('data-chromeExtensionData', JSON.stringify(data));
});

}(document));
28 changes: 28 additions & 0 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "Nextcloud Screensharing",
"description": "Screensharing utility for the Nextcloud Spreed app.",
"author": "Joachim Bauch <bauch@struktur.de>",
"homepage_url": "https://nextcloud.com",
"version": "0.0.1",
"manifest_version": 2,
"minimum_chrome_version": "34",
"icons": {
},
"permissions": [
"tabs",
"desktopCapture",
"https://*/*"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"js": ["detector.js"],
"matches": ["https://*/*"],
"run_at": "document_end",
"all_frames": true
}
]
}

0 comments on commit 8322906

Please sign in to comment.