javascript - Firefox 扩展,上下文识别
问题描述
我已经构建了一个 AddIn,一个国际象棋游戏可视化器,它在桌面浏览器 Firefox、Chrome、Opera、Safari 和 IE 上工作了很多年。插件在从上下文菜单调用时运行,并解析当前页面中的选定文本。所选文本应为Chess Notation Format,可以是 FEN 或 PGN。
这是第二次在 FF 版本更改时插件与 Firefox 不兼容,我必须进行架构更改。新的 firefox 架构是为了与 Chrome 兼容,但它只是部分兼容,所以我不能完全重用 chrome 的代码。我还使用
了将弹出窗口中的数据通信到由弹出窗口注入的内容脚本中的信息,执行脚本()
和使用 executeScript() 将数据从弹出窗口传递到由弹出窗口注入的内容脚本
以下是我的问题:
- 看background.js的代码,在pop.js调用browser.runtime.onMessage.addListener之前调用了browser.runtime.sendMessage。在完全创建由 browser.windows.create 打开的窗口、所有脚本结束执行并完全加载文档后,我不明白如何从 background.js 发送消息。我也不能在调用时这样做
document.addEventListener('DOMContentLoaded'
,当我调用 browser.runtime.onMessage.addListener 时,它会生成错误Error: sendRemoveListener on closed conduit b212f9bfb4f0394efe56168a583c91346caf2d00@temporary-addon.412316861125
并且可能根本没有执行。也许有我可以处理的特殊事件,我没有看到太多的文档。在 Chrome 中,方法大多相似,但效果很好。 - 在一些不可用的情况下,我仍然可以捕获从 background.js 发送的消息:如果我打开了两个窗口,但对于调试目的还是很好的。
document.innerHTML
问题是,无论我尝试做什么,在 pop.js 的处理程序内部都是未定义的。我无法处理来自扩展 api 处理程序的窗口内容。我认为该文档已完全加载,因为它由两个打开的窗口中的第一个处理。
注意,我可以通过调用 URL 参数将选择文本发送到新打开的弹出窗口。它有效,但我认为这是一种解决方法。我在 Opera 和 Safari 上使用它,它也适用于 Firefox,但我正在考虑尽可能摆脱它。
有一个场景,简化:
background.js:
{//Firefox create context menus
var id = chrome.contextMenus.create({"title": "Chess game", "contexts":["selection", "page"]});
var childId = chrome.contextMenus.create
({
"title": "Play Small","contexts":["selection", "page"],
"parentId": id,
"onclick": (info, tab) => { playBoard (info, tab, "mini18"); }
});
}
function onCreated(windowInfo, request)
{
browser.windows.get(windowInfo.id).then
(
(wnd) => { browser.runtime.sendMessage(request); }
);
}
function playBoard (info, tab, imagePath)
{
let creating = browser.windows.create({ type:"detached_panel", url:"pop.html", width:250, height:100 });
creating.then
(
(inf) =>
{onCreated
(
inf,
{
chessObject:
{
gametype : "PGN_OR_FEN_board",
content : selection,
imgPath : info.selectionText
}
}
)
}
);
}
pop.js:
browser.runtime.onMessage.addListener
(
(request) =>
{
console.log("popup chrome listen to game: " + request.chessObject.content);
console.log("popup chrome listen to game: document inner html: " + document.innerHTML);
}
);
弹出.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>hello world</title>
<script language="javascript" src="pop.js"></script>
</head>
<body>
hello popup
</body>
</html>
清单.json:
{
"manifest_version": 2,
"name": "Roatta Waaayyyy!!!",
"version": "1.0.0.4",
"description": "Chess AddIn for Firefox",
"icons": { "32": "icons/roatta_32_32.jpg" },
"permissions": [ "contextMenus" ],
"background": { "scripts": ["background.js"] }
}
这里的参考是 GIT 上的完整源代码,我现在尝试实现的是 Firefox65,它旨在取代以前的 Firefox。基本版本是用于 Chrome 的版本,最初是用于 Firefox 的版本。
解决方案
正如@wOxxOm 所建议的,我应用了反向消息模式,并且它有效。
现在 background.js 注册一个监听器并等待被调用,然后它会移除监听器:
{//Firefox
console.log("Creating context menus");
var id = chrome.contextMenus.create({"title": "Chess game", "contexts":["selection", "page"]});
var childId = chrome.contextMenus.create
({
"title": "Play Small","contexts":["selection", "page"],
"parentId": id,
"onclick": (info, tab) => { playBoard (info, tab, "mini18"); }
});
}
function playBoard (info, tab, imagePath)
{
var createData =
{
type : "detached_panel",
url : "pop.html",
width : 250,
height: 100
};
let requestData =
{
chessObject:
{
gametype : "PGN_OR_FEN_board",
content : info.selectionText,
imgPath : imagePath
}
};
try
{
console.log ("Play Board: " + imagePath);
console.log ("Selection: " + info.selectionText);
let creating = browser.windows.create(createData);
function onGameDataExchange(request)
{
browser.runtime.onMessage.removeListener(onGameDataExchange);
return Promise.resolve(requestData);
}
browser.runtime.onMessage.addListener (onGameDataExchange);
console.log ("opened pop.html");
}
catch (err)
{
console.log ("Error: main background playBoard() " + err);
}
}
pop.js 是请求消息的那个:
document.addEventListener('DOMContentLoaded',
function (event)
{
browser.runtime.sendMessage ( { chessObject: { gametype : "PGN_OR_FEN_board" } } )
.then
(
(request) =>
{
console.log("on DOMContentLoaded message: " + request.chessObject.gametype);
console.log("on DOMContentLoaded message: " + request.chessObject.content);
console.log("on DOMContentLoaded message: " + request.chessObject.imgPath);
}
);
console.log("Popup DOMContentLoaded send message end");
}
);
推荐阅读
- ios - iOS:外部显示 AVPlayerController 关闭问题
- dart - 将 JSON 转换为列表
- java - 我收到状态 401 错误:当我尝试通过 keycloak 调用我的 Secured API 时未授权
- angular - Angular 5 JSPDF缺少图像
- javascript - 使用带有过滤器(布尔)的 RxJS 进行查询?
- amazon-cognito - 通过 CLI 配置 AWS Cognito 用户池高级安全功能账户接管风险配置
- python - 如何使用多个布尔条件选择 Pandas DataFrame 中的特定列
- php - 如何在具有不同站点地址和 Wordpress 地址的 Wordpress 上使用预览
- docker - del 构建依赖后大小不能改变
- python - tar zxvf 命令需要永远解压 Python-3.5.5.tgz