Using sandboxed pages in chrome extensions - google-chrome-extension

Manifest version 2 of chrome extensions will no longer support use of eval or new Function on regular extension pages. My chrome extension uses a UI Framework (Kendo UI) on the options page that makes use of these mechanisms and therefore I'm looking for a solution.
According to this session from IO 2012 the idea is to put the corresponding page into a sandbox and load it into the extension via an iframe.
Here is a simplified example what I'm trying to do: https://gist.github.com/3058943
manifest.json:
{
"name": "Sandbox test",
"manifest_version": 2,
"options_page": "main.html",
"sandbox": {
"pages": [ "index.html" ]
}
}
main.html:
<html>
<head></head>
<body>
<iframe id="iframe" src="index.html" ></iframe>
</body>
</html>
index.html:
<html>
<head></head>
<body>
<h1>Inside the sandbox</h1>
</body>
</html>
When I load the options page in this example, I'm getting the error message:
Denying load of chrome-extension://fahdnpkbgfjkocogbjlljfbhnljcehoh/index.html. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by web pages.
I don't think that each sandboxed page is also supposed to be a web_accessible_resources.
But even when I try to define the sandboxed pages also as web_accessible_resources in the manifest file, then the sandboxed page gets loaded but use of new Function inside the iframe is still blocked.

The above described error message occurs on Chrome 20.0.1132.47.
I tested with the dev channel version 21.0.1180.15 and here the sandboxed iframe loads without problems.

Related

Chrome extension injection blocked by sandbox CSP

I am currently working on a Chrome extension which has a script that needs to access global properties of the page. To do so, I came up with an approach very similar to Method 1 in this Stack Overflow answer, the only difference being that instead of inserting a new script element directly in the document, the extension creates an ìframe with a src attribute pointing to a HTML document that already contains such a script tag. This approach is convenient in my use case as this newly created iframe and HTML document are also used for other purposes, but this is not relevant to the minimal reproducible example showcased here.
Here's the code responsible for creating the iframe, executed via a content script content.js:
const iframe = document.createElement("iframe");
iframe.setAttribute("src", chrome.runtime.getURL("inject.html"));
document.body.insertBefore(iframe, document.body.firstChild);
Here is a simplified version of inject.html:
<!DOCTYPE html>
<html>
<body>
<script src="inject.js"></script>
</body>
</html>
Here is inject.js (which in reality contains code accessing the global properties of the page):
console.log("Loaded!");
Finally, manifest.json sets both inject.js and inject.html as web accessible resources and injects content.js in all pages:
{
"name": "Example",
"version": "0.0.1",
"author": "Pyves",
"content_scripts": [
{
"all_frames": true,
"matches": [
"<all_urls>"
],
"js": [
"content.js"
]
}
],
"web_accessible_resources": [
"inject.html",
"inject.js"
],
"manifest_version": 2
}
The extension is in particular targeting GitHub raw pages (for instance https://raw.githubusercontent.com/PyvesB/JavAssembly/master/README.md), which happen to have a sandbox Content Security Policy. So far this setup has been working like a charm, however since updating my Chromium-based browsers from version 63 to 64 earlier this month, the extension is no longer fully functional. inject.js is blocked, with the following error message in the browser's console:
Blocked script execution in 'chrome-extension://xxxx/inject.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
Am I missing something here? How can I once again inject extension scripts in sandboxed frames in Chromium 64+?

open all the links on a web page with a single click on Chrome Extensions

I want open all the links on a web page with a single click on Chrome Extensions. I try for that وbut I did not get any results. please help me ...
my manifist.json file :
{
"name": "Open Links in New Tabs",
"version": "1.0",
"description": "open all link in page on new tabs with one click",
"background_page" : "background.html",
"browser_action": {
"default_icon": "icon.png"
},
"permissions":
["tabs"],
"manifest_version": 2
}
background.html file :
<!doctype html>
<html>
<head>
<script src="background.js"></script>
</head>
<body>
</body>
</html>
background.js file :
for(i = 0; i < document.links.length; i++)
{ chrome.tabs.create({active: true, url: document.links[i].href});}
Please explain any problems. thanks
When you access the document object in background.js, you're looking at background page, not the currently active tab.
To access the DOM contents of the open page, you will need a content script. It can then send a message to the background script (which has access to chrome.tabs) with the list of links to open.
Please take a moment to read this excellent overview of extension architecture. Also, read on messaging to pass the list.
Actually, if you're going to be injecting the script programmatically via chrome.tabs.executeScript, you can ditch messaging and just use the callback of executeScript.
As a side note, since you don't have any HTML in the background page, you can replace it with an auto-generated script page like this:
manifest.json
"background": {
scripts": ["background.js"]
},
in place of "background_page"
Lastly, consider minimal permissions that you need.
If your extension is supposed to trigger on click on the extension button (wrapped in a chrome.browserAction.onClicked listener), you can inject a script "for free" with activeTab permission, no need for tabs/host pemission.
Same goes to chrome.tabs.create, you don't need the mighty and scary "tabs" permission.
There are quite a few.
A background script doesn't have access to the page DOM of a tab. The only DOM it can access directly is the DOM of the background.html. You should use a content script and message passing.
background_page is an option of Manifest Version 1, you are using Manifest Version 2, for which the option is called background. Usually you provide the background.js directly as a script (see https://developer.chrome.com/extensions/background_pages). You should return after you implemented those suggestions

How to run content script code on an HTML file locally hosted by Google Chrome Extension? [duplicate]

I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}

Using LESS in a Chrome Extension

I'm attempting to use LESS in a tab created via a Chrome extension (chrome.tabs.create), but I'm getting a cross domain error ("NETWORK_ERR: XMLHttpRequest Exception 101"), referring to the LESS JavaScript file. I'm not clear on how to set up the permissions. Adding the LESS JavaScript file to "web_accessible_resources" doesn't seem to help. All other files, such as css and js files load fine. It seems I only receive this error from within the less source. Any ideas?
To explain my setup a bit more, the LESS JavaScript file and .less file are loaded in an HTML file something like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet/less" href="static/css/main.less">
<script src="/static/js/jquery-1.8.2.min.js"></script>
</head>
<body>
Whatever...
</body>
</html>
This html file is loaded in background.js like this:
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.create({url: 'mypage.html'})
});
The manifest file has permissions for "tabs" and "all urls", and loads background.js.
I'm not sure where you include the client side less.js compiler. See also: http://lesscss.org/#client-side-usage. Less.js is a client-side javascript. It seems the less.js loads from an other URL (domain) than your main.less file. This can be fixed by enabeling CORS, see: http://enable-cors.org/. On the domain where home.less has been installed, the server should send an Access-Control-Allow-Origin: * header.
less.js loads the less files with a XMLHttpRequests which supports CORS for most modern browsers see http://caniuse.com/#search=cors. More details can be found at http://www.html5rocks.com/en/tutorials/cors/
For development use less.js from local folder.
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
for release use any less compiler like lessc.

Does content_scripts matches "chrome-extension://*/*" work?

I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}

Resources