I am using the 'chrome.storage.sync.get/set' to save my data. My question is, will the data saved using this API will get reset when I close chrome browser window and open it again. Is there any method to clear the data saved when we exit from chrome? I know there is a method 'chrome.storage.sync.clear()'. But this should happen only when the user exits from chrome.
will the data saved using this API will get reset when I close chrome browser window and open it again
No, it's saved — not just locally, but also potentially synced to the user's Google account. That's the point of the sync storage area. The documentation says sync is like localStorage, but synced to the user's account.
If you're using it for transient data, don't. Use local instead (as there doesn't appear to be an extension equivalent of session storage) or perhaps just store the data in your extension's runtime environment (it's not clear what you're using this for).
I know there is a method chrome.storage.sync.clear(). But this should happen only when the user exits from chrome.
You'd have to trigger clear from an event. Unfortunately, there is not currently an official way for an extension to get notified when Chrome closes (there's an open issue on it). Hopefully there will be a way at some point, but there isn't currently.
You're right chrome.storage.sync.clear(), removes all storage from sync. However, if you want to use that function when the browser 'exists', you'll have to look at the Processes Api.
You would probably want to use this function (from the documentation) :
chrome.processes.onExited.addListener(function(){...});
It takes processId as one of the arguments. So you would just have to get hold of the processId for the browser process. I found a relevant answer for this on SO only. It suggests you do something like:
//Basically loop through all the processes to get the browser's Process Id
var browserId;
chrome.processes.getProcessInfo([], false, function(processes) {
processes.forEach(function(process) {
if (process.type === 'browser') {
browserId = process.id;
}
});
});
Once you have the browser's Process Id, you can add a listener to the exit event and do the needful. I hope it gets you started in the right direction.
Related
I am trying to do an API call when the user is trying to close/reload the browser/tab. I don't want to call the API if the user clicks on cancel. I followed JavaScript, browsers, window close - send an AJAX request or run a script on window closing, but it didn't solve my issue. I followed catching beforeunload confirmation canceled? for differentiating between confirm and cancel. I have no idea how to make the API call when the user reloads/closes the browser and not to call the API when user clicks on cancel. I followed JavaScript, browsers, window close - send an AJAX request or run a script on window closing and tried like
For showing alert on reload or close the tab
<script>
window.addEventListener("onbeforeunload", function(evt){
evt.preventDefault()
const string = '';
evt.returnValue = string;
return string;
})
</script>
and on click of cancel, nothing should happen. If the user is forcefully closing the browser or reloading, the API should be called
<script type="module">
import lifecycle from 'https://cdn.rawgit.com/GoogleChromeLabs/page-lifecycle/0.1.1/dist/lifecycle.mjs';
lifecycle.addEventListener('statechange', function(event) {
if (event.originalEvent === 'visibilitychange' && event.newState === 'hidden') {
var URL = "https://api.com/" //url;
var data = '' //payload;
navigator.sendBeacon(URL, data);
}
});
</script>
But it's not happening. Any help is appreciated. Thanks
Your problem is happening because you're using beforeunload to present a prompt.
I can see that you're handling the beforeunload event properly, so you must already be aware that browser vendors have deliberately limited the ability of script authors to do custom stuff when the user wants to leave the page. This is to prevent abuse.
Part of that limitation is that you don't get to find out what the user decides to do. And there will not be any clever workarounds, either. Once you tell the browser to present the beforeunload prompt, you lose all your power. If the user clicks the Okay button (i.e. decides to leave the page), the browser will refuse to run any more of your code.
Presenting the prompt creates a fork in the road that you are prevented from observing. So, put a laser tripwire there instead of a fork:
window.addEventListener("onbeforeunload", function(evt) {
navigator.sendBeacon(url, payload)
})
This is guaranteed to run when the user actually leaves the page, and only when the user actually leaves the page. But, you sacrifice the ability to try to talk the user out of leaving. You can't have it both ways.
You can't always get what you want, but if you try, sometimes you just might find you get what you need. -- The Rolling Stones
I can only think of one way to accomplish what you need, but it requires help from the server. This is not an option for most people (usually because the beacon goes to a third-party analytics provider who won't do this), but I'm including it here for completeness.
before the beforeunload handler returns, fire a beacon message that says "user is maybe leaving the page"
after firing that beacon, and still before returning, set up a document-wide mousemove handler that fires a second beacon message that says "the user is still here" (and also de-registers itself)
return false to present the prompt
modify your server so that it will reconcile these two events after some kind of delay:
if the server receives beacon 1 and then also receives beacon 2 (within some reasonably short time-frame, e.g. 5 minutes), it means the user tried to leave but then changed their mind, and so the server should delete the record of beacon 1
if the server receives beacon 1 but doesn't receive beacon 2 within the time-frame, then it means the user really did leave, and so the server would rewrite the previous beacon datapoint to say "user actually departed"; you wouldn't need to actually write beacon 2 to your datastore
(Or, depending on expected traffic and your infrastructure, maybe the server just holds the beacon 1 datapoint in RAM for the 5 minutes and commits it to your datastore only if beacon 2 never shows up. Or you could write both beacons to the database and then have a different process reconcile the beacons later. The outcome is identical, but they have different performance characteristics and resource requirements.)
P.S.: Never use "URL" (all caps) as a variable name in javascript. "URL" is actually a useful web API, so if you use that exact variable name, you're clobbering a useful ability. It's just like if you did let navigator = 'Henry'. Yes, it will execute without error, but it shadows a useful native capability.
I am trying to send data when the window closes to prevent 2 people from editing and overwriting each others data. Currently I am using a sendBeacon within a unload event handler.
FireFox:
Refresh: Works
Back button: Works
Close window: Works
Chrome:
Refresh: Works
Back button: Works
Close window: Doesn't work
Here is my code
function sendDataOnClose(edit,trans){
var url = "../../save.php"; //This has a post request handler and works properly with other functions for saving data
const data = JSON.stringify
({
"translations": trans,
"edit": edit
});
navigator.sendBeacon(url, data);
}
function handleClose(){
if(edit){
console.log("sending a false when edit is: "+ edit)
sendDataOnClose(false, translations);
}
}
window.addEventListener('unload', handleClose);
The latest sendBeacon documentation on MDN, states "The navigator.sendBeacon() method asynchronously sends a small amount of data over HTTP to a web server. It’s intended to be used in combination with the visibilitychange event (but not with the unload and beforeunload events)."
To use the visibilitychange event like suggested, you could
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon(handleClose);
}
});
I have experienced similar issues with trying send data on the unload event. Is the user base all on desktop? Mobile devices don't reliably fire the unload event. The Page Lifecycle API provides the visibility change event and the pagehide events which could be used together to get closer to your desired result.
The Page Lifecycle API attempts to solve this problem by:
Introducing and standardizing the concept of lifecycle states on the web.
Defining new, system-initiated states that allow browsers to limit the resources that can be consumed by hidden or inactive tabs.
Creating new APIs and events that allow web developers to respond to transitions to and from these new system-initiated states.
source
The issue you are experiencing is likely more of an issue without how browsers suspend pages or discard them entirely. Unfortunately, browsers are not unified on how they do this, and to add to the complexity there is different behavior on desktop vs. mobile.
There are several threads that dive in deeper to this issue if you are interested. Until browsers standardize on this, I'm not sure there is an easy answer, such as "use x event".
Issue filed on Page Visibility
Issue on MDN's strints about sendBeacon
Thanks to hackers, many other things are removed for security reasons.
I noticed your question had the PHP tag as well; I will give you a, not good idea, but a functional one. Avoid on-close-page handles even JavaScript or frameworks just post with JavaScript a table database where you store time() and an target id then if timeout is maybe more than 30 sec you set then you will remove from table that stuff, and you will know that page isn't still working (translation: use a server "online users" idea (bad but necessary one like anything generates lots of traffic in an app).
Using these in JavaScript in the side client is bad idea and you open gates for bad guys that will exploit your app.
We're writing an app that monitors online presence. There are multiple scenarios where we need the user to have more than one browser window open. We're running into a problem where the user, after opening and running the firebase js code in a secondary browser window, will close that secondary window. This sets their presence to offline in the primary window because the onDisconnect event fires in the secondary window.
Is there a workaround for this scenario? Is this where the special /.info/connected location could be used?
The .info/connected presence data only tells a given client if they are linked up to the Firebase server, so it won't help you in this case. You could try one of these:
Reset the variable if it goes offline
If you have multiple clients monitoring the same variable (multiple windows falls into this category), it's natural to expect them to conflict about presence values. Have each one monitor the variable for changes and correct it as necessary.
var ref = firebaseRef.child(MY_ID).child('status');
ref.onDisconnect().remove();
ref.on('value', function(ss) {
if( ss.val() !== 'online' ) {
// another window went offline, so mark me still online
ss.ref().set('online');
}
});
This is fast and easy to implement, but may be annoying since my status might flicker to offline and then back online for other clients. That could, of course, be solved by putting a short delay on any change event before it triggers a UI update.
Give each connection its own path
Since the purpose of the onDisconnect is to tell you if a particular client goes offline, then we should naturally give each client its own connection:
var ref = firebaseRef.child(MY_ID).child('status').push(1);
ref.onDisconnect().remove();
With this use case, each client that connects adds a new child under status. If the path is not null, then there is at least one client connected.
It's actually fairly simple to check for online presence by just looking for a truthy value at status:
firebaseRef.child(USER_ID).child('status').on('value', function(ss) {
var isOnline = ss.val() !== null;
});
A downside of this is that you really only have a thruthy value for status (you can't set it to something like "idle" vs "online"), although this too could be worked around with just a little ingenuity.
Transactions don't work in this case
My first thought was to try a transaction, so you could increment/decrement a counter when each window is opened/closed, but there doesn't seem to be a transaction method off the onDisconnect event. So that's how I came up with the multi-path presence value.
Another simple solution (Using angularfire2, but using pure firebase is similar):
const objRef = this.af.database.list('/users/' + user_id);
const elRef = objRef.push(1);
elRef.onDisconnect().remove();
Each time a new tab is opened a new element is added to the array. The reference for "onDisconnect" is with the new element, and only it is excluded.
The user will be offline when this array is empty.
I want to implement an idle time-out for the web application that we are building. I had earlier achieved this using AsynchronousSessionAuditor from codeplex, which essentially looks for the formsauthentication and session cookie timeout by constant polling.
But it has a draw back of not respecting the client side events, it will look for only last postback to decide when to log off.
The jquery plug jquery-idle-timeout-plugin from erichynds solves this issue of client side events but suffers from another drawback that is not able to recognise user is active on some other tab.
Is there anyone already fixed the TABBED browsing issue with jquery-idle-timeout-plugin already? Or is there any better approach of application time out for web applications (by the way this web app is build using asp.net f/w)
If I understand your question right, it is not possible, since there are no events triggered in javascript for activity outside of the current window/tab.
Unless you have a addon to go along with your website for each browser, which could monitor all activity in the browser, but that is not really a practical approach.
Well, you'd have to code it by hand, which is not really hard. You can use the onfocus and onblur functions to do something like this:
$(function() {
window.isActive = true;
$(window).focus(function() { this.isActive = true; });
$(window).blur(function() { this.isActive = false; });
showIsActive();
});
function showIsActive()
{
console.log(window.isActive)
window.setTimeout("showIsActive()", 2000);
}
function doWork()
{
if (!window.isActive) { /* Check for idle time */}
}
If you make a little search you can find that varaieties of this question have already been asked and answered, you can probably find a solution you can implement with one of the plugins you mentioned.
Try:
Run setTimeout only when tab is active
or
How to tell if browser/tab is active
EDIT--> ADDED:
Or I'd try a different approach. You could create a cookie with some hash and save that hash in your DB with a timestamp that updates whenever the window is active (you could check every 5 seconds or something, it's not an intensive request)
Then, do another check before(but in the same request) to see how much time has passed since the last timestamp and log them out if necessary.
it won't log them out isntantly when time has passed, but it will when they try to access the site either by opening it again or by focusing on the tab/window.
I'm using the following to successfully capture user's location (mobile browser):
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition);
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>
This works, but often times the browser will seemingly cache the location data. The page that calls this geolocation code shows information relative to the user's location, so what happens is the user can move (change location), the page is reloaded, but the previous location data is used (showing incorrect data). Sometimes the page will have to be refreshed once or even twice for the page to use new location data.
Does anyone know of any means to force the code to get and use "up to date" location data each time script is executed?
FWIW, I'm experiencing problem in iOS Safari (6.1). Have not been able to test in Android yet.
Thanks for reading and for any help.
Edit: As Oleksiy has written in his answer, the Geolocation API now supports this. You can add {maximumAge: 0} as the third option parameter of getCurrentPosition. There is also a timeout and a high accuracy option available in the PositionOptions as noted in the specification.
Your navigator call would change to the following:
navigator.geolocation.getCurrentPosition(
handlePosition,
(error)=>{},
{maximumAge:0}
);
No can't be done. You don't have any control over the browser geolocation other than the code in your example. The html5 geo location api is very, very limited and that is a pain. I also had a question whether I could ask it if permission for the domain had already been granted and the answer was also no.
The problem is that the api is implemented in the browser itself and that are just no endpoints for these kind of functions.
What you could do is make an array in js to store previous locations and before you update your view test against that array to see if you got a stale location.
You do have this ability now.
getCurrentPosition takes three parameters: success, failure and options
Try this:
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition, (error)=>{}, {maximumAge:0});
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>