Chrome extension - Document.getelementbyId(...) evaluating to null? - javascript

In console I can input document.getElementById('...') and get a value back. Or even .textContent and get the string I want.
Once I pop this into my chrome extension and run it, it evaluates document.getElementById('...') as null. What's up?
Manifest.json:
{
"name": "CSUF RMP",
"version": "0.1",
"manifest_version" : 2,
"description": "Displays professor ratings on icon click",
"background" : {
"scripts" : ["background.js"]
},
"browser_action": {
"default_icon": "icon16.png"
},
"content_scripts": [
{
"matches": ["https://mycsuf.fullerton.edu/*"],
"js": ["script.js"]
}
],
"permissions": ["<all_urls>", "*://*/*", "http://*/*", "https://*/*"]
}
Background.js:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "script.js"});
});
My script.js is literally what I posted at the top. The script is supposed to have access to the web page's DOM (thus I need a content script) and run it on click of the icon (hence the background.js)
I can get the page to run and show an alert or something, but that line isn't evaluating the page's dom, just null.

I think I know what is the problem here,
you are executing script.js just like a normal script, and a normal script can't interact with the page DOM, you can think about it as just runing a script from a file- it don't have the content script's privileges that way.
What you can do is open a new tab (with the url of the content script), and then pass to the content script at that new tab a message which tells him to run a specific function there.
You can test it without using message sending by setting the onload of the content script to something like: onload=alert(document.getElementById('...')); and than open a new tab from the background page: chrome.tabs.create({"url":"https://mycsuf.fullerton.edu"});
tell me how it goes :)
Edit: forgot to mention that you need the 'tabs' permission in your manifest file in order to open new tabs and test the thing out.

Related

Chrome extension that gets the DOM elements of the page user is visiting

I am new to extension development so I am making an extension which gets the product's name or price from the DOM of the page user is visiting. I made it but i am facing a problem that every single time i have to reload the page.
For example, If user is at flipkart.com say and visiting some product, then as soon as i click on specific product (of course the product's page is going to be loaded) i have to click on my extension icon then and only then it gets the data i need.
if the page is fully loaded and then i click on my extension icon i dont see the output i need, instead it prints nothing on console.
In other words, what should i do so that, i dont have to worry about clicking on the extension icon and the data i need, is automatically in my popup.html.
manifest.json
{
"manifest_version" : 2 ,
"name" : "myextension",
"version" : "1.0",
"browser_action":
{
"default_popup" : "popup.html"
},
"content_scripts": [
{
"matches": ["https://www.amazon.in/*","https://www.flipkart.com/*"],
"js": ["jquery-3.2.1.js","mycontentscript.js"]
}
],
"background" :{
"scripts" : ["background.js"]
},
"permissions": [
"*://flipkart.com/*","*://amazon.in/*", "tabs", "http://localhost/*", "webNavigation" //local host added
],
"content_security_policy": "script-src 'self' https://*/* default-src 'self' "
}
mycontentscript.js
var prdname=document.getElementsByClassName('_3eAQiD')[0].innerText; //just getting the name of prduct
myob ={
"prd" : prdname
};
var port = chrome.runtime.connect();
port.postMessage(myob); //sending product name to myscript.js
myscript.js
chrome.runtime.onConnect.addListener(function(port){
port.onMessage.addListener(function(res){
alert(res.prd); ///just alerting here
});
});
the main thing is it wont give me alert when the DOM is fully loaded .
In other words, i have to click on the extension icon, at the same time when my product page loads otherwise it wont work!
Can you please help me fix this???
You can run some code to save product page in background script. And later load it from you popup script (which i assume where myscript.js is laoded)
So this code goes to background script which is running all the time
//background.js
var productName
chrome.runtime.onMessage.addListener((request) => {
switch (request.command) {
case "saveProduct":
productName = request.productName
break
case "loadProcut":
return productName
break
}
})
The following to content script that is loaded when user opens the page specified in manifest.json
// mycontentscript.js
var prdname=document.getElementsByClassName('_3eAQiD')[0].innerText
chrome.runtime.sendMessage({
command: "saveProduct"
productName: prdname
})
And finally this loads the product name from the popup js
// myscript.js
chrome.runtime.sendMessage({
command: "loadProcut"
},function(productName){
console.log(productName)
alert(productName)
})

Chrome extension to load the script without clicking on icon

Hello all i want to load the script whether or not user clicks on my extension icon
This is my extension it works great but i want it to work without making the user click on the icon to load the scripts ..
Here is the code .
{
"name": "Injecta",
"version": "0.0.1",
"manifest_version": 2,
"description": "Injecting stuff",
"background":
{
"scripts": ["jquery.js","background.js"]
},
"browser_action": {
"default_title": "Inject!"
},
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
This is my background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript({
file: 'jquery.js'
});
chrome.tabs.executeScript({
file: 'inject.js'
});
});
i just want the extension to load all the scripts with the page load. currently user has to click on the icon to load the scripts..
What executeScript does is basically creating a Content Script dynamically. This is called Programmatic Injection.
An alternative method of working with content scripts is specifying them in the manifest. This achieves exactly what you're asking: content scripts are executed automatically when the page is loaded.
"content_scripts" : [
{
"js": ["jquery.js", "inject.js"],
"matches": ["*://*/*"]
}
],
Adjust the matches parameter to only include match patterns for pages you want it to run on.
Make sure to check out the documentation of run_at parameter if you need to fine-tune when injection happens.
if (typeof jQuery === 'undefined') {}

