diff --git a/v3/_locales/en/messages.json b/v3/_locales/en/messages.json new file mode 100644 index 0000000..6ef1b38 --- /dev/null +++ b/v3/_locales/en/messages.json @@ -0,0 +1,211 @@ +{ + "extensionName": { + "message": "User-Agent Switcher and Manager", + "description": "Name of the extension." + }, + "extensionDescription": { + "message": "Spoof websites trying to gather information about your web navigation to deliver distinct content you may not want", + "description": "Description of the extension." + }, + "userAgentSwitcherandManagerOptions": { + "message": "User-Agent Switcher and Manager :: Options" + }, + "blackListMode": { + "message": "Black-List Mode" + }, + "description": { + "message": "Description" + }, + "blackListModeDescription": { + "message": "Apply the custom user-agent string to all tabs except the tabs with the following top-level hostnames (comma-separated list of hostnames). Note that even if a window-based user-agent string is set from the toolbar popup, your browser's default user-agent string is used." + }, + "whiteListMode": { + "message": "White-List Mode" + }, + "whiteListModeDescription": { + "message": "Only apply the custom user-agent string to the tabs with following top-level hostnames. Note that if a window-based user-agent string is set from the toolbar popup, this user-agent will overwrite the global one." + }, + "customMode": { + "message": "Custom Mode" + }, + "customModeDescription": { + "message": "Try to resolve the user-agent string from a JSON object; otherwise either use the default user-agent string or use the one that the user is set from the popup interface. Use \"*\" as the hostname to match all domains. You can randomly select from multiple user-agent strings by providing an array instead of a fixed string. If there is a \"_\" key in your JSON object which refers to an array of hostnames, then the extension only randomly selects the user-agent string once for each hostname inside this list. This is useful if you don't want the random user-agent to change until this browser session is over." + }, + "insertSample": { + "message": "Insert a sample" + }, + "cache": { + "message": "Use caching to improve performance (recommended value is true). Uncheck this option only if you are using the custom mode and also you need the user-agent string to be altered from the provided list on every single request." + }, + "exactMatch": { + "message": "Use exact matching (if checked, you will need to insert all sub-domains in the white-list and black-list modes to be considered. If unchecked, all the sub-domains are passing the matching condition (e.g: www.google.com passes the matching if google.com is in the list))" + }, + "faqs": { + "message": "Open FAQs page on updates" + }, + "userAgentData": { + "message": "Expose \"navigator.userAgentData\" object on Chromium browsers" + }, + "log": { + "message": "Display debugging info in the browser console" + }, + "disableSpoofing": { + "message": "Disable Spoofing" + }, + "disableSpoofingDescription": { + "message": "A comma-separated list of keywords that the extension should not spoof the user-agent header. Use this list to protect URLs that contain these protected keywords. Each keyword need to be at least 5 char long." + }, + "customUserAgentParsing": { + "message": "Custom User-Agent Parsing" + }, + "customUserAgentParsingDescription": { + "message": "A JSON object to bypass the internal user-agent string parsing method. The keys are the actual user-agent strings and the value of each key is an object of the keys that need to be set for the \"navigator\" object. You can use the \"[delete]\" keyword if you want a key in the \"navigator\" object to get deleted." + }, + "siblingHostnames": { + "message": "Sibling Hostnames" + }, + "siblingHostnamesDescription": { + "message": "A JSON array that contains one or more groups of hostnames to have a single user-agent string per group. For all hostnames in one group, the user-agent string calculation only occurs once, and all the other members use the same calculated string. This is useful to make sure a group of connected websites only access to the same user-agent string." + }, + "importSettings": { + "message": "Import Settings" + }, + "exportSettings": { + "message": "Export Settings" + }, + "exportSettingsTitle": { + "message": "To generate minified version, press Shift key while pressing this button" + }, + "help": { + "message": "FAQs Page (Help)" + }, + "donate": { + "message": "Support Development" + }, + "save": { + "message": "Save" + }, + "managedStorage": { + "message": "This extension supports managed storage so that preferences can be altered automatically or can be pre-configured by a domain administrator. Read the FAQs page for more info." + }, + "options": { + "message": "Options" + }, + "optionsTitle": { + "message": "Open options page" + }, + "restart": { + "message": "Restart" + }, + "restartTitle": { + "message": "Click to reload the extension. This will cause all the window-based user-agent strings to be cleared." + }, + "refreshTab": { + "message": "Refresh Tab" + }, + "refreshTabTitle": { + "message": "Refresh the current page" + }, + "reset": { + "message": "Reset" + }, + "resetTitle": { + "message": "Reset browser's user-agent string to the default one. This will not reset window-based UA strings. To reset them, use the 'Restart' button." + }, + "testUA": { + "message": "Test UA" + }, + "testUATitle": { + "message": "Test your user-agent string" + }, + "considerContainers": { + "message": "Consider Containers" + }, + "considerContainersTitle": { + "message": "Allow the extension to access your browser's containers. If this permission is granted, tabs inside isolated containers do not follow the default container's user-agent string. You need to set this string for each new container." + }, + "applyActiveWindow": { + "message": "Apply (active window)" + }, + "applyActiveWindowTitle": { + "message": "Set this user-agent string for all tabs inside the current window" + }, + "applyAllWindows": { + "message": "Apply (all windows)" + }, + "applyAllWindowsTitle": { + "message": "Set this user-agent string as the browser's User-Agent string" + }, + "applyContainer": { + "message": "Apply (container)" + }, + "applyContainerTitle": { + "message": "Set this user-agent string as the current container's User-Agent string" + }, + "applyContainerWindow": { + "message": "Apply (container on window)" + }, + "applyContainerWindowTitle": { + "message": "Set this user-agent string for all tabs inside the current window's container" + }, + "resetContainer": { + "message": "Reset (container)" + }, + "resetContainerTitle": { + "message": "Reset the container's user-agent string to the default one. This will not reset window-based UA strings. To reset them, use the 'Restart' button." + }, + "oscpuTitle": { + "message": "This is a readonly field. Use options page for custom parsing." + }, + "appVersionTitle": { + "message": "This is a readonly field. Use options page for custom parsing." + }, + "platformTitle": { + "message": "This is a readonly field. Use options page for custom parsing." + }, + "vendorTitle": { + "message": "This is a readonly field. Use options page for custom parsing." + }, + "productTitle": { + "message": "This is a readonly field. Use options page for custom parsing." + }, + "uaTitle": { + "message": "To set a blank user-agent string, use the 'empty' keyword. To construct a custom user-agent string based on the current browser's navigator object, use ${} notation. Whatever is inside this notation is read from the 'navigator' object. For instance, to append a string to the default user-agent, use '${userAgent} THIS IS THE APPENDED STRING'" + }, + "uaPlaceholder": { + "message": "Your preferred user-agent string" + }, + "noMatch": { + "message": "No matching user-agent string for this query" + }, + "ztoa": { + "message": "Z to A" + }, + "atoz": { + "message": "A to Z" + }, + "filterAmong": { + "message": "Filter among $1" + }, + "filterAgents": { + "message": "Filter Agents" + }, + "msgDefaultUA": { + "message": "Default UA, press the reset button instead" + }, + "msgUASet": { + "message": "User-Agent is Set" + }, + "msgDisabledOnContainer": { + "message": "Disabled on this container. Uses the default user-agent string." + }, + "msgDisabled": { + "message": "Disabled. Uses the default user-agent string." + }, + "optionsSaved": { + "message": "Options saved." + }, + "dbReset": { + "message": "Double-click to reset!" + } +} diff --git a/v3/_locales/ru/messages.json b/v3/_locales/ru/messages.json new file mode 100644 index 0000000..0ac10e9 --- /dev/null +++ b/v3/_locales/ru/messages.json @@ -0,0 +1,208 @@ +{ + "extensionName": { + "message": "User-Agent Switcher and Manager", + "description": "Name of the extension." + }, + "extensionDescription": { + "message": "Подменяет User-Agent на веб-сайтах, пытающихся собрать информацию о ваших путешествиях по сети и выдать не нужное вам содержимое", + "description": "Description of the extension." + }, + "userAgentSwitcherandManagerOptions": { + "message": "User-Agent Switcher and Manager :: Настройки" + }, + "blackListMode": { + "message": "Режим черного списка" + }, + "description": { + "message": "Описание" + }, + "blackListModeDescription": { + "message": "Применить установленную строку User-Agent ко всем вкладкам за исключением содержащих следующие домены верхнего уровня (список доменов разделяется запятыми). Важно: даже если применяемая к окну строка User-Agent установлена из всплывающего окна, для этого списка будет использоваться строка User-Agent вашего браузера по умолчанию." + }, + "whiteListMode": { + "message": "Режим белого списка" + }, + "whiteListModeDescription": { + "message": "Применять установленную строку User-Agent только к вкладкам, содержащим следующие домены верхнего уровня. Важно: даже если применяемая к окну строка User-Agent установлена из всплывающего окна, данный User-Agent заменит собой глобальный." + }, + "customMode": { + "message": "Режим настройки" + }, + "customModeDescription": { + "message": "Пробовать считывание строки User-Agent из объекта JSON; в другом случае использовать строку User-Agent по умолчанию или установленную во всплывающем окне. Используйте \"*\" в качестве сервера для применения ко всем доменам. Вы можете случайно выбирать из нескольких строк User-Agent с помощью массива вместо фиксированной строки. Если в объекте JSON присутствует ключ \"_\", отсылающий к массиву серверов, то расширение будет случайно выбирать строку User-Agent для каждого сервера в списке. Это полезно, если вы не желаете случайно менять User-Agent до перезапуска браузера." + }, + "insertSample": { + "message": "Вставить пример" + }, + "cache": { + "message": "Использовать кэширование для улучшения производительности (рекомендуемое значение true). Отключите эту опцию только при использовании режима настройки, когда нужно изменять строку User-Agent с помощью списка при каждом запросе." + }, + "exactMatch": { + "message": "Использовать точное совпадение (если включено, вам нужно добавлять все поддомены в черный и белый списки как задумано. Если выключено, все поддомены проходят проверку на совпадение (например, www.google.com проходит проверку, если google.com находится в списке))" + }, + "faqs": { + "message": "Открывать страницу FAQ при обновлении" + }, + "log": { + "message": "Отображать отладочную информацию в консоли браузера" + }, + "disableSpoofing": { + "message": "Отключить подмену User-Agent" + }, + "disableSpoofingDescription": { + "message": "Разделяемый запятыми список ключевых слов, на которых расширение не должно подменять заголовок User-Agent. Используйте этот список для защиты URL, содержащих эти ключевые слова. Каждое ключевое слово должно быть длиной не менее 5 символов." + }, + "customUserAgentParsing": { + "message": "Парсинг установленного User-Agent" + }, + "customUserAgentParsingDescription": { + "message": "Объект JSON для обхода внутреннего метода парсинга строки User-Agent. Ключи — настоящие строки User-Agent. Значение каждого ключа- объект ключей, требуемых для установки объекта \"navigator\". Вы можете использовать ключевое слово \"[delete]\", если вам нужен ключ в объекте \"navigator\" для удаления." + }, + "siblingHostnames": { + "message": "Родственные домены" + }, + "siblingHostnamesDescription": { + "message": "Массив JSON, содержащий одну или больше групп серверов с отдельной строкой User-Agent на группу. Для всех серверов в одной группе вычисление строки User-Agent проводится только один раз, все остальные члены группы используют ту же самую строку. С помощью этого можно убедиться, что група связанных веб-сайтов имеет доступ только к одной и той же строке User-Agent." + }, + "importSettings": { + "message": "Импортировать настройки" + }, + "exportSettings": { + "message": "Экспортировать настройки" + }, + "exportSettingsTitle": { + "message": "Чтобы сгенерировать уменьшенную версию, нажмите эту кнопку, удерживая клавишу Shift" + }, + "help": { + "message": "Страница FAQ (Помощь)" + }, + "donate": { + "message": "Поддержать разработку" + }, + "save": { + "message": "Сохранить" + }, + "managedStorage": { + "message": "Данное расширение поддерживает Managed Storage, и эти настройки могут быть изменены автоматически или установлены изначально администратором домена. Прочтите FAQ для получения более подробной информации." + }, + "options": { + "message": "Настройки" + }, + "optionsTitle": { + "message": "Открыть страницу настроек" + }, + "restart": { + "message": "Перезапустить" + }, + "restartTitle": { + "message": "Нажмите, чтобы перезапустить расширение. Это очистит все строки User-Agent, примененные к окну." + }, + "refreshTab": { + "message": "Обновить вкладку" + }, + "refreshTabTitle": { + "message": "Обновить текущую страницу" + }, + "reset": { + "message": "Сбросить" + }, + "resetTitle": { + "message": "Сбросить строку User-Agent браузера на значение по умолчанию. Это не сбросит строки User-Agent, примененные к окну. Чтобы сбросить их, нажмите кнопку 'Перезапустить'." + }, + "testUA": { + "message": "Тест UA" + }, + "testUATitle": { + "message": "Тестировать вашу строку User-Agent" + }, + "considerContainers": { + "message": "Учитывать контейнеры" + }, + "considerContainersTitle": { + "message": "Позволять расширению иметь доступ к контейнерам вашего браузера. При наличии доступа вкладки внутри изолированных контейнеров не используют строку User-Agent контейнера по умолчанию. Вам нужно устанавливать эту строку для каждого нового контейнера." + }, + "applyActiveWindow": { + "message": "Применить (активное окно)" + }, + "applyActiveWindowTitle": { + "message": "Установить эту строку User-Agent для всех вкладок внутри текущего окна" + }, + "applyAllWindows": { + "message": "Применить (все окна)" + }, + "applyAllWindowsTitle": { + "message": "Установить эту строку User-Agent в качестве основной строки браузера" + }, + "applyContainer": { + "message": "Применить (контейнер)" + }, + "applyContainerTitle": { + "message": "Установить эту строку User-Agent в качестве строки текущего контейнера" + }, + "applyContainerWindow": { + "message": "Применить (контейнер в окне)" + }, + "applyContainerWindowTitle": { + "message": "Установить эту строку User-Agent для всех вкладок внутри текущего окна контейнера" + }, + "resetContainer": { + "message": "Сбросить (контейнер)" + }, + "resetContainerTitle": { + "message": "Сбросить строку User-Agent контейнера на значение по умолчанию. Это не сбросит строки User-Agent, примененные к окну. Чтобы сбросить их, нажмите кнопку 'Перезапустить'." + }, + "oscpuTitle": { + "message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную." + }, + "appVersionTitle": { + "message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную." + }, + "platformTitle": { + "message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную." + }, + "vendorTitle": { + "message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную." + }, + "productTitle": { + "message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную." + }, + "uaTitle": { + "message": "Чтобы установить пустую строку User-Agent, используйте ключевое слово 'empty'. Чтобы составить собственную строку User-Agent, основанную на текущем объекте navigator браузера, используйте нотацию ${}. Все внутри этой нотации будет прочитано из объекта 'navigator'. Например, чтобы присоединить строку к User-Agent по умолчанию, используйте '${userAgent} ПРИСОЕДИНЕННАЯ СТРОКА'" + }, + "uaPlaceholder": { + "message": "Ваша предпочитаемая строка User-Agent" + }, + "noMatch": { + "message": "Для данного запроса нет строк User-Agent" + }, + "ztoa": { + "message": "От Z до A" + }, + "atoz": { + "message": "От A до Z" + }, + "filterAmong": { + "message": "Выбрать из $1" + }, + "filterAgents": { + "message": "Выбрать UA" + }, + "msgDefaultUA": { + "message": "User-Agent по умолчанию, вместо этого нажмите кнопку 'Сбросить'" + }, + "msgUASet": { + "message": "User-Agent установлен" + }, + "msgDisabledOnContainer": { + "message": "Отключено в этом контейнере. Используется строка User-Agent по умолчанию." + }, + "msgDisabled": { + "message": "Отключено. Используется строка User-Agent по умолчанию." + }, + "optionsSaved": { + "message": "Настройки сохранены." + }, + "dbReset": { + "message": "Щелкните 2 раза левой кнопкой мыши для сброса!" + } +} diff --git a/v3/data/icons/128.png b/v3/data/icons/128.png new file mode 100644 index 0000000..5a1728e Binary files /dev/null and b/v3/data/icons/128.png differ diff --git a/v3/data/icons/16.png b/v3/data/icons/16.png new file mode 100644 index 0000000..5f500f4 Binary files /dev/null and b/v3/data/icons/16.png differ diff --git a/v3/data/icons/18.png b/v3/data/icons/18.png new file mode 100644 index 0000000..265595a Binary files /dev/null and b/v3/data/icons/18.png differ diff --git a/v3/data/icons/19.png b/v3/data/icons/19.png new file mode 100644 index 0000000..c9b4803 Binary files /dev/null and b/v3/data/icons/19.png differ diff --git a/v3/data/icons/256.png b/v3/data/icons/256.png new file mode 100644 index 0000000..6024c3a Binary files /dev/null and b/v3/data/icons/256.png differ diff --git a/v3/data/icons/32.png b/v3/data/icons/32.png new file mode 100644 index 0000000..d98aac4 Binary files /dev/null and b/v3/data/icons/32.png differ diff --git a/v3/data/icons/36.png b/v3/data/icons/36.png new file mode 100644 index 0000000..6496212 Binary files /dev/null and b/v3/data/icons/36.png differ diff --git a/v3/data/icons/38.png b/v3/data/icons/38.png new file mode 100644 index 0000000..4533c51 Binary files /dev/null and b/v3/data/icons/38.png differ diff --git a/v3/data/icons/48.png b/v3/data/icons/48.png new file mode 100644 index 0000000..8643a43 Binary files /dev/null and b/v3/data/icons/48.png differ diff --git a/v3/data/icons/512.png b/v3/data/icons/512.png new file mode 100644 index 0000000..d262332 Binary files /dev/null and b/v3/data/icons/512.png differ diff --git a/v3/data/icons/64.png b/v3/data/icons/64.png new file mode 100644 index 0000000..d005e4a Binary files /dev/null and b/v3/data/icons/64.png differ diff --git a/v3/data/icons/active/128.png b/v3/data/icons/active/128.png new file mode 100644 index 0000000..bac2a00 Binary files /dev/null and b/v3/data/icons/active/128.png differ diff --git a/v3/data/icons/active/16.png b/v3/data/icons/active/16.png new file mode 100644 index 0000000..f4d5c6d Binary files /dev/null and b/v3/data/icons/active/16.png differ diff --git a/v3/data/icons/active/18.png b/v3/data/icons/active/18.png new file mode 100644 index 0000000..c820a17 Binary files /dev/null and b/v3/data/icons/active/18.png differ diff --git a/v3/data/icons/active/19.png b/v3/data/icons/active/19.png new file mode 100644 index 0000000..b7b6c51 Binary files /dev/null and b/v3/data/icons/active/19.png differ diff --git a/v3/data/icons/active/256.png b/v3/data/icons/active/256.png new file mode 100644 index 0000000..24da822 Binary files /dev/null and b/v3/data/icons/active/256.png differ diff --git a/v3/data/icons/active/32.png b/v3/data/icons/active/32.png new file mode 100644 index 0000000..57822fb Binary files /dev/null and b/v3/data/icons/active/32.png differ diff --git a/v3/data/icons/active/36.png b/v3/data/icons/active/36.png new file mode 100644 index 0000000..b87ea10 Binary files /dev/null and b/v3/data/icons/active/36.png differ diff --git a/v3/data/icons/active/38.png b/v3/data/icons/active/38.png new file mode 100644 index 0000000..054e54a Binary files /dev/null and b/v3/data/icons/active/38.png differ diff --git a/v3/data/icons/active/48.png b/v3/data/icons/active/48.png new file mode 100644 index 0000000..0ba8aa7 Binary files /dev/null and b/v3/data/icons/active/48.png differ diff --git a/v3/data/icons/active/512.png b/v3/data/icons/active/512.png new file mode 100644 index 0000000..d88307d Binary files /dev/null and b/v3/data/icons/active/512.png differ diff --git a/v3/data/icons/active/64.png b/v3/data/icons/active/64.png new file mode 100644 index 0000000..aebdf46 Binary files /dev/null and b/v3/data/icons/active/64.png differ diff --git a/v3/data/icons/ignored/128.png b/v3/data/icons/ignored/128.png new file mode 100644 index 0000000..990b4ac Binary files /dev/null and b/v3/data/icons/ignored/128.png differ diff --git a/v3/data/icons/ignored/16.png b/v3/data/icons/ignored/16.png new file mode 100644 index 0000000..9f2e81b Binary files /dev/null and b/v3/data/icons/ignored/16.png differ diff --git a/v3/data/icons/ignored/18.png b/v3/data/icons/ignored/18.png new file mode 100644 index 0000000..37734c0 Binary files /dev/null and b/v3/data/icons/ignored/18.png differ diff --git a/v3/data/icons/ignored/19.png b/v3/data/icons/ignored/19.png new file mode 100644 index 0000000..b5c11ce Binary files /dev/null and b/v3/data/icons/ignored/19.png differ diff --git a/v3/data/icons/ignored/256.png b/v3/data/icons/ignored/256.png new file mode 100644 index 0000000..2ce7bd0 Binary files /dev/null and b/v3/data/icons/ignored/256.png differ diff --git a/v3/data/icons/ignored/32.png b/v3/data/icons/ignored/32.png new file mode 100644 index 0000000..edcb7e2 Binary files /dev/null and b/v3/data/icons/ignored/32.png differ diff --git a/v3/data/icons/ignored/36.png b/v3/data/icons/ignored/36.png new file mode 100644 index 0000000..5e30608 Binary files /dev/null and b/v3/data/icons/ignored/36.png differ diff --git a/v3/data/icons/ignored/38.png b/v3/data/icons/ignored/38.png new file mode 100644 index 0000000..acc5911 Binary files /dev/null and b/v3/data/icons/ignored/38.png differ diff --git a/v3/data/icons/ignored/48.png b/v3/data/icons/ignored/48.png new file mode 100644 index 0000000..dc37bda Binary files /dev/null and b/v3/data/icons/ignored/48.png differ diff --git a/v3/data/icons/ignored/512.png b/v3/data/icons/ignored/512.png new file mode 100644 index 0000000..621ed25 Binary files /dev/null and b/v3/data/icons/ignored/512.png differ diff --git a/v3/data/icons/ignored/64.png b/v3/data/icons/ignored/64.png new file mode 100644 index 0000000..c028aa0 Binary files /dev/null and b/v3/data/icons/ignored/64.png differ diff --git a/v3/data/inject/isolated.js b/v3/data/inject/isolated.js new file mode 100644 index 0000000..6a69c4f --- /dev/null +++ b/v3/data/inject/isolated.js @@ -0,0 +1,17 @@ +const port = document.createElement('span'); +port.id = 'ua-port-fgTd9n'; +document.documentElement.append(port); + +// preferences +self.prefs = self.prefs || { + ua: 'Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36', + uad: true, + major: 100, + name: 'Google Chrome', + mobile: false, + platform: 'Windows', + architecture: 'x86', + bitness: '64', + platformVersion: '10.0.0' +}; +Object.assign(port.dataset, self.prefs); diff --git a/v3/data/inject/main.js b/v3/data/inject/main.js new file mode 100644 index 0000000..b4eef84 --- /dev/null +++ b/v3/data/inject/main.js @@ -0,0 +1,102 @@ +const port = document.getElementById('ua-port-fgTd9n'); +port.remove(); +console.log(12, port); + +// overwrite navigator.userAgent +{ + const {get} = Object.getOwnPropertyDescriptor(Navigator.prototype, 'userAgent'); + + Object.defineProperty(Navigator.prototype, 'userAgent', { + get: new Proxy(get, { + apply() { + return port.dataset.ua; + } + }) + }); +} + +// overwrite navigator.userAgentData +if (port.dataset.uad) { + self.NavigatorUAData = self.NavigatorUAData || new class NavigatorUAData { + brands = []; + mobile = false; + platform = 'Unknown'; + toJSON() { + return {}; + } + getHighEntropyValues() { + return Promise.resolve({}); + } + }; + + Object.defineProperty(self.NavigatorUAData.prototype, 'brands', { + get: new Proxy(Object.getOwnPropertyDescriptor(self.NavigatorUAData.prototype, 'brands').get, { + apply() { + return [{ + brand: port.dataset.name, + version: port.dataset.major + }, { + brand: 'Chromium', + version: port.dataset.major + }, { + brand: 'Not=A?Brand', + version: '24' + }]; + } + }) + }); + Object.defineProperty(self.NavigatorUAData.prototype, 'mobile', { + get: new Proxy(Object.getOwnPropertyDescriptor(self.NavigatorUAData.prototype, 'mobile').get, { + apply() { + return port.dataset.mobile === 'true'; + } + }) + }); + Object.defineProperty(self.NavigatorUAData.prototype, 'platform', { + get: new Proxy(Object.getOwnPropertyDescriptor(self.NavigatorUAData.prototype, 'platform').get, { + apply() { + return port.dataset.platform; + } + }) + }); + self.NavigatorUAData.prototype.toJSON = new Proxy(self.NavigatorUAData.prototype.toJSON, { + apply(target, self) { + return { + brands: self.brands, + mobile: self.mobile, + platform: self.platform + }; + } + }); + self.NavigatorUAData.prototype.getHighEntropyValues = new Proxy(self.NavigatorUAData.prototype.getHighEntropyValues, { + apply(target, self, args) { + const hints = args[0]; + + if (!hints || Array.isArray(hints) === false) { + return Promise.reject(Error(`Failed to execute 'getHighEntropyValues' on 'NavigatorUAData'`)); + } + + const r = self.toJSON(); + + if (hints.includes('architecture')) { + r.architecture = port.dataset.architecture; + } + if (hints.includes('bitness')) { + r.bitness = port.dataset.bitness; + } + if (hints.includes('model')) { + r.model = ''; + } + if (hints.includes('platformVersion')) { + r.platformVersion = port.dataset.platformVersion; + } + if (hints.includes('uaFullVersion')) { + r.uaFullVersion = self.brands[0].version; + } + if (hints.includes('fullVersionList')) { + r.fullVersionList = this.brands; + } + return Promise.resolve(r); + } + }); +} diff --git a/v3/manifest.json b/v3/manifest.json new file mode 100755 index 0000000..d05f66f --- /dev/null +++ b/v3/manifest.json @@ -0,0 +1,34 @@ +{ + "manifest_version": 3, + "name": "__MSG_extensionName__", + "version": "0.6.0", + "default_locale": "en", + "description": "__MSG_extensionDescription__", + "permissions": [ + "storage", + "scripting", + "webNavigation", + "webRequest", + "declarativeNetRequest", + "contextMenus" + ], + "host_permissions": [ + "" + ], + "icons": { + "16": "data/icons/active/16.png", + "32": "data/icons/active/32.png", + "48": "data/icons/active/48.png", + "64": "data/icons/active/64.png", + "128": "data/icons/active/128.png", + "256": "data/icons/active/256.png" + }, + "storage": { + "managed_schema": "schema.json" + }, + "background":{ + "service_worker": "worker.js" + }, + "action": {}, + "homepage_url": "https://add0n.com/useragent-switcher.html" +} diff --git a/v3/schema.json b/v3/schema.json new file mode 100644 index 0000000..96b767d --- /dev/null +++ b/v3/schema.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "properties": { + "ua": { + "title": "Custom User-Agent String", + "type": "string" + }, + "json": { + "title": "JSON String of all Preferences", + "type": "string" + } + } +} diff --git a/v3/worker.js b/v3/worker.js new file mode 100644 index 0000000..2a5aab5 --- /dev/null +++ b/v3/worker.js @@ -0,0 +1,72 @@ +const enable = () => chrome.storage.local.get({ + enabled: true +}, async prefs => { + await chrome.scripting.unregisterContentScripts(); + + if (prefs.enabled) { + const common = { + 'matches': ['*://*/*'], + 'allFrames': true, + 'matchOriginAsFallback': true, + 'runAt': 'document_start' + }; + + await chrome.scripting.registerContentScripts([{ + ...common, + 'id': 'protected', + 'js': ['/data/inject/isolated.js'], + 'world': 'ISOLATED' + }, { + ...common, + 'id': 'unprotected', + 'js': ['/data/inject/main.js'], + 'world': 'MAIN' + }]); + } +}); +chrome.runtime.onStartup.addListener(enable); +chrome.runtime.onInstalled.addListener(enable); + +const policy = () => ({ + ua: 'Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36', + uad: true, + major: 100, + name: 'Google Chrome', + mobile: false, + platform: 'Windows', + architecture: 'x86', + bitness: '64', + platformVersion: '10.0.0' +}); + +// web navigation +const onCommitted = d => { + const p = policy(d); + + if (p) { + chrome.scripting.executeScript({ + target: { + tabId: d.tabId, + frameIds: [d.frameId] + }, + injectImmediately: true, + func: p => { + /* global port */ + if (typeof port === 'undefined') { + self.prefs = p; + } + else { + Object.assign(port.dataset, p); + } + }, + args: [p] + }); + } +}; +chrome.storage.local.get({ + enabled: true +}, prefs => { + if (prefs.enabled) { + chrome.webNavigation.onCommitted.addListener(onCommitted); + } +});