How to block a URL to load and then present a HTML? - javascript

I want to intercept some user requests, cancel it and then present a hand made HTML.
First I tried to call window.stop() in the beginning of content.js, but after checking the Network tab of the Developer Tool I noticed that some elements are still being requested (although not loaded, it seems).
Then I tried to add a chrome.webRequest.onBeforeRequest listener inside background.js. So inside the callback I set my hand made HTML (document.getElementsByTagName("html")[0].innerHTML = myHtml) and in the end I canceled the original request (return {cancel: true}), but, although the original request is being canceled, my HTML doesn't appear.

Related

NS_BINDING_ABORTED only on first PUT attempt in Firefox

In my JS single page web app I have a reset-button that triggers 'onclick' and will use vanilla fetch() to PUT an empty JSON array to my API. Both are hosted on the same domain/server. When using Firefox (currently 86.0), the first time I push the reset button, the call is aborted. The console says NetworkError when attempting to fetch resource white the Network tab says NS_BINDING_ABORTED in the transferred column.
When I reload my app (F5) and push the same button again, it works. And also any time from now on. As the same code is executed, the failing and the working calls would send the same headers and payload.
Chrome does not show this behavior, there the first call works too.
Even stranger, this first failing PUT call in Firefox seems to only fail once per URL. The web app provides "areas" to users with the area ID in the frontend URL, e.g.
https://example.org/areas/#/myAreaA
and
https://example.org/areas/#/myAreaB
These will PUT to the API, which also has these IDs in their URLs:
https://example.org/api/areas/myAreaA/state/
and
https://example.org/api/areas/myAreaB/state/
For each of these URLs, the first PUT call fails with NS_BINDING_ABORTED but works thereafter. If I copy the URL for such an area into a new Tab or even close+open the Browser again, the Error does not appear again. The web app does not use any cookies.
The web app does a lot of other API calls to the same backend/areaID, no other show this behavior. However, this is the only PUT call, all other calls are GET/POST/HEAD/PATCH requests.
What could be the reason for the first PUT failing?
Following "NetworkError when attempting to fetch resource." only on Firefox I found the problem. It seems that Firefox' onclick event propagation interferes here with the fetch() call. As soon as I added
event.preventDefault()
in the onclick-handler before doing the actual fetch(), everything started to work again.

How to prevent current tab URL to load some requests?

I want to prevent some requests to be made from certain URLs. Example:
I'm at www.url.com/news/currentNews.html and I want to block some requests being made from this URL structure (i.e. www.url.com/*/*), but I don't want to block any request being made from www.url.com (the main page).
From inside background.js we can use chrome.webRequest.onBeforeRequest.addListener, but it intercepts all requests regardless of the current URL, which doesn't work for me.
I know we can get current tab URL from background.js using chrome.tabs.query, however, since this is an async method, I couldn't make it work the way I want. Any ideas?

Accessing localStorage of an iFrame in an event callback?

I'm trying to cheat a bit with localStorage. The spec defines that when a value in localStorage changes, all other open pages on the same domain receive a storage event callback. I would also like the event to fire on the page where the value was changed.
I added a hidden iFrame to each page which loads an empty document from the same domain and tried using it as the target for the localStorage change (so technically the page that I'm looking at isn't the origin of the localStorage change)
It works fine except for when I do the same thing inside an event callback...
function fnSetupMusicPlayerSection(i, oSection) {
var oAudio, oLocalStorageFrame, oLocalStorageWindow;
oAudio = oSection.querySelector('audio');
oLocalStorageFrame = oSection.querySelector('iframe.local-storage-target');
oLocalStorageWindow = oLocalStorageFrame.contentWindow || oLocalStorageFrame;
oLocalStorageWindow.localStorage.setItem('loadSetter', '1111');
oAudio.addEventListener('play', function(oEvent) {
oLocalStorageWindow.localStorage.setItem('callbackSetter', '2222');
});
}
loadSetter is successfully stored and all windows receive the storage event. When I click to play the audio I get the following error inside the callback - Uncaught DOMException: Failed to execute 'setItem' on 'Storage': access is denied for this document.
Is there anything I can do to solve this? I really don't want to have to write code to update the current page separately
Update: I don't know if I'm doing something wrong in the example I gave above but the code does seem to work inside some callbacks. I have an anchor on the page with a click event where I can set localStorage through the iFrame
You can try postMessage API to enable communication between your page and iFrame. In brief, send a message to instruct iFrame to update its localStorage, and another message to ask iFrame to return its localStorage content whenever you need the data you sent.
Be careful since:
This is a HTML5 API. Check if your app's minimum requirements allows the implementation.
This is a cross-origin communication, which means if other pages in your browser use postMessage, your iFrame will receive it too. You might need to add info into message to notice iFrame which message it should read.

Browser refresh sends the last $http call made

AngularJS 1.2.13
var httpdelete = $http.delete("/api/categories/" + id);
httpdelete.success(function(data){
alert("Success");
});
httpdelete.error(function(data, status, header, config){
alert("Error!");
});
I do an asynchronous $http.delete request
The success callback function is executed and the alert box "success" appears.
I hit the browser refresh button
The $http.delete line is not executed (debugged with break points). Instead the error callback function is immedialy executed. The alert box "error" appears. No request made it to the server after clicking on the browser's refresh button
I was expecting the entire page to reload when I hit the browser's refresh button.
Instead, AngularJS seems to attempt to resend my last delete query without having to execute $http.delete and goes straight to the error callback.
How can I restore the natural behaviour of the browser's refresh button? I want it to reload the entire page and not attempt to resend the last asynchronous http request.
Open the network tab of the chrome dev tools. Load your page and hit F5. If you don't see a get to your index.html (or whatever your base url is), it's because angular handled it. If you do see the get, the you have rebooted the app for real.
Once you know which one it is, you can investigate further. Setting a breakpoint in the httpdelete callback and inspecting the callstack might also help.
Okay so here is what happened, my backend Nodejs+Express+MongoDB delete action was not returning anything to the client (browser). I didn't think it was necessary to return any information after deleting the document from mongodb.
The side effect of that is as I described in the original post. After deleting the document on the server, if a user refreshes the page using the browser refresh button then the page is not refreshed. Instead the $http.delete request is resent to the server and on top of it the error callback is executed.
After modifying my server side action and make it return a json document such as { success: true, message: "" } after a delete request, the browser's refresh button behaves as it should have which is to reload the entire single application page index.html.

How to append parameters to URL before page starts loading?

In Chrome, I'm looking to detect in a page URL is going to be on example.com's domain, and if it is, before loading, append foo=bar as a parameter and load that instead.
I've found that I can access when the Omnibar has been submitted here, but it seems like it'd load the original URL anyways, and while that's alright it's twice the bandwidth I feel is necessary. It's not a problem when it's only one page, but it's a change that needs to happen on every page in an site, so double the bandwidth definitely becomes an issue.
Currently, it works to detect if the URL is going to be example.com and is submitted, then call window.stop() and then set location.href to example.com/&?foo=bar but that doesn't seem ideal.
In short, the user goes to http://www.example.com and then the script changes it to http://www.example.com/&?foo=bar before loading the original link.
Take a look at the chrome.webRequest API, in particular the following method:
onBeforeRequest (optionally synchronous)
Fires when a request is about to occur. This event is sent before any TCP connection is made and can be used to cancel or redirect requests.
You can use
window.location.search = "foo=bar"
may be this helps.

Categories