From 649130af69241c6880abec2286bd658f9cd1ffbe Mon Sep 17 00:00:00 2001 From: Alan Date: Fri, 16 Feb 2018 01:58:26 +0300 Subject: [PATCH 1/3] Changed logic for handling multiple controllable tabs --- .gitignore | 2 + extension/background.html | 10 ++ extension/background.js | 278 ++++++++++++++++---------------------- extension/manifest.json | 2 +- extension/plugin-api.js | 7 +- 5 files changed, 133 insertions(+), 166 deletions(-) create mode 100644 extension/background.html diff --git a/.gitignore b/.gitignore index 60c0056..f217f53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.swp keysocket.zip +*.crx +*.pem diff --git a/extension/background.html b/extension/background.html new file mode 100644 index 0000000..33a4932 --- /dev/null +++ b/extension/background.html @@ -0,0 +1,10 @@ + + + + +keysocket + + + + + \ No newline at end of file diff --git a/extension/background.js b/extension/background.js index b8bc0b1..d9f234b 100644 --- a/extension/background.js +++ b/extension/background.js @@ -13,71 +13,136 @@ * limitations under the License. */ -var registeredTabs = []; -var registerTab = function (tabId) { - if (registeredTabs.indexOf(tabId) == -1) { - registeredTabs.push(tabId); +var tabsState = {}; +var controllableTabs = {} +var lastPlayingTab = -1; +var activeTab = -1; +var playingTabs = {}; + +function sendCommand(tabId, command) { + + if (command === 'play-pause') { + + if (playingTabs[tabId]) { + delete playingTabs[tabId] + } else { + playingTabs[tabId] = true; + } + + } + + chrome.tabs.sendMessage(tabId, {command: command}); +} + +function registerTab(tabId) { + if (!controllableTabs.hasOwnProperty(tabId)) { + controllableTabs[tabId] = true; + + chrome.tabs.get(tabId, function(tab) { + if (tab.audible) { + playingTabs[tabId] = true; + } + }); chrome.pageAction.show(tabId); - chrome.pageAction.setIcon({ - tabId: tabId, - path: { - '19': 'icons/icon19.png', - '38': 'icons/icon38.png' - } - }); - chrome.pageAction.setTitle({ - tabId: tabId, - title: 'Click to disable media keys for this tab' - }); - - updateContextMenu(tabId); + //TODO: save state in local storage + toggleState(tabId, true) } }; -var unregisterTab = function (tabId) { - var index = registeredTabs.indexOf(tabId); - if (index > -1) { - registeredTabs.splice(index, 1); - chrome.pageAction.setIcon({ - tabId: tabId, - path: { - '19': 'icons/icon19-inactive.png', - '38': 'icons/icon38-inactive.png' - } - }); - chrome.pageAction.setTitle({ - tabId: tabId, - title: 'Click to enable media keys for this tab' - }); +function unregisterTab(tabId) { + if (controllableTabs.hasOwnProperty(tabId)) { + delete controllableTabs[tabId]; + delete tabsState[tabId]; + + if (playingTabs.hasOwnProperty(tabId)) { + delete playingTabs[tabId]; + } - updateContextMenu(tabId); } }; -var updateContextMenu = function(tabId){ - chrome.tabs.query({active: true}, function(tab){ - tab = tab[0]; - if(tab.id == tabId) { - var index = registeredTabs.indexOf(tabId); - if (index > -1) { - chrome.contextMenus.update("keySocketMediaKeys-disableThisTab", {enabled: true}); - chrome.contextMenus.update("keySocketMediaKeys-enableThisTab", {enabled: false}); - } - else { - chrome.contextMenus.update("keySocketMediaKeys-disableThisTab", {enabled: false}); - chrome.contextMenus.update("keySocketMediaKeys-enableThisTab", {enabled: true}); - } - } - }); -}; - -chrome.commands.onCommand.addListener(function (command) { +function checkActive(tabId, changeInfo) { + if (!changeInfo.hasOwnProperty('audible')) { + return; + } + + if (!controllableTabs.hasOwnProperty(tabId)) { + console.log('ignore unregistered'); + return; + } + + var audible = changeInfo.audible; + + if (audible) { + playingTabs[tabId] = true; + lastPlayingTab = tabId; + console.log('update playingTabs', playingTabs); + } else { + + if (playingTabs[tabId] !== undefined) { + delete playingTabs[tabId]; + console.log('delete tab', playingTabs); + } + + lastPlayingTab = tabId; + } +} + +function toggleState(tabId, state) { + tabId = tabId.id || tabId + tabsState[tabId] = state !== undefined && state || !tabsState[tabId] + postfix = '' + + if (!tabsState[tabId]) { + postfix = '-inactive' + } + + chrome.pageAction.setIcon({ + tabId: tabId, + path: { + '19': 'icons/icon19' + postfix + '.png', + '38': 'icons/icon38' + postfix + '.png' + } + }); + +} + +function processAction(command) { console.log('Command:', command); - for (var i = 0; i < registeredTabs.length; i++) { - chrome.tabs.sendMessage(registeredTabs[i], {command: command}); - } + var isPlaying = false; + + for (tabId in playingTabs) { + + if (playingTabs.hasOwnProperty(tabId) && tabsState[tabId]) { + isPlaying = true; + sendCommand(+tabId, command); + console.log('control playing', tabId); + } + + } + + if (isPlaying) { + return; + } + + if (controllableTabs[activeTab] && tabsState[activeTab]){ + console.log('control active', activeTab); + sendCommand(activeTab, command) + } else if (lastPlayingTab !== -1 && tabsState[lastPlayingTab]) { + console.log('control lastPlayingTab', lastPlayingTab) + sendCommand(lastPlayingTab, command); + } +} + +chrome.commands.onCommand.addListener(processAction); +chrome.tabs.onRemoved.addListener(unregisterTab); +chrome.tabs.onUpdated.addListener(checkActive); +chrome.pageAction.onClicked.addListener(toggleState); + +chrome.tabs.onActivated.addListener(function (evt) { + activeTab = evt.tabId; }); chrome.runtime.onMessage.addListener( @@ -91,108 +156,3 @@ chrome.runtime.onMessage.addListener( } } ); - -chrome.tabs.onRemoved.addListener(unregisterTab); - -chrome.pageAction.onClicked.addListener(function (tab) { - var index = registeredTabs.indexOf(tab.id); - if (index < 0) { - registerTab(tab.id); - } else { - unregisterTab(tab.id); - } -}); - -chrome.tabs.onActivated.addListener(function (evt) { - updateContextMenu(evt.tabId); -}); - -chrome.contextMenus.create({id: "keySocketMediaKeys-group", title: "Key Socket Media Keys"}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-disableThisTab", - title: "Disable this tab", - onclick: function (a, tab) { - unregisterTab(tab.id); - } -}); -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-enableThisTab", - title: "Enable this tab", - onclick: function (a, tab) { - registerTab(tab.id); - } -}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-separator1", - type: "separator" -}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-disableAllTabs", - title: "Disable all tabs", - onclick: function (a, tab) { - chrome.tabs.getAllInWindow(null, function (tabs) { - for (var i = 0; i < tabs.length; i++) { - unregisterTab(tabs[i].id); - } - }); - } -}); -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-enableAllTabs", - title: "Enable all tabs", - onclick: function (a, tab) { - chrome.tabs.getAllInWindow(null, function (tabs) { - for (var i = 0; i < tabs.length; i++) { - registerTab(tabs[i].id); - } - }); - } -}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-separator2", - type: "separator" -}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-disableAllBut", - title: "Disable all but this tab", - onclick: function (a, tab) { - chrome.tabs.getAllInWindow(null, function (tabs) { - for (var i = 0; i < tabs.length; i++) { - if (tab.id !== tabs[i].id) { - unregisterTab(tabs[i].id); - } - } - }); - - registerTab(tab.id); - } -}); - -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-enableAllBut", - title: "Enable all but this tab", - onclick: function (a, tab) { - unregisterTab(tab.id); - - chrome.tabs.getAllInWindow(null, function (tabs) { - for (var i = 0; i < tabs.length; i++) { - if (tab.id !== tabs[i].id) { - registerTab(tabs[i].id); - } - } - }); - } -}); \ No newline at end of file diff --git a/extension/manifest.json b/extension/manifest.json index 22feba5..8bc6343 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -45,7 +45,7 @@ } }, "background": { - "scripts": ["background.js"], + "page": "background.html", "persistent": true }, "page_action": { diff --git a/extension/plugin-api.js b/extension/plugin-api.js index 14c308d..3db9089 100644 --- a/extension/plugin-api.js +++ b/extension/plugin-api.js @@ -122,14 +122,9 @@ keySocket.injectHandler = function (keysocketEventHandler) }); }; - injectFunction(handleKeysocketMessages); - + injectCode('(' + handleKeysocketMessages + ')()'); injectCode('window.keysocketOnKeyPressed = ' + keysocketEventHandler); - function injectFunction(injectionFunction) { - injectCode('(' + injectionFunction + ')()'); - } - function injectCode(injection) { var injectedScript = document.createElement('script'); injectedScript.textContent = injection; From 31b05b3149e94b110277f49b1d29be2a411b76a7 Mon Sep 17 00:00:00 2001 From: Alan Date: Sun, 4 Mar 2018 17:57:21 +0300 Subject: [PATCH 2/3] Replace tabs with spaces --- extension/background.js | 174 ++++++++++++++++++++-------------------- extension/manifest.json | 2 +- extension/plugin-api.js | 2 +- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/extension/background.js b/extension/background.js index d9f234b..7f3efc3 100644 --- a/extension/background.js +++ b/extension/background.js @@ -20,32 +20,32 @@ var activeTab = -1; var playingTabs = {}; function sendCommand(tabId, command) { - - if (command === 'play-pause') { - - if (playingTabs[tabId]) { - delete playingTabs[tabId] - } else { - playingTabs[tabId] = true; - } - - } - - chrome.tabs.sendMessage(tabId, {command: command}); + + if (command === 'play-pause') { + + if (playingTabs[tabId]) { + delete playingTabs[tabId] + } else { + playingTabs[tabId] = true; + } + + } + + chrome.tabs.sendMessage(tabId, {command: command}); } function registerTab(tabId) { if (!controllableTabs.hasOwnProperty(tabId)) { controllableTabs[tabId] = true; - - chrome.tabs.get(tabId, function(tab) { - if (tab.audible) { - playingTabs[tabId] = true; - } - }); + + chrome.tabs.get(tabId, function(tab) { + if (tab.audible) { + playingTabs[tabId] = true; + } + }); chrome.pageAction.show(tabId); - //TODO: save state in local storage + //TODO: save state in local storage toggleState(tabId, true) } }; @@ -53,87 +53,87 @@ function registerTab(tabId) { function unregisterTab(tabId) { if (controllableTabs.hasOwnProperty(tabId)) { delete controllableTabs[tabId]; - delete tabsState[tabId]; - - if (playingTabs.hasOwnProperty(tabId)) { - delete playingTabs[tabId]; - } + delete tabsState[tabId]; + + if (playingTabs.hasOwnProperty(tabId)) { + delete playingTabs[tabId]; + } } }; function checkActive(tabId, changeInfo) { - if (!changeInfo.hasOwnProperty('audible')) { - return; - } - - if (!controllableTabs.hasOwnProperty(tabId)) { - console.log('ignore unregistered'); - return; - } - - var audible = changeInfo.audible; - - if (audible) { - playingTabs[tabId] = true; - lastPlayingTab = tabId; - console.log('update playingTabs', playingTabs); - } else { - - if (playingTabs[tabId] !== undefined) { - delete playingTabs[tabId]; - console.log('delete tab', playingTabs); - } - - lastPlayingTab = tabId; - } + if (!changeInfo.hasOwnProperty('audible')) { + return; + } + + if (!controllableTabs.hasOwnProperty(tabId)) { + console.log('ignore unregistered'); + return; + } + + var audible = changeInfo.audible; + + if (audible) { + playingTabs[tabId] = true; + lastPlayingTab = tabId; + console.log('update playingTabs', playingTabs); + } else { + + if (playingTabs[tabId] !== undefined) { + delete playingTabs[tabId]; + console.log('delete tab', playingTabs); + } + + lastPlayingTab = tabId; + } } function toggleState(tabId, state) { - tabId = tabId.id || tabId - tabsState[tabId] = state !== undefined && state || !tabsState[tabId] - postfix = '' - - if (!tabsState[tabId]) { - postfix = '-inactive' - } - - chrome.pageAction.setIcon({ - tabId: tabId, - path: { - '19': 'icons/icon19' + postfix + '.png', - '38': 'icons/icon38' + postfix + '.png' - } - }); + tabId = tabId.id || tabId + tabsState[tabId] = state !== undefined && state || !tabsState[tabId] + postfix = '' + + if (!tabsState[tabId]) { + postfix = '-inactive' + } + + chrome.pageAction.setIcon({ + tabId: tabId, + path: { + '19': 'icons/icon19' + postfix + '.png', + '38': 'icons/icon38' + postfix + '.png' + } + }); } function processAction(command) { console.log('Command:', command); - var isPlaying = false; - - for (tabId in playingTabs) { - - if (playingTabs.hasOwnProperty(tabId) && tabsState[tabId]) { - isPlaying = true; - sendCommand(+tabId, command); - console.log('control playing', tabId); - } - - } - - if (isPlaying) { - return; - } - - if (controllableTabs[activeTab] && tabsState[activeTab]){ - console.log('control active', activeTab); - sendCommand(activeTab, command) - } else if (lastPlayingTab !== -1 && tabsState[lastPlayingTab]) { - console.log('control lastPlayingTab', lastPlayingTab) - sendCommand(lastPlayingTab, command); - } + var isPlaying = false; + + for (tabId in playingTabs) { + + if (playingTabs.hasOwnProperty(tabId) && tabsState[tabId]) { + isPlaying = true; + sendCommand(+tabId, command); + console.log('control playing', tabId); + } + + } + + if (isPlaying) { + return; + } + + if (controllableTabs[activeTab] && tabsState[activeTab]){ + console.log('control active', activeTab); + sendCommand(activeTab, command) + } else if (lastPlayingTab !== -1 && tabsState[lastPlayingTab]) { + console.log('control lastPlayingTab', lastPlayingTab) + sendCommand(lastPlayingTab, command); + } } chrome.commands.onCommand.addListener(processAction); @@ -142,7 +142,7 @@ chrome.tabs.onUpdated.addListener(checkActive); chrome.pageAction.onClicked.addListener(toggleState); chrome.tabs.onActivated.addListener(function (evt) { - activeTab = evt.tabId; + activeTab = evt.tabId; }); chrome.runtime.onMessage.addListener( diff --git a/extension/manifest.json b/extension/manifest.json index 8bc6343..f62ace3 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -45,7 +45,7 @@ } }, "background": { - "page": "background.html", + "page": "background.html", "persistent": true }, "page_action": { diff --git a/extension/plugin-api.js b/extension/plugin-api.js index 3db9089..3cb02a1 100644 --- a/extension/plugin-api.js +++ b/extension/plugin-api.js @@ -122,7 +122,7 @@ keySocket.injectHandler = function (keysocketEventHandler) }); }; - injectCode('(' + handleKeysocketMessages + ')()'); + injectCode('(' + handleKeysocketMessages + ')()'); injectCode('window.keysocketOnKeyPressed = ' + keysocketEventHandler); function injectCode(injection) { From 3bc8cf34d7eb019104219d4f02a0700e9988740a Mon Sep 17 00:00:00 2001 From: Alan Date: Sun, 4 Mar 2018 19:10:03 +0300 Subject: [PATCH 3/3] Readability improvements to the backgound script --- extension/background.js | 94 ++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/extension/background.js b/extension/background.js index 7f3efc3..832c287 100644 --- a/extension/background.js +++ b/extension/background.js @@ -12,23 +12,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + var tabsState = {}; -var controllableTabs = {} +var controllableTabs = {}; +var playingTabs = {}; var lastPlayingTab = -1; var activeTab = -1; -var playingTabs = {}; + +function togglePlaying(tabId, state) { + if(state === undefined) { + state = !playingTabs[tabId]; + } + + if (playingTabs.hasOwnProperty(tabId) && !state) { + delete playingTabs[tabId]; + } else if (!playingTabs.hasOwnProperty(tabId) && state) { + playingTabs[tabId] = true; + } +} function sendCommand(tabId, command) { if (command === 'play-pause') { - - if (playingTabs[tabId]) { - delete playingTabs[tabId] - } else { - playingTabs[tabId] = true; - } - + togglePlaying(tabId); } chrome.tabs.sendMessage(tabId, {command: command}); @@ -40,56 +46,45 @@ function registerTab(tabId) { chrome.tabs.get(tabId, function(tab) { if (tab.audible) { - playingTabs[tabId] = true; + togglePlaying(tabId, true); } }); chrome.pageAction.show(tabId); //TODO: save state in local storage - toggleState(tabId, true) + tabsPluginState(tabId, true); } -}; +} function unregisterTab(tabId) { if (controllableTabs.hasOwnProperty(tabId)) { delete controllableTabs[tabId]; - delete tabsState[tabId]; - - if (playingTabs.hasOwnProperty(tabId)) { - delete playingTabs[tabId]; - } - + delete tabsPluginState[tabId]; + togglePlaying(tabId, false); } -}; +} -function checkActive(tabId, changeInfo) { +function checkAudible(tabId, changeInfo) { if (!changeInfo.hasOwnProperty('audible')) { return; } if (!controllableTabs.hasOwnProperty(tabId)) { - console.log('ignore unregistered'); + console.log('ignore unregistered', tabId); return; } - var audible = changeInfo.audible; - - if (audible) { + if (changeInfo.audible) { playingTabs[tabId] = true; lastPlayingTab = tabId; console.log('update playingTabs', playingTabs); } else { - - if (playingTabs[tabId] !== undefined) { - delete playingTabs[tabId]; - console.log('delete tab', playingTabs); - } - + togglePlaying(tabId, false); lastPlayingTab = tabId; } } -function toggleState(tabId, state) { +function tabsPluginState(tabId, state) { tabId = tabId.id || tabId tabsState[tabId] = state !== undefined && state || !tabsState[tabId] postfix = '' @@ -110,7 +105,6 @@ function toggleState(tabId, state) { function processAction(command) { console.log('Command:', command); - var isPlaying = false; for (tabId in playingTabs) { @@ -136,23 +130,25 @@ function processAction(command) { } } -chrome.commands.onCommand.addListener(processAction); -chrome.tabs.onRemoved.addListener(unregisterTab); -chrome.tabs.onUpdated.addListener(checkActive); -chrome.pageAction.onClicked.addListener(toggleState); +function processRegisterMessage(request, sender, sendResponse) { + console.log('Received tab message: ', request); + + if (request.command == 'registerTab' && sender.tab) { + registerTab(sender.tab.id); + } else if (request.command == 'unregisterTab' && sender.tab) { + unregisterTab(sender.tab.id); + } +} -chrome.tabs.onActivated.addListener(function (evt) { +function switchActiveTab(evt) { activeTab = evt.tabId; -}); +} + +chrome.commands.onCommand.addListener(processAction); +chrome.tabs.onRemoved.addListener(unregisterTab); +chrome.tabs.onUpdated.addListener(checkAudible); +chrome.pageAction.onClicked.addListener(tabsPluginState); +chrome.runtime.onMessage.addListener(processRegisterMessage); +chrome.tabs.onActivated.addListener(switchActiveTab); -chrome.runtime.onMessage.addListener( - function (request, sender, sendResponse) { - console.log('Received tab message: ', request); - if (request.command == 'registerTab' && sender.tab) { - registerTab(sender.tab.id); - } else if (request.command == 'unregisterTab' && sender.tab) { - unregisterTab(sender.tab.id); - } - } -);