cross domain request in injected script from chrome extension - google-chrome

I am writing a chrome extension that injects an iframe in the open tab and loads a url in it.The url to be loaded is not on the same domain as the opened page in the tab is.I am using following code :
--menifest.json--
"background" : {
"scripts": ["background.js"]
},
"permissions": [
"tabs", "http://*/", "https://*/"
]
--background.js--
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null,
{file:"logic.js"});
});
--logic.js--
var newdiv = document.createElement('div');
var iframe = document.createElement('iframe');
iframe.setAttribute('src','http://google.co.in');
newdiv.appendChild(iframe);
document.body.appendChild(newdiv);
this works only when the curent page is http://google.co.in and not on other pages.So I am hitting cross domain issues.but as far as I know,extensions can make the cross domain requests,then how to do it?Please help.

Google uses X-Frame-Options header, many websites make use of them as a best practise
There are three possible values for X-Frame-Options:
DENY
The page cannot be displayed in a frame, regardless of the site attempting to do so.
SAMEORIGIN
The page can only be displayed in a frame on the same origin as the page itself.
ALLOW-FROM uri
The page can only be displayed in a frame on the specified origin.
Google uses SAMEORIGIN Value, so this works only when the curent page is http://google.co.in.
So, you are not hitting cross domain issues and Yes extensions can make the cross domain requests.

Related

Chrome Automatically Highlighting Address Bar On New Tab Open [duplicate]

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?

Redirect a http request to a website from within an iframe with a Reverse Proxy in front of the site

I am using nginx as a Reverse Proxy in front of a website and intercept download/preview requests for the files stored on the site. The download requests come from within an iframe and if the user is not authorised, I redirect them to the logout page. But this does not take the main page (outside of the iframe) to the logout page. Any idea how to go about this?
If the user is not authorised you may want to send a message from the iframe to its parent. On receiving the message you would then redirect the parent window to the logout page. An example implementation is found here.
However this becomes much harder if you are not able to modify the iframe page's source. Since you are using nginx, one solution would be script injection using the ngx_http_sub_module module. This module replaces one string in the response with another. Note that this module is not included by default, you may need to build nginx with the --with-http_sub_module parameter. See the module page for more information, including an example.
The iframe needs the line:
parent.postMessage( "redirect", "http://www.your-domain.com" );
To inject this with nginx you might try:
location / {
sub_filter '</head>' '<script language="javascript">parent.postMessage( "redirect", "http://www.your-domain.com" );</script></head>';
sub_filter_once on;
}
The parent window would need the corresponding code:
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[ eventMethod ];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child window
eventer( messageEvent, function( e ) {
// normally if the message was meant to come from your domain
// you would check e.origin to verify that it's not someone
// sending messages you don't want
if ( e.data = "redirect" ) {
window.location.replace( "your-logout-url" );
}
}, false );
A more advanced solution might include the redirect url in the message; you could then handle the iframe redirecting to different locations.

Checking tab status in a chrome extension with a popup without the tabs permission

I'm currently trying to build my first chrome extension and I only need it to interact with pages of a few domains, so I want to avoid using the "tabs" permission since I understand it would have me request access to all information and all domains.
Instead I want to restrict myself to using the aciveTab permission and, if need be, a content script.
In short, what I want to do is display a "Subscribe button" in my extension's popup if the currently selected tab's url is of the domain(s) I'm interested in.
I can get the url of the page when it's created using a content script but I don't know how to make sure the user is still on that page when my extension is clicked.
I haven't managed to get anything done with activeTab.
Thanks in advance for any piece of advice you can give, I'll check on the answers (if any) after work.
A working example with the activeTab permisison:
In your popup.js
chrome.tabs.query({lastFocusedWindow: true, active: true}, function(tabs) {
if (tabs && tabs[0] && tabs[0].url) {
var match = tabs[0].url.match(/^[^:]+:\/\/([^\/]+)/);
if (match) {
var domain = match[1];
if (domain == 'stackoverflow.com')
alert('test');
}
}
});
Note:
You have to declare the "activeTab" permission in your manifest (of course).
JavaScript code must be in a standalone file and included in popup.html with <script src="..."></script>. Inline JavaScript is not allowed due to CSP.

Load remote webpage in background page: Chrome Extension

