Skip to content

Commit 804ec98

Browse files
committed
issue #153 - keep service worker alive during the execution
1 parent c38ecf7 commit 804ec98

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

src/js/background/actions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ async function playProject() {
2626
}
2727
else if(cba.instructArray.length) {
2828
setBadgeText("play");
29+
const playingTabId = await cba.getPlayingTabId();
30+
if (playingTabId) {
31+
void browser.tabs.sendMessage(playingTabId, {action: "startKeepAlive"});
32+
}
2933
const [instruction] = cba.instructArray.splice(0, 1);
3034
cba.playingActionIndex = (cba.defInstructArray.length - cba.instructArray.length) - 1;
3135

src/js/cs/main.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020

2121
require("./record");
2222
require("./actions");
23+
const {sendRpcMessage, addRpcListener, removeRpcListener} = require("../rpc/client");
24+
/**
25+
* @typedef {import("../rpc/types").RpcHandler} RpcHandler
26+
*/
2327

2428
browser.runtime.onMessage.addListener((request) => {
2529
if(request.action == "highlight") {
@@ -28,6 +32,9 @@ browser.runtime.onMessage.addListener((request) => {
2832
else if(request.action == "unHighlight") {
2933
return setHighlight(request.selector, false);
3034
}
35+
else if (request.action == "startKeepAlive") {
36+
keepAlive();
37+
}
3138
});
3239

3340
function setHighlight(query, highlight = true)
@@ -39,3 +46,65 @@ function setHighlight(query, highlight = true)
3946
target.style["outline-width"] = highlight ? "1px" : "";
4047
}
4148
}
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(/[018]/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();

src/js/rpc/host.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
const listeners = [];
3232

3333
browser.runtime.onConnect.addListener((port) => {
34+
if (port.name === "keepAlive") {
35+
return;
36+
}
3437
if (port.name !== "rpcPort") throw new Error("Unknown port.");
3538
port.onMessage.addListener(async(/** @type {RpcMessages} */ msg) => {
3639
for (const listener of listeners) {

0 commit comments

Comments
 (0)