Using chrome.tabs.executeScript when the tab changes URL or reloads

I am building a Chrome Extension and I want to inject and run Javascript code into a tab.
For example :
chrome.tabs.query({active: true, lastFocusedWindow: true}, function(selectedTab) {
chrome.tabs.executeScript(selectedTab[0].id, {code: code_});
});
With the code_ variable being :
$('#gbqfq').val('test');
$("#gbqf").submit();
$('#rso > div.srg > li:nth-child(1) > div > h3 > a').click();
This simple script is meant to be executed on google.com and should type and search "test" and click on the first result.
The problem is that after submitting the request, the tab changes its URL and thus loads another page. And it seems that when the page loads, all the scripts injected by chrome.tabs.executeScript disapears.
Is there a way to run a single script through different pages in the same tab ?
My extension should allow the user to run his own script, so it is complicated (maybe impossible?) to know in advance at which point of the script the tab is expected to reload (in order to use several chrome.tabs.executeScript calls).
Here is the manifest.json of my Extension, I am only using a popup (no background, no content_scripts) :
{
"manifest_version": 2,
...
"options_page": "options.html",
"permissions": [
"storage",
"unlimitedStorage",
"tabs",
"windows",
"http://*/*",
"https://*/*"
],
"browser_action":
{
"default_popup": "popup.html"
}
}
No, you cannot run the same script after a tab navigates away, since the JavaScript context in which the script lives is torn down.
So you will need to inject a script again after the page loads.
You probably want to do something along these lines:
Inject your submitting script and save the tab ID.
Initiate a submit.
Listen to chrome.tabs.onUpdated filtered by tab ID above and status "complete".
Check that the URL is the one you expected, then inject your data-gathering script.

chrome extension's content script not working in google, youtube pages

I'm trying to create a chrome extension. When the user clicks my extension's icon (browserAction) the content script appends an extra div to the body of the open page(current tab). It works fine in all the sites except google's search page and youtube. I'm not getting any error message or anything. It simply wont give any response.
This is my code in content.js:
alert('sdsd');
$('body').append("<div id='popup'>My extension name</div>");
I've put the alert for testing purpose. So when extension is toggled it should show an alert message followed by appending the div to body, ideally! But it wont for these 2 sites.
Any idea what could be going wrong here?
manifest
{
"name": "My first extension",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"content_scripts": [{
"all_frames": true,
"css": ["style.css"],
"matches": ["http://*/*","https://*/*"]
}],
"permissions": [ "tabs","http://*/*" ],
"browser_action": { "name": "test" },
"manifest_version": 2
}
background.js
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.executeScript(null,{file:"jquery.min.js"},function(){
chrome.tabs.executeScript(null,{file:"content.js"});
});
});
In Youtube's page, $ is overwritten and isn't jQuery. It's
bound: function ()
{
return document.getElementById.apply(document, arguments)
}
So your code makes an exception as there document.getElementById('body') is undefined.
You should try using noConflict().
EDIT :
Why aren't you simply listing jQuery.min.js and your content.js in the content_scripts instead of injecting them programmatically. This would avoid conflicts.
EDIT 2 :
Now that you use content scripts, you should use communication as described here to send from background.js to the content script the instruction to show the alert.
EDIT 3 :
Another solution would have been to use programmatic injection (as you initially did) and not use jquery, $('body').append("<div id='popup'>My extension name</div>"); being translated in vanilla JS to
var div = document.createElement('div');
div.id = 'popup';
document.body.appendChild(div);
document.getElementById('popup').innerHTML = "My extension name"​;​
But it's generally cleaner (and requires less permissions) to avoid programmatic injection.

Injecting Redirect JS in Chrome extension. Fail! :(

I'm trying to generate an extension that keeps my brother of facebook. So I decided i'll redirect all facebook links to google for starters.
This is how i went about it.
My manifest.json file :
{
"name": "FBRehab"
"version": "1.0",
"description": "Redirect FB",
"permissions": [
"tabs", "http://www.facebook.com/*", "https://www.facebook.com/*"
],
"browser_action": {
"default_icon": "icon.png",
"background_page": "background.html"
},
]
}
My background.html :
<html>
<head>
<script>
chrome.tabs.executeScript(null, { file: "jquery.js" }, function() {
chrome.tabs.executeScript(null, { file: "try.js" });
});
</script>
</head>
and try.js
<head>
<script language="JavaScript">
var time = null
function move() {
window.location = 'www.google.com'
}
</script>
</head>
Yet, it does not redirect. I've tried directly injecting the try.js using content scripts too.
Please help me.
Thanking you.
Ashar :)
Remember a Background Page runs exactly once in Chrome, it is a single long running script that runs exactly once.
Basically what your code does now is that once your browser loads, it will inject jquery and try Content Scripts to the current tab. You have no tabs that are currently loaded (which it will fail unless you have it auto load a tab). Then it will not do anything anymore because the Background Page runs exactly once!
What you need to do instead is use a Content Script which should be defined as follows:
// Only execute in the top window, we don't want to inject the iframes.
if (window == top) {
window.location = 'www.google.com'
}
In your manifest, you will have the following:
{
"name": "No more Facebook extension",
...
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["redirect.js"]
}
],
...
}
I think you want to use a content script instead of a background page. You can specify that your content script should only run on specific web pages.
Do you ever call move()? Doesn't look like it to me, but I've never developed a Chrome extension before... so I'm not sure if it is ever called automatically.

Categories