@@ -19,12 +19,10 @@ var _CustomEventTarget = _interopRequireDefault(require("./CustomEventTarget.js"
1919var _Connection = require ( "./Connection.js" ) ;
2020var _Errors = require ( "./Errors.js" ) ;
2121function _interopRequireDefault ( obj ) { return obj && obj . __esModule ? obj : { default : obj } ; }
22+ const STORED_CONNECTIONS_KEY = "bgscript.connections" ;
23+
2224/**
2325 * Class that will handle all the content scripts that will connect to the background script.
24- *
25- * @property {Map<string, Connection> } scriptConnections A Map that will relate every script ID to its Connection object.
26- * @property {object } exposedData The properties and methods exposed to the connecting scripts.
27- * @property {function } errorCallback A callback that gets fired whenever there is an error in the script. It will get passed some details about the error.
2826 */
2927class BackgroundHandler extends _CustomEventTarget . default {
3028 /**
@@ -33,24 +31,53 @@ class BackgroundHandler extends _CustomEventTarget.default {
3331 * @param {object } exposedData An object containing all properties and methods to be exposed to the content scripts
3432 * @param {object } options An object that will customize how this class works.
3533 */
36- constructor ( exposedData = { } , options = {
37- runtime : chrome . runtime
38- } ) {
39- var _options$errorCallbac , _options$runtime ;
34+ constructor ( exposedData = { } , options = { } ) {
35+ var _options$errorCallbac , _options$runtime , _options$storage , _options$chromeTabs ;
4036 super ( ) ;
37+
38+ /** @type {Map<string, Connection> } scriptConnections A Map that will relate every script ID to its Connection object. */
4139 this . scriptConnections = new Map ( ) ; // script-id --> connection
40+ /** @property {object } exposedData The properties and methods exposed to the connecting scripts. */
4241 this . exposedData = exposedData ;
42+ /** @property {function } errorCallback A callback that gets fired whenever there is an error in the script. It will get passed some details about the error. */
4343 this . errorCallback = ( _options$errorCallbac = options . errorCallback ) !== null && _options$errorCallbac !== void 0 ? _options$errorCallbac : null ;
44+
45+ /** @property {chrome.runtime } runtime The runtime that will be used to create the connections. */
4446 this . runtime = ( _options$runtime = options . runtime ) !== null && _options$runtime !== void 0 ? _options$runtime : chrome . runtime ;
47+ this . storage = ( _options$storage = options . storage ) !== null && _options$storage !== void 0 ? _options$storage : chrome . storage ;
48+ this . chromeTabs = ( _options$chromeTabs = options . chromeTabs ) !== null && _options$chromeTabs !== void 0 ? _options$chromeTabs : chrome . tabs ;
4549 this . runtime . onConnect . addListener ( port => this . handleNewConnection ( port ) ) ;
50+ this . restoreConnections ( ) ;
51+ }
52+ async restoreConnections ( ) {
53+ let data = await this . storage . local . get ( STORED_CONNECTIONS_KEY ) ;
54+ if ( data [ STORED_CONNECTIONS_KEY ] ) {
55+ let connections = data [ STORED_CONNECTIONS_KEY ] ;
56+ for ( let [ scriptId , tab ] of connections ) {
57+ this . chromeTabs . sendMessage ( tab , {
58+ type : _Connection . CONNECTION_PREFIX + "ping" ,
59+ scriptId
60+ } ) ;
61+ }
62+ }
63+ }
64+ async saveConnections ( ) {
65+ let conns = [ ] ;
66+ for ( let [ scriptId , _ ] of this . scriptConnections ) {
67+ let [ name , tabId ] = scriptId . split ( "-" ) ;
68+ conns . push ( [ name , parseInt ( tabId ) ] ) ;
69+ }
70+ await this . storage . local . set ( {
71+ [ STORED_CONNECTIONS_KEY ] : conns
72+ } ) ;
4673 }
4774
4875 /**
4976 * Handle a new incoming connection
5077 *
5178 * @param {chrome.runtime.Port } port The newly created connection to a content script
5279 */
53- handleNewConnection ( port ) {
80+ async handleNewConnection ( port ) {
5481 var _port$sender$tab$id , _port$sender ;
5582 if ( ! this . isInternalConnection ( port ) ) return ;
5683 let [ name , scriptId ] = this . parsePortName ( port ) ;
@@ -73,6 +100,7 @@ class BackgroundHandler extends _CustomEventTarget.default {
73100 // see BackgroundScript.js:68
74101 connection . addListener ( "disconnect" , ( ) => this . disconnectScript ( name , tabId ) ) ;
75102 this . scriptConnections . set ( scriptId , connection ) ;
103+ await this . saveConnections ( ) ;
76104
77105 // Fire the connection event
78106 this . fireEvent ( "connectionreceived" , {
@@ -176,6 +204,25 @@ class BackgroundHandler extends _CustomEventTarget.default {
176204 return proxy ;
177205 }
178206
207+ /**
208+ * Get all tab ids where a specific scriptId is present.
209+ *
210+ * @param {string } scriptId
211+ * @returns {number[] } The tab IDs
212+ */
213+ getScriptTabs ( scriptId ) {
214+ let tabs = [ ] ;
215+ for ( let [ id , connection ] of this . scriptConnections ) {
216+ if ( id . startsWith ( scriptId ) ) {
217+ var _connection$port$send ;
218+ if ( ( _connection$port$send = connection . port . sender ) !== null && _connection$port$send !== void 0 && ( _connection$port$send = _connection$port$send . tab ) !== null && _connection$port$send !== void 0 && _connection$port$send . id ) {
219+ tabs . push ( connection . port . sender . tab . id ) ;
220+ }
221+ }
222+ }
223+ return tabs ;
224+ }
225+
179226 /**
180227 * Check if a script with a specific id associated to a specific tab has made a connection to the background page.
181228 *
@@ -251,6 +298,7 @@ class BackgroundScript extends _CustomEventTarget.default {
251298 this . context = ( _options$context = options . context ) !== null && _options$context !== void 0 ? _options$context : "content" ;
252299 this . runtime = ( _options$runtime = options . runtime ) !== null && _options$runtime !== void 0 ? _options$runtime : chrome . runtime ;
253300 this . connectBackgroundScript ( ) ;
301+ this . checkForReconnection ( ) ;
254302 }
255303
256304 /**
@@ -311,6 +359,20 @@ class BackgroundScript extends _CustomEventTarget.default {
311359 return proxy ;
312360 }
313361
362+ /**
363+ * Check if the background script is pinging us
364+ */
365+ checkForReconnection ( ) {
366+ this . runtime . onMessage . addListener ( async ( req , sender , sendResponse ) => {
367+ if ( this . connection != null ) return ;
368+ if ( req . type == _Connection . CONNECTION_PREFIX + "ping" ) {
369+ if ( req . scriptId == this . scriptId ) {
370+ this . connectBackgroundScript ( ) ;
371+ }
372+ }
373+ } ) ;
374+ }
375+
314376 /**
315377 * Function that returns a uuid version 4 formatted string.
316378 *
@@ -474,7 +536,7 @@ class Connection extends _CustomEventTarget.default {
474536 }
475537
476538 /**
477- * Decides how to answer based on the incomin message type.
539+ * Decides how to answer based on the incoming message type.
478540 *
479541 * @param {Object } message The incoming message
480542 */
0 commit comments