update on safari
Safari (release v29) patched localstorage so that you can no longer use it for detection.
I saw one other solution that tries to save blob/files in indexedDB and that will reject with an error saying that it can't store fils when surfing in private mode.
but there is a new / easier method with the new whatwg/fs
navigator.storage.getDirectory().then(root => {
console.log('not private')
}, err => {
console.log('private')
})
Chrome 83 arrives with redesigned security settings, third-party cookies blocked in Incognito by default!
So this one is easy, create a iframe to a third party site, have it send a postMessage
back notifying you if navigator.cookieEnabled
is true or false. Ofc users have the option to disable third party cookie as well. So i tested and disabled 3th party cookies in the settings. But it still said cookie was enabled on third-party iframes using navigator.cookieEnabled
. it only became disabled once i used Incognito - perhaps a bug?
new Promise((rs, rj, m = new MessageChannel(), d = document, i = d.createElement('iframe')) => {
i.src = 'https://httpbin.org/base64/PHNjcmlwdD5vbm1lc3NhZ2UgPSBlID0+IGUuZGF0YS5wb3N0TWVzc2FnZShuYXZpZ2F0b3IuY29va2llRW5hYmxlZCk8L3NjcmlwdD4='
i.onload = _ => i.contentWindow.postMessage(m.port1, '*', [m.port1], m.port2.onmessage = e => i.remove(rs(e.data)))
i.hidden = 1
d.body.append(i)
}).then(thirdPartyCookieEabled =>
console.log('Third party cookie enabled:', thirdPartyCookieEabled)
)
You could also probably do it using only js + ajax but didn't want to set up a 2 servers to test it myself. but for this SameSite=none have to be set as well.
res = await fetch('https://httpbin.org/cookies/set?enabled=1', {
credentials: 'include'
})
json = await res.json()
console.log(!!json.cookies.enabled)
Here is my take on detecting private mode
function detectPrivateMode(cb) {
var db,
on = cb.bind(null, true),
off = cb.bind(null, false)
function tryls() {
try {
localStorage.length ? off() : (localStorage.x = 1, localStorage.removeItem("x"), off());
} catch (e) {
// Safari only enables cookie in private mode
// if cookie is disabled then all client side storage is disabled
// if all client side storage is disabled, then there is no point
// in using private mode
navigator.cookieEnabled ? on() : off();
}
}
// Blink (chrome & opera)
window.webkitRequestFileSystem ? webkitRequestFileSystem(0, 0, off, on)
// FF
: "MozAppearance" in document.documentElement.style ? (db = indexedDB.open("test"), db.onerror = on, db.onsuccess = off)
// Safari
: /constructor/i.test(window.HTMLElement) || window.safari ? tryls()
// IE10+ & edge
: !window.indexedDB && (window.PointerEvent || window.MSPointerEvent) ? on()
// Rest
: off()
}
detectPrivateMode(function (isPrivateMode) {
console.log('is private mode: ' + isPrivateMode)
})
edit found a modern, faster, synkronas way to try it in firefox (they don't have service workers in privat mode) similar to ie don't include indexedDB but the test only works in secure sites
: "MozAppearance" in document.documentElement.style ? navigator.serviceWorker ? off() : on()