Skip to content

Fix bugs related to strict privacy settings in browsers#1166

Open
zner0L wants to merge 3 commits intomasterfrom
z_indexeddb_bug
Open

Fix bugs related to strict privacy settings in browsers#1166
zner0L wants to merge 3 commits intomasterfrom
z_indexeddb_bug

Conversation

@zner0L
Copy link
Copy Markdown
Member

@zner0L zner0L commented Nov 6, 2024

This should also fix the Error: No available storage method found. that was reported via email several times.

@zner0L zner0L requested a review from baltpeter November 6, 2024 20:55
@zner0L zner0L changed the title Properly handle disabled cookies in the privacy controls Fix bugs related to strict privacy settings in browsers Nov 6, 2024
@cypress
Copy link
Copy Markdown

cypress bot commented Nov 6, 2024

datenanfragen/website    Run #8314

Run Properties:  status check passed Passed #8314  •  git commit 29b24bded4: Fixed #1014, #1089: Skip errors we can not control
Project datenanfragen/website
Branch Review z_indexeddb_bug
Run status status check passed Passed #8314
Run duration 03m 41s
Commit git commit 29b24bded4: Fixed #1014, #1089: Skip errors we can not control
Committer Lorenz Sieben
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 1
Tests that did not run due to a developer annotating a test with .skip  Pending 8
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 80
View all changes introduced in this branch ↗︎

};

