How to prevent reload of pages in Chrome Extension? - google-chrome

I have written a Chrome Extension to Clear TYPO3 CMS Caches right out of the browser's address bar.
Now I would like to add an optional feature, to clear the caches automatically on page refresh . That means, when the user presses F5, CTRL+R, clicks the reload icon in toolbar or clicks in context menu to "Reload", first my ajax script should be executed (to clear the CMS cache) and after it, the page may get reloaded.
Is there a possibility to do it with the Chrome API?
I tried first the window.onbeforeupdate event in content script - and this is triggered always when the page is reloading, but also if I close the window or switch to another website. And furthermore I can't tell the browser to wait for my ajax request here.
What works is to check in document.onkeydown event the keys 116 (F5) and 82 (R) with control key and use event.preventDefault(). But this will not cover the two other possible cases to refresh the cache.
Thanks!

I've found a solution. It does not really match my requirements, but it works (even better).
Chrome provides a webRequest API which allows you to modify or block all http requests.
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
if (!severalConditionsToCheckIfIWantToDoTheMagic) {
return;
}
$.ajax(url, {
async:false,
complete:function () {
return {redirectUrl:details.url};
}
});
},
{urls:["<all_urls>"]},
["blocking"]
);
In this example first I check if I want to do the ajax request. If yes, the next step is no do the ajax request. It is important, that the request is not asynchronous. On complete I return the original url of the request, which is basically just a reload.
The reason why it does not really match my requirements, is that it will be triggered always, on any request, not just on reload. That means in my conditions I have to check against:
Other websites
Other request types (loading css, js or images are also request), I just need the type 'main_frame'
Some variables belonging to my extension
Now, the script will be also triggered when I click on a link which is on the website - but for my case this is fine.

Related

Google Chrome - add to homescreen - force refresh

I have a website with "add to homescreen" enabled - i.e. I have got a manifest.json file with "display": "standalone".
The problem I'm having is when I open the website via the homescreen shortcut, it will resume from when I last accessed it. I have to pull to refresh to make it fetch the latest content.
My question is, is it possible to make it do a refresh every time it is accessed?
If you'd like to take specific action inside of your web app whenever it moves from the "background" to the "foreground" again, you could listen for the appropriate events using the Page Lifecycle API.
The most straightforward way of doing this would probably be to listen for visibilitychange events, and programmatically refresh your data source when you detect that the current visibilityState has transitioned to 'visible'.
This could look like:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
// Your refresh logic goes here.
}
});

How to combine advantages of localStorage and sessionStorage

