原生消息传递在Safari Web扩展中。

huangapple go评论82阅读模式
英文:

Native messaging in safari web extension

问题

我正在尝试将当前页面的信息发送到我的原生应用程序。

我在 manifest.json 中将 nativeMessaging 列为权限。当用户在 popup.html 中点击按钮时,popup.js 发送消息到 content,然后 content 发送消息到后台服务,后者应将消息发送到扩展程序。我可以看到直到原生消息那一点都正常工作,但在那一点上什么都没有发生。

popup.js

//处理响应/错误

function notifyContentPage(e) {
  browser.tabs.query({active: true, currentWindow: true}, function(tabs) {
    if (tabs.length == 0) {
      console.log("无法发送消息到当前选项卡");
    } else {
      console.log("弹出窗口发送获取HTML消息");
      const sendingToContent = browser.tabs.sendMessage(tabs[0].id, {type: "get html"});
      sendingToContent.then(handleResponse, handleError);
    }
  });
}

document.getElementById("parse").addEventListener("click", notifyContentPage);

content.js

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (!sender.tab && request.type == "get html") {
    console.log("内容发送保存解析消息");
    browser.runtime.sendMessage({ type: "save parsed" }, function(response) {
        console.log(`内容接收到保存解析的响应: ${response}`);
    })
  }
  sendResponse("ok");
});

background.js

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type = "save parsed") {
    browser.runtime.sendNativeMessage("应用程序ID", {message: request}, function(response) {
      sendResponse(`接收到原生消息响应 ${response[0]}`);
    });
  } else {
    sendResponse(`接收到未知请求 ${request.type}`);
    return true;
  }
});

SafariWebExtensionHandler

import SafariServices
import os.log

let SFExtensionMessageKey = "message"

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
    func beginRequest(with context: NSExtensionContext) {
      os_log("开始处理请求")
        let item = context.inputItems[0] as! NSExtensionItem
        let message = item.userInfo?[SFExtensionMessageKey]
        os_log(.default, "从 browser.runtime.sendNativeMessage 接收到消息: %@", message as! CVarArg)

        let response = NSExtensionItem()
        response.userInfo = [ SFExtensionMessageKey: [ "回复给": message ] ]

        context.completeRequest(returningItems: [response], completionHandler: nil)
    }
}

manifest.json

{
    "manifest_version": 3,
    "default_locale": "en",
    "name": "__MSG_extension_name__",
    "description": "__MSG_extension_description__",
    "version": "1.0",
    "icons": {
        "48": "images/icon-48.png",
        "96": "images/icon-96.png",
        "128": "images/icon-128.png",
        "256": "images/icon-256.png",
        "512": "images/icon-512.png"
    },
    "background": {
      "service_worker": "background.js"
    },
    "content_scripts": [{
        "js": [ "content.js" ],
        "matches": [ "<all_urls>" ]
    }],
    "action": {
        "default_popup": "popup.html",
        "default_icon": {
            "16": "images/toolbar-icon-16.png",
            "19": "images/toolbar-icon-19.png",
            "32": "images/toolbar-icon-32.png",
            "38": "images/toolbar-icon-38.png",
            "48": "images/toolbar-icon-48.png",
            "72": "images/toolbar-icon-72.png"
        }
    },
    "permissions": [
        "<all_urls>",
        "nativeMessaging",
        "activeTab"
    ]
}
英文:

I am trying to send information about the current page to my native app.

I have nativeMessaging listed as a permission in the manifest.json. When the user clicks a button in the popup.html, popup.js sends a message to content, which sends a message to the background service, which should send a message to the extension. I can see that everything up to the native message is working, but nothing happens at that point.

popup.js

//handle response/error

function notifyContentPage(e) {  
  browser.tabs.query({active: true, currentWindow: true}, function(tabs) {
    if (tabs.length == 0) {
      console.log(&quot;could not send mesage to current tab&quot;);
    } else {
      console.log(&quot;Popup sending get html message&quot;);
      const sendingToContent = browser.tabs.sendMessage(tabs[0].id, {type: &quot;get html&quot;});
      sendingToContent.then(handleResponse, handleError);
    }
  });
}

document.getElementById(&quot;parse&quot;).addEventListener(&quot;click&quot;, notifyContentPage);

content.js

browser.runtime.onMessage.addListener((request, sender, sendResponse) =&gt; {
  if (!sender.tab &amp;&amp; request.type == &quot;get html&quot;) {
    
    console.log(&quot;Content sending save parsed message&quot;);
    browser.runtime.sendMessage({ type: &quot;save parsed&quot; }, function(response) {
        console.log(`Content received save parsed response: ${response}`);
    })
  }
  sendResponse(&quot;ok&quot;);
});