export class SavedIdData {
// Get rid of localforage at some point.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a TODO comment?

type KeyValueDatabase = IDBPDatabase<{ [key: string]: string }>;

const errorFilter = (e: Error) =>
// These migh be caused if IndexedDB is disabled in Firefox
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// These migh be caused if IndexedDB is disabled in Firefox
// These might be caused if IndexedDB is disabled in Firefox

// These migh be caused if IndexedDB is disabled in Firefox
e.name === 'InvalidStateError' ||
e.name === 'SecurityError' ||
// We couldn’t identify the cause for this error, but it seems to be caused by problem in the browser, so there is
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We couldn’t identify the cause for this error, but it seems to be caused by problem in the browser, so there is
// We couldn’t identify the cause for this error, but it seems to be caused by a problem in the browser, so there is

}
} catch (e) {
if (e instanceof Error && errorFilter(e)) {
return;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we're returning undefined instead of false here?

Comment thread src/privacy-controls.tsx
Comment on lines +95 to +101
{!navigator.cookieEnabled ? (
<div className="box box-info">
<Text id="explanation-cookies-disabled" />
</div>
) : (
<></>
)}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{!navigator.cookieEnabled ? (
<div className="box box-info">
<Text id="explanation-cookies-disabled" />
</div>
) : (
<></>
)}
{!navigator.cookieEnabled && (
<div className="box box-info">
<Text id="explanation-cookies-disabled" />
</div>
)}

@baltpeter
Copy link
Copy Markdown
Member

baltpeter commented Oct 14, 2025

I've been trying really hard to trigger the errors this PR guards against (by using a build without this changes, of course) but just have not been successful.

I've tried (unsuccessfully) to hit the Uncaught UnknownError: Internal error. (#1014 (comment)).

I've also tried to trigger the other errors related to IDB being disabled. Here's what I tried:

In Firefox 144.0:

  • Use in private window (works without issues)
  • Tools -> Page Info -> Permissions -> Store data in persistent storage: Block (doesn't seem to have any effect, neither in normal nor private window)
  • In about:config, disable dom.indexedDB.privateBrowsing.enabled (in private window, storage correctly falls back to local storage, I didn't notice any issues)
  • Disabling IDB specifically isn't possible anymore since Firefox 72 (https://bugzilla.mozilla.org/show_bug.cgi?id=1488583)
  • In about:preferences#privacy, set "Enhanced Tracking Protection" to custom and the maximum: especially "Block all cookies (will cause websites to break)", disable "fix major site issues" (the privacy controls for "My requests" and "Saved ID data" are automatically disabled correctly, if I try to enable them, they are reset on the next load)
  • In about:preferences#privacy, set History -> "Firefox will" to "Use custom settings for history" and enable "Always use private browsing mode", via (works without issues)

In Tor Browser 14.5.8 (based on Mozilla Firefox 128.14.0esr), using the hosted site:

  • Use regularly (works without issues)
  • In about:preferences#privacy, under "Cookies and Site Data", click "Manage exceptions" and block https://www.datarequests.org (has no effect, we do still data in IDB without issues, lol)
  • Tools -> Page Info -> Permissions -> Store data in persistent storage: Block (doesn't seem to have any effect, either)

@baltpeter
Copy link
Copy Markdown
Member

I've finally been able to trigger an error in Chromium 141.0.7390.54 (Official Build) snap (64-bit)!

In chrome://settings/content/siteData, enable "Don't allow sites to save data on your device (not recommended)".

This causes a lot of errors to be thrown when visiting any page:

Debug information:

{
    "message": "Uncaught UnknownError: The user denied permission to access the database.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "code": 0,
        "message": "The user denied permission to access the database.",
        "description": "Unexpected error while opening IndexedDB in PrivacyAsyncStorage.getDb",
        "name": "UnknownError",
        "enduser_message": "An unexpected error occured while trying to access the database in your browser.",
        "context": {
            "options": {
                "storeName": "proceedings",
                "name": "Datenanfragen.de"
            }
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught UnknownError: The user denied permission to access the database.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "code": 0,
        "message": "The user denied permission to access the database.",
        "description": "Unexpected error while opening IndexedDB in PrivacyAsyncStorage.getDb",
        "name": "UnknownError",
        "enduser_message": "An unexpected error occured while trying to access the database in your browser.",
        "context": {
            "options": {
                "storeName": "proceedings",
                "name": "Datenanfragen.de"
            }
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught Error: No available storage method found.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "message": "No available storage method found.",
        "description": "Could not retrieve all fixed id_data",
        "name": "Error",
        "stack": "Error: No available storage method found.\n    at driverPromiseLoop (webpack-internal:///./node_modules/localforage/dist/localforage.js:2718:33)",
        "context": {
            "desc": "Email address"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught UnknownError: The user denied permission to access the database.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "code": 0,
        "message": "The user denied permission to access the database.",
        "description": "Unexpected error while opening IndexedDB in PrivacyAsyncStorage.getDb",
        "name": "UnknownError",
        "enduser_message": "An unexpected error occured while trying to access the database in your browser.",
        "context": {
            "options": {
                "storeName": "proceedings",
                "name": "Datenanfragen.de"
            }
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught UnknownError: The user denied permission to access the database.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "code": 0,
        "message": "The user denied permission to access the database.",
        "description": "Unexpected error while opening IndexedDB in PrivacyAsyncStorage.getDb",
        "name": "UnknownError",
        "enduser_message": "An unexpected error occured while trying to access the database in your browser.",
        "context": {
            "options": {
                "storeName": "proceedings",
                "name": "Datenanfragen.de"
            }
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

Debug information:

{
    "message": "Uncaught UnknownError: The user denied permission to access the database.",
    "type": "error",
    "colno": 5,
    "filename": "webpack-internal:///./src/Utility/errors.ts",
    "lineno": 47,
    "error": {
        "code": 0,
        "message": "The user denied permission to access the database.",
        "description": "Error in doesStoreExist",
        "name": "UnknownError",
        "enduser_message": "An unexpected error occured while trying to access the database in your browser.",
        "context": {
            "name": "Datenanfragen.de",
            "storeName": "my-requests"
        }
    },
    "defaultPrevented": false,
    "eventPhase": 2,
    "isTrusted": true,
    "returnValue": true,
    "code_version": "1.0.0",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "url": {
        "ancestorOrigins": {},
        "href": "http://localhost:1314/id-data-controls/",
        "origin": "http://localhost:1314",
        "protocol": "http:",
        "host": "localhost:1314",
        "hostname": "localhost",
        "port": "1314",
        "pathname": "/id-data-controls/",
        "search": "",
        "hash": ""
    }
}

@baltpeter
Copy link
Copy Markdown
Member

The Chromium "Don't allow sites to save data on your device (not recommended)" problem is not fixed by this PR.

@baltpeter
Copy link
Copy Markdown
Member

With this setting, there is also another error that isn't fixed by this PR, either:

image

For some reason, the error handler doesn't include that error and trying to copy it from the dev tools produces useless output, so here's a screenshot of the error object:

image

This is fact happens whenever you try to access window.localStorage:

image

And, for some reason, navigator.cookieEnabled is true:

image

@baltpeter
Copy link
Copy Markdown
Member

Alright, to summarize:

  • I'm almost convinced that (currently, who knows what will happen in the future), it isn't possible to reproduce the problems wrt disabling site storage in Firefox anymore. But I don't mind us guarding against them just in case.
  • The Internal error. problem is probably still possible but you need to hit some really unusual edge cases, which from my research, no-one else has been able to do deliberately, either. But I am confident that the changes in this PR handle this case as well as we can.
  • If the Chromium problem is fixed and my minor nits above are addressed, I am happy to merge this (finally, sorry :|).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

JS error (Uncaught UnknownError: The user denied permission to access the database.)

2 participants