20
20
21
21
require ( "./record" ) ;
22
22
require ( "./actions" ) ;
23
+ const { sendRpcMessage, addRpcListener, removeRpcListener} = require ( "../rpc/client" ) ;
24
+ /**
25
+ * @typedef {import("../rpc/types").RpcHandler } RpcHandler
26
+ */
23
27
24
28
browser . runtime . onMessage . addListener ( ( request ) => {
25
29
if ( request . action == "highlight" ) {
@@ -28,6 +32,9 @@ browser.runtime.onMessage.addListener((request) => {
28
32
else if ( request . action == "unHighlight" ) {
29
33
return setHighlight ( request . selector , false ) ;
30
34
}
35
+ else if ( request . action == "startKeepAlive" ) {
36
+ keepAlive ( ) ;
37
+ }
31
38
} ) ;
32
39
33
40
function setHighlight ( query , highlight = true )
@@ -39,3 +46,65 @@ function setHighlight(query, highlight = true)
39
46
target . style [ "outline-width" ] = highlight ? "1px" : "" ;
40
47
}
41
48
}
49
+
50
+ /**
51
+ * @returns {Promise<import("../background/CBA").State | null> }
52
+ */
53
+ function getCbaState ( ) {
54
+ return new Promise ( ( resolve ) => {
55
+ const uuid = uuidv4 ( ) ;
56
+ const onTimeout = ( ) => {
57
+ removeRpcListener ( handler ) ;
58
+ resolve ( null ) ;
59
+ }
60
+ /** @type {RpcHandler } */
61
+ const handler = ( state ) => {
62
+ if ( state . msgType === "GetStateResponse" && state . id === uuid ) {
63
+ removeRpcListener ( handler ) ;
64
+ resolve ( state . state ) ;
65
+ }
66
+ clearTimeout ( onTimeout ) ;
67
+ } ;
68
+ setTimeout ( onTimeout , 1000 ) ;
69
+ addRpcListener ( handler ) ;
70
+ sendRpcMessage ( { msgType : "GetState" , id : uuid } ) ;
71
+ } ) ;
72
+ }
73
+
74
+ function uuidv4 ( ) {
75
+ return "10000000-1000-4000-8000-100000000000" . replace ( / [ 0 1 8 ] / g, c =>
76
+ ( c ^ crypto . getRandomValues ( new Uint8Array ( 1 ) ) [ 0 ] & 15 >> c / 4 ) . toString ( 16 )
77
+ ) ;
78
+ }
79
+
80
+ /**
81
+ * While a CBA project is being executed Service worker should be kept alive. It
82
+ * has been observed that service worker is being killed by the browser on
83
+ * `click-update` and `update` actions, breaking our user workflow which
84
+ * involves project with repeating run and relying on page update triggered by
85
+ * the user .
86
+ */
87
+ let keepAlivePort ;
88
+ let postTimer ;
89
+ async function keepAlive ( ) {
90
+ const state = await getCbaState ( ) ;
91
+ if ( state === null ) {
92
+ return ;
93
+ }
94
+ // If project is playing or paused, keep service worker alive.
95
+ if ( state && ( state . allowPlay || state . paused ) ) {
96
+ keepAlivePort = chrome . runtime . connect ( { name : 'keepAlive' } ) ;
97
+ postTimer = window . setTimeout ( keepAlive , 15000 ) ;
98
+ } else {
99
+ if ( keepAlivePort ) {
100
+ keepAlivePort . disconnect ( ) ;
101
+ keepAlivePort = null ;
102
+ }
103
+ if ( postTimer ) {
104
+ window . clearTimeout ( postTimer ) ;
105
+ postTimer = null ;
106
+ }
107
+ }
108
+ }
109
+
110
+ keepAlive ( ) ;
0 commit comments