Compare commits
4 commits
3086c5ef41
...
683749748b
Author | SHA1 | Date | |
---|---|---|---|
683749748b | |||
d470131bde | |||
136b0ecae1 | |||
54998a68a4 |
5 changed files with 247 additions and 131 deletions
39
clickall.js
39
clickall.js
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
||||||
* Copyright (c) Ad5001 2021
|
* Copyright (c) Ad5001 2021-2023
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
@ -9,10 +9,10 @@
|
||||||
|
|
||||||
// This file handles all clicking automaticly all similar buttons (e.g : same text & element name)
|
// This file handles all clicking automaticly all similar buttons (e.g : same text & element name)
|
||||||
|
|
||||||
const CLICK_ALL_SCRIPT = `
|
const clickAllScript = (targetElementId) => {
|
||||||
var bound, selectedElements, clickedButton, buttonText, classes, query, sameElements;
|
let bound, selectedElements, clickedButton, buttonText, classes, query, sameElements
|
||||||
// Get the potential selected button
|
// Get the potential selected button
|
||||||
bound = browser.menus.getTargetElement(targetElementId).getBoundingClientRect();
|
bound = browser.menus.getTargetElement(targetElementId).getBoundingClientRect()
|
||||||
selectedElements = document.elementsFromPoint(bound.x+bound.width/2, bound.y+bound.height/2)
|
selectedElements = document.elementsFromPoint(bound.x+bound.width/2, bound.y+bound.height/2)
|
||||||
|
|
||||||
// Leftover debug for positioning
|
// Leftover debug for positioning
|
||||||
|
@ -37,17 +37,27 @@ if(selectedElements.length > 0) {
|
||||||
btn.click()
|
btn.click()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
` // Requires targetElementId to be defined beforehands
|
}
|
||||||
const CLICK_ALL_TITLE = "Click all similar buttons";
|
// Requires targetElementId to be defined beforehands
|
||||||
const CLICK_ALL_MENU_CONTEXTS = ["editable", "image", "link", "page"];
|
const CLICK_ALL_TITLE = "Click all similar buttons"
|
||||||
|
const CLICK_ALL_MENU_CONTEXTS = ["all"]
|
||||||
|
|
||||||
function clickAllSimilarButtons(info, tab) {
|
function clickAllSimilarButtons(info, tab) {
|
||||||
browser.tabs.executeScript(tab.id, {
|
browser.scripting.executeScript({
|
||||||
frameId: info.frameId,
|
target: {
|
||||||
code: `var targetElementId = ${info.targetElementId};${CLICK_ALL_SCRIPT}`,
|
tabId: tab.id,
|
||||||
});
|
frameIds: [ info.frameId ],
|
||||||
|
},
|
||||||
|
func: clickAllScript,
|
||||||
|
args: [ info.targetElementId ]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creating menu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(browser.menus) { // Not supported on Firefox for Android
|
||||||
browser.menus.create({
|
browser.menus.create({
|
||||||
id: "unchecker-clickall",
|
id: "unchecker-clickall",
|
||||||
title: CLICK_ALL_TITLE,
|
title: CLICK_ALL_TITLE,
|
||||||
|
@ -56,5 +66,10 @@ browser.menus.create({
|
||||||
"32": "icons/click.svg"
|
"32": "icons/click.svg"
|
||||||
},
|
},
|
||||||
contexts: CLICK_ALL_MENU_CONTEXTS,
|
contexts: CLICK_ALL_MENU_CONTEXTS,
|
||||||
onclick(info, tab) { clickAllSimilarButtons(info, tab) }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
browser.menus.onClicked.addListener((info, tab) => {
|
||||||
|
if(info.menuItemId == "unchecker-clickall")
|
||||||
|
clickAllSimilarButtons(info, tab)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
{
|
{
|
||||||
|
|
||||||
"description": "Simple extension letting you uncheck all checkboxes on a page.",
|
"description": "Simple extension letting you uncheck all checkboxes on a page.",
|
||||||
"manifest_version": 2,
|
"manifest_version": 3,
|
||||||
"name": "unchecker",
|
"name": "unchecker",
|
||||||
"version": "1.1",
|
"version": "1.2.2",
|
||||||
"author": "Ad5001",
|
"author": "Ad5001",
|
||||||
"developer": {
|
"developer": {
|
||||||
"name": "Ad5001",
|
"name": "Ad5001",
|
||||||
"url": "https://ad5001.eu"
|
"url": "https://ad5001.eu"
|
||||||
},
|
},
|
||||||
"applications": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "unchecker@ad5001.eu",
|
"id": "unchecker@ad5001.eu",
|
||||||
"strict_min_version": "60.0"
|
"strict_min_version": "113.0"
|
||||||
|
},
|
||||||
|
"gecko_android": {
|
||||||
|
"strict_min_version": "113.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"homepage_url": "https://apps.ad5001.eu/unchecker/",
|
"homepage_url": "https://apps.ad5001.eu/unchecker/",
|
||||||
|
@ -21,9 +24,9 @@
|
||||||
"scripts": ["uncheck.js", "clickall.js"]
|
"scripts": ["uncheck.js", "clickall.js"]
|
||||||
},
|
},
|
||||||
|
|
||||||
"browser_action": {
|
"action": {
|
||||||
"default_icon": "icons/on.svg",
|
"default_icon": "icons/on.svg",
|
||||||
"browser_style": true
|
"default_title": "Uncheck all checkboxes"
|
||||||
},
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
"48": "icons/off.svg",
|
"48": "icons/off.svg",
|
||||||
|
@ -32,7 +35,8 @@
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"tabs",
|
"tabs",
|
||||||
"menus"
|
"menus",
|
||||||
|
"scripting"
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
86
test/frame.html
Normal file
86
test/frame.html
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<!--
|
||||||
|
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
||||||
|
* Copyright (c) Ad5001 2021-2023
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Unchecker tests in iframe</title>
|
||||||
|
<style>
|
||||||
|
legend {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
padding: 3px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggled {
|
||||||
|
border-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: .4rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="test.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Example radio list</legend>
|
||||||
|
|
||||||
|
<input type="radio" id="choice-value1" name="choice-value">
|
||||||
|
<label for="choice-value">Example, irrelevant choice value 1</label><br/>
|
||||||
|
|
||||||
|
<input type="radio" id="choice-value2" name="choice-value">
|
||||||
|
<label for="choice-value">Example, irrelevant choice value 2</label><br/>
|
||||||
|
</fieldset>
|
||||||
|
<br>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Third party partners example</legend>
|
||||||
|
|
||||||
|
<input type="checkbox" id="ga-choice" checked="true">
|
||||||
|
<label for="ga-choice">Google Analytics</label><br/>
|
||||||
|
|
||||||
|
<input type="checkbox" id="facebook-ads" checked="true">
|
||||||
|
<label for="facebook-ads">Facebook Partnering</label><br/>
|
||||||
|
|
||||||
|
<input type="checkbox" id="amazon-sales" checked="true">
|
||||||
|
<label for="amazon-sales">Amazon</label><br/>
|
||||||
|
|
||||||
|
<input type="checkbox" id="salesforce" checked="true">
|
||||||
|
<label for="salesforce">Salesforce</label><br/>
|
||||||
|
</fieldset>
|
||||||
|
<br>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Third party partners second</legend>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Google Analytics</td>
|
||||||
|
<td><button role="toggle" class="toggled" name="ga-choice">On</button></td>
|
||||||
|
<td><button role="toggle" name="ga-choice">Off</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Facebook Partnering</td>
|
||||||
|
<td><button role="toggle" class="toggled" name="facebook-ads">On</button></td>
|
||||||
|
<td><button role="toggle" name="facebook-ads">Off</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Amazon</td>
|
||||||
|
<td><button role="toggle" class="toggled" name="amazon-sales">On</button></td>
|
||||||
|
<td><button role="toggle" name="amazon-sales">Off</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Salesforce</td>
|
||||||
|
<td><button role="toggle" class="toggled" name="salesforce">On</button></td>
|
||||||
|
<td><button role="toggle" name="salesforce">Off</button></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</fieldset>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<!--
|
<!--
|
||||||
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
||||||
* Copyright (c) Ad5001 2021
|
* Copyright (c) Ad5001 2021-2023
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
@ -25,6 +25,11 @@
|
||||||
input {
|
input {
|
||||||
margin: .4rem;
|
margin: .4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="test.js"></script>
|
<script src="test.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -81,5 +86,9 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>IFramed tests</legend>
|
||||||
|
|
||||||
|
<iframe src="./frame.html"></iframe>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
154
uncheck.js
154
uncheck.js
|
@ -1,146 +1,148 @@
|
||||||
/**
|
/**
|
||||||
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
|
||||||
* Copyright (c) Ad5001 2021
|
* Copyright (c) Ad5001 2021-2023
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
* obtain one at http://mozilla.org/MPL/2.0/.
|
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
const UNCHK_SCRIPT = `
|
const uncheckAll = () => {
|
||||||
function disable_checkboxes(element){
|
|
||||||
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
|
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
|
||||||
el.checked = false
|
el.checked = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
disable_checkboxes(document.body)
|
|
||||||
document.body.querySelectorAll('iframe').forEach(function(el){disable_checkboxes(el.contentDocument || el.contentWindow.document)})
|
const checkAll = () => {
|
||||||
`
|
|
||||||
const CHK_SCRIPT = `
|
|
||||||
function check_checkboxes(element){
|
|
||||||
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
|
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
|
||||||
el.checked = true
|
el.checked = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
check_checkboxes(document.body)
|
const TITLE_UNCHECK = "Uncheck all checkboxes"
|
||||||
document.body.querySelectorAll('iframe').forEach(function(el){check_checkboxes(el.contentDocument || el.contentWindow.document)})
|
const TITLE_CHECK = "Check all checkboxes"
|
||||||
`
|
const APPLICABLE_PROTOCOLS = ["http:", "https:"]
|
||||||
const TITLE_APPLY = "Uncheck all checkboxes";
|
const MENU_CONTEXTS = ["all"]
|
||||||
const TITLE_REMOVE = "Check all checkboxes";
|
|
||||||
const APPLICABLE_PROTOCOLS = ["http:", "https:"];
|
|
||||||
const MENU_CONTEXTS = ["editable", "image", "link", "page"];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle Script: based on the current title, insert or remove the Script.
|
* Toggle Script: based on the current title, insert or remove the Script.
|
||||||
* Update the page action's title and icon, aswell as the context menu item to reflect its state.
|
* Update the page actions title and icon, aswell as the context menu item to reflect its state.
|
||||||
**/
|
**/
|
||||||
function toggleScript(tab) {
|
function toggleScript(tab) {
|
||||||
|
|
||||||
function gotTitle(title) {
|
function gotTitle(title) {
|
||||||
if (title === TITLE_APPLY) {
|
console.log((title === TITLE_UNCHECK ? "Unchecking all checkboxes..." : "Checking all checkboxes...") + " at tab " + tab.id)
|
||||||
browser.browserAction.setIcon({tabId: tab.id, path: "icons/off.svg"});
|
if(title === TITLE_UNCHECK) {
|
||||||
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_REMOVE});
|
browser.action.setIcon({tabId: tab.id, path: "icons/off.svg"})
|
||||||
browser.menus.remove("unchecker-main").then(function() {
|
browser.action.setTitle({tabId: tab.id, title: TITLE_CHECK})
|
||||||
browser.menus.create({
|
browser.scripting.executeScript({
|
||||||
id: "unchecker-main",
|
func: uncheckAll,
|
||||||
title: TITLE_REMOVE,
|
target: {
|
||||||
|
tabId: tab.id,
|
||||||
|
allFrames: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(browser.menus)
|
||||||
|
browser.menus.update("unchecker-main", {
|
||||||
|
title: TITLE_CHECK,
|
||||||
icons: {
|
icons: {
|
||||||
"16": "icons/off.svg"
|
"16": "icons/off.svg"
|
||||||
},
|
}
|
||||||
contexts: MENU_CONTEXTS,
|
})
|
||||||
onclick(info,tab) { toggleScript(tab) }
|
|
||||||
});
|
|
||||||
}, function(){})
|
|
||||||
browser.tabs.executeScript({
|
|
||||||
code: UNCHK_SCRIPT
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
|
browser.action.setIcon({tabId: tab.id, path: "icons/on.svg"})
|
||||||
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
|
browser.action.setTitle({tabId: tab.id, title: TITLE_UNCHECK})
|
||||||
browser.menus.remove("unchecker-main").then(function() {
|
browser.scripting.executeScript({
|
||||||
browser.menus.create({
|
func: checkAll,
|
||||||
id: "unchecker-main",
|
target: {
|
||||||
title: TITLE_APPLY,
|
tabId: tab.id,
|
||||||
|
allFrames: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(browser.menus)
|
||||||
|
browser.menus.update("unchecker-main", {
|
||||||
|
title: TITLE_UNCHECK,
|
||||||
icons: {
|
icons: {
|
||||||
"16": "icons/on.svg"
|
"16": "icons/on.svg"
|
||||||
},
|
}
|
||||||
contexts: MENU_CONTEXTS,
|
})
|
||||||
onclick(info,tab) { toggleScript(tab) }
|
|
||||||
});
|
|
||||||
}, function(){})
|
|
||||||
browser.tabs.executeScript({
|
|
||||||
code: CHK_SCRIPT
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var gettingTitle = browser.browserAction.getTitle({tabId: tab.id});
|
browser.action.getTitle({tabId: tab.id}).then(gotTitle)
|
||||||
gettingTitle.then(gotTitle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true only if the URL's protocol is in APPLICABLE_PROTOCOLS.
|
* Returns true only if the URL's protocol is in APPLICABLE_PROTOCOLS.
|
||||||
**/
|
**/
|
||||||
function protocolIsApplicable(url) {
|
function protocolIsApplicable(url) {
|
||||||
let anchor = document.createElement('a');
|
let anchor = document.createElement('a')
|
||||||
anchor.href = url;
|
anchor.href = url
|
||||||
return APPLICABLE_PROTOCOLS.includes(anchor.protocol);
|
return APPLICABLE_PROTOCOLS.includes(anchor.protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the page action: set icon and title, then show.
|
* Initialize the page action set icon and title, then show.
|
||||||
* Only operates on tabs whose URL's protocol is applicable.
|
* Only operates on tabs whose URL's protocol is applicable.
|
||||||
**/
|
**/
|
||||||
function initializebrowserAction(tab, createMenu) {
|
function initializebrowserAction(tab, createMenu) {
|
||||||
|
// console.log("Initializing browser action for tab", tab, createMenu)
|
||||||
if(protocolIsApplicable(tab.url)) {
|
if(protocolIsApplicable(tab.url)) {
|
||||||
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
|
browser.action.setIcon({tabId: tab.id, path: "icons/on.svg"})
|
||||||
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
|
browser.action.setTitle({tabId: tab.id, title: TITLE_UNCHECK})
|
||||||
browser.browserAction.show(tab.id);
|
|
||||||
}
|
}
|
||||||
if(createMenu) {
|
if(createMenu && browser.menus) {
|
||||||
browser.menus.remove("unchecker-main").then(function() {
|
browser.menus.remove("unchecker-main").then(function() {
|
||||||
browser.menus.create({
|
browser.menus.create({
|
||||||
id: "unchecker-main",
|
id: "unchecker-main",
|
||||||
title: TITLE_APPLY,
|
title: TITLE_UNCHECK,
|
||||||
icons: {
|
icons: {
|
||||||
"16": "icons/on.svg"
|
"16": "icons/on.svg"
|
||||||
},
|
},
|
||||||
contexts: MENU_CONTEXTS,
|
contexts: MENU_CONTEXTS
|
||||||
onclick(info,tab) { toggleScript(tab) }
|
})
|
||||||
});
|
})
|
||||||
}, function(){})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the default context menu for the main function.
|
||||||
|
*/
|
||||||
|
if(browser.menus) { // Not supported on Firefox for Android
|
||||||
|
browser.menus.create({
|
||||||
|
id: "unchecker-main",
|
||||||
|
title: TITLE_UNCHECK,
|
||||||
|
icons: {
|
||||||
|
"16": "icons/on.svg"
|
||||||
|
},
|
||||||
|
contexts: MENU_CONTEXTS
|
||||||
|
})
|
||||||
|
browser.menus.onClicked.addListener((info, tab) => {
|
||||||
|
if(info.menuItemId == "unchecker-main")
|
||||||
|
toggleScript(tab)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When first loaded, initialize the page action for all tabs.
|
* When first loaded, initialize the page action for all tabs.
|
||||||
**/
|
**/
|
||||||
browser.menus.create({
|
|
||||||
id: "unchecker-main",
|
browser.tabs.query({}).then((tabs) => {
|
||||||
title: TITLE_APPLY,
|
|
||||||
icons: {
|
|
||||||
"16": "icons/on.svg"
|
|
||||||
},
|
|
||||||
contexts: MENU_CONTEXTS,
|
|
||||||
onclick(info,tab) { toggleScript(tab) }
|
|
||||||
});
|
|
||||||
let gettingAllTabs = browser.tabs.query({});
|
|
||||||
gettingAllTabs.then((tabs) => {
|
|
||||||
for(let tab of tabs) {
|
for(let tab of tabs) {
|
||||||
initializebrowserAction(tab, false);
|
initializebrowserAction(tab, false)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each time a tab is updated, reset the page action for that tab.
|
* Each time a tab is updated, reset the page browser.action.for that tab.
|
||||||
**/
|
**/
|
||||||
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
|
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
|
||||||
initializebrowserAction(tab, true);
|
initializebrowserAction(tab, true)
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle Script when the page action is clicked.
|
* Toggle Script when the page browser.action.is clicked.
|
||||||
**/
|
**/
|
||||||
browser.browserAction.onClicked.addListener(toggleScript);
|
browser.action.onClicked.addListener(toggleScript)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue