So I have an extension I'm writing and I'm trying to execute a script when the user clicks on the pageAction icon. When the icon is clicked, the method calls chrome.tabs.executeScript(...). The problem is that the chrome.tabs.executeScript function is not executing and I can't tell why. I know that I'm getting to the code where it calls executeScript because I have an alert there that appears. Here is some of my code:
manifest.json
{
"manifest_version": 2,
"name": "name here",
"description": "description here",
"version": "0.1",
"permissions": [
"<all_urls>",
"tabs"
],
"icons": {
"16" : "images/icon16.png",
"48" : "images/icon48.png",
"128": "images/icon128.png"
},
"background": {
"scripts": ["js/check.js"]
},
"page_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "default title here"
}
}
js/check.js
chrome.tabs.onUpdated.addListener(checkForValidUrl);
function checkForValidUrl(tabId, changeInfo, tab) {
if (tab.url.indexOf('g') > -1) {
chrome.pageAction.show(tabId);
}
};
chrome.pageAction.onClicked.addListener(function(tab) {
alert("hello world"); //this code is executed...
//...this code is not
chrome.tabs.executeScript(tab.id, {file: "save.js"}, function() {
if(chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
}
});
});
js/save.js
alert("hello world");
Like I say in the code, the hello world in my pageAction onClick function works. The executeScript method does not. Any idea about what is going on would be helpful.
After messing around with lots of different things in my code, I've found the solution to my problem. The error seems to be in the line that says {file: "save.js"}. When it's looking for save.js, it's apparently looking in the top directory, where my manifest.json file is located, not in the directory that my code is in. I had to change my code to {file: "js/save.js"} in order for my save.js file to be found.
According to the docs:
To insert code into a page, your extension must have cross-origin permissions for the page. It also must be able to use the chrome.tabs module. You can get both kinds of permission using the manifest file's permissions field.
So you need a permission for the site, i.e. http://example.com/ in the permission field.
Related
I am developing my first browser extension for my website.
What this extension should basically do is to have a browser action which opens a pop-up where you can edit specific cookie values for the current page.
However, cookie A can exist on the page / while cookie B can exist on the page /checkout. So I don't want to list every cookie inside the pop-up, only the one which is active on the current page.
So, I searched the documentation and found that in order to communicate between web page and add-on you have to use the message system as described here
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Communicating_with_the_web_page
To do so, my website has a JavaScript file which is loaded on every page. In this JavaScript I'm executing the following code
window.postMessage({type: 'FROM_PAGE', data: visibleCookies}, '*');
This piece of code is definitely executed, because I put a console.log before or after that statement, I can see that it's being logged.
Now, in my content script I want to listen to this by executing the following code
// experimentManager.js
console.log('testd');
window.addEventListener('message', (event) => {
console.log(event);
if (event.source !== window) {
return;
}
});
However, the console.log(event); is never executed. The listener is never activated. When I press the browser action so that the popup opens testd is logged into console, but still, the listener doesn't get any events. It's just not getting executed.
I don't know which files are relevant, but this is my manifest.json
// manifest.json
{
"manifest_version": 2,
"name": "My first addon",
"version": "1.0",
"description": "My first addon description",
"icons": {
"48": "icons/icon.png"
},
"browser_action": {
"default_icon": "icons/icon.png",
"default_title": "My first addon",
"default_popup": "popup/manage_experiment.html",
"browser_style": true
},
"permissions": [
"tabs",
"cookies",
"<all_urls>"
],
"content_scripts": [
{
"matches": ["*://*.mydomain/*"],
"js": ["experimentManager.js"]
}
]
}
And inside the pop-up script I'm executing this code among other things
browser.tabs.executeScript({file: "/content_scripts/experimentManager.js"})
.then(manageExperiments)
.catch(handleError);
which is probably the reason why the console.log('testd') gets executed, but nothing else?
What am I missing?
Alright, Im fairly new to making chrome extensions in general and I want to know how to intercept a tag and make a site run a different javascript file when the script is called. I have an extension made to test this out and try to figure it out myself, but it has not worked. When I type in the url of the file to replace, it redirects me to the file that I want it to, but the tag won't redirect to it or if it is, it's not running any of the code from the file. Please help?
content.js
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if( details.url == "http://www.bellum.io/js/attackCooldown.js" )
return {redirectUrl: "http://yourjavascript.com/1177311921/alertjs.js" };
},
{urls: ["*://www.bellum.io/*.js"]},
["blocking"]);
manifest.json
{
"name": "Simple Webrequest Test",
"version": "0.1",
"description": "Webrequest Test",
"manifest_version": 2,
"permissions": [
"<all_urls>","webRequest","webRequestBlocking","http://*/*"
],
"background": {
"scripts": ["content.js"],
"persistent": true
}
}
I've made a Chrome script that modifies a specific login Page. It works as expected, but I can see in the console that it is always active, although it should only be applied on the login site.
My manifest file:
{
"manifest_version": 2,
"name": "Login Enhancer",
"description": "Login without a hassle",
"version": "1.0",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"permissions": [
"https://*.examplesite.io/subdomain/portal/#/login"
],
"background": {
"scripts": [
"background.js"
]
}
}
background.js:
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.active) {
chrome.tabs.executeScript(null, {file: 'script.js'});
}
});
script.js
// delete useless Remember Me Function
document.querySelector('.remember-me').remove();
After I've logged in when I'm browsing on examplesite.io/subdomain the console says on every new page:
Uncaught TypeError: Cannot read property 'remove' of null
at script.js:2
Obviously there is no more remember-me button to remove. This has probably to do with the Listener in my background.js File. What is the correct listener so the script.js is only executed once on https://*.examplesite.io/subdomain/portal/#/login and not everywhere on https://*.examplesite.io?
For what you have shown in the question, the best way to do this is to use a content_scripts entry in your manifest.json to load your content script instead of using chrome.tabs.executeScript() to do so. Doing it as a content_scripts entry will inject the script once whenever the specified page is loaded. It is significantly less complicated than using chrome.tabs.executeScript() for the purpose of loading a script when a URL matches a certain page. In general, chrome.tabs.executeScript() should be used when the interaction with the user begins with the user clicking on a browserAction or pageAction button (which you are not using), or when you want more detailed control over when the script is injected other than always once for pages matching a specific URL, or URL pattern (which you don't need for what you are doing).
In your case, you are wanting to inject the script once, every time a specific URL is loaded. This is exactly the use case for which the content_scripts key in manifest.json exists.
Given that your background script was doing nothing other than loading your content script, using a content_scripts entry means you do not need a background script. In addition, you don't need to explicitly specify permissions for that particular URL. Your extension is implicitly given permissions for the URLs which match the content_scripts matches key.
You could do this by changing your manifest.json to:
{
"manifest_version": 2,
"name": "Login Enhancer",
"description": "Login without a hassle",
"version": "1.0",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"content_scripts": [
{
"matches": ["https://*.examplesite.io/subdomain/portal/#/login"],
"js": ["script.js"]
}
]
}
I want to change the url of current tab in chrome and reload the page.
I tried this code but not work, any help here will be greatly appreciated.
background.js:
function updateUrl(){
chrome.tabs.getCurrent(function (tab) {
var tabUrl = encodeURIComponent(tab.url);
var myNewUrl = tabUrl + "some text";
chrome.tabs.update(tab.id, {url: myNewUrl});
})
}
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
updateUrl();
}
})
manifest.json:
{
"name": "test",
"version": "0.1",
"manifest_version": 2,
"permissions": [
"tabs",
"webNavigation",
"http://www.example.com/*"
],
"background": { "scripts": ["background.js"] },
"content_scripts":
[
{
"matches": ["http://www.example.com/*"],
"js": ["background.js", "jquery.js"]
}
]
}
From your manifest it looks like you're trying to include background.js as a content script and a background script. chrome.tabs isn't available in content scripts so this won't work.
Depending on your specific use case, if you want to append a specific URL you could use the chrome.webRequest API to achieve this.
background.js:
chrome.webRequest.onBeforeRequest.addListener(function (details) {
return {
redirectUrl: details.url + "some text"
}
}, {
urls: ["http://www.example.com/*"]
}, ["blocking"]);
manifest.js:
{
"name": "test",
"version": "0.1",
"manifest_version": 2,
"permissions": [
"webRequest",
"webRequestBlocking",
"http://www.example.com/*"
],
"background": {
"scripts": [
"background.js"
]
}
}
This will add "some text" to the end of every request the browser makes to "http://www.example.com/*"
If you do want to use a content script to do this, then you'll need to take a look at message passing. This will allow you to make a call to the background script (which can use chrome.tabs) from your content script. Once the message has been sent the background page could then update the tab.
chrome.tabs.getCurrent is used to get the tab that this script is being made from. It will return undefined if called from a non-tab context (for example: a background page or popup view).
Since you have got the tab inside chrome.tabs.onUpdated handler, you could directly use it without the need to retrieve it again.
function updateUrl(tabId, tabUrl){
var myNewUrl = encodeURIComponent(tabUrl) + "some text";
chrome.tabs.update(tabId, {url: myNewUrl});
}
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
updateUrl(tab.id, tab.url);
}
});
From you manifest.json, background.js are used for both background page and content scripts, that's a bad design though not the root cause for this question.
It would be better if you could divide the logic into two parts, content script used for manipulating current web page DOM and background page used for extension related things.
I am a psychology student and I read papers very often. The university libraries provide the access to the databases but I need to use library search engine and log in every time. Quite annoying. I found a way to avoid jumping around the pages.
Here is the method:
I add "ezp.lib.unimelb.edu.au" to the end of the target database address after I found a paper in Google Scholar, then it will redirect to the library login page.
For example, the paper's address is:
http://www.sciencedirect.com/science/article/pii/S0006899315008550
I modified it as:
http://www.sciencedirect.com.ezp.lib.unimelb.edu.au/science/article/pii/S000689315008550
I want to create a Chrome Extension to finish this job on click (too lazy). I tried for hours but it does not work.
Here is what I have done:
I have three files in a folder:
First file: manifest.json
{
"manifest_version": 2,
"name": "Damn! Take me to the library!",
"description": "This extension automatically adds the 'ezp.lib.unimelb.edu.au' to the browser's address, allowing you to visit the databases bought by the library quickly",
"version": "1.0",
"browser_action": {
"default_icon": "unimelb.png",
"default_title": "Damn! Take me to the library!"
},
"background":{
"scripts":["popup.js"]
},
"permissions": [
"activeTab",
"tabs"
]
}
Second file: popup.js
function getCurrentTabUrlthenChangeIt(callback) {
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
var url = tab.url;
callback(url);
var newurl = url.replace('/',"ezp.lib.unimelb.edu.au/");
window.location.replace(newurl);
});
}
Third file: unimelb.png
When I load this folder into Chrome, it does not work.
It's the first time I use JS, anyone has any suggestions?
Thanks!
You can do this even without clicking. You can use the content script for this URL pattern so that your script gets injected to this page. Then you can send a message to the background script using chrome.runtime.sendMessage() and your listener will create a link you want here and then just reload the tab using chrome.tabs.update() with the new URL.
manifest.json
{
"name": "My extension",
...
"content_scripts": [{
"matches": ["http://www.sciencedirect.com/science/article/pii/*"],
"js": ["content-script.js"]
}],
...
}
content-script.js
chrome.runtime.sendMessage({loadURL: true});
background.js
chrome.runtime.onMessage.addListener(function(message, sender, response) {
if (message.loadURL) {
var newurl = sender.tab.url.replace("/", "ezp.lib.unimelb.edu.au/");
chrome.tabs.update(sender.tab.id, {url: newURL})
}
);
This is my first answer to the StackOverflow Community, I hope it helps.
Instead of making an extension, it would be a lot easier to make a bookmarklet which can be used in any browser...
Right click on the bookmark bar
Choose "Add page..."
Under "Name", enter whatever you want "Journal redirect" or whatever
Under "URL", copy and paste the following code (no spaces)
javascript:(function(){location.href=location.href.replace('sciencedirect.com/','sciencedirect.com/ezp.lib.unimelb.edu.au/');})();
Now when you're on the page, click that bookmark and it'll redirect you.
Update: Try this code in the URL for other domains
javascript:(function(){var%20l=location;l.href=l.origin+l.href.replace(l.origin,'ezp.lib.unimelb.edu.au/');})();
manifest.json
{
"manifest_version": 2,
"name": "Damn! Take me to the library!",
"description": "This extension automatically adds the 'ezp.lib.unimelb.edu.au' to the browser's address, allowing you to visit the databases bought by the library quickly",
"version": "1.0",
"browser_action": {
"default_icon": "unimelb.png",
"default_title": "Damn! Take me to the library!"
},
"background":{
"scripts":["background.js"]
},
"permissions": [
"activeTab",
"tabs"
]
}
background.js
//Wait for click
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {
"file": "popup.js"
}, function(){
"popup.js";
console.log("Script Executed ...");
});
})
popup.js
// Change the url to library when on click
var l=location;l.href=l.origin+l.href.replace(l.origin, '.ezp.lib.unimelb.edu.au');
They work well.
It's so cool to finish the first chrome extension. Thank for the help from Mottie.
Anyone looking to edit the url based on some pattern can use the chrome extension Edit Url by Regex
For example for the scenario in this post, while using the extension, you can provide the regex as http.*/science/ and the value as http://www.sciencedirect.com.ezp.lib.unimelb.edu.au/science/
and click submit. The url will get updated as expected.