Please tell me, why local javascript cannot open a local file?
I'm trying to create a simple javascript/html app that shall run on the local machine from local filesystem. This app is trying to read the configuration file (json) using different methods, but gets the following errors (Chrome):
In case of XMLHttpRequest, method open("GET", filename, true) throws an exception:
XMLHttpRequest cannot load file:///bla-bla-bla. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
In case of document.createElement("iframe").src=filename I have another exception:
VM596:1 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a cross-origin frame."
In case of var f=new File([], filename, { type: "text/plain" }); I've got the File object with the zero size and no errors at all. FileReader returns an empty result then.
So, my questions are:
Why is it "cross-origin"? These files are stored in the same directory!
And how could I open the local file from the same origin/directory I run the script?
Please help.
P.S.: Yes, I know about --allow-file-access-from-files but I need to run this by customers.
Why is it "cross-origin"? These files are stored in the same directory!
Because Chrome considers all file:// URLs to be cross-origin to each other.
And how could I open the local file from the same origin/directory I run the script?
From Chrome? You don't. Not unless you disable CORS entirely with a command-line option (which is a bad idea, as it's trivially easy to forget you've set that command-line option and go surf the web, leaving yourself wide open to exploits cashing in on the fact you've disabled web security).
Other browsers may treat origin null differently.
Instead, run a local web server and make the files available via the local web server. Then you can access them because it'll be a same-origin http URL, not a file URL. Or use any of the dozen or so frameworks that let you write apps in JavaScript (rather than using the browser). Or a simple NodeJS script serving the files (it's about 10 lines long). Etc.
What you can do to read your .json file, is to declare it a .js.
data.js
var data = `{"value1": 10, "value2": "hello"}`
index.html
<script src="data.js"></script>
<script>
console.log(JSON.parse(data))
</script>
This will print
Object {value1: 10, value2: "hello"}
Both of them have to be in the same directory, otherwise you've to change the import of data.js.
A little late for this party, but I had the same issue and this was how I got around the problem
Create a js template such as this:
template.js
(function(global, factory) {
"use strict";
factory(global);
})(typeof window !== "undefined" ? window : this, function(window) {
"use strict";
var myObjectJson = '<JSONREPLACE>';
var myObject = JSON.parse(myObjectJson);
window.myObject = myObject;
});
Then, have your json replace the tag either by your program that could generate the exported js itself, or create a batch script file that does that for you. I'm using C# so I just build the template directly from there. If the language you're working on is half-decent, you should be able to generate and export your file.
Make sure you use a minified json string.
Then you use your generated file just like you'd use jQuery
<script src="generated.js"></script>
and access your object with
window.myObject;
It's slightly more complicated to set-up, but once you do, you completely remove the cross-origin issue.
Related
So I'm trying to think of a method to get a "local" file not from the user but from the Google Chrome App or Extension which ever it may be since I am building both. Basically, it'll be my Settings JSON and I need access to it through my Options Page, like to have access to it via my content scripts but it's ok, and I need access to it via my Background page.
Sample Settings.json
{
"defaultResults": "all",
"view":"full",
"results":"cur",
"count":"5",
"omni":{
"h8":{
"title":"Hello World",
"url":"www.someurl.com"
}
}
}
So does anyone have any real options for this. I'm not positive if Google has already implemented a native function for this such as chrome.getAppFile("file URL"); or something of that matter. I'd rather not use Ajax inside my app for this file. And I'd rather not use it everywhere. So hopefully, someone here will have a reasonable idea how I should go about this.
You can do this in 2 ways, as described in this answer.
By assigning your JSON object to a variable, saving the script as settings.js, and including it in your background page, as follows:
settings.js looks as follows:
var settings = {"param":value,...}; //Your JSON object
then, in your background page:
<script src="settings.js"></script>
By making an AJAX call to your settings.json from your background page:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();
As discussed in the comments, you cannot use FileSystem API in chrome extensions. Only chrome apps have access to it. Either way, the FileSystem API works in a sandboxed zone, so I'm not sure if you can write to files packed with the extension.
I have a Worker.js file and a Subworker.js file in my Scripts folder. No problem creating a worker, I can step through its code in the debugger; but when I want that worker to spawn a subworker, it isn't getting created, and I'm unable to step through the subworker code file in the debugger.
In myPage.htm script block:
var worker = new Worker("Scripts/Worker.js"); // Succeeds
In Worker.js script file:
var subworker = new Worker("Subworker.js"); //without the folder name FAILS
The IE10 developer tools Network console shows this:
URL....................Method...Result..Type.......................Received.......Taken......Initiator
/Scripts/Worker.js.....GET......200.....application/x-javascript...1.00KB..........<1ms......webworker
/Scripts/Subworker.js..GET......404.....text/html..................2.50KB..........239.29s...webworker
EDIT: Found the answer to the 404 error although still unable to instantiate the subworker:
var subworker = new Worker("..Subworker.js");
EDIT2: Also found that the following trick to cause the current version of a script to be used generates a 400 error:
var subworker = new Worker("..Subworker.js?version=2.0");
I'm in about the same boat.
My plan is to load a subworker from another doamin or file:// protocol because you cannot load one directly from a regular js script. I still need to test this, but I know that Workers/SharedWorkers are not subject to the normal Cross-Origin Restriction Policy, except** for when you're trying to load one (and hopefully only when doing this from a window script).
Another method is to use window.postMessage to forward messages to a Worker that it has created in the other window.
Alternatively, for my specific needs I am considering running a headless browser locally, a CDN, or a localhost "forever-server" with CORS enabled -- but this most likely still requires a window.postMessage().
Hope this helps, Tim!
Post back if you find an answer, eh?
I've been experimenting with the Valence javaScript client library and the 'GettingStartedSample' download from D2L.
If the sample files are uploaded, accessed and ran from within a D2L course site the script works, however, if I try to run it from a localhost I run into a problem. On localhost I can successfully authenticate the application however when I try to run a 'Get Versions' or 'WhoAmI' request nothing happens.
Firebug tells me the following:
Object { readyState=0, status=0, statusText="error" } server.js (line 77)
error server.js (line 78)
(an empty string) (line 79)
Should I be able to make a request using the javascript client library from a localhost?
The short answer is yes, but you need to do some additional work.
I would advise reading up on the same origin policy so you have some background as to why XHRs (in your case, Valence calls) between domains do not work out of the box. The easiest thing to do is to use jsonp if all you are making are GET requests. If you need to make other requests, you will need to look into getting CORS support set up on your instance.
I have written a Chrome extension. I cannot use
localStorage.setItem and localStorage.getItem for storing and retrieving because background and browser action runs in different environment [as seen here].
So I decided to use the Chrome storage API:
var storage = chrome.storage.local;
var myTestVar = 'somevar';
var obj = {};
obj[myTestVar] = $("#somevar").val();
storage.set(obj);
which produced the following error:
Uncaught TypeError: Cannot read property 'local' of undefined
What am I doing wrong?
Make sure that all necessary permissions have been declared in the manifest file. "storage", in your case.
In general, the following steps should fix the problem of apparently undefined Chrome APIs:
Read the documentation of the API you're using and get yourself familiar with the prerequisites, usually manifest permissions (e.g. chrome.storage#manifest).
Check if your (user's) Chrome version supports the API, by looking at What's new.
Check if the script is running in the right context. Most APIs are only available to the extension's process. (the chrome.storage API can also be used in content script though)
Otherwise, resort to your usual debugging skills: Typos, variable shadowing, ...
You'll get this error if you try running your app as a simple HTML page opening the HTML file in Chrome.
Add the app in Chrome properly (as an Extension) then run it.
function publish(text) {
$('#helpdiv').prepend(text);
}
function get_help(topic) {
$.get(topic, publish);
}
<p>Hi. click here for more help.</p>
<div id="helpdiv"></div>
I've inherited this chunk of HTML and javascript above (snippet). It is/was going to be used as local help. Currently it is online only and it works fine. However, when I copy the files locally, I get "Permission Denied" in Internet Explorer and in Chrome doesn't do anything when I "click here for more help". What it's supposed to do is load the help content from inline-help.html and display it in the helpdiv div. Now here is the kicker, if I take the same files and copy them to inetpub on my PC and load them as http://localhost/hello.html it functions perfectly.
Presumably this is a security thing where the "local" zone isn't allowing me to load files off of the user's HD? But I'm not really sure what's going on and would like to understand this problem further and potentially come up with a workaround.
Any insight is greatly appreciated.
jquery's "get" uses xmlHttpRequest, which doesn't work on local files, unfortunately. If you really need to be able to fetch local data (or data from a different domain) asynchronously, you should use dynamic script tags. However that means the data file has to be reformatted as JSON data.
I don't think your browser is allowing you to run javascript locally (using the file:/// access method). But when you load it from http://localhost/ it works fine.
You need to either develop on a website, or use your localhost server.