Can a Chrome extension's event page detect when the browser has finished starting up?

蹲街弑〆低调 提交于 2021-02-16 09:37:07

问题


I have a Chrome extension that tracks the order in which tabs are accessed by listening for tab-related events like tabs.onActivated, onRemoved, etc. It uses an event page instead of a persistent background page to add the event listeners. The tab access order is stored in chrome.storage.local.

The extension works fine while in the normal course of using the browser. But when Chrome is first launched and restores the previous session, it reopens the windows in the order they were originally opened, firing onActivated events for the reopened tabs.

If the extension listened to these events, they would cause the stored tab access order to change, which I'm trying to avoid. I don't want to start listening to the tab events until Chrome has finished restoring the session and has settled down. But I'm not sure how to detect that change in state using an event page that normally has to re-add the event listeners every time it's loaded.

I've tried something like the following to delay adding the tab event listeners until shortly after the last window has been created during startup (it listens for windows.onCreated because Chrome will start up in the background when you restart Windows, but no windows are created at that point):

var gStartingUp = false;

chrome.runtime.onStartup.addListener(() => {
    var timer = null;

    gStartingUp = true;

    chrome.windows.onCreated.addListener(window => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            gStartingUp = false;
            addListeners();
        }, 750);
    });
);

if (!gStartingUp) {
    addListeners();
}

In normal usage, gStartingUp would default to false and the listeners would get added. But when the browser fires the onStartup event, the handler isn't called fast enough to prevent the addListeners() call from happening, so the listeners are added during startup as well. I suppose I could add a timeout before calling addListeners(), but that would delay adding them during normal usage.

Is there a way for an extension's event page to reliably detect that Chrome has finished its startup processing?


回答1:


My initial solution below is too unreliable. I actually saw a case where Chrome restarted, the event page loaded, the timeout to add the listeners fired after 100ms, but the onStartup event didn't fire for another two whole seconds.

So I gave up on trying to delay adding the event handlers until after the onStartup event was handled. Instead, each handler now checks a startingUp flag that's set in the onStartup handler, and only processes the event if it's not in the startup phase. That check is unnecessary for most of the lifetime of the extension, but it at least avoids adding an artificial delay before handling events.

I also switched to listening for tabs.onActivated events during startup, as Chrome seems to reopen the windows first during startup, and then reopens the tabs. So waiting for a pause in tab activations should be a better signal that Chrome has finished starting up.

var startingUp = false;

chrome.runtime.onStartup.addListener(() => {
    var timer = null;

    startingUp = true;

    function onActivated()
    {
        clearTimeout(timer);
        timer = setTimeout(() => {
            startingUp = false;
            chrome.tabs.onActivated.removeListener(onActivated);
        }, 500);
    }

    chrome.tabs.onActivated.addListener(onActivated);
);

chrome.tabs.onActivated.addListener(tabID => {
    if (!startingUp) {
        // handle event
    }
});

Initial solution

The answer to that question would appear to be "no". The best I've been able to do is indeed delay calling addListeners() long enough for the onStartup listener to fire when Chrome is starting up:

var startingUp = false,
    addedListeners = false;

chrome.runtime.onStartup.addListener(() => {
    var timer = null;

    startingUp = true;

    chrome.windows.onCreated.addListener(window => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            startingUp = false;
            addListeners();
        }, 500);
    });
);

setTimeout(function() {
    if (!startingUp && !addedListeners) {
        addListeners();
    }
}, 100);

This seems to mostly work, and the 100ms delay in adding event handlers every time the page is reloaded doesn't seem to be noticeable in actual usage (I've tried 0, 10 and 50ms delays, but they'd sometimes fire before the onStartup handler).

But it all feels very kludgy and brittle if the timing is off. Any improved solutions are welcome.



来源:https://stackoverflow.com/questions/47522818/can-a-chrome-extensions-event-page-detect-when-the-browser-has-finished-startin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!