removeListener в Chrome extension not working - google-chrome-extension

Here is the contents of background.js:
var toggle = false;
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if(toggle) {
var start_working = function() {
chrome.tabs.query({ url: ["http://*/*","https://*/*"], currentWindow: true }, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 1;"});
chrome.tabs.executeScript(tabs[i].id, {file: 'js/new.js'});
chrome.browserAction.setIcon({path: "add48.png", tabId:tabs[i].id});
}
});
}
if (!chrome.tabs.onUpdated.hasListener(start_working)) {
chrome.tabs.onUpdated.addListener(start_working);
chrome.tabs.query({url: ["http://*/*","https://*/*"]}, function (tabs) {
console.log('1start_working='+chrome.tabs.onUpdated.hasListener(start_working));
console.log('1toggle='+toggle);
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 1;"});
chrome.tabs.executeScript(tabs[i].id, {file: 'js/new.js'});
chrome.browserAction.setIcon({path: "add48.png", tabId:tabs[i].id});
}
}
);
}
} else {
chrome.tabs.onUpdated.removeListener(start_working);
console.log('2start_working='+chrome.tabs.onUpdated.hasListener(start_working));
console.log('2toggle='+toggle);
chrome.tabs.query({url: ["http://*/*","https://*/*"], currentWindow: true }, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 0; $('#sort_g').remove();"});
chrome.browserAction.setIcon({path: "add48_off.png", tabId:tabs[i].id});
}
}
);
return false;
}
});
Here is the code of manifest.json:
{
"manifest_version": 2,
"name": "Ds",
"version": "0.2",
"background": {
"scripts": ["background.js"]
},
"icons": {
"48": "add48.png",
"128": "add128.png"
},
"browser_action": {
"default_icon": "add48_off.png"
},
"permissions": [
"tabs",
"notifications",
"*://*/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-2.2.4.min.js"],
"run_at": "document_end",
"all_frames": true
}
],
"web_accessible_resources": ["tpl/panel.html"]
}
When we click on the application icon, we add an element to all the HTML tabs and make the icon "active", and when we click the icon again, we change the icon to gray and remove the html element from all pages.
Also, when updating the html tab, the element should again appear and the extension icon should be active.
All this is implemented, but after disabling the extension, an html element still appears, although the new.js script should not be connected and chrome.tabs.onUpdated.hasListener(start_working)=false
Here's the log after disabling the extension:
background.js:49 2start_working=false
background.js:50 2toggle=false
But when updating the tab anyway, the html element appears on the page
I can not understand why this happens? Moreover, the console shows that after disabling the extension, when updating the page, the new.js script is connected already 3 times.

Related

Create iframe using Google Chrome Extension manifest v3

I'm migrating an extension from manifest v2 to manifest v3 (and refactor and redesign...)
In the old version we were using an iframe within the tab, like this:
background.js
const open = () => {
const oldIframe = document.getElementById('cm-frame');
if (oldIframe) {
oldIframe.remove();
return;
}
const iframe = document.createElement('iframe');
iframe.setAttribute('id', 'cm-frame');
iframe.setAttribute('style', 'top: 10px;right: 10px;width: 450px;height: 100%;z-index: 2147483650;border: none; position:fixed;');
iframe.setAttribute('allow', '');
iframe.src = chrome.extension.getURL('index.html');
iframe.frameBorder = 0;
document.body.appendChild(iframe);
};
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript({
code: '(' + open.toString() + ')();'
}, () => { });
});
I've tried the same approach using chrome.actions.onClicked.addListener with chrome.scripting.executeScript and had no luck.
I know we could just use a popup ("default_popup": "popup.html",) but the iframe works better in terms of integration and design.
I was able to make it work.
background.js
chrome.action.onClicked.addListener(async function (tab) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => {
const oldIframe = document.getElementById('cm-frame');
if (oldIframe) {
oldIframe.remove();
return;
}
const iframe = document.createElement('iframe');
iframe.setAttribute('id', 'cm-frame');
iframe.setAttribute(
'style',
'top: 10px;right: 10px;width: 400px;height: calc(100% - 20px);z-index: 2147483650;border: none; position:fixed;'
);
iframe.setAttribute('allow', '');
iframe.src = chrome.runtime.getURL('popup.html');
document.body.appendChild(iframe);
},
});
});
This my manifest.json file in case someone also needs it (I had to add stuff to permissions and web_accessible_resources to make it work and load correctly):
{
"manifest_version": 3,
"name": "Contact Mapping Extension",
"background": { "service_worker": "background.bundle.js" },
"action": {
"default_icon": "icon-34.png"
},
"icons": {
"128": "icon-128.png"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
"js": ["contentScript.bundle.js"],
"css": ["content.styles.css"]
}
],
"web_accessible_resources": [
{
"resources": ["content.styles.css", "icon-128.png", "icon-34.png", "popup.html"],
"matches": ["<all_urls>"]
}
],
"permissions": [
"tabs",
"activeTab",
"scripting"
]
}

