Chrome extension Background and content script posting message - javascript

I have a content script which includes jquery ui component and i want to send data to my server with http post. However i have come to realize that you can not send http post message to a https website or vice versa. If i send my message to the background script and post from there will i have a problem about it? Will it make a difference if the site is http or https? If it makes a difference how can i get this done?

Yes, you can use http POST, as well as any other http method (e.g., GET, PUT, PATCH), in a content script -- as well as a background script, for that matter.
However, in both cases, the URL to which you're sending your request must be declared in your extension's permissions. You do this in the manifest. For example, if you would like to send http requests to http://www.some-domain.com, you must add that URL (or a pattern matching that URL) to the permissions array of your manifest:
{
...
"permissions": [
"http://www.some-domain.com/*"
],
"name": "Test",
"manifest_version": 2,
"version": "0.0.0"
}
You can add wild cards to your URL permission patterns; thus, if you'd like to match both https and http, you can do something like *://www.some-domain.com/*. See the official literature here.
I should warn you that if you are attaching a content script to a page that was loaded as https rather than http, you will likely not be allowed to send an unsecure http request due to Chrome blocking mixed content, which I believe requires a user override. So a good rule of thumb is: if you're attaching your content script to a page loaded via http, then use http to send the request; if you're attaching to a page loaded via https, then use https.
One last tip: Don't forget to reload your extension after you've changed the manifest, or the permission changes won't be reflected. To reload your extension, go to chrome://extensions, find your extension, then hit reload.

If you send from your background script there is no problem with switching protocols but you had to declare permission to these urls:
see more at the google manifest documentation and this duplicated question

Related

What makes a browser load content from an http URL even when frontend source has an https URL?

my vue component is loading external content in an iframe
<iframe src="https://external-site" />
works fine locally, but once I deploy to my https site
Mixed Content: The page at 'https://my-site' was
loaded over HTTPS, but requested an insecure frame
'http://external-site'. This request has been blocked; the
content must be served over HTTPS.
network tab shows 2 requests, both have status (cancelled), and both have request url is HTTPS..
For general cases like redirecting URLs with no trailing slash to corresponding URLs with trailing slash added, some servers have broken configurations with http: hardcoded in the redirect — even if the server has other configuration that subsequently redirects all http URLs to https.
For example, the case in the question had a URL https://tithe.ly/give?c=1401851 (notice the missing trailing slash) that was redirecting to http://tithe.ly/give/?c=1401851 (notice the http, no-https). So that’s where the browser stopped and reported a mixed-content error.
That http://tithe.ly/give/?c=1401851 redirected to https://tithe.ly/give/?c=1401851 (https) in this case. So the fix for the problem in the question would be to change the request URL in the source to https://tithe.ly/give/?c=1401851 (with trailing slash included).
If you were to open https://tithe.ly/give?c=1401851 (no trailing slash) directly in a browser, the chain of redirects described in this answer just happens transparently and so it looks superficially like the original URL is OK. That can leave you baffled about why it doesn’t work.
Also: when you check the Network pane in browser devtools, it’s not going to readily show you the redirect chain, because as noted above, browsers follow redirects transparently — except when the chain has a non-https URL, causing the browser to stop, breaking the chain.
So the general troubleshooting/debugging tip for this kind of problem is: Check the request URL using a command-line HTTP client like curl, and step through each of the redirects it reports, looking carefully at the Location response-header values; like this:
$ curl -i https://tithe.ly/give?c=1401851
…
location: http://tithe.ly/give/?c=1401851
…
$ curl -i http://tithe.ly/give/?c=1401851
…
Location: https://tithe.ly/give/?c=1401851

Chrome Extension: Can it be done: Request to local rest service