I want to share my authentication token between browser tabs which would suggest to use HTML5 localStorage. But I don't want anything related to authentication to stay in my storage when the browser is closed which would suggest using HTML5 sessionStorage.
Reference 1 related to this topic (click):
That means that you can't share between tabs, for this you should use localStorage
Reference 2 related to this topic (click):
Therefore, it's recommended not to store any sensitive information in local storage
How can I combine the sharing of my authentication token between tabs and still make sure that when the browser closes nothing stays behind in storage?
How do other websites solve this seemingly simple problem.
We use cookies.
Storages have their uses.
But cookies meet all your requirements.
Cookies are shared across all same origin tab. You can even specify their paths, but they are shared by default.
Cookies are automatically deleted by browser when it is closed, you need to do nothing; this is again the default behaviour.
Cookies can be easily made as secure or more secure than storage.
Sometime the best solution is the simplest solution.
No need to reinvent the wheel.
Cookie Security
Session cookie is stored on disk like sessionStorage (in case the browser crash and need to recover).
So they are about equally secure in term of local disk read/write.
Both cookie and storage processing script may be acquired or even stolen during http transfer,
so you must use HTTPS for both cases.
(This is the least you should do.)
Cookie can be configured to be HTTP only,
preventing JavaScript from accessing it,
thus making immune from XSS script and greasemonkey hijacking.
In case when an auth token is stolen, we also associate each token with the machine's user agent and ip.
This prevent the token from being used by someone from external network.
If you want, you can add more content negotiation headers to the mix - not all robots copy all headers.
For another level of security, you can add client side fingerprinting.
These fingerprints must be captured on client side and transferred over network, so they are not bulletproof,
but they will force internal attackers (attackers on same network with the user) to jump through another hoop.
At this point, they will usually switch to easier attacks outside your control.
One option to achieve this could be to clean the localStorage when the page is about to be closed/unloaded, so nothing stays behind in storage. That way the localStorage would behave like the sessionStorage in the sense that it would be removed once the page is closed, but it would still have the advantage from the localStorage of sharing data across tabs.
For that you could use the onbeforeunload event:
The beforeunload event is fired when the window, the document and its resources are about to be unloaded.
Something like this:
// code here
...
// you have the data in the localStorage
localStorage.setItem("data", "My Data");
// more code here
...
// when the page is about to be unloaded, remove the localStorage data
window.addEventListener("beforeunload", function() {
localStorage.removeItem("data");
});
But that solution is way too simple, and there is a catch: when you close one tab, the localStorage data is deleted, even if you have other tabs open! (leaving them without any data). To prevent removing the data when one of the tabs is closed, you could keep track of the number of tabs, and only clean the localStorage when the number is zero.
The pseudo-code for that would be:
On page load:
If the localStorage has a count of tabs
Increment the tab count by 1
Or else (no count of tabs)
Create a variable in the localStorage that will contain the number of tabs.
Set that variable to 1 (the current tab).
On page unload:
Decrease the tab count by 1.
If the tab count is zero (this was the last tab open)
Delete the content of the localStorage
And here is a really simple demo. I added some console.log messages so you can open the console and see what is happening with each load/unload:
<!doctype html>
<html>
<head>
<title>Test LocalStorage</title>
</head>
<body>
<h1>Hello World!</h1>
<div id="tabs">Open tabs = 0</div>
<script>
window.addEventListener("load", function() {
if (!localStorage.tabs) {
console.log("Create the tab count");
localStorage.setItem("tabs", 1);
// restore data in case of refresh, or set to initial value in case of new window
localStorage.setItem("data", sessionStorage.getItem("data") || "Initial");
} else {
console.log("Add one tab to the count");
localStorage.tabs++;
}
document.getElementById("tabs").innerHTML = "Open tabs = " + localStorage.tabs;
});
window.addEventListener("beforeunload", function() {
if (parseInt(localStorage.tabs) == 1) {
console.log("Last tab: remove localStorage");
// save the data temporarily in the sessionStorage (in case of reload)
sessionStorage.setItem("data", localStorage.getItem("data"));
localStorage.removeItem("tabs");
localStorage.removeItem("data");
} else {
console.log("There are more tabs open, decrease count by 1");
localStorage.tabs--;
}
});
</script>
</body>
</html>
Copy that code into a page, and open it in several tabs, you'll see how the number of tabs increases (and updates if you reload one of the open tabs). Then close them and with the last one, the "data" item in the localStorage will be cleared.

How to get the changed content in the page?

I wrote a user script for the latest Chrome browser. It seems the script can't get the changed content of the page after loaded (for example, after the page loaded, I clicked ¿sth? and an embedded window popped up).
Even if I used window.setTimeout(), I still can't the get updated content in the timer callback through document.getElementById(). I inspected the page and found that the popup element existed in the DOM.
Is this a limitation of user script? Or some other methods could be used to get the update in user script?
Update:
I tried DOMSubtreemodified event as suggested. But the behavior is still strange.
I added only one one line of JavaScript to the userscript for my.safaribooksonline.com,
document.addEventListener("DOMSubtreeModified", function () {
alert(eval('typeof OpenSignInPopup')); });
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup. But I can run the alert statement in the script console in the same page at the same time, and shows the result as "function".
This function was not loaded when the user script is running at first. So how can I use it in the user script?
You need to provide details, like the relevant code snippet(s) and the pages targeted.
In general, you can fire off the DOMSubtreeModified event in chrome. That should get you access to the changed DOM.
Also, are you sure the new content is not in an iframe?
Update for new OP info:
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup.
In Chrome, Greasemonkey code cannot interact with the page's JS functions like that. You'll need to inject your code into the page. See this SO answer for more information.

