@@ -19,12 +19,10 @@ var _CustomEventTarget = _interopRequireDefault(require("./CustomEventTarget.js"
19
19
var _Connection = require ( "./Connection.js" ) ;
20
20
var _Errors = require ( "./Errors.js" ) ;
21
21
function _interopRequireDefault ( obj ) { return obj && obj . __esModule ? obj : { default : obj } ; }
22
+ const STORED_CONNECTIONS_KEY = "bgscript.connections" ;
23
+
22
24
/**
23
25
* 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.
28
26
*/
29
27
class BackgroundHandler extends _CustomEventTarget . default {
30
28
/**
@@ -33,24 +31,53 @@ class BackgroundHandler extends _CustomEventTarget.default {
33
31
* @param {object } exposedData An object containing all properties and methods to be exposed to the content scripts
34
32
* @param {object } options An object that will customize how this class works.
35
33
*/
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 ;
40
36
super ( ) ;
37
+
38
+ /** @type {Map<string, Connection> } scriptConnections A Map that will relate every script ID to its Connection object. */
41
39
this . scriptConnections = new Map ( ) ; // script-id --> connection
40
+ /** @property {object } exposedData The properties and methods exposed to the connecting scripts. */
42
41
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. */
43
43
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. */
44
46
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 ;
45
49
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
+ } ) ;
46
73
}
47
74
48
75
/**
49
76
* Handle a new incoming connection
50
77
*
51
78
* @param {chrome.runtime.Port } port The newly created connection to a content script
52
79
*/
53
- handleNewConnection ( port ) {
80
+ async handleNewConnection ( port ) {
54
81
var _port$sender$tab$id , _port$sender ;
55
82
if ( ! this . isInternalConnection ( port ) ) return ;
56
83
let [ name , scriptId ] = this . parsePortName ( port ) ;
@@ -73,6 +100,7 @@ class BackgroundHandler extends _CustomEventTarget.default {
73
100
// see BackgroundScript.js:68
74
101
connection . addListener ( "disconnect" , ( ) => this . disconnectScript ( name , tabId ) ) ;
75
102
this . scriptConnections . set ( scriptId , connection ) ;
103
+ await this . saveConnections ( ) ;
76
104
77
105
// Fire the connection event
78
106
this . fireEvent ( "connectionreceived" , {
@@ -176,6 +204,25 @@ class BackgroundHandler extends _CustomEventTarget.default {
176
204
return proxy ;
177
205
}
178
206
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
+
179
226
/**
180
227
* Check if a script with a specific id associated to a specific tab has made a connection to the background page.
181
228
*
@@ -251,6 +298,7 @@ class BackgroundScript extends _CustomEventTarget.default {
251
298
this . context = ( _options$context = options . context ) !== null && _options$context !== void 0 ? _options$context : "content" ;
252
299
this . runtime = ( _options$runtime = options . runtime ) !== null && _options$runtime !== void 0 ? _options$runtime : chrome . runtime ;
253
300
this . connectBackgroundScript ( ) ;
301
+ this . checkForReconnection ( ) ;
254
302
}
255
303
256
304
/**
@@ -311,6 +359,20 @@ class BackgroundScript extends _CustomEventTarget.default {
311
359
return proxy ;
312
360
}
313
361
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
+
314
376
/**
315
377
* Function that returns a uuid version 4 formatted string.
316
378
*
@@ -474,7 +536,7 @@ class Connection extends _CustomEventTarget.default {
474
536
}
475
537
476
538
/**
477
- * Decides how to answer based on the incomin message type.
539
+ * Decides how to answer based on the incoming message type.
478
540
*
479
541
* @param {Object } message The incoming message
480
542
*/
0 commit comments