|
|
|
@ -15,6 +15,7 @@ import launchMetaMaskUi, { updateBackgroundConnection } from '../../ui'; |
|
|
|
|
import { |
|
|
|
|
ENVIRONMENT_TYPE_FULLSCREEN, |
|
|
|
|
ENVIRONMENT_TYPE_POPUP, |
|
|
|
|
EXTENSION_MESSAGES, |
|
|
|
|
PLATFORM_FIREFOX, |
|
|
|
|
} from '../../shared/constants/app'; |
|
|
|
|
import { isManifestV3 } from '../../shared/modules/mv3.utils'; |
|
|
|
@ -29,8 +30,8 @@ const container = document.getElementById('app-content'); |
|
|
|
|
|
|
|
|
|
const ONE_SECOND_IN_MILLISECONDS = 1_000; |
|
|
|
|
|
|
|
|
|
const WORKER_KEEP_ALIVE_INTERVAL = ONE_SECOND_IN_MILLISECONDS; |
|
|
|
|
// Service Worker Keep Alive Message Constants
|
|
|
|
|
const WORKER_KEEP_ALIVE_INTERVAL = ONE_SECOND_IN_MILLISECONDS; |
|
|
|
|
const WORKER_KEEP_ALIVE_MESSAGE = 'WORKER_KEEP_ALIVE_MESSAGE'; |
|
|
|
|
const ACK_KEEP_ALIVE_WAIT_TIME = 60_000; // 1 minute
|
|
|
|
|
const ACK_KEEP_ALIVE_MESSAGE = 'ACK_KEEP_ALIVE_MESSAGE'; |
|
|
|
@ -40,33 +41,35 @@ const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS; |
|
|
|
|
|
|
|
|
|
const PHISHING_WARNING_SW_STORAGE_KEY = 'phishing-warning-sw-registered'; |
|
|
|
|
|
|
|
|
|
let lastMessageRecievedTimestamp = Date.now(); |
|
|
|
|
let lastMessageReceivedTimestamp = Date.now(); |
|
|
|
|
|
|
|
|
|
let extensionPort; |
|
|
|
|
let ackTimeoutToDisplayError; |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* As long as UI is open it will keep sending messages to service worker |
|
|
|
|
* In service worker as this message is received |
|
|
|
|
* if service worker is inactive it is reactivated and script re-loaded |
|
|
|
|
* Time has been kept to 1000ms but can be reduced for even faster re-activation of service worker |
|
|
|
|
*/ |
|
|
|
|
let extensionPort; |
|
|
|
|
let timeoutHandle; |
|
|
|
|
|
|
|
|
|
if (isManifestV3) { |
|
|
|
|
// Checking for SW aliveness (or stuckness) flow
|
|
|
|
|
// 1. Check if we have an extensionPort, if yes
|
|
|
|
|
// 2a. Send a keep alive message to the background via extensionPort
|
|
|
|
|
// 2b. Add a listener to it (if not already added)
|
|
|
|
|
// 3a. Set a timeout to check if we have received an ACK from background
|
|
|
|
|
// 3b. If we have not received an ACK within Xs, we know the background is stuck or dead
|
|
|
|
|
// 3b. If we have not received an ACK within ACK_KEEP_ALIVE_WAIT_TIME,
|
|
|
|
|
// we know the background is stuck or dead
|
|
|
|
|
// 4. If we recieve an ACK_KEEP_ALIVE_MESSAGE from the service worker, we know it is alive
|
|
|
|
|
|
|
|
|
|
const ackKeepAliveListener = (message) => { |
|
|
|
|
if (message.name === ACK_KEEP_ALIVE_MESSAGE) { |
|
|
|
|
lastMessageRecievedTimestamp = Date.now(); |
|
|
|
|
clearTimeout(timeoutHandle); |
|
|
|
|
lastMessageReceivedTimestamp = Date.now(); |
|
|
|
|
clearTimeout(ackTimeoutToDisplayError); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handle = setInterval(() => { |
|
|
|
|
const keepAliveInterval = setInterval(() => { |
|
|
|
|
browser.runtime.sendMessage({ name: WORKER_KEEP_ALIVE_MESSAGE }); |
|
|
|
|
|
|
|
|
|
if (extensionPort !== null && extensionPort !== undefined) { |
|
|
|
@ -77,12 +80,12 @@ if (isManifestV3) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
timeoutHandle = setTimeout(() => { |
|
|
|
|
ackTimeoutToDisplayError = setTimeout(() => { |
|
|
|
|
if ( |
|
|
|
|
Date.now() - lastMessageRecievedTimestamp > |
|
|
|
|
Date.now() - lastMessageReceivedTimestamp > |
|
|
|
|
ACK_KEEP_ALIVE_WAIT_TIME |
|
|
|
|
) { |
|
|
|
|
clearInterval(handle); |
|
|
|
|
clearInterval(keepAliveInterval); |
|
|
|
|
displayCriticalError( |
|
|
|
|
'somethingIsWrong', |
|
|
|
|
new Error("Something's gone wrong. Try reloading the page."), |
|
|
|
@ -110,10 +113,7 @@ async function start() { |
|
|
|
|
const activeTab = await queryCurrentActiveTab(windowType); |
|
|
|
|
|
|
|
|
|
let loadPhishingWarningPage; |
|
|
|
|
/** |
|
|
|
|
* In case of MV3 the issue of blank screen was very frequent, it is caused by UI initialising before background is ready to send state. |
|
|
|
|
* Code below ensures that UI is rendered only after background is ready. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (isManifestV3) { |
|
|
|
|
/* |
|
|
|
|
* In case of MV3 the issue of blank screen was very frequent, it is caused by UI initialising before background is ready to send state. |
|
|
|
@ -121,7 +121,7 @@ async function start() { |
|
|
|
|
* In case the UI is already rendered, only update the streams. |
|
|
|
|
*/ |
|
|
|
|
const messageListener = async (message) => { |
|
|
|
|
if (message?.name === 'CONNECTION_READY') { |
|
|
|
|
if (message?.name === EXTENSION_MESSAGES.CONNECTION_READY) { |
|
|
|
|
if (isUIInitialised) { |
|
|
|
|
// Currently when service worker is revived we create new streams
|
|
|
|
|
// in later version we might try to improve it by reviving same streams.
|
|
|
|
@ -147,10 +147,8 @@ async function start() { |
|
|
|
|
* worker has been registered, so that the warning page works offline. |
|
|
|
|
*/ |
|
|
|
|
loadPhishingWarningPage = async function () { |
|
|
|
|
const currentPlatform = getPlatform(); |
|
|
|
|
|
|
|
|
|
// Check session storage for whether we've already initalized the phishing warning
|
|
|
|
|
// service worker this browser session and do not attempt to re-initialize if so.
|
|
|
|
|
// Check session storage for whether we've already initialized the phishing warning
|
|
|
|
|
// service worker in this browser session and do not attempt to re-initialize if so.
|
|
|
|
|
const phishingSWMemoryFetch = await browser.storage.session.get( |
|
|
|
|
PHISHING_WARNING_SW_STORAGE_KEY, |
|
|
|
|
); |
|
|
|
@ -159,7 +157,9 @@ async function start() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const currentPlatform = getPlatform(); |
|
|
|
|
let iframe; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
const extensionStartupPhishingPageUrl = new URL( |
|
|
|
|
process.env.PHISHING_WARNING_PAGE_URL, |
|
|
|
@ -195,7 +195,9 @@ async function start() { |
|
|
|
|
() => deferredReject(new PhishingWarningPageTimeoutError()), |
|
|
|
|
PHISHING_WARNING_PAGE_TIMEOUT, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
await loadComplete; |
|
|
|
|
|
|
|
|
|
// store a flag in sessions storage that we've already loaded the service worker
|
|
|
|
|
// and don't need to try again
|
|
|
|
|
if (currentPlatform === PLATFORM_FIREFOX) { |
|
|
|
@ -225,12 +227,13 @@ async function start() { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// resetExtensionStreamAndListeners takes care to remove listeners from closed streams
|
|
|
|
|
// it also creates new streams and attach event listeners to them
|
|
|
|
|
// it also creates new streams and attaches event listeners to them
|
|
|
|
|
const resetExtensionStreamAndListeners = () => { |
|
|
|
|
extensionPort.onMessage.removeListener(messageListener); |
|
|
|
|
extensionPort.onDisconnect.removeListener( |
|
|
|
|
resetExtensionStreamAndListeners, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// message below will try to activate service worker
|
|
|
|
|
// in MV3 is likely that reason of stream closing is service worker going in-active
|
|
|
|
|
browser.runtime.sendMessage({ name: WORKER_KEEP_ALIVE_MESSAGE }); |
|
|
|
|