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..832c287 100644 --- a/extension/background.js +++ b/extension/background.js @@ -12,187 +12,143 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -var registeredTabs = []; -var registerTab = function (tabId) { - if (registeredTabs.indexOf(tabId) == -1) { - registeredTabs.push(tabId); - - 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); + +var tabsState = {}; +var controllableTabs = {}; +var playingTabs = {}; +var lastPlayingTab = -1; +var activeTab = -1; + +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; } -}; -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' +function sendCommand(tabId, command) { + + if (command === 'play-pause') { + togglePlaying(tabId); + } + + 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) { + togglePlaying(tabId, true); } }); - chrome.pageAction.setTitle({ - tabId: tabId, - title: 'Click to enable media keys for this tab' - }); - updateContextMenu(tabId); + chrome.pageAction.show(tabId); + //TODO: save state in local storage + tabsPluginState(tabId, true); } -}; +} -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) { - console.log('Command:', command); - - for (var i = 0; i < registeredTabs.length; i++) { - chrome.tabs.sendMessage(registeredTabs[i], {command: command}); +function unregisterTab(tabId) { + if (controllableTabs.hasOwnProperty(tabId)) { + delete controllableTabs[tabId]; + delete tabsPluginState[tabId]; + togglePlaying(tabId, false); } -}); - -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); - } +function checkAudible(tabId, changeInfo) { + if (!changeInfo.hasOwnProperty('audible')) { + return; } -); - -chrome.tabs.onRemoved.addListener(unregisterTab); - -chrome.pageAction.onClicked.addListener(function (tab) { - var index = registeredTabs.indexOf(tab.id); - if (index < 0) { - registerTab(tab.id); + + if (!controllableTabs.hasOwnProperty(tabId)) { + console.log('ignore unregistered', tabId); + return; + } + + if (changeInfo.audible) { + playingTabs[tabId] = true; + lastPlayingTab = tabId; + console.log('update playingTabs', playingTabs); } else { - unregisterTab(tab.id); + togglePlaying(tabId, false); + lastPlayingTab = tabId; } -}); - -chrome.tabs.onActivated.addListener(function (evt) { - updateContextMenu(evt.tabId); -}); +} + +function tabsPluginState(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' + } + }); -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); +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; } -}); -chrome.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-enableThisTab", - title: "Enable this tab", - onclick: function (a, tab) { - registerTab(tab.id); + + 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.contextMenus.create({ - parentId: "keySocketMediaKeys-group", - id: "keySocketMediaKeys-separator1", - type: "separator" -}); +function processRegisterMessage(request, sender, sendResponse) { + console.log('Received tab message: ', request); -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); - } - }); + if (request.command == 'registerTab' && sender.tab) { + registerTab(sender.tab.id); + } else if (request.command == 'unregisterTab' && sender.tab) { + unregisterTab(sender.tab.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); - } - } - }); +function switchActiveTab(evt) { + activeTab = evt.tabId; +} - registerTab(tab.id); - } -}); +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.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..f62ace3 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..3cb02a1 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;