Is it possible to determine a tab's opener within a Google Chrome extension?

I am looking for a way to determine a given tab's opener (parent tab) within a Google Chrome extension.
I've looked at the documention for Tab but there doesn't really seem to be anything that would yield this information. http://code.google.com/chrome/extensions/tabs.html
I've tried injecting this content script into pages (thinking I could pass the value to my background page):
alert(window.opener);
.. but it just yields null.
The best thing I've come up with so far is to keep track of the currently focused tab, and whenever a new tab is created, just assume that the focused tab is the opener/parent of the new tab. I believe this would de facto identify the parent tab correctly most of the time since background tabs rarely (are allowed to) open new pages. However, it seems kludgey and potentially inaccurate at times -- for example, if another extension opened a new tab, this method may misidentify the new tab's opener.
Update: it is now possible to reliably determine a tab's opener tab within a Chrome extension natively using the newly added webNavigation API, and specifically by hooking the onCreatedNavigationTarget event.
https://code.google.com/chrome/extensions/trunk/webNavigation.html
Chrome has added an experimental extension API which can accomplish this -- specifically webNavigation.onBeforeRetarget. http://code.google.com/chrome/extensions/experimental.webNavigation.html
However since this is still experimental (not usable in Chrome stable versions or releasable on the Chrome Web Store) I have ended up using another approach.
Basically:
In content_script.js:
chrome.extension.sendRequest({
request: {
op: "pageLoadStarted",
url: document.location.href,
referrer: document.referrer
}
});
In background.html:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
console.log('onRequest: ' + JSON.stringify(request));
console.log(JSON.stringify(sender));
});
This approach allows me to obtain the referrer of a tab, which I can then correlate with an existing tab's url. This isn't always a one-to-one mapping, so I do some additional magic such as preferring the currently selected tab as the opener if its url matches the new tab's referrer.
This really is just a hack to approximate the functionality that would be provided more simply and accurately by webNavigation.onBeforeRetarget or window.opener.
Further investigation has revealed that onCreatedNavigationTarget() does not always fire when you think it would to indicate an opener-opened relationship.
An additional hint can sometimes be found in the Tab object returned by chrome.tabs.onCreated/onUpdated in the .openerTabId parameter.
A comprehensive solution will probably have to rely on multiple of the methods described in these answers.
port.onMessage.addListener(
function(msg) {
var tabid = port.sender.tab.openerTabId;
console.log("Received message from tab that was opened by tab id : " + tabid);
// reliably shows the tab id of the tab that opened
// the tab sending the message
});

Are there "Pop Up Blockers"/Add Ons that change a post to a get in IE8?

We have some code where the user clicks a link which launches a pop up window. The code that creates the window then does an HTTP post to the window. Once the post has succeeded, the page is redirected (as a javascript location) to a PDF that was created during the post.
One person is getting an error where the posted data is not getting posted. In fact, the request is coming across as a GET.
Originally I thought this may be some kind of bookmark to the original page issue. But it happens in two different places that use the same concept in a different manner. And, since the post is triggered through JavaScript and the result is immediately relocated it would be no trivial matter to actually get a link to the original page.
So, the question is, are there any "pop-up" blocker like security tools that would allow pop-up's but convert all POSTS on them to GETS?
Example Call:
function LoadPDF(File){
document.forms[0].PDF.value = File;
win = "Window" + Math.round(Math.random()*100000);
open("",win,'toolbar=no');
function SubmitForm(){
document.forms[0].action = 'CreatePDF.cfm';
document.forms[0].target = win;
document.forms[0].submit();
}
//Give window time to open.
setTimeout(SubmitForm,550);
}
The code that creates the window then does an HTTP post to the window.
Popup blockers block popups as they are opening, which is pretty much the point of their existence. It would have to be a pretty lame popup blocker that allowed the popup to open and then translated the POST to a GET. It's possible a GreaseMonkey script or extension could translate it maybe.
Tell the user to disable any plugins/extensions and try again.