I'm trying to work on a Chrome browser extension which does fun things on a contextmenu. The problem is, I can't get the JS files to load within the manifest.json content_scripts.
I don't receive an error, the files simply do not load.
The scripts are good, if I put them in my background page, they fire fine through that background page. The downside of that is it's restricted to only the background page.
{
"name": "Mini",
"description": "Mini",
"permissions": ["contextMenus","management","contentSettings","tabs","http://*/*","https://*/*","editable"],
"version": "0.1",
"manifest_version": 1,
"background_page": "mini.html",
"icons" : {"16" : "mini.png"},
"contexts" : ["link","tab","page"],
"content_scripts": [{"matches":["<all_urls>"],"js":["jquery172min.js","mini.js"]}]
}
I've tried all forms of matches, including "http://\*/\*", "https://\*/\*", "\*://\*/\*"
I've tried whitespaces, no whitespaces. I'm drawing a blank here.
Any help would be appreciated.
$(document).ready(function () {
alert("page is ready");
},true);
My apologies for that. This is a copy of the javascript/Jquery I'm using to test whether the extension has loaded or not. It's just a simple alert.
Content scripts cannot use the chrome.contextMenus API (in fact, these can only use some of the chrome.extension methods).
It's possible to apply match patterns to individual menu items, via chrome.contextMenus.create({title: 'Test', documentUrlPatterns: 'http://*/*'});.
Created menu items can also be modified (chrome.contextMenus.update) and removed (chrome.contextMenus.remove).
To communicate between a Content script and the background page, see Message passing.
Related
I am using the addons sdk/tabs api to inject content scripts into tabs when they are loaded like this:
tabs.on(ready, function (tab) {
var worker = tab.attach({
contentScriptWhen: 'end',
contentScriptFile: myAwesomeArrayOfScripts
});
...
Is there an easy way i can prevent the attach on domain patterns?
Most importantly i need to prevent it to work on about: domains like the new tab page of firefox.
Obviously i'm able to control execution with code like this:
if (tab.url.indexOf('about:') === 0) return;
But it looks very unclear solution compared to chrome declarative manifest, where you can have this:
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*", "file://*/*" ],
Is there anything similar? Firefox documentation is confusing... too many things and too many versions and articles from the past.
Use the sdk/page-mod module instead of attaching content scripts via tabs events if you want to declare a content script. Then you can use the includeand exclude keys to specify URL patterns (exclude was introduced in Firefox 32).
Using Firefox's tab.attach is similar to chrome.tabs.executeScript, which should only be used to imperatively execute a content script.
I want to ask is there ANY way or extension that can pre-highlight text within the iframe whenever a new window is opened containing iframe? I have tried many extension but none of them works.
I need to filter out content based on certain keywords and the content is within iframe. I can do it with CTRL+F but there are many keywords like 10-15 within each article to be found. So it makes my job very tough and time consuming. Few extensions that I have tried from chrome are multi highlighter, pearls, FF but none of them seems to work.
I also know the reason why these extension can't access content within the iframe i.e. due to cross origin policies.
But I also remember around an year ago I worked with chrome extension named 'Autofill' that could pre-select form elements whenever I opened new chrome window containing iframe.
So is there any work around?
You can set your extension permission to run content scripts in all frames as document at http://developer.chrome.com/extensions/content_scripts.html#registration by setting all_frames to true in the content scripts section of your manifest file. Adding to Google's example from that page, part of your manifest file might look like
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"],
"all_frames": true
}
],
...
}
You'll need to be careful since your content scripts are going to be inject into the page once for the parent page and one for each iFrame on the page. Once your content script is injected into all frames on the page you can work your magic with finding and highlighting text.
if (window === top) {
console.log('Running inside the main document', location.href);
} else {
console.log('Running inside the frame document', location.href,
[...document.querySelectorAll('*')]);
}
I am trying to understand chrome background pages. I managed to get background.js script running after cannibalizing on the of examples and it pops up with an alert box every time a user visits a page. However, when I take the same script and move it to a background.html file, I cannot seem to get the file to execute.
I have updated the the manifest file to a page (instead of script) and the extension loads fine. I have also tried playing around with either having the javascript in a script tag directly in the body or in a function as it is now that is called onload on the body or in the head.
Perhaps I don't understand the concept of what a background.html page is used for in a Chrome extension?
Manifest file:
{
"name": "Testing Extension",
"version": "0.2",
"background": { "pages": ["background.html"] },
"permissions": [
"tabs", "https://mail.google.com/*", "http://*/*, https://*/*"
],
"browser_action": {
"name": "Do some action",
"icons": ["icon.png"]
},
"manifest_version": 2,
"web_accessible_resources": ["injectImage.js", "background.html"]
}
injectImage.js
alert('Got Here');
'use strict';
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript(null, {file: "injectImage.js"});
});
chrome.browserAction.setBadgeBackgroundColor({color: [0, 200, 0, 100]});
var i = 0;
window.setInterval(function () {
chrome.browserAction.setBadgeText({text: String(i)});
i++;
}, 10);
background.html
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.8.0.min.js"></script>
<script src="injectImage.js"></script>
</head>
<body>
</body>
</html>
currently this code doesn't seem to do anything other than put an icon in the top right corner.
Your background is only one page and acts like a local server that can send and receive data between the content_scripts and default_popup or other extension pages.
For anyone starting out, look at each example's manifest version, which is defined in manifest.json. Version 2 has stricter security policies and inline javascript is invalid so copying sample v1 code and pasting it into background.html will not work anymore. All scripts need to be in an external file that can be included in an HTML file using the src attribute like <script src="main.js"></script>
My understanding is that you have four commonly used components for a basic extension:
DOM of the tab being viewed which can only be accessed by content_scripts
content_scripts is an array of javascript files identified in manifest.json that are sequentially injected directly into the tab's DOM. Apparently the JS variables and functions from the tab and your content_scripts cannot interact.
One background HTML page which Chrome either generates by concatenating an array of scripts OR is defined as one page, commonly named background.html.
{"browser_action" : {"default_popup" : "popup.html"}} is an optional user interface defined in manifest.json that is displayed when someone clicks your extension icon. The popup has no way to reach the tab's DOM so if the tab's content matters then it must be requested using Chrome messages like chrome.extension.sendMessage
Your background is defined either as one or more scripts:
"background": {
"scripts": ["background.js"]
},
Or as a page:
"background": {
"page": "background.html"
},
If you want to find out what is happening inside of the background then you can use console.log but in order to inspect the output you have to launch the inspector from the Extensions page. You can even see that the background file is always named "_generated_background_page.html".
You have a typo in your manifest file. Including a background page should look like this:
"background": {"page": "background.html"}
OR you can directly define js instead of defining a background page and referencing a script file in it (Inline scripts are not allowed as per Content Security Policy (CSP))
"background": {
"scripts": ["background.js"]
},
For version 3
background pages are replaced by service_workers in MV3
Replace background.page or background.scripts with background.service_worker in manifest.json.
{
"manifest_version": 3,
"name": "",
"background": {
"service_worker": "background.js"
}
}
One more gotcha not mentioned here. Doing <script src="myscript"/> doesn't work :P, you have to type it out completely with <script src="myscript"></script>. Took me a bit to figure that out.
I am currently writing a chrome extension so that I have a button on the bar and when clicked I wanted it to grab the URL of the currently selected tab and open a new tab as follows:
FixedURL/grabbedURL ex: lets say the currently opened page is "http://www.abc.com" and the fixed url I assign is "http://www.123.com" so the new URL I want to be opened will be http://www.123.com/http://www.abc.com
This way only the second part of URL opened in a new tab will change depending on the selected tab.
I already created a manifest.json and the icons, title, etc...
I then tried to use both background.html and popup.html but to no avail.
I also am kinda lost on the whole .js file thing and how to link all of them together.
The maximum I could achieve is having chrome open:
chrome://settings/extensions/obidbojnjbigokbpalmaacmgmecopond/title.url
when I clicked the button.
Here is my manifest.json
{
"name": "Circumvent",
"version": "1.0",
"description": "Opens new tab",
"browser_action": {
"default_icon": "111.png",
"default_title": "Circumvent!",
"popup": "main.html"
},
"icons": {
"48": "111.png"
},
"permissions": [
"tabs","notifications","http://*/*"
]
}
Any idea of what a sample code will look like and/or a brief clarification would be really awesome and very helpful!
Thanks in advance....
P.S. my first extension
You should add a background page and have it listen for clicks on your extension's browser action button:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.create({"url" : "http://www.123.com/" + tab.url})
});
(This code goes in your background page.)
You'll need to remove the popup line in your manifest, since the onClicked handler won't fire if there's a popup (and besides, you don't want a popup, you just need a button).
I'm writing a Chrome content script and when I inject this in the DOM:
"<a href='#' onclick='alert(\"Hi!\");return false;'>Hi</a>"
it works fine (the alert pops up when I click it), however if I create a function for the alert, it will say function undefined. Ex:
"<a href='#' onclick='alertPlease(\"Hi!\");return false;'>Hi</a>"
function alertPlease(x){
alert(x);
}
All my code is the same content script js file.
Do I have to place whatever code that can be used after loading in another js file in the background? I tried adding a background page with the 'alertPlease();' function, but that didn't work either.
Any hint will be greatly appreciated!
Thanks!
Content scripts run in an "isolated world." The webpage and content scripts can't see each other's JavaScript variables (although they can see the same DOM). When you add an onclick attribute within the DOM, the handler is created on the webpage's world, not your extension's world, so that code can't access the other function you defined. Instead of using an onclick handler, you should define your event listener in pure Javascript and then use addEventListener to attach it.
Isolated worlds are a feature to improve security and stability. Things are similar if you're developing within the Greasemonkey sandbox in Firefox.
Doing one of these today with manifest version 3, I learned:
I can't append a button to the page and use
<button type="button" onclick="myContentScriptFunction();">Call CS Function</div>
But, in the content script, I can do vanilla
let loadButton = document.createElement('button');
loadButton.innerText = 'Call CS Function';
loadButton.addEventListener('click', myContentScriptFunction);
document.querySelector('body').append(loadButton);
or jQuery
let loadButton = $("<button type="button">Call CS Function</button>")
loadButton.on("click", myContentScriptFunction)
$("body").append(loadButton);
And both worked as expected with all code in the content script
Info Source: Chrome Extension Samples Example
Specify any scripts in the manifest.json file under "content_scripts"
{
"name": "My Extension",
"content_scripts": [{
"matches": ["<all_urls>"],
"css": ["style.css"],
"js": ["jquery-1.5.js", "script.js"]
}]
}