I know there is a way to make JS work in chrome extension: just include a default_popup parameter in your manifest.json to specify an HTML page, then include the JS onto the HTML using <script>. But is there a way to get JS to do some stuff without having to open a HTML page (e.g. change the icon of the extension without a HTML popup having to be opened)?
Yes, that is called background page. You can create it without a .html file, but it will dynamically create one for you, called _generated_background_page.html.
You can can add following to your manifest.json to specify a background page:
{
"name": "My extension",
...
"background": {
"scripts": ["background.js"]
},
...
}
To view the background page go to chrome://chrome/extensions activate "Developer mode" and you can see the background page with developer tools:
For your example, changing the icon, you could use the chrome.browserAction.
Related
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'm developing a Google Chrome Extension which changes its icon depending of your IP localization. I face issues with refresh after an extension's icon change.
The icon is actually changing thanks to this command from my background.js file.
chrome.browserAction.setIcon ( { path: 'france.png' } );
Unfortunately, the setIcon command seems to be asynchronous. Icon change actually appears a few seconds after the change in the code. Is there a way to force chrome to refresh icons ?
Many chrome extensions seem to be able to control this but I couldn't find out how they manage this.
Here are more details :
In order to understand more clearly, I removed all my javascript code from different files, except the setIcon line. Here is Manifest line which declares my javascriptfiles.
"background": { "scripts": [ "jquery.min.js", "popup.js", "background.js"] },
popup.js: Now empty
background.js: Only these two following lines :
console.log ("I'm background script");
chrome.browserAction.setIcon({path: 'france.png'});
After extension reload with the extensions manager, I click on its icon. Chrome make the static html popup to appear and load background.jsfile. As a proof of it, the text immediately appears on the console window.
But I have to clic a few more times on the icon extension to see it changed by chrome.
I should do something wrong somewhere, but actually, as I removed everything, I have no clue where this delay could come from.
To instantly update the icon handle all relevant webNavigation events in the background script:
chrome.webNavigation.onCommitted.addListener(updateIcon);
chrome.webNavigation.onHistoryStateUpdated.addListener(updateIcon);
chrome.webNavigation.onBeforeNavigate.addListener(updateIcon);
function updateIcon(details) {
if (details.frameId != 0) {
return; // only update the icon for main page, not iframe/frame
}
chrome.browserAction.setIcon({
path: {19: "france-19.png", 38: "france-38.png"},
tabId: details.tabId
});
}
Your manifest.json should have webNavigation permission, of course.
I am writing a Chrome extension that adds a context menu item and performs an action when the user right-clicks a YouTube hyperlink.
My manifest file defines the background script as well as the javascript that is run when a link is clicked. Here are the relevant parts of my manifest.json file:
"background": {
"persistent": false,
"scripts": ["scripts/background.js"]
},
"content_scripts": [
{
"matches": ["*://*.youtube.com/*" , "*://youtube.com/*"],
"js": ["scripts/click.js"]
}
],
As you can see the background page uses the javascript file background.js and the context script uses click.js.
I am trying to debug click.js using the Chrome Developer Tools inspection utility but the problem I am running into is I can't figure out a way to get click.js to show up in the sources panel of the inspector.
If I go to the Chrome extensions page and click "Inspect views: background page" the inspector opens up but the only script shown is background.js.
If I right-click the extensions button (shown in the upper right) and select "Inspect popup" again I don't see click.js, only the javascript files that are loaded from within popup.html.
My question is, how do I debug javascript that is executed after a context menu click in Chrome? Should I "hack" it and force the script to always load click.js by adding it to the background page:
"background": {
"persistent": false,
"scripts": ["scripts/background.js", "scripts/click.js"]
},
If I did this, I could then see the script when inspecting the background page and set breakpoints, etc.
This seems like too much of a hack. There must be a more elegant way to inspect javascript files that aren't associated with the background page or any other html page (such as popup.html).
Is there a way to force the inspect window to load all javascript sources regardless of whether or not they are loaded with the page that is being inspected? Or is the inspection page limited to what is actually loaded, not the full set of scripts?
Thank you,
Clock
With Chrome 27, it seems that extensions that override Chrome's New Tab Page can't take focus away from Chrome's Omnibox like they used to in previous versions of Chrome.
Is there a new way to focus an input box in a New Tab Page, or has this functionality been disabled completely? :(
To test this, create an extension folder with three files:
1. manifest.json:
{
"name": "Focus Test",
"version": "0",
"minimum_chrome_version": "27",
"chrome_url_overrides": {
"newtab": "newTab.html"
},
"manifest_version": 2
}
2. focus.js:
document.getElementById('foo').focus();
3. newTab.html:
<html>
<body>
<input id="foo" type="text" />
<script type="text/javascript" src="focus.js"></script>
</body>
</html>
Then, when you load the extension and open a new tab, the input field does not get focused on the new tab page.
I have also tried adding the autofocus attribute to the input field, but no luck either. The extension's new tab page can't take focus away from Chrome's Omnibox.
Any ideas? Is this a bug or a new "feature"?
ManifestV3 update
This answer is adapted from https://stackoverflow.com/a/11348302/1754517.
This has been tested with both Manifest V2 and V3.
Tested in Google Chrome 99.0.4844.51 64-bit (Windows 10).
Replace the content of focus.js with:
if (location.search !== "?x") {
location.search = "?x";
throw new Error; // load everything on the next page;
// stop execution on this page
}
Add the autofocus attribute to the <input>.
Go to the Extensions page in Chrome and click the Load unpacked button. Choose the folder of your extension.
Open your new tab page. You might see a modal dialogue reading Change back to Google?. Click Keep it to keep your custom new tab page.
Inline Javascript - Manifest V2 only
If you're inlining the Javascript in the HTML file, then you'll need to take some extra steps:
After adding your inline Javascript to your HTML file, open DevTools (F12 key) and observe the error output in the Console. Example output you should see:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem:".
Either the 'unsafe-inline' keyword, a hash ('sha256-MK0Gypb4mkZTI11eCOtWT+mGYcJNpN5zccvhfeaRb6E='), or a nonce ('nonce-...') is required to enable inline execution.
Select & copy this hash.
Add a line to manifest.json to allow the JS to run, pasting in the hash you just copied between the single-quotes. E.g.:
"content_security_policy": "script-src 'self' 'sha256-MK0Gypb4mkZTI11eCOtWT+mGYcJNpN5zccvhfeaRb6E='"
Go to the Extensions page again. Remove the extension, then re-add it using the Load unpacked button.
Open your new tab page. Your extension should now autofocus on the <input>.
Note inlining only works with Manifest V2; Manifest V3 returns a failure message when attempting to load the extension (even with a properly formed "content_security_policy" object in manifest.json, to replace the Manifest V2 "content_security_policy" string):
Failed to load extension
File C:\path\to\extension
Error 'content_security_policy.extension_pages': Insecure CSP value "'sha256-...'" in directive 'script-src'.
Could not load manifest.
As per the Chrome Extension Documentation,
Don't rely on the page having the keyboard focus.
The address bar always gets the focus first when the user creates a new tab.
See reference here: Override Pages
Here's the solution for Manifest v3
chrome.tabs.onCreated.addListener((tab) => {
if (tab.pendingUrl === 'chrome://newtab/') {
chrome.tabs.remove(tab.id)
chrome.tabs.create({
url: '/index.html',
})
}
})
I saw a pretty old blog which updates the new tab conditionally. However, simply updating the tab does not steal the focus. I had to close the pending tab and open a new one.
Cons: An ugly chrome-extension://akfdobdepdedlohhjdalbeadhkbelajj/index.html in the URL bar.
I have a cheap work around that allows stealing focus from address bar focus. It's not for everyone. I do actually do use this because I want to control a new tab focus just that bad in my own custom new tab solution:
<script>
alert('Use enter key to cancel this alert and then I will control your focus');
document.getElementById('...AckerAppleIsCrafty...').focus()
</script>
USE CASE: I built my own HTML chrome custom tab that has a search input that custom searches my history and bookmarks the way I like it too.
Cash me focusing outside how bout dat?
In the following google chrome extension file why do i cannot use a jquery script inside myscript.js file,Is jquery not loaded inside myscript.js file, what changes should be done in manifest file to use jquery inside myscript.js
Manifest.json
{
"manifest_version": 2,
"name": "One-click Kittens",
"description": "This extension demonstrates a browser action with kittens.",
"version": "1.0",
"background": { "scripts": ["jquery-1.9.1.min.js","myscript.js"] },
"permissions": [
"tabs", "http://*/*"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
myscript.js
alert($("#extension-command-list").val()); //undefined
alert($("#extension-command-list").html()); //undefined
$(document).ready(function() {
alert("hello world"); //not seen
});
EDIT:
"background": { "scripts": ["jquery-1.9.1.min.js"] },
"content_scripts": [
{
"matches": ["https://*/*"],
"js": ["myscript.js"] or "js": ["jquery-1.9.1.min.js","myscript.js"]
}
],
The reason you are getting undefined is becaus you are not specifying a background page.
So.. the background page Chrome generates, looks just like
<html>
<head></head>
<body>
<script src="jquery-1.9.1.min.js"></script>
<script src="myscript.js"></script>
</body>
</html>
As you see there isn't any Element which can be selected, thats why your first too alert's return undefined.
Anyway, the alert("hello world") should be shown too, as the DOMContentLoaded or similar should be fired any way.
Could it be that you want to select Elements of an site you are visiting ?
If so, you should put myscript.js in an Content Script instead of a background page.
There you get access to the DOM of the site.
So the question is, what are you up to ?
If you actually want to select Elements in your background page, you have to specify one,
Looking at the background pages site shows you, its as easy as:
{
"name": "My extension",
...
"background": {
"page": "background.html"
},
...
}
Edit:
"default_popup" : "popup.html"
Refers to a Browser Actions Popup. A browser Action is used
[...] to put icons in the main Google Chrome toolbar, to the right of the address bar. In addition to its icon, a browser action can also have a tooltip, a badge, and a popup.
So
If a browser action has a popup, the popup appears when the user clicks the icon. The popup can contain any HTML contents that you like, and it's automatically sized to fit its contents.
To add a popup to your browser action, create an HTML file with the popup's contents. Specify the HTML file in the default_popup field of browser_action in the manifest, or call the setPopup method.
"background":"{...}"
A common need for extensions is to have a single long-running script to manage some task or state. Background pages to the rescue.
As the architecture overview explains, the background page is an HTML page that runs in the extension process. It exists for the lifetime of your extension, and only one instance of it at a time is active.
Also has a background script access to all parts of the Chrome Extension's Api. chrome.* if you have requested the permissions respectively
Now lets say, you want to for example extend the ContextMenu of chrome with some functionalities.
To do this, you first have create a contextMenuEntry in the background page.
And just like your background page has only one instance of it running at a time, and that for the lifetime of the extension, so should your contextMenuEntry only have one instance of it, which gets created when your extension runs and remains for the lifetime of your extension.
Now assume you want to display the currently selected text of the page you are visiting in one of you Menu Entries.
To do that, you need access to the chrome.contextMenus API Method but a contentscript is not allowed to use this.
To get this to work you need to pass a message with the selected text to the background page through e.g. chrome.extension.sendMessage
In the background page you can then update your existing contextmenuentry to display the selected text.
sry i couldn't think of a better example right now