Function runs before the tab has loaded - Chrome Extension

So I am trying to find something on a new tab that I open from my chrome extension. The extension can open the tab but the Function runs before the script. I want a script or this function to run once the tab has loaded.
This is my manifest.json file:
{
"name": "SwagBot",
"version": "0.0.1",
"manifest_version": 2,
"description": "The Offical SwagBot extension to cop your supreme!",
"browser_action":{
"default_popup":"popup.html"
},
"permissions": [
"https://*/*",
"http://*/*",
"storage",
"tabs",
"activeTab",
"webRequest",
"webRequestBlocking",
"webNavigation",
"declarativeContent"
]
}
Here is my javascript:
function findItem(){
allText = document.getElementsByClassName("name-link");
console.log('start');
for(i = 0; i < allText.length; i++){
if(i % 2 == 0){
names.push(allText[i].innerHTML);
}else{
colors.push(allText[i].innerHTML);
links.push(allText[i].href);
}
}
for(i = 0; i < names.length; i++){
if(names[i].indexOf(itemName) != -1){
name_flag = true;
console.log('here');
}
if(colors[i].indexOf(itemColor) != -1 && name_flag == true){
itemlink = links[i];
console.log(itemlink);
}
}
}
StartButton.addEventListener('click', function() {
chrome.storage.sync.get(["category",], function(items) {
index_url = "http://www.TEHWEBPAGEIWANT.com" + items.category;
console.log(index_url);
chrome.tabs.create({
url: index_url
});
});
chrome.tabs.onCreated.addListener(findItem);
});
});
Any help would really be appreciated, thank you. :)

chrome.browserAction.onClicked cannot be triggered

I am working on some experiments that requires to auto generate IDs for elements, I have decided to go with chrome extension.
However, the content script only got triggered when I land on the homepage of the site (e.g. https://secure.checkout.visa.com/). Once I navigate to other pages (e.g. tap on "Create Account"), the script didn't get triggered, I tried to set a break point on the content script but it only got hit on the home page, but not on create account page.
Any idea what went wrong here? Below is the code:
// manifest.json
{
"manifest_version": 2,
"name": "Chrome Auto Gen ID",
"description": "Generate IDs",
"version": "1.0",
"permissions": ["activeTab"],
"background": {
"scripts": ["event_page.js"],
"persistent": false
},
"browser_action": {
"default_title": "Auto generate ID"
},
"content_scripts": [
{
"matches": ["https://secure.checkout.visa.com/*"],
"js": ["jquery-3.2.1.min.js", "auto_gen_id.js"],
"all_frames": true,
"run_at": "document_idle"
}
]
}
The content script:
// auto_gen_id.js
var divs = document.getElementsByTagName("div");
var inputs = document.getElementsByTagName("input");
var sections = document.getElementsByTagName("section");
var count = 0;
function genId(list) {
for (var i = 0; i < list.length; ++i) {
var element = list[i];
if (element.hasAttribute("id")) {
continue;
}
element.id = "gen-id-" + count++;
}
}
genId(divs);
genId(inputs);
The background script:
// event_page.js
chrome.browserAction.onClicked.addListener(function(tab) {
console.log('Generating IDs on ' + tab.url);
chrome.tabs.executeScript(null, {file: "auto_gen_id.js"});
});
Thanks #makyen and #wOxxOm, followed the suggestions below to solve the problem:
Is there a JavaScript/jQuery DOM change listener

Unable to set chrome extension content.js to only work when the icon is clicked?

Right now, I have an app that always runs the content.js script and replaces all images in the browser that it can find with a different image. I want to make it so that this only happens when you actually click the icon for the extension.
Here is my manifest.json:
{
"manifest_version": 2,
"name": "Unicorn",
"description": "changes images and words to unicorn related ones",
"version": "1.0",
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"browser_action": {
"default_title": "Unicorn"
}
}
Here is content.js:
chrome.browserAction.onClicked.addListener(function (tab) { //should be fired when User Clicks ICON
var elements = document.getElementsByTagName('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if(isImage(element)){
element.src="http://67.media.tumblr.com/30b1b0d0a42bca3759610242a1ff0348/tumblr_nnjxy1GQAA1tpo3v2o1_540.jpg";
}
for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];
if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace(/wild/gi, 'rainbow bright');
if (replacedText !== text) {
element.replaceChild(document.createTextNode(replacedText), node);
}
}
}
}
});
function isImage(i) {
return i instanceof HTMLImageElement;
}
This works fine without the line chrome.browserAction.onClicked.addListener(function (tab) { and the closing brackets for it. What am I missing here?
The browser action click handler should be moved to Background context for it to work, then you can send a message to current tab.
manifest.json
{
"manifest_version": 2,
"name": "Unicorn",
"description": "changes images and words to unicorn related ones",
"version": "1.0",
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"background": {
"scripts": [
"background.js"
]
},
"browser_action": {
"default_title": "Unicorn"
}
}
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.sendMessage(tab.id, {
method: 'showImages'
});
});
content.js
function showImages() {
var elements = document.getElementsByTagName('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (isImage(element)) {
element.src = "http://67.media.tumblr.com/30b1b0d0a42bca3759610242a1ff0348/tumblr_nnjxy1GQAA1tpo3v2o1_540.jpg";
}
for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];
if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace(/wild/gi, 'rainbow bright');
if (replacedText !== text) {
element.replaceChild(document.createTextNode(replacedText), node);
}
}
}
}
}
function isImage(i) {
return i instanceof HTMLImageElement;
}
// Message handler
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.method === 'showImages') {
showImages();
}
});

