I'm essentially just trying to get the current tab url if they're on youtube.com. I keep getting an error from the script.
Error:
Uncaught TypeError: Cannot call method 'getSelected' of undefined
Manifest
{
"name": "YouTube Fix",
"version": "0.0.1",
"manifest_version": 2,
"description": "Fix some of the annoying little things in YouTube.",
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"content_scripts": [{
"matches": ["http://www.youtube.com/*"],
"js": ["background.js"],
"run_at": "document_start"
}],
"permissions": ["tabs"]
}
Background.js
//this is what is giving me the error:
chrome.tabs.getSelected(null, function (tab) {
myFunction(tab.url);
});
function myFunction(tablink) {
if (tablink == "http://www.youtube.com") {
window.location = "http://www.youtube.com/feed/subscriptions/u";
}
document.getElementById("comments-textarea").disabled = false;
}
The following forks fine, no need for chrome.tabs.getSelected(null, function (tab) {}),because your page always runs for "matches": ["http://www.youtube.com/*"],;
More over add this condition to your code if(document.getElementById("comments-textarea") != null){
Working background.js
if (window.location == "http://www.youtube.com") {
window.location = "http://www.youtube.com/feed/subscriptions/u";
}
if (document.getElementById("comments-textarea") != null) {
document.getElementById("comments-textarea").disabled = false;
}
manifest.json
{
"name": "YouTube Fix",
"version": "0.0.1",
"manifest_version": 2,
"description": "Fix some of the annoying little things in YouTube.",
"content_scripts": [{
"matches": ["http://www.youtube.com/*"],
"js": ["background.js"],
"run_at": "document_start"
}],
"permissions": ["tabs"]
}
Let me know if you need more information.
You're running background.js as a content script rather than a background or event page, and https://developer.chrome.com/extensions/content_scripts.html says that "content scripts have some limitations. They cannot … Use chrome.* APIs (except for parts of chrome.extension)"
Instead, you should put something like
"background": {
"scripts": ["background.js"],
"persistent": false
},
into your manifest. See https://developer.chrome.com/extensions/event_pages.html for more details.
Quoted from here: https://groups.google.com/a/chromium.org/forum/?fromgroups=#!topic/chromium-extensions/A5bMuwCfBkQ
chrome.tabs.getSelected() is deprecated. The following page explains
how to use chrome.tabs.query instead:
http://code.google.com/chrome/extensions/whats_new.html#16 The relevant bit of text is:
"""
The methods getAllInWindow() and getSelected() have been deprecated.
To get details about all tabs in the specified window, use
chrome.tabs.query() with the argument {'windowId': windowID}. To get
the tab that is selected in the specified window, use
chrome.tabs.query() with the argument {'active': true}.
"""
chrome.tabs.getSelected is deprecated. Use chrome.tabs.query instead:
chrome.tabs.query({
"active": true
}, function(tab){
console.log(tab[0]); //selected tab
});
Also, content scripts can not access chrome.tabs APIs. Do this:
chrome.extension.getBackgroundPage().chrome.tabs.query(...
(This might not work. Not tested.)
Related
I'm trying to set up a background script fetching data from content periodically and write it to a file (kind of webpage scraping)
Unfortunately I got stuck at the very beginning:
Background sends a message to content and the callback is called but the parameter is not passed correctly, it's "undefined" whatever I try...
Manifest:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches" : ["<all_urls>"],
"js": ["content.js"]
}],
"browser_action": {
"default_title": "Test Extension"
},
"permissions": ["activeTab"]
}
content.js
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.text === 'report_back') {
sendResponse({data: "goodbye"});
}
});
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.sendMessage(tab.id, {text: 'report_back'}, function(response) {
console.log(response.data);
});
});
If you are getting:
Error in event handler for (unknown): TypeError: Cannot read property 'data' of undefined at ...
I'm guessing you are clicking on the extension icon when you are in a tab like chrome://extensions
Try clicking on it from any other website and it should work.
I have a very simple chrome extension, where I'm trying to pass a message from the background script to the content script. But chrome.runtime is undefined.
Here's literally all the code, as you can see there's almost nothing to it. In the content script, runtime is undefined.
Background Script:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.runtime.sendMessage({action: 'someAction'},
function(response) {
console.log('Response: ', response);
});
});
Content Script:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
sendResponse({
user: 'user'
});
});
manifest.json
{
"manifest_version": 2,
"name": "My Extension",
"version": "1.0",
"description": "Some stupid extension",
"browser_action": {
"default_icon": "icons/MyExtensionIcon.png"
},
"icons": {
"48": "icons/MyExtensionIcon.png"
},
"permissions": [
"tabs",
"storage",
"https://*/",
"http://*/"
],
"content_scripts": [
{
"matches": ["*://*.twitter.com/*", "https://twitter.com/*"],
"js": ["js/content.js"]
}
],
"background": {
"scripts": ["js/background.js"],
"persistent": true
},
"web_accessible_resources": [
"js/*",
"css/*"
]
}
Other Info:
Chrome Version 58.0.3029.110 (64-bit)
Installing my extension as an
"Unpacked extension" with developer mode
Ok I figured it out. It's absolutely stupid, but it appears this is simply a Heisenbug. By adding a breakpoint, or debugger statement, it causes that value to be undefined. Maybe a chrome bug?
I swear, every day Chrome feels more, and more like Internet Explorer.
I've an extension which need to keenly keep an eye on the URL of the very active tab in the browser [chrome]. Currently, I've been able to track those URL's which user load/reload from start. But if there is a tab change, the content script doesn't send message to background script and get back anything.
In fact I want to reload content.js script on tab change of user as well.
Here's what I've done till now:
CONTENT.JS:
// Code here....
chrome.extension.sendMessage({ wants: 'URL' }, function(res) {
var urlResponse = res.url;
});
// Code here....
Works pretty well, but this content.js doesn't fire on tab change. Instead it fires when a document is changed in same tab (like visiting new link, etc)
BACKGROUND.JS:
chrome.extension.onMessage.addListener(
function(script, sender, sendResponse) {
if (script.wants == 'URL') {
sendResponse({ maskedURL: sender.tab.url });
}
}
);
MANIFEST.JSON:
{
"manifest_version": 2,
"name": "NAME HERE",
"description": "DESC HERE",
"version": "1.1",
"options_page": "options.html",
"browser_action": {
"default_title": "NAME",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"icons": { "16": "icon.png",
"48": "icon.png",
"128": "icon.png" },
"permissions": [
"storage",
"<all_urls>",
"tabs"
],
"content_scripts": [
{
"matches": ["http://*/*","https://*/*"],
"js": ["content.js"]
}
],
"web_accessible_resources": [
"bg.png",
"*.woff",
"*.woff2"
],
"background": {
"scripts": ["background.js"]
}
}
Thank you!
EDIT: Xan please have a look:
Could not understand your question properly but I will try to clarify to the best of my knowledge.
content.js is run once when a new page is opened or an existing page is refreshed.It cant access the details of the currently active tab.
If you want to know about any details of the tabs,use chrome.tabs API in background.js
chrome.tabs.onActivated.addListener(activeInfo){ //Fired when an active tab is changed
chrome.tabs.query({'active':true,'currentWindow':true},function(array_of_tabs){//Gives details of the active tab in the current window.
alert(array_of_tabs[0].url);
});
I have a context menu option and when it is selected I want insert some HTML. I have tried doing this
var div=document.createElement("div");
document.body.appendChild(div);
div.innerText='test123';
But it's not working for me.
Note I am trying to avoid using jQuery.
Here you can research how to create an extension and download the sample manifest.json.
Content Scripts can be used to run js/css matching certain urls.
manifest.json
{
"name": "Append Test Text",
"description": "Add test123 to body",
"version": "1.0",
"permissions": [
"activeTab"
],
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["content-script.js"]
}
],
"browser_action": {
"default_title": "Append Test Text"
},
"manifest_version": 2
}
content-script.js
var div=document.createElement("div");
document.body.appendChild(div);
div.innerText="test123";
The above will execute the content-script.js for all urls matching http://*/* where * is a wildcard. so basically all http pages.
Content scripts have many properties which can be found in the link above.
Programmatic injection can be used when js/css shouldn't be injected into every page that matches the pattern.
Below shows how to execute the js onclick of the extension icon:-
manifest.json
{
"name": "Append Test Text",
"description": "Add test123 to body",
"version": "1.0",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Append Test Text"
},
"manifest_version": 1
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
code: 'var div=document.createElement("div"); document.body.appendChild(div); div.innerText="test123";'
});
});
This uses the executeScript method, which also has an option to call a separate file like so:-
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
file: "insert.js"
});
});
insert.js
var div=document.createElement("div");
document.body.appendChild(div);
div.innerText="test123";
I've been searching all over SO and reading through google docs but I can't seem to find a solution.
My Chrome extension is injecting a content script and I want to set an onRequest.listener in order to sendRequests to the content script. This is the script I used to for the onRequest.listener. The problem is I keep getting this error for some unknown reason.
Error Message:
Uncaught TypeError: Cannot ready property 'onRequest' of undefined
contentscript.js line 1;
Here's the relevant code...
Manifest.json
{
"name": "Injector Extension",
"version": "1.0",
"manifest_version": 1,
"icons": { "128": "icon.png" },
"browser_action": {
"default_icon": "icon.png",
"default_title": "Injector Extension",
"default_popup": "popup.html"
},
"options_page": "options.html",
"background": {
"page": "background.html"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"unlimitedStorage"],
"content_scripts": [{
"matches": [" (injector specific url) "],
"js": ["contentscript.js"]
}],
"web_accessible_resources": ["js/script.js"]
}
content script
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "fromPopup") {
// Send JSON data back to Popup.
sendResponse({data: "from Content Script to Popup"});
} else {
sendResponse({}); // snub them.
}
});
popup
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "fromPopup", tabid: tab.id}, function(response) {
console.log(response.data);
});
});
chrome.extension.onRequest.addListener works only in extension context. It won't run inside a content script.
chrome.extension.sendRequest works in content script context
Update accordingly and will work.
Edit: Exemplifying simple message passing:
Extension script:
chrome.extension.onRequest.addListener(function(r,s,sr){
if(r==='HELLO') return sr.call(this,'BACK AT YOU');
});
Content script:
chrome.extension.sendRequest('HELLO', function(data){ alert(data); });
// will alert "BACK AT YOU"