首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在一个全合一(Edge/Firefox/Chrome)浏览器扩展的内容脚本中实现消息传递回调?

如何在一个全合一(Edge/Firefox/Chrome)浏览器扩展的内容脚本中实现消息传递回调?
EN

Stack Overflow用户
提问于 2018-05-30 13:26:19
回答 1查看 514关注 0票数 2

开发环境操作系统: Windows 7企业级LTS

浏览器兼容性最低要求:从2018年起,应该支持所有边缘浏览器、火狐浏览器、Chrome浏览器。

当前正在进行的问题:无法在dev工作站上运行VM;无法运行Windows10VM来调试Microsoft扩展。

解释:

  • “一体式浏览器扩展”指的是使用相同代码的浏览器扩展代码,在各种支持WebExtensions / Chrome扩展的浏览器上使用相同的代码,差别很小。至少,相同的代码库应该可以在Edge、Firefox和Chrome上运行,只需做很小的改动。
  • 内容脚本 for Edge/Firefox/Chrome扩展的回调处理方式不同。
  • 由于未知的原因,我无法在工作站机器上运行VM。当VM运行时,VM客户端是黑色的。这是我无法解决的本地化问题,因此我不得不寻找另一个解决方案/替代方案。

如何以不同的方式处理内容脚本:

  • browser.runtime.sendMessage使用回调,并返回undefined
  • 火狐:browser.runtime.sendMessage使用承诺,并返回承诺。
  • Chrome:chrome.runtime.sendMessage使用回调,并返回undefined

根据各种参考资料:

*

https://www.smashingmagazine.com/2017/04/browser-extension-edge-chrome-firefox-opera-brave-vivaldi/

在内容脚本上,可以在顶部声明以下JavaScript片段,以便创建一个可以在其他地方引用的全局变量:

代码语言:javascript
复制
//Global "browser" namespace definition.
window.browser = (function() {
    return window.msBrowser || window.browser || window.chrome;
})();

不幸的是,由于我遇到的问题(VM没有运行),我无法判断是否仍在使用window.msBrowser。当我在使用时处理消息回调时,这个解决方案对我没有帮助。

尽管如此,我的主要问题是:如何编写能够正确处理回调的消息传递函数?

目前,我正在使用以下代码:

代码语言:javascript
复制
function sendGlobalMessage(messageRequest, callback) {
    if (chrome && window.openDatabase) {
        //This is Chrome browser
        chrome.runtime.sendMessage(messageRequest, callback);
    }
    else if (browser) {
        try {
            //Edge will error out because of a quirk in Edge IndexedDB implementation.
            //See https://gist.github.com/nolanlawson/a841ee23436410f37168
            let db = window.indexedDB.open("edge", (Math.pow(2, 30) + 1));
            db.onerror = function(e) {
                throw new Error("edge is found");
            };
            db.onsuccess = function(e) {
                //This is Firefox browser.
                browser.runtime.sendMessage(messageRequest).then(callback);
            };
        }
        catch (e) {
            //This is Edge browser
            browser.runtime.sendMessage(messageRequest, callback);
        }
    }
}

我真的觉得这是一个麻烦的解决方案,因为代码是基于浏览器平台的排他性怪癖,以便分离chrome.runtime.sendMessagebrowser.runtime.sendMessage API调用,以便在各自的平台中处理回调。我真的想要改变这一点。

因此,我想问的是,有什么更好的方法来检测不同的平台,而同时正确地处理消息传递回调()?

提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-30 14:29:01

我相信我解决了它。

编辑:最终版本(更新更稳定,消息传递更少):

代码语言:javascript
复制
//Global "browser" namespace definition, defined as "namespace". Can be renamed to anything else.
window.namespace = (function() {
    return window.browser || window.chrome;
})();

function sendGlobalResponse(message, callback){
    if (window.namespace === window.chrome) {
        //Chrome
        window.namespace.runtime.sendMessage(message, callback);
    }
    else if (window.namespace === window.browser) {
        //Using instanceof to check for object type, and use the returned evaluation as a truthy value.
        let supportPromises = false;
        try {
            supportPromises = window.namespace.runtime.getPlatformInfo() instanceof Promise;
        }
        catch(e) { }

        if (supportPromises){
            //Firefox
            window.namespace.runtime.sendMessage(message).then(callback);
        }
        else {
            //Edge
            window.namespace.runtime.sendMessage(message, callback);
        }
    }
}

(原文):

最终版本(现已过时):

代码语言:javascript
复制
//Global "browser" namespace definition.
window.namespace = (function() {
    return window.browser || window.chrome;
})();

function sendGlobalResponse(message, callback){
    if (window.namespace === window.chrome) {
        //Chrome
        window.namespace.runtime.sendMessage(message, callback);
    }
    else if (window.namespace === window.browser) {
        let returnValue = window.namespace.runtime.sendMessage({});
        if (typeof returnValue === "undefined"){
            //Edge
            window.namespace.runtime.sendMessage(message, callback);
        }
        else {
            //Firefox
            window.namespace.runtime.sendMessage(message).then(callback);
        }
    }
}

在第二个if语句中,通过检查window.browser.runtime.sendMessage的返回值是Promise还是undefined,我们可以检测平台是Firefox还是Edge

我认为这是处理内容脚本上的消息传递回调/消息响应的唯一解决方案。

我真的想不出比这更好的解决办法了。所以从现在开始我就用这个。

但是,如果其他人知道更好的方法,在每个函数调用中不需要为Firefox和Edge发送1条额外的虚拟消息,那就太好了!

糟糕的是,内容脚本中的任何内容都不是持久的,即使您存储了运行代码的平台的信息,在筛选出要调用哪个runtime.sendMessage函数之前,仍然必须从后台脚本中获取信息,所以这并不能真正节省很多时间。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50605931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档