在选项页面中使用 <form> & browser.storage.local.get() 在内容脚本中不起作用
Using a <form> in an options page & browser.storage.local.get() does not work in content script
我正在使用 Firefox Add-on,用户可以在其中的选项页面上设置一些值。当用户访问站点时,将执行内容脚本,然后需要读取先前在选项页面上设置的值。
我按照 MDN 指南“Implement a settings page”'Adding settings' 标题下的每个步骤进行操作,并使用给定的示例代码创建了所有文件。虽然设置、更改和读取选项页面上的值工作正常,但我无法在内容脚本文件(在指南中名为 borderify.js)中执行相同操作。在指南的具体代码示例中,无论在选项页面上设置了什么,它始终使用默认的蓝色边框。
我检查了内容脚本的 wiki 页面,但它只是说:'In addition to the standard DOM APIs, content scripts can use the following WebExtension APIs: [...] Everything from storage.'
所有这些都使用全新的 Firefox 配置文件和版本 50.0.2 进行了测试。
有人可以帮我解决这个问题吗?
manifest.json
{
"manifest_version": 2,
"name": "Settings example",
"version": "1.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["borderify.js"]
}
],
"applications": {
"gecko": {
"id": "settings-example@mozilla.org"
}
},
"options_ui": {
"page": "options.html"
},
"permissions": ["storage"]
}
options.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form>
<label>Border color<input type="text" id="color" ></label>
<button type="submit">Save</button>
</form>
<script src="options.js"></script>
</body>
</html>
options.js
function saveOptions(e) {
browser.storage.local.set({
color: document.querySelector("#color").value
});
}
function restoreOptions() {
function setCurrentChoice(result) {
document.querySelector("#color").value = result.color || "blue";
}
function onError(error) {
console.log(`Error: ${error}`);
}
var getting = browser.storage.local.get("color");
getting.then(setCurrentChoice, onError);
}
document.addEventListener("DOMContentLoaded", restoreOptions);
document.querySelector("form").addEventListener("submit", saveOptions);
borderify.js
function onError(error) {
console.log(`Error: ${error}`);
}
function onGot(item) {
var color = "blue";
if (item.color) {
color = item.color;
}
document.body.style.border = "10px solid " + color;
}
var getting = browser.storage.local.get("color");
getting.then(onGot, onError);
有两个问题阻止此代码工作:
- 52 之前的 Firefox 版本中的一个错误导致在内容脚本中实现来自
browser.storage.local.get()
的 Promise 时返回对象数组。这个 Promise 应该用一个对象来实现。
- 在选项页面中使用
<form>
的 submit
事件而不在事件处理程序中执行 preventDefault()
。
对于 Firefox 版本 <52
browser.storage.local.get()
中的 Firefox 错误
在您的内容脚本中,当来自 browser.storage.local.get()
的 Promise 实现时,您会收到一个包含一个对象的数组,而不是一个对象。数组中的对象正确地具有 color
属性。如果您在 options.js 中使用与 browser.storage.local.get()
相同的代码,您会正确地获得一个对象。在 Firefox Developer Edition (52.0a2) 和 Nightly (53.0a1) 中,对象被正确接收。
在所有情况下都returns正确使用chrome.storage.local.get()
API对象。我建议使用 API 而不是 browser.storage.local.get()
.
如果您决定继续使用 browser.storage.local.get()
,那么您将需要考虑当前在 Firefox < 52 中获取对象数组(在 item[0]
中使用正确的对象)并正确获取Firefox 中的一个对象 >= 52.
在选项页面中使用 <form>
的 submit
事件需要 preventDefault()
这是 MDN 页面“Implement a settings page”上的代码中的一个问题。我已更新该页面上的代码以反映下述问题。
问题是您在 options.html 和 [ 中使用 <form>
的 submit
事件=72=] 不阻止 e.preventDefault()
.
的默认操作
如果您不阻止默认操作,Firefox 会尝试将页面提交给原始 URL。在选项页面上,这显然失败了。但是,它以一种导致 Firefox 重新加载选项页面的方式失败。这会破坏您的选项页面之前存在的范围,导致对 storage.local.set()
的调用在实际设置值之前中止。 storage.local.set()
是异步的,因此它在被中止之前启动,但还不足以实际更改 StorageArea 中的值。
如果您将 e.preventDefault();
添加到 options.js 中的 saveOptions()
,您的扩展程序将正常工作,如下所示:
function saveOptions(e) {
e.preventDefault();
browser.storage.local.set({
color: document.querySelector("#color").value
});
}
我正在使用 Firefox Add-on,用户可以在其中的选项页面上设置一些值。当用户访问站点时,将执行内容脚本,然后需要读取先前在选项页面上设置的值。
我按照 MDN 指南“Implement a settings page”'Adding settings' 标题下的每个步骤进行操作,并使用给定的示例代码创建了所有文件。虽然设置、更改和读取选项页面上的值工作正常,但我无法在内容脚本文件(在指南中名为 borderify.js)中执行相同操作。在指南的具体代码示例中,无论在选项页面上设置了什么,它始终使用默认的蓝色边框。
我检查了内容脚本的 wiki 页面,但它只是说:'In addition to the standard DOM APIs, content scripts can use the following WebExtension APIs: [...] Everything from storage.'
所有这些都使用全新的 Firefox 配置文件和版本 50.0.2 进行了测试。
有人可以帮我解决这个问题吗?
manifest.json
{
"manifest_version": 2,
"name": "Settings example",
"version": "1.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["borderify.js"]
}
],
"applications": {
"gecko": {
"id": "settings-example@mozilla.org"
}
},
"options_ui": {
"page": "options.html"
},
"permissions": ["storage"]
}
options.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form>
<label>Border color<input type="text" id="color" ></label>
<button type="submit">Save</button>
</form>
<script src="options.js"></script>
</body>
</html>
options.js
function saveOptions(e) {
browser.storage.local.set({
color: document.querySelector("#color").value
});
}
function restoreOptions() {
function setCurrentChoice(result) {
document.querySelector("#color").value = result.color || "blue";
}
function onError(error) {
console.log(`Error: ${error}`);
}
var getting = browser.storage.local.get("color");
getting.then(setCurrentChoice, onError);
}
document.addEventListener("DOMContentLoaded", restoreOptions);
document.querySelector("form").addEventListener("submit", saveOptions);
borderify.js
function onError(error) {
console.log(`Error: ${error}`);
}
function onGot(item) {
var color = "blue";
if (item.color) {
color = item.color;
}
document.body.style.border = "10px solid " + color;
}
var getting = browser.storage.local.get("color");
getting.then(onGot, onError);
有两个问题阻止此代码工作:
- 52 之前的 Firefox 版本中的一个错误导致在内容脚本中实现来自
browser.storage.local.get()
的 Promise 时返回对象数组。这个 Promise 应该用一个对象来实现。 - 在选项页面中使用
<form>
的submit
事件而不在事件处理程序中执行preventDefault()
。
对于 Firefox 版本 <52
browser.storage.local.get()
中的 Firefox 错误
在您的内容脚本中,当来自 browser.storage.local.get()
的 Promise 实现时,您会收到一个包含一个对象的数组,而不是一个对象。数组中的对象正确地具有 color
属性。如果您在 options.js 中使用与 browser.storage.local.get()
相同的代码,您会正确地获得一个对象。在 Firefox Developer Edition (52.0a2) 和 Nightly (53.0a1) 中,对象被正确接收。
在所有情况下都returns正确使用chrome.storage.local.get()
API对象。我建议使用 API 而不是 browser.storage.local.get()
.
如果您决定继续使用 browser.storage.local.get()
,那么您将需要考虑当前在 Firefox < 52 中获取对象数组(在 item[0]
中使用正确的对象)并正确获取Firefox 中的一个对象 >= 52.
在选项页面中使用 <form>
的 submit
事件需要 preventDefault()
这是 MDN 页面“Implement a settings page”上的代码中的一个问题。我已更新该页面上的代码以反映下述问题。
问题是您在 options.html 和 [ 中使用 <form>
的 submit
事件=72=] 不阻止 e.preventDefault()
.
如果您不阻止默认操作,Firefox 会尝试将页面提交给原始 URL。在选项页面上,这显然失败了。但是,它以一种导致 Firefox 重新加载选项页面的方式失败。这会破坏您的选项页面之前存在的范围,导致对 storage.local.set()
的调用在实际设置值之前中止。 storage.local.set()
是异步的,因此它在被中止之前启动,但还不足以实际更改 StorageArea 中的值。
如果您将 e.preventDefault();
添加到 options.js 中的 saveOptions()
,您的扩展程序将正常工作,如下所示:
function saveOptions(e) {
e.preventDefault();
browser.storage.local.set({
color: document.querySelector("#color").value
});
}