├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── _locales │ └── en │ │ └── messages.json ├── content.ts ├── contentLoader.ts ├── icon.svg └── manifest.json ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ 3 | dist/ 4 | web-ext-artifacts/ 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Matt Hensman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hide Private Mode 2 | 3 | Firefox extension that provides an [IndexedDB implementation](https://github.com/dumbmatter/fakeIndexedDB) to sites in private browsing mode. 4 | 5 | ## Usage 6 | 7 | Ensure the extension is allowed to run in private windows: 8 | https://support.mozilla.org/en-US/kb/extensions-private-browsing 9 | 10 | ## Building 11 | 12 | ### Requirements 13 | 14 | * Node.js 15 | 16 | ### Instructions 17 | 18 | ````sh 19 | git clone https://github.com/hensm/hide_private_mode 20 | cd hide_private_mode 21 | npm install 22 | npm run build 23 | ```` 24 | 25 | | npm script | Description | 26 | | ---------- | ----------- | 27 | | `build` | Builds to `./dist`. | 28 | | `watch` | Builds to `./dist` and listens for changes. | 29 | | `start` | Starts Firefox with built extension. | 30 | | `lint` | Runs TSLint on source files. | 31 | | `package` | Runs `build` in production mode and outputs extension archive to `./web-ext-artifacts`. | 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "parcel build src/manifest.json", 4 | "watch": "parcel watch src/manifest.json", 5 | "start": "web-ext run -s ./dist", 6 | "lint": "tslint -c tslint.json -p tsconfig.json src/**/*.ts", 7 | "package": "npm run package:parcel && npm run package:web-ext", 8 | "package:parcel": "NODE_ENV=production npm run build -- --no-source-maps", 9 | "package:web-ext": "web-ext build -s ./dist --overwrite-dest" 10 | }, 11 | "devDependencies": { 12 | "@types/firefox-webext-browser": "^67.0.2", 13 | "fake-indexeddb": "^2.1.1", 14 | "parcel-bundler": "^1.12.4", 15 | "parcel-plugin-clean-dist": "0.0.6", 16 | "parcel-plugin-web-extension": "^1.6.1", 17 | "tslint": "^5.20.1", 18 | "typescript": "^3.8.3", 19 | "web-ext": "^3.2.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": { 3 | "message": "Hide Private Mode" 4 | } 5 | , "extensionDescription": { 6 | "message": "Prevents detection of private browsing mode." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/content.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import indexedDB from "fake-indexeddb"; 4 | import FDBCursor from "fake-indexeddb/lib/FDBCursor"; 5 | import FDBCursorWithValue from "fake-indexeddb/lib/FDBCursorWithValue"; 6 | import FDBDatabase from "fake-indexeddb/lib/FDBDatabase"; 7 | import FDBFactory from "fake-indexeddb/lib/FDBFactory"; 8 | import FDBIndex from "fake-indexeddb/lib/FDBIndex"; 9 | import FDBKeyRange from "fake-indexeddb/lib/FDBKeyRange"; 10 | import FDBObjectStore from "fake-indexeddb/lib/FDBObjectStore"; 11 | import FDBOpenDBRequest from "fake-indexeddb/lib/FDBOpenDBRequest"; 12 | import FDBRequest from "fake-indexeddb/lib/FDBRequest"; 13 | import FDBTransaction from "fake-indexeddb/lib/FDBTransaction"; 14 | import FDBVersionChangeEvent from "fake-indexeddb/lib/FDBVersionChangeEvent"; 15 | 16 | 17 | Object.defineProperty(window, "indexedDB", { 18 | get () { 19 | return indexedDB; 20 | } 21 | }); 22 | 23 | window.IDBCursor = FDBCursor; 24 | window.IDBCursorWithValue = FDBCursorWithValue; 25 | window.IDBDatabase = FDBDatabase; 26 | window.IDBFactory = FDBFactory; 27 | window.IDBIndex = FDBIndex; 28 | window.IDBKeyRange = FDBKeyRange; 29 | window.IDBObjectStore = FDBObjectStore; 30 | window.IDBOpenDBRequest = FDBOpenDBRequest; 31 | window.IDBRequest = FDBRequest; 32 | window.IDBTransaction = FDBTransaction; 33 | window.IDBVersionChangeEvent = FDBVersionChangeEvent; 34 | 35 | 36 | if (!("serviceWorker" in navigator)) { 37 | Object.defineProperty(navigator, "serviceWorker", { 38 | get () { 39 | return new class extends EventTarget { 40 | get controller () { 41 | return null; 42 | } 43 | , get ready () { 44 | return new Promise(() => {}); 45 | } 46 | 47 | , register () { 48 | return new Promise(() => {}); 49 | } 50 | , getRegistration () { 51 | return new Promise(() => {}); 52 | } 53 | , getRegistrations () { 54 | return new Promise(() => {}); 55 | } 56 | , startMessages () {} 57 | }; 58 | } 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /src/contentLoader.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * If loaded in private browsing mode on an HTML web page, inject 5 | * content.ts script into page script context. 6 | */ 7 | if (document instanceof HTMLDocument 8 | && browser.extension.inIncognitoContext) { 9 | 10 | const req = new XMLHttpRequest(); 11 | req.open("GET", browser.runtime.getURL("content.js"), false); 12 | req.send(); 13 | 14 | if (req.status === 200) { 15 | const scriptElement = document.createElement("script"); 16 | scriptElement.textContent = req.responseText; 17 | 18 | (document.head || document.documentElement).append(scriptElement); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/icon.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "__MSG_extensionName__" 3 | , "description": "__MSG_extensionDescription__" 4 | , "version": "0.0.6" 5 | 6 | , "developer": { 7 | "name": "Matt Hensman " 8 | , "url": "https://github.com/hensm/hide_private_mode" 9 | } 10 | 11 | , "browser_specific_settings": { 12 | "gecko": { 13 | "id": "hide_private_mode@matt.tf" 14 | , "strict_min_version": "60.0" 15 | } 16 | } 17 | 18 | , "icons": { 19 | "48": "icon.svg" 20 | , "96": "icon.svg" 21 | } 22 | 23 | , "content_scripts": [ 24 | { 25 | "all_frames": true 26 | , "js": [ "contentLoader.ts" ] 27 | , "matches": [ "" ] 28 | , "run_at": "document_start" 29 | } 30 | ] 31 | 32 | , "default_locale": "en" 33 | , "manifest_version": 2 34 | 35 | , "permissions": [ 36 | "" 37 | ] 38 | , "web_accessible_resources": [ 39 | "content.ts" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true 4 | , "module": "commonjs" 5 | , "removeComments": true 6 | , "strict": true 7 | , "target": "ESNext" 8 | } 9 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error" 3 | , "extends": [ 4 | "tslint:recommended" 5 | ] 6 | , "jsRules": false 7 | , "rules": { 8 | "arrow-parens": false 9 | , "import-spacing": false 10 | , "interface-name": false 11 | , "max-classes-per-file": false 12 | , "max-line-length": [ true, { 13 | "limit": 80 14 | , "ignore-pattern": "//|.*(\"|`);?$" 15 | }] 16 | , "member-access": [ true ] 17 | , "no-consecutive-blank-lines": false 18 | , "no-console": [ true, "log" ] 19 | , "no-namespace": [ true, "allow-declarations" ] 20 | , "object-literal-sort-keys": false 21 | , "radix": false 22 | , "semicolon": [ true, "always" ] 23 | , "space-before-function-paren": [ true, "always" ] 24 | , "trailing-comma": false 25 | , "variable-name": [ true 26 | , "ban-keywords" 27 | , "check-format" 28 | , "allow-pascal-case" 29 | , "allow-leading-underscore" ] 30 | } 31 | , "rulesDirectory": [] 32 | } 33 | --------------------------------------------------------------------------------