ERROR: QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to
add something to storage that exceeded the quota.”

Safari in Private Browsing on iOS and OSX

So apparently Apple didn’t want to (or for undisclosed technical reasons
couldn’t) support the WebStorage standard (known as localStorage and
sessionStorage) in Private Browsing mode.

EDIT 2017-10-17: Alexander points out in the comments below that Apple fixed
this, and that it should ship in iOS 11

Other browsers fully support the protocols, with the understanding that
at the end of the private browsing session the storage will be wiped
clean.

As far as I know the feature specification doesn’t define what browsers
should do in Private Browsing, so I suppose its not technically a spec
violation.

If Apple didn’t want to support it, they should have just not exposed
the localStorage or sessionStorage properties on window. Then
everybody’s if (window.localStorage) checks would work correctly and
we could move on with our lives.1

But instead of doing that, they made it seem like it was available but
instead throw an exception when you try to write to it. Reading just
returns null, and remove is apparently a no-op. But as soon as you
attempt to write, your page explodes. This is probably half way through
some process, making it more difficult to diagnose than necessary.

Why expose a broken API?

Frequently Asked Questions

Why did Apple do this?

I don’t know.

Care to speculate?

Sure. It’s probably some difficulty with their technical implementation
that made it difficult to clear the storage at the end of the session.
They’re already doing that with cookies, so I doubt it was just the
confused orders of some middle manager.

How do I reliably feature detect localStorage?

You’ll have to attempt a write and catch the raised exception. It’s not
enough to just check the existence of window.localStorage.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

functionisPrivateBrowsingSupportedEvenIfThisIsSafari() {

if (window.localStorage) {

var test = "__localstoragetest__";

try {

window.localStorage.setItem(test, test);

window.localStorage.removeItem(test);

} catch(ex) {

console.log("No storage for you!");

returnfalse;

}

returntrue;

}

returnfalse;

}

What if I’m relying on localStorage and need to support private browsing on Safari?

That sounds like trouble. I feel for you.

You need to store that data server-side and retrieve it when needed.

If your data storage needs are small, you can polyfill localStorage with
cookies, but in my experience its pretty easy to hit the max cookie
size, especially if you’re URL encoding JSON.

Its probably better to treat localStorage as a progressive enhancement:
it adds useful extra features but is not a key requirement.

What if I’ve completely architected my app around localStorage and just discovered this in production?

You’ll obviously need to re-architect or tell those creepers to quit
using private browsing.

And add Safari Private Browsing to your QA device support matrix.

1.Feature detection now requires you to attempt a write and catch the exception. ↩