Chrome extension : Is it possible to keep extension open on reload?

I'm building an google extension that inserts html in page and shows a menu on browser action icon click and I don't find way to keep my extension open when I reload the page. So on every reload, we have to active it again from Browser Action icon.
Below the manifest file
{
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "img/icone.png",
"default_title": "show menu"
},
"icons" : {
"128" : "img/icone_128.png",
"48" : "img/icone_48.png",
"32" : "img/icone_32.png",
"24" : "img/icone_24.png",
"16" : "img/icone_16.png"
},
"manifest_version": 2,
"name": "p|layer",
"version": "1.0.4",
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css":["css/grid.css", "css/font-awesome.min.css"],
"js":["js/jquery-1.11.1.min.js","js/jquery-ui.js", "js/jquery.nicefileinput.min.js"]
}
],
"web_accessible_resources": [
"fonts/fontawesome-webfont.woff"
],
"permissions": [ "activeTab"]
}
script (background.js) injecting contentscript
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
chrome.tabs.executeScript(tab.id,
{"file": "js/contentscript.js"},
function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
chrome.tabs.insertCSS(tab.id, {file: "css/grid.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/font-awesome.min.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/slider.css"});
});
any help will be appreciated
So, from the comments the problem was inferred: your button click activates your content script, but a page reload clears it. Assuming you want the button click to act as a toggle:
1) Always inject the content script / CSS, but don't show the UI immediately:
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css": ["css/grid.css", "css/font-awesome.min.css", "css/slider.css"],
"js": [
"js/jquery-1.11.1.min.js", "js/jquery-ui.js",
"js/jquery.nicefileinput.min.js", "js/contentscript.js"
]
}
],
2) Keep track of "activated" tabs:
var activeTabs = {};
chrome.browserAction.onClicked.addListener( function(tab){
var active;
if(activeTabs[tab.id]){
delete activeTabs[tab.id];
active = false;
} else {
activeTabs[tab.id] = true;
active = true;
}
/* (part 3) */
});
chrome.tabs.onRemoved.addListener( function(tabId){
delete activeTabs[tabId];
});
chrome.tabs.onReplaced.addListener( function(newTabId, oldTabId){
if(activeTabs[oldTabId]) activeTabs[newTabId] = true;
delete activeTabs[oldTabId];
});
3) Use messaging to show/hide UI:
Content script:
chrome.runtime.onMessage.addListener( function(message. sender, sendResponse){
if(message.showUI) showUI();
if(message.hideUI) hideUI();
});
Background script:
chrome.browserAction.onClicked.addListener( function (tab) {
var active;
/* (part 2) */
if(active) {
chrome.tabs.sendMessage(tab.id, {showUI: true});
} else {
chrome.tabs.sendMessage(tab.id, {hideUI: true});
}
});
Additional robustness can be added for the cases of extension reload, but that's the gist of it.

Resources