WebExtension:重新加载选项卡时发生反应

时间:2016-07-16 04:27:44

标签: firefox events tabs reload firefox-webextensions

我正在开发一个Firefox WebExtension,它有一个弹出窗口并使用chrome.storage.local来存储状态。到目前为止,我已经使用选项卡ID存储特定选项卡的数据。

如果重新加载当前选项卡,我想重新初始化本地存储。这是因为扩展可能对DOM进行了一些更改,如果重新加载选项卡将会丢失;因此它存储的状态是不正确的。

从弹出窗口调用初始JavaScript代码。

如何在重新加载页面时运行一些代码?

由于

1 个答案:

答案 0 :(得分:1)

如果没有关于您想要做什么的更多信息,很难确定最佳方法。特别是,很难确切地知道您希望回应的情况。

看起来你可以使用tabs.onUpdated事件的监听器。虽然这比你实际想要的更频繁,但它会重新加载页面。

下面是在URL加载或重新加载页面时调用函数completedLoadingURLInTab()的代码。我留下了一堆console.log()次电话作为评论,我通常会将其删除。它们可以取消注释,以便在事件触发时始终显示在控制台中。这可以用于确切地确定从事件接收的数据的内容以及在各种页面导航期间触发的事件序列。

注1:我发现在某些情况下changeInfo对象可能无效。有必要查看是否存在使用hasOwnProperty()的属性,然后从tabs.Tab对象获取也传递给事件处理程序的值。
注2: manifest.json 中的tabs权限是必需的。

function completedLoadingURLInTab(tabId, newUrl,oldUrl) {
    //We have completed, loading a URL.
    if(newUrl === oldUrl) {
        //We re-loaded the previous URL
        console.log(">>>>>>> Re-load tab=" + tabId + " with URL=" + newUrl);
    } else {
        //This URL _may_ be just a new position in the same page.  That
        //  is something that needs to be checked for here.
        console.log(">>>>>>> New URL loaded in tab=" + tabId + ". URL=" + newUrl);
    }

    //Remember the newUrl so we can check against it the next time
    //  an event is fired.
    tabsInfo[tabId].previousCompleteUrl = newUrl;
    tabsInfo[tabId].loadingUrl = newUrl;
}

let tabsInfo = {};
function InfoForTab(_loadingUrl,_previousUrl,_status) {
    this.loadingUrl = _loadingUrl;
    this.previousCompleteUrl = (_previousUrl === undefined) ? "" : _previousUrl;
    this.status = (_status === undefined) ? "" : _status;
}

function foundNewTab(tabId) {
    //Create an object to hold the collected info for the tab.
    tabsInfo[tabId] = new InfoForTab();
    console.log("New tab. ID=" + tabId);
}

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if(!tabsInfo.hasOwnProperty(tabId)) {
        //This is the first time we have encountered this tab.
        foundNewTab(tabId);
    }
    let output="";
    //We use the properties of "tab" instead of "changeInfo" because in testing it was
    //  clear that changeInfo was not always properly populated. The key(s) may just
    //  exist, but not have any value associated with them.

    /*
    //Testing output showing when the event is fired.
    //  This is used to determine, by experimentation, what events to ignore and which
    //  combinations and sequence of events occur during page navigation.
    output += (changeInfo.hasOwnProperty("status")) ? "\nstatus=" + tab.status : "";
    output += (changeInfo.hasOwnProperty("url")) ? "\nurl=" + tab.url : "";
    output += (changeInfo.hasOwnProperty("pinned")) ? "\npinned=" + tab.pinned : "";
    output += (changeInfo.hasOwnProperty("audible")) ? "\naudible=" + tab.audible : "";
    output += (changeInfo.hasOwnProperty("mutedInfo")) ? "\nmutedInfo="+tab.mutedInfo : "";
    output +=(changeInfo.hasOwnProperty("favIconUrl"))?"\nfavIconUrl="+tab.favIconUrl : "";
    console.log("tabs.updated event: tabId=" + tabId + ":: changeInfo="
                + Object.keys(changeInfo) + output
    );
    */
    if(changeInfo.hasOwnProperty("status") && changeInfo.hasOwnProperty("url")
        && (tab.status === "loading")) {
        //A URL is being loaded into the tab. This can be for the first time,
        //  or transitioning to a new URL, or reloading the page.
        let outputFirst = "";
        let outputLoading = "Loading";
        if(tabsInfo[tabId].previousCompleteUrl === tab.url) {
            //We are re-loading the same URL
            outputLoading = "Re-loading";
        }
        //console.log(outputLoading  + " URL=" + tab.url);
        //We save the URL which is being loaded, but we really don't do anything with it.
        tabsInfo[tabId].loadingUrl = tab.url;
        tabsInfo[tabId].status = "loading";
        return;
    } //else
    if(changeInfo.hasOwnProperty("status") && (tab.status === "complete")) {
        if( tabsInfo[tabId].status === "loading") {
            tabsInfo[tabId].status = "complete";
            //console.log("In tabId="+tabId+" completed loading URL="+tab.url);
            completedLoadingURLInTab(tabId, tab.url, tabsInfo[tabId].previousCompleteUrl);
            return;
        } //else
        if( tabsInfo[tabId].status === "complete") {
            if(tabsInfo[tabId].previousCompleteUrl === tab.url) {
                //console.log("In tabId=" + tabId + " got completed status change after"
                //              + "already complete with URL="
                //              + tabsInfo[tabId].previousCompleteUrl);
                return;
            }//else
            //console.log("In tabId=" + tabId + " completed directly loading new URL="
            //            + tab.url);
            completedLoadingURLInTab(tabId, tab.url, tabsInfo[tabId].previousCompleteUrl);
            return;
        }
    }//else
    if(changeInfo.hasOwnProperty("status") && (tab.status === "loading")
        && ( tabsInfo[tabId].status === "complete")) {
        //console.log("In tabId=" + tabId + " leaving page");
        return;
    }//else
    if(changeInfo.hasOwnProperty("status") ) {
        if((tab.status === "complete") && (tab.url === "about:newtab")
            && tabsInfo[tabId].loadingUrl === undefined ) {
            //We have completed loading about:newtab for the first time in this tab.
            tabsInfo[tabId].status = "complete";
            completedLoadingURLInTab(tabId, tab.url, tabsInfo[tabId].previousCompleteUrl);
            return;
        } //else
        //console.log("In tabId=" + tabId + " got status change to " + tab.status
        //              + " prior to loading a URL with current URL=" + tab.url);
        return;
    }//else
});

在加载附加组件,打开新选项卡并进行一些导航(包括重新加载几页)之后,控制台中的输出可能如下所示:

New tab. ID=6
>>>>>>> New URL loaded in tab=6. URL=about:newtab
>>>>>>> New URL loaded in tab=6. URL=https://www.google.com/?gws_rd=ssl
>>>>>>> Re-load tab=6 with URL=https://www.google.com/?gws_rd=ssl
>>>>>>> New URL loaded in tab=6. URL=https://www.google.com/?gws_rd=ssl#q=test
>>>>>>> Re-load tab=6 with URL=https://www.google.com/?gws_rd=ssl#q=test
>>>>>>> New URL loaded in tab=6. URL=https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onUpdated
>>>>>>> New URL loaded in tab=6. URL=https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onUpdated#changeInfo
>>>>>>> Re-load tab=6 with URL=https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onUpdated#changeInfo

或者,使用webNavigation事件

webNavigation事件为您提供有关网络导航的直接信息。他们可能会为您提供比tabs.onUpdated更好的解决方案。

如果您使用webNavigation个事件,则需要尝试查看哪些事件组合会针对您所关注的情况触发。最有可能是Completed和/或ReferenceFragmentUpdated

因此,您可以了解这些事件触发时的情况,以下代码将在控制台中记录所有webNavigation个事件:

var webNavEvents = ['BeforeNavigate',
                    'Committed',
                    'Completed',
                    //'CreatedNavigationTarget', //Not supported by Firefox
                    'DOMContentLoaded',
                    'ErrorOccurred',
                    'HistoryStateUpdated',
                    'ReferenceFragmentUpdated'
                    //'TabReplaced' //Not supported by Firefox
                    ];


webNavEvents.forEach(function(navType){
    browser.webNavigation['on' + navType].addListener(function(type,details){
        console.log('\twebNavigation->' + type 
                    + ': tadId=' + details.tabId
                    + ':: url=' + details.url
                    + ((typeof details.transitionType === 'string') ? ':: transitionType='
                        + details.transitionType : '')
        );
    }.bind(undefined,navType));
});