Created
November 7, 2016 17:29
-
-
Save myano/29bcfecbaa6d516cdfcf15ba276d6c06 to your computer and use it in GitHub Desktop.
web-scrobbler\core\background\main.js from https://github.com/inverse/web-scrobbler/tree/multi-scrobble
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* Background script entry point | |
* | |
* - sets up injecting mechanism for supported sites | |
* - creates controllers for each recognized tab | |
* - sets up all chrome.* listeners, which are forwarded controllers if needed | |
* - checks auth status on run (browser start or extension enabling) and prompts for login if needed | |
*/ | |
require([ | |
'legacy/scrobbler', | |
'services/background-ga', | |
/* 'scrobblers/lastfm', */ | |
'scrobblers/librefm', | |
'notifications', | |
'inject', | |
'objects/injectResult', | |
'controller', | |
'storage', | |
'config', | |
'chromeStorage', | |
'services/scrobbleService' | |
], function(legacyScrobbler, GA, /* LastFM, */ LibreFM, Notifications, inject, injectResult, Controller, Storage, config, ChromeStorage, ScrobbleService) { | |
/** | |
* Single controller instance for each tab with injected script | |
* This allows us to work with tabs independently | |
*/ | |
var tabControllers = {}; | |
/** | |
* Flag for "page session" where at least single injection occurred | |
* Used for tracking number of actually active users | |
* @type {boolean} | |
*/ | |
var isActiveSession = false; | |
/** | |
* Callback for injecting script | |
* | |
* @param {InjectResult} result | |
*/ | |
var injectCb = function(result) { | |
var tabId = result.getTabId(); | |
// no match - do cleanup | |
if (result.getResult() === injectResult.results.NO_MATCH) { | |
// remove controller if any | |
if (tabControllers[tabId] !== undefined) { | |
delete tabControllers[tabId]; | |
} | |
// hide action icon - there may be any | |
try { | |
chrome.pageAction.hide(tabId); | |
} catch (e) { | |
// ignore, the tab may no longer exist | |
} | |
return; | |
} | |
// matched, but the connector is disabled | |
if (result.getResult() === injectResult.results.MATCHED_BUT_DISABLED) { | |
legacyScrobbler.setActionIcon(config.ACTION_SITE_DISABLED, tabId); | |
return; | |
} | |
// matched, create controller if needed | |
if (result.getResult() === injectResult.results.MATCHED_AND_INJECTED) { | |
// controllers are used for v2 connectors only | |
if (result.getConnector().version === 2) { | |
// intentionally overwrite previous controller, if any | |
tabControllers[tabId] = new Controller(tabId, result.getConnector()); | |
} | |
else { | |
// show 'recognized' action icon until the track info is recognized and validated | |
legacyScrobbler.setActionIcon(config.ACTION_SITE_RECOGNIZED, tabId); | |
} | |
GA.event('core', 'inject', result.getConnector().label); | |
if (!isActiveSession) { | |
isActiveSession = true; | |
GA.send('pageview', '/background-injected?version=' + chrome.app.getDetails().version); | |
} | |
} | |
}; | |
/** | |
* Returns controller for given tab. There should always be one | |
* | |
* @param {int} tabId | |
*/ | |
function getControllerByTabId(tabId) { | |
if (!tabControllers[tabId]) { | |
console.warn('Missing controller for tab ' + tabId + ' (should only happen for legacy connector)'); | |
} | |
return tabControllers[tabId]; | |
} | |
// --- done once on background script load ------------------------------------------------------------------------- | |
// cleanup and other stuff to be done on specific version changes | |
{ | |
var oldLfmStorage = Storage.getNamespace('LastFM'); | |
// update Core namespace to Chrome storage | |
ChromeStorage.get(function(allData) { | |
// init | |
if (allData === null || Object.keys(allData).length === 0) { | |
allData = { | |
Core: { | |
appVersion: chrome.app.getDetails().version | |
}, | |
LastFM: { // attempt to migrate from localStorage so user doesn't have to re-auth | |
token: oldLfmStorage.get('token') || null, | |
sessionID: oldLfmStorage.get('sessionID') || null | |
} | |
}; | |
} | |
// update | |
else { | |
allData.Core.appVersion = chrome.app.getDetails().version; | |
} | |
// save and proceed in starting up | |
ChromeStorage.set(allData, startup); | |
}); | |
} | |
// setup listener for messages from connectors | |
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { | |
var ctrl; | |
switch (request.type) { | |
// Interface for new V2 functionality. Routes control flow to new structures, so we can | |
// have two cores side by side. The old functionality will be later removed | |
case 'v2.stateChanged': | |
ctrl = getControllerByTabId(sender.tab.id); | |
if (ctrl) { | |
ctrl.onStateChanged(request.state); | |
} | |
break; | |
// Returns current song object - used in page action popup. | |
// Tab ID is stored inside request data | |
case 'v2.getSong': | |
ctrl = getControllerByTabId(request.tabId); | |
if (ctrl) { | |
sendResponse(ctrl.getCurrentSong()); // object or null | |
} else { | |
sendResponse(false); // no v2 controller, legacy mode | |
} | |
break; | |
// Returns current song object - used in page action popup. | |
// Tab ID is stored inside request data | |
case 'v2.correctSong': | |
ctrl = getControllerByTabId(request.tabId); | |
if (ctrl) { | |
ctrl.setUserSongData(request.data); | |
} | |
break; | |
case 'v2.toggleLove': | |
ctrl = getControllerByTabId(request.tabId); | |
if (ctrl) { | |
ctrl.toggleLove(request.data, sendResponse); | |
} | |
break; | |
// Redirect all other messages to legacy listener | |
default: | |
legacyScrobbler.runtimeOnMessage(request, sender, sendResponse); | |
} | |
return true; | |
}); | |
// setup listener for tab updates | |
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { | |
// wait for navigation to complete (this does not mean page onLoad) | |
if (changeInfo.status !== 'complete') { | |
return; | |
} | |
inject.onTabsUpdated(tabId, changeInfo, tab, injectCb); | |
}); | |
// setup listener for page action clicks | |
chrome.pageAction.onClicked.addListener(function(tab) { | |
// route events to controllers or assume legacy scrobbler if no controller is found | |
var ctrl = getControllerByTabId(tab.id); | |
if (ctrl) { | |
ctrl.onPageActionClicked(tab); | |
} else { | |
legacyScrobbler.onPageActionClicked(tab); | |
} | |
}); | |
/** | |
* Called on the extension start, after maintenance storage reads/writes are done | |
*/ | |
function startup() { | |
// track background page loaded - happens once per browser session | |
GA.send('pageview', '/background-loaded?version=' + chrome.app.getDetails().version); | |
// debug log internal storage state for people who send logs (tokens are anonymized) | |
ChromeStorage.debugLog(); | |
var scrobblerNotifications = ChromeStorage.getNamespace('ScrobblerNotifications'); | |
// check session ID status and show notification if authentication is needed | |
/* | |
LastFM.getSession(function(sessionID) { | |
if (sessionID !== 'undefined') { | |
Notifications.showAuthenticate(LastFM.getAuthUrl.bind(LastFM)); | |
} else { | |
console.info(LastFM.getLabel() + ' Session ID ' + 'xxxxx' + sessionID.substr(5)); | |
} | |
}.bind(LastFM)); | |
ScrobbleService.bindScrobbler(LastFM); | |
*/ | |
// check session ID status and show notification if authentication is needed | |
LibreFM.getSession(function(sessionID) { | |
if (sessionID !== 'undefined') { | |
scrobblerNotifications.get(function(data) { | |
if (typeof data.librefm === 'undefined') { | |
Notifications.showAuthenticate(LibreFM.getAuthUrl.bind(LibreFM)); | |
data.librefm = true; | |
scrobblerNotifications.set(data, null); | |
} | |
}); | |
} else { | |
console.info(LibreFM.getLabel() + ' Session ID ' + 'xxxxx' + sessionID.substr(5)); | |
} | |
}.bind(LibreFM)); | |
ScrobbleService.bindScrobbler(LibreFM); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment