window.localStorage vs chrome.storage.local - javascript

I'm developing a Chrome extension and I need to store some data and then get it in some point. I did investigation on available storages and came across to the following ones: window.localStorage and chrome.storage.local.
So my question is, which one is the right choice to use in Chrome extensions:
window.localStorage or chrome.storage.local?
P.S. I'm using browser action to load a local HTML in IFRAME. So I'm not using popup.js.

localStorage
Pros:
Synchronous, and thus easier to work with: var value = localStorage[key]
Has support in Dev Tools: Resources > Local Storage to view and modify.
Cons:
Only stores strings, therefore you need to serialize data yourself, i.e. with JSON.stringify
Is not accessible from content scripts (or rather, context scripts share it with the page and not the extension), so you need to rely on Messaging to pass values to them.
Synchronous AND shared between concurrently-executing extension pages, leading to possible synchronization issues.
chrome.storage.local
Pros:
Automagically serializes JSON-compatible data, can store non-strings with no additional boilerplate.
Fully available within Content Scripts.
Supports events that notify about changes: chrome.storage.onChanged
With "unlimitedStorage" permission, can hold arbitrarily large amounts of data.
Has a nice built-in mechanism for default values:
chrome.storage.local.get({key: defaultValue}, function(value){/*...*/});
Fully supported in Firefox WebExtensions and Edge Extensions.
Cons:
Asynchronous, therefore a bit harder to work with:
chrome.storage.local.get("key", function(value){/* Continue here */});
Not visualized in Dev Tools; one needs to call chrome.storage.local.get(null) to get all values or use something like Storage Area Explorer.
chrome.storage.sync
Same as above, but:
Pros:
Automatically synced between signed-in Chrome instances, if extensions sync is enabled.
Cons:
Inflexible quotas on data size and update frequency.
As of 2016-11-06, not yet supported in either Firefox WebExtensions or Edge Extensions, so non-portable.
Note: storage.sync is now FF WebExtension compatible, though there is no way to make Chrome and FF natively sync between each other.

It depends entirely on what your Chrome Extension will be doing. window.localStorage is HTML5 storage. Unless you're running it in the background page, it can only allow you to get and set data into storage for a specific domain. This is also true for code injected into the DOM, since it would use the localStorage on the web page.
In other words, you won't be able to share data across different web pages unless you use localStorage in the background page, which operates independently of web pages, since it has a chrome:// URI as its domain.
chrome.storage.local, on the other hand, is designed for Chrome Extensions and Chrome Apps to store data in a more central location. Since this isn't accessible to normal web pages, each Extension gets its own storage. One possibility is for your background page to handle dealing with the setting and getting of the data, while your content scripts deal with modifying and interacting with the web page.
However, these API's work in content scripts as well, and both of the extensions I've written use chrome.storage.local called from the content scripts.
As an example, I built a Stack App that preserves inbox items in Stack Exchange until you've actually read them, called StackInbox. Since Stack Exchange sites span across hundreds of domains, I chose chrome.storage.local because I could save the user's accountId and reuse it across all the sites, ensuring that the inbox data is synchronized, while also using this directly in the content script.
As a simple test, put some data in localStorage on one domain, in a content script, and try to pull it from another, and you'll see that the data won't be there. With chrome.storage.local, this isn't a problem.
Lastly, Chrome Extensions and Chrome Apps are whitelisted, since the user chose to install it, so they typically can do more things than a normal website. For instance, by specifying the "unlimitedStorage" permission in your manifest, you can store data well beyond the 5MB limit placed upon HTML5 localStorage.
For more information, see Google's documentation on Chrome Storage.

Related

How do you properly handle caching static web content?

Browsers cache static files. It's what they're designed to do. 99% of the time, that's a good thing. Until we as developers update that static content.
If a developer updates a javascript file, but a user's browser pulls the cached version of it, then:
Best case, it'll be missing some new functionality until the browser decides to update its cache
Worse case, if you also updated the html page to call a javascript function that didn't exist in the older version of the javascript file that the browser cached, your page breaks
As developers, we know to hit Ctrl+Shift+R, or Ctrl+F5, or open dev console, disable cache on the Network tab, and reload. But users don't know that.
What is the best practice to handle updates to static content?
Is it to make sure that when you add new functions to a .js file, you push out the update to production a few hours/days before you update the html to call that function in <script> tags, allowing browsers to updated their cache over that time?
Is it to not call javascript functions from HTML within <script> tags at all?
Is there a way to somehow force browsers to expire cache on a specific static file when you update it?
Something else?
Obviously disabling all caching on your site is possible, but not a realistic solution.
PS. I'm not using any kind of frontend framework - just raw javascript/jquery. If the situation is different with frontend frameworks, I'd love to heard about that too at a high level
If I understand correctly, you want the JavaScript file to be updated for the user when you update. you should use service work API to create a cache version for specific files or use the Google workbox library. click here. for service worker API click here
Some years ago location.reload(true) allowed bypassing the cache like CTRL / Command+Shift+R does. Only Firefox continues to support this feature by now, but the hard reload using javascript is no longer supported on chromium based browsers. (spec doesn't describe this feature (anymore))
This change was also discussed on this issue on github/Microsoft/TypeScript and several other places on the web.
jQuery uses a simple workaround to be compatible with almost everything. If you load something with jQuerys jQuery.ajax({ url, cache: false }), it appends a _=TIMESTAMP parameter to the url, which has a similar effect but may bloat the cache.
You can make use of the Entity tag header (ETag). Entity tags are similar to fingerprints and if the resource at a given URL changes, a new Etag value must be generated by the server, which is a similar behavior to the Last-Modified header. (caniuse:etag)
Entity tags in: Apache, IIS, nginx (nginx docs), nodejs
It is also possible to clear the sites cache with a Clear-Site-Data: "cache" header. (mdn, caniuse:clear-site-data)

Cross domain local storage using iframes - "Block third-party cookies"

There are already a few questions related to using the local storage with iframes to be able to share data across different domains. However, none of them addresses the issue when the "Block third-party cookies" is enabled.
Currently, by default now Chrome uses the option "Block third-party cookies in Incognito" which breaks the localStorage use within iframes whenever you use the incognito mode.
Is there any workaround for this problem? We're using post message to send the data for the iframe.
The behavior you are describing sounds exactly like the pattern of behavior the Third-Party Cookie Block is intended to prevent.
There have been numerous changes in Chrome (and other browsers) regarding cookies and iframe.
The basics of what is changing is there is now a 'SameSite' cookie policy, where Only cookies set as SameSite=None; Secure will be available in third-party contexts, provided they are being accessed from secure connections.
Also in safari, the third-party frame will have to request access to the storage API before the cookie will be accessible.
Firefox is using a partitioned approach to the storage, and so the frame will behave as normal unless you then open your application as a new window then the cookie store may or may not follow depending on how the new window was created.
Cookie Status is an excellent resource to track how third party cookies work in the different browsers and what you should change to make it work.
I want to add my two cents here because all replies to this question completely miss the point of what's being asked. Take what I have here with a grain of salt, it's based on the most recent versions of Chromium and my personal experience, but maybe it can help someone understand the mess Chromimium has made.
Obscure Chromium Setting
First and foremost the setting within Chromium applications does not explicitly state that local storage or anything regarding "data" will be impacted by "blocking third-party cookies".
Ironically this setting used to actually explain that third-party cookies and data would be blocked, but in recent versions no longer mention data anymore, just cookies.
Is local storage a Cookie?
No. Local storage has nothing to do with cookies, and therefore the option for "blocking third-party cookies" is disingenuous because it lacks describing that local storage will also be blocked.
Local Storage data is stored by the browser for a particular domain. This data is not shared or exposed in any way.
So does local storage have "third-party data"?
No, there is also nothing "third-party" about local storage.
In context of cookies, a "third-party cookie" is a cookie for a domain that was created by a different domain, hence being "third-party". This allows domains to inject data into cookies that get sent to a different domain, which could be useful if you want to let that other domain know something, though this could also become nefarious. This essentially was a way of two domains to have a communication channel based on the user's session, but it becomes a privacy concern because it enables these domains to communicate in context of the user.
What does "third-party" mean for local storage? Nothing. Local storage is bound to the domain that's accessing the storage object - there is no "third-party" mechanism when setting or retrieving data from local storage since it is always in context of the window frame where the code is executing.
This further exasperates the problem: Why does "blocking third-party cookies" prevent local storage which is neither "third-party" nor a "cookie"?
So what does this setting do to local storage?
The "block third-party cookies" setting will block, as the name suggests, third-party cookies, but will also block local storage within an embedded iframe document. The embedded page will not be able to access the local storage property and will throw "Access denied" exceptions when the web page attempts to do so.
Blocking third-party cookies will have no impact to websites since it's used as a mechanism to share information with no returned output and no dependency of success. If your app uses local storage, it will likely break without it.
What's the security concern?
Doesn't that make sense that an embedded page can't access the local storage?
As other comments have incorrectly stated is that accessing the local storage within an embedded iframe would essentially enable cross-domain data access.
This is incorrect. The localStorage property is unique to the window variable of the frame, it is not unique to the parent domain. In other words, if you have an embedded iframe it will have a separate local storage than the parent window. This is because local storage is unique to the domain for which the code is executing in, and therefore there is no "cross-domain" access happening as part of it.
There must be other ways this is a security concern
As other comments have mentioned, the ultimate concern is leaking data across domains. So how can this happen?
It is technically possible to access the local storage property bi-laterally - child iframes can access their parent's window property and vice-versa, parent frames can access embedded iframe window objects, however Chromium blocks this by default. I tried turning off all security settings within Chromium and could not directly access the localStorage property in a parent/child or child/parent direction.
In the context of Chromium I have no reason to believe that local storage can be accessed across domains in any way unless it's explicitly instructed by the frame source page using a special header.
So why does Chromium block local storage in iframes?
Perhaps it made sense at a time before local storage became what it is today, or before accessing iframe window properties from relative frames was prevented.
Ultimately if Chromium implements local storage properly, there should be no possibility of cross-domain access without the hosting website being explicitly configured to allow such behavior. See FireFox for an example of this done properly.
What should Chromium do?
Separate out blocking local storage into it's own setting, and it should be disabled by default because there is very little reason to outright disable the entire feature that breaks a website.

LocalStorage variable auto disappear

This is might be a dump question but i could not figure it out why.
So, i have to permanently store some configuration number into the browser, so if the app reload, it can get those config number right away. I think we can do it by using localStorage.
I implemented and got it working, using :
localStorage.setItem('token', 'fsdfdsfsdfdsfds');
localStorage.setItem('config1', 'config1');
localStorage.setItem('config2', 'config2');
localStorage.setItem('config3', 'config3);
However, after 2 hours all of the config1, config2, config3 are gone. Only the token one still exists in localStorage. I though that item in localStore should stay as long as we want. We have full control over it.
Any explain here ? Thanks
I suggest you use Chrome.storage.api, the data will persists when you close the browser. Works the same, key/pairs are stored and retrieved. I stopped using localStorage when I can do the same in Chrome.storage api.
I'm not sure how Chrome handles localStorage in incognito mode so I can't give you a detailed answer but one thing I know is that you can't rely on localStorage in incognito.
Check MDN -> Web Storage API -> Private Browsing / Incognito modes
Most modern browsers support a privacy option called 'Incognito', 'Private Browsing' or something similar that doesn't store data like history and cookies. This is fundamentally incompatible with Web Storage for obvious reasons. As such, browser vendors are experimenting with different scenarios for how to deal with this incompatibility.
Most browsers have opted for a strategy where storage APIs are still available and seemingly fully functional, with the one big difference that all stored data is wiped after the browser is closed. For these browsers there are still different interpretations of what should be done with existing stored data (from a regular browsing session). Should it be available to read when in Private mode? Then there are some browsers, most notably Safari, that have opted for a solution where storage is available, but is empty and has a quota of 0 bytes assigned, effectively making it impossible to write data to it.
Developers should be aware of these different implementations and take them into account when developing websites depending on Web Storage APIs. For more information please have a look at this WHATWG blog post that specifically deals with this topic.

How to ensure that JavaScript page does not communicate

I created a small JavaScript application for which I reused some (quite large) JavaScript resources that I downloaded from the internet.
My application runs in the browser like other interactive web applications but works entirely offline.
However, I intend to enter some private information in the application which it shall visualize. Since I cannot ultimately trust the JavaScript pieces that I downloaded, I wonder if there is a JavaScript option to make sure that no data is downloaded and, in particular, uploaded to the web.
Note that I am aware that I can cutoff the local internet connection or perhaps change browser settings or use an application firewall, but this would not be a solution that suits my needs. You may assume that the isolation of a browser instance is save, that is no other, possibly malicious, web sites can access my offline JavaScript application or the user data I enter. If there is a secure way to (automatically) review the code of the downloaded resources (e.g. because communication is possible only via a few dedicated JavaScript commands that I can search for) that would be an acceptable solution too.
You should take a look at the Content Security Policy (CSP) (see here and here). This basically blocks every connection from your browser to any other hosts, unless explicitely allowed. Be aware that not all browsers support CSP, which leads to potential security problems.
Reviewing the library code might be difficult because there are many ways to mask such code pieces.
Find it yourself by watching your browser's network activity while your application is in action.
There are more than enough tools to do this. Also, if you know how to use netstat command line tool, it is readily shipped with windows.
Here is one cool chrome extension which watches the traffic of the current tab.
https://chrome.google.com/webstore/detail/http-trace/idladlllljmbcnfninpljlkaoklggknp
And, here is another extension which can modify the selected traffic.
https://chrome.google.com/webstore/detail/tamper-chrome-extension/hifhgpdkfodlpnlmlnmhchnkepplebkb?hl=en
You can set the filters and modify all requests/responses happening in your page.
If you want to write an extension to block requests yourself, check this answer out.

Saving data to a local file using only JavaScript

The set-up in question:
I have a stand alone, offline, kiosk mode instance of Chrome running on a Windows machine. I have full access to the system and any admin rights. I can start Chrome with any flags set or unset.
The task:
I have been asked to create a log file which tracks user activity within the offline app I am coding. It's a simple form of analytics which will append each event to the end of the file separated with a comma. The file will then be sent to a server once a day via a scheduled task. (None of this is my idea so please don't troll me)
Ruled out:
Any server side code - I have lobbied for Node, PHP etc but as this will be distributed to many different installations so we cannot guarantee this will be installed.
Flash/ActiveX/Java - ideally would like to avoid this (even though these will be installed by default)
Possible solutions:
File API - I have looked at this but AFAIK if opens dialogue boxes to save the data to each file and this needs to happen in the background.
Security - I have read in other SO Questions that this can be achieved if the security settings are reduced but no-one goes on to explain which ones. Is there a simple flag which allows it?
How to enable local file system read write access from Google chrome? - similar question!
Ideal result: (something akin to PHP)
$file = 'log.txt';
$current = file_get_contents($file);
$current .= ",clicked:link";
file_put_contents($file, $current);
Possible ideal side result: proving this isn't possible and forcing PHP/Node/Java to be used ;)
In reply to those suggesting local storage : I'm not storing unique key/value pairs and that is very much like setting a cookie. Similarily there are file size limits.
To those suggesting web SQL such as SQLite in chrome - there are file size limits if it's not a chrome extension. The only way I see that working is if I were to find the location of the file in the windows directory (C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\databases) and upload that from the schedules task. Perfectly feasible but it is not a desirable answer.
You could use HTML5?
http://diveintohtml5.info/storage.html
var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);
You can use the Chrome Apps File API, you will need to grant access to the file via a user action once, but after that you can get access the file again by using restoreEntry
You can use localStorage to save offline data. It's impossible to access other files using Javascript since it's a violation of the sandbox.
From http://en.wikipedia.org/wiki/JavaScript#Security:
JavaScript and the DOM provide the potential for malicious authors to deliver scripts to run on a client computer via the web. Browser authors contain this risk using two restrictions. First, scripts run in a sandbox in which they can only perform web-related actions, not general-purpose programming tasks like creating files.
You may want to look into Local Storage which is part of the HTML5 spec.
This will only be supported in modern browsers though.
If you need to use older browsers then may still be able to achieve what you're after using dojox.storage
Use HTML5 features like Web Storage or Web SQL database to store your logs.
Whenever needed read logs from the client side storage and send it back to the server & delete the client storage.
Refer http://www.html5rocks.com/en/features/storage.

Categories

Resources