blogccasion

Things not available when someone blocks all cookies

The other day, I received a harmless-looking Issue for my app SVGcode (announcement blog post). The Issue read:

Crash when opened with cookies blocked

Hey I block cookies by default. Unfortunately your website doesn’t handle that nicely despite it not needing (IMO) cookies to operate. I'm getting this error, because blocking cookies also blocks localStorage.

Uncaught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document. Please add fallback to js provided localStorage, because it makes the app unusable.

I don't use cookies in the app at all, but for sure, when I disabled cookies in Chrome, the app wasn't usable.

Chrome Settings with all cookies blocked.

All I am using is some innocent localStorage and IndexedDB to persist user settings like the values of the sliders or the chosen color scheme.

Turns out, with all cookies blocked, Chrome disables a lot of (all?) APIs that can be used to persist data and thus potentially profile users. Here are the ones that I found:

The code sample below shows all these APIs and the error messages they throw when you try to use them with cookies blocked.

localStorage;
// Uncaught DOMException: Failed to read the 'localStorage' property from Window: Access is denied for this document.

sessionStorage;
// Uncaught DOMException: Failed to read the 'sessionStorage' property from 'Window: Access is denied for this document.

await caches.open('test');
// Uncaught DOMException: An attempt was made to break through the security policy of the user agent.

const openRequest = indexedDB.open('test', 1);
openRequest.onerror = function () {
  console.error(openRequest.error);
};
// DOMException: The user denied permission to access the database.

openDatabase('test', '1', 'test', 1);
// Uncaught DOMException: An attempt was made to break through the security policy of the user agent.

await navigator.serviceWorker.register('.');
// Uncaught DOMException: Failed to register a ServiceWorker for scope ('https://example.com/') with script ('https://example.com/'): The user denied permission to use Service Worker.

await navigator.storage.getDirectory();
// Uncaught DOMException: Storage directory access is denied.

webkitRequestFileSystem(
  window.PERSISTENT,
  1,
  () => {},
  (err) => console.error(err)
);
// DOMException: An ongoing operation was aborted, typically with a call to abort().

webkitRequestFileSystem(
  window.TEMPORARY,
  1,
  () => {},
  (err) => console.error(err)
);
// DOMException: An ongoing operation was aborted, typically with a call to abort().

await navigator.locks.request('test', () => {});
// Uncaught DOMException: The request was denied.

await navigator.locks.query();
// Uncaught DOMException: The request was denied.

Did I miss anything? If so, please let me know!

Console errors when trying to access localStorage, sessionStorage, the Cache API, IndexedDB, and Web SQL.

The fix for the Issue was annoying, but simple. Always try...catch any potentially blocked calls:

SVGcode app with blocked cookies working and showing caught exceptions in the DevTools console.

Please report any other errors you encounter (I don't care for the analytics script failing). And thanks, @JakubekWeg for caring enough to having opened this Issue! Jakub is the proof that users exist who block any and all cookies. Check your error logs, you might be losing users, too!

(On a tangent, MDN is completely broken with cookies blocked, too. I was about to report this problem (because I care and love MDN 😍), when I discovered a PR is already under way that fixes the Issue. Thanks, @bershanskiy!)

MDN with blocked cookies

Since the user blocks cookies, I assumed cookies would of course not work, but I was made aware of an interesting interoperability case by @Semmel_Of_Nine when comparing the behavior of document.cookie and the Cookie Store API:

// All cookies are blocked in browser settings.

document.cookie = 'silently=ignored';
// > 'silently=ignored'
document.cookie;
// > ''

await cookieStore.set('throws', 'on-write');
// > Uncaught DOMException: An unknown error occured while writing the cookie.
await cookieStore.getAll();
// > []

The reading behavior is the same, both act as if there were no cookies by returning an empty string or an empty array respectively. The writing behavior is different, though. To align with document.cookie's write behavior, should write operations for the Cookie Store API fail silently when cookies are blocked? Asked this question in an Issue in the Cookie Store API's repo… Fun fact: spelling "occurred" is hard, double 'c' and double 'r' (crbug/1359247).

Amendment 2: Web Locks API

Twitter user @_bayotop pointed out that the Web Lock API is also affected.