【问题标题】:Implement cross extension message passing in chrome extension and app在chrome扩展和app中实现跨扩展消息传递
【发布时间】:2014-07-05 02:59:29
【问题描述】:

我正在尝试根据this article 在 chrome 扩展和 chrome 应用程序之间进行交叉扩展消息传递。但我不确定如何正确地做到这一点。我使用后台js来接收和发送消息。但不知道它是否有效。实际上我想从 chrome 扩展中保存文件,因为它无法完成,我认为这可以工作。因此,我们非常欢迎任何想法、建议或示例。

我已经经历了许多替代方案,也出现在this question 中。然后答案之一指向这个例子。我发现this example 工作正常。我希望我可以使用 Chrome App 的 fileSystem API 使用这种机制来保存文件。

【问题讨论】:

    标签: javascript google-chrome google-chrome-extension messaging google-chrome-app


    【解决方案1】:

    Chrome 消息传递 API 只能传输 JSON 可序列化值。如果文件很小,那么您可以在扩展程序中使用FileReader 读取文件内容,通过外部消息通道将消息发送到Chrome 应用程序,然后save the data using the FileWriter API

    当文件很大时,使用file.slice(start, end)分块读取文件,然后按照与小文件相同的方法。

    扩展名:

    var app_id = '.... ID of app (32 lowercase a-p characters) ....';
    var file = ...; // File or Blob object, e.g. from an <input type=file>
    
    var fr = new FileReader();
    fr.onload = function() {
        var message = {
            blob: fr.result,
            filename: file.name,
            filetype: file.type
        };
        chrome.runtime.sendMessage(app_id, message, function(result) {
            if (chrome.runtime.lastError) {
                // Handle error, e.g. app not installed
                console.warn('Error: ' + chrome.runtime.lastError.message);
            } else {
                // Handle success
                console.log('Reply from app: ', result);
            }
        });
    };
    fr.onerror = function() { /* handle error */ };
    // file or sliced file.
    fr.readAsText(file);
    

    应用:

    chrome.runtime.onMessageExternal.addListener(
      function(message, sender, sendResponse) {
        // TODO: Validate that sender.id is allowed to invoke the app!
    
        // Do something, e.g. convert back to Blob and do whatever you want.
        var blob = new Blob([message.blob], {type: message.filetype});
    
        console.log('TODO: Do something with ' + message.filename + ':', blob);
    
        // Do something, e.g. reply to message
        sendResponse('Processed file');
        // if you want to send a reply asynchronously, uncomment the next line.
        // return true;
    });
    

    编辑:尽管使用以下方法在理论上听起来不错,但它在实践中不起作用,因为为应用程序/扩展创建了一个单独的 SharedWorker 进程。

    如果你想发送大文件(例如Files),那么你可以实现以下:

    1. 扩展:创建proxy.html(内容=&lt;script src=proxy.js&gt;&lt;/script&gt;)。 (随意选择其他名称)。
    2. 分机:将proxy.html 放入web_accessible_resources
    3. App:绑定一个window.onmessage事件监听器。此事件侦听器将从您将在下一步加载的帧中接收消息。
    4. 应用程序:在应用程序的框架中加载chrome-extension://[EXTENSIONID]/proxy.html。此扩展 ID 可以是硬编码的(请参阅Obtaining Chrome Extension ID for development,也可以通过外部扩展消息传递 API 进行交换(确保验证源 - 对 ID 进行硬编码是最好的方法)。
    5. 扩展:proxy.html加载时,检查是否location.ancestorOrigins[0] == 'chrome-extension://[APPID]',避免安全漏洞。如果此条件失败,则终止所有步骤。
    6. 扩展:当您想将FileBlob 传递给应用程序时,请使用parent.postMessage(blob, 'chrome-extension://[APPID]');
    7. App:当它从扩展框架接收到blob时,将其保存到您通过chrome.fileSystem API获取的FileSystem中。

    最后要解决的任务是从扩展中获取文件到嵌入在应用程序中的扩展框架 (proxy.html)。这可以通过SharedWorker 来完成,请参见this answer 示例(您可以跳过创建新框架的部分,因为扩展框架已经在前面的步骤之一中创建)。
    请注意,目前 (Chrome 35),Files can only be sent with a work-around due to a bug

    【讨论】:

    • 感谢您提供重要信息,但我对第 4 步和第 5 步有点困惑。我必须在应用程序中包含 proxy.html 吗?如果是这样,我也可以在扩展中使用它的内容吗?我想通过单击按钮或任何其他方式从扩展名中保存文件。那么我可以使用代理 html 来构建我的扩展 ui 吗?
    • @RuwankaMadhushan proxy.html 仅用于将非 JSON 序列化对象(例如 File)从扩展程序发送到应用程序。 proxy.html 是扩展的一部分,并嵌入在应用程序的框架中。在扩展程序的 UI 中选择文件后,File 对象将传递给 SharedWorker,后者又将对象传递给 proxy.html,后者将对象传递给应用程序。这是相当复杂的,但它有效。将文件从应用程序发送到扩展程序的方式类似。
    • 由于我又是扩展开发的新手,我遇到了问题,如何将proxy.html 嵌入应用程序、嵌入标签或有其他方法?由于扩展程序无法选择文件,您在扩展程序 UI 中选择文件是什么意思?我应该从网页收集一些信息并将其保存为 xml,我还想读取该 xml 并在扩展 UI 中显示其内容。我可以用你的方法吗?
    • @RuwankaMadhushan 现在您提到要保存(XML)字符串,我强烈建议使用外部消息传递将消息作为字符串发送,正如我在答案顶部提到的那样.它比替代方法简单得多,并且可以满足您的目的。
    • 其实我不知道 xml 字符串的大小如何,这就是为什么我对你的方法感兴趣,虽然它很复杂。所以你能解释一下我感到困惑的一点吗?
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多