diff --git a/.bowerrc b/.bowerrc
deleted file mode 100644
index 5773025..0000000
--- a/.bowerrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "directory": "app/bower_components"
-}
diff --git a/.firebase/hosting.d2Vic2l0ZQ.cache b/.firebase/hosting.d2Vic2l0ZQ.cache
deleted file mode 100644
index bff5691..0000000
--- a/.firebase/hosting.d2Vic2l0ZQ.cache
+++ /dev/null
@@ -1,50 +0,0 @@
-styles/core.css,1595840369786,46b50c321b39e89a491b6727a01628c34245605a30beb3e7414c5e01cff90e6e
-index.html,1595840369867,ba089e47ba60710123d3517bf8af48f1002704b40af6ee456c339a786564e0ae
-html/iframe/chat.html,1595840369933,a671af0cddbeaef30f863717873e11ff6f295aed5ffbaa043494ebe0ec4a33ca
-images/icons/android-icon-192x192.png,1595840369917,ae586a4518a08bfae8f6ed29b180967bb1023b7dcc890d4a0eabf3a8f459c46c
-fonts/Open_Sans/LICENSE.txt,1595840369905,17f0f0a955b32272a4f41fd44841f95b2a7333f1641116547d4231e7b7af8361
-images/icons/android-icon-36x36.png,1595840369919,a14f796d3294bceef60489787316f6e97e9dbccd169f45d0d46b7415929b08ce
-images/icons/android-icon-48x48.png,1595840369921,415ac75bc2875ba8069b75b80a0fd03cf9e90b3b2a53a3f36355f63fcbc2b32a
-images/icons/android-icon-72x72.png,1595840369924,d87db46d6c8b5ce3210179935c731aa1a4e5bc9b4108ca8b52568e05340fb1d7
-images/icons/apple-icon-114x114.png,1595840369926,13b631bfe93beb1a578868b62e7001999a9732b31a340d480f57f4f1f5fd94f7
-images/icons/android-icon-96x96.png,1595840369925,065c26131ab232ba1253d61443df311930b9e4e8aab335858b7f8b66c6ea5533
-images/icons/apple-icon-120x120.png,1595840369926,66c4bfc967303dbac393aa40a04bdf8c952687339d42eeba6ac873e517f2ecfe
-images/icons/apple-icon-144x144.png,1595840369927,16d9acef18c051e16244a5a512d1c6469c4a5535ce387d07474586856e636b45
-images/icons/android-icon-144x144.png,1595840369914,16d9acef18c051e16244a5a512d1c6469c4a5535ce387d07474586856e636b45
-images/icons/apple-icon-152x152.png,1595840369927,903f37828f64d5a757084e3da808acb0d6143d5ae2f3bca602e3c301c3ec5f97
-images/icons/apple-icon-57x57.png,1595840369928,cb824f469da8903eb7fba95090612cd0bb534eb006fa95bfcabc3b3b430fb371
-images/icons/apple-icon-60x60.png,1595840369928,8f6b95268d1983217ad44978347bd892f7d37a17e9f48bf7d3192ab8a1160d3a
-images/icons/apple-icon-72x72.png,1595840369928,d87db46d6c8b5ce3210179935c731aa1a4e5bc9b4108ca8b52568e05340fb1d7
-images/icons/browserconfig.xml,1595840369930,cd6445d8fe791d1cae6328c3eee28a97d3e7e1bf501c62d8f2108f5087e7d730
-images/icons/apple-icon-180x180.png,1595840369927,9c1f053db53ee1c7c99cd795b261928a0f9b620ac74c74784968c5eec651bbe6
-images/icons/favicon-16x16.png,1595840369930,e2df1c109d2f44227cb4bff99c28a9958bbda1148db94c3a9792ec25f4f6e1d1
-images/icons/favicon-32x32.png,1595840369930,036accd70b5ce09dc6039d986e44736038261482d5d2742383494a9d389a3768
-images/icons/apple-icon.png,1595840369929,df258a3d133440aedb709977dd6fe387a0aed22617411a5560ac5b10dce6bad1
-images/icons/apple-icon-76x76.png,1595840369928,afa18b3b753e1d78323403a205ce94239e84f1da677bcf1e03248a04092cc83b
-images/icons/favicon-96x96.png,1595840369930,065c26131ab232ba1253d61443df311930b9e4e8aab335858b7f8b66c6ea5533
-images/icons/apple-icon-precomposed.png,1595840369929,df258a3d133440aedb709977dd6fe387a0aed22617411a5560ac5b10dce6bad1
-images/icons/manifest.json,1595840369931,46e7f5e409f1e10cb0007bcdd51eb6031ff1bd4a61d07513a4d2b80f6cc5381f
-images/icons/ms-icon-144x144.png,1595840369931,16d9acef18c051e16244a5a512d1c6469c4a5535ce387d07474586856e636b45
-images/icons/ms-icon-150x150.png,1595840369932,b0d8b457a7a60a064472bdfa5c7c83110ccc1defe296184468bc75756e5d4540
-images/icons/ms-icon-310x310.png,1595840369932,ad87c2f970d82d2f57add11fa0750eb135459b158bf0f8b8ce4839e92cbb31b9
-scripts/backgroundPortManager.js,1595840369901,341513c3258d73a2c170f280d015206404e8e4ab1269dc794d6957b36d9a4b79
-images/icons/favicon.ico,1595840369931,637008d0ad07668fa8f0251760e4c71dc0b9649d8d8098fa35abce8c562cf011
-scripts/backgroundPortManager.js.map,1595840369837,be6470ef1384147836c2f2c0334f7735e2e95516c1534fff1ac1eb18162ef167
-scripts/chat.js,1595840369786,9955a95b2ef9ff07630c1124bdfe9355950d5672d50fa83c9bedce42db7a81b1
-scripts/chat.js.map,1595840369783,3b52c180214bf3a858c85ca6b727605046dba44e67e77de44b3bcb9f51eb301d
-scripts/inject.js,1595840369789,ce9d5502c41c85e883e02dc1fd4123d494c4750c9862b322c8b1f525d15e87e7
-images/icons/ms-icon-70x70.png,1595840369932,703d7e1c795ddf09ee426e60fc3edde9e69a663aa7ea1a464addbe1972f0b635
-scripts/logger.js,1595840369750,8531df21fded5c2b7c0c28b2548e5d4cd2437c57f10d52802d821095a48741ea
-scripts/logger.js.map,1595840369749,082250fe83e2fe9aee688ad427ff3d7a50c6ec2a81f039a0dc2eca9140164451
-scripts/portManager.js,1595840369903,eb655c910f173e6ebb2ec3b402804573963eac626b183331d8cacebe34ad94c5
-styles/chat.css,1595840369787,243f520009fdb00e153908a2b3a57eea6853981e250775cefef18f476906cc48
-styles/inject.css,1595840369787,b4434f3afb87583142913b017f9092ff0723fec77e50c16d1fd880c4e26bf7bb
-scripts/portManager.js.map,1595840369838,af571486e2042c3f2c14ed4b87846a10bb4840467814ceb390bc5a13982e604d
-scripts/inject.js.map,1595840369789,80faf7b5ee6729bfc7fc7624a2b77853da00761ed14b556cd4cbdea8c469cb53
-libs/jquery-3.5.1.min.js,1595840369788,a6c14aef7ed02ef768bcdbb789322eea70b6a860e467cdbcc1238429e3274c5f
-images/aero_arrow.cur,1595840369888,4b93b0fd38f2201b3516f4ebbaf8132ae23207c246fac2755ad3f794b5bcd37b
-fonts/Open_Sans/OpenSans-ExtraBold.ttf,1595840369908,0b790194f0e2d1f5665624f990a7ea11cc76b90670691bf54a4e654e4f9be595
-fonts/Open_Sans/OpenSans-Regular.ttf,1595840369911,966d538f2bd817920517cb7db6439d226be602c95ec4919483737fd74c198089
-libs/jquery-3.5.1.min.js.map,1595840369788,5d5f9d57069201811da9ec14bd1398f3b9fec24fb13e179e39b2562dc36f1a9d
-scripts/bundle.js,1595840369781,5bf85cc6b943a420b9a13f4d7cde5dc53ddd6146cc3c07802d340b146f054805
-scripts/bundle.js.map,1595840369772,dedc40529e52ab54731d6331a5d7da99a3ee9fe4dc1e2307c39ffe1cbc222372
diff --git a/.gitignore b/.gitignore
index d47ba66..c874f0e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ temp
.tmp
.firebase
dist
+notes
.sass-cache
app/bower_components
website
diff --git a/.yo-rc.json b/.yo-rc.json
deleted file mode 100644
index c6bb600..0000000
--- a/.yo-rc.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "generator-mocha": {
- "ui": "bdd",
- "rjs": false
- }
-}
\ No newline at end of file
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..aeb3c37
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,14 @@
+Requires npm and gulp to build
+
+Versions used to build v1.0.0 of Internet Friends:
+
+npm v8.4.1
+gulp CLI v2.3.0
+gulp Local v4.0.2
+
+To build:
+
+1) cd to the root directory
+2) run 'npm install'
+3) run 'gulp'
+4) run 'gulp package'
\ No newline at end of file
diff --git a/app/extension/html/background.html b/app/extension/html/background.html
deleted file mode 100644
index c5f9f5d..0000000
--- a/app/extension/html/background.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
- Internet Friends
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/extension/html/iframe/chat.html b/app/extension/html/iframe/chat.html
index d7f37fb..92a6612 100644
--- a/app/extension/html/iframe/chat.html
+++ b/app/extension/html/iframe/chat.html
@@ -7,7 +7,7 @@
-
+
Internet Friends
diff --git a/app/extension/scripts/backgroundPortManager.js b/app/extension/scripts/backgroundPortManager.js
deleted file mode 100644
index 9fd73a9..0000000
--- a/app/extension/scripts/backgroundPortManager.js
+++ /dev/null
@@ -1,170 +0,0 @@
-'use strict';
-
-var backgroundPortManager = function (messageCallback, roomDisconnectCallback){
- // variables ----------------------------------------------------------------
- var _this = {},
- _openTabs = {},
- _rooms = {},
- _messageCallback = null,
- _roomDisconnectCallback = null;
-
- // initialize ---------------------------------------------------------------
- _this.init = function (messageCallback, roomDisconnectCallback){
- _messageCallback = messageCallback;
- _roomDisconnectCallback = roomDisconnectCallback;
-
- // send messages from "background.js"
- chrome.runtime.onConnect.addListener(processTabPortConnected);
-
- Logger.log('Internet Friends Background Port Manager Initialized');
- };
-
- // private functions --------------------------------------------------------
- function getUrl(port) {
- let url;
-
- if (port.sender.tab.url) { // Chrome
- url = new URL(port.sender.tab.url);
- }
- else // FireFox
- {
- var tabId = port.sender.tab.id;
- var source = port.name;
- if (source == 'InternetFriends-main') {
- url = new URL(port.sender.tab.url);
- } else if (_openTabs[tabId]['InternetFriends-main']) {
- url = new URL(_openTabs[tabId]['InternetFriends-main'].sender.url);
- }
- }
-
- return url;
- }
-
- function getRoomCodeFromPort(port, url) {
- // Room code is based on url and title
- // e.g. 'www.google.com/search : test - Google Search'
- // The goal is to group users based on the page they're currently on
- // Ignoring url.search because many websites url.search values are unique to each user
- var url = getUrl(port);
- return url.host + url.pathname + " : " + port.sender.tab.title;
- }
-
- // events -------------------------------------------------------------------
- function processTabPortConnected (port){
- // Only process if site not disabled
- var websiteUrl = getUrl(port);
-
- // If websiteUrl is present in disabledSites, InternetFriends is disabled for this site, return
- if (IFSettings.disabledSites[websiteUrl.host])
- return;
-
- var tabId = port.sender.tab.id;
- var source = port.name;
- var roomCode = getRoomCodeFromPort(port);
-
- Logger.log('Tab Connected RoomCode: ' + roomCode + ' ID: ' + tabId);
-
- // Add port to tab
- if(!_openTabs[tabId])
- _openTabs[tabId] = {};
-
- _openTabs[tabId][source] = port;
-
- // Create room
- if (!_rooms[roomCode])
- _rooms[roomCode] = {};
-
- // Add tab to room
- _rooms[roomCode][tabId] = true;
-
- // After both sources have connected
- if(_openTabs[tabId]['InternetFriends-chat'] &&
- _openTabs[tabId]['InternetFriends-main'])
- {
- // Setup Listeners
- _openTabs[tabId]['InternetFriends-chat'].onMessage.addListener(function (event) { processMessage(event, tabId, 'InternetFriends-chat', roomCode) });
- _openTabs[tabId]['InternetFriends-main'].onMessage.addListener(function (event) { processMessage(event, tabId, 'InternetFriends-main', roomCode) });
- _openTabs[tabId]['InternetFriends-chat'].onDisconnect.addListener(function () { processTabPortDisconnect(tabId, 'InternetFriends-chat', roomCode) });
- _openTabs[tabId]['InternetFriends-main'].onDisconnect.addListener(function () { processTabPortDisconnect(tabId, 'InternetFriends-main', roomCode) });
-
- // Post loaded messages
- _openTabs[tabId]['InternetFriends-chat'].postMessage({event: 'loaded'});
- _openTabs[tabId]['InternetFriends-main'].postMessage({event: 'loaded'});
- }
- };
-
- function processMessage (message, tabId, source, roomCode) {
- _messageCallback(message, roomCode);
-
- // Forward to iframe
- if(source != 'InternetFriends-chat') {
- message.data.userId = "localuser";
- _this.tellByTabId(tabId, message);
- }
- }
-
- function processTabPortDisconnect (tabId, source, roomCode){
- // process the disconnect
- if (_openTabs[tabId]) {
- delete _openTabs[tabId][source];
- }
-
- if(source == 'InternetFriends-main') {
- delete _openTabs[tabId];
- delete _rooms[roomCode][tabId];
-
- let tabIds = Object.keys(_rooms[roomCode]);
-
- // If there are no other tabs associated with this room code, disconnect
- if (tabIds.length === 0)
- _roomDisconnectCallback(roomCode);
- }
- };
-
- // public functions ---------------------------------------------------------
- _this.tellByRoomCode = function (roomCode, data){
- if (!_rooms[roomCode])
- return false;
-
- let success = false;
-
- // Loop through all tabs that are associated with the given room code
- for (var tabId in _rooms[roomCode]) {
- success ||= _this.tellByTabId(tabId, data);
- }
-
- // If any tabs were found, this should return true
- return success;
- };
-
- _this.tellByTabId = function (tabId, data){
- if(_openTabs[tabId] && _openTabs[tabId]["InternetFriends-chat"]) {
- _openTabs[tabId]["InternetFriends-chat"].postMessage(data);
- return true;
- }
-
- return false;
- };
-
- _this.updateBadgeTextByRoomCode = function (roomCode, peers) {
- if (!_rooms[roomCode])
- return false;
-
- // Loop through all tabs that are associated with the given room code
- for (var tabId in _rooms[roomCode]) {
- chrome.browserAction.setBadgeText(
- {
- text: peers > 0 ? peers.toString() : '',
- tabId: parseInt(tabId)
- }
- );
- }
-
- return true;
- };
-
- // messages -----------------------------------------------------------------
- _this.init(messageCallback, roomDisconnectCallback);
-
- return _this;
-};
diff --git a/app/extension/scripts/portManager.js b/app/extension/scripts/portManager.js
index 2e2ccc9..e0605d2 100644
--- a/app/extension/scripts/portManager.js
+++ b/app/extension/scripts/portManager.js
@@ -12,26 +12,9 @@ var portManager = function (source, messageCallback, disconnectCallback){
_messageListener = messageCallback;
_disconnectListener = disconnectCallback;
- // receive messages from "background.js"
- _port = chrome.runtime.connect({name: "InternetFriends-" + source});
- _port.onMessage.addListener(port_onMessage);
- _port.onDisconnect.addListener(port_onDisconnect);
-
Logger.log(`PortManager Initialized in "${source}"`);
};
- // private functions --------------------------------------------------------
-
- // events -------------------------------------------------------------------
- function port_onMessage (message){
- // call the listener callback
- if (_messageListener) _messageListener(message);
- };
-
- function port_onDisconnect (){
- if (_disconnectListener) _disconnectListener();
- };
-
// public functions ---------------------------------------------------------
_this.tell = function (event, data){
var data = data || {};
@@ -43,6 +26,25 @@ var portManager = function (source, messageCallback, disconnectCallback){
});
}
};
+
+ _this.connect = function () {
+ Logger.log("Connecting to Background Script...");
+
+ _port = chrome.runtime.connect({name: "InternetFriends-" + source});
+
+ if (_messageListener) _port.onMessage.addListener(_messageListener);
+ if (_disconnectListener) _port.onDisconnect.addListener(_disconnectListener);
+ }
+
+ _this.disconnect = function () {
+ if (!_port)
+ return;
+
+ Logger.log("Disconnecting from Background Script...");
+
+ _port.disconnect();
+ _port = null;
+ }
// messages -----------------------------------------------------------------
_this.init(source, messageCallback, disconnectCallback);
diff --git a/app/manifest.json b/app/manifest.json
index 4bebfd0..f05ac43 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,20 +1,20 @@
{
"name": "__MSG_appName__",
- "version": "1.0.0",
- "manifest_version": 2,
+ "version": "1.1.1",
+ "manifest_version": 3,
"description": "__MSG_appDescription__",
"icons": {
"16": "images/icon-16.png",
"128": "images/icon-128.png"
},
"default_locale": "en",
- "incognito": "split",
"background": {
- "page": "html/background.html"
+ "service_worker": "scripts/background.js"
},
"permissions": [
"storage",
- "activeTab"
+ "activeTab",
+ "tabs"
],
"content_scripts": [{
"matches": [
@@ -42,19 +42,23 @@
"run_at": "document_start"
}],
"web_accessible_resources": [
- "scripts/logger.js",
- "scripts/settings.js",
- "scripts/backgroundPortManager.js",
- "scripts/bundle.js",
- "scripts/popup.js",
- "html/iframe/chat.html",
- "scripts/chat.js",
- "styles/core.css",
- "styles/chat.css",
- "styles/slider.css",
- "styles/popup.css"
+ {
+ "resources": [
+ "scripts/logger.js",
+ "scripts/settings.js",
+ "scripts/background.js",
+ "scripts/popup.js",
+ "html/iframe/chat.html",
+ "scripts/bundle.js",
+ "styles/core.css",
+ "styles/chat.css",
+ "styles/slider.css",
+ "styles/popup.css"
+ ],
+ "matches": ["*://*/*"]
+ }
],
- "browser_action": {
+ "action": {
"default_popup": "html/popup.html",
"default_icon": {
"19": "images/icon-19.png",
diff --git a/app/scripts.babel/background.js b/app/scripts.babel/background.js
index d3c6389..595a012 100644
--- a/app/scripts.babel/background.js
+++ b/app/scripts.babel/background.js
@@ -1,166 +1,67 @@
-'use strict';
-
-var swarm = require('webrtc-swarm')
-var signalhub = require('signalhub')
-
-var Background = (function() {
- // variables ----------------------------------------------------------------
- var _this = {},
- _local = false,
- _portManager = null,
- _swarms = {};
-
- // initialize ---------------------------------------------------------------
- _this.init = function() {
- // receive post messages from 'inject.js' and any iframes
- _portManager = new backgroundPortManager(processMessageFromBrowser, processRoomDisconnect);
-
- if (chrome && chrome.browserAction) {
- chrome.browserAction.setBadgeBackgroundColor({ color: IFSettings.userColor });
-
- // add listener for storage changes
- IFEvents.addEventListener('settings.change.userColor', function () {
- chrome.browserAction.setBadgeBackgroundColor({color: IFSettings.userColor });
- });
- }
-
- Logger.log('Internet Friends Background Script Initialized');
- };
-
- // private functions --------------------------------------------------------
- function connectToSwarm(roomCode, callback) {
- if (_swarms[roomCode])
- return;
-
- Logger.log('connecting to swarm ', roomCode);
-
- // init user info message
- var userInfoMessage = {
- event: 'userInfo',
- data: {
- userId: 'localuser',
- userColor: IFSettings.userColor,
- }
- }
-
- // send user info message to front end
- _portManager.tellByRoomCode(roomCode, userInfoMessage);
-
- var hub = signalhub(roomCode, _local ? ['localhost:8080'] : ['https://if-signalhub.herokuapp.com/'])
- _swarms[roomCode] = swarm(hub)
-
- _swarms[roomCode].on('peer', function(peer, id) {
- Logger.log('connected to a new peer:', id)
- Logger.log('total peers:', _swarms[roomCode].peers.length)
-
- // setup data listener
- peer.on('data', (payload) => {
- const message = JSON.parse(payload.toString())
- message.data.source = 'peer'
- message.data.userId = id
- Logger.log(message);
-
- // Forward the message to the chat window
- const foundRoom = _portManager.tellByRoomCode(roomCode, message);
- if (!foundRoom) {
- disconnectFromSwarm(roomCode)
+// ---------------------------------------- Badge Text Listener ----------------------------------------
+chrome.runtime.onMessage.addListener(
+ function(request, sender, sendResponse) {
+ if (request.event === 'updateBadgeText')
+ {
+ let peers = request.data.peers;
+
+ chrome.action.setBadgeText(
+ {
+ text: peers > 0 ? peers.toString() : '',
+ tabId: sender.tab.id
}
- })
-
- // update the badge based on the number of peers
- _portManager.updateBadgeTextByRoomCode(roomCode, _swarms[roomCode].peers.length);
-
- // send user info message to peers on connection
- userInfoMessage.data.userColor = IFSettings.userColor;
- peer.send(JSON.stringify(userInfoMessage));
- })
-
- _swarms[roomCode].on('disconnect', function(peer, id) {
- Logger.log('disconnected from a peer:', id)
- _portManager.tellByRoomCode(roomCode, {
- event: 'disconnected',
- data: {
- source: 'peer',
- userId: id
- }
- });
-
- // update the badge based on the number of peers
- _portManager.updateBadgeTextByRoomCode(roomCode, _swarms[roomCode] ? _swarms[roomCode].peers.length : 0);
- })
-
- // Resend user info if the user color is changed
- IFEvents.addEventListener('settings.change.userColor', function () {
- userInfoMessage.data.userColor = IFSettings.userColor;
-
- // send to the swarm
- sendMessageToSwarm(userInfoMessage, roomCode);
-
- // also send locally
- _portManager.tellByRoomCode(roomCode, userInfoMessage);
- });
-
- if (callback)
- callback();
- };
-
- function disconnectFromSwarm(roomCode) {
- if (_swarms[roomCode]) {
- Logger.log('disconnecting from swarm ', roomCode);
-
- _swarms[roomCode].close()
- delete _swarms[roomCode]
-
- Logger.log('disconnected');
+ );
}
- };
-
- function sendMessageToSwarm(message, roomCode) {
- // if message if intended for a new swarm
- if (!_swarms[roomCode]) {
- // connect to the new swarm
- connectToSwarm(roomCode, function () {
- // once connected, send the message to the swarm
- if (_swarms[roomCode]) {
- _swarms[roomCode].peers.forEach((peer) => {
- peer.send(JSON.stringify(message));
- });
- }
- });
+ else if (request.event === 'updateBadgeColor')
+ {
+ chrome.action.setBadgeBackgroundColor({ color: request.data.userColor });
}
- // already connected, send the message to the swarm
- else if (_swarms[roomCode]) {
- _swarms[roomCode].peers.forEach((peer) => {
- peer.send(JSON.stringify(message));
- });
- }
- };
- // events -------------------------------------------------------------------
- function processMessageFromBrowser(message, roomCode) {
- if (message.event == 'pageHidden') {
- disconnectFromSwarm(roomCode);
- } else if (message.event == 'pageVisible') {
- connectToSwarm(roomCode);
- } else if (message.event != 'scroll') {
- var wsMessage = JSON.parse(JSON.stringify(message));
- sendMessageToSwarm(wsMessage, roomCode);
- }
+ // dummy response due to bug: https://stackoverflow.com/questions/71520198/manifestv3-new-promise-error-the-message-port-closed-before-a-response-was-rece/71520415#71520415
+ sendResponse();
+ }
+);
+
+// ---------------------------------------- Logger ----------------------------------------
+var debug = false;
+var Logger = {
+ log: debug ? console.log.bind(console) : function(){}
+};
+
+// ---------------------------------------- Settings ----------------------------------------
+// wrap in a self-invoking function to use define private variables & functions
+(function () {
+ // define default combo
+ var _defaultCombo = {
+ ctrlKey: true,
+ shiftKey: true,
+ altKey: false,
+ key: "Enter"
};
- function processRoomDisconnect(roomCode) {
- disconnectFromSwarm(roomCode);
- };
+ // define function for getting a random color
+ function getRandomColor () {
+ return 'hsla(' + Math.round(Math.random() * 360) + ', 78%, 54%, 1)';
+ }
+
+ // if chrome is available
+ if (chrome && chrome.storage) {
+ // retrieve settings from storage
+ chrome.storage.sync.get(null, function(result) {
+ var storedSettings = result;
+
+ // set settings based on storedSettings, get default values if necessary
+ var settings = {
+ combo: storedSettings?.combo || _defaultCombo,
+ disabledSites: storedSettings?.disabledSites || {},
+ enableChat: storedSettings?.enableChat === true || storedSettings?.enableChat === undefined,
+ userColor: storedSettings?.userColor || getRandomColor()
+ }
- return _this;
-}());
+ // store new settings
+ chrome.storage.sync.set(settings);
-// If IFSettings have not been initialized, wait for init event to be dispatched
-if (!IFSettings) {
- IFEvents.addEventListener('settings.init', function () {
- Background.init();
- });
-} else {
- // else, init now
- Background.init();
-}
\ No newline at end of file
+ Logger.log('Settings initialized:', settings);
+ });
+ }
+}());
\ No newline at end of file
diff --git a/app/scripts.babel/chat.js b/app/scripts.babel/chat.js
index bfcbd2f..3653321 100644
--- a/app/scripts.babel/chat.js
+++ b/app/scripts.babel/chat.js
@@ -1,3 +1,110 @@
+var swarm = require('webrtc-swarm')
+var signalhub = require('signalhub')
+const { createHash } = require('crypto');
+
+var IFSwarm = function(messageCallback) {
+ // variables ----------------------------------------------------------------
+ var _this = {},
+ _local = false,
+ _swarm = null,
+ _messageCallback = messageCallback,
+ _userInfoMessage = {
+ event: 'userInfo',
+ data: {}
+ };
+
+
+ // initialize ---------------------------------------------------------------
+ function init() {
+ };
+
+ // public functions --------------------------------------------------------
+ _this.connect = function(roomCode) {
+ if (_swarm)
+ return;
+
+ let encodedRoomCode = createHash('sha256').update(roomCode).digest('hex');
+
+ Logger.log('connecting to swarm ', roomCode);
+ Logger.log('encoded room code: ', encodedRoomCode);
+
+ var hub = signalhub(encodedRoomCode, _local ? ['localhost:8080'] : ['https://if-signalhub.herokuapp.com/'])
+ _swarm = swarm(hub, { wrtc: require('wrtc') })
+
+ _swarm.on('peer', function(peer, id) {
+ Logger.log('connected to a new peer:', id)
+ Logger.log('total peers:', _swarm.peers.length)
+
+ // setup data listener
+ peer.on('data', (payload) => {
+ const message = JSON.parse(payload.toString())
+ message.data.source = 'peer'
+ message.data.userId = id
+ Logger.log(message);
+
+ // fire callback with the given message
+ _messageCallback(message);
+ })
+
+ // update the badge based on the number of peers
+ chrome.runtime.sendMessage({ event: 'updateBadgeText', data: { peers: _swarm ? _swarm.peers.length : 0 }});
+
+ // send user info message to peers on connection
+ _userInfoMessage.data.userColor = IFSettings.userColor;
+ peer.send(JSON.stringify(_userInfoMessage));
+ })
+
+ _swarm.on('disconnect', function(peer, id) {
+ Logger.log('disconnected from a peer:', id)
+
+ // fire callback with the given message
+ _messageCallback({
+ event: 'disconnected',
+ data: {
+ source: 'peer',
+ userId: id
+ }
+ });
+
+ // update the badge based on the number of peers
+ chrome.runtime.sendMessage({ event: 'updateBadgeText', data: { peers: _swarm ? _swarm.peers.length : 0 }});
+ })
+
+ // Resend user info if the user color is changed
+ IFEvents.addEventListener('settings.change.userColor', function () {
+ _userInfoMessage.data.userColor = IFSettings.userColor;
+
+ // send to the swarm
+ _this.sendMessage(_userInfoMessage);
+ });
+ };
+
+ _this.disconnect = function () {
+ if (!_swarm)
+ return;
+
+ Logger.log('disconnecting from swarm');
+
+ _swarm.close()
+ _swarm = null;
+
+ Logger.log('disconnected');
+ };
+
+ _this.sendMessage = function (message) {
+ if (!_swarm)
+ return;
+
+ _swarm.peers.forEach((peer) => {
+ peer.send(JSON.stringify(message));
+ });
+ };
+
+ init();
+
+ return _this;
+};
+
var User = function(id, submitCallback) {
// variables ----------------------------------------------------------------
var _this = {},
@@ -26,8 +133,14 @@ var User = function(id, submitCallback) {
if (_id == "localuser") {
_inputElement = $('').appendTo(_userElement);
setupInputElement();
+ _this.setColor(IFSettings.userColor);
+
+ // Add listener for color changes
+ IFEvents.addEventListener('settings.change.userColor', function () {
+ _this.setColor(IFSettings.userColor);
+ });
} else {
- var cursorURL = typeof chrome !== "undefined" && chrome.extension ? chrome.extension.getURL('../../images/aero_arrow.png') : './images/aero_arrow.png';
+ var cursorURL = typeof chrome !== "undefined" && chrome.runtime ? chrome.runtime.getURL('../../images/aero_arrow.png') : './images/aero_arrow.png';
_mouseElement = $('').appendTo(_userElement);
_mouseBGElm = $('').appendTo(_mouseElement);
_mouseBGElm.css({ 'background-image': 'url(' + cursorURL + ')' });
@@ -62,8 +175,10 @@ var User = function(id, submitCallback) {
};
function repositionElements() {
- _userElement.css('top', _mousePosition.y + 'px');
- _userElement.css('left', _mousePosition.x + 'px');
+ _userElement.css({
+ 'top': _mousePosition.y + 'px',
+ 'left': _mousePosition.x + 'px'
+ });
if (!_flipped && _mousePosition.x > document.documentElement.clientWidth / 2) {
_flipped = true;
@@ -135,22 +250,53 @@ var User = function(id, submitCallback) {
var Chat = (function() {
// variables ----------------------------------------------------------------
var _this = {},
- _portManager = null,
+ _roomCode = null,
+ _connectionTimeout = null,
_users = {},
- _scrollPosition = {},
- _mouseVisible = true;
+ _scrollPosition = { x: 0, y: 0 },
+ _mouseVisible = true,
+ _swarm = null;
// initialize ---------------------------------------------------------------
_this.init = function() {
Logger.log('Chat View Initialized')
- _portManager = new portManager("chat", onMessage);
- _scrollPosition = { x: 0, y: 0 };
+ Logger.log('Chat Init Visibility State: ', document.visibilityState);
+
+ _swarm = new IFSwarm(onMessage);
+
+ window.addEventListener("message", (event) => {
+ if (event.data.data)
+ event.data.data.userId = 'localuser';
+
+ onMessage(event.data);
+ });
+
+ document.addEventListener("visibilitychange", onVisibilityStateChanged, false);
+
+ window.parent.postMessage('iframeInitialized', '*');
};
// events -------------------------------------------------------------------
function onMessage(message) {
Logger.log('got chat message', message)
+
+ // forward certain messages that didn't come from the swarm (from a peer)
+ if (_swarm && (!message.data.source || message.data.source != 'peer')) {
+ switch (message.event) {
+ case 'userInfo':
+ case 'mousemove':
+ case 'userchat':
+ case 'disconnected':
+ _swarm.sendMessage(message);
+ break;
+ }
+ }
+
+ // process messages
switch (message.event) {
+ case 'roomCodeChanged':
+ message_onRoomCodeChanged(message.data);
+ break;
case 'userInfo':
message_onUserInfo(message.data);
break;
@@ -182,8 +328,18 @@ var Chat = (function() {
// private functions ---------------------------------------------------------
function submitInput(message) {
- var data = { message: message };
- _portManager.tell('userchat', data);
+ // process locally
+ message_onUserchat({ userId: 'localuser', message: message })
+
+ // send to swarm
+ if (_swarm) {
+ _swarm.sendMessage({
+ event: 'userchat',
+ data: {
+ message: message
+ }
+ });
+ }
};
function getUser(userId) {
@@ -192,8 +348,40 @@ var Chat = (function() {
return _users[userId];
};
+
+ function onVisibilityStateChanged() {
+ Logger.log('Visiblility Changed: ', document.visibilityState);
+ tryConnect();
+ }
+
+ function tryConnect() {
+ // wait one second before connecting in case multiple changes are made in rapid succession
+ clearTimeout(_connectionTimeout);
+ _connectionTimeout = setTimeout(function () {
+ if (document.visibilityState === 'visible') {
+ _swarm.connect(_roomCode);
+ } else {
+ _swarm.disconnect();
+ }
+ }, 1000);
+ }
// messages -----------------------------------------------------------------
+ function message_onRoomCodeChanged(data) {
+ // if the room code is the same, return
+ if (data.roomCode === _roomCode)
+ return;
+
+ // disconnect from the current room
+ _swarm.disconnect();
+
+ // set the new room code
+ _roomCode = data.roomCode;
+
+ // reconnect to the swarm
+ tryConnect();
+ }
+
function message_onUserInfo(data) {
var user = getUser(data.userId);
user.setColor(data.userColor);
diff --git a/app/scripts.babel/inject.js b/app/scripts.babel/inject.js
index cb0196c..89205c6 100644
--- a/app/scripts.babel/inject.js
+++ b/app/scripts.babel/inject.js
@@ -2,14 +2,14 @@ var Inject = (function() {
// constants ----------------------------------------------------------------
var ID = {
CONTAINER: 'internetFriends-container',
- IFRAME_PREFIX: 'internetFriends-iframe-'
+ IFRAME: 'internetFriends-iframe'
};
// variables ----------------------------------------------------------------
var _this = {},
- _views = {},
_container = null,
- _portManager = null,
+ _iframe = null,
+ _roomCode = null,
_comboDown = false;
// initialize ---------------------------------------------------------------
@@ -23,25 +23,50 @@ var Inject = (function() {
return;
}
- // create the main container
- _container = $('', { id: ID.CONTAINER });
- _container.appendTo(document.body);
+ // add message listener
+ window.addEventListener("message", (event) => {
+ switch (event.data) {
+ case 'iframeInitialized':
+ onIframeInitialized();
+ break;
+ }
+ });
+ // create the main container
+ _container = document.createElement('div');
+ _container.id = ID.CONTAINER;
+ document.body.append(_container);
+
// add the "chat" iframe
- getView('chat', _container);
-
- // setup port manager to communicate with background.js
- _portManager = new portManager("main", onMessage, onDisconnect);
- _portManager.tell("tabInit");
+ _iframe = document.createElement('iframe');
+ _iframe.id = ID.IFRAME;
+ _iframe.src = typeof chrome !== "undefined" && chrome.runtime ? chrome.runtime.getURL('html/iframe/chat.html?view=chat&_' + new Date().getTime()) : './html/iframe/chat.html';
+ _container.append(_iframe);
+ };
+ // private functions --------------------------------------------------------
+ function onIframeInitialized() {
+ Logger.log('iFrame initialized, sendMessage and swarm events are now available');
+
+ // update the room code
+ _roomCode = getRoomCode();
+ onRoomCodeChanged();
+
+ // add listener to detect room code changes that occur without page refresh
+ new MutationObserver(() => {
+ let roomCode = getRoomCode();
+ if (_roomCode !== roomCode) {
+ _roomCode = roomCode;
+ onRoomCodeChanged();
+ }
+ }).observe(document, {subtree: true, childList: true});
+
// add event listeners
document.addEventListener("scroll", dom_onScroll, false);
document.addEventListener("mouseover", dom_onMousemove, false);
document.addEventListener("mousemove", dom_onMousemove, false);
document.addEventListener("mouseenter", dom_onMouseenter, false);
document.addEventListener("mouseleave", dom_onMouseleave, false);
- document.addEventListener("webkitvisibilitychange", dom_onVisibilityChange, false);
- document.addEventListener("msvisibilitychange", dom_onVisibilityChange, false);
// if chat is not enabled, return
if (!IFSettings.enableChat) {
@@ -52,90 +77,41 @@ var Inject = (function() {
// only detect key presses if chat is enabled
document.addEventListener("keydown", dom_onKeydown, false);
document.addEventListener("keyup", dom_onKeyup, false);
- };
-
- // private functions --------------------------------------------------------
- function getView(id) {
- // return the view if it's already created
- if (_views[id]) return _views[id];
-
- // iframe initial details
- var src = typeof chrome !== "undefined" && chrome.extension ? chrome.extension.getURL('html/iframe/' + id + '.html?view=' + id + '&_' + new Date().getTime()) : './html/iframe/chat.html',
- iframe = $('', { id: ID.IFRAME_PREFIX + id, src: src, scrolling: false });
-
- // view
- _views[id] = {
- isLoaded: false,
- iframe: iframe
- };
-
- // add to the container
- _container.append(iframe);
-
- return _views[id];
- };
-
- // messages coming from "background.js"
- function onMessage(request) {
- Logger.log(request);
-
- switch (request.event) {
- case 'loaded':
- message_onLoaded();
- break;
- }
- };
-
- function onDisconnect() {
- Logger.log("Tab Disconnected from Background Scripts");
-
- // remove related elements
- getView('chat', _container).iframe.remove();
- _container.remove();
-
- // remove event listeners
- document.removeEventListener("scroll", dom_onScroll, false);
- document.removeEventListener("mouseover", dom_onMousemove, false);
- document.removeEventListener("mousemove", dom_onMousemove, false);
- document.removeEventListener("mouseenter", dom_onMouseenter, false);
- document.removeEventListener("mouseleave", dom_onMouseleave, false);
- document.removeEventListener("keydown", dom_onKeydown, false);
- document.removeEventListener("keyup", dom_onKeyup, false);
- document.removeEventListener("webkitvisibilitychange", dom_onVisibilityChange, false);
- document.removeEventListener("msvisibilitychange", dom_onVisibilityChange, false);
-
- _portManager = null;
- };
+ }
- function isPageHidden() {
- return document.hidden || document.msHidden || document.webkitHidden;
+ function onRoomCodeChanged() {
+ sendMessage('roomCodeChanged', { roomCode: _roomCode });
}
- // messages -----------------------------------------------------------------
- function message_onLoaded() {
- var data = { scrollX: window.scrollX, scrollY: window.scrollY };
+ function getRoomCode() {
+ // Room code is based on url and title
+ // e.g. 'www.google.com/search : test - Google Search'
+ // The goal is to group users based on the page they're currently on
+ // Ignoring url.search because many websites url.search values are unique to each user
+ return document.location.host + document.location.pathname + ':' + document.title;
+ }
- if (_portManager)
- _portManager.tell("scroll", data);
+ function sendMessage(event, data) {
+ _iframe.contentWindow.postMessage({ event, data: data || {} }, 'chrome-extension://' + chrome.runtime.id);
}
// events -------------------------------------------------------------------
function dom_onScroll() {
var data = { scrollX: window.scrollX, scrollY: window.scrollY };
- _portManager.tell("scroll", data);
+ sendMessage("scroll", data);
};
function dom_onMousemove(event) {
var data = { x: event.pageX, y: event.pageY, vw: ((event.pageX / document.documentElement.clientWidth) * 100) };
- _portManager.tell("mousemove", data);
+ sendMessage("mousemove", data);
};
function dom_onMouseenter(event) {
- _portManager.tell("mouseenter");
+ sendMessage("mouseenter");
};
function dom_onMouseleave(event) {
- _portManager.tell("mouseleave");
+ sendMessage("mouseleave");
};
function dom_onKeydown(event) {
@@ -158,20 +134,12 @@ var Inject = (function() {
// Detect combo release
if (event.ctrlKey == combo.ctrlKey && event.shiftKey == combo.shiftKey && event.altKey == combo.altKey && key === combo.key && _comboDown) {
Logger.log('Key Combo Detected. Opening Chat.');
- _portManager.tell("openchat");
+ sendMessage("openchat");
_comboDown = false;
event.preventDefault();
}
};
- function dom_onVisibilityChange(event) {
- if (isPageHidden()) {
- _portManager.tell("pageHidden");
- } else {
- _portManager.tell("pageVisible");
- }
- }
-
return _this;
}());
diff --git a/app/scripts.babel/popup.js b/app/scripts.babel/popup.js
index d1ccead..f60aa36 100644
--- a/app/scripts.babel/popup.js
+++ b/app/scripts.babel/popup.js
@@ -64,7 +64,7 @@ var Popup = (function() {
});
var _mouseBGElm = document.getElementById('fakeMouse');
- var cursorURL = typeof chrome !== "undefined" && chrome.extension ? chrome.extension.getURL('../../images/aero_arrow.png') : '../images/aero_arrow.png';
+ var cursorURL = typeof chrome !== "undefined" && chrome.runtime ? chrome.runtime.getURL('../../images/aero_arrow.png') : '../images/aero_arrow.png';
_mouseBGElm.style.backgroundImage = "url(" + cursorURL + ")";
let initColor = { h: 207, s: 86, v: 95 };
let hsl = colorWheel.color.hsl;
@@ -107,6 +107,7 @@ var Popup = (function() {
// private functions --------------------------------------------------------
function updateUserColor () {
chrome.storage.sync.set({'userColor': _userColor});
+ chrome.runtime.sendMessage({ event: 'updateBadgeColor', data: { userColor: _userColor }});
}
function setComplementaryColors (iroColor) {
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 3173391..0000000
--- a/bower.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "internetfriends",
- "private": true,
- "version": "0.0.0",
- "dependencies": {},
- "devDependencies": {
- "chai": "^4.2.0",
- "mocha": "^8.0.1"
- }
-}
diff --git a/gulpfile.js b/gulpfile.js
index 9229ff4..5d97253 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -34,7 +34,7 @@ function jsBabel() {
function jsBrowserify() {
return browserify({
- entries: 'app/scripts/background.js',
+ entries: 'app/scripts/chat.js',
debug: false
})
.bundle()
@@ -64,7 +64,7 @@ function res(cb) {
const manifest = require('./app/manifest.json');
var log = require('fancy-log');
var debug = require('gulp-debug');
- return src(manifest.web_accessible_resources, { cwd: './app/', base: './app/', allowEmpty: true })
+ return src(manifest.web_accessible_resources[0].resources, { cwd: './app/', base: './app/', allowEmpty: true })
.pipe(debug())
.pipe($.if('*.css', $.cleanCss({compatibility: '*'})))
.pipe(dest('dist'));
@@ -127,7 +127,7 @@ function websiteManifest(cb){
const manifest = require('./app/manifest.json');
return src([
'!*.html',
- ...manifest.web_accessible_resources,
+ ...manifest.web_accessible_resources[0].resources,
...manifest.content_scripts[0].css,
...manifest.content_scripts[0].js
], { cwd: './app/', base: './app/', allowEmpty: true })
diff --git a/package-lock.json b/package-lock.json
index e1a532c..c4f9dba 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,7 @@
"gulp-useref": "^5.0.0",
"gulp-zip": "^5.1.0",
"signalhub": "^4.9.0",
+ "uuid": "^8.3.2",
"vinyl-source-stream": "^2.0.0",
"webrtc-swarm": "github:tom-james-watson/webrtc-swarm",
"wiredep": "^4.0.0",
@@ -11628,6 +11629,15 @@
"node": ">=0.6"
}
},
+ "node_modules/request/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -13105,6 +13115,16 @@
"node": ">=4"
}
},
+ "node_modules/tempfile/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "optional": true,
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
"node_modules/ternary-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz",
@@ -13779,12 +13799,11 @@
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"node_modules/uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
- "uuid": "bin/uuid"
+ "uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache": {
@@ -23324,6 +23343,11 @@
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
@@ -24485,6 +24509,14 @@
"requires": {
"temp-dir": "^1.0.0",
"uuid": "^3.0.1"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "optional": true
+ }
}
},
"ternary-stream": {
@@ -25036,9 +25068,9 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"v8-compile-cache": {
"version": "2.3.0",
diff --git a/package.json b/package.json
index 3c73997..bee0a71 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,7 @@
"gulp-useref": "^5.0.0",
"gulp-zip": "^5.1.0",
"signalhub": "^4.9.0",
+ "uuid": "^8.3.2",
"vinyl-source-stream": "^2.0.0",
"webrtc-swarm": "github:tom-james-watson/webrtc-swarm",
"wiredep": "^4.0.0",
diff --git a/permissions.txt b/permissions.txt
deleted file mode 100644
index f443f57..0000000
--- a/permissions.txt
+++ /dev/null
@@ -1 +0,0 @@
-This extension is designed to allow users to connect to each other while browsing online. It works by connecting users who are browsing on the same website at the same time. A chat room for each website a user is browsing. When browsing a website with other users, other users cursors and chat messages will be displayed on the associated tab.
\ No newline at end of file
diff --git a/promotion/IF Window.PNG b/promotion/IF Window.PNG
new file mode 100644
index 0000000..4ccac21
Binary files /dev/null and b/promotion/IF Window.PNG differ
diff --git a/promotion/hi 1280x800.png b/promotion/hi 1280x800.png
new file mode 100644
index 0000000..9f33cac
Binary files /dev/null and b/promotion/hi 1280x800.png differ
diff --git a/promotion/hi 440x280.png b/promotion/hi 440x280.png
new file mode 100644
index 0000000..36cbf4d
Binary files /dev/null and b/promotion/hi 440x280.png differ
diff --git a/promotion/hi 920x680.png b/promotion/hi 920x680.png
new file mode 100644
index 0000000..dd8356b
Binary files /dev/null and b/promotion/hi 920x680.png differ
diff --git a/promotion/hi grab.PNG b/promotion/hi grab.PNG
new file mode 100644
index 0000000..d3ced6d
Binary files /dev/null and b/promotion/hi grab.PNG differ
diff --git a/promotion/hi.psd b/promotion/hi.psd
new file mode 100644
index 0000000..8f2fbbb
Binary files /dev/null and b/promotion/hi.psd differ
diff --git a/requirements before submission.txt b/requirements before submission.txt
deleted file mode 100644
index 6c90f49..0000000
--- a/requirements before submission.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Step-by-step build instructions to create an exact copy of the add-on code.
-A build script that executes all necessary technical steps.
-Operating system and build environment requirements.
-Details (including required version and installation instructions), of any programs used in the build process (for example: node and npm version used).
\ No newline at end of file