How to override `location.href` in Electron to a custom URL? - javascript

Description
Is it possible to modify or override the perceived current location and origin in Electron.js?
I am loading a local .html file in Electron, and I need to manually override location.href, document.domain, and all other references to the current location to point to https://example.com/my/page in order for some external libraries (e.g. reCAPTCHA) to work with the local page.
Is it possible to set the current location to be example.com, without actually making a request to the remote URL, so that any javascript on the page thinks that the current URL is that, instead of app://....?
What I've tried
For my tests, I achieved it by running a MITM proxy that intercepts HTTPS requests, and instead of making a request to the origin, responds with a locally generated html page, which therefore I can inject my actual content into.
However, I don't want to go with this approach, and I was wondering if Electron could natively masquerade as a custom URL while loading local files, and report to any content un the page with the appropriate location/origin.

Related

Electron - what are the risks of disableWebSecurity in WebView?

I'm loading a remote resource in a webview, but I want to inject some local content such as images (using preload script) into it. I guess the only way is to use the file protocol, but it won't work without disableWebSecurity set to true. Would that make my application vulnerable?
Edit: I managed to do what I wanted without disabling security by using a custom protocol, for some reason it is allowed. https://github.com/electron/electron/blob/master/docs/api/protocol.md

Open files in network not working

I have WAMP installed on a network machine. I have a table with file links, for people could open those files directly from a web page.
Those files are in another server, in the same network as WAMP.
When the users click on the link it appears the following error:
"not allowed to load local resource: file:///networkdrive/directorie/file.xls"
How can I resolve this?
I have this:
<button type="button" onClick="openfile('networkdrive/ptlr/Sectorial/LRCD/HorĂ¡rios/Equipas Turno.xls')">botao</button>
<script>
function openfile(file) {
window.location = "file:///" + file;
}
</script>
Just read the error: "not allowed to load local resource (...)"
Or on Firefox I get "Access to (...) from script denied".
It seems you are looking for a magical solution that will solve it, but no, it's exactly as the description of the error says: you are not allowed to do that because of security reasons.
The problem is that you're trying to make the browser open a file on your local drive, and that's not allowed from any protocol other than file:/// itself. So, what you'll want to do is either make sure the local file is also accessible via a server, or open the webpages that contain this script from file:/// too.
You can see this at work by first opening http://jsbin.com/OYObEMA/1/ and seeing this same error occur, then pressing CTRL+S and saving it as a single HTML file, and opening that HTML file then. The JSBin one opens via the internet, so isn't given access to the file:/// protocol, but the local (downloaded) HTML file can access it.
One way you could kind-of do this is to just provide the url the user needs to go to instead. So, just make an <input> that has a value set to the url the user would need to go to, and then provide the instructions "please copy this url into your url bar to open this file". That's not an elegant way to do it, but it would kind-of work.
About your answer to my initial comment: sure, I understood that. The question was not meant in a literal way, but to make you start thinking about what you actually try! You mix different environments.
either need to use webdav for this, if your client side applications are able to use that http extension to load and save files, or
you have to do the old scheme known from the IT middleages which is still typical for MS-Windows systems: offer the file for download via http and add an additional upload service (which will give you versioning pain), or
deliver your web page via the same protocol (network share) so that it is opened with as a local file on the client side, since then your are allowed to open additional local files referenced inside the web page.

Loading local html file in Android browser through intents

I need to parse a local HTML file in the google chrome browser. I have read that a way of doing this, is to copy the HTML file into the SD card and load it. What I want to do is, open the HTML file in the chrome browser from the MyProject/assets folder.
I am currently loading the html through a url. Loading the html locally would make the page load faster. This is what I am doing right now.
Intent i = new Intent("android.intent.action.MAIN");
i.setComponent(ComponentName.unflattenFromString("com.android.chrome/com.android.chrome.Main"));
i.addCategory("android.intent.category.LAUNCHER");
i.setData(Uri.parse("http://www.example.com"));
startActivity(i);
What I want to do is something like this
Intent i = new Intent("android.intent.action.MAIN");
i.setComponent(ComponentName.unflattenFromString("com.android.chrome/com.android.chrome.Main"));
i.addCategory("android.intent.category.LAUNCHER");
i.setData(Uri.parse("MyProject/assets/htmlfile.html"));
startActivity(i);
First, get rid of the setComponent() call. Treat your users with respect, and allow them to use whatever browser they wish. Besides, Chrome is only on a small percentage of Android devices, meaning that your app will crash on most devices.
Second, get rid of the addCategory() call, and replace your Intent action with Intent.ACTION_VIEW.
All of that should be done regardless of where you are getting your Web content from, as your current approach is incorrect and unreliable.
With respect to assets, other apps cannot directly read your assets via a Uri. You can create a ContentProvider that serves your assets, but Chrome does not support the content:// Uri scheme. In fact, Chrome only supports http:// and https:// Uri values for loading arbitrary URLs -- it does not even seem to support file:// very well.
If you want to view an asset, display it in a WebView widget. There, you can use a file:///android_asset/ URL to reference one of your own app's assets.

Javascript used to include html, is it cached?

