У меня есть расширение для Chrome, которое блокирует несколько веб-сайтов. Я пытаюсь сделать тумблер, чтобы он перестал блокировать сайты, когда переключатель выключен. В настоящее время у меня есть html и css, реализованные во всплывающем меню, но нет кода, который фактически отключает скрипт и удаляет блоки. Как я могу реализовать некоторый код, который отключит скрипт?
Я использую версию 111.0.5563.146 Google Chrome, версия манифеста 3.
Вот код, который у меня сейчас есть:
manifest.json
{
"manifest_version": 3,
"name": "On-Off Switch",
"version": "1.0.0",
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"declarative_net_request": {
"rule_resources": [
{
"id": "ruleset_1",
"enabled": false,
"path": "ruleset_1.json"
}
]
},
"permissions": [
"declarativeNetRequest",
"storage"
]
}
всплывающее окно.html
<!DOCTYPE html>
<html>
<head>
<title>popup</title>
</head>
<body>
<p>popup</p>
<button id = "on">On</button>
<button id = "off">Off</button>
<script src = "popup.js"></script>
</body>
</html>
всплывающее окно.js
document.getElementById("on").onclick = () => {
chrome.storage.local.set({active: true});
}
document.getElementById("off").onclick = () => {
chrome.storage.local.set({active: false});
}
набор правил_1.json
[
{
"id": 1,
"action": { "type": "block" },
"condition": { "urlFilter": "stackoverflow.com", "resourceTypes": ["main_frame"] }
},
{
"id": 2,
"action": { "type": "block" },
"condition": { "urlFilter": "google.com/search*", "resourceTypes": ["main_frame"] }
}
]
фон.js
async function runtime_on_installed(details) {
if (details.reason == "install") {
// Store the extension's current state
// which is determined by the "declarative_net_request" key in manifest.json
let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
if (ruleset_ids.length == 0) {
// Extension is currently inactive
await chrome.storage.local.set({active: false});
}
else if (ruleset_ids.length == 1) {
// Extension is currently active
await chrome.storage.local.set({active: true});
}
}
else if (details.reason == "update") {
// Restore the extension's stored state
// https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#method-updateEnabledRulesets
// "Note that the set of enabled static rulesets is persisted across sessions but not across extension updates, i.e. the rule_resources manifest key will determine the set of enabled static rulesets on each extension update."
let { active } = chrome.storage.local.get("active");
let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
if (active && ruleset_ids.length == 0) {
// Extension is supposed to be active, but is inactive
chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
}
else if (!active && ruleset_ids.length == 1) {
// Extension is supposed to be inactive, but is active
chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
}
}
}
function storage_on_changed(changes, area_name) {
if (area_name == "local") {
if (changes.active.oldValue == false && changes.active.newValue == true) {
chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
}
else if (changes.active.oldValue == true && changes.active.newValue == false) {
chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
}
}
}
chrome.runtime.onInstalled.addListener(runtime_on_installed);
chrome.storage.onChanged.addListener(storage_on_changed);
На данный момент ни один блок не работает. Незадолго до этого блок stackoverflow.com
работал, а блок google.com/search*
— нет. Может быть, это связано с тем, как я определяю правила?
@ThomasMueller Я думал о варианте C, у меня уже есть тумблер HTML/CSS, однако он не включает и не выключает скрипт и в настоящее время бесполезен. Состояние переключателя также всегда отключается после закрытия всплывающего окна.
Я использую Chromium 111.0.5563.146 (официальная сборка) Arch Linux (64-разрядная версия) — тот же номер версии, что и у вас. Код в вашем вопросе работает для меня. Расширение блокирует как stackoverflow.com/questions , так и google.com/search?q=test, когда оно активно. Но по умолчанию он неактивен ("enabled": false,
), и его нужно активировать с помощью кнопки «Вкл.» во всплывающем окне. Кроме этого, я не могу придумать ни одной причины, по которой это не сработает.
Напоминаю: на линии let { active } = chrome.storage.local.get("active");
нужен await
оператор: let { active } = await chrome.storage.local.get("active");
Вот пример.
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"declarativeNetRequest"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
}
}
всплывающее окно.html
<html>
<body>
<button id = "add">Add</button>
<button id = "remove">Remove</button>
<script src = "popup.js"></script>
</body>
</html>
всплывающее окно.js
document.getElementById("add").onclick = () => {
chrome.runtime.sendMessage({ method: "add" });
}
document.getElementById("remove").onclick = () => {
chrome.runtime.sendMessage({ method: "remove" });
}
фон.js
const rule =
{
"id": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "stackoverflow.com",
"resourceTypes": ["main_frame"]
}
};
chrome.runtime.onMessage.addListener((message) => {
switch (message.method) {
case "add":
chrome.declarativeNetRequest.updateDynamicRules({ addRules: [rule] });
break;
case "remove":
chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [1] });
break;
}
});
Я продолжаю получать ошибку rule with id 1 does not have a unique id
Добавление идентификатора 1, когда идентификатор 1 уже существует, является ошибкой.
Как я могу сделать этот блок поддоменом? Я могу установить что-то вроде google.com
, но это не блокирует google.com/search?q...
Это основано на ответе НориоЯмамото (поэтому я проголосовал за него), но использует статические правила.
manifest.json
{
"manifest_version": 3,
"name": "On-Off Switch",
"version": "1.0.0",
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"declarative_net_request": {
"rule_resources": [
{
"id": "ruleset_1",
"enabled": false,
"path": "ruleset_1.json"
}
]
},
"permissions": [
"declarativeNetRequest",
"storage"
]
}
ruleset_1.json
[
{
"id": 1,
"action": { "type": "block" },
"condition": { "urlFilter": "stackoverflow.com", "resourceTypes": ["main_frame"] }
}
]
background.js
async function runtime_on_installed(details) {
if (details.reason == "install") {
// Store the extension's current state
// which is determined by the "declarative_net_request" key in manifest.json
let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
if (ruleset_ids.length == 0) {
// Extension is currently inactive
await chrome.storage.local.set({active: false});
}
else if (ruleset_ids.length == 1) {
// Extension is currently active
await chrome.storage.local.set({active: true});
}
}
else if (details.reason == "update") {
// Restore the extension's stored state
// https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#method-updateEnabledRulesets
// "Note that the set of enabled static rulesets is persisted across sessions but not across extension updates, i.e. the rule_resources manifest key will determine the set of enabled static rulesets on each extension update."
let { active } = await chrome.storage.local.get("active");
let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
if (active && ruleset_ids.length == 0) {
// Extension is supposed to be active, but is inactive
chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
}
else if (!active && ruleset_ids.length == 1) {
// Extension is supposed to be inactive, but is active
chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
}
}
}
function storage_on_changed(changes, area_name) {
if (area_name == "local") {
if (changes.active.oldValue == false && changes.active.newValue == true) {
chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
}
else if (changes.active.oldValue == true && changes.active.newValue == false) {
chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
}
}
}
chrome.runtime.onInstalled.addListener(runtime_on_installed);
chrome.storage.onChanged.addListener(storage_on_changed);
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Popup</title>
</head>
<body>
<p>Popup</p>
<button id = "on">On</button>
<button id = "off">Off</button>
<script src = "popup.js"></script>
</body>
</html>
popup.js
document.getElementById("on").onclick = () => {
chrome.storage.local.set({active: true});
}
document.getElementById("off").onclick = () => {
chrome.storage.local.set({active: false});
}
Могу ли я (и как) использовать это, чтобы заблокировать только поддомен, например example.com/foo/bar
, но не example.com
в целом?
Ничего, я неправильно понял ваш вопрос, придется подумать над этим еще немного - С "urlFilter": "google.com"
он блокирует google.com/search?q=test - Кстати, /foo/bar - это путь, а не поддомен example.com — Дополнительные сведения о формате urlFilter см. в chrome.declarativeNetRequest > Rules и chrome.declarativeNetRequest > RuleCondition > urlFilter
Это блокирует путь, но также блокирует google.com
в целом. Мне нужно, чтобы заблокировать путь, не блокируя весь сайт. Вставка google.com/search?q=a
, похоже, ничего не блокирует. Спасибо за исправление.
"urlFilter": "google.com/search*"
блокирует google.com/search?q=a, но не google.com. Прочтите документацию и, если формат urlFilter недостаточно точен, используйте regexFilter.
Кажется, это не работает для меня. Я использую тот же код, что и вы, за исключением дополнительного правила, которое я добавил. Этот код работает для вас?
Меня устраивает. Я всегда тестирую свой код перед публикацией, иначе он обычно полон ошибок :-) Чтобы помочь вам, мне нужна ваша версия Chrome, полный код вашего расширения, пошаговые инструкции по воспроизведению проблемы, ожидаемые результаты, и фактические результаты. Отредактируйте свой вопрос с этой информацией.
Хорошо, я добавил свой текущий код к вопросу. Как я уже сказал, мой код в настоящее время почти такой же, как ваш, так как я все еще пытаюсь заставить его работать.
Как вы хотите переключать состояние расширения? - а) Щелкнув один раз левой кнопкой мыши по значку действия расширения ? - б) С контекстным меню? (= один раз щелкните правой кнопкой мыши значок действия расширения, затем один раз щелкните левой кнопкой мыши по нужному элементу контекстного меню) chrome.contextMenus - c) С помощью кнопки во всплывающем окне расширения? (нажмите один раз левой кнопкой мыши на значок действия расширения, откроется всплывающее окно, затем нажмите кнопку внутри всплывающего окна)