This question already has answers here:
Get the current URL with JavaScript?
(28 answers)
"Cannot read property of undefined" when using chrome.tabs or other chrome API in content script
(4 answers)
Closed 1 year ago.
I am working on a chrome extension. My manifest.json contains the entry
"content_scripts": [
{
"matches": ["file:///C:/Example/*"],
"css": ["my-styles.css"],
"js": ["content-script.js"],
"run_at": "document_end"
}],
In the file content-script.js I need to get the url address of the active tab. I tried to define a variable, but it raises error "Uncaught ReferenceError: tabs is not defined"
var url = tabs[0].url;
I also tried defining a function to get the url, but it is also not working, raising error "Uncaught TypeError: Cannot read properties of undefined (reading 'query')"
function get_base_url() {
var base_url = '';
chrome.tabs.query({
active: true,
lastFocusedWindow: true
}, function(tabs) {
base_url = tabs[0].url;
return base_url;
});
}
I found out I can use document.URL. My mistake was that I previously tried with document.url and the expression is case sensitive
Related
Im trying to send message to content.js from background.js when extension icon is clicked.
Background.js :
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.query({active : true, lastFocusedWindow : true}, function (tabs) {
var CurrTab = tabs[0];
chrome.tabs.sendMessage(CurrTab, 'run');
})
})
Content.js :
chrome.runtime.onMessage.addListener(function(){
view();
})
I have this error in background.js, i don't know why.
Error handling response: TypeError: Error in invocation of
tabs.sendMessage(integer tabId, any message, optional object options,
optional function responseCallback): No matching signature.
What im doing wrong?
In Background.js change the following :
chrome.tabs.sendMessage(CurrTab, 'run');
to
chrome.tabs.sendMessage(CurrTab.id, 'run');
As told by wOxxOm in the comments.
Secondly make sure that in manifest.json file you have specified the url of the website(where content script needs to be injected) in content_scripts/matches tag.
I just started with developing a Firefox add-on. It works fine in Firefox so I'd like to make it "compatible" to a Coogle Chrome extension.
For this I inject Mozilla webextension-polyfill and basically the add-on also runs in Chrome. There is one thing however I can't get to work...
In Firefox a notifcation is shown to the user if the content script sends a message which is received by the background script. Running this in Chrome results in the following exception:
Uncaught (in promise)
{message: "The message port closed before a response was received."}
callbackArgs # VM18 browser-polyfill.js:630
sendResponseAndClearCallback # VM29 extensions::messaging:417
disconnectListener # VM29 extensions::messaging:441
EventImpl.dispatchToListener # VM19 extensions::event_bindings:403
publicClassPrototype.(anonymous function) # VM25 extensions::utils:138
EventImpl.dispatch_ # VM19 extensions::event_bindings:387
EventImpl.dispatch # VM19 extensions::event_bindings:409
publicClassPrototype.(anonymous function) # VM25 extensions::utils:138
dispatchOnDisconnect # VM29 extensions::messaging:378
I can tell that this comes from the webextension-polyfill but I cannot find a way so that the notification is also shown in Chrome.
Here are the relevant code snippets...
manifest.json
{
"manifest_version": 2,
// ...
"background": {
"scripts": [
"lib/browser-polyfill.js",
"background-script.js"
],
"persistent": false
},
"options_ui": {
"page": "settings/options.html"
}
}
background-script.js
function notify(message) {
if (message.copied) {
browser.notifications.create({
"type": "basic",
"title": "Notifaction title",
"message": "Hello, world!"
});
}
}
browser.browserAction.onClicked.addListener(() => {
browser.tabs.executeScript({file: "lib/browser-polyfill.js"});
browser.tabs.executeScript({file: "content-script.js"});
});
browser.runtime.onMessage.addListener(notify);
content-script.js
browser.storage.local.get({elementId: ""})
.then(() => {
browser.runtime.sendMessage({copied: true});
});
There are two problems here...
Issue 1
The onMessage handler needs a return true. Only then the polyfill seems to be able to handle the messages correctly.
Issue 2
This seems to look like a bug in the polyfill. In Chrome the iconUrl option is required when creating a notification whereas it is optional in Firefox.
If I apply these two things the notification works in Firefox and Chrome.
I am developing a chrome extension that requires corss domain XHR. So I need to make get requests to a server and get some text out of it. I am currently loading the unpacked extension from my computer. The script doesn't seem to be working.
Here is my manifest.json:
{
"name": "My extension",
"version": "1.1",
"manifest_version": 2,
"description": "Testing http requests",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"http://*/"
]
}
And here is the script that performs the get request (from this tutorial):
function showresponse(){
var query = document.getElementById("query").value;
var url = "http://blah.com/search.php?term="+query;
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
console.log("hello world");
document.getElementById("container").innerHTML = xhr.responseText;
}
}
xhr.send(null);
}
The id's etc are set according to my popup.html file and that's set up correctly and it includes this js file containing the showresponse() function definition.
I also tried packaging my extension to get a myextension.crx file after reading this question and I tried opening the file in my browser, but chrome doesn't allow installing the extension from localhost or unknown servers for security reasons I suppose.
My question is how do I make a cross domain XHR in a chrome extension?
Also the response from the get request to the server is actually an html document and I need to filter some text out of the returned html tags. As I am making a query to a php script, can I receive and therefore play around with the html output if I make a get request in javascript?
How do I go about acheiving this?
Trying to set and get values in my Chrome extension using local storage. Don't know what I did, but it's no longer working.ยจ
In manifest I have:
"permissions": [
"tabs", "http://*/*", "https://*/*", "storage"
],
This is the complete js, which sets a value and then tries to read it:
chrome.storage.local.set({'userid': "foo"}, function (result) {
chrome.storage.local.get('userid', function (result) {
alert(userid.result);
});
});
The alert says "undefined", not "foo" as expected.
The js is executed when i go to a certain page, specified in manifest for "content_scripts".
Doh, I figured it out. It should be:
alert(result.userid);
(reverse userid and result)
I've written the following script to change the URL of a tab in Chrome, but can't figure out how to get it to automatically run on every page.
var nytimes = /.*nytimes\.com.*/;
var patt = /(&gwh=).*$/;
function updateUrl(tab){
if(tab.url.match(nytimes))
{
var newUrl = tab.url.replace(patt,"");
chrome.tabs.update(tab.id, {url: newurl});
}
}
chrome.tabs.onUpdated.addListener(function(tab) {updateUrl(tab);});
I put that into my background page, but it isn't working. Do I need to put the code somewhere else to get it to run?
I strongly suggest you read about content scripts. They are exactly what you're looking for but you need to understand that they have limited access to the Chrome.* API, so you'll have to use message passing in order to use your current functionality. However, by using content scripts you can probably make this simpler using one of my proposed solutions.
Solution 1
Assuming you want to send the redirect to the same URL every time, you can easily configure your extension to only run your content script on the NY Times site. For example;
Content Script: content.js
location = 'http://example.com';
Solution 2
However, if the redirect URL can vary you many want to abstract that logic in to your background page. For example;
Content Script: content.js
// Or you can pass a more specific section of the URL (e.g. `location.pathname`)
chrome.extension.sendRequest({href: location.href}, function(data) {
location = data.url;
});
Background Page: background.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
sendResponse({
url: getUrl(request.href) // TODO: `getUrl` method containing your logic...
});
});
Important!
Regardless of which approach you go for you will also need to request permission to run the content script on the target site in your manifest file.
Manifest: manifest.json
{
...
"content_scripts": [
{
"js": ["content.js"],
"matches": ["*://*.nytimes.com/*"],
"run_at": "document_start"
}
],
...
}