Is it possible to load a remote webpage into a background page using a chrome extension?
"background": {
"page": "local.html"
}
works, but
"background": {
"page": "http://...."
}
fails with the following error:
Could not load background page http://....
No, that's not possible. It is possible since Chrome 22 - see the bottom of the answer.
You can whitelist a https: resource in the manifest file file, so that your background script can manually be constructed. Make sure that you include a fallback resource in your extension, in the case that the network is down:
<!-- ... doctype etc ... (background.html) -->
<script src="https://..../external_bg.js"></script>
<script src="bg.js"></script>
Because of the Content security policy (CSP), you cannot run inline JavaScript, so you have to use external JS files. bg.js may look like:
if (!window.namespace_of_external_bg) {
// Fallback, by defining fallback methods or injecting a new script:
document.write('<script src="fallback_bg.js"></script>');
}
If you want to dynamically construct a page, avoid use of eval-like methods, because these are also forbidden by the CSP. You can write a template, and request external values to populate your template. localStorage can be used to cache variables. For an example on caching external resources, see Chrome extension adding external javascript to current page's html. This answer referred to Content scripts, so the exact method cannot be used to enable caching scripts (because you would need to use eval to load the script). However, the caching technique can still be used.
I have also tried to use the following method, which does not work (included in this answer, so that you don't have to try it yourself):
Create a Blob from the AJAX response, then use webkitURL.createObjectURL to create a temporary URL to load the resource.
// Modification of https://stackoverflow.com/a/10371025
// Instead of `chrome.tabs.executeScript`, use
// x.responseText or x.response (eg when using x.responseType='arraybuffer')
var blob = new Blob([x.responseText], {type: 'application/javascript'});
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var s = document.createElement('script');
s.src = url;
document.head.appendChild(s);
The previous code yields the following error:
Refused to load the script 'blob:chrome-extension%3A//damgmplfpicjkeogacmlgiceidmilllf/96356d24-3680-4188-812e-5661d23e81df' because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:".
Loading external resources in the background page
Since Chrome 22, it is technically possible (using the unsafe-eval CSP policy) to load non-https resources in the background page. This obviously not recommended because of security concerns (because it's susceptible to the MITM attack, for instance).
Here's an example to load an arbitrary resource and run it in the context of the background script.
function loadScript(url) {
var x = new XMLHttpRequest();
x.onload = function() {
eval(x.responseText); // <---- !!!
};
x.open('GET', url);
x.send();
}
// Usage:
loadScript('http://badpractic.es/insecure.js');
The unsafe-eval CSP policy must be specified.
As usual, to make cross-origin requests, the URL must be whitelisted in the manifest at the permissions section, or the server must enable CORS.
So, the manifest should at least contain:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": ["http://badpractic.es/insecure.js"],
"background": {"scripts": ["background.js"] }

Could I make a Google Chrome extension for chrome pages (downloads, extensions etc)?

I'd like to make a very simple extensions that slightly alters how the Downloads page looks. Changing the History page might be interesting too, but that's for later.
Is there a way to do that?
I tried making a Content Script extension, with "chrome://downloads" as match in manifest.json. Chrome won't allow that and responds with an error when packaging the extension.
Is there another simple way? It has to be simple, because changes would be simple, because all chrome:// pages are built with HTML, JS and CSS.
edit
After trying with background scripts a little...
I can't get chrome.tabs.executeScript to work! I added in background.html:
chrome.browserAction.onClicked.addListener(function(tab) {
alert(this.document.body.innerHTML);
alert(chrome.tabs.executeScript(null, {
code : "document.body.style.backgroundColor = 'red';"
}));
});
And I added this in manifest.json to add a (invisible) 'browser action button':
,"browser_action": {
/* "popup": "background.html",*/
"name": "Alter page"
}
The onClicked event fires both alerts (first is background.html's body, second is undefined). But the code (a string with document.body.style.backgroundColor = 'red';) doesn't execute! And ofcourse there's no debugging for extensions like this =)
Any tips anyone? I'm trying to get a hold of the tab's window.document (not background.html's window.document!). An injected script (that's what chrome.tabs.executeScript is supposed to do) should do that.
PS
I'm stealing from make_page_red/manifest and make_page_red/background.html
The 'extension' I have so far: http://hotblocks.nl/js/downloads.rar
EDIT
I found out what I want to achieve is possible with just CSS. I don't need to inject javascript. Does that make it easier? Does that make it possible? =)
According to this documentation, chrome:// URLs are an invalid scheme so they won't be matched:
A match pattern is essentially a URL that begins with a permitted scheme (http, https, file, or ftp), and that can contain '*' characters.
I would look into using override pages instead.
As requested, here's my extension that can at least load when chrome://downloads is loaded, although as I said, I don't think you can modify the page even if you know that's the page you're viewing.
manifest.json
{
"name": "Test",
"version": "0.0.1",
"background_page": "background.html",
"permissions": [
"tabs"
]
}
background.html
<script>
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
{
if (tab.status == "complete")
{
alert(tab.url);
// should alert 'chrome://downloads' on that page. You can
// check for this url here and then do whatever you want
}
});
</script>
Update: Since Chrome 31 there is an API for extensions that allows access to Chrome's downloads: https://developer.chrome.com/extensions/downloads
There's also an API that allows access to list and manage other installed extensions: https://developer.chrome.com/extensions/management
(Previous Answer)
Unfortunately, there's not currently an API for Chrome extensions to access information about a user's downloads. It's a widely requested feature, though, and there's some discussion among Chrome developers here: http://code.google.com/p/chromium/issues/detail?id=12133
Star the issue if it's a feature that you'd like to see, and you'll receive email updates.
As this page shows, there is no API to override the downloads page... However, there is a way to make a file you have made replace the chrome://downloads/ page whenever it is loaded using javascript in your background page...
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status === "loading"){
if(tab.url === "chrome://downloads/"){
chrome.tabs.update(tab.id, {url: "REPLACEMENT.html"});
}
}
});
Essentially what this does is - As soon as the page chrome://downloads begins loading (using the tabs.onUpdated API), the page is redirected to REPLACEMENT.html (Using tabs.update API)... There is no visible delay in the tab update
as this script is run before the chrome://downloads page begins loading... You can use a similar code in your file by pressing CTRL + U on the downloads page to view and copy its source code