I have a need for a solution to a repetitive task I do in Google Chrome.
I come across IP addresses once in a while, and I need to geo locate them.
On my system I already have a REST service that If I called a certain url:
http://localhost:8080/json/8.8.8.8
I get a JSON response with GEO data.
I want to create a chrome extension that would trigger a geo rest call on selection or even hovering over a IPv4 string.
Is such an extension possible? Would it be blocked by cross domain request protection?
You can do is as an extension to chrome, content scripts, message passing and setting up proper permissions.
Content scripts will run on selected (or all) pages and can do whatever you want with the page. They just sandboxed from page's JavaScript environment. You can develop a hover action which recognize IP address and send the information to the background page where it can be processed (in environment and especially permissions of the extensions which are not available in context of content scripts).
In the background page you can make a request using either XMLHttpRequest or Fetch function. After you process the data you can return the result to the page via message passing or do whatever you want with it.
In the manifest file you can set up specific URL you want to send information to or <all_urls> to have permission to send request everywhere.
...
"permissions": [
"http://*.google.com/"
],
...
Then your request won't be subject of CORS and same domain policy.
You can run the following scriptlet directly from Chrome's address bar:
javascript:var xhr = new XMLHttpRequest;xhr.open('GET', 'http://localhost:8080/json/'+window.getSelection().toString(), true);xhr.onload = function (e) {alert(xhr.responseText)};xhr.send();
(note that you'll need to prepend the "javascript:" to the text on the address bar when copying from here because Chrome trims it when pasting).
Add this as a new page bookmark (name it something like "IP Geo Data") and put it on the bookmarks bar. Alternatively just type its name and choose it on from the ombibox autocomplete. You'll need to have the IP you want data about selected.
You're right about the cross domain protection, but since you control the service on your localhost:8080/json, just have it add the following headers on requests made to that path:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since

CORS: PHP bypass not working

I'm working on a Chrome extension part of which is a function which manipulates images on a page using canvas and its context.getImageData function. That's when I ran into CORS issues. It's my understanding that a server serving an image has to server said image with appropriate CORS headers in order for cross-domain requests to be successful. I started reading up on this (to me) new and unfamiliar technology (tutorial). A substantial number of servers doesn't employ CORS and it's very important for the function of my extension that every image is processed. I've spent a whole day trying to circumvent this issue using client-side scripting but came to the conclusion that the only way is to send the image url to a server and then serve it back with the needed CORS headers (Access-Control-Allow-Origin: *). Now before I get into explaining my implementation I'd like to quote a paragraph from the tutorial page I linked previously.
Cross-Domain from Chrome Extensions
Chrome extensions support cross-domain requests in a two different ways:
Include domain in manifest.json - Chrome extensions can make cross-domain requests to any domain if the domain is included in the "permissions" section of the manifest.json file:
"permissions": [ "http://*.html5rocks.com"]
The server doesn't need to include any additional CORS headers or do any more work in order for the request to succeed.
This should mean that "permissions": "<all_urls>" should circumvent same origin policy restrictions. However, this does not work.
My solution
An XMLHttpRequest passes the image url and callback function to the server on localhost (for testing purposes) which first sets the appropriate header:
header('Access-Control-Allow-Origin: *');,
and then prints a JSON encoded array containing image width, height, and using file_get_contents, imagecreatefromstring, and base64_encode, the equivalent of context.getImageData and a call to the callback function.
The callback function sets the src property of an Image Object (that has crossOrigin set to Anonymous) which is used for drawing the images onto the canvas and sets it's width and height properties.
Result
The expected result was for every image to be loaded and processed without raising a Cross-origin image load denied by Cross-Origin Resource Sharing policy error, however now every image seems to be served without the needed CORS headers crippling my extension. I checked the headers the page on localhost which processes this request sends and it seems to be okay. (screenshot)
Conclusion
My implementation of this solution seems like it should work and I really have no idea why it doesn't. The server is sending the Access-Control-Allow-Origin header, the image data is good and the callback function is called. This is the only issue left to resolve before release. This is a really intriguing issue. I realise the header I'm sending isn't the only one I might want to send but it's sufficient for testing purposes.
I hope this question was clear, and detailed enough for someone to help me resolve this issue. Please do not hesitate to ask for more information and/or code snippets as I didn't really include any code in an attempt to keep this concise.
If your image src is a data uri (base64 encoded image data), then there is no headers to set access control.
Just set the image source to the url you're calling in ajax and send back the image not encoded(echo file_get_contents).

Chrome extension Cross Domain Request

I know that this has been talked about many times here, and I have read most of these threads but I can't seem to get my script working.
Problem is that I am trying to use bitly api to shorten urls in google chrome extension. I am saving users login and apiKey in localstorage and before I do so I validate them.
The code to do so is:
$.ajax({
url:"http://api.bit.ly/v3/validate",
dataType:'jsonp',
data:{
login: login,
apiKey: apiKey,
x_login :"test",
x_apiKey :"test"
},
success:function (jo, textStatus, jqXHR) {
if (jo.status_code == 200) {
setItem('dg_BitlyApiKey', apiKey);
setItem('dg_BitlyLogin', login);
alert('Saved');
} else {
alert('Incorrect login and/or apiKey!')
}
}
});
I do have my permissions set to "permissions": ["tabs", "notifications", "http://*/*", "https://*/*"] but I still keep getting:
Refused to load script from 'http://api.bit.ly/v3/validate?callback=jQuery17204477599645033479_1334062200771&login=&apiKey=&x_login=test&x_apiKey=test&_=1334062201506' because of Content-Security-Policy.
The script itself works outside the extension so I assume the problem isn't within the script but with the permissions.
What am I doing wrong here?
The problem is that you aren't really doing a XHR request, you're doing a JSONP request on an insecure HTTP resource. See the question How to load an external JavaScript inside an extension popup and the related Chromium bug report.
Yeah, we're no longer allowing insecure scripts in extensions. If you load a script over HTTP, an active network attacker can inject script into your extension, which is a security vulnerability.
JSONP operates by dynamically adding a new script tag into your page and then executing the contents. In your case, the script resource is fetched over HTTP (instead of HTTPS). If your extension uses version 2 of the extension manifest, its background pages cannot fetch non-HTTPS scripts.
Solution: If you use the Bitly API over HTTPS, I believe that will fix your issue. Send your Ajax call to https://api-ssl.bitly.com/v3/validate (instead of your current value of http://api.bit.ly/v3/validate)
You need to package your app/extension for cross domain requests to work. A hosted application will not be able to do cross domain requests. See:
Cross-Origin XMLHttpRequest in chrome extensions
To make Cross-Origin Requests in Chrome Extension you need to Avoid Cross-Origin Fetches in Content Scripts.
Full answer you can found in
https://stackoverflow.com/a/56929473/3680164
Or in the documentation
https://www.chromium.org/Home/chromium-security/extension-content-script-fetches

A question about cross-domain (subdomain) ajax request

Let's say I have the main page loaded from http://www.example.com/index.html. On that page there is js code that makes an ajax request to http://n1.example.com//echo?message=hello. When the response is received a div on the main page is updated with the response body.
Will that work on all popular browsers?
Edit:
The obvious solution is to put a proxy in front of www.example.com and n1.example.com and set it so that every request going to a subresource of http://www.example.com/n1 gets proxied to http://n1.example.com/.
Cross domain is entirely a different subject. But cross sub-domain is relatively easy. All you need to do is to set the document.domain to be same in both the parent page and the iframe page.
document.domain = "yourdomain.com"
More info here
Note: this technique will only let you interact with iframes from parents of your domain. It does not alter the Origin sent by XMLHttpRequest.
All modern browsers support CORS and henceforth we should leverage this addition.
It works on simple handshaking technique were the 2 domains communicating trust each other by way of HTTP headers sent/received. This was long awaited as same origin policy was necessary to avoid XSS and other malicious attempts.
To initiate a cross-origin request, a browser sends the request with an Origin HTTP header. The value of this header is the site that served the page. For example, suppose a page on http://www.example-social-network.com attempts to access a user's data in online-personal-calendar.com. If the user's browser implements CORS, the following request header would be sent:
Origin: http://www.example-social-network.com
If online-personal-calendar.com allows the request, it sends an Access-Control-Allow-Origin header in its response. The value of the header indicates what origin sites are allowed. For example, a response to the previous request would contain the following:
Access-Control-Allow-Origin: http://www.example-social-network.com
If the server does not allow the cross-origin request, the browser will deliver an error to example-social-network.com page instead of the online-personal-calendar.com response.
To allow access to all pages, a server can send the following response header:
Access-Control-Allow-Origin: *
However, this might not be appropriate for situations in which security is a concern.
Very well explained here in below wiki page.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Another solution that may or may not work for you is to dynamically insert/remove script tags in your DOM that point to the target domain. This will work if the target returns json and supports a callback.
Function to handle the result:
<script type="text/javascript">
function foo(result) {
alert( result );
}
</script>
Instead of doing an AJAX request you would dynamically insert something like this:
<script type="text/javascript" src="http://n1.example.com/echo?callback=foo"></script>
Another workaround, is to direct the ajax request to a php (for example) page on your domain, and in that page make a cURL request to the subdomain.
The simplest solution I found was to create a php on your subdomain and include your original function file within it using a full path.
Example:
www.domain.com/ajax/this_is_where_the_php_is_called.php
Subdomain:
sub.domain.com
Create:
sub.domain.com/I_need_the_function.php
Inside I_need_the_function.php just use an include:
include_once("/server/path/public_html/ajax/this_is_where_the_php_is_called.php");
Now call sub.domain.com/I_need_the_function.php from your javascript.
var sub="";
switch(window.location.hostname)
{
case "www.domain.com":
sub = "/ajax/this_is_where_the_php_is_called.php";
break;
case "domain.com":
sub = "";
break;
default: ///your subdomain (or add more "case" 's)
sub = "/I_need_the_function.php";
}
xmlHttp.open("GET",sub,true);
The example is as simple as I can make it. You may want to use better formatted paths.
I hope this helps some one. Nothing messy here - and you are calling the original file, so any edits will apply to all functions.
New idea: if you want cross subdomain (www.domain.com and sub.domain.com) and you are working on apache. things can get a lot easier. if a subdomain actually is a subdirectory in public_html (sub.domain.com = www.domain.com/sub/. so if you have ajax.domain.com/?request=subject...you can do something like this: www.domain.com/ajax/?request=subject
works like a charm for me, and no stupid hacks, proxies or difficult things to do for just a few Ajax requests!
I wrote a solution for cross sub domain and its been working for my applications. I used iframe and setting document.domain="domain.com" on both sides. You can find my solution at :
https://github.com/emphaticsunshine/Cross-sub-domain-solution

Categories

Resources