英文:
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("could not send mesage to current tab");
} else {
console.log("Popup sending get html message");
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("Content sending save parsed message");
browser.runtime.sendMessage({ type: "save parsed" }, function(response) {
console.log(`Content received save parsed response: ${response}`);
})
}
sendResponse("ok");
});
background.js
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type = "save parsed") {
browser.runtime.sendNativeMessage("application.id", {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 = "message"
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
os_log("started processing request")
let item = context.inputItems[0] as! NSExtensionItem
let message = item.userInfo?[SFExtensionMessageKey]
os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)
let response = NSExtensionItem()
response.userInfo = [ SFExtensionMessageKey: [ "Response to": 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"
]
}
答案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) => {
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;**
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论