Dynamically reload local JavaScript source / JSON data - javascript

What are the possible cross-browser (at least Firefox & Chrome) methods to dynamically reload a local JavaScript file that is referenced by a locally loaded HTML file?
Background:
A local HTML page is being used to render some data that is formatted and displayed by two referenced JavaScript files. One file contains the JavaScript code and the other file contains JSON data.
This JSON data is updated on disk by another program and it would be nice to have the UI automatically incorporate these updates without manually reloading the page (or opening a new page).
In Firefox, I believe the issue could be resolved using AJAX to load the HTML, but in Chrome this will not work due to the same origin policy failures (I unfortunately cannot necessarily rely on --disable-web-security to mitigate this since all prior instances of Chrome must be closed for that to work).
The only solution I see is to run a local web server, but I am hoping for something simpler and less invasive (Perhaps loading the JavaScript in an iframe and reloading the iframe, although I imagine this would be prevented by browser security).
Does anyone have any recommendations?

If your app starts up Chrome then you can include the --allow-file-access-from-files flag in the start command.

I use the following code to reload JavaScript and JSON files.
/* Load a JavaScript or JSON file to use its data */
function loadJsFile(filename, dataIsLoaded){
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filename);
fileref.onload = dataIsLoaded;
if (typeof fileref!="undefined"){
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
/* The callback that is invoked when the file is loaded */
function dataIsLoaded(){
console.log("Your data is ready to use");
}
Usage when the JSON file is in the same directory as the website:
var jsonFile= "myData.json";
loadJsFile(jsonFile, dataIsLoaded);
I tested it successfully in IE10 and Firefox 22; it doesn't work in Chrome though.

Related

Embedded appendChild JS files not re-fetched on browser hard refresh

I have a web page with multiple embedded JS files, almost all of which are inserted using the normal <script src="/blah.js?v=20200414"> tag. They all have a cache-busting query string, based on the date they were created.
There is one script which is loaded using the following
<script>
window.setTimeout(loadScriptElm, 2000);
function loadScriptElm()
{
var scriptElm = document.createElement("script");
scriptElm.src = "/special-script.js?v=20200414";
document.getElementsByTagName("body")[0].appendChild(scriptElm);
}
</script>
All the scripts have a Cache-Control for 900 seconds. The code in all of them runs just fine.
When I initially load the page, all the scripts are retrieved from the server. When I do a refresh (using F5), all the scripts are loaded from browser cache (assuming the cache TTL hasn't expired).
When I do a 'hard refresh' (using Ctrl+F5), all the 'regularly-embedded' scripts are re-fetched from the server (as I would expect), but the special-script.js file is not - it's still retrieved from browser cache. Why doesn't a hard refresh also re-fetch this file?
I can reliably recreate this on Chrome/Brave, but I haven't tried other browsers. It seems like a bug, but maybe it's not... Is this 'expected behavior'? If so, is it documented anywhere?

Loading external javascript in a Chrome Extension

I'm trying to load some external javascript code in my Chrome extension. However, due to the sandboxed environment of the extension, I can't see any of the functions defined by the external code.
The external code implements a dependency mechanism, whereby one javascript file may require another, and so forth. It also looks at arguments to the URL used to load the javascript to determine the top level javascript file to load. So it basically is able to load any arbitrary web app, and it is not known in advance all the files that will be used. So I can't use any static definitions in the extension.
There is also the issue that since all extension code is sandboxed, I don't have complete access to the document - for instance, it can't access the window variable.
But if I put all the code in the external code, I run into content security problems if one script tries to load another. The whole reason I went was an extension is because of the bone-headed misimplementation of CSP by every single browser in existence whereby bookmarklets can't access external resources.
What's the best practice for bypassing or working around the extension sandbox to basically be able to run code as if the page itself had loaded it, without any issues with CSP?
In the content script you could do something like this to load the js file
function inject(url, exteral) {
// 1. Build the absolute URL
// 2. Create a script tag and set src attribute
// 3. Append script tag to thw window
if (!external){
url = chrome.extension.getURL(url);
}
var scriptElement = document.createElement('script');
scriptElement.src = url;
(document.body || document.head || document.documentElement).appendChild(scriptElement);
}
If the js file is packged with the extension, it must be placed in the
manifest.json under web_accesible_resources.
othwerwise it need to have the same protocol that the page it is injected in (http | https)
Since the content script is not allowed to call the window functions, you could
call window.postMessage to send data from the actual window to content script.

IE extension - Injecting Javascript file

I am developing an IE extension which works on sites opened in Internet Explorer. It is designed to work the same way as a chrome extension. I am trying to implement the Background function of chrome extension using c++ and the content script by injecting JS into the current web page. The content script, I am trying to load via IHTMLWindow2 execScript on Document load event. Now that I need to inject JS files directly I tried the following.
Had the JS file under a folder inside the Project destination and tried to inject using physical path.
std::wstring filePath(_T("d:/xx/xxx/x/x/Content/myFile.js"));
scriptText = scriptText+ filePath + endScript;
VARIANT vrt = {0};
HRESULT hrexec = ifWnd->execScript(SysAllocString(scriptText.c_str()),L"javascript", &vrt);
The scriptText has some javascript code to create script element with type and src attributes. The filePath holds the physical path towards the js file.[Also tried relative path but it was a no go]
The above was not working correctly in IE9 due to mixed content issue, upon which I researched to figure out that IE9 expects the js file to be retrieved from a server rather than local physical path. The console throws me the below exception.
SEC7111: HTTPS security is compromised by file:<filepath>
SCRIPT16388: Operation aborted
I am pretty much not sure is there any round about for injecting Javascript to the current DOM from the physical path. Please help me on this.
Also let me know is there any other possibility of injecting the JS file from the current working directory into the DOM.
You don't have to inject a <SCRIPT> tag in the DOM.
If your js file contains:
var strHello = "Hello";
function SayHello() { alert( strHello ); }
you may just read the file into memory, construct a BSTR string with it, and pass that string to IHTMLWindow2::execScript.
Later, another call to execScript with the string SayHello(); will popup the alert box. The code you injected is still here.

Get Source of Loaded URLs via Chrome Extension?

I'm writing a Chrome extension that needs to be able to analyze the source code of a specific HTML page and all the external Javascript and CSS files it loads without loading them again via an XHR request - that is, it will be analyzing the running copies loaded by the browser.
Is that possible? I know it's possible to analyze the source of a particular open tab, but while these Javascript files will be loaded by the browser, they obviously won't be occupying their own tab or window (only the HTML loading them will be.) Please help!
Out of the box, there is no way to get the source of the resources without resorting to the chrome.experimental.devtools.resources APIs.
However, when the experimental APIs are enabled using the --enable-experimental-extension-apis switch, you can do the following to retrieve the source of each resource:
chrome.experimental.devtools.resources.onFinished.addListener(function(resource) {
resource.getContent(function(content, encoding) {
if(encoding !== 'base64') {
alert(content);
}
});
});

Ajax Parsing Local XML

I'm building a local html file to show dynamically some data from an XML file and by using Chrome's Inspector I figured my XML file is not being parsed because it is "not hosted on a webserver"
XMLHttpRequest cannot load data.xml. Cross origin requests are only supported for HTTP.
I know that there are a few flags I could pass to Chrome/web browser to workaround this limitation but I'm looking into some alternative method. I will probably have to distribute this files to a few people and teaching them how to pass flags to the browser is not an option for me. Hosting them on a web server is not an option either.
Thanks a lot in advance.
No ghost unless you set up a local server or host the XML file locally. Ajax has to follow the same origin policy.
If you're willing to use a library you can use jQuery's AJAX method to perform a cross-domain request (i'm not entirely certain that jQuery will support what you're trying to do). JSONP works, but you have XML data...
You could try loading it in a script tag anyway and see if you can get the innerHTML value without breaking the script; once you're done getting the text from it, remove the script from the page. You may be able to get at the data before the browser tries to parse the script by attaching onload and onreadystatechange events to the script element.
var s = document.createElement('script');
s.src = '/path/to/file.xml';
s.onload = s.onreadystatechange = getData;
function getData(e)
{
//get the text out of the script element
//remove the event handler from the script element
//remove the script from the page
}
document.getElementsByTagName('body')[0].appendChild(s);
I didn't test it, but it might work.
How about setting up a local webserver? XAMPP should be easy to install even for novice. Just tell them to put your files in the htdocs folder, run xampp and start the apache server.
Unless there's a compelling reason to have a separate html and xml file, you could just put the data directly in the html file.
I'm afraid if chrome only provides options that you don't like to apply, your application and chrome will not come together. Access via iframe & object does'nt work too, load()-method of createDocument is not supported by chrome(if it does I guess you got the same error).
Whatever you try will be a sideway to pass chrome's restrictions, what cannot be good, because I think they have good reasons to setup these restrictions.

Categories

Resources