I'm using a method of creating a .js file on server #1 which contains document.writes to write html code, then a simple js include inside html code on server #2 to load that html code (there are multiple server #2's). This is basically replacing an iframe method with the advantage being that each server #2 owner controls their own css.
The method works perfectly as is. My question has to deal with caching. Each time the page is loaded on server #2 I want the .js reloaded, as it will change frequently on server #1. This appears to be the case on each browser I tested, but can I rely on this as being the default case, or is it dependent on browser settings? Despite all I've read on caching I can't figure out what triggers the load for a case like this.
You can control browser caching using HTTP headers on the server side. Like cache-control and cache-expiration. More here - http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
In a case like this, the caching is triggered by the cache policy of the js file. Not the html file.
The browser doesn't cache the rendered page (well, it does for back buttons but that's not what we're talking about). The browser caches the source file. Therefore even if the html page is configured to be cached for a long time the javascript injected content will only be cached as long as its been configured to.
To configure caching policy you need to set specific headers on the server side. Sometimes you can do this in a CGI script. Sometimes you can do this in the server configuration files.
Google "http caching" and read up on how to configure a page to be cached or not cached (also google "json disable caching" or "ajax disable caching" because this issue crops up a lot with ajax).

Access elements on an external page

I have an html page that is being accessed via a link that places an external page in the url - e.g.
http://www.mydomain.com/mypage?external-page=encodedURL
It is the responsibility of my page to scrape some data from the URL it is handed.
How can I access the passed-in page using javascript/jquery? I need to be able to pull out the content for certain classes and ids.
Is this a violation of same origin policy? If so, is there some other way to process an external page like this? Seems strange to me that I can hit the web page in a browser or a terminal command and receive the content, but not in a js file.
You can use a browser extension to scrape the external page, then send the data to your site, OR display it within the page, so that it can then be accessed by your page's javascript via the DOM.
You can use a proxy on your domain which fetches the external page and hands it to your javascript whose origin is on your domain, too.
You can use an API for the external page which is accessible.
You can ask,command, change the code of the external page (if you have access to it) to serve pages with Access-Control-Allow-Origin=*
I think this is all you can do.
EDIT: The "seems strange" is until you realize the intended difference between a user, and a process. The user is not thought to be malicious, but a process could be. A process could for example, grab data from a user's logged in gmail session if it had access to the external page, and transmit that data to a server. Since the user on the terminal is probably (but not always !) the one who logged in to that session, the user is not thought to be malicious. But a script whose origin is some website that user navigates to, should not be able to act with the same permissions as that user. Since that script is an agent as well, and can make actions, but it is not created or directed by the user. That's the strongest reason for the isolation of origin's and the same origin policy.
Example
Execution Context of Bookmarklets, and IFrames
If you are injecting JS into every page via a bookmarklet, then that injected code will behave as if it has the same origin as the rest of the page, or at least the "top frame" of that page. It will execute in the same context as the top frame. If there are nested iframes in the page then you will get an "unsafe attempt to access page x from " error if your bookmarklet tries to inject into there. This is because the bookmarklet has it's origin in the top page, and the top page can never access nested iframes on different domains anyway.
So if some part of the site you wish to scrape is in an iframe below the top frame, your bookmarklet will fail to get it.
Transmitting Data using a bookmarklet
If you want to take a url on one page, on your domain, then grab data from that url, on another domain, then display that data back on the same page, you need a way to get the data across. You could use a bookmarklet but the flow would still involve some "user help". It would go something like this:
Load your domain's page, D. User puts a url into an input box. Clicks submit.
Javascript on D opens a new tab/window pointing to the user provided url.
User clicks your scraping bookmarklet on that external page, which collects the desired data, X.
Desired data, X, is sent via Ajax to a "server", S, with session identifier I.
Page D, polls the server S, until it gets notified that some data with session identifier I has been grabbed, then it gets that data and displays it on D.
There is the need for a server. You can't use local storage to transmit the information since this is specific to a domain. There is an alterative that does not require a server. It requires making a browser extension.
Transmitting data using a browser extension The "background page" of the extension is basically the same as a local server for all the browser tabs, it permits transmitting of information across tabs targeted to different domains. The "clients" in this set up are the "content scripts", which are loaded to every page (just like a bookmarklet, except without the requirement for a user to actually click the bookmarklet to load it. It happens automatically). The flow would go like this:
Page D again. User inputs url in input box. Clicks submit -> which triggers some code in the extension.
The extension background page instructs a tab to open and targets it to the url.
A content script loads automatically into that tab, checks with the background what data it should get. It gets that data, and sends it, via a message (a json string) to the background page.
The background page pushes that notification and the data on to the original contents script on page D. Which displays the information.
Optionally, the background page also transmits the information to your server for saving into that user's datastore.
The language I use for the browser extension "background page" and "content script" is pretty much focussed on Google Chrome. The same concepts are available in Safari, Firefox as well. If you want to support IE you're going to have to work out something else. IE10 does not plan to even support extensions.
If the external page and your page is on the same domain, then you should be able to access that external page using JavaScript. Otherwise, the JavaScript won't be allowed to access the external site, browsers will prevent Cross-site scripting.

Categories