In my short coder life I see such behavior for the first time:
An extension at its own works like I expect, but if I pull some variables into the console, I realize, that they are loaded multiple times (three, four and five, depends from placement of console.log in the background.js). This is the list of them - to see in the background.js too:
console.log("domen: "+currentDomain);
console.log("language/countrysubdomen: "+savedApi);
console.log("index: "+badgeText);
Is it something, that one can neglect? Should it be avoided? How? These variables are loaded in file, which is 60 lines long - I was going through this file some times and recognizes no cause for multiple loading.
Why is it happen? What is in the background.js wrong and how it could be improved to get this issue away?
manifest
{
"name": " App",
"description": "",
"version": "1.0",
"background": {
"scripts": [
"background.js",
"psl.js"
],
"persistent": false
},
"options_page": "options.html",
"options_ui": {
"page": "options.html",
"chrome_style": true,
"open_in_tab": false
},
"permissions": [
"webNavigation",
"activeTab",
"tabs",
"http://*/*",
"https://*/*",
"storage",
"background"
],
"browser_action": {
"default_title": "metrics",
"default_icon": {
"19": "icon19.png",
"38": "icon38.png"
},
"default_popup": "popup.html"
},
"icons": {
"16": "icon16.png",
"19": "icon19.png",
"24": "icon24.png",
"32": "icon32.png",
"38": "icon38.png",
"48": "icon48.png",
"128": "icon128.png"
},
"web_accessible_resources": [
"welcome.html"
],
"manifest_version": 2
}
background
var currentDomain = "";
var currentHost = "";
var currentFullpath = "";
var currentUrl = "";
var currentFolder = "";
var badgeText = "";
chrome.runtime.onInstalled.addListener(function (object) {
if (chrome.runtime.OnInstalledReason.INSTALL === object.reason) {
chrome.tabs.create({ url: chrome.extension.getURL("welcome.html") }, function (tab) {
console.log("New tab launched with instructions to use the extension");
});
}
});
chrome.tabs.onUpdated.addListener(function (tabid, changeInfo, tab) {
chrome.tabs.query({ 'active': true, 'currentWindow': true }, function (tabs) {
let newUrl = new URL(tabs[0].url);
currentHost = newUrl.host;
currentUrl = tabs[0].url;
currentFullpath = currentUrl.substring(0, currentUrl.lastIndexOf("/"));
currentFolder = currentUrl.split("/");
parsed = psl.parse(currentHost);
currentDomain = parsed.domain;
console.log("domen: " + currentDomain);
chrome.storage.sync.get('savedApi', ({ savedApi }) => {
console.log("language/countrysubdomen: " + savedApi);
if (savedApi == null)
savedApi = 'de';
if (currentDomain == null)
return false;
var xhr = new XMLHttpRequest();
var protocol = "https://";
var middle = ".myservice.com/seo/__loadModule/domain/"
var end = "/mobile/1/_action/_data_visindex_normal/";
xhr.open("GET", protocol + savedApi + middle + currentDomain + end, true);
xhr.responseType = 'document';
xhr.send();
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
function getElementByXpath(path) {
return xhr.response.evaluate(path, xhr.response, null, XPathResult.STRING_TYPE, null).stringValue;
}
badgeText = getElementByXpath("normalize-space(//div[#class='data']/span[#class='value']/text())");
console.log("index: " + badgeText);
chrome.browserAction.setTitle({ title: "The number of " + currentDomain + " is " + String(badgeText) });
chrome.browserAction.setBadgeText({ text: String(badgeText) });
chrome.browserAction.setBadgeBackgroundColor({ color: '#1d2554' });
};
};
});
});
});
You added a listener to chrome.tabs.onUpdated, so the listener may be triggered for a number of reasons:
a tab begins loading
a tab stops loading
the title of a tab changes or is set for the first time
the favicon is set
This is a non-exhaustive list. For a complete list, see the chrome.tabs.onUpdated event documentation.
It is quite normal that your onUpdated listener should be called multiple times. To see why it is being called, insert this line at the top of your listener:
chrome.tabs.onUpdated.addListener(function (tabid, changeInfo, tab) {
console.log('chrome.tabs.onUpdated listener called. Changed info: ' + JSON.stringify(changeInfo));
Related
window.open(".....")
chrome.cookies.getAll({domain: "......"}, function(cookies) {
for(var i=0; i<cookies.length;i++) {
chrome.cookies.remove({url: "......", name: "STX_SESSION"});
}})
chrome.tabs.reload()
window.open(".....")
const interval = setInterval(function() {
chrome.cookies.getAll({domain: "....."}, function(cookies) {
for(var i=0; i<cookies.length;i++) {
chrome.cookies.remove({url: ".....", name: "STX_SESSION"});
}})
chrome.tabs.reload()
window.open("......")
}, 1200000);
})
manifest.json
{
"name" : "....",
"version" : "1.0",
"description" : "....",
"permissions": [ "cookies", "tabs", "<all_urls>" , "http://*/", "https://*/"],
"icons": { "16": "....", "48": ".....", "128": "...." },
"browser_action": {
"default_icon": "....."
},
"background": {
"scripts": ["script.js"]
},
"manifest_version": 2
}
This is my code. I would like to reset the interval or in other word stop the background script from running. Is it possible to do this by clicking on the extension icon?
You cannot stop the background script since you've used the default value for persistent but you can stop the interval.
You can add a click event listener to the extension's icon using:
chrome.browserAction.onClicked.addListener(() => { .. });
And to stop the interval use clearInterval(interval).
Here is a complete solution:
chrome.browserAction.onClicked.addListener(() => clearInterval(interval));
In order for all this to work, you'll have to add browser_action to the permissions array in the manifest and make sure, the browser_action key doesn't have a default_popup key-value pair.
All in all, you should be using "manifest_version": 3 I think manifest version 2 extension are no longer accepted for publishing on the Google Web Store.
Based on your comment, it seems that you want to toggle the interval on click, here is how you can do that (along with some refactoring):
function doStuff() {
chrome.cookies.getAll({domain: "......"}, function(cookies) {
for(var i=0; i<cookies.length;i++) {
chrome.cookies.remove({url: "......", name: "STX_SESSION"});
}
});
chrome.tabs.reload()
}
doStuff();
window.open(".....")
const interval = setInterval(doStuff, 1200000);
chrome.browserAction.onClicked.addListener(() => {
if (interval === null) {
interval = setInterval(doStuff, 1200000);
} else {
clearInterval(interval)
interval = null;
}
});
Overflow Developes: I have search a lot about the textarea selection but have't found the proper solution.
Goal: I am going to build my own extension in which I want to perform some functionality. I have accessed the DOM. And further cannot able to access the only textarea.
Required: enter image description here I Want this type of working in my extension.
manifest.json
{
"manifest_version": 2,
"name": "DOM",
"version": "0.0",
"background": {
"persistent": false,
"scripts": [
"background.js"
]
},
"content_scripts": [
{
"matches": [
"*://*.stackoverflow.com/*"
],
"js": [
"content.js"
]
}
],
"browser_action": {
"default_title": "DOM",
"default_popup": "index.html"
},
"permissions": [
"activeTab",
"tabs",
"<all_urls>"
]}
index.html
<!DOCTYPE html>
<html>
<head>Fayzan</head>
<body> <button id="test">DOM!</button>
<script src="test.js"></script>
</body>
</html>
Content.js
// Listen for messages
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.text === 'report_back') {
// Call the specified callback, passing
// the web-page's DOM content as argument
sendResponse(document.all[0].outerHTML);
}
});
background.js
var urlRegex = /^https?:\/\/(?:[^./?#]+\.)?stackoverflow\.com/;
function doStuffWithDom(domContent) {
console.log('I received the following DOM content:\n' + domContent);
} // When the browser-action button is clicked...
chrome.browserAction.onClicked.addListener(function(tab) { // ...check the URL of the active tab against our pattern and...
if (urlRegex.test(tab.url)) { // ...if it matches, send a message specifying a callback too
chrome.tabs.sendMessage(tab.id, {
text: 'report_back'
}, doStuffWithDom);
}
});
test.js
document.getElementById("test").addEventListener('click', () => {
alert("DOM POPUP");
function modifyDOM() {
console.log('Tab script:');
console.log(document.body);
return document.body.innerHTML;
}
chrome.tabs.executeScript({
code: '(' + modifyDOM + ')();'
},
(results) => {
console.log("fayzan bhatti");
console.log(results);
}
);
});
I'm attempting to create a Chrome extension which will add a parameter to the end of a URL if the URL matches a given pattern (*://*.mydomain.com/s/*). Below is the manifest file and background script I have, but I cannot get it working. What am I doing wrong?
manifest.json:
{
"manifest_version": 2,
"name": "Search Grid View",
"version": "0.1",
"description": "Changes MyDomain.com search to grid view by default",
"background": {
"scripts": ["background.js"]
},
"permissions": [
"tabs",
"webRequest",
"*://*.mydomain.com/s/*",
"webRequestBlocking"
]
}
background.js:
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
var currentUrl = tabs[0].url;
var newUrl = currentUrl + "&style=gridview"
return { redirectUrl: newUrl};
},
{
urls: [
'*://*.mydomain.com/s/*'
],
types: ['main_frame']
},
['blocking']);
Thanks in advance for any advice!
Use debugger - click your extension's background page on chrome://extensions page and switch to the Sources panel.
To obtain the url use onBeforeRequest's callback parameter
Check if the url is already modified.
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
return {
redirectUrl: details.url +
(details.url.indexOf("?") == -1 ? "?" : "") +
(details.url.indexOf("&style=gridview") == -1 ? "&style=gridview" : "")
};
},
{urls: ['*://*.mydomain.com/s/*'], types: ['main_frame']},
['blocking']
);
I'm trying to remove the cache when the user go to this url stackoverflow.com/?clear then reload and go to stackoverflow.com with a clean cache, I tried a many methods but I failed.
Here is my last attempt, It's not affect the cache at all!
Manifest Code
{
"name": "stackoverflow",
"version": "1.0",
"background": {
"scripts": ["jquery.js","background.js"],
"persistent": false
},
"page_action" :
{
"default_icon" : "icon.png",
"default_title" : "Remove"
},
"permissions" : [
"declarativeContent", "browsingData", "tabs"
],
"manifest_version": 2
}
background.js
chrome.runtime.onInstalled.addListener(function() {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL contains a 'stackoverflow.com/?clea' ...
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlContains: 'stackoverflow.com/?clear' },
})
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction() ]
}
]);
});
});
function clearMe(tab) {
var ms = (30 * 60) * 1000; // 30 minutes
var time = Date.now() - ms;
chrome.browsingData.removeCache({"since": time}, function() {
chrome.tabs.update({url: 'http://stackoverflow.com'});
});
}
//It will be perfect if user do not have to click
chrome.pageAction.onClicked.addListener(clearMe)
I need better alternative to remove cache without even the user click a button.
tabs api should be enough for this. Here's how you should do it. I've tested it and it's working fine.
Manifest Code
{
"name": "stackoverflow",
"version": "1.0",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions" : [
"tabs", "browsingData"
],
"manifest_version": 2
}
background.js
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
// if url is changed
if (changeInfo.url) {
var url = changeInfo.url;
if (url.indexOf("stackoverflow.com/?clear") != -1) {
alert("Clearing cache...");
clearMe(tab);
}
}
});
function clearMe(tab) {
var ms = (30 * 60) * 1000; // 30 minutes
var time = Date.now() - ms;
chrome.browsingData.removeCache({"since": time}, function() {
chrome.tabs.update(tab.id, { url: 'http://stackoverflow.com' });
});
}
I wish to pass JS info from the popup to the background tab.
Is this possible?
I tried several things but nothing worked.
My manifest:
{
"name": "Test",
"description": "Make the current page red",
"version": "2.0",
"permissions": [
"activeTab"
],
"background": {
"persistent": false
},
"browser_action": {
"default_title": "Make this page red",
"default_popup": "popup.html",
},
"manifest_version": 2
,
"content_scripts": [ {
"js": [ "jquery.min.js" ],
"matches": [ "http://*/*", "https://*/*"]
}]
}
My popup:
<head>
<title>Options for Color Chooser</title>
<script type="text/javascript" src="popup.js"></script>
</head>
<body style="width:300px; height:250px; text-align:center;">
<input id="gobtn" type="button" value="Start" />
</body>
</html>
And my JS:
function() {
var btncolor = "red";
chrome.extension.onRequest.addListener(function() {
$("body").css("background",btncolor);
alert("!");
});
}
Any help would be very much appreciated
You'll need to make a request function in your popup.js, and then listen for it in your main JS file. Try this:
popup.js
var btn = document.getElementById('gobtn');
btn.addEventListener('click', setPageColor);
function setPageColor( newColor ) {
newColor = newColor || 'red';
// This is the syntax for "talking" to our current tab
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {action: "setColor", color: newColor}, function(response) {
// You can do whatever you want with the response :)
if (response.msg === 'SUCCESS') console.log('It worked!')
if (response.msg === 'FAIL') console.error('Fail -_-')
});
});
}
main.js
...
// This is the "receiving end", which has full DOM/window access on the tab
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
// request.action provides a nice pattern for re-using this listener
if (request.action == "setColor") {
color = request.color;
document.body.setAttribute('style', 'color:' + color)
sendResponse({ msg: 'SUCCESS' });
}
else {
sendResponse({ msg: 'FAIL' }); // Send nothing..
}
});