background.js


browser.runtime.onMessage.addListener((request, sender, sendResponse) =&gt; {
  
  if (request.type = &quot;save parsed&quot;) {
    browser.runtime.sendNativeMessage(&quot;application.id&quot;, {message: request}, function(response) {
      sendResponse(`Received native message response ${response[0]}`);
    });
  } else {
    sendResponse(`Received unknown request ${request.type}`);
    return true;
  }
});

SafariWebExtensionHandler

import SafariServices
import os.log

let SFExtensionMessageKey = &quot;message&quot;

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {

    func beginRequest(with context: NSExtensionContext) {
      os_log(&quot;started processing request&quot;)
        let item = context.inputItems[0] as! NSExtensionItem
        let message = item.userInfo?[SFExtensionMessageKey]
        os_log(.default, &quot;Received message from browser.runtime.sendNativeMessage: %@&quot;, message as! CVarArg)

        let response = NSExtensionItem()
        response.userInfo = [ SFExtensionMessageKey: [ &quot;Response to&quot;: message ] ]

        context.completeRequest(returningItems: [response], completionHandler: nil)
    }

}

manifest.json

{
    &quot;manifest_version&quot;: 3,
    &quot;default_locale&quot;: &quot;en&quot;,

    &quot;name&quot;: &quot;__MSG_extension_name__&quot;,
    &quot;description&quot;: &quot;__MSG_extension_description__&quot;,
    &quot;version&quot;: &quot;1.0&quot;,

    &quot;icons&quot;: {
        &quot;48&quot;: &quot;images/icon-48.png&quot;,
        &quot;96&quot;: &quot;images/icon-96.png&quot;,
        &quot;128&quot;: &quot;images/icon-128.png&quot;,
        &quot;256&quot;: &quot;images/icon-256.png&quot;,
        &quot;512&quot;: &quot;images/icon-512.png&quot;
    },

    &quot;background&quot;: {
      &quot;service_worker&quot;: &quot;background.js&quot;
    },

    &quot;content_scripts&quot;: [{
        &quot;js&quot;: [ &quot;content.js&quot; ],
        &quot;matches&quot;: [ &quot;&lt;all_urls&gt;&quot; ]
    }],

    &quot;action&quot;: {
        &quot;default_popup&quot;: &quot;popup.html&quot;,
        &quot;default_icon&quot;: {
            &quot;16&quot;: &quot;images/toolbar-icon-16.png&quot;,
            &quot;19&quot;: &quot;images/toolbar-icon-19.png&quot;,
            &quot;32&quot;: &quot;images/toolbar-icon-32.png&quot;,
            &quot;38&quot;: &quot;images/toolbar-icon-38.png&quot;,
            &quot;48&quot;: &quot;images/toolbar-icon-48.png&quot;,
            &quot;72&quot;: &quot;images/toolbar-icon-72.png&quot;
        }
    },

    &quot;permissions&quot;: [
        &quot;&lt;all_urls&gt;&quot;,
        &quot;nativeMessaging&quot;,
        &quot;activeTab&quot;
    ]
}

答案1

得分: 1

根据Ben Dodson的这篇文章,我认为我找到了答案。

在调用sendNativeMessage时,看起来我有一个拼写错误,他的文章提到:

在这里需要注意的一件重要事项是,当您回应来自内容的消息时,必须返回true,否则连接会立即关闭(即它不会等待本机应用程序回应)。

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  
  if (request.type = "save parsed") {
    browser.runtime.sendNativeMessage("application.id", request, function(response) {
      sendResponse(`Received native message response ${response[0]}`);
    });
    return true;
  } else {
    sendResponse(`Received unknown request ${request.type}`);
    return true;
  }
});
英文:

I think I found the answer based on this article by Ben Dodson.

It looks I had a typo in the call the sendNativeMessage, and his article mentions

> One important item to note here is that you must return true when you are responding to a message from the content otherwise the connection is closed instantly (i.e. it will not wait for the native app to respond).

browser.runtime.onMessage.addListener((request, sender, sendResponse) =&gt; {
  
  if (request.type = &quot;save parsed&quot;) {
    browser.runtime.sendNativeMessage(&quot;application.id&quot;, **request**, function(response) {
      sendResponse(`Received native message response ${response[0]}`);
    });
    **return true;**
  } else {
    sendResponse(`Received unknown request ${request.type}`);
    **return true;**
  }
});

huangapple
  • 本文由 发表于 2023年6月12日 07:08:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452849.html
  • safari-extension
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定