I would like to open a Chrome extension (acting as a background page) from a link on my website.
Things I have tried:
Make an a tag linking to the extension's main HTML page.
Sending the user to a page which does a 302 redirect to the HTML page.
Using Javascript to redirect the user, with window.location = ...
All of these do not work and open an about:blank page instead. The exception (which seems odd) is when I use strategy #2 and the link is opened from my desktop mail client.
Any ideas as to how this can be accomplished? Requesting the tabs permission is not possible in our case.
Try reading about message passing from a webpage to a background page of your extension (sounds like a thing you want to accomplish).
You need to add the taregt HTML file in the web_accessible_resources section of your manifest. E.g.:
Extension file-structure:
root-dir/
|_____manifest.json
|_____content.js
|_____myfile.html
content.js:
/* Append a link to the web-page's body */
var a = document.createElement("a");
a.href = chrome.extension.getURL("myfile.html");
a.target = "_blank";
a.textContent = "My HTML file";
document.body.appendChild(a);
manifest.json:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": true,
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": false
}],
"web_accessible_resources": ["myfile.html"]
}
Related
I know normally you just set the URL next to matches like - "matches": ["<all_urls>"], but I could not find any documentation of what the URL is for new tabs in firefox, I could only find that URL for chrome.
Heres my manifest.json -
{
"manifest_version": 2,
"name": "TestExt1",
"version": "1.0",
"icons": {
"48": "icons/icon1.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["TestExt1.js"]
}
]
}
I read another post on here about making a button opening a new tab using "_blank", so I tried setting my matches to "matches": ["_blank"], in the manifest file but that did not work. I have confirmed my issue is not with the javascript file because it works on every other URL.
How can I set my scripts to only make changes to new tabs?
Or is this something I have to make happen within the content script files themselves?
the default new tab page with the tiles is about:newtab
the default home page is about:home
for a blank page use about:blank
See the about:about page for available about pages.
It seeems that my content script document.URL always has the same value even when I click on a random <a href link.
In the below function in the content script, I have a function called performclick() which finds a random link on the current document, then clicks it.
Now shouldn't the next time I call performclick(), I get another document object? i.e. document of the currently focused active tab?
Like when I click a link on the main page and it opens a new tab with another website loaded in it, then I need the content script to give me the document of this new tab that has the clicked website link loaded in it.
But some how I always keep getting the document object of the same main page.
Please help
Manifest
{
"manifest_version": 2,
"name": "OSP Updater",
"version": "1.0.0",
"content_scripts": [{
"run_at": "document_start",
"js": ["content.js"],
"matches": [ "<all_urls>" ]
}],
"permissions": [
"background", "webRequest", "webRequestBlocking", "tabs", "<all_urls>"
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"web_accessible_resources": ["jsui.js"]
}
Content Script
window.onload = function () {
var elm = document.getElementById("my-container");
if (elm != undefined && elm != null) {
//alert("Main Page LOADED!!!");
}
}
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.clickit == "yes") {
performclick();
}
});
function performclick() {
//document.URL is always the same
var links = document.querySelectorAll("a");
if (links.length) {
var linkToClick = links[1];
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('click', true, true);
linkToClick.dispatchEvent(clickEvent);
}
}
Update #1:
Silly me, it turns out that I was sending a message from my background script to my content script via the first tab.
I did my clicking decision in the background script than sends a signal to the content script so that the content script can do the actual clicking.
So since I was sending message from the background script to the content script in the 1st tab, it lead the document object to always belong to the first tab (i.e. main page).
Hope this helps someone, always check if you are doing messaging then check its logic.
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.
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') {}
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.