diff --git a/.eslintrc-ignores.js b/.eslintrc-ignores.js index 18b3e2d2e476b04a4a27f61b60ec565329091f89..9ccd1e1e5c5f909806b518eb8250900a7b942ac3 100644 --- a/.eslintrc-ignores.js +++ b/.eslintrc-ignores.js @@ -302,4 +302,10 @@ module.exports = [ // Test files for circular import in modules. "dom/base/test/jsmodules/import_circular.mjs", "dom/base/test/jsmodules/import_circular_1.mjs", + + "browser/app/profile/001-base-profile.js", + "browser/app/profile/000-tor-browser.js", + "mobile/android/app/000-tor-browser-android.js", + "toolkit/content/pt_config.json", + "toolkit/components/lox/lox_wasm.jsm", ]; diff --git a/.gitignore b/.gitignore index b32e3b1075aee012232b52cfb5a4777505146b5a..e051532a9161531c521d02ca3b7e0583e9a4daf8 100644 --- a/.gitignore +++ b/.gitignore @@ -354,3 +354,14 @@ media/libvpx/config/**/config.log # Ignore generated files resulting from building the minidump analyzer tests. toolkit/crashreporter/minidump-analyzer/analyzer-test/target/ + +# Ignore binary base of Tor Browser +.binaries + +# Other files modified at build time +mobile/android/.experimenter.json + +# Tor libraries for local builds +mobile/android/fenix/app/tor-expert-bundle.aar +mobile/android/fenix/app/src/main/assets/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..af3c9bf5020f1c708c34464f33230dfbbd20274f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,16 @@ +stages: + - update-container-images + - lint + - startup-test + - update-translations + +variables: + IMAGE_PATH: containers.torproject.org/tpo/applications/tor-browser/base:latest + LOCAL_REPO_PATH: /srv/apps-repos/tor-browser.git + +include: + - local: '.gitlab/ci/mixins.yml' + - local: '.gitlab/ci/jobs/lint/lint.yml' + - local: '.gitlab/ci/jobs/startup-test/startup-test.yml' + - local: '.gitlab/ci/jobs/update-containers.yml' + - local: '.gitlab/ci/jobs/update-translations.yml' diff --git a/.gitlab/ci/containers/base/Containerfile b/.gitlab/ci/containers/base/Containerfile new file mode 100644 index 0000000000000000000000000000000000000000..c10d1a45ad7b77569dcae9fc492eca860ca6cd6a --- /dev/null +++ b/.gitlab/ci/containers/base/Containerfile @@ -0,0 +1,51 @@ +# This image is published in containers.torproject.org/tpo/applications/tor-browser/base +# +# Whenever there are changes to this file, +# they are autopublished on merge to the tpo/applications/tor-browser repository. +# +# The image is updated roughly once a monce when the tor-browser repository is rebased. + +FROM containers.torproject.org/tpo/tpa/base-images/python:bookworm + +RUN apt-get update && apt-get install -y \ + clang \ + curl \ + git \ + libasound2-dev \ + libdbus-glib-1-dev \ + libgtk-3-dev \ + libpango1.0-dev \ + libpulse-dev \ + libx11-xcb-dev \ + libxcomposite-dev \ + libxcursor-dev \ + libxdamage-dev \ + libxi-dev \ + libxrandr-dev \ + libxtst-dev \ + make \ + m4 \ + mercurial \ + nasm \ + pkgconf \ + unzip \ + x11-utils \ + xvfb \ + xz-utils \ + wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +COPY taskcluster/docker/recipes/install-node.sh ./install-node.sh +RUN chmod +x install-node.sh +RUN ./install-node.sh +RUN rm ./install-node.sh + +COPY taskcluster/kinds/fetch/toolchains.yml ./toolchains.yml +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $(grep -oP 'rust-\K[0-9.]+(?=:)' ./toolchains.yml) +RUN $HOME/.cargo/bin/cargo install cbindgen --version $(grep -oP 'cbindgen-\K[0-9.]+(?=:)' ./toolchains.yml) +RUN rm ./toolchains.yml + +CMD ["/bin/bash"] diff --git a/.gitlab/ci/jobs/lint/helpers.py b/.gitlab/ci/jobs/lint/helpers.py new file mode 100755 index 0000000000000000000000000000000000000000..aa12aca59019c9c858787e87c5e98bb9b6381449 --- /dev/null +++ b/.gitlab/ci/jobs/lint/helpers.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +import argparse +import os +import re +import shlex +import subprocess + + +def git(command): + result = subprocess.run( + ["git"] + shlex.split(command), check=True, capture_output=True, text=True + ) + return result.stdout.strip() + + +def get_firefox_tag(reference): + """Extracts the Firefox tag associated with a branch or tag name. + + The "firefox tag" is the tag that marks + the end of the Mozilla commits and the start of the Tor Project commits. + + Know issue: If ever there is more than one tag per Firefox ESR version, + this function may return the incorrect reference number. + + Args: + reference: The branch or tag name to extract the Firefox tag from. + Expected format is tor-browser-91.2.0esr-11.0-1, + where 91.2.0esr is the Firefox version. + + Returns: + The reference specifier of the matching Firefox tag. + An exception will be raised if anything goes wrong. + """ + + # Extracts the version number from a branch or tag name. + firefox_version = "" + match = re.search(r"(?<=browser-)([^-]+)", reference) + if match: + # TODO: Validate that what we got is actually a valid semver string? + firefox_version = match.group(1) + else: + raise ValueError(f"Failed to extract version from reference '{reference}'.") + + major_version = firefox_version.split(".")[0] + minor_patch_version = "_".join(firefox_version.split(".")[1:]) + + remote_tags = git("ls-remote --tags origin") + + # Each line looks like: + # 9edd658bfd03a6b4743ecb75fd4a9ad968603715 refs/tags/FIREFOX_91_9_0esr_BUILD1 + pattern = ( + rf"(.*)FIREFOX_{re.escape(major_version)}_{re.escape(minor_patch_version)}(.*)$" + ) + match = re.search(pattern, remote_tags, flags=re.MULTILINE) + if not match: + # Attempt to match with a nightly tag, in case the ESR tag is not found + pattern = rf"(.*)FIREFOX_NIGHTLY_{re.escape(major_version)}(.*)$" + match = re.search(pattern, remote_tags, flags=re.MULTILINE) + + if match: + return match.group(0).split()[0] + else: + raise ValueError( + f"Failed to find reference specifier for Firefox tag of version '{firefox_version}' from '{reference}'." + ) + + +def get_list_of_changed_files(): + """Gets a list of files changed in the working directory. + + This function is meant to be run inside the Gitlab CI environment. + + When running in a default branch, get the list of changed files since the last Firefox tag. + When running for a new MR commit, get a list of changed files in the current MR. + + Returns: + A list of filenames of changed files (excluding deleted files). + An exception wil be raised if anything goes wrong. + """ + + base_reference = "" + + if os.getenv("CI_PIPELINE_SOURCE") == "merge_request_event": + # For merge requests, the base_reference is the common ancestor between the MR and the target branch + base_reference = os.getenv("CI_MERGE_REQUEST_DIFF_BASE_SHA") + else: + # When not in merge requests, the base reference is the Firefox tag + base_reference = get_firefox_tag(os.getenv("CI_COMMIT_BRANCH")) + + if not base_reference: + raise RuntimeError("No base reference found. There might be more errors above.") + + # Fetch the tag reference + git(f"fetch origin {base_reference} --depth=1 --filter=blob:none") + # Return but filter the issue_templates files because those file names have spaces which can cause issues + return git("diff --diff-filter=d --name-only FETCH_HEAD HEAD").split("\n") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="") + + parser.add_argument( + "--get-firefox-tag", + help="Get the Firefox tag related to a given (tor-mullvad-base)-browser tag or branch name.", + type=str, + ) + parser.add_argument( + "--get-changed-files", + help="Get list of changed files." + "When running from a merge request get sthe list of changed files since the merge-base of the current branch." + "When running from a protected branch i.e. any branch that starts with <something>-browser-, gets the list of files changed since the FIREFOX_ tag.", + action="store_true", + ) + + args = parser.parse_args() + + if args.get_firefox_tag: + print(get_firefox_tag(args.get_firefox_tag)) + elif args.get_changed_files: + print("\n".join(get_list_of_changed_files())) + else: + print("No valid option provided.") diff --git a/.gitlab/ci/jobs/lint/lint.yml b/.gitlab/ci/jobs/lint/lint.yml new file mode 100644 index 0000000000000000000000000000000000000000..ef810c2fdc29f43cee044ea97c4bd54884759ec3 --- /dev/null +++ b/.gitlab/ci/jobs/lint/lint.yml @@ -0,0 +1,296 @@ +.base: + extends: .with-local-repo-bash + stage: lint + image: $IMAGE_PATH + interruptible: true + variables: + MOZBUILD_STATE_PATH: "$CI_PROJECT_DIR/.cache/mozbuild" + cache: + paths: + - node_modules + - .cache/mozbuild + # Store the cache regardless on job outcome + when: 'always' + # Share the cache throughout all pipelines running for a given branch + key: $CI_COMMIT_REF_SLUG + tags: + # Run these jobs in the browser dedicated runners. + - firefox + +eslint: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l eslint + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + # Files that are likely audited. + - '**/*.js' + - '**/*.jsm' + - '**/*.json' + - '**/*.jsx' + - '**/*.mjs' + - '**/*.sjs' + - '**/*.html' + - '**/*.xhtml' + - '**/*.xml' + - 'tools/lint/eslint.yml' + # Run when eslint policies change. + - '**/.eslintignore' + - '**/*eslintrc*' + # The plugin implementing custom checks. + - 'tools/lint/eslint/eslint-plugin-mozilla/**' + - 'tools/lint/eslint/eslint-plugin-spidermonkey-js/**' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +stylelint: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l stylelint + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + # Files that are likely audited. + - '**/*.css' + - 'tools/lint/styleint.yml' + # Run when stylelint policies change. + - '**/.stylelintignore' + - '**/*stylelintrc*' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +py-black: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l black + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + # The list of extensions should match tools/lint/black.yml + - '**/*.py' + - '**/moz.build' + - '**/*.configure' + - '**/*.mozbuild' + - 'pyproject.toml' + - 'tools/lint/black.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +py-ruff: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l ruff + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.py' + - '**/*.configure' + - '**/.ruff.toml' + - 'pyproject.toml' + - 'tools/lint/ruff.yml' + - 'tools/lint/python/ruff.py' + - 'tools/lint/python/ruff_requirements.txt' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +yaml: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l yaml + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.yml' + - '**/*.yaml' + - '**/.ymllint' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +shellcheck: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l shellcheck + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.sh' + - 'tools/lint/shellcheck.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +clang-format: + extends: .base + script: + - ./mach configure --without-wasm-sandboxed-libraries --with-base-browser-version=0.0.0 + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l clang-format + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.cpp' + - '**/*.c' + - '**/*.cc' + - '**/*.h' + - '**/*.m' + - '**/*.mm' + - 'tools/lint/clang-format.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +rustfmt: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l rustfmt + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.rs' + - 'tools/lint/rustfmt.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +fluent-lint: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l fluent-lint + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.ftl' + - 'tools/lint/fluent-lint.yml' + - 'tools/lint/fluent-lint/exclusions.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +localization: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l l10n + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/locales/en-US/**' + - '**/l10n.toml' + - 'third_party/python/compare-locales/**' + - 'third_party/python/fluent/**' + - 'tools/lint/l10n.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +mingw-capitalization: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l mingw-capitalization + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.cpp' + - '**/*.cc' + - '**/*.c' + - '**/*.h' + - 'tools/lint/mingw-capitalization.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +mscom-init: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l mscom-init + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.cpp' + - '**/*.cc' + - '**/*.c' + - '**/*.h' + - 'tools/lint/mscom-init.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +file-whitespace: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l file-whitespace + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.c' + - '**/*.cc' + - '**/*.cpp' + - '**/*.css' + - '**/*.dtd' + - '**/*.idl' + - '**/*.ftl' + - '**/*.h' + - '**/*.html' + - '**/*.md' + - '**/*.properties' + - '**/*.py' + - '**/*.rs' + - '**/*.rst' + - '**/*.webidl' + - '**/*.xhtml' + - '**/*.java' + - 'tools/lint/file-whitespace.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +test-manifest: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l test-manifest-alpha -l test-manifest-disable -l test-manifest-skip-if + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.ini' + - 'python/mozlint/**' + - 'tools/lint/**' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') + +trojan-source: + extends: .base + script: + - .gitlab/ci/jobs/lint/helpers.py --get-changed-files | xargs -d '\n' ./mach lint -l trojan-source + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + # List copied from: taskcluster/ci/source-test/mozlint.yml + # + - '**/*.c' + - '**/*.cc' + - '**/*.cpp' + - '**/*.h' + - '**/*.py' + - '**/*.rs' + - 'tools/lint/trojan-source.yml' + # Run job whenever a commit is merged to a protected branch + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PIPELINE_SOURCE == 'push') diff --git a/.gitlab/ci/jobs/startup-test/startup-test-android.py b/.gitlab/ci/jobs/startup-test/startup-test-android.py new file mode 100644 index 0000000000000000000000000000000000000000..81a39cbb9199b7d3742b16518e6ad38dc2cf1bff --- /dev/null +++ b/.gitlab/ci/jobs/startup-test/startup-test-android.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +import argparse +import json +import os +import sys +import time +from datetime import datetime, timedelta +from enum import Enum + +import requests + +""" +This script runs Android tests on BrowserStack using the BrowserStack App Automate Espresso API. + +Usage: + startup-test-android.py --devices <devices> [--tests <tests>] [--app_file_path <app_file_path>] [--test_file_path <test_file_path>] + +Arguments: + --devices: Comma-separated list of devices to test on (required). + --tests: Comma-separated list of tests to run (optional). If not provided, all tests will run. + --app_file_path: Path to the app file (optional). If not provided, yesterday's nightly will be downloaded. + --test_file_path: Path to the test file (optional). If not provided, yesterday's nightly will be downloaded. + +Environment Variables: + BROWSERSTACK_USERNAME: BrowserStack username (required). + BROWSERSTACK_API_KEY: BrowserStack API key (required). + +Description: + - If app and test file paths are not provided, the script downloads the latest nightly build from the Tor Project. + - Uploads the app and test files to BrowserStack. + - Triggers the test run on the specified devices. + - Polls for the test status until completion or timeout. + - Prints the test results and exits with an appropriate status code. +""" + +parser = argparse.ArgumentParser( + description="Run Android startup tests on BrowserStack." +) +parser.add_argument( + "--devices", + type=str, + help="Comma-separated list of devices to test on", + required=True, +) +parser.add_argument("--tests", type=str, help="Comma-separated list of tests to run") +parser.add_argument("--app_file_path", type=str, help="Path to the app file") +parser.add_argument("--test_file_path", type=str, help="Path to the test file") + +args = parser.parse_args() + +if args.app_file_path: + app_file_path = args.app_file_path + test_file_path = args.test_file_path + if not test_file_path: + print( + "\033[1;31mIf either app or test file paths are provided, both must be provided.\033[0m" + ) +else: + + def download_file(url, dest_path): + try: + response = requests.get(url, stream=True) + response.raise_for_status() + with open(dest_path, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + f.write(chunk) + except Exception as e: + print(f"\033[1;31mFailed to download file from {url}.\033[0m") + print(e) + sys.exit(1) + + yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y.%m.%d") + download_url_base = f"https://nightlies.tbb.torproject.org/nightly-builds/tor-browser-builds/tbb-nightly.{yesterday}/nightly-android-aarch64" + print( + f"No file paths provided, downloading yesterday's nightly from {download_url_base}" + ) + + app_file_url = f"{download_url_base}/tor-browser-noopt-android-aarch64-tbb-nightly.{yesterday}.apk" + test_file_url = ( + f"{download_url_base}/tor-browser-tbb-nightly.{yesterday}-androidTest.apk" + ) + + # BrowserStack will fail if there are `.` in the file name other than before the extension. + yesterday = yesterday.replace(".", "-") + app_file_path = f"/tmp/nightly-{yesterday}.apk" + test_file_path = f"/tmp/nightly-test-{yesterday}.apk" + + download_file(app_file_url, app_file_path) + download_file(test_file_url, test_file_path) + +devices = [device.strip() for device in args.devices.split(",")] +tests = args.tests.split(",") if args.tests else [] + +browserstack_username = os.getenv("BROWSERSTACK_USERNAME") +browserstack_api_key = os.getenv("BROWSERSTACK_API_KEY") +if not browserstack_username or not browserstack_api_key: + print( + "\033[1;31mEnvironment variables BROWSERSTACK_USERNAME and BROWSERSTACK_API_KEY must be set.\033[0m" + ) + sys.exit(1) + +# Upload app file +with open(app_file_path, "rb") as app_file: + response = requests.post( + "https://api-cloud.browserstack.com/app-automate/espresso/v2/app", + auth=(browserstack_username, browserstack_api_key), + files={"file": app_file}, + ) + +if response.status_code != 200: + print("\033[1;31mFailed to upload app file.\033[0m") + print(response.text) + sys.exit(1) + +bs_app_url = response.json().get("app_url") +print("\033[1;32mSuccessfully uploaded app file.\033[0m") +print(f"App URL: {bs_app_url}") + +# Upload test file +with open(test_file_path, "rb") as test_file: + response = requests.post( + "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite", + auth=(browserstack_username, browserstack_api_key), + files={"file": test_file}, + ) + +if response.status_code != 200: + print("\033[1;31mFailed to upload test file.\033[0m") + print(response.text) + sys.exit(1) + +bs_test_url = response.json().get("test_suite_url") +print("\033[1;32mSuccessfully uploaded test file.\033[0m") +print(f"Test URL: {bs_test_url}") + +# Trigger tests +test_params = { + "app": bs_app_url, + "testSuite": bs_test_url, + "devices": devices, + "class": tests, +} + +response = requests.post( + "https://api-cloud.browserstack.com/app-automate/espresso/v2/build", + auth=(browserstack_username, browserstack_api_key), + headers={"Content-Type": "application/json"}, + data=json.dumps(test_params), +) + +if response.status_code != 200: + print("\033[1;31mFailed to trigger test run.\033[0m") + print(response.text) + sys.exit(1) + +build_id = response.json().get("build_id") +print("\033[1;32mSuccessfully triggered test run.\033[0m") +print( + f"Test status also available at: https://app-automate.browserstack.com/builds/{build_id}\n===" +) + +# Poll for status +POLLING_TIMEOUT = 30 * 60 # 30min +POLLING_INTERVAL = 30 # 30s + + +class TestStatus(Enum): + QUEUED = "queued" + RUNNING = "running" + ERROR = "error" + FAILED = "failed" + PASSED = "passed" + TIMED_OUT = "timed out" + SKIPPED = "skipped" + + @classmethod + def from_string(cls, s): + try: + return cls[s.upper().replace(" ", "_")] + except KeyError: + raise ValueError(f"\033[1;31m'{s}' is not a valid test status.\033[0m") + + def is_terminal(self): + return self not in {TestStatus.QUEUED, TestStatus.RUNNING} + + def is_success(self): + return self in {TestStatus.PASSED, TestStatus.SKIPPED} + + def color_print(self): + if self == TestStatus.PASSED: + return f"\033[1;32m{self.value}\033[0m" + + if self in {TestStatus.ERROR, TestStatus.FAILED, TestStatus.TIMED_OUT}: + return f"\033[1;31m{self.value}\033[0m" + + if self == TestStatus.SKIPPED: + return f"\033[1;33m{self.value}\033[0m" + + return self.value + + +start_time = time.time() +elapsed_time = 0 +test_status = None +while elapsed_time <= POLLING_TIMEOUT: + response = requests.get( + f"https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{build_id}", + auth=(browserstack_username, browserstack_api_key), + ) + + if response.status_code != 200: + print("\033[1;31mFailed to get test status.\033[0m") + print(response.text) + sys.exit(1) + + test_status = TestStatus.from_string(response.json().get("status")) + if test_status.is_terminal(): + print(f"===\nTest finished. Result: {test_status.color_print()}") + break + else: + elapsed_time = time.time() - start_time + print(f"Test status: {test_status.value} ({elapsed_time:.2f}s)") + + if elapsed_time > POLLING_TIMEOUT: + print("===\n\033[1;33mWaited for tests for too long.\033[0m") + break + + time.sleep(POLLING_INTERVAL) + +if test_status is None or not test_status.is_success(): + sys.exit(1) diff --git a/.gitlab/ci/jobs/startup-test/startup-test.py b/.gitlab/ci/jobs/startup-test/startup-test.py new file mode 100644 index 0000000000000000000000000000000000000000..65e3bc33bae6000fa9ce6bd5baf036c94912dd1c --- /dev/null +++ b/.gitlab/ci/jobs/startup-test/startup-test.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess +from datetime import datetime, timedelta + +PLATFORM_TO_ARCH = { + "linux": ["x86_64", "i686"], + "macos": ["x86_64", "aarch64"], + "windows": ["x86_64", "i686"], +} + + +class DynamicArchAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + platform = getattr(namespace, "platform", None) + if not platform: + raise argparse.ArgumentError( + self, "The --platform argument must be provided before --arch." + ) + + valid_archs = PLATFORM_TO_ARCH.get(platform, []) + if values not in valid_archs: + raise argparse.ArgumentError( + self, + f"Invalid architecture '{values}' for platform '{platform}'. " + f"Valid options are: {', '.join(valid_archs)}", + ) + setattr(namespace, self.dest, values) + + +parser = argparse.ArgumentParser( + description="Downloads and executes yesterday's build of Tor or Mullvad browser nightly." +) + +parser.add_argument( + "--platform", + required=True, + help="Specify the platform (linux, macos or windows). Must be provided before --arch.", + choices=PLATFORM_TO_ARCH.keys(), +) +parser.add_argument( + "--arch", + required=True, + help="Specify the architecture (validated dynamically based on --platform).", + action=DynamicArchAction, +) +parser.add_argument( + "--browser", + required=True, + choices=["tor", "mullvad"], + help="Specify the browser (tor or mullvad)", +) + +args = parser.parse_args() +arch = f"-{args.arch}" +extra = "" + +if args.platform == "linux": + archive_extension = "tar.xz" + binary = f"Browser/start-{args.browser}-browser" +elif args.platform == "macos": + archive_extension = "dmg" + # The URL doesn't include the architecture for MacOS, + # because it's a universal build. + arch = "" + if args.browser == "tor": + binary = "Contents/MacOS/firefox" + else: + binary = "Contents/MacOS/mullvadbrowser" +elif args.platform == "windows": + archive_extension = "exe" + + if args.browser == "tor": + extra = "-portable" + binary = "Browser/firefox.exe" + else: + binary = "mullvadbrowser.exe" + +yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y.%m.%d") + +download_url_base = ( + "https://nightlies.tbb.torproject.org/nightly-builds/tor-browser-builds" +) +if args.browser == "tor": + download_url = f"{download_url_base}/tbb-nightly.{yesterday}/nightly-{args.platform}{arch}/{args.browser}-browser-{args.platform}{arch}{extra}-tbb-nightly.{yesterday}.{archive_extension}" +else: + download_url = f"{download_url_base}/tbb-nightly.{yesterday}/mullvadbrowser-nightly-{args.platform}{arch}/{args.browser}-browser-{args.platform}{arch}-tbb-nightly.{yesterday}.{archive_extension}" + +subprocess.run( + [ + "python3", + "testing/mozharness/scripts/does_it_crash.py", + "--run-for", + "30", + "--thing-url", + download_url, + "--thing-to-run", + binary, + ] +) diff --git a/.gitlab/ci/jobs/startup-test/startup-test.yml b/.gitlab/ci/jobs/startup-test/startup-test.yml new file mode 100644 index 0000000000000000000000000000000000000000..cb4d15395342917488a5201fc61eae011a9b6a7f --- /dev/null +++ b/.gitlab/ci/jobs/startup-test/startup-test.yml @@ -0,0 +1,63 @@ +# startup-test-windows: +# extends: .with-local-repo-pwsh +# variables: +# LOCAL_REPO_PATH: "C:\\Users\\windoes\\tor-browser.git" +# stage: startup-test +# interruptible: true +# parallel: +# matrix: +# - BROWSER: ["tor", "mullvad"] +# tags: +# - x86-win11 +# script: +# - ./mach python testing/mozbase/setup_development.py +# - ./mach python .gitlab/ci/jobs/startup-test/startup-test.py --platform windows --arch x86_64 --browser $BROWSER +# rules: +# - if: $CI_PIPELINE_SOURCE == "schedule" + +# startup-test-macos: +# extends: .with-local-repo-bash +# variables: +# LOCAL_REPO_PATH: "/Users/gitlab-runner/tor-browser.git" +# stage: startup-test +# interruptible: true +# parallel: +# matrix: +# - BROWSER: ["tor", "mullvad"] +# tags: +# - x86-macos +# script: +# - ./mach python testing/mozbase/setup_development.py +# - ./mach python .gitlab/ci/jobs/startup-test/startup-test.py --platform macos --arch x86_64 --browser $BROWSER +# rules: +# - if: $CI_PIPELINE_SOURCE == "schedule" + +startup-test-linux: + extends: .with-local-repo-bash + image: $IMAGE_PATH + stage: startup-test + interruptible: true + parallel: + matrix: + - BROWSER: ["tor", "mullvad"] + tags: + - firefox + script: + - Xvfb :99 -screen 0 1400x900x24 & + - export DISPLAY=:99 + - ./mach python testing/mozbase/setup_development.py + - ./mach python .gitlab/ci/jobs/startup-test/startup-test.py --platform linux --arch x86_64 --browser $BROWSER + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + +startup-test-android: + extends: .with-local-repo-bash + image: $IMAGE_PATH + stage: startup-test + interruptible: true + tags: + - firefox + script: + - ./mach python .gitlab/ci/jobs/startup-test/startup-test-android.py --devices "Samsung Galaxy S23-13.0, Samsung Galaxy S8-7.0" --tests org.mozilla.fenix.LaunchTest + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" diff --git a/.gitlab/ci/jobs/update-containers.yml b/.gitlab/ci/jobs/update-containers.yml new file mode 100644 index 0000000000000000000000000000000000000000..3ec72cad27f6f74d0935e31a21a7033d77a0a944 --- /dev/null +++ b/.gitlab/ci/jobs/update-containers.yml @@ -0,0 +1,16 @@ +build-base-image: + stage: update-container-images + interruptible: true + image: containers.torproject.org/tpo/tpa/base-images/podman:bookworm + script: + - export TAG="${CI_REGISTRY_IMAGE}/base:latest" + - podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - podman build --layers=false $IMAGE -t ${TAG} -f .gitlab/ci/containers/base/Containerfile . + - | + echo -e "\e[33mPushing new image to registry as ${TAG}\e[0m" + podman push ${TAG} + rules: + - if: ($CI_COMMIT_BRANCH && $CI_COMMIT_REF_PROTECTED == 'true' && $CI_PROJECT_NAMESPACE == 'tpo/applications' && $CI_PIPELINE_SOURCE == 'push') + changes: + - '.gitlab/ci/containers/base/Containerfile' + - '.gitlab-ci.yml' diff --git a/.gitlab/ci/jobs/update-translations.yml b/.gitlab/ci/jobs/update-translations.yml new file mode 100644 index 0000000000000000000000000000000000000000..e694073e1699a47c2fa0d2a0859684bf933db793 --- /dev/null +++ b/.gitlab/ci/jobs/update-translations.yml @@ -0,0 +1,80 @@ +.update-translation-base: + stage: update-translations + rules: + - if: ($TRANSLATION_FILES != "" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push") + changes: + - "**/*.ftl" + - "**/*.properties" + - "**/*.dtd" + - "**/*strings.xml" + - "**/update-translations.yml" + - "**/l10n/combine/combine.py" + - "**/l10n/combine-translation-versions.py" + - if: ($TRANSLATION_FILES != "" && $FORCE_UPDATE_TRANSLATIONS == "true") + variables: + COMBINED_FILES_JSON: "combined-translation-files.json" + TRANSLATION_FILES: '[ + { + "name": "brand.ftl", + "where": ["browser/branding/tb-release", "toolkit/torbutton"], + "branch": "tor-browser", + "directory": "branding" + }, + { + "name": "brand.properties", + "where": ["browser/branding/tb-release", "toolkit/torbutton"], + "branch": "tor-browser" + }, + { "name": "tor-browser.ftl", "branch": "tor-browser" }, + { "name": "aboutTBUpdate.dtd", "branch": "tor-browser" }, + { "name": "torbutton.dtd", "branch": "tor-browser" }, + { "name": "onionLocation.properties", "branch": "tor-browser" }, + { "name": "settings.properties", "branch": "tor-browser" }, + { "name": "torbutton.properties", "branch": "tor-browser" }, + { "name": "torConnect.properties", "branch": "tor-browser" }, + { "name": "torlauncher.properties", "branch": "tor-browser" }, + { "name": "base-browser.ftl", "branch": "base-browser" }, + { + "name": "torbrowser_strings.xml", + "branch": "fenix-torbrowserstringsxml", + "exclude-legacy": true + } + ]' + TRANSLATION_INCLUDE_LEGACY: "true" + + +combine-en-US-translations: + extends: .update-translation-base + needs: [] + image: python + variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + cache: + paths: + - .cache/pip + # Artifact is for translation project job + artifacts: + paths: + - "$COMBINED_FILES_JSON" + expire_in: "60 min" + reports: + dotenv: job_id.env + # Don't load artifacts for this job. + dependencies: [] + script: + # Save this CI_JOB_ID to the dotenv file to be used in the variables for the + # push-en-US-translations job. + - echo 'COMBINE_TRANSLATIONS_JOB_ID='"$CI_JOB_ID" >job_id.env + - pip install compare_locales + - python ./tools/base-browser/l10n/combine-translation-versions.py "$CI_COMMIT_BRANCH" "$TRANSLATION_FILES" "$COMBINED_FILES_JSON" + +push-en-US-translations: + extends: .update-translation-base + needs: + - job: combine-en-US-translations + variables: + COMBINED_FILES_JSON_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${COMBINE_TRANSLATIONS_JOB_ID}/artifacts/${COMBINED_FILES_JSON}" + trigger: + strategy: depend + project: tor-browser-translation-bot/translation + branch: tor-browser-ci diff --git a/.gitlab/ci/mixins.yml b/.gitlab/ci/mixins.yml new file mode 100644 index 0000000000000000000000000000000000000000..7a35eac53885e1d97e4265885c46a519839a175a --- /dev/null +++ b/.gitlab/ci/mixins.yml @@ -0,0 +1,70 @@ +.with-local-repo-bash: + variables: + GIT_STRATEGY: "none" + before_script: + - git init + - git remote add local "$LOCAL_REPO_PATH" + - | + # Determine the reference of the target branch in the local repository copy. + # + # 1. List all references in the local repository + # 2. Filter the references to the target branch + # 3. Remove tags + # 4. Keep a single line, in case there are too many matches + # 5. Clean up the output + # 6. Remove everything before the last two slashes, because the output is like `refs/heads/...` or `refs/remotes/...` + TARGET_BRANCH=$(git ls-remote local | grep ${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME} | grep -v 'refs/tags/' | awk '{print $2}' | tail -1 | sed 's|[^/]*/[^/]*/||') + if [ -z "$TARGET_BRANCH" ]; then + echo "Target branch $TARGET_BRANCH is not yet in local repository. Stopping the pipeline." + exit 1 + fi + - git fetch --depth 500 local $TARGET_BRANCH + - git remote add origin "$CI_REPOSITORY_URL" + - | + if [ -z "${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}" ]; then + echo "No branch specified. Stopping the pipeline." + exit 1 + fi + - echo "Fetching from remote branch ${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}" + - | + if ! git fetch origin "${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"; then + echo -e "\e[31mFetching failed for branch ${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} from $CI_REPOSITORY_URL.\e[0m" + echo "Attempting to fetch the merge request branch, assuming this pipeline is not running in a fork." + git fetch origin "merge-requests/${CI_MERGE_REQUEST_IID}/head" + fi + - git checkout FETCH_HEAD + +.with-local-repo-pwsh: + variables: + GIT_STRATEGY: "none" + before_script: + - git init + - git remote add local $env:LOCAL_REPO_PATH + - | + $branchName = $env:CI_COMMIT_BRANCH + if ([string]::IsNullOrEmpty($branchName)) { + $branchName = $env:CI_MERGE_REQUEST_TARGET_BRANCH_NAME + } + $TARGET_BRANCH = git ls-remote local | Select-String -Pattern $branchName | Select-String -Pattern -NotMatch 'refs/tags/' | Select-Object -Last 1 | ForEach-Object { $_.ToString().Split()[1] -replace '^[^/]*/[^/]*/', '' } + if ([string]::IsNullOrEmpty($TARGET_BRANCH)) { + Write-Output "Target branch $TARGET_BRANCH is not yet in local repository. Stopping the pipeline." + exit 1 + } + - git remote add origin $env:CI_REPOSITORY_URL + - | + $branchName = $env:CI_COMMIT_BRANCH + if ([string]::IsNullOrEmpty($branchName)) { + $branchName = $env:CI_MERGE_REQUEST_SOURCE_BRANCH_NAME + } + if ([string]::IsNullOrEmpty($branchName)) { + Write-Output "No branch specified. Stopping the pipeline." + exit 1 + } + - Write-Output "Fetching from remote branch $branchName" + - | + if (! git fetch origin $branchName) { + Write-Output "Fetching failed for branch $branchName from $env:CI_REPOSITORY_URL." + Write-Output "Attempting to fetch the merge request branch, assuming this pipeline is not running in a fork." + git fetch origin "merge-requests/$env:CI_MERGE_REQUEST_IID/head" + } + - git checkout FETCH_HEAD diff --git a/.gitlab/issue_templates/Backport Android Security Fixes.md b/.gitlab/issue_templates/Backport Android Security Fixes.md new file mode 100644 index 0000000000000000000000000000000000000000..9ebdf097626f1359419b49ff57e7e84974e52303 --- /dev/null +++ b/.gitlab/issue_templates/Backport Android Security Fixes.md @@ -0,0 +1,142 @@ +<details> + <summary>Explanation of Variables</summary> + +- `$(ESR_VERSION)`: the Mozilla defined ESR version, used in various places for building tor-browser tags, labels, etc + - **Example**: `102.8.0` +- `$(RR_VERSION)`: the Mozilla defined Rapid-Release version; Tor Browser for Android is based off of the `$(ESR_VERSION)`, but Mozilla's Firefox for Android is based off of the `$(RR_VERSION)` so we need to keep track of security vulnerabilities to backport from the monthly Rapid-Release train and our frozen ESR train. + - **Example**: `110` +- `$(PROJECT_NAME)`: the name of the browser project, either `base-browser` or `tor-browser` +- `$(TOR_BROWSER_MAJOR)`: the Tor Browser major version + - **Example**: `12` +- `$(TOR_BROWSER_MINOR)`: the Tor Browser minor version + - **Example**: either `0` or `5`; Alpha's is always `(Stable + 5) % 10` +- `$(BUILD_N)`: a project's build revision within a its branch; many of the Firefox-related projects have a `$(BUILD_N)` suffix and may differ between projects even when they contribute to the same build. + - **Example**: `build1` +</details> + +**NOTE:** It is assumed the `tor-browser` rebases (stable and alpha) have already happened and there exists a `build1` build tags for both `base-browser` and `tor-browser` (stable and alpha) + +### **Bookkeeping** + +- [ ] Link this issue to the appropriate [Release Prep](https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep) issues (stable and alpha). + +### **Security Vulnerabilities Report**: https://www.mozilla.org/en-US/security/advisories/ + +- Potentially Affected Components: + - `firefox`/`geckoview`: https://github.com/mozilla/gecko-dev + - `application-services`: https://github.com/mozilla/application-services + - `android-components` (ESR 102 only): https://github.com/mozilla-mobile/firefox-android + - `fenix` (ESR 102 only): https://github.com/mozilla-mobile/firefox-android + - `firefox-android`: https://github.com/mozilla-mobile/firefox-android + +**NOTE:** `android-components` and `fenix` used to have their own repos, but since November 2022 they have converged to a single `firefox-android` repo. Any backports will require manually porting patches over to our legacy repos until we have transitioned to ESR 115. + +- [ ] Go through the `Security Vulnerabilities fixed in Firefox $(RR_VERSION)` report and create a candidate list of CVEs which potentially need to be backported in this issue: + - CVEs which are explicitly labeled as 'Android' only + - CVEs which are fixed in Rapid Release but not in ESR + - 'Memory safety bugs' fixed in Rapid Release but not in ESR +- [ ] Foreach issue: + - Create link to the CVE on [mozilla.org](https://www.mozilla.org/en-US/security/advisories/) + - **Example**: https://www.mozilla.org/en-US/security/advisories/mfsa2023-05/#CVE-2023-25740 + - Create link to the associated Bugzilla issues (found in the CVE description) + - Create links to the relevant `gecko-dev`/other commit hashes which need to be backported OR a brief justification for why the fix does not need to be backported + - To find the `gecko-dev` version of a `mozilla-central`, search for a unique string in the relevant `mozilla-central` commit message in the `gecko-dev/release` branch log. + - **NOTE:** This process is unfortunately somewhat poorly defined/ad-hoc given the general variation in how Bugzilla issues are labeled and resolved. In general this is going to involve a bit of hunting to identify needed commits or determining whether or not the fix is relevant. + +### CVEs + +<!-- CVE Resolution Template, foreach CVE to investigate add an entry in the form: +- [ ] https://www.mozilla.org/en-US/security/advisories/mfsaYYYY-NN/#CVE-YYYY-XXXXX // CVE description + - https://bugzilla.mozilla.org/show_bug.cgi?id=NNNNNN // Bugzilla issue + - **Note**: Any relevant info about this fix, justification for why it is not necessary, etc + - **Patches** + - firefox-android: https://link.to/relevant/patch + - firefox: https://link.to/relevant/patch + --> + +### **tor-browser**: https://gitlab.torproject.org/tpo/applications/tor-browser.git +- [ ] Backport any Android-specific security fixes from Firefox rapid-release + - [ ] Backport patches to `tor-browser` stable branch + - [ ] Open MR + - [ ] Merge + - [ ] Rebase patches onto: + - [ ] `base-browser` stable + - [ ] `tor-browser` alpha + - [ ] `base-browser` alpha + - [ ] Sign/Tag commits: + - **Tag**: `$(PROJECT_NAME)-$(ESR_VERSION)-$(TOR_BROWSER_MAJOR).$(TOR_BROWSER_MINOR)-1-$(BUILD_N)` + - **Message**: `Tagging $(BUILD_N) for $(ESR_VERSION)-based stable|alpha)` + - [ ] `base-browser` stable + - [ ] `tor-browser` stable + - [ ] `base-browser` alpha + - [ ] `tor-browser` alpha + - [ ] Push tags to `upstream` +- **OR** +- [ ] No backports + +### **application-services**: https://gitlab.torproject.org/tpo/applications/application-services +- **NOTE**: we will need to setup a gitlab copy of this repo and update `tor-browser-build` before we can apply security backports here +- [ ] Backport any Android-specific security fixes from Firefox rapid-release + - [ ] Backport patches to `application-services` stable branch + - [ ] Open MR + - [ ] Merge + - [ ] Rebase patches onto `application-services` alpha + - [ ] Sign/Tag commits: + - **Tag**: `application-services-$(ESR_VERSION)-$(TOR_BROWSER_MAJOR).$(TOR_BROWSER_MINOR)-1-$(BUILD_N)` + - **Message**: `Tagging $(BUILD_N) for $(ESR_VERSION)-based stable|alpha` + - [ ] `application-services` stable + - [ ] `application-services` alpha + - [ ] Push tags to `upstream` +- **OR** +- [ ] No backports + + +### **android-components (Optional, ESR 102)**: https://gitlab.torproject.org/tpo/applications/android-components.git +- [ ] Backport any Android-specific security fixes from Firefox rapid-release + - **NOTE**: Since November 2022, this repo has been merged with `fenix` into a singular `firefox-android` repo: https://github.com/mozilla-mobile/firefox-android. Any backport will require a patch rewrite to apply to our legacy `android-components` project. + - [ ] Backport patches to `android-components` stable branch + - [ ] Open MR + - [ ] Merge + - [ ] Rebase patches onto `android-components` alpha + - [ ] Sign/Tag commits: + - **Tag**: `android-components-$(ESR_VERSION)-$(TOR_BROWSER_MAJOR).$(TOR_BROWSER_MINOR)-1-$(BUILD_N)` + - **Message**: `Tagging $(BUILD_N) for $(ESR_VERSION)-based stable|alpha)` + - [ ] `android-components` stable + - [ ] `android-components` alpha + - [ ] Push tags to `upstream` +- **OR** +- [ ] No backports + + +### **fenix (Optional, ESR 102)**: https://gitlab.torproject.org/tpo/applications/fenix.git +- [ ] Backport any Android-specific security fixes from Firefox rapid-release + - **NOTE**: Since February 2023, this repo has been merged with `android-components` into a singular `firefox-android` repo: https://github.com/mozilla-mobile/firefox-android. Any backport will require a patch rewrite to apply to our legacy `fenix` project. + - [ ] Backport patches to `fenix` stable branch + - [ ] Open MR + - [ ] Merge + - [ ] Rebase patches onto `fenix` alpha + - [ ] Sign/Tag commits: + - **Tag**: `tor-browser-$(ESR_VERSION)-$(TOR_BROWSER_MAJOR).$(TOR_BROWSER_MINOR)-1-$(BUILD_N)` + - **Message**: `Tagging $(BUILD_N) for $(ESR_VERSION)-based stable|alpha)` + - [ ] `fenix` stable + - [ ] `fenix` alpha + - [ ] Push tags to `upstream` +- **OR** +- [ ] No backports + +### **firefox-android**: https://gitlab.torproject.org/tpo/applications/firefox-android +- [ ] Backport any Android-specific security fixes from Firefox rapid-release + - [ ] Backport patches to `firefox-android` stable branch + - [ ] Open MR + - [ ] Merge + - [ ] Rebase patches onto `fenix` alpha + - [ ] Sign/Tag commits: + - **Tag**: `firefox-android-$(ESR_VERSION)-$(TOR_BROWSER_MAJOR).$(TOR_BROWSER_MINOR)-1-$(BUILD_N)` + - **Message**: `Tagging $(BUILD_N) for $(ESR_VERSION)-based stable|alpha)` + - [ ] `firefox-android` stable + - [ ] `firefox-android` alpha + - [ ] Push tags to `upstream` +- **OR** +- [ ] No backports + +/confidential diff --git a/.gitlab/issue_templates/Bugzilla Triage.md b/.gitlab/issue_templates/Bugzilla Triage.md new file mode 100644 index 0000000000000000000000000000000000000000..749f2e910d998cf7acb2cd58ba03b5fed9b9000c --- /dev/null +++ b/.gitlab/issue_templates/Bugzilla Triage.md @@ -0,0 +1,51 @@ + # Bugzilla Triage + + **NOTE** This issue presumes the branches and tags for the next Firefox release have already been created in tor-browser.git + + - [ ] Generate Bugzilla triage CSV + - Run (from `tor-browser-build` root): + ```bash + ./tools/browser/generate-bugzilla-triage-csv ${FIREFOX_VERSION} ${PREVIOUS_NIGHTLY_TAG} ${NEXT_NIGHLTY_TAG} ${TRIAGE_ISSUE_NUMBER} ${REVIEWERS} > out.csv + ``` + - `${FIREFOX_VERSION}`: the major Firefox version of the nightly to review + - **Example**: 129 + - `${PREVIOUS_NIGHTLY_TAG}`: the nightly 'end' tag of the previous major Firefox version + - **Example**: `FIREFOX_NIGHTLY_128_END` + - `${NEXT_NIGHLTY_TAG}`: the nightly 'end' tag of the next major Firefox version we are reviewing + - **Example**: `FIREFOX_NIGHTLY_129_END` + - `${TRIAGE_ISSUE_NUMBER}`: this `tor-browser` issue + - **Example**: `43303` + - `${REVIEWERS}`: `morgan` and two additional devs to triage this Firefox version + - `boklm` + - `brizental` + - `clairehurst` + - `dan` + - `henry` + - `jwilde` + - `ma1` + - `pierov` + - **Example**: + ```bash + ./tools/browser/generate-bugzilla-triage-csv 129 FIREFOX_NIGHTLY_128_END FIREFOX_NIGHTLY_129_END 43303 morgan pierov henry > 129.csv + ``` + - [ ] Attach the generated CSV file to the triage isssue + - [ ] Import to Google Sheets ( https://sheets.google.com ) + - [ ] Create blank spreadsheet + - [ ] **Title**: `Bugzilla Triage ${VERSION}` + - [ ] Import CSV: File > Import > Upload + - **Import location**: "Replace spreadsheet" + - **Separator type**: "Comma" + - **Convert text to numbers, dates, and fomulas**: "✅" + - [ ] Convert 'Review' column's issue cells to check-boxes: + - Select relevant cells (i.e.: `A2:A1554` for in the 129 triage) + - Insert > Checkbox + - [ ] Convert 'Triaged by' cells to check-boxes + - [ ] Share Spreadsheet + - 🔒 Share > General access + - Change `Restricted` to `Anyone with the link` + - Post link in an internal note on this issue + - [ ] Page requested reviewers to this issue + - [ ] Triage Completed by: + - [ ] morgan + - [ ] reviewer 1 <!-- replace with reviewer name :) --> + - [ ] reviewer 2 <!-- replace with reviewer name :) --> diff --git a/.gitlab/issue_templates/Emergency Security Issue.md b/.gitlab/issue_templates/Emergency Security Issue.md new file mode 100644 index 0000000000000000000000000000000000000000..33e6a1d7452a9662d11cb4333dc65b1aca4634cf --- /dev/null +++ b/.gitlab/issue_templates/Emergency Security Issue.md @@ -0,0 +1,90 @@ +**NOTE** This is an issue template to standardise our process for responding to and fixing critical security and privacy vulnerabilities, exploits, etc. + +## Information + +### Related Issue +- tor-browser#AAAAA +- mullvad-browser#BBBBB +- tor-browser-build#CCCCC + +#### Affected Platforms + +- [ ] Android +- [ ] Desktop + - [ ] Windows + - [ ] macOS + - [ ] Linux + +### Type of Issue: What are we dealing with? + +- [ ] Security (sandbox escape, remote code execution, etc) +- [ ] Proxy Bypass (traffic contents becoming MITM'able) +- [ ] De-Anonymization (otherwise identifying which website a user is visiting) +- [ ] Cross-Site Linkability (correlating sessions across circuits and websites) +- [ ] Disk Leak (persisting session information to disk) +- [ ] Other (please explain) + +### Involvement: Who needs to be consulted and or involved to fix this? + +- [ ] Applications Developers + - [ ] **boklm** : build, packaging, signing, release + - [ ] **clairehurst** : Android, macOS + - [ ] **dan** : Android, macOS + - [ ] **henry** : accessibility, frontend, localisation + - [ ] **ma1** : firefox internals + - [ ] **pierov** : updater, fonts, localisation, general + - [ ] **richard** : signing, release + - [ ] **thorin** : fingerprinting +- [ ] Other Engineering Teams + - [ ] Networking (**ahf**, **dgoulet**) + - [ ] Anti-Censorship (**meskio**, **cohosh**) + - [ ] UX (**donuts**) + - [ ] TPA (**anarcat**, **lavamind**) +- [ ] External Tor Partners + - [ ] Mozilla + - [ ] Mullvad + - [ ] Brave + - [ ] Guardian Project (Orbot, Onion Browser) + - [ ] Tails + - [ ] Other (please list) + +### Urgency: When do we need to act? + +- [ ] **ASAP** :rotating_light: Emergency release :rotating_light: +- [ ] Next scheduled stable +- [ ] Next scheduled alpha, then backport to stable +- [ ] Next major release +- [ ] Other (please explain) + +#### Justification + +<!-- Provide some paragraph here justifying the logic behind our estimated urgency --> + +### Side-Effects: Who will be affected by a fix for this? +Sometimes fixes have side-effects: users lose their data, roadmaps need to be adjusted, services have to be upgraded, etc. Please enumerate the known downstream consequences a fix to this issue will likely incur. +- [ ] End-Users (please list) +- [ ] Internal Partners (please list) +- [ ] External Partners (please list) + +## Todo: + +### Communications + +- [ ] Start an initial email thread with the following people: + - [ ] **bella** + - [ ] Relevant Applications Developers + - [ ] **(Optional)** **micah** + - if there are considerations or asks outside the Applications Team + - [ ] **(Optional)** Other Team Leads + - if there are considerations or asks outside the Applications Team + - [ ] **(Optional)** **gazebook** + - if there are consequences to the organisation or partners beyond a browser update, then a communication plan may be needed + +/cc @bella +/cc @ma1 +/cc @micah +/cc @richard + +/confidential + +Godspeed! :pray: diff --git a/.gitlab/issue_templates/QA - Android.md b/.gitlab/issue_templates/QA - Android.md new file mode 100644 index 0000000000000000000000000000000000000000..3acc5a06dd54f30ca71020427ed6be24d7a0b6b5 --- /dev/null +++ b/.gitlab/issue_templates/QA - Android.md @@ -0,0 +1,71 @@ +Manual QA test check-list for major android releases. Please copy/paste form into your own comment, fill out relevant info and run through the checklist! +<details> + <summary>Tor Browser Android QA Checklist</summary> +```markdown +# System Information + +- Version: Tor Browser XXX +- OS: Android YYY +- Device + CPU Architecture: ZZZ + +# Features + +## Base functionality +- [ ] Tor Browser launches successfully +- [ ] Connects to the Tor network +- [ ] Localisation (Browser chrome) + - [ ] Check especially the recently added strings +- [ ] Toolbars and menus work +- [ ] Fingerprinting resistance: https://arkenfox.github.io/TZP/tzp.html +- [ ] Security level (Standard, Safer, Safest) + - **TODO**: test pages verifying correct behaviour + +## Proxy safety +- [ ] Tor exit test: https://check.torproject.org +- [ ] Circuit isolation + - Following websites should all report different IP addresses + - https://ifconfig.io + - https://myip.wtf + - https://wtfismyip.com +- [ ] DNS leaks: https://dnsleaktest.com + +## Connectivity + Anti-Censorship +- [ ] Bridges: + - Bootstrap + - Browse: https://check.torproject.org + - [ ] Default bridges: + - [ ] obfs4 + - [ ] meek + - [ ] snowflake + - [ ] User provided bridges: + - [ ] obfs4 from https://bridges.torproject.org + - [ ] webtunnel from https://bridges.torproject.org + - [ ] conjure from [gitlab](https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/conjure/-/blob/main/client/torrc?ref_type=heads#L6) + +## Web Browsing +- [ ] HTTPS-Only: http://http.badssl.com +- [ ] .onion: + - [ ] torproject.org onion: http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/ + - [ ] Onion service errors + - [ ] invalid onion: http://invalid.onion + - [ ] onion offline: http://wfdn32ds656ycma5gvrh7duvdvxbg2ygzr3no3ijsya25qm6nnko4iqd.onion/ + - [ ] onion baddssl: https://gitlab.torproject.org/tpo/applications/team/-/wikis/Development-Information/BadSSL-But-Onion + - **TODO** all the identity block states + - **TODO** client auth +- [ ] **TODO**: .securedrop.tor.onion +- [ ] **TODO**: onion-service alt-svc +- [ ] HTML5 Video: https://tekeye.uk/html/html5-video-test-page + - [ ] MPEG4 + - [ ] WebM + - [ ] Ogg +- [ ] WebSocket Test: https://websocketking.com/ + +## External Components +- [ ] NoScript + - [ ] Latest Version: https://addons.mozilla.org/en-US/firefox/addon/noscript/ + - [ ] Not removable from about:addons + - [ ] Tests: https://test-data.tbb.torproject.org/test-data/noscript/ + - **TODO**: fix test pages +``` + +</details> diff --git a/.gitlab/issue_templates/QA - Desktop.md b/.gitlab/issue_templates/QA - Desktop.md new file mode 100644 index 0000000000000000000000000000000000000000..78ad8c43ec61f397fbfa1d16e451a585981f70c4 --- /dev/null +++ b/.gitlab/issue_templates/QA - Desktop.md @@ -0,0 +1,164 @@ +Manual QA test check-list for major desktop releases. Please copy/paste form into your own comment, fill out relevant info and run through the checklist! + +<details> + <summary>Tor Browser Desktop QA Checklist</summary> + +```markdown +# System Information + +- Version: Tor Browser XXX +- OS: Windows|macOS|Linux YYY +- CPU Architecture: +- Profile: New|Old + +# Features + +## Base functionality +- [ ] Tor Browser launches successfully +- [ ] Connects to the Tor network + - [ ] Homepage loads: + - [ ] about:tor + - [ ] about:blank + - [ ] custom +- [ ] Tor Browser loads URLs passed by command-line after bootstrapped +- [ ] Localisation (Browser chrome) + - [ ] Language notification/message bar + - [ ] Spoof English + - [ ] Check especially the recently added strings +- [ ] UI Customisations: + - [ ] New Identity + - [ ] Toolbar icon + - [ ] Hamburger menu + - [ ] File menu + - [ ] New circuit for this site + - [ ] Circuit display + - [ ] Hamburger menu + - [ ] File menu + - [ ] No Firefox extras (Sync, Pocket, Report broken site, Tracking protection, etc) + - [ ] No unified extensions button (puzzle piece) + - [ ] NoScript button hidden + - [ ] Context Menu Populated +- [ ] Fingerprinting resistance: https://arkenfox.github.io/TZP/tzp.html +- [ ] Security level (Standard, Safer, Safest) + - Displays in: + - toolbar icon + - toolbar panel + - about:preferences#privacy + - [ ] On switch, each UI element is updated + - [ ] On custom config (toggle `svg.disabled`) + - [ ] each UI element displays warning + - [ ] `Restore defaults` reverts custom prefs + - **TODO**: test pages verifying correct behaviour +- [ ] New identity +- [ ] Betterboxing + - [ ] Reuse last window size + - [ ] Content alignment + - [ ] No letterboxing: + - [ ]empty tabs or privileged pages (eg: about:blank, about:about) + - [ ] full-screen video + - [ ] pdf viewer + - [ ] reader-mode +- [ ] Downloads Warning + - [ ] Downloads toolbar panel + - [ ] about:downloads + - [ ] Library window (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>o</kbd>) +- [ ] Drag and Drop protections: + - [ ] Dragging a link from a tab to another tab in the same window works + - [ ] Dragging a link from a tab to another tab in a separate window works + - [ ] Dragging a link into the library creates a bookmark + - [ ] Dragging a link from Tor Browser to Firefox doesn't work + - [ ] Dragging a link from Firefox to Tor Browser works + - [ ] Dragging a link from Tor Browser to another app (e.g., text editor) doesn't work + - [ ] Repeat with page favicon + +## Proxy safety +- [ ] Tor exit test: https://check.torproject.org +- [ ] Circuit isolation + - Following websites should all report different IP addresses + - https://ifconfig.io + - https://myip.wtf + - https://wtfismyip.com +- [ ] DNS leaks: https://dnsleaktest.com +- [ ] Circuit Display + - [ ] Website => circuit + - [ ] Remote PDF => circuit + - [ ] Remote image => circuit + - [ ] .onion Website => circuit with onion-service relays + - [ ] .tor.onion Website => circuit with onion-service relays, link to true onion address + - http://ft.securedrop.tor.onion + - [ ] Website in reader mode => circuit (same as w/o reader mode) + - [ ] Local image => no circuit + - [ ] Local SVG with remote content => catch-all circuit, but not shown + - [ ] Local PDF => no circuit + - [ ] Local HTML `file://` with local resources => no circuit + - [ ] Local HTML `file://` with remote resources => catch-all circuit, but not shown + +## Connectivity + Anti-Censorship +- [ ] Tor daemon config by environment variables + - https://gitlab.torproject.org/tpo/applications/team/-/wikis/Environment-variables-and-related-preferences +- [ ] Internet Test ( about:preferences#connection ) + - [ ] Fails when offline + - [ ] Succeeds when online +- [ ] Bridges: + - Bootstrap + - Browse: https://check.torproject.org + - Bridge node in circuit-display + - Bridge cards + - Disable + - Remove + - [ ] Default bridges: + - [ ] Removable as a group, not editable + - [ ] obfs4 + - [ ] meek + - [ ] snowflake + - [ ] User provided bridges: + - [ ] Removable and editable individually + - [ ] obfs4 from https://bridges.torproject.org + - [ ] webtunnel from https://bridges.torproject.org + - [ ] conjure from [gitlab](https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/conjure/-/blob/main/client/torrc?ref_type=heads#L6) + - [ ] Request bridges... + - [ ] Removable as a group, but not editable + - [ ] Succeeds when bootstrapped + - [ ] Succeeds when not bootstrapped + - **TODO**: Lox +- [ ] Connect Assist + - Useful pref: `torbrowser.debug.censorship_level` + - [ ] Auto-bootstrap updates Tor connection settings on success + - [ ] Auto-bootstrap restore previous Tor connection settings on failure + +## Web Browsing +- [ ] HTTPS-Only: http://http.badssl.com +- [ ] Crypto-currency warning on http website + - **TODO**: we should provide an example page +- [ ] .onion: + - [ ] torproject.org onion: http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/ + - [ ] Onion-Location pill + - [ ] Client authentication + - You can create an ephemeral client-auth onion-service using [onion share](https://onionshare.org) + - [ ] Remember key option saves the key between sessions. + - [ ] Saved keys are viewable in preferences (privacy). + - [ ] Can remove individual keys. + - [ ] Can remove all keys at once. + - [ ] Onion service errors + - [ ] invalid onion: http://invalid.onion + - [ ] onion offline: http://wfdn32ds656ycma5gvrh7duvdvxbg2ygzr3no3ijsya25qm6nnko4iqd.onion/ + - [ ] onion baddssl: https://gitlab.torproject.org/tpo/applications/team/-/wikis/Development-Information/BadSSL-But-Onion + - **TODO** all the identity block states + - **TODO** client auth +- [ ] **TODO**: .securedrop.tor.onion +- [ ] **TODO**: onion-service alt-svc +- [ ] HTML5 Video: https://tekeye.uk/html/html5-video-test-page + - [ ] MPEG4 + - [ ] WebM + - [ ] Ogg +- [ ] WebSocket Test: https://websocketking.com/ + +## External Components +- [ ] NoScript + - [ ] Latest Version: https://addons.mozilla.org/en-US/firefox/addon/noscript/ + - [ ] Not removable from about:addons + - [ ] Tests: https://test-data.tbb.torproject.org/test-data/noscript/ + - **TODO**: fix test pages +``` + +</details> diff --git a/.gitlab/issue_templates/Rebase Browser - Alpha.md b/.gitlab/issue_templates/Rebase Browser - Alpha.md new file mode 100644 index 0000000000000000000000000000000000000000..a408de32b9ac219ac98bbac5dbc28b0d44b022ef --- /dev/null +++ b/.gitlab/issue_templates/Rebase Browser - Alpha.md @@ -0,0 +1,153 @@ +**NOTE:** All examples in this template reference the rebase from 102.7.0esr to 102.8.0esr + +<details> + <summary>Explanation of Variables</summary> + +- `$(ESR_VERSION)`: the Mozilla defined ESR version, used in various places for building tor-browser tags, labels, etc + - **Example**: `102.8.0` +- `$(ESR_TAG)`: the Mozilla defined hg (Mercurial) tag associated with `$(ESR_VERSION)` + - **Example**: `FIREFOX_102_8_0esr_RELEASE` +- `$(ESR_TAG_PREV)`: the Mozilla defined hg (Mercurial) tag associated with the previous ESR version when rebasing (ie, the ESR version we are rebasing from) + - **Example**: `FIREFOX_102_7_0esr_BUILD1` +- `$(BROWSER_MAJOR)`: the browser major version + - **Example**: `12` +- `$(BROWSER_MINOR)`: the browser minor version + - **Example**: either `0` or `5`; Alpha's is always `(Stable + 5) % 10` +- `$(BASE_BROWSER_BRANCH)`: the full name of the current `base-browser` branch + - **Example**: `base-browser-102.8.0esr-12.5-1` +- `$(BASE_BROWSER_BRANCH_PREV)`: the full name of the previous `base-browser` branch + - **Example**: `base-browser-102.7.0esr-12.5-1` +- `$(TOR_BROWSER_BRANCH)`: the full name of the current `tor-browser` branch + - **Example**: `tor-browser-102.8.0esr-12.5-1` +- `$(TOR_BROWSER_BRANCH_PREV)`: the full name of the previous `tor-browser` branch + - **Example**: `tor-browser-102.7.0esr-12.5-1` +</details> + +**NOTE:** It is assumed that we've already identified the new ESR branch during the tor-browser stable rebase + +### **Bookkeeping** + +- [ ] Link this issue to the appropriate [Release Prep](https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep) issue. + +### Update Branch Protection Rules + +- [ ] In [Repository Settings](https://gitlab.torproject.org/tpo/applications/tor-browser/-/settings/repository): + - [ ] Remove previous alpha `base-browser` and `tor-browser` branch protection rules (this will prevent pushing new changes to the branches being rebased) + - [ ] Create new `base-browser` and `tor-browser` branch protection rule: + - **Branch**: `*-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1*` + - **Example**: `*-102.8.0esr-12.5-1*` + - **Allowed to merge**: `Maintainers` + - **Allowed to push and merge**: `Maintainers` + - **Allowed to force push**: `false` + - If you copied and pasted from old rules, double check you didn't add spaces at the end, as GitLab will not trim them! + +### **Create New Branches** + +- [ ] Find the Firefox mercurial tag `$(ESR_TAG)` + - If `$(BROWSER_MINOR)` is 5, the tag should already exist from the stable release + - Otherwise: + - [ ] Go to `https://hg.mozilla.org/releases/mozilla-esr$(ESR_MAJOR)/tags` + - [ ] Find and inspect the commit tagged with `$(ESR_TAG)` + - Tags are in yellow in the Mercurial web UI + - [ ] Find the equivalent commit in `https://github.com/mozilla/gecko-dev/commits/esr$(ESR_MAJOR)` + - The tag should be very close to `HEAD` (usually the second, before a `No bug - Tagging $(HG_HASH) with $(ESR_TAG)`) + - **Notice**: GitHub sorts commits by time, you might want to use `git log gecko-dev/esr$(ESR_MAJOR)` locally, instead + - [ ] Sign/Tag the `gecko-dev` commit: `git tag -as $(ESR_TAG) $(GIT_HASH) -m "Hg tag $(ESR_TAG)"` +- [ ] Create new alpha `base-browser` branch from Firefox mercurial tag + - Branch name in the form: `base-browser-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1` + - **Example**: `base-browser-102.8.0esr-12.5-1` +- [ ] Create new alpha `tor-browser` branch from Firefox mercurial tag + - Branch name in the form: `tor-browser-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1` + - **Example**: `tor-browser-102.8.0esr-12.5-1` +- [ ] Push new `base-browser` branch to `upstream` +- [ ] Push new `tor-browser` branch to `upstream` + +### **Rebase tor-browser** + +- [ ] Checkout a new local branch for the `tor-browser` rebase + - **Example**: `git branch tor-browser-rebase FIREFOX_102_8_0esr_BUILD1` +- [ ] **(Optional)** `base-browser` rebase and autosquash + - **NOTE** This step may be skipped if the `HEAD` of the previous `base-browser` branch is a `-buildN` tag + - [ ] Cherry-pick the previous `base-browser` commits up to `base-browser`'s `buildN` tag onto new `base-browser` rebase branch + - **Example**: `git cherry-pick FIREFOX_102_7_0esr_BUILD1..base-browser-102.7.0esr-12.5-1-build1` + - [ ] Rebase and autosquash these cherry-picked commits + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_BUILD1 HEAD` + - [ ] Cherry-pick remainder of patches after the `buildN` tag + - **Example**: `git cherry-pick base-browser-102.7.0esr-12.5-1-build1..upstream/base-browser-102.7.0esr-12.5-1` + +- [ ] `tor-browser` rebase and autosquash + - [ ] Note the current git hash of `HEAD` for `tor-browser` rebase+autosquash step: `git rev-parse HEAD` + - [ ] Cherry-pick the appropriate previous `tor-browser` branch's commit range up to the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick base-browser-102.7.0esr-12.5-1-build1..tor-browser-102.7.0esr-12.5-1-build1` + - **Example (if separate base-browser rebase was skipped)**: `git cherry-pick FIREFOX_102_7_0esr_BUILD1..tor-browser-102.7.0esr-12.5-1-build1` + - [ ] Rebase and autosquash **ONLY** these newly cherry-picked commits using the commit noted previously: `git rebase --autosquash --interactive $(PREV_HEAD)` + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_RELEASE` + - [ ] **(Optional)** Patch reordering + - **NOTE**: We typically want to do this after new features or bug fix commits which are not !fixups to an existing commit have been merged and are just sitting at the end of the commit history + - Relocate new `base-browser` patches in the patch-set to enforce this rough thematic ordering: + - **MOZILLA BACKPORTS** - official Firefox patches we have backported to our ESR branch: Android-specific security updates, critical bug fixes, worthwhile features, etc + - **MOZILLA REVERTS** - revert commits of official Firefox patches + - **UPLIFT CANDIDATES** - patches which stand on their own and should be uplifted to `mozilla-central` + - **BUILD CONFIGURATION** - tools/scripts, gitlab templates, etc + - **BROWSER CONFIGURATION** - branding, mozconfigs, preference overrides, etc + - **SECURITY PATCHES** - security improvements, hardening, etc + - **PRIVACY PATCHES** - fingerprinting, linkability, proxy bypass, etc + - **FEATURES** - new functionality: updater, UX, letterboxing, security level, add-on + - Relocate new `tor-browser` patches in the patch-set to enforce this rough thematic ordering: + - **BUILD CONFIGURATION** - tools/scripts, gitlab templates, etc + - **BROWSER CONFIGURATION** - branding, mozconfigs, preference overrides, etc + - **UPDATER PATCHES** - updater tweaks, signing keys, etc + - **SECURITY PATCHES** - non tor-dependent security improvements, hardening, etc + - **PRIVACY PATCHES** - non tor-dependent fingerprinting, linkability, proxy bypass, etc + - **FEAURES** - non tor-dependent features + - **TOR INTEGRATION** - legacy tor-launcher/torbutton, tor modules, bootstrapping, etc + - **TOR SECURITY PATCHES** - tor-specific security improvements + - **TOR PRIVACY PATCHES** - tor-specific privacy improvements + - **TOR FEATURES** - new tor-specific functionality: manual, onion-location, onion service client auth, etc + - [ ] Cherry-pick remainder of patches after the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick tor-browser-102.7.0esr-12.5-1-build1..upstream/tor-browser-102.7.0esr-12.5-1` + - [ ] Rebase and autosquash again, this time replacing all `fixup` and `squash` commands with `pick`. The goal here is to have all of the `fixup` and `squash` commits beside the commit which they modify, but kept un-squashed for easy debugging/bisecting. + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_RELEASE` +- [ ] Compare patch sets to ensure nothing *weird* happened during conflict resolution: + - [ ] diff of diffs: + - Do the diff between `current_patchset.diff` and `rebased_patchset.diff` with your preferred difftool and look at differences on lines that starts with + or - + - `git diff $(ESR_TAG_PREV)..$(BROWSER_BRANCH_PREV) > current_patchset.diff` + - `git diff $(ESR_TAG)..$(BROWSER_BRANCH) > rebased_patchset.diff` + - diff `current_patchset.diff` and `rebased_patchset.diff` + - If everything went correctly, the only lines which should differ should be the lines starting with `index abc123...def456` (unless the previous `base-browser` branch includes changes not included in the previous `tor-browser` branch) + - [ ] rangediff: `git range-diff $(ESR_TAG_PREV)..$(TOR_BROWSER_BRANCH_PREV) $(ESR_TAG)..HEAD` + - **Example**: `git range-dif FIREFOX_102_7_0esr_BUILD1..upstream/tor-browser-102.7.0esr-12.5-1 FIREFOX_102_8_0esr_BUILD1..HEAD` +- [ ] Open MR for the `tor-browser` rebase +- [ ] Merge +- Update and push `base-browser` branch + - [ ] Reset the new `base-browser` branch to the appropriate commit in this new `tor-browser` branch + - [ ] Push these commits to `upstream` +- [ ] Set `$(TOR_BROWSER_BRANCH)` as the default GitLab branch + - [ ] Go to [Repository Settings](https://gitlab.torproject.org/tpo/applications/tor-browser/-/settings/repository) + - [ ] Expand `Branch defaults` + - [ ] Set the branch and leave the `Auto-close` checkbox unchecked + - [ ] Save changes + +### **Sign and Tag** + +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the new alpha `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser alpha build1 + ``` + - [ ] Push tag to `upstream` +- [ ] Sign/Tag HEAD of the merged `base-browser` branch: + - In **tor-browser.git**, checkout the new alpha `base-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.basebrowser alpha build1 + ``` + - [ ] Push tag to `upstream` +- [ ] Update tor-browser-build's `main` branch (no MR required, you can just push it if you have the permissions) + - [ ] Update `projects/firefox/config` + - [ ] Update `firefox_platform_version` + - [ ] Set `browser_build` to 1 (to prevent failures in alpha testbuilds) + - [ ] Update `projects/geckoview/config` + - [ ] Update `firefox_platform_version` + - [ ] Set `browser_build` to 1 (to prevent failures in alpha testbuilds) diff --git a/.gitlab/issue_templates/Rebase Browser - Legacy.md b/.gitlab/issue_templates/Rebase Browser - Legacy.md new file mode 100644 index 0000000000000000000000000000000000000000..472e6f1efa2960a3e9898acf541d45855185a0a0 --- /dev/null +++ b/.gitlab/issue_templates/Rebase Browser - Legacy.md @@ -0,0 +1,111 @@ +**NOTE:** All examples in this template reference the rebase from 115.17.0esr to 115.18.0esr + +<details> + <summary>Explanation of Variables</summary> + +- `$(ESR_VERSION)`: the Mozilla defined ESR version, used in various places for building tor-browser tags, labels, etc + - **Example**: `115.18.0` +- `$(ESR_TAG)`: the Mozilla defined hg (Mercurial) tag associated with `$(ESR_VERSION)` + - **Example**: `FIREFOX_115_18_0esr_BUILD1` +- `$(ESR_TAG_PREV)`: the Mozilla defined hg (Mercurial) tag associated with the previous ESR version when rebasing (ie, the ESR version we are rebasing from) + - **Example**: `FIREFOX_115_17_0esr_BUILD1` +- `$(BASE_BROWSER_BRANCH)`: the full name of the current `base-browser` branch + - **Example**: `base-browser-115.18.0esr-13.5-1` +- `$(BASE_BROWSER_BRANCH_PREV)`: the full name of the previous `base-browser` branch + - **Example**: `base-browser-115.17.0esr-13.5-1` +- `$(TOR_BROWSER_BRANCH)`: the full name of the current `tor-browser` branch + - **Example**: `tor-browser-115.18.0esr-13.5-1` +- `$(TOR_BROWSER_BRANCH_PREV)`: the full name of the previous `tor-browser` branch + - **Example**: `tor-browser-115.17.0esr-13.5-1` +</details> + +### **Bookkeeping** + +- [ ] Link this issue to the appropriate [Release Prep](https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep) issue. + +### Update Branch Protection Rules + +- [ ] In [Repository Settings](https://gitlab.torproject.org/tpo/applications/tor-browser/-/settings/repository): + - [ ] Remove previous legacy `base-browser` and `tor-browser` branch protection rules (this will prevent pushing new changes to the branches being rebased) + - [ ] Create new `base-browser` and `tor-browser` branch protection rule: + - **Branch**: `*-$(ESR_VERSION)esr-13.5-1*` + - **Example**: `*-115.18.0esr-13.5-1*` + - **Allowed to merge**: `Maintainers` + - **Allowed to push and merge**: `Maintainers` + - **Allowed to force push**: `false` + +### **Identify the Firefox Tagged Commit and Create New Branches** + +- [ ] Find the Firefox mercurial tag here: https://hg.mozilla.org/releases/mozilla-esr102/tags + - **Example**: `FIREFOX_115_18_0esr_BUILD1` +- [ ] Find the analogous `gecko-dev` commit: https://github.com/mozilla/gecko-dev + - **Tip**: Search for unique string (like the Differential Revision ID) found in the mercurial commit in the `gecko-dev/esr115` branch to find the equivalent commit + - **Example**: `293d490d2e8d9fbb91c76336288f1287cbe285fb` +- [ ] Sign and Tag `gecko-dev` commit + - Sign/Tag `gecko-dev` commit : + - **Tag**: `$(ESR_TAG)` + - **Message**: `Hg tag $(ESR_TAG)` +- [ ] Create new legacy `base-browser` branch from tag + - Branch name in the form: `base-browser-$(ESR_VERSION)esr-13.5-1` + - **Example**: `base-browser-115.18.0esr-13.5-1` +- [ ] Create new legacy `tor-browser` branch from + - Branch name in the form: `tor-browser-$(ESR_VERSION)esr-13.5-1` + - **Example**: `tor-browser-115.18.0esr-13.5-1` +- [ ] Push new `base-browser` branch to `upstream` +- [ ] Push new `tor-browser` branch to `upstream` +- [ ] Push new `$(ESR_TAG)` to `upstream` + +### **Rebase tor-browser** + +- [ ] Checkout a new local branch for the `tor-browser` rebase + - **Example**: `git branch tor-browser-rebase FIREFOX_115_18_0esr_BUILD1` +- [ ] **(Optional)** `base-browser` rebase + - **NOTE** This step may be skipped if the `HEAD` of the previous `base-browser` branch is a `-buildN` tag + - [ ] Cherry-pick the previous `base-browser` commits up to `base-browser`'s `buildN` tag onto new `base-browser` rebase branch + - **Example**: `git cherry-pick FIREFOX_115_17_0esr_BUILD1..base-browser-115.17.0esr-13.5-1-build2` + - [ ] Rebase and autosquash these cherry-picked commits + - **Example**: `git rebase --autosquash --interactive FIREFOX_115_18_0esr_BUILD1 HEAD` + - [ ] Cherry-pick remainder of patches after the `buildN` tag + - **Example**: `git cherry-pick base-browser-115.17.0esr-13.5-1-build21..upstream/base-browser-115.17.0esr-13.5-1` +- [ ] `tor-browser` rebase + - [ ] Note the current git hash of `HEAD` for `tor-browser` rebase+autosquash step: `git rev-parse HEAD` + - [ ] Cherry-pick the appropriate previous `tor-browser` branch's commit range up to the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick base-browser-115.17.0esr-13.5-1-build1..tor-browser-115.17.0esr-13.5-1-build2 + - **Example (if separate base-browser rebase was skipped)**: `git cherry-pick FIREFOX_115_17_0esr_BUILD1..tor-browser-115.17.0esr-13.5-1-build2` + - [ ] Rebase and autosquash these newly cherry-picked commits: `git rebase --autosquash --interactive $(PREV_HEAD)` + - **Example**: `git rebase --autosquash --interactive FIREFOX_115_18_0esr_BUILD1` + - [ ] Cherry-pick remainder of patches after the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick tor-browser-115.17.0esr-13.5-1-build1..upstream/tor-browser-115.17.0esr-13.5-1` + - [ ] Rebase and autosquash again, this time replacing all `fixup` and `squash` commands with `pick`. The goal here is to have all of the `fixup` and `squash` commits beside the commit which they modify, but kept un-squashed for easy debugging/bisecting. + - **Example**: `git rebase --autosquash --interactive FIREFOX_115_18_0esr_BUILD1` +- [ ] Compare patch sets to ensure nothing *weird* happened during conflict resolution: + - [ ] diff of diffs: + - Do the diff between `current_patchset.diff` and `rebased_patchset.diff` with your preferred difftool and look at differences on lines that starts with + or - + - `git diff $(ESR_TAG_PREV)..$(BROWSER_BRANCH_PREV) > current_patchset.diff` + - `git diff $(ESR_TAG)..$(BROWSER_BRANCH) > rebased_patchset.diff` + - diff `current_patchset.diff` and `rebased_patchset.diff` + - If everything went correctly, the only lines which should differ should be the lines starting with `index abc123...def456` (unless the previous `base-browser` branch includes changes not included in the previous `tor-browser` branch) + - [ ] rangediff: `git range-diff $(ESR_TAG_PREV)..$(TOR_BROWSER_BRANCH_PREV) $(ESR_TAG)..HEAD` + - **Example**: `git range-dif FIREFOX_115_17_0esr_BUILD1..upstream/tor-browser-115.17.0esr-13.5-1 FIREFOX_115_18_0esr_BUILD1..HEAD` +- [ ] Open MR for the `tor-browser` rebase +- [ ] Merge +- Update and push `base-browser` branch + - [ ] Reset the new `base-browser` branch to the appropriate commit in this new `tor-browser` branch + - [ ] Push these commits to `upstream` + +### **Sign and Tag** + +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the new legacy `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser legacy build1 + ``` + - [ ] Push tag to `upstream` +- [ ] Sign/Tag HEAD of the merged `base-browser` branch: + - In **tor-browser.git**, checkout the new legacy `base-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.basebrowser legacy build1 + ``` + - [ ] Push tag to `upstream` diff --git a/.gitlab/issue_templates/Rebase Browser - Rapid.md b/.gitlab/issue_templates/Rebase Browser - Rapid.md new file mode 100644 index 0000000000000000000000000000000000000000..6b8fc0be427b3f53fcf21f041565b9c9146b0998 --- /dev/null +++ b/.gitlab/issue_templates/Rebase Browser - Rapid.md @@ -0,0 +1,276 @@ +- **NOTE**: All examples in this template reference the rebase from Firefox 129.0a1 to 130.0a1 +- **TODO**: + - Documentation step for any difficulties or noteworthy things for each rapid rebase + +<details> + <summary>Explanation of Channels</summary> + + There are unfortunately some collisions between how we and Mozilla name our release channels which can make things confusing: + - **Firefox**: + - **Nightly**: \_START and \_END tags, version in the format `$(MAJOR).$(MINOR)a1` + - **Example**: Firefox Nightly 130 was `130.0a1` + - **Note**: Nightly is 2 major versions ahead of the current Release + - **Beta**: tagged each Monday, Wednesday, and Friday until release, version in the format `$(MAJOR).$(MINOR)b$(PATCH)` + - **Example**: the first Firefox Beta 130 was `130.0b1` + - **Note**: Beta is 1 major version ahead of the current Release, should be irrelevant to us + - **Release**: tagged monthly, version in the format `$(MAJOR).$(MINOR)` or `$(MAJOR).$(MINOR).$(PATCH)` + - **Example** Firefox Release 130 was `130.0` + - **ESR**: tagged monthly, version in the format `$(ESR_MAJOR).$(ESR_MINOR).$(ESR_PATCH)esr` + - **Example**: Firefox ESR 128.1 is `128.1.0esr` + - **Tor+Mullvad Browser**: + - **Rapid**: tagged monthly, based on the latest Firefox Nightly + - **Nightly**: not tagged, built nightly from our current Alpha branch's `HEAD` + - **Alpha**: tagged monthly, based on the latest Firefox ESR + - **Stable**: tagged monthly, based on oldest supported Firefox ESR + +</details> + +<details> + <summary>Branching Overview</summary> + + Rebasing Tor Browser Rapid onto the current Firefox Nightly is a bit more confusing/involved than rebasing Tor Browser Alpha or Stable from one minor ESR to the next minor ESR. + + The general process basically involves rebasing the previous Firefox Nightly-based Tor Browser Rapid onto the latest Firefox Nightly, and then cherry-picking all of the commits from the previous Firefox ESR-based Tor Browser Alpha after that channel's `build1` tag. This process presumes that the previous Tor Browser Alpha branch is locked and receiving no more changes. + + This diagram provides a high-level view of the overall code-flow for rebasing/cherry-picking commits from Tor Browser Alpha based on Firefox 128.1.0esr and Tor Browser Rapid based on Firefox 129.0a1 onto Firefox 130.0a1: + + ```mermaid +%%{init: { 'themeVariables': {'git0': '#0072b2', 'gitBranchLabel0': '#fff', 'git1': "#e69f00", 'gitBranchLabel1': '#fff', 'git2': '#009e73', 'gitBranchLabel2': '#fff', 'git3': '#cc79a7', 'gitBranchLabel3': '#fff'}, 'gitGraph': {'mainBranchName': 'tor-browser-128.1.0esr-14.5-1'}} }%% +gitGraph: + branch tor-browser-129.0a1-15.0-2 + branch tor-browser-130.0a1-15.0-1 + branch tor-browser-130.0a1-15.0-2 + + checkout tor-browser-128.1.0esr-14.5-1 + commit id: "FIREFOX_128_1_0esr_BUILD1" + commit id: "base-browser-128.1.0esr-14.5-1-build1" + commit id: "tor-browser-128.1.0esr-14.5-1-build1" + commit id: "tor-browser-128.1.0esr-14.5-1-build2" + + checkout tor-browser-129.0a1-15.0-2 + commit id: "FIREFOX_NIGHTLY_129_END" + %% commit id: "tor-browser-129.0a1-15.0-2-build1" + + checkout tor-browser-130.0a1-15.0-1 + commit id: "FIREFOX_NIGHTLY_130_END" + + checkout tor-browser-130.0a1-15.0-2 + commit id: "FIREFOX_NIGHTLY_130_END " + + checkout tor-browser-130.0a1-15.0-1 + merge tor-browser-129.0a1-15.0-2 + + checkout tor-browser-130.0a1-15.0-2 + merge tor-browser-130.0a1-15.0-1 + + + checkout tor-browser-129.0a1-15.0-2 + commit id: "tor-browser-129.0a1-15.0-2-build1" + + checkout tor-browser-130.0a1-15.0-1 + merge tor-browser-129.0a1-15.0-2 id: "tor-browser-130.0a1-15.0-1-build1" + + checkout tor-browser-130.0a1-15.0-2 + merge tor-browser-130.0a1-15.0-1 + + checkout tor-browser-130.0a1-15.0-1 + merge tor-browser-128.1.0esr-14.5-1 + + checkout tor-browser-130.0a1-15.0-2 + merge tor-browser-130.0a1-15.0-1 + + checkout tor-browser-128.1.0esr-14.5-1 + commit id: "tor-browser-128.1.0esr-14.5-1" + + checkout tor-browser-130.0a1-15.0-1 + merge tor-browser-128.1.0esr-14.5-1 id:"tor-browser-130.0a1-15.0-1-build2" + + checkout tor-browser-130.0a1-15.0-2 + + merge tor-browser-130.0a1-15.0-1 + commit id: "tor-browser-130.0a1-15.0-2-build1" + + ``` + + In this concrete example, the rebaser performs the following steps: + - create new `tor-browser-130.0a1-15.0-1`, and `tor-browser-130.0a1-15.0-2` branches from the `FIREFOX_NIGHTLY_130_END` tag. + - these will be the rebase review branches + - onto `tor-browser-130.0a1-15.0-1`, cherry-pick the range `FIREFOX_NIGHTLY_129_END..tor-browser-129.0a1-15.0-2-build1` (i.e. the Firefox Nightly 129-based Tor Browser Rapid commits) + - this updates the previous Tor Browser Rapid onto Firefox Nightly 130 + - cherry-pick the new alpha patches onto `tor-browser-130.0a1-15.0-1` (i.e. cherry-pick `tor-browser-128.1.0esr-14.5-1-build2..origin/tor-browser-128.1.0esr-14.5-1`) + - onto `tor-browser-130.0a1-15.0-2`, rebase and autosquash the `FIREFOX_NIGHTLY_130_END..tor-browser-130.0a1-15.0-2-build1` commit range + - onto `tor-browser-130.0a1-15.0-2`, cherry-pick the remaining commit range `tor-browser-130.0a1-15.0-2-build1..origin/tor-browser-130.0a1-15.0-2` + - re-order any remaining fixup! commits to be adjacent to their parents (i.e. the same rebase command queue as one would get from `git rebase --autosquash`, but with the `fixup!` commands replaced with `pick!` commands). + - this re-organises the branch in a nicely-bisectable way, and will ensure the rebase+autosquash step for the next release *should* succeed without any additional effort + +</details> + +<details> + <summary>Explanation of Variables</summary> + +- `$(NIGHTLY_VERSION)`: the Mozilla defined nightly version, used in various places for building tor-browser tags, labels, etc + - **Example**: `130.0a1` +- `$(NIGHTLY_TAG)`: the Mozilla defined hg (Mercurial) tag associated with `$(NIGHTLY_VERSION)` + - **Example**: `FIREFOX_NIGHTLY_130_END` +- `$(NIGHTLY_TAG_PREV)`: the Mozilla defined hg (Mercurial) tag associated with the previous nightly version when rebasing (ie, the nightly version we are rebasing from) + - **Example**: `FIREFOX_NIGHTLY_129_END` +- `$(BROWSER_VERSION)`: the browser version which will first be based on the next major ESR version this *Firefox* Nightly series is leading up to + - **Example**: `15` +- `$(TOR_BROWSER_BRANCH)`: the full name of the current `tor-browser` branch based off of the Firefox Nightly channel + - **Example**: `tor-browser-130.0a1-15.0-1` +- `$(TOR_BROWSER_BRANCH_PREV)`: the full name of the previous `tor-browser` branch based off of the Firefox Nightly channel + - **Example**: `tor-browser-129.0a1-15.0-1` +</details> + +### Update Branch Protection Rules + +- [ ] In [Repository Settings](https://gitlab.torproject.org/tpo/applications/tor-browser/-/settings/repository): + - [ ] Remove previous nightly `tor-browser` branch protection rules (this will prevent pushing new changes to the branches being rebased) + - [ ] Create new `tor-browser` branch protection rule: + - **Branch**: `tor-browser-$(NIGHTLY_VERSION)-$(BROWSER_VERSION)-*` + - **Example**: `tor-browser-130.0a1-15.0-*` + - **Allowed to merge**: `Maintainers` + - **Allowed to push and merge**: `Maintainers` + - **Allowed to force push**: `false` + - ⚠️ **IMPORTANT**: If you copied and pasted from old rules, double check you didn't add spaces at the end, as GitLab will not trim them! + +### **Create New Branches** + +- [ ] Find the Firefox mercurial tag `$(NIGHTLY_TAG)` + - Go to https://hg.mozilla.org/mozilla-central/tags + - Find and inspect the commit tagged with `$(NIGHTLY_TAG)` + - Tags are in yellow in the Mercurial web UI + - Find the equivalent commit in https://github.com/mozilla/gecko-dev/commits/master + - **Notice**: GitHub sorts commits by time, you might want to use `git log gecko-dev/master` locally, instead + - Using the differential revision link is useful to quickly find the git commit + - Sign/Tag the `gecko-dev` commit: `git tag -as $(NIGHTLY_TAG) $(GIT_HASH) -m "Hg tag $(NIGHTLY_TAG)"` +- [ ] Create two new rapid `tor-browser` branches from Firefox mercurial tag + - Branch name in the form: `tor-browser-$(NIGHTLY_VERSION)-$(BROWSER_VERSION)-${BRANCH_NUM}` + - **Example**: `tor-browser-130.0a1-15.0-1` and `tor-browser-130.0a1-15.0-2` +- [ ] Push new `tor-browser` branches and the `firefox` tag to `upstream` + +### **Rebase previous `-2` rapid branch's HEAD onto current `-1` rapid branch** + +- **Desired outcome**: + - An easy to review branch with the previous rapid branch rebased onto the latest Firefox Nighty tag + - It must be possible to run `git range-diff` between the previous `-2` and the new branch + - We want to see only the effects of the rebase + - No autosquash should happen at this point + - **Expected difficulties**: + - Conflicts with upstream developments + - Sometimes it will be hard to keep a feature working. It's fine to drop it, and create an issue to restore it after a deeper investigation. +- [ ] Checkout a new local branch for the first part of the `-1` rebase + - **Example**: `git checkout -b rapid-rebase-part1 origin/tor-browser-130.0a1-15.0-1` +- [ ] Firefox Nightly-based `tor-browser` rebase: + - [ ] cherry-pick previous Tor Browser Rapid `-2` branch to new `-1` rebase branch + - **Example**: `git cherry-pick FIREFOX_NIGHTLY_129_END..origin/tor-browser-129.0a1-15.0-2` +- [ ] Rebase Verification: + - [ ] Clean range-diff between the previous rapid branch and current rebase branch + - **Example**: + ```bash + git range-diff FIREFOX_NIGHTLY_129_END..origin/tor-browser-129.0a1-15.0-2 FIREFOX_NIGHTLY_130_END..rapid-rebase-part1 + ``` + - [ ] Optional: clean diff of diffs between previous rapid branch and current rebase branch + - **Example**: + ```bash + git diff FIREFOX_NIGHTLY_129_END origin/tor-browser-129.0a1-15.0-2 > 129.diff + git diff FIREFOX_NIGHTLY_130_END HEAD > 130.diff + # A two-column diff tool is suggested rather than plain-diff, e.g., meld on Linux. + meld 129.diff 130.diff + ``` + - **Note**: Only differences should be due to resolving merge conflicts with upstream changes from Firefox Nightly +- [ ] Open MR +- [ ] Merge +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the `-1` rapid `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser rapid build1 + ``` + - [ ] Push tag to `upstream` + +### **Port new alpha patches to `-1`** + +- **Desired outcome**: + - The previous release-cycle's new alpha patches cherry-picked to the end of the current nightly + - It must be possible to run `git range-diff ESR-build1..ESR NIGHTLY-build1..` + - **Expected difficulties**: + - Conflicts with upstream developments (similar to the previous part) + - The range might contain cherry-picked upstream commits, which will result in empty commits: it's fine to skip them + - **Note**: The Tor Browser Alpha branch should be closed at this point and not receiving any more MRs +- [ ] Checkout a new local branch for the second part of the `-1` rebase + - **Example**: `git checkout -b rapid-rebase-part2 origin/tor-browser-130.0a1-15.0-1` +- [ ] Cherry-pick the new `tor-browser` alpha commits (i.e. the new dangling commits which did not appear in the previous Tor Browser Alpha release): + - **Example** `git cherry-pick tor-browser-128.1.0esr-14.5-1-build1..origin/tor-browser-128.1.0esr-14.5-1` +- [ ] Rebase Verification + - [ ] Clean range-diff between the alpha patch set ranges + - **Example**: + ```bash + git range-diff tor-browser-128.1.0esr-14.5-1-build1..origin/tor-browser-128.1.0esr-14.5-1 origin/tor-browser-130.0a1-15.0-1..HEAD + ``` + - [ ] Clean diff of diffs between the alpha patch set ranges + - **Example**: + ```bash + git diff tor-browser-128.1.0esr-14.5-1-build1 origin/tor-browser-128.1.0esr-14.5-1 > 128.1.0esr.diff + git diff origin/tor-browser-130.0a1-15.0-1 HEAD > 130.diff + # A two-column diff tool is suggested rather than plain-diff, e.g., meld on Linux. + meld 128.1.0esr.diff 130.diff + ``` + - **Note**: Only differences should be due to resolving merge conflicts with upstream changes from Firefox Nightly +- [ ] Open MR +- [ ] Merge +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the `-1` rapid `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser rapid build2 + ``` + - [ ] Push tag to `upstream` + +### **Squash and Reorder tor-browser `-1` branch to new `-2` branch** +- **Desired outcome**: + - The rapid branch from the previous step prepared for the next nightly + - **Rationale**: + - We squash a lot of commits. We want to keep them a little bit longer rather than squashing them immediately for troubleshooting and documentation purposes. + - Doing this as a separate pass helps to separate errors due to upstream changes from errors due to processes created by our workflow. + - **Expected difficulties**: + - our patches aren't disjoint, therefore we might have conflicts when shuffling them around. +- [ ] Checkout a new local branch for the `-2` rebase, aligned to -1-build1 + - **Example**: `git checkout -b rapid-rebase-part3 tor-browser-130.0a1-15.0-1-build1` +- [ ] Rebase with autosquash. This step should be trivial and not involve any conflicts. + - **Example**: `git rebase -i --autosquash FIREFOX_NIGHTLY_130_END` +- [ ] Cherry-pick the remaining commits + - **Example**: `git cherry-pick tor-browser-130.0a1-15.0-1-build1..upstream/tor-browser-130.0a1-15.0-1` +- [ ] Create a branch for self-reviewing purposes, or take note of the current commit hash somewhere + - **Example**: `git branch rapid-rebase-part3-review` + - You do not need to publish this, and you can delete it at the end of the process (`git branch -D rapid-rebase-part3-review`) + - When you are a reviewer, it might be useful to repeat these steps locally. They should not involve mental overhead (and PieroV has a script to automate this) +- [ ] Rebase and reorder commits (i.e. replace `fixup `, `fixup -C ` and `squash ` with `pick ` commands) + - Notice the space at the end, to avoid replacing `fixup!` with `pick!` in the commit subject, even though git will probably not care of such changes +- [ ] Rebase Verification + - [ ] Clean range-diff between the temporary review branch and the final branch + - **Example**: + ```bash + git range-diff FIREFOX_NIGHTLY_130_END..rapid-rebase-part3-review FIREFOX_NIGHTLY_130_END..rapid-rebase-part3 + ``` + - If you are the reviewer, it should be trivial to create such a branch on your own, as no shuffling is involved + - [ ] Clean diff of diffs between rapid branches + - **Example**: + ```bash + git diff FIREFOX_NIGHTLY_130_END tor-browser-130.0a1-15.0-1-build2 > 130-1.diff + git diff FIREFOX_NIGHTLY_130_END HEAD > 130-2.diff + ``` + - [ ] Understandable range-diff (i.e. `fixup!` patches are distributed from end of branch next to their parent) + - **Example**: + ```bash + git range-diff FIREFOX_NIGHTLY_130_END..tor-browser-130.0a1-15.0-1-build2 FIREFOX_NIGHTLY_130_END..HEAD + ``` +- [ ] Open MR +- [ ] Merge +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the `-2` rapid `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser rapid build1 + ``` + - [ ] Push tag to `upstream` diff --git a/.gitlab/issue_templates/Rebase Browser - Stable.md b/.gitlab/issue_templates/Rebase Browser - Stable.md new file mode 100644 index 0000000000000000000000000000000000000000..6cc5251dc6dd7244e36a81026807ef3fecfcddeb --- /dev/null +++ b/.gitlab/issue_templates/Rebase Browser - Stable.md @@ -0,0 +1,115 @@ +**NOTE:** All examples in this template reference the rebase from 102.7.0esr to 102.8.0esr + +<details> + <summary>Explanation of Variables</summary> + +- `$(ESR_VERSION)`: the Mozilla defined ESR version, used in various places for building tor-browser tags, labels, etc + - **Example**: `102.8.0` +- `$(ESR_TAG)`: the Mozilla defined hg (Mercurial) tag associated with `$(ESR_VERSION)` + - **Example**: `FIREFOX_102_8_0esr_RELEASE` +- `$(ESR_TAG_PREV)`: the Mozilla defined hg (Mercurial) tag associated with the previous ESR version when rebasing (ie, the ESR version we are rebasing from) + - **Example**: `FIREFOX_102_7_0esr_BUILD1` +- `$(BROWSER_MAJOR)`: the browser major version + - **Example**: `12` +- `$(BROWSER_MINOR)`: the browser minor version + - **Example**: either `0` or `5`; Alpha's is always `(Stable + 5) % 10` +- `$(BASE_BROWSER_BRANCH)`: the full name of the current `base-browser` branch + - **Example**: `base-browser-102.8.0esr-12.0-1` +- `$(BASE_BROWSER_BRANCH_PREV)`: the full name of the previous `base-browser` branch + - **Example**: `base-browser-102.7.0esr-12.0-1` +- `$(TOR_BROWSER_BRANCH)`: the full name of the current `tor-browser` branch + - **Example**: `tor-browser-102.8.0esr-12.0-1` +- `$(TOR_BROWSER_BRANCH_PREV)`: the full name of the previous `tor-browser` branch + - **Example**: `tor-browser-102.7.0esr-12.0-1` +</details> + +### **Bookkeeping** + +- [ ] Link this issue to the appropriate [Release Prep](https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep) issue. + +### Update Branch Protection Rules + +- [ ] In [Repository Settings](https://gitlab.torproject.org/tpo/applications/tor-browser/-/settings/repository): + - [ ] Remove previous stable `base-browser` and `tor-browser` branch protection rules (this will prevent pushing new changes to the branches being rebased) + - [ ] Create new `base-browser` and `tor-browser` branch protection rule: + - **Branch**: `*-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1*` + - **Example**: `*-102.8.0esr-12.0-1*` + - **Allowed to merge**: `Maintainers` + - **Allowed to push and merge**: `Maintainers` + - **Allowed to force push**: `false` + +### **Identify the Firefox Tagged Commit and Create New Branches** + +- [ ] Find the Firefox mercurial tag here: https://hg.mozilla.org/releases/mozilla-esr102/tags + - **Example**: `FIREFOX_102_8_0esr_BUILD1` +- [ ] Find the analogous `gecko-dev` commit: https://github.com/mozilla/gecko-dev + - **Tip**: Search for unique string (like the Differential Revision ID) found in the mercurial commit in the `gecko-dev/esr102` branch to find the equivalent commit + - **Example**: `3a3a96c9eedd02296d6652dd50314fccbc5c4845` +- [ ] Sign and Tag `gecko-dev` commit + - Sign/Tag `gecko-dev` commit : + - **Tag**: `$(ESR_TAG)` + - **Message**: `Hg tag $(ESR_TAG)` +- [ ] Create new stable `base-browser` branch from tag + - Branch name in the form: `base-browser-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1` + - **Example**: `base-browser-102.8.0esr-12.0-1` +- [ ] Create new stable `tor-browser` branch from + - Branch name in the form: `tor-browser-$(ESR_VERSION)esr-$(BROWSER_MAJOR).$(BROWSER_MINOR)-1` + - **Example**: `tor-browser-102.8.0esr-12.0-1` +- [ ] Push new `base-browser` branch to `upstream` +- [ ] Push new `tor-browser` branch to `upstream` +- [ ] Push new `$(ESR_TAG)` to `upstream` + +### **Rebase tor-browser** + +- [ ] Checkout a new local branch for the `tor-browser` rebase + - **Example**: `git branch tor-browser-rebase FIREFOX_102_8_0esr_BUILD1` +- [ ] **(Optional)** `base-browser` rebase + - **NOTE** This step may be skipped if the `HEAD` of the previous `base-browser` branch is a `-buildN` tag + - [ ] Cherry-pick the previous `base-browser` commits up to `base-browser`'s `buildN` tag onto new `base-browser` rebase branch + - **Example**: `git cherry-pick FIREFOX_102_7_0esr_BUILD1..base-browser-102.7.0esr-12.0-1-build1` + - [ ] Rebase and autosquash these cherry-picked commits + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_BUILD1 HEAD` + - [ ] Cherry-pick remainder of patches after the `buildN` tag + - **Example**: `git cherry-pick base-browser-102.7.0esr-12.0-1-build1..upstream/base-browser-102.7.0esr-12.0-1` +- [ ] `tor-browser` rebase + - [ ] Note the current git hash of `HEAD` for `tor-browser` rebase+autosquash step: `git rev-parse HEAD` + - [ ] Cherry-pick the appropriate previous `tor-browser` branch's commit range up to the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick base-browser-102.7.0esr-12.0-1-build1..tor-browser-102.7.0esr-12.0-1-build1` + - **Example (if separate base-browser rebase was skipped)**: `git cherry-pick FIREFOX_102_7_0esr_BUILD1..tor-browser-102.7.0esr-12.0-1-build1` + - [ ] Rebase and autosquash these newly cherry-picked commits: `git rebase --autosquash --interactive $(PREV_HEAD)` + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_RELEASE` + - [ ] Cherry-pick remainder of patches after the last `tor-browser` `buildN` tag + - **Example**: `git cherry-pick tor-browser-102.7.0esr-12.0-1-build1..upstream/tor-browser-102.7.0esr-12.0-1` + - [ ] Rebase and autosquash again, this time replacing all `fixup` and `squash` commands with `pick`. The goal here is to have all of the `fixup` and `squash` commits beside the commit which they modify, but kept un-squashed for easy debugging/bisecting. + - **Example**: `git rebase --autosquash --interactive FIREFOX_102_8_0esr_RELEASE` +- [ ] Compare patch sets to ensure nothing *weird* happened during conflict resolution: + - [ ] diff of diffs: + - Do the diff between `current_patchset.diff` and `rebased_patchset.diff` with your preferred difftool and look at differences on lines that starts with + or - + - `git diff $(ESR_TAG_PREV)..$(BROWSER_BRANCH_PREV) > current_patchset.diff` + - `git diff $(ESR_TAG)..$(BROWSER_BRANCH) > rebased_patchset.diff` + - diff `current_patchset.diff` and `rebased_patchset.diff` + - If everything went correctly, the only lines which should differ should be the lines starting with `index abc123...def456` (unless the previous `base-browser` branch includes changes not included in the previous `tor-browser` branch) + - [ ] rangediff: `git range-diff $(ESR_TAG_PREV)..$(TOR_BROWSER_BRANCH_PREV) $(ESR_TAG)..HEAD` + - **Example**: `git range-dif FIREFOX_102_7_0esr_BUILD1..upstream/tor-browser-102.7.0esr-12.0-1 FIREFOX_102_8_0esr_BUILD1..HEAD` +- [ ] Open MR for the `tor-browser` rebase +- [ ] Merge +- Update and push `base-browser` branch + - [ ] Reset the new `base-browser` branch to the appropriate commit in this new `tor-browser` branch + - [ ] Push these commits to `upstream` + +### **Sign and Tag** + +- [ ] Sign/Tag `HEAD` of the merged `tor-browser` branch: + - In **tor-browser.git**, checkout the new stable `tor-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.torbrowser stable build1 + ``` + - [ ] Push tag to `upstream` +- [ ] Sign/Tag HEAD of the merged `base-browser` branch: + - In **tor-browser.git**, checkout the new stable `base-browser` branch + - In **tor-browser-build.git**, run signing script: + ```bash + ./tools/browser/sign-tag.basebrowser stable build1 + ``` + - [ ] Push tag to `upstream` diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md new file mode 100644 index 0000000000000000000000000000000000000000..6ce85a4864be808be37b6d688f99d64fa30a0e50 --- /dev/null +++ b/.gitlab/issue_templates/bug.md @@ -0,0 +1,32 @@ +<!-- +* Use this issue template for reporting a new bug. +--> + +### Summary +**Summarize the bug encountered concisely.** + + +### Steps to reproduce: +**How one can reproduce the issue - this is very important.** + +1. Step 1 +2. Step 2 +3. ... + +### What is the current bug behavior? +**What actually happens.** + + +### What is the expected behavior? +**What you want to see instead** + + + +### Environment +**Which operating system are you using? For example: Debian GNU/Linux 10.1, Windows 10, Ubuntu Xenial, FreeBSD 12.2, etc.** +**Which installation method did you use? Distribution package (apt, pkg, homebrew), from source tarball, from Git, etc.** + +### Relevant logs and/or screenshots + + +/label ~bug diff --git a/.gitlab/merge_request_templates/Rebase.md b/.gitlab/merge_request_templates/Rebase.md new file mode 100644 index 0000000000000000000000000000000000000000..8d188d42fe961e5a0e3838180b4079d87c3efae6 --- /dev/null +++ b/.gitlab/merge_request_templates/Rebase.md @@ -0,0 +1,23 @@ +## Merge Info + +<!-- Bookkeeping information for release management --> + +### Rebase Issue +- tor-browser#xxxxx +- mullvad-browser#xxxxx + +### Release Prep Issue +- tor-browser-build#xxxxx + +### Issue Tracking +- [ ] Link rebase issue with appropriate [Release Prep issue](https://gitlab.torproject.org/groups/tpo/applications/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep&first_page_size=20) for changelog generation + +### Review + +#### Request Reviewer + +- [ ] Request review from a release engineer: boklm, dan, ma1, morgan, pierov + +#### Change Description + +<!-- Any interesting notes about the rebase and an overview of what the reviewer should expect from the diff of diffs and range-diff --> diff --git a/.gitlab/merge_request_templates/default.md b/.gitlab/merge_request_templates/default.md new file mode 100644 index 0000000000000000000000000000000000000000..743d5e1fb43eb2771a3fc60b18858f5d257d2654 --- /dev/null +++ b/.gitlab/merge_request_templates/default.md @@ -0,0 +1,85 @@ +## Merge Info + +<!-- Bookkeeping information for release management --> + +### Issues + +#### Resolves +- tor-browser#xxxxx +- mullvad-browser#xxxxx +- tor-browser-build#xxxxx + +#### Related + +- tor-browser#xxxxx +- mullvad-browser#xxxxx +- tor-browser-build#xxxxx + +### Merging + +<!-- This block tells the merger where commits need to be merged and future code archaeologists where commits were *supposed* to be merged --> + +#### Target Branches + +- [ ] **`tor-browser`** - `!fixups` to `tor-browser`-specific commits, new features, security backports +- [ ] **`base-browser`** *and* **`mullvad-browser`** - `!fixups` to `base-browser`-specific commits, new features to be shared with `mullvad-browser`, and security backports + - ⚠️ **IMPORTANT**: Please list the `base-browser`-specific commits which need to be cherry-picked to the `base-browser` and `mullvad-browser` branches here + +#### Target Channels + +- [ ] **Alpha**: esr128-14.5 +- [ ] **Stable**: esr128-14.0 +- [ ] **Legacy**: esr115-13.5 + +### Backporting + +#### Timeline +- [ ] **No Backport (preferred)**: patchset for the next major stable +- [ ] **Immediate**: patchset needed as soon as possible (fixes CVEs, 0-days, etc) +- [ ] **Next Minor Stable Release**: patchset that needs to be verified in nightly before backport +- [ ] **Eventually**: patchset that needs to be verified in alpha before backport + +#### (Optional) Justification +- [ ] **Security update**: patchset contains a security fix (be sure to select the correct item in _Timeline_) +- [ ] **Censorship event**: patchset enables censorship circumvention +- [ ] **Critical bug-fix**: patchset fixes a bug in core-functionality +- [ ] **Consistency**: patchset which would make development easier if it were in both the alpha and release branches; developer tools, build system changes, etc +- [ ] **Sponsor required**: patchset required for sponsor +- [ ] **Localization**: typos and other localization changes that should be also in the release branch +- [ ] **Other**: please explain + +### Issue Tracking +- [ ] Link resolved issues with appropriate [Release Prep issue](https://gitlab.torproject.org/groups/tpo/applications/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Release%20Prep&first_page_size=20) for changelog generation + +### Review + +#### Request Reviewer + +- [ ] Request review from an applications developer depending on modified system: + - **NOTE**: if the MR modifies multiple areas, please `/cc` all the relevant reviewers (since Gitlab only allows 1 reviewer) + - **accessibility** : henry + - **android** : clairehurst, dan + - **build system** : boklm + - **extensions** : ma1 + - **firefox internals (XUL/JS/XPCOM)** : jwilde, ma1 + - **fonts** : pierov + - **frontend (implementation)** : henry + - **frontend (review)** : donuts, morgan + - **localization** : henry, pierov + - **macOS** : clairehurst, dan + - **nightly builds** : boklm + - **rebases/release-prep** : dan, ma1, pierov, morgan + - **security** : jwilde, ma1 + - **signing** : boklm, morgan + - **updater** : pierov + - **windows** : jwilde, morgan + - **misc/other** : pierov, morgan + +#### Change Description + +<!-- Whatever context the reviewer needs to effectively review the patchset; if the patch includes UX updates be sure to include screenshots/video of how any new behaviour --> + + +#### How Tested + +<!-- Description of steps taken to verify the change --> diff --git a/.prettierignore b/.prettierignore index e96648f699b45ae7298d4917299d184b463ecfaf..ecce23aafb6b5b612e5ff8f71602ea1a1b0af298 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1529,3 +1529,9 @@ tools/browsertime/package-lock.json tools/ts/error_list.json try_task_config.json xpcom/idl-parser/xpidl/fixtures/xpctest.d.json + +browser/app/profile/001-base-profile.js +browser/app/profile/000-tor-browser.js +mobile/android/app/000-tor-browser-android.js +toolkit/content/pt_config.json +toolkit/components/lox/lox_wasm.jsm diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..116a82f263482bf7a4d8b72a5198f2b25d2982c9 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +The tor-browser repository is based on Mozilla Firefox. + +See the following wiki links for more information: + ++ [Repository Overview](https://gitlab.torproject.org/tpo/applications/team/-/wikis/Development-Information/Tor-Browser/Tor-Browser-Repository-Overview) ++ [Contributing](https://gitlab.torproject.org/tpo/applications/team/-/wikis/Development-Information/Tor-Browser/Contributing-to-Tor-Browser) diff --git a/README.txt b/README.txt deleted file mode 100644 index fe37f6a66beed913b66df259e9bf51ab804ed7a5..0000000000000000000000000000000000000000 --- a/README.txt +++ /dev/null @@ -1,21 +0,0 @@ -An explanation of the Firefox Source Code Directory Structure and links to -project pages with documentation can be found at: - - https://firefox-source-docs.mozilla.org/contributing/directory_structure.html - -For information on how to build Firefox from the source code and create the patch see: - - https://firefox-source-docs.mozilla.org/contributing/contribution_quickref.html - -If you have a question about developing Firefox, and can't find the solution -on https://firefox-source-docs.mozilla.org/, you can try asking your question on Matrix at chat.mozilla.org in `Introduction` (https://chat.mozilla.org/#/room/#introduction:mozilla.org) channel. - - -Nightly development builds can be downloaded from: - - https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/ - - or - - https://www.mozilla.org/firefox/channel/desktop/#nightly - -Keep in mind that nightly builds, which are used by Firefox developers for -testing, may be buggy. diff --git a/browser/actors/CryptoSafetyChild.sys.mjs b/browser/actors/CryptoSafetyChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..49a0ecc2f60cefea7b9f7e6c4dabd68de5635e7e --- /dev/null +++ b/browser/actors/CryptoSafetyChild.sys.mjs @@ -0,0 +1,49 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* Copyright (c) 2020, The Tor Project, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + setTimeout: "resource://gre/modules/Timer.sys.mjs", +}); + +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "isCryptoSafetyEnabled", + "security.cryptoSafety", + true // Defaults to true. +); + +export class CryptoSafetyChild extends JSWindowActorChild { + handleEvent(event) { + if ( + !lazy.isCryptoSafetyEnabled || + // Ignore non-HTTP addresses. + // We do this before reading the host property since this is not available + // for about: pages. + !this.document.documentURIObject.schemeIs("http") || + // Ignore onion addresses. + this.document.documentURIObject.host.endsWith(".onion") || + (event.type !== "copy" && event.type !== "cut") + ) { + return; + } + + // We send a message to the parent to inspect the clipboard content. + // NOTE: We wait until next cycle to allow the event to propagate and fill + // the clipboard before being read. + // NOTE: Using navigator.clipboard.readText fails with Wayland. See + // tor-browser#42702. + lazy.setTimeout(() => { + this.sendAsyncMessage("CryptoSafety:CopiedText", { + host: this.document.documentURIObject.host, + }); + }); + } +} diff --git a/browser/actors/CryptoSafetyParent.sys.mjs b/browser/actors/CryptoSafetyParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..c266cc8d4ece735af495747498bd305ea99a6b33 --- /dev/null +++ b/browser/actors/CryptoSafetyParent.sys.mjs @@ -0,0 +1,130 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* Copyright (c) 2020, The Tor Project, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", + Bech32Decode: "resource://gre/modules/Bech32Decode.sys.mjs", +}); + +ChromeUtils.defineLazyGetter(lazy, "CryptoStrings", function () { + return new Localization(["toolkit/global/tor-browser.ftl"]); +}); + +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "isCryptoSafetyEnabled", + "security.cryptoSafety", + true // Defaults to true. +); + +function looksLikeCryptoAddress(s) { + // P2PKH and P2SH addresses + // https://stackoverflow.com/a/24205650 + const bitcoinAddr = /^[13][a-km-zA-HJ-NP-Z1-9]{25,39}$/; + if (bitcoinAddr.test(s)) { + return true; + } + + // Bech32 addresses + if (lazy.Bech32Decode(s) !== null) { + return true; + } + + // regular addresses + const etherAddr = /^0x[a-fA-F0-9]{40}$/; + if (etherAddr.test(s)) { + return true; + } + + // t-addresses + // https://www.reddit.com/r/zec/comments/8mxj6x/simple_regex_to_validate_a_zcash_tz_address/dzr62p5/ + const zcashAddr = /^t1[a-zA-Z0-9]{33}$/; + if (zcashAddr.test(s)) { + return true; + } + + // Standard, Integrated, and 256-bit Integrated addresses + // https://monero.stackexchange.com/a/10627 + const moneroAddr = + /^4(?:[0-9AB]|[1-9A-HJ-NP-Za-km-z]{12}(?:[1-9A-HJ-NP-Za-km-z]{30})?)[1-9A-HJ-NP-Za-km-z]{93}$/; + if (moneroAddr.test(s)) { + return true; + } + + return false; +} + +export class CryptoSafetyParent extends JSWindowActorParent { + async receiveMessage(aMessage) { + if ( + !lazy.isCryptoSafetyEnabled || + aMessage.name !== "CryptoSafety:CopiedText" + ) { + return; + } + + // Read the global clipboard. We assume the contents come from the HTTP + // page specified in `aMessage.data.host`. + const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor("text/plain"); + Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard); + let data = {}; + trans.getTransferData("text/plain", data); + data = data?.value.QueryInterface(Ci.nsISupportsString).data; + + let address = data?.replace(/\s+/g, ""); + + if (!address || !looksLikeCryptoAddress(address)) { + return; + } + + if (address.length > 32) { + address = `${address.substring(0, 32)}…`; + } + + const [titleText, bodyText, reloadText, dismissText] = + await lazy.CryptoStrings.formatValues([ + { id: "crypto-safety-prompt-title" }, + { + id: "crypto-safety-prompt-body", + args: { address, host: aMessage.data.host }, + }, + { id: "crypto-safety-prompt-reload-button" }, + { id: "crypto-safety-prompt-dismiss-button" }, + ]); + + const buttonPressed = Services.prompt.confirmEx( + this.browsingContext.topChromeWindow, + titleText, + bodyText, + Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 + + Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_1, + reloadText, + dismissText, + null, + null, + {} + ); + + if (buttonPressed === 0) { + const { browsingContext } = this.manager; + const browser = browsingContext.embedderElement; + if (browser) { + lazy.TorDomainIsolator.newCircuitForBrowser( + browser.ownerGlobal.gBrowser.selectedBrowser + ); + } + } + } +} diff --git a/browser/actors/RFPHelperChild.sys.mjs b/browser/actors/RFPHelperChild.sys.mjs deleted file mode 100644 index 14b17bc2dbf3273e7a629bb2610ee810a757256b..0000000000000000000000000000000000000000 --- a/browser/actors/RFPHelperChild.sys.mjs +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; - -const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing"; - -const lazy = {}; - -XPCOMUtils.defineLazyPreferenceGetter( - lazy, - "isLetterboxingEnabled", - kPrefLetterboxing, - false -); - -export class RFPHelperChild extends JSWindowActorChild { - handleEvent(event) { - if (lazy.isLetterboxingEnabled && event.type == "resize") { - this.sendAsyncMessage("Letterboxing:ContentSizeUpdated"); - } - } -} diff --git a/browser/actors/RFPHelperParent.sys.mjs b/browser/actors/RFPHelperParent.sys.mjs deleted file mode 100644 index 0e4e3e8be642117c60e9855e696f607d902a64c9..0000000000000000000000000000000000000000 --- a/browser/actors/RFPHelperParent.sys.mjs +++ /dev/null @@ -1,33 +0,0 @@ -1; /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; - -const lazy = {}; -ChromeUtils.defineESModuleGetters(lazy, { - RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", -}); - -const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing"; - -XPCOMUtils.defineLazyPreferenceGetter( - lazy, - "isLetterboxingEnabled", - kPrefLetterboxing, - false -); - -export class RFPHelperParent extends JSWindowActorParent { - receiveMessage(aMessage) { - if ( - lazy.isLetterboxingEnabled && - aMessage.name == "Letterboxing:ContentSizeUpdated" - ) { - let browser = this.browsingContext.top.embedderElement; - let window = browser.ownerGlobal; - lazy.RFPHelper.contentSizeUpdated(window); - } - } -} diff --git a/browser/actors/moz.build b/browser/actors/moz.build index 25957ca7102a56507e27844710662b3d6ca98d9c..624c41160e516fa92b676157a19ae69793c4e7c8 100644 --- a/browser/actors/moz.build +++ b/browser/actors/moz.build @@ -54,6 +54,8 @@ FINAL_TARGET_FILES.actors += [ "ContentSearchParent.sys.mjs", "ContextMenuChild.sys.mjs", "ContextMenuParent.sys.mjs", + "CryptoSafetyChild.sys.mjs", + "CryptoSafetyParent.sys.mjs", "DecoderDoctorChild.sys.mjs", "DecoderDoctorParent.sys.mjs", "DOMFullscreenChild.sys.mjs", @@ -75,8 +77,6 @@ FINAL_TARGET_FILES.actors += [ "PromptParent.sys.mjs", "RefreshBlockerChild.sys.mjs", "RefreshBlockerParent.sys.mjs", - "RFPHelperChild.sys.mjs", - "RFPHelperParent.sys.mjs", "ScreenshotsComponentChild.sys.mjs", "SearchSERPTelemetryChild.sys.mjs", "SearchSERPTelemetryParent.sys.mjs", diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index 08490ba27ca2c4d7ed7a99cf9fd45f78b0660312..b4815a9007e3f1e277eeed34c81252904633698e 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -100,11 +100,13 @@ tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME) $(objdir)/macbuild/Contents/MacOS- rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) '$(dist_dest)/Contents/MacOS' cp -RL $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns' cp -RL $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/document.icns '$(dist_dest)/Contents/Resources/document.icns' +ifndef BASE_BROWSER_UPDATE $(MKDIR) -p '$(dist_dest)/Contents/Library/LaunchServices' ifdef MOZ_UPDATER cp -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices' +endif endif $(MKDIR) -p '$(dist_dest)/Contents/Frameworks' mv '$(dist_dest)/Contents/Resources/ChannelPrefs.framework' '$(dist_dest)/Contents/Frameworks' - printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo' + printf APPLTORB > '$(dist_dest)/Contents/PkgInfo' endif diff --git a/browser/app/macbuild/Contents/Info.plist.in b/browser/app/macbuild/Contents/Info.plist.in index 73b400d58fd25ac13132f1a3fe3ea619e4f4e4f9..c503d19a250f69752028545ab9f4796389292552 100644 --- a/browser/app/macbuild/Contents/Info.plist.in +++ b/browser/app/macbuild/Contents/Info.plist.in @@ -201,7 +201,7 @@ <key>CFBundleShortVersionString</key> <string>@APP_VERSION@</string> <key>CFBundleSignature</key> - <string>MOZB</string> + <string>TORB</string> <key>CFBundleURLTypes</key> <array> <dict> diff --git a/browser/app/macbuild/Contents/MacOS-files.in b/browser/app/macbuild/Contents/MacOS-files.in index f43118ba8879a8ca9b8a52331531a0115764cead..33d8daa20782ff7bca041968afb6bb9fbb38f876 100644 --- a/browser/app/macbuild/Contents/MacOS-files.in +++ b/browser/app/macbuild/Contents/MacOS-files.in @@ -17,7 +17,6 @@ /minidump-analyzer #endif /nmhproxy -/pingsender /pk12util /ssltunnel /xpcshell diff --git a/browser/app/moz.build b/browser/app/moz.build index f41ce92556bb18b01e8a3a27fa06a690bfe98cd8..4f9a417b1d2a01e7a3d7761ad350142ff77ac0a0 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -76,7 +76,8 @@ if CONFIG["CC_TYPE"] == "clang-cl": if CONFIG["OS_ARCH"] == "WINNT": RCINCLUDE = "splash.rc" DIRS += [ - "pbproxy", + # tor-browser#41798 don't build private_browsing.exe on Windows + # "pbproxy", "winlauncher", ] USE_LIBS += [ diff --git a/browser/app/permissions b/browser/app/permissions index 1c72a96de885675a42a2b64784fd6ff8ff618eff..4a1813e72e807795d833805403532de59c81899b 100644 --- a/browser/app/permissions +++ b/browser/app/permissions @@ -6,20 +6,3 @@ # * permission is an integer between 1 and 15 # Permissions defined here will also be set for private browsing. # See PermissionManager.cpp for more... - -# UITour -# Bug 1557153: www.mozilla.org gets a special workaround in UITourChild.sys.mjs -# Bug 1837407: support.mozilla.org gets a special workaround for similar reasons. -origin uitour 1 https://www.mozilla.org -origin uitour 1 https://support.mozilla.org -origin uitour 1 about:home -origin uitour 1 about:newtab - -# XPInstall -origin install 1 https://addons.mozilla.org - -# Remote troubleshooting -origin remote-troubleshooting 1 https://support.mozilla.org - -# autoplay video/audio -origin autoplay-media 1 about:welcome diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js new file mode 100644 index 0000000000000000000000000000000000000000..cf9027fb298cfa87acd885cf710f984f8179387c --- /dev/null +++ b/browser/app/profile/000-tor-browser.js @@ -0,0 +1,153 @@ +#include 001-base-profile.js + +pref("app.update.notifyDuringDownload", true); +pref("app.update.url.manual", "https://www.torproject.org/download/languages/"); +pref("app.update.url.details", "https://www.torproject.org/download/"); +pref("app.update.badgeWaitTime", 0); +pref("app.releaseNotesURL", "about:blank"); +// disables the 'What's New?' link in the about dialog, otherwise we need to +// duplicate logic for generating the url to the blog post that is already more +// easily found in about:tor +pref("app.releaseNotesURL.aboutDialog", "about:blank"); +// point to our feedback url rather than Mozilla's +pref("app.feedback.baseURL", "https://support.torproject.org/%LOCALE%/misc/bug-or-feedback/"); + +pref("browser.shell.checkDefaultBrowser", false); + +// Proxy and proxy security +pref("network.proxy.socks", "127.0.0.1"); +pref("network.proxy.socks_port", 9150); +pref("network.proxy.socks_remote_dns", true); +pref("network.proxy.no_proxies_on", ""); // For fingerprinting and local service vulns (#10419) +pref("network.proxy.allow_hijacking_localhost", true); // Allow proxies for localhost (#31065) +pref("network.proxy.type", 1); +// localhost is already blocked by setting `network.proxy.allow_hijacking_localhost` to +// true, allowing users to explicitly block ports makes them fingerprintable; for details, see +// Bug 41317: Tor Browser leaks banned ports in network.security.ports.banned +pref("network.security.ports.banned", "", locked); +pref("network.dns.disabled", true); // This should cover the #5741 patch for DNS leaks +pref("network.http.max-persistent-connections-per-proxy", 256); +// Disable DNS over HTTPS. Set to explicitly off MODE_TRROFF = 5. +// See tor-browser#41906. +pref("network.trr.mode", 5, locked); + +// Treat .onions as secure +pref("dom.securecontext.allowlist_onions", true); + +// Disable HTTPS-Only mode for .onion domains (tor-browser#19850) +pref("dom.security.https_only_mode.upgrade_onion", false); + +// Bug 40423/41137: Disable http/3 +// We should re-enable it as soon as Tor gets UDP support +pref("network.http.http3.enable", false); + +// 0 = do not use a second connection, see all.js and #7656 +pref("network.http.connection-retry-timeout", 0); + +// Tor Browser used to be compatible with non-Tor proxies. This feature is not +// available anymore, but this legacy preference can be still used to disable +// first-party domain circuit isolation. +// In general, it should not be used. This use-case is still supported only for +// sites that break with this isolation (and even in that case, its use should +// be reduced to the strictly required time). +pref("extensions.torbutton.use_nontor_proxy", false); + +// tor-browser#43170: Disable user-agent spoofing in HTTP header +pref("privacy.resistFingerprinting.spoofOsInUserAgentHeader", false); + +// Browser home page: +pref("browser.startup.homepage", "about:tor"); + +// tor-browser#40701: Add new download warning +pref("browser.download.showTorWarning", true); + + +// Tor connection setting preferences. + +pref("torbrowser.settings.quickstart.enabled", false); +pref("torbrowser.settings.bridges.enabled", false); +// TorBridgeSource. Initially TorBridgeSource.Invalid = -1. +pref("torbrowser.settings.bridges.source", -1); +pref("torbrowser.settings.bridges.lox_id", ""); +// obfs4|meek-azure|snowflake|etc. +pref("torbrowser.settings.bridges.builtin_type", ""); +// torbrowser.settings.bridges.bridge_strings.0 +// torbrowser.settings.bridges.bridge_strings.1 +// etc hold the bridge lines. +pref("torbrowser.settings.proxy.enabled", false); +// TorProxyType. Initially TorProxyType.Invalid = -1. +pref("torbrowser.settings.proxy.type", -1); +pref("torbrowser.settings.proxy.address", ""); +pref("torbrowser.settings.proxy.port", 0); +pref("torbrowser.settings.proxy.username", ""); +pref("torbrowser.settings.proxy.password", ""); +pref("torbrowser.settings.firewall.enabled", false); +// comma-delimited list of port numbers. +pref("torbrowser.settings.firewall.allowed_ports", ""); + + +// This pref specifies an ad-hoc "version" for various pref update hacks we need to do +pref("extensions.torbutton.pref_fixup_version", 0); + +// Formerly tor-launcher defaults + +pref("extensions.torlauncher.start_tor", true); +pref("extensions.torlauncher.prompt_at_startup", true); + +pref("extensions.torlauncher.max_tor_log_entries", 1000); + +// By default, Tor Launcher configures a TCP listener for the Tor +// control port, as defined by control_host and control_port. +// Set control_port_use_ipc to true to use an IPC object (e.g., a Unix +// domain socket) instead. You may also modify control_ipc_path to +// override the default IPC object location. If a relative path is used, +// it is handled like torrc_path (see below). +pref("extensions.torlauncher.control_host", "127.0.0.1"); +pref("extensions.torlauncher.control_port", 9151); +pref("extensions.torlauncher.control_port_use_ipc", false); +pref("extensions.torlauncher.control_ipc_path", ""); + +// By default, Tor Launcher configures a TCP listener for the Tor +// SOCKS port. The host is taken from the network.proxy.socks pref and +// the port is taken from the network.proxy.socks_port pref. +// Set socks_port_use_ipc to true to use an IPC object (e.g., a Unix +// domain socket) instead. You may also modify socks_ipc_path to +// override the default IPC object location. If a relative path is used, +// it is handled like torrc_path (see below). +// Modify socks_port_flags to use a different set of SocksPort flags (but be +// careful). +pref("extensions.torlauncher.socks_port_use_ipc", false); +pref("extensions.torlauncher.socks_ipc_path", ""); +pref("extensions.torlauncher.socks_port_flags", "ExtendedErrors IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"); + +// The tor_path is relative to the application directory. On Linux and +// Windows this is the Browser/ directory that contains the firefox +// executables, and on Mac OS it is the TorBrowser.app directory. +pref("extensions.torlauncher.tor_path", ""); + +// The torrc_path and tordatadir_path are relative to the data directory, +// which is TorBrowser-Data/ if it exists as a sibling of the application +// directory. If TorBrowser-Data/ does not exist, these paths are relative +// to the TorBrowser/ directory within the application directory. +pref("extensions.torlauncher.torrc_path", ""); +pref("extensions.torlauncher.tordatadir_path", ""); + +// BridgeDB-related preferences (used for Moat). +pref("extensions.torlauncher.bridgedb_front", "www.phpmyadmin.net"); +pref("extensions.torlauncher.bridgedb_reflector", "https://1723079976.rsc.cdn77.org"); +pref("extensions.torlauncher.moat_service", "https://bridges.torproject.org/moat"); + +// Log levels +pref("browser.tor_provider.log_level", "Warn"); +pref("browser.tor_provider.cp_log_level", "Warn"); +pref("lox.log_level", "Warn"); +pref("torbrowser.bootstrap.log_level", "Info"); +pref("browser.torsettings.log_level", "Warn"); +pref("browser.torMoat.loglevel", "Warn"); +pref("browser.tordomainisolator.loglevel", "Warn"); +pref("browser.torcircuitpanel.loglevel", "Log"); +pref("browser.tor_android.log_level", "Info"); +pref("browser.dragdropfilter.log_level", "Warn"); +pref("browser.onionAuthPrompt.loglevel", "Warn"); +pref("browser.onionalias.log_level", "Warn"); +pref("browser.torRequestWatch.log_level", "Warn"); diff --git a/browser/app/profile/001-base-profile.js b/browser/app/profile/001-base-profile.js new file mode 100644 index 0000000000000000000000000000000000000000..33bd1d0a5d457f7eb567b982d7a2275f63ac888b --- /dev/null +++ b/browser/app/profile/001-base-profile.js @@ -0,0 +1,1015 @@ +// Preferences to harden Firefox's security and privacy +// Do not edit this file. + +// Use the OS locale by default (tor-browser#17400) +pref("intl.locale.requested", ""); + +// Home page and new tab is blank rather than Firefox Home (Activity Stream). +// tor-browser#31575 and tor-browser#30662 +pref("browser.startup.homepage", "about:blank"); +pref("browser.newtabpage.enabled", false); + +// tor-browser#43164: Prevent search-bar from being auto-hidden when not used for awhile +// This preference is locked so that the browser itself can never set an actual +// value that would trigger the migration. +pref("browser.search.widget.lastUsed", "", locked); + +// Disable initial homepage notifications +pref("browser.search.update", false); +pref("startup.homepage_welcome_url", ""); +pref("startup.homepage_welcome_url.additional", ""); + +// Disable Firefox Welcome Dialog +pref("browser.aboutwelcome.enabled", false); + +#if MOZ_UPDATE_CHANNEL == release +// tor-browser#42640: Disable Firefox Flame button due to unknown interactions with New Identity +pref("browser.privatebrowsing.resetPBM.enabled", false, locked); +#endif + +// Bug 41668: allow users to apply updates. This is set also in firefox.js for +// all platforms, except for Windows. As explained on firefox.js, Firefox uses a +// per-installation preference on Windows. However, we patch this behavior, and +// we set this preference also for Windows. +pref("app.update.auto", true); + +// Try to nag a bit more about updates: Pop up a restart dialog an hour after the initial dialog +pref("app.update.promptWaitTime", 3600); + +#ifndef XP_MACOSX +// Disable staged updates on platforms other than macOS. +// Staged updates do not work on Windows due to #18292. +// Also, on Windows and Linux any changes that are made to the browser profile +// or Tor data after an update is staged will be lost. +pref("app.update.staging.enabled", false); +#endif + +pref("browser.startup.homepage_override.buildID", "20100101"); + +// Disable the "Refresh" prompt that is displayed for stale profiles. +pref("browser.disableResetPrompt", true); + +// Disk activity: Disable Browsing History Storage +pref("browser.privatebrowsing.autostart", true); +pref("browser.cache.disk.enable", false); +pref("permissions.memory_only", true); +pref("security.nocertdb", true); +pref("media.aboutwebrtc.hist.enabled", false); + +// Disk Activity + +// Disable auto-downloading to ~/Downloads and other download tweaks to minimize +// disk leaks (tor-browser#42050). +pref("browser.download.useDownloadDir", false); +pref("browser.download.always_ask_before_handling_new_types", true); +pref("browser.download.manager.addToRecentDocs", false); +pref("browser.download.start_downloads_in_tmp_dir", true); +// tor-browser#42147: Always delete temporary files, also on macOS (this pref is +// already true for other platforms). +// Also, this always happens in PBM. If not in PBM, requires +// browser.download.start_downloads_in_tmp_dir to be true too. +pref("browser.helperApps.deleteTempFileOnExit", true); + +// Prevent download stuffing / DOS (tor-browser#41764) +pref("browser.download.enable_spam_prevention", true); + +// Misc privacy: Disk +pref("signon.rememberSignons", false); +pref("browser.formfill.enable", false); +pref("signon.formlessCapture.enabled", false); // Added with tor-browser#41496 +pref("signon.autofillForms", false); +pref("extensions.formautofill.available", ""); +pref("extensions.formautofill.addresses.enabled", false); +pref("extensions.formautofill.creditCards.enabled", false); +// Do not store extra data (form, scrollbar positions, cookies, POST data) for +// the session restore functionality. +pref("browser.sessionstore.privacy_level", 2); +// Use the in-memory media cache and increase its maximum size (#29120) +pref("browser.privatebrowsing.forceMediaMemoryCache", true); +pref("media.memory_cache_max_size", 65536); +// tor-browser#41065: lie about the available quota. +// This value is in KiB, and will be divided by 5. Currently: 50GiB, to be +// coherent with Firefox's usual value. However, this might be too much for live +// systems. +// This will be the limit also after granting the persistent storage permission, +// but we are not interested in it, since we support only PBM. +// We can come back to it, and hardcode the two spaced differently, if we ever +// think we need it. +pref("dom.quotaManager.temporaryStorage.fixedLimit", 52428800); +// Disable restore in case of crash (tor-browser#41503) +// This should not be needed in PBM, but we added it anyway like other options. +pref("browser.sessionstore.resume_from_crash", false); +// Disable capturing thumbnails (tor-browser#41595) +// Also not needed in PBM at the moment. +pref("browser.pagethumbnails.capturing_disabled", true); +// tor-browser#41988: Remove page titles from window titles to prevent possible +// disk leaks, e.g., in system logs. +// For example, it happened that GNOME shell logged the window name that caused +// JS errors/unexpected conditions for unrelated issues. +// TODO: commented out for now because of UX concerns, to be reconsidered in 14.5 +// pref("privacy.exposeContentTitleInWindow", false); +// pref("privacy.exposeContentTitleInWindow.pbm", false); + +// tor-browser#42054: Opt-out from any built-in backup system, even though +// local, as it might be a violation of our standalone mode. +// Users can still opt-in if they wish. +pref("browser.backup.enabled", false); +pref("browser.backup.scheduled.enabled", false); + +// Empty clipboard content from private windows on exit (tor-browser#42154) +pref("browser.privatebrowsing.preserveClipboard", false); + +// tor-browser#42611: Do not include the URL of the image, when copying it. +// Also, do not save clipboard in history/cloud. +pref("clipboard.imageAsFile.enabled", false); +pref("clipboard.copyPrivateDataToClipboardCloudOrHistory", false); + +// Enable HTTPS-Only mode (tor-browser#19850) +pref("dom.security.https_only_mode", true); +// The previous pref automatically sets this to true (see StaticPrefList.yaml), +// but set it anyway only as a defense-in-depth. +pref("dom.security.https_only_mode_pbm", true); +// tor-browser#43197, defense in depth if ever https-only got disabled +pref("dom.security.https_first_add_exception_on_failiure", false); + +// tor-browser#22320: Hide referer when coming from a .onion address +// We enable this here (rather than in Tor Browser) in case users of other +// base-browser derived browsers configure it to use a system Tor daemon +// to visit onion services. +pref("network.http.referer.hideOnionSource", true); + +// Require Safe Negotiation ( https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/27719 ) +// Blocks connections to servers that don't support RFC 5746 [2] as they're potentially vulnerable to a +// MiTM attack [3]. A server without RFC 5746 can be safe from the attack if it disables renegotiations +// but the problem is that the browser can't know that. Setting this pref to true is the only way for the +// browser to ensure there will be no unsafe renegotiations on the channel between the browser and the server +// [STATS] SSL Labs (July 2021) reports over 99% of top sites have secure renegotiation [4] +// [1] https://wiki.mozilla.org/Security:Renegotiation +// [2] https://datatracker.ietf.org/doc/html/rfc5746 +// [3] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3555 +// [4] https://www.ssllabs.com/ssl-pulse/ +pref("security.ssl.require_safe_negotiation", true); + +// mullvad-browser#361: Disable TLS cyphersuites using SHA1 for signing (ECDSA) +// see https://bugzilla.mozilla.org/show_bug.cgi?id=1600437 +pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", false); +pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", false); +// lock those disabled by https://bugzilla.mozilla.org/show_bug.cgi?id=1036765 +pref("security.ssl3.dhe_rsa_aes_128_sha", false, locked); +pref("security.ssl3.dhe_rsa_aes_256_sha", false, locked); + +// Wrapping a static pref to lock it and prevent changing. +// See tor-browser#40565. +pref("security.tls.version.enable-deprecated", false, locked); + +// Misc privacy: Remote +pref("browser.send_pings", false); +// Space separated list of URLs that are allowed to send objects (instead of +// only strings) through webchannels. The default for Firefox is some Mozilla +// domains. +pref("webchannel.allowObject.urlWhitelist", ""); +pref("geo.enabled", false); +pref("geo.provider.network.url", ""); +pref("geo.provider.ms-windows-location", false); +pref("geo.provider.use_corelocation", false); +pref("geo.provider.use_gpsd", false); +pref("geo.provider.use_geoclue", false); +pref("browser.search.suggest.enabled", false); +pref("browser.search.suggest.enabled.private", false); +pref("browser.urlbar.suggest.searches", false); +pref("browser.urlbar.suggest.quicksuggest.nonsponsored", false); +pref("browser.urlbar.suggest.quicksuggest.sponsored", false); +// tor-browser#41576: Do not suggest weather and addons. +pref("browser.urlbar.suggest.addons", false); +pref("browser.urlbar.addons.featureGate", false); +pref("browser.urlbar.suggest.weather", false); +pref("browser.urlbar.weather.featureGate", false); +// tor-browser#42886: Disable trending results. +pref("browser.urlbar.suggest.trending", false); +pref("browser.urlbar.trending.featureGate", false); +// tor-browser#42792: Explicitly turn off Pocket suggestions in the URL bar. +pref("browser.urlbar.pocket.featureGate", false); +// tor-browser#41691: Hide "Firefox Suggest" in the UI +pref("browser.urlbar.groupLabels.enabled", false); +pref("browser.safebrowsing.malware.enabled", false); +pref("browser.safebrowsing.phishing.enabled", false); +pref("browser.safebrowsing.downloads.enabled", false); +pref("browser.safebrowsing.downloads.remote.enabled", false); +pref("browser.safebrowsing.blockedURIs.enabled", false); +pref("browser.safebrowsing.downloads.remote.url", ""); +pref("browser.safebrowsing.provider.google.updateURL", ""); +pref("browser.safebrowsing.provider.google.gethashURL", ""); +pref("browser.safebrowsing.provider.google4.updateURL", ""); +pref("browser.safebrowsing.provider.google4.gethashURL", ""); +pref("browser.safebrowsing.provider.mozilla.updateURL", ""); +pref("browser.safebrowsing.provider.mozilla.gethashURL", ""); +pref("datareporting.healthreport.uploadEnabled", false); +pref("datareporting.policy.dataSubmissionEnabled", false); +// tor-browser#42735: Disable recent search suggestions +pref("browser.urlbar.recentsearches.featureGate", false); +pref("browser.urlbar.suggest.recentsearches", false); + +// Make sure Unified Telemetry is really disabled, see: #18738. +pref("toolkit.telemetry.unified", false); +// This needs to be locked, or nightly builds will automatically lock it to true +pref("toolkit.telemetry.enabled", false, locked); +pref("toolkit.telemetry.server", "data:,"); +pref("toolkit.telemetry.archive.enabled", false); +pref("toolkit.telemetry.newProfilePing.enabled", false); // Added in tor-browser#41496 +pref("toolkit.telemetry.shutdownPingSender.enabled", false); // Added in tor-browser#41496 +pref("toolkit.telemetry.firstShutdownPing.enabled", false); // Added in tor-browser#41496 +pref("toolkit.telemetry.updatePing.enabled", false); // Make sure updater telemetry is disabled; see #25909. +pref("toolkit.telemetry.bhrPing.enabled", false); +pref("toolkit.telemetry.coverage.opt-out", true); +pref("toolkit.coverage.opt-out", true); +pref("toolkit.coverage.endpoint.base", ""); +pref("browser.tabs.crashReporting.sendReport", false); +pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false); +// Added in tor-browser#41496 even though false by default +pref("browser.crashReports.unsubmittedCheck.enabled", false); +// Disable checkbox in about:neterror that controls +// security.xfocsp.errorReporting.automatic. See tor-browser#42653. +pref("security.xfocsp.errorReporting.enabled", false); +// Added in tor-browser#41496 even though it shuld be already always disabled +// since we disable MOZ_CRASHREPORTER. +pref("breakpad.reportURL", "data:"); +#ifdef XP_WIN +// Defense-in-depth: ensure that the Windows default browser agent will +// not ping Mozilla if it is somehow present (we omit it at build time). +pref("default-browser-agent.enabled", false); +#endif +// Disable sync by default +pref("identity.fxaccounts.enabled", false); +// Blank the sync URL as a defense in depth (added with tor-browser#41496) +pref("identity.sync.tokenserver.uri", ""); +// Never sync with other browsers +pref("services.sync.engine.addons", false); +pref("services.sync.engine.addresses", false); +pref("services.sync.engine.bookmarks", false); +pref("services.sync.engine.creditcards", false); +pref("services.sync.engine.history", false); +pref("services.sync.engine.passwords", false); +pref("services.sync.engine.prefs", false); +pref("services.sync.engine.tabs", false); +pref("extensions.getAddons.cache.enabled", false); // https://blog.mozilla.org/addons/how-to-opt-out-of-add-on-metadata-updates/ +pref("privacy.donottrackheader.enabled", false); // (mullvad-browser#17) +// Make sure there is no Tracking Protection active in Tor Browser, see: #17898. +pref("privacy.trackingprotection.enabled", false); +pref("privacy.trackingprotection.pbmode.enabled", false); +pref("privacy.trackingprotection.emailtracking.pbmode.enabled", false); +pref("privacy.trackingprotection.annotate_channels", false); +pref("privacy.trackingprotection.cryptomining.enabled", false); +pref("privacy.trackingprotection.fingerprinting.enabled", false); +pref("privacy.trackingprotection.socialtracking.enabled", false); +pref("privacy.socialtracking.block_cookies.enabled", false); +pref("privacy.annotate_channels.strict_list.enabled", false); +// tor-browser#43178: for defense-in-depth, avoid remote overrides to FPP. +// Notice that it should not apply to RFP anyway... +pref("privacy.fingerprintingProtection.remoteOverrides.enabled", false); + +// Disable the Pocket extension (Bug #18886 and #31602) +pref("extensions.pocket.enabled", false); + +// Disable Privacy-Preserving-Attribution (Bug #42687) +pref("dom.private-attribution.submission.enabled", false); + +// Custom extensions preferences tor-browser#41581 +pref("extensions.hideNoScript", true); +pref("extensions.hideUnifiedWhenEmpty", true); + +// Disable activity stream/"Recommended by Pocket" in about:home (Bug #41029) +pref("browser.newtabpage.activity-stream.discoverystream.enabled", false); +pref("browser.newtabpage.activity-stream.feeds.section.topstories", false); +pref("browser.newtabpage.activity-stream.showSponsored", false); +pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false); +pref("browser.newtabpage.activity-stream.default.sites", ""); +// Activity Stream telemetry +pref("browser.newtabpage.activity-stream.feeds.telemetry", false); +pref("browser.newtabpage.activity-stream.telemetry", false); + +// tor-browser#40788: disable AS's calls to home. +// Notice that null is between quotes because it is a JSON string. +// Keep checked firefox.js to see if new entries are added. +pref("browser.newtabpage.activity-stream.asrouter.providers.cfr", "null"); +pref("browser.newtabpage.activity-stream.asrouter.providers.message-groups", "null"); +pref("browser.newtabpage.activity-stream.asrouter.providers.messaging-experiments", "null"); + +// Disable fetching asrouter.ftl and related console errors (tor-browser#40763). +pref("browser.newtabpage.activity-stream.asrouter.useRemoteL10n", false); + +// tor-browser#42054: make sure search result telemetry is disabled. +pref("browser.search.serpEventTelemetryCategorization.enabled", false); + +// tor-browser#42872, #42555: Disable translations. +// Translation have a bad UX in 128 (and with our config). Maybe we will +// re-enable after auditing and fixing the UX. +pref("browser.translations.enable", false); + +// tor-browser#41945 - disable automatic cookie banners dismissal until +// we're sure it does not causes fingerprinting risks or other issues. +pref("cookiebanners.service.mode", 0); +pref("cookiebanners.service.mode.privateBrowsing", 0); +pref("cookiebanners.ui.desktop.enabled", false); + +// Disable moreFromMozilla pane in the preferences/settings (tor-browser#41292). +pref("browser.preferences.moreFromMozilla", false); + +// Disable webcompat reporter +pref("extensions.webcompat-reporter.enabled", false); + +// Disable Content Analysis SDK (tor-browser#42364) +pref("browser.contentanalysis.enabled", false); +pref("browser.contentanalysis.default_result", 0); + +// Disable contentRelevancy component (which itself is gated on Nimbus) (tor-browser#42867) +pref("toolkit.contentRelevancy.enabled", false); +pref("toolkit.contentRelevancy.ingestEnabled", false); +pref("toolkit.contentRelevancy.log", false); + +pref("browser.search.region", "US"); // Disable GeoIP search lookups (#16254) +// Disable use of WiFi location information +pref("browser.region.network.scan", false); +pref("browser.region.network.url", ""); +pref("browser.region.local-geocoding", false); +// Bug 40083: Make sure Region.sys.mjs fetching is disabled +pref("browser.region.update.enabled", false); + +// Don't load Mozilla domains in a separate privileged tab process +pref("browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", false); +pref("browser.tabs.remote.separatedMozillaDomains", ""); + +// Avoid DNS lookups on search terms +pref("browser.urlbar.dnsResolveSingleWordsAfterSearch", 0); + +// Disable about:newtab and "first run" experiments +pref("messaging-system.rsexperimentloader.enabled", false); +// true means that you are *not* opting out. See its usage in various file. +pref("app.shield.optoutstudies.enabled", false); +// Disable Normandy/Shield +pref("app.normandy.enabled", false); +pref("app.normandy.api_url", ""); + +// [SETTING] General>Browsing>Recommend extensions as you browse (Bug #40700) +pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false); // disable CFR [FF67+] + +// [SETTING] General>Browsing>Recommend features as you browse (Bug #40700) +pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", false); // disable CFR [FF67+] + +// Clear the list of trusted recursive resolver services +pref("network.trr.default_provider_uri", ""); + +// Disable the /etc/hosts parser +// If true, entries from /etc/hosts will be excluded **from TRR results**. +// Vice-versa, if it is false, TRR will override any /etc/hosts customization. +pref("network.trr.exclude-etc-hosts", false); + +// Disable crlite +pref("security.remote_settings.crlite_filters.enabled", false); +pref("security.pki.crlite_mode", 0); + +// Disable website password breach alerts +pref("signon.management.page.breach-alerts.enabled", false); +// tor-browser#42814: Opt out from Firefox relay by default. +// Firefox would normally assign disabled when a user has been presented the +// opportunity to use the service and opted out (see firefox.js). +pref("signon.firefoxRelay.feature", "disabled"); + +// Disable remote "password recipes". They are a way to improve the UX of the +// password manager by havinc specific heuristics for some sites. +// It needs remote settings and in general we disable the password manager. +// More information about this feature at +// https://bugzilla.mozilla.org/show_bug.cgi?id=1119454 +pref("signon.recipes.remoteRecipes.enabled", false); + +// Disable ServiceWorkers by default. They do not work in PBM in any case. +// See https://bugzilla.mozilla.org/show_bug.cgi?id=1320796 +pref("dom.serviceWorkers.enabled", false); +// Push notifications use an online Mozilla service and a persistent ID stored +// in dom.push.userAgentID, so disable them by default. +// See also https://support.mozilla.org/kb/push-notifications-firefox +pref("dom.push.enabled", false); +// As a defense in depth measure, also set the push server URL to empty. +// See tor-browser#18801. +pref("dom.push.serverURL", ""); + +// Fingerprinting +// tor-browser#41797: For release builds, lock RFP +// tor-browser#42125: Set (and lock in release) also exempted domains. +#if MOZ_UPDATE_CHANNEL == release +pref("privacy.resistFingerprinting", true, locked); +pref("privacy.resistFingerprinting.exemptedDomains", "", locked); +// tor-browser#42125: Some misleading guides suggest to set this to false, but +// the result would be that the canvas is completely white +// (see StaticPrefList.yaml), so lock it to true. +// Might be removed (MozBug 1670447). +pref("privacy.resistFingerprinting.randomDataOnCanvasExtract", true, locked); +#else +pref("privacy.resistFingerprinting", true); +pref("privacy.resistFingerprinting.exemptedDomains", ""); +#endif +// tor-browser#18603: failIfMajorPerformanceCaveat is an optional attribute that +// can be used when creating a WebGL context if the browser detects that the +// performance would be low. That could be used to fingerpting users with a not +// good graphics card, so disable it (actually, defense in depth, it is already +// disabled by default from Firefox). +pref("webgl.disable-fail-if-major-performance-caveat", true); +// tor-browser#16404: disable until we investigate it further (#22333) +pref("webgl.enable-webgl2", false); +pref("browser.link.open_newwindow.restriction", 0); // Bug 9881: Open popups in new tabs (to avoid fullscreen popups) +// tor-browser#42767: Disable offscreen canvas until verified it is not fingerprintable +pref("gfx.offscreencanvas.enabled", false); +// Prevent scripts from moving and resizing open windows +pref("dom.disable_window_move_resize", true); +// Set video VP9 to 0 for everyone (bug 22548) +pref("media.benchmark.vp9.threshold", 0); +pref("privacy.resistFingerprinting.block_mozAddonManager", true); // Bug 26114 +pref("dom.webmidi.enabled", false); // Bug 41398: Disable Web MIDI API +// tor-browser#42043: Stop reporting device IDs (and spoof their number without +// RFP, RFP already reports 1 audioinput and 1 videoinput, but still has +// randomized IDs when this pref is true). +// Defense-in-depth (already the default value) from Firefox 119 or 120. +pref("media.devices.enumerate.legacy.enabled", false); +// Bug 10286: Always disable Touch API. +// We might need to deepen this topic, see tor-browser#42069. +pref("dom.w3c_touch_events.enabled", 0); +#ifndef ANDROID +// Bug 42138: Disable touch-based overscroll UX +pref("apz.overscroll.enabled", false); +#endif +pref("dom.vr.enabled", false); // Bug 21607: Disable WebVR for now +pref("security.webauth.webauthn", false); // Bug 26614: Disable Web Authentication API for now +// Disable SAB, no matter if the sites are cross-origin isolated. +pref("dom.postMessage.sharedArrayBuffer.withCOOP_COEP", false); +// Disable intermediate preloading (Bug 30682) +pref("security.remote_settings.intermediates.enabled", false); +// Bug 2874: Block Components.interfaces from content +pref("dom.use_components_shim", false); +// Enable letterboxing +pref("privacy.resistFingerprinting.letterboxing", true); +// tor-browser#41917: Center letterboxed area vertically +pref("privacy.resistFingerprinting.letterboxing.vcenter", true); +// tor-browser#41917: Letterboxing gradient background +pref("privacy.resistFingerprinting.letterboxing.gradient", true); +// tor-browser#41918: Should we reuse last window sizes if letterboxing is enabled +pref("privacy.resistFingerprinting.letterboxing.rememberSize", false); +// tor-browser#41695: How many warnings we show if user closes them without restoring the window size +pref("privacy.resistFingerprinting.resizeWarnings", 3); +// tor-browser#43402: Avoid a resize from the skeleton to the newwin size. +// Should be fixed in ESR-140 with Bug 1448423. +pref("browser.startup.blankWindow", false); +// Enforce Network Information API as disabled +pref("dom.netinfo.enabled", false); +pref("network.http.referer.defaultPolicy", 2); // Bug 32948: Make referer behavior consistent regardless of private browing mode status +pref("network.http.referer.defaultPolicy.pbmode", 2); +pref("network.http.referer.XOriginTrimmingPolicy", 2); // Bug 17228: Force trim referer to scheme+host+port in cross-origin requests +// Bug 40463: Disable Windows SSO +pref("network.http.windows-sso.enabled", false, locked); +// Bug 43165: Disable Microsoft SSO on macOS +pref("network.http.microsoft-entra-sso.enabled", false); +pref("network.microsoft-sso-authority-list", ""); +// tor-browser#40424 +pref("pdfjs.enableScripting", false); +#if MOZ_UPDATE_CHANNEL == release +// tor-browser#42255: pdfjs.disabled used to be part of RFP until Bug 1838415; lock pref to false in stable +pref("pdfjs.disabled", false, locked); +#endif +// Bug 40057: Ensure system colors are not used for CSS4 colors +pref("browser.display.use_system_colors", false); +// tor-browser#43366: do not use system accent color in inputs. +// See also https://bugzilla.mozilla.org/show_bug.cgi?id=1861362. +pref("widget.non-native-theme.use-theme-accent", false); +// tor-browser#43236: Disable vsync on Wayland to prevent refresh rate leaks. +pref("widget.wayland.vsync.enabled", false); + +// tor-browser#41943: defense-in-depth, but do not lock anymore (enabled in Firefox 119, http://bugzil.la/1851162) +pref("javascript.options.spectre.disable_for_isolated_content", false); + +// Third party stuff +pref("privacy.firstparty.isolate", true); // Always enforce first party isolation +// tor-browser#40123 and #40308: Disable for now until audit +pref("privacy.partition.network_state", false); +// Only accept cookies from the originating site (block third party cookies) +pref("network.cookie.cookieBehavior", 1); +pref("network.cookie.cookieBehavior.pbmode", 1); +pref("network.predictor.enabled", false); // Temporarily disabled. See https://bugs.torproject.org/16633 +pref("network.predictor.enable-prefetch", false); +pref("network.http.speculative-parallel-limit", 0); +pref("browser.places.speculativeConnect.enabled", false); +pref("network.prefetch-next", false); +pref("browser.urlbar.speculativeConnect.enabled", false); +// Bug 40220: Make sure tracker cookie purging is disabled. +// It depends on Firefox's tracking protection, which we currently do not enable +// See also tor-browser#30939. +pref("privacy.purge_trackers.enabled", false); +// Do not allow cross-origin sub-resources to open HTTP authentication +// credentials dialogs. Hardens against potential credentials phishing. +pref("network.auth.subresource-http-auth-allow", 1); + +// tor-browser#42684: Disable network prefetch +pref("network.dns.disablePrefetch", true); +pref("network.dns.disablePrefetchFromHTTPS", true); +pref("dom.prefetch_dns_for_anchor_http_document", false); +pref("dom.prefetch_dns_for_anchor_https_document", false); + +pref("network.protocol-handler.external-default", false); +pref("network.protocol-handler.external.mailto", false); +pref("network.protocol-handler.external.news", false); +pref("network.protocol-handler.external.nntp", false); +pref("network.protocol-handler.external.snews", false); +pref("network.protocol-handler.warn-external.mailto", true); +pref("network.protocol-handler.warn-external.news", true); +pref("network.protocol-handler.warn-external.nntp", true); +pref("network.protocol-handler.warn-external.snews", true); +#ifdef XP_WIN + pref("network.protocol-handler.external.ms-windows-store", false); + pref("network.protocol-handler.warn-external.ms-windows-store", true); +#endif +pref("network.proxy.allow_bypass", false, locked); // #40682 +// Bug 40548: Disable proxy-bypass +pref("network.proxy.failover_direct", false, locked); +// Lock to 'true', which is already the firefox default, to prevent users +// from making themselves fingerprintable by disabling. This pref +// alters content load order in a page. See tor-browser#24686 +pref("network.http.tailing.enabled", true, locked); + +// tor-browser#23044: Make sure we don't have any GIO supported protocols +// (defense in depth measure). +// As of Firefox 118 (Bug 1843763), upstream does not add any protocol by +// default, but setting it to blank seems a good idea (tor-browser#42054). +pref("network.gio.supported-protocols", ""); +pref("media.peerconnection.enabled", false); // Disable WebRTC interfaces +// Mullvad Browser enables WebRTC by default, meaning that there the following prefs +// are first-line defense, rather than "in depth" (mullvad-browser#40) +// tor-browser#41667 - Defense in depth: use mDNS to avoid local IP leaks on Android too if user enables WebRTC +pref("media.peerconnection.ice.obfuscate_host_addresses", true); +// tor-browser#41671 - Defense in depth: connect using TURN only, to avoid IP leaks if user enables WebRTC +pref("media.peerconnection.ice.relay_only", true); +// tor-browser#42029 - Defense-in-depth: disable non-proxied UDP WebRTC +pref("media.peerconnection.ice.default_address_only", true); +pref("media.peerconnection.ice.no_host", true); +pref("media.peerconnection.ice.proxy_only_if_behind_proxy", true); + +// Disables media devices but only if `media.peerconnection.enabled` is set to +// `false` as well. (see bug 16328 for this defense-in-depth measure) +pref("media.navigator.enabled", false); +// GMPs (Gecko Media Plugins, https://wiki.mozilla.org/GeckoMediaPlugins) +// We make sure they don't show up on the Add-on panel and confuse users. +// And the external update/donwload server must not get pinged. We apply a +// clever solution for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=769716. +// See tor-browser#15910. +pref("media.gmp-provider.enabled", false); +pref("media.gmp-manager.url.override", "data:text/plain,"); +// Since ESR52 it is not enough anymore to block pinging the GMP update/download +// server. There is a local fallback that must be blocked now as well. See: +// https://bugzilla.mozilla.org/show_bug.cgi?id=1267495. +pref("media.gmp-manager.updateEnabled", false); +// Mozilla is relying on preferences to make sure no DRM blob is downloaded and +// run. Even though those prefs should be set correctly by specifying +// --disable-eme (which we do), we disable all of them here as well for defense +// in depth (see bug 16285 for more details). +pref("browser.eme.ui.enabled", false); +pref("media.gmp-widevinecdm.visible", false); +pref("media.gmp-widevinecdm.enabled", false); +pref("media.eme.enabled", false); +pref("media.mediadrm-widevinecdm.visible", false); +// The in-browser debugger for debugging chrome code is not coping with our +// restrictive DNS look-up policy. We use "127.0.0.1" instead of "localhost" as +// a workaround. See bug 16523 for more details. +pref("devtools.debugger.chrome-debugging-host", "127.0.0.1"); +// Disable using UNC paths (bug 26424 and Mozilla's bug 1413868) +pref("network.file.disable_unc_paths", true); +// Enhance our treatment of file:// to avoid proxy bypasses (see Mozilla's bug +// 1412081 and CVE-2017-16541) +pref("network.file.path_blacklist", "/net"); + +// Security slider +pref("svg.disabled", false); +pref("mathml.disabled", false); + +// Bug 40408 +pref("svg.context-properties.content.allowed-domains", ""); + +// Network and performance +pref("security.ssl.enable_false_start", true); +// tor-browser#18945 +pref("network.manage-offline-status", false); +// No need to leak things to Mozilla, see bug 21790 and tor-browser#40322 +pref("network.captive-portal-service.enabled", false); +pref("network.connectivity-service.enabled", false); +pref("captivedetect.canonicalURL", ""); + +#ifdef XP_WIN +// tor-browser#41683: Disable the network process on Windows +// Mozilla already disables the network process for HTTP. +// With this preference, we completely disable it, because we found that it +// breaks stuff with mingw. See also tor-browser#41489. +pref("network.process.enabled", false); +#endif + +// Extension support +pref("extensions.autoDisableScopes", 0); +// Only load extensions from the application and user profile. +// Do not load from the user directory (AddonManager.SCOPE_USER=2, which is +// shared between profiles, e.g., %appdata%\Mozilla\Extensions\ on Windows, or +// ~/.mozilla/extensions on Linux for Firefox), and do not load from system +// directories/the Windows registry (AddonManager.SCOPE_SYSTEM=8). +// More information: https://archive.ph/DYjAM +pref("extensions.enabledScopes", 5); // AddonManager.SCOPE_PROFILE=1 | AddonManager.SCOPE_APPLICATION=4 +// We don't know what extensions Mozilla is advertising to our users and we +// don't want to have some random Google Analytics script running either on the +// about:addons page, see bug 22073, 22900 and 31601. +pref("extensions.getAddons.showPane", false); +pref("extensions.htmlaboutaddons.recommendations.enabled", false); +// Disable personalized Extension Recommendations in about:addons and +// addons.mozilla.org +pref("browser.discovery.enabled", false); +// tor-browser#26114: Allow NoScript to work on addons.mozilla.org and other Mozilla sites. +// Revisited and confirmed in tor-browser#41445. +pref("extensions.webextensions.restrictedDomains", ""); +// Don't give Mozilla-recommended third-party extensions special privileges. +pref("extensions.postDownloadThirdPartyPrompt", false); +// tor-browser#41701: Reporting an extension does not work. The request goes to +// Mozilla and is always rejected anyway (HTTP 400). +pref("extensions.abuseReport.enabled", false); +// We are already providing the languages we support in multi-lingual packages. +// Therefore, do not allow download of additional language packs. They are not a +// privacy/security threat, we are disabling them for UX reasons. See bug 41377. +pref("intl.multilingual.downloadEnabled", false); + +// Enforce certificate pinning, see: https://bugs.torproject.org/16206 +pref("security.cert_pinning.enforcement_level", 2); + +// Don't load OS client certs. +pref("security.osclientcerts.autoload", false); + +// Don't allow MitM via enterprise roots, see bug 30681 +pref("security.enterprise_roots.enabled", false); + +// Don't ping Mozilla for MitM detection, see bug 32321 +pref("security.certerrors.mitm.priming.enabled", false); + +// Don't automatically enable enterprise roots, see bug 40166 +pref("security.certerrors.mitm.auto_enable_enterprise_roots", false); + +// Disable share menus on Mac and Windows tor-browser#41117 +pref("browser.menu.share_url.allow", false, locked); + +// Disable special URL bar behaviors +pref("browser.urlbar.suggest.topsites", false); +pref("browser.urlbar.quicksuggest.enabled", false); +pref("browser.urlbar.richSuggestions.featureGate", false); +pref("browser.urlbar.yelp.featureGate", false); +pref("browser.urlbar.mdn.featureGate", false); + +// tor-browser#41884: Do not start a search when clicking on the new tab button +// with the middle mouse button (to prevent searching for anything you might +// have selected or already in your clipboard). +pref("browser.tabs.searchclipboardfor.middleclick", false); + +// tor-browser#41417: do not allow live reload until we switch to Fluent and +// stop using .textContent. +// Even after that, it might be a good idea to keep it off, as it is not handled +// very well, and it might give a window during which websites could fingerprint +// the change (see tor-browser#42349 and tor-browser#42771). +pref("intl.multilingual.liveReload", false); + +// Enable URL query stripping to protect against cross-site tracking (tor-browser#41092) +pref("privacy.query_stripping.enabled", true); +pref("privacy.query_stripping.enabled.pbmode", true); +pref("privacy.query_stripping.strip_on_share.enabled", true); + +// Ensure global privacy control headers are consistent in private browsing and +// non-private browsing (tor-browser#42777). +pref("privacy.globalprivacycontrol.enabled", true); +pref("privacy.globalprivacycontrol.pbmode.enabled", true); + +// Disable platform text recognition functionality (tor-browser#42057) +pref("dom.text-recognition.enabled", false); + +// Log levels +pref("browser.new_identity.log_level", "Info"); + +#ifdef XP_WIN +pref("browser.taskbar.lists.enabled", false); +pref("browser.taskbar.lists.frequent.enabled", false); +pref("browser.taskbar.lists.tasks.enabled", false); +pref("browser.taskbar.lists.recent.enabled", false); + +// tor-browser#41806: Prevent the browser from adding a new Private Browsing +// start menu item automatically +pref("browser.privacySegmentation.createdShortcut", true); + +// Do not re-open the browser automatically after reboots when "Restart apps" is +// enabled (tor-browser#41503) +pref("toolkit.winRegisterApplicationRestart", false); +// tor-browser#43051: Hide the checkbox to open the browser automatically on +// Windows startup. +pref("browser.startup.windowsLaunchOnLogin.enabled", false); +#endif + +#ifdef ANDROID +// tor-browser#43023 Force use of only standard emoji font +// (not actually stopping samsung emoji font detection, but defense in depth and a step towards normalization) +pref("font.name-list.emoji", "Noto Color Emoji"); +#endif + +// If we are bundling fonts, whitelist those bundled fonts, and restrict system fonts to a selection. + +#ifdef MOZ_BUNDLED_FONTS + +// Bug 40342: Always use bundled fonts +pref("gfx.bundled-fonts.activate", 1); + +#ifdef XP_MACOSX +pref("font.system.whitelist", "AppleGothic, Apple Color Emoji, Arial, Arial Black, Arial Narrow, Courier, Courier New, Geneva, Georgia, Heiti TC, Helvetica, Helvetica Neue, Hiragino Kaku Gothic ProN, Kailasa, Lucida Grande, Menlo, Monaco, PingFang HK, PingFang SC, PingFang TC, Songti SC, Songti TC, Tahoma, Thonburi, Times, Times New Roman, Verdana, STIX Two Math, Noto Sans Adlam, Noto Sans Armenian, Noto Sans Balinese, Noto Sans Bamum, Noto Sans Bassa Vah, Noto Sans Batak, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Buhid, Noto Sans Canadian Aboriginal, Noto Sans Chakma, Noto Sans Cham, Noto Sans Cherokee, Noto Sans Coptic, Noto Sans Deseret, Noto Sans Devanagari, Noto Sans Elbasan, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Grantha, Noto Sans Gujarati, Noto Sans Gunjala Gondi, Noto Sans Gurmukhi, Noto Sans Hanifi Rohingya, Noto Sans Hanunoo, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Javanese, Noto Sans Kayah Li, Noto Sans Khojki, Noto Sans Khudawadi, Noto Sans Lao, Noto Sans Lepcha, Noto Sans Limbu, Noto Sans Lisu, Noto Sans Mahajani, Noto Sans Malayalam, Noto Sans Mandaic, Noto Sans Masaram Gondi, Noto Sans Medefaidrin, Noto Sans Meetei Mayek, Noto Sans Mende Kikakui, Noto Sans Miao, Noto Sans Modi, Noto Sans Mongolian, Noto Sans Mro, Noto Sans Myanmar, Noto Sans Multani, Noto Sans Newa, Noto Sans New Tai Lue, Noto Sans NKo, Noto Sans Ol Chiki, Noto Sans Oriya, Noto Sans Osage, Noto Sans Osmanya, Noto Sans Pahawh Hmong, Noto Sans Pau Cin Hau, Noto Sans Rejang, Noto Sans Runic, Noto Sans Samaritan, Noto Sans Saurashtra, Noto Sans Sharada, Noto Sans Shavian, Noto Sans Sinhala, Noto Sans Sora Sompeng, Noto Sans Soyombo, Noto Sans Sundanese, Noto Sans Syloti Nagri, Noto Sans Symbols 2, Noto Sans Symbols, Noto Sans Syriac, Noto Sans Tagalog, Noto Sans Tagbanwa, Noto Sans Tai Le, Noto Sans Tai Tham, Noto Sans Tai Viet, Noto Sans Takri, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tifinagh Adrar, Noto Sans Tifinagh Agraw Imazighen, Noto Sans Tifinagh Ahaggar, Noto Sans Tifinagh Air, Noto Sans Tifinagh APT, Noto Sans Tifinagh Azawagh, Noto Sans Tifinagh Ghat, Noto Sans Tifinagh Hawad, Noto Sans Tifinagh, Noto Sans Tifinagh Rhissa Ixa, Noto Sans Tifinagh SIL, Noto Sans Tifinagh Tawellemmet, Noto Sans Tirhuta, Noto Sans Vai, Noto Sans Wancho, Noto Sans Warang Citi, Noto Sans Yi, Noto Sans Zanabazar Square, Noto Serif Armenian, Noto Serif Balinese, Noto Serif Bengali, Noto Serif Devanagari, Noto Serif Dogra, Noto Serif Ethiopic, Noto Serif Georgian, Noto Serif Grantha, Noto Serif Gujarati, Noto Serif Gurmukhi, Noto Serif Hebrew, Noto Serif Kannada, Noto Serif Khmer, Noto Serif Khojki, Noto Serif Lao, Noto Serif Malayalam, Noto Serif Myanmar, Noto Serif NP Hmong, Noto Serif Sinhala, Noto Serif Tamil, Noto Serif Telugu, Noto Serif Tibetan, Noto Serif Yezidi"); + +// Armenian +pref("font.name-list.serif.x-armn", "Noto Serif Armenian, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-armn", "Noto Sans Armenian, Helvetica, Arial"); +pref("font.name-list.monospace.x-armn", "Noto Sans Armenian, Menlo, Courier New"); +// Bengali +pref("font.name-list.serif.x-beng", "Noto Serif Bengali, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-beng", "Noto Sans Bengali, Helvetica, Arial"); +pref("font.name-list.monospace.x-beng", "Noto Sans Bengali, Menlo, Courier New"); +// Canadian Aboriginal +pref("font.name-list.serif.x-cans", "Noto Serif Canadian Aboriginal, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-cans", "Noto Sans Canadian Aboriginal, Helvetica, Arial"); +pref("font.name-list.monospace.x-cans", "Noto Sans Canadian Aboriginal, Menlo, Courier New"); +// ChineseCN +pref("font.name-list.serif.zh-CN", "Songti SC, Times, Times New Roman"); +pref("font.name-list.sans-serif.zh-CN", "PingFang SC, Helvetica, Arial"); +pref("font.name-list.monospace.zh-CN", "PingFang SC, Menlo, Courier New"); +// ChineseHK +pref("font.name-list.serif.zh-HK", "Songti TC, Times, Times New Roman"); +pref("font.name-list.sans-serif.zh-HK", "PingFang HK, Helvetica, Arial"); +pref("font.name-list.monospace.zh-HK", "PingFang HK, Menlo, Courier New"); +// ChineseTW +pref("font.name-list.serif.zh-TW", "Songti TC, Times, Times New Roman"); +pref("font.name-list.sans-serif.zh-TW", "PingFang TC, Helvetica, Arial"); +pref("font.name-list.monospace.zh-TW", "PingFang TC, Menlo, Courier New"); +// Devanagari +pref("font.name-list.serif.x-devanagari", "Noto Serif Devanagari, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-devanagari", "Noto Sans Devanagari, Helvetica, Arial"); +pref("font.name-list.monospace.x-devanagari", "Noto Sans Devanagari, Menlo, Courier New"); +// Ethiopic +pref("font.name-list.serif.x-ethi", "Noto Serif Ethiopic, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-ethi", "Noto Sans Ethiopic, Helvetica, Arial"); +pref("font.name-list.monospace.x-ethi", "Noto Sans Ethiopic, Menlo, Courier New"); +// Georgian +pref("font.name-list.serif.x-geor", "Noto Serif Georgian, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-geor", "Noto Sans Georgian, Helvetica, Arial"); +pref("font.name-list.monospace.x-geor", "Noto Sans Georgian, Menlo, Courier New"); +// Gujarati +pref("font.name-list.serif.x-gujr", "Noto Serif Gujarati, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-gujr", "Noto Sans Gujarati, Helvetica, Arial"); +pref("font.name-list.monospace.x-gujr", "Noto Sans Gujarati, Menlo, Courier New"); +// Gurmukhi +pref("font.name-list.serif.x-guru", "Noto Serif Gurmukhi, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-guru", "Noto Sans Gurmukhi, Helvetica, Arial"); +pref("font.name-list.monospace.x-guru", "Noto Sans Gurmukhi, Menlo, Courier New"); +// Hebrew +pref("font.name-list.serif.he", "Noto Serif Hebrew, Times, Times New Roman"); +pref("font.name-list.sans-serif.he", "Noto Sans Hebrew, Helvetica, Arial"); +pref("font.name-list.monospace.he", "Noto Sans Hebrew, Menlo, Courier New"); +// Kannada +pref("font.name-list.serif.x-knda", "Noto Serif Kannada, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-knda", "Noto Sans Kannada, Helvetica, Arial"); +pref("font.name-list.monospace.x-knda", "Noto Sans Kannada, Menlo, Courier New"); +// Khmer +pref("font.name-list.serif.x-khmr", "Noto Serif Khmer, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-khmr", "Noto Sans Khmer, Helvetica, Arial"); +pref("font.name-list.monospace.x-khmr", "Noto Sans Khmer, Menlo, Courier New"); +// Malayalam +pref("font.name-list.serif.x-mlym", "Noto Serif Malayalam, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-mlym", "Noto Sans Malayalam, Helvetica, Arial"); +pref("font.name-list.monospace.x-mlym", "Noto Sans Malayalam, Menlo, Courier New"); +// Mathematics +pref("font.name-list.serif.x-math", "STIX Two Math, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-math", "STIX Two Math, Helvetica, Arial"); +pref("font.name-list.monospace.x-math", "STIX Two Math, Menlo, Courier New"); +// Oriya +pref("font.name-list.serif.x-orya", "Noto Sans Oriya, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-orya", "Noto Sans Oriya, Helvetica, Arial"); +pref("font.name-list.monospace.x-orya", "Noto Sans Oriya, Menlo, Courier New"); +// Sinhala +pref("font.name-list.serif.x-sinh", "Noto Serif Sinhala, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-sinh", "Noto Sans Sinhala, Helvetica, Arial"); +pref("font.name-list.monospace.x-sinh", "Noto Sans Sinhala, Menlo, Courier New"); +// Tamil +pref("font.name-list.serif.x-tamil", "Noto Serif Tamil, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-tamil", "Noto Sans Tamil, Helvetica, Arial"); +pref("font.name-list.monospace.x-tamil", "Noto Sans Tamil, Menlo, Courier New"); +// Telugu +pref("font.name-list.serif.x-telu", "Noto Serif Telugu, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-telu", "Noto Sans Telugu, Helvetica, Arial"); +pref("font.name-list.monospace.x-telu", "Noto Sans Telugu, Menlo, Courier New"); +// Tibetan +pref("font.name-list.serif.x-tibt", "Noto Serif Tibetan, Times, Times New Roman"); +pref("font.name-list.sans-serif.x-tibt", "Noto Serif Tibetan, Helvetica, Arial"); +pref("font.name-list.monospace.x-tibt", "Noto Serif Tibetan, Menlo, Courier New"); +// Others (Balinese, Grantha, Khojki, Lao, Myanmar) +pref("font.name-list.serif.x-unicode", "Times, Times New Roman, Noto Serif Balinese, Noto Serif Grantha, Noto Serif Khojki, Noto Serif Lao, Noto Serif Myanmar"); +pref("font.name-list.sans-serif.x-unicode", "Helvetica, Arial, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +pref("font.name-list.monospace.x-unicode", "Menlo, Courier New, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +// The rest are not customized, because they are covered only by one font +#endif + +#ifdef XP_WIN +pref("font.system.whitelist", "Arial, Cambria Math, Consolas, Courier New, Georgia, Lucida Console, MS Gothic, MS ゴシック, MS PGothic, MS Pゴシック, MV Boli, Malgun Gothic, Microsoft Himalaya, Microsoft JhengHei, Microsoft YaHei, 微软雅黑, Segoe UI, SimSun, 宋体, Sylfaen, Tahoma, Times New Roman, Verdana, Twemoji Mozilla, Noto Sans Adlam, Noto Sans Balinese, Noto Sans Bamum, Noto Sans Bassa Vah, Noto Sans Batak, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Buhid, Noto Sans Canadian Aboriginal, Noto Sans Chakma, Noto Sans Cham, Noto Sans Cherokee, Noto Sans Coptic, Noto Sans Deseret, Noto Sans Devanagari, Noto Sans Elbasan, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Grantha, Noto Sans Gujarati, Noto Sans Gunjala Gondi, Noto Sans Gurmukhi, Noto Sans Hanifi Rohingya, Noto Sans Hanunoo, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Javanese, Noto Sans Kayah Li, Noto Sans Khojki, Noto Sans Khudawadi, Noto Sans Lao, Noto Sans Lepcha, Noto Sans Limbu, Noto Sans Lisu, Noto Sans Mahajani, Noto Sans Malayalam, Noto Sans Mandaic, Noto Sans Masaram Gondi, Noto Sans Medefaidrin, Noto Sans Meetei Mayek, Noto Sans Mende Kikakui, Noto Sans Miao, Noto Sans Modi, Noto Sans Mongolian, Noto Sans Mro, Noto Sans Myanmar, Noto Sans Multani, Noto Sans Newa, Noto Sans New Tai Lue, Noto Sans NKo, Noto Sans Ol Chiki, Noto Sans Oriya, Noto Sans Osage, Noto Sans Osmanya, Noto Sans Pahawh Hmong, Noto Sans Pau Cin Hau, Noto Sans Rejang, Noto Sans Runic, Noto Sans Samaritan, Noto Sans Saurashtra, Noto Sans Sharada, Noto Sans Shavian, Noto Sans Sinhala, Noto Sans Sora Sompeng, Noto Sans Soyombo, Noto Sans Sundanese, Noto Sans Syloti Nagri, Noto Sans Symbols 2, Noto Sans Symbols, Noto Sans Syriac, Noto Sans Tagalog, Noto Sans Tagbanwa, Noto Sans Tai Le, Noto Sans Tai Tham, Noto Sans Tai Viet, Noto Sans Takri, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tifinagh Adrar, Noto Sans Tifinagh Agraw Imazighen, Noto Sans Tifinagh Ahaggar, Noto Sans Tifinagh Air, Noto Sans Tifinagh APT, Noto Sans Tifinagh Azawagh, Noto Sans Tifinagh Ghat, Noto Sans Tifinagh Hawad, Noto Sans Tifinagh, Noto Sans Tifinagh Rhissa Ixa, Noto Sans Tifinagh SIL, Noto Sans Tifinagh Tawellemmet, Noto Sans Tirhuta, Noto Sans Vai, Noto Sans Wancho, Noto Sans Warang Citi, Noto Sans Yi, Noto Sans Zanabazar Square, Noto Serif Balinese, Noto Serif Bengali, Noto Serif Devanagari, Noto Serif Dogra, Noto Serif Ethiopic, Noto Serif Georgian, Noto Serif Grantha, Noto Serif Gujarati, Noto Serif Gurmukhi, Noto Serif Kannada, Noto Serif Khmer, Noto Serif Khojki, Noto Serif Lao, Noto Serif Malayalam, Noto Serif Myanmar, Noto Serif NP Hmong, Noto Serif Sinhala, Noto Serif Tamil, Noto Serif Telugu, Noto Serif Tibetan, Noto Serif Yezidi, Noto Naskh Arabic, Noto Sans, Noto Serif"); + +// Arabic +pref("font.name-list.serif.ar", "Times New Roman, Noto Naskh Arabic"); +pref("font.name-list.sans-serif.ar", "Segoe UI, Tahoma, Arial, Noto Naskh Arabic"); +pref("font.name-list.monospace.ar", "Consolas, Noto Naskh Arabic"); +// Bengali +pref("font.name-list.serif.x-beng", "Noto Serif Bengali, Times New Roman"); +pref("font.name-list.sans-serif.x-beng", "Noto Sans Bengali, Arial"); +pref("font.name-list.monospace.x-beng", "Noto Sans Bengali, Consolas"); +// Canadian Aboriginal +pref("font.name-list.serif.x-cans", "Noto Serif Canadian Aboriginal, Times New Roman"); +pref("font.name-list.sans-serif.x-cans", "Noto Sans Canadian Aboriginal, Arial"); +pref("font.name-list.monospace.x-cans", "Noto Sans Canadian Aboriginal, Consolas"); +// Cyrillic (we use Noto only for fallback, system fonts have a good coverage) +pref("font.name-list.serif.x-cyrillic", "Times New Roman, Noto Serif"); +pref("font.name-list.sans-serif.x-cyrillic", "Arial, Noto Sans"); +// Devanagari +pref("font.name-list.serif.x-devanagari", "Noto Serif Devanagari, Times New Roman"); +pref("font.name-list.sans-serif.x-devanagari", "Noto Sans Devanagari, Arial"); +pref("font.name-list.monospace.x-devanagari", "Noto Sans Devanagari, Consolas"); +// Ethiopic +pref("font.name-list.serif.x-ethi", "Noto Serif Ethiopic, Times New Roman"); +pref("font.name-list.sans-serif.x-ethi", "Noto Sans Ethiopic, Arial"); +pref("font.name-list.monospace.x-ethi", "Noto Sans Ethiopic, Consolas"); +// Georgian +pref("font.name-list.serif.x-geor", "Noto Serif Georgian, Times New Roman"); +pref("font.name-list.sans-serif.x-geor", "Noto Sans Georgian, Arial"); +pref("font.name-list.monospace.x-geor", "Noto Sans Georgian, Consolas"); +// Gujarati +pref("font.name-list.serif.x-gujr", "Noto Serif Gujarati, Times New Roman"); +pref("font.name-list.sans-serif.x-gujr", "Noto Sans Gujarati, Arial"); +pref("font.name-list.monospace.x-gujr", "Noto Sans Gujarati, Consolas"); +// Gurmukhi +pref("font.name-list.serif.x-guru", "Noto Serif Gurmukhi, Times New Roman"); +pref("font.name-list.sans-serif.x-guru", "Noto Sans Gurmukhi, Arial"); +pref("font.name-list.monospace.x-guru", "Noto Sans Gurmukhi, Consolas"); +// Kannada +pref("font.name-list.serif.x-knda", "Noto Serif Kannada, Times New Roman"); +pref("font.name-list.sans-serif.x-knda", "Noto Sans Kannada, Arial"); +pref("font.name-list.monospace.x-knda", "Noto Sans Kannada, Consolas"); +// Khmer +pref("font.name-list.serif.x-khmr", "Noto Serif Khmer, Times New Roman"); +pref("font.name-list.sans-serif.x-khmr", "Noto Sans Khmer, Arial"); +pref("font.name-list.monospace.x-khmr", "Noto Sans Khmer, Consolas"); +// Malayalam +pref("font.name-list.serif.x-mlym", "Noto Serif Malayalam, Times New Roman"); +pref("font.name-list.sans-serif.x-mlym", "Noto Sans Malayalam, Arial"); +pref("font.name-list.monospace.x-mlym", "Noto Sans Malayalam, Consolas"); +// Oriya +pref("font.name-list.serif.x-orya", "Noto Sans Oriya, Times New Roman"); +pref("font.name-list.sans-serif.x-orya", "Noto Sans Oriya, Arial"); +pref("font.name-list.monospace.x-orya", "Noto Sans Oriya, Consolas"); +// Sinhala +pref("font.name-list.serif.x-sinh", "Noto Serif Sinhala, Times New Roman"); +pref("font.name-list.sans-serif.x-sinh", "Noto Sans Sinhala, Arial"); +pref("font.name-list.monospace.x-sinh", "Noto Sans Sinhala, Consolas"); +// Tamil +pref("font.name-list.serif.x-tamil", "Noto Serif Tamil, Times New Roman"); +pref("font.name-list.sans-serif.x-tamil", "Noto Sans Tamil, Arial"); +pref("font.name-list.monospace.x-tamil", "Noto Sans Tamil, Consolas"); +// Telugu +pref("font.name-list.serif.x-telu", "Noto Serif Telugu, Times New Roman"); +pref("font.name-list.sans-serif.x-telu", "Noto Sans Telugu, Arial"); +pref("font.name-list.monospace.x-telu", "Noto Sans Telugu, Consolas"); +// Tibetan +pref("font.name-list.serif.x-tibt", "Microsoft Himalaya, Noto Serif Tibetan, Times New Roman"); +pref("font.name-list.sans-serif.x-tibt", "Microsoft Himalaya, Noto Serif Tibetan, Arial"); +pref("font.name-list.monospace.x-tibt", "Microsoft Himalaya, Noto Serif Tibetan, Consolas"); +// Others (Balinese, Grantha, Khojki, Lao, Myanmar) +pref("font.name-list.serif.x-unicode", "Times New Roman, Noto Serif Balinese, Noto Serif Grantha, Noto Serif Khojki, Noto Serif Lao, Noto Serif Myanmar"); +pref("font.name-list.sans-serif.x-unicode", "Arial, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +pref("font.name-list.monospace.x-unicode", "Consolas, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +// The rest are not customized, because they are covered only by one font +#endif + +#ifdef XP_LINUX +pref("font.system.whitelist", "Arimo, Cousine, Noto Naskh Arabic, Noto Sans Adlam, Noto Sans Armenian, Noto Sans Balinese, Noto Sans Bamum, Noto Sans Bassa Vah, Noto Sans Batak, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Buhid, Noto Sans Canadian Aboriginal, Noto Sans Chakma, Noto Sans Cham, Noto Sans Cherokee, Noto Sans Coptic, Noto Sans Deseret, Noto Sans Devanagari, Noto Sans Elbasan, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Grantha, Noto Sans Gujarati, Noto Sans Gunjala Gondi, Noto Sans Gurmukhi, Noto Sans Hanifi Rohingya, Noto Sans Hanunoo, Noto Sans Hebrew, Noto Sans JP, Noto Sans Javanese, Noto Sans KR, Noto Sans Kannada, Noto Sans Kayah Li, Noto Sans Khmer, Noto Sans Khojki, Noto Sans Khudawadi, Noto Sans Lao, Noto Sans Lepcha, Noto Sans Limbu, Noto Sans Lisu, Noto Sans Mahajani, Noto Sans Malayalam, Noto Sans Mandaic, Noto Sans Masaram Gondi, Noto Sans Medefaidrin, Noto Sans Meetei Mayek, Noto Sans Mende Kikakui, Noto Sans Miao, Noto Sans Modi, Noto Sans Mongolian, Noto Sans Mro, Noto Sans Multani, Noto Sans Myanmar, Noto Sans NKo, Noto Sans New Tai Lue, Noto Sans Newa, Noto Sans Ol Chiki, Noto Sans Oriya, Noto Sans Osage, Noto Sans Osmanya, Noto Sans Pahawh Hmong, Noto Sans Pau Cin Hau, Noto Sans Rejang, Noto Sans Runic, Noto Sans SC, Noto Sans Samaritan, Noto Sans Saurashtra, Noto Sans Sharada, Noto Sans Shavian, Noto Sans Sinhala, Noto Sans Sora Sompeng, Noto Sans Soyombo, Noto Sans Sundanese, Noto Sans Syloti Nagri, Noto Sans Symbols, Noto Sans Symbols 2, Noto Sans Syriac, Noto Sans TC, Noto Sans Tagalog, Noto Sans Tagbanwa, Noto Sans Tai Le, Noto Sans Tai Tham, Noto Sans Tai Viet, Noto Sans Takri, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tifinagh, Noto Sans Tifinagh APT, Noto Sans Tifinagh Adrar, Noto Sans Tifinagh Agraw Imazighen, Noto Sans Tifinagh Ahaggar, Noto Sans Tifinagh Air, Noto Sans Tifinagh Azawagh, Noto Sans Tifinagh Ghat, Noto Sans Tifinagh Hawad, Noto Sans Tifinagh Rhissa Ixa, Noto Sans Tifinagh SIL, Noto Sans Tifinagh Tawellemmet, Noto Sans Tirhuta, Noto Sans Vai, Noto Sans Wancho, Noto Sans Warang Citi, Noto Sans Yi, Noto Sans Zanabazar Square, Noto Serif Armenian, Noto Serif Balinese, Noto Serif Bengali, Noto Serif Devanagari, Noto Serif Dogra, Noto Serif Ethiopic, Noto Serif Georgian, Noto Serif Grantha, Noto Serif Gujarati, Noto Serif Gurmukhi, Noto Serif Hebrew, Noto Serif Kannada, Noto Serif Khmer, Noto Serif Khojki, Noto Serif Lao, Noto Serif Malayalam, Noto Serif Myanmar, Noto Serif NP Hmong, Noto Serif Sinhala, Noto Serif Tamil, Noto Serif Telugu, Noto Serif Thai, Noto Serif Tibetan, Noto Serif Yezidi, STIX Two Math, Tinos, Twemoji Mozilla"); + +// Arabic +pref("font.name-list.serif.ar", "Noto Naskh Arabic, Tinos"); +pref("font.name-list.sans-serif.ar", "Noto Naskh Arabic, Arimo"); +pref("font.name-list.monospace.ar", "Noto Naskh Arabic, Cousine"); +// Armenian +pref("font.name-list.serif.x-armn", "Noto Serif Armenian, Tinos"); +pref("font.name-list.sans-serif.x-armn", "Noto Sans Armenian, Arimo"); +pref("font.name-list.sans-serif.x-armn", "Noto Sans Armenian, Cousine"); +// Bengali +pref("font.name-list.serif.x-beng", "Noto Serif Bengali, Tinos"); +pref("font.name-list.sans-serif.x-beng", "Noto Sans Bengali, Arimo"); +pref("font.name-list.monospace.x-beng", "Noto Sans Bengali, Cousine"); +// Canadian Aboriginal +pref("font.name-list.serif.x-cans", "Noto Serif Canadian Aboriginal, Tinos"); +pref("font.name-list.sans-serif.x-cans", "Noto Sans Canadian Aboriginal, Arimo"); +pref("font.name-list.monospace.x-cans", "Noto Sans Canadian Aboriginal, Cousine"); +// ChineseCN +pref("font.name-list.serif.zh-CN", "Noto Sans SC Regular, Tinos"); +pref("font.name-list.sans-serif.zh-CN", "Noto Sans SC Regular, Arimo"); +pref("font.name-list.monospace.zh-CN", "Noto Sans SC Regular, Cousine"); +// ChineseHK +pref("font.name-list.serif.zh-HK", "Noto Sans TC Regular, Tinos"); +pref("font.name-list.sans-serif.zh-HK", "Noto Sans TC Regular, Arimo"); +pref("font.name-list.monospace.zh-HK", "Noto Sans TC Regular, Cousine"); +// ChineseTW +pref("font.name-list.serif.zh-TW", "Noto Sans TC Regular, Tinos"); +pref("font.name-list.sans-serif.zh-TW", "Noto Sans TC Regular, Arimo"); +pref("font.name-list.monospace.zh-TW", "Noto Sans TC Regular, Cousine"); +// Cyrillic +pref("font.name-list.serif.x-cyrillic", "Tinos"); +pref("font.name-list.sans-serif.x-cyrillic", "Arimo"); +pref("font.name-list.monospace.x-cyrillic", "Cousine"); +// Devanagari +pref("font.name-list.serif.x-devanagari", "Noto Serif Devanagari, Tinos"); +pref("font.name-list.sans-serif.x-devanagari", "Noto Sans Devanagari, Arimo"); +pref("font.name-list.monospace.x-devanagari", "Noto Sans Devanagari, Cousine"); +// Ethiopic +pref("font.name-list.serif.x-ethi", "Noto Serif Ethiopic, Tinos"); +pref("font.name-list.sans-serif.x-ethi", "Noto Sans Ethiopic, Arimo"); +pref("font.name-list.monospace.x-ethi", "Noto Sans Ethiopic, Cousine"); +// Georgian +pref("font.name-list.serif.x-geor", "Noto Serif Georgian, Tinos"); +pref("font.name-list.sans-serif.x-geor", "Noto Sans Georgian, Arimo"); +pref("font.name-list.monospace.x-geor", "Noto Sans Georgian, Cousine"); +// Greek +pref("font.name-list.serif.el", "Tinos"); +pref("font.name-list.sans-serif.el", "Arimo"); +pref("font.name-list.monospace.el", "Cousine"); +// Gujarati +pref("font.name-list.serif.x-gujr", "Noto Serif Gujarati, Tinos"); +pref("font.name-list.sans-serif.x-gujr", "Noto Sans Gujarati, Arimo"); +pref("font.name-list.monospace.x-gujr", "Noto Sans Gujarati, Cousine"); +// Gurmukhi +pref("font.name-list.serif.x-guru", "Noto Serif Gurmukhi, Tinos"); +pref("font.name-list.sans-serif.x-guru", "Noto Sans Gurmukhi, Arimo"); +pref("font.name-list.monospace.x-guru", "Noto Sans Gurmukhi, Cousine"); +// Hebrew +pref("font.name-list.serif.he", "Noto Serif Hebrew, Tinos"); +pref("font.name-list.sans-serif.he", "Noto Sans Hebrew, Arimo"); +pref("font.name-list.monospace.he", "Noto Sans Hebrew, Cousine"); +// Japanese +pref("font.name-list.serif.ja", "Noto Sans JP Regular, Tinos"); +pref("font.name-list.sans-serif.ja", "Noto Sans JP Regular, Arimo"); +pref("font.name-list.monospace.ja", "Noto Sans JP Regular, Cousine"); +// Kannada +pref("font.name-list.serif.x-knda", "Noto Serif Kannada, Tinos"); +pref("font.name-list.sans-serif.x-knda", "Noto Sans Kannada, Arimo"); +pref("font.name-list.monospace.x-knda", "Noto Sans Kannada, Cousine"); +// Khmer +pref("font.name-list.serif.x-khmr", "Noto Serif Khmer, Tinos"); +pref("font.name-list.sans-serif.x-khmr", "Noto Sans Khmer, Arimo"); +pref("font.name-list.monospace.x-khmr", "Noto Sans Khmer, Cousine"); +// Korean +pref("font.name-list.serif.ko", "Noto Sans KR Regular"); +pref("font.name-list.sans-serif.ko", "Noto Sans KR Regular"); +pref("font.name-list.monospace.ko", "Noto Sans KR Regular"); +// Malayalam +pref("font.name-list.serif.x-mlym", "Noto Serif Malayalam, Tinos"); +pref("font.name-list.sans-serif.x-mlym", "Noto Sans Malayalam, Arimo"); +pref("font.name-list.monospace.x-mlym", "Noto Sans Malayalam, Cousine"); +// Mathematics +pref("font.name-list.serif.x-math", "STIX Two Math, Tinos"); +pref("font.name-list.sans-serif.x-math", "STIX Two Math, Arimo"); +pref("font.name-list.monospace.x-math", "STIX Two Math, Cousine"); +// Oriya +pref("font.name-list.serif.x-orya", "Noto Sans Oriya, Tinos"); +pref("font.name-list.sans-serif.x-orya", "Noto Sans Oriya, Arimo"); +pref("font.name-list.monospace.x-orya", "Noto Sans Oriya, Cousine"); +// Sinhala +pref("font.name-list.serif.x-sinh", "Noto Serif Sinhala, Tinos"); +pref("font.name-list.sans-serif.x-sinh", "Noto Sans Sinhala, Arimo"); +pref("font.name-list.monospace.x-sinh", "Noto Sans Sinhala, Cousine"); +// Tamil +pref("font.name-list.serif.x-tamil", "Noto Serif Tamil, Tinos"); +pref("font.name-list.sans-serif.x-tamil", "Noto Sans Tamil, Arimo"); +pref("font.name-list.monospace.x-tamil", "Noto Sans Tamil, Cousine"); +// Telugu +pref("font.name-list.serif.x-telu", "Noto Serif Telugu, Tinos"); +pref("font.name-list.sans-serif.x-telu", "Noto Sans Telugu, Arimo"); +pref("font.name-list.monospace.x-telu", "Noto Sans Telugu, Cousine"); +// Thai +pref("font.name-list.serif.th", "Noto Serif Thai, Tinos"); +pref("font.name-list.sans-serif.th", "Noto Sans Thai, Arimo"); +pref("font.name-list.monospace.th", "Noto Sans Thai, Cousine"); +// Tibetan +pref("font.name-list.serif.x-tibt", "Noto Serif Tibetan, Tinos"); +pref("font.name-list.sans-serif.x-tibt", "Noto Serif Tibetan, Arimo"); +pref("font.name-list.monospace.x-tibt", "Noto Serif Tibetan, Cousine"); +// Western +pref("font.name-list.serif.x-western", "Tinos"); +pref("font.name-list.sans-serif.x-western", "Arimo"); +pref("font.name-list.monospace.x-western", "Cousine"); +// Others (Balinese, Grantha, Khojki, Lao, Myanmar) +pref("font.name-list.serif.x-unicode", "Tinos, Noto Serif Balinese, Noto Serif Grantha, Noto Serif Khojki, Noto Serif Lao, Noto Serif Myanmar"); +pref("font.name-list.sans-serif.x-unicode", "Arimo, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +pref("font.name-list.monospace.x-unicode", "Cousine, Noto Sans Balinese, Noto Sans Grantha, Noto Sans Khojki, Noto Sans Lao, Noto Sans Myanmar"); +// The rest are not customized, because they are covered only by one font +#endif +#endif diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index a976fc641c270589e31de8399c74bce0907406d0..798b186d40bb5ac111bacf3725a844d9f4f6125a 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -50,9 +50,9 @@ pref("extensions.recommendations.themeRecommendationUrl", "https://color.firefox pref("extensions.update.autoUpdateDefault", true); -// Check AUS for system add-on updates. -pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml"); -pref("extensions.systemAddon.update.enabled", true); +// No AUS check for system add-on updates for Tor Browser users. +pref("extensions.systemAddon.update.url", ""); +pref("extensions.systemAddon.update.enabled", false); // Disable add-ons that are not installed by the user in all scopes by default. // See the SCOPE constants in AddonManager.sys.mjs for values to use here. diff --git a/browser/base/content/aboutDialog-appUpdater.js b/browser/base/content/aboutDialog-appUpdater.js index 4f999fb5f45bb8eae307891e60092d4d1155f645..4e0ce398b54c7e5dc2283a97b077569cbc1add6f 100644 --- a/browser/base/content/aboutDialog-appUpdater.js +++ b/browser/base/content/aboutDialog-appUpdater.js @@ -205,7 +205,7 @@ appUpdater.prototype = { if (aChildID == "downloadAndInstall") { let updateVersion = gAppUpdater.update.displayVersion; // Include the build ID if this is an "a#" (nightly or aurora) build - if (/a\d+$/.test(updateVersion)) { + if (!AppConstants.BASE_BROWSER_UPDATE && /a\d+$/.test(updateVersion)) { let buildID = gAppUpdater.update.buildID; let year = buildID.slice(0, 4); let month = buildID.slice(4, 6); diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js index 8c5c7768e0e716c196063b4c986dea2631185972..952a48b105f1c78ee2b99a5a1bf6e0c35485924f 100644 --- a/browser/base/content/aboutDialog.js +++ b/browser/base/content/aboutDialog.js @@ -43,34 +43,21 @@ function init() { } // Include the build ID and display warning if this is an "a#" (nightly or aurora) build - let versionIdMap = new Map([ - ["base", "aboutDialog-version"], - ["base-nightly", "aboutDialog-version-nightly"], - ["base-arch", "aboutdialog-version-arch"], - ["base-arch-nightly", "aboutdialog-version-arch-nightly"], - ]); - let versionIdKey = "base"; + let versionId = "basebrowser-about-dialog-version"; let versionAttributes = { - version: AppConstants.MOZ_APP_VERSION_DISPLAY, + version: AppConstants.BASE_BROWSER_VERSION, + firefoxVersion: AppConstants.MOZ_APP_VERSION_DISPLAY, }; let arch = Services.sysinfo.get("arch"); if (["x86", "x86-64"].includes(arch)) { versionAttributes.bits = Services.appinfo.is64Bit ? 64 : 32; } else { - versionIdKey += "-arch"; versionAttributes.arch = arch; } let version = Services.appinfo.version; if (/a\d+$/.test(version)) { - versionIdKey += "-nightly"; - let buildID = Services.appinfo.appBuildID; - let year = buildID.slice(0, 4); - let month = buildID.slice(4, 6); - let day = buildID.slice(6, 8); - versionAttributes.isodate = `${year}-${month}-${day}`; - document.getElementById("experimental").hidden = false; document.getElementById("communityDesc").hidden = true; } @@ -78,11 +65,7 @@ function init() { // Use Fluent arguments for append version and the architecture of the build let versionField = document.getElementById("version"); - document.l10n.setAttributes( - versionField, - versionIdMap.get(versionIdKey), - versionAttributes - ); + document.l10n.setAttributes(versionField, versionId, versionAttributes); // Show a release notes link if we have a URL. let relNotesLink = document.getElementById("releasenotes"); diff --git a/browser/base/content/aboutDialog.xhtml b/browser/base/content/aboutDialog.xhtml index 1e5c0f1c59175ec4a39938974c4a7a5c6355439f..1f2c9cc459fb32e958d7e149d7249edf0eacd526 100644 --- a/browser/base/content/aboutDialog.xhtml +++ b/browser/base/content/aboutDialog.xhtml @@ -15,7 +15,7 @@ data-l10n-id="aboutDialog-title" #endif role="dialog" - aria-describedby="version distribution distributionId communityDesc contributeDesc trademark" + aria-describedby="version distribution distributionId projectDesc helpDesc trademark" > #ifdef XP_MACOSX #include macWindow.inc.xhtml @@ -33,9 +33,15 @@ rel="stylesheet" href="chrome://branding/content/aboutDialog.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/content/aboutDialogTor.css" + /> <html:link rel="localization" href="branding/brand.ftl"/> <html:link rel="localization" href="browser/aboutDialog.ftl"/> + <html:link rel="localization" href="toolkit/global/base-browser.ftl"/> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl"/> </linkset> <html:div id="aboutDialogContainer"> @@ -129,22 +135,24 @@ <label is="text-link" useoriginprincipal="true" href="about:credits" data-l10n-name="community-exp-creditsLink"/> </description> </vbox> - <description class="text-blurb" id="communityDesc" data-l10n-id="community-2"> - <label is="text-link" href="https://www.mozilla.org/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog" data-l10n-name="community-mozillaLink"/> - <label is="text-link" useoriginprincipal="true" href="about:credits" data-l10n-name="community-creditsLink"/> + <!-- Keep communityDesc and contributeDesc to avoid JS errors trying to hide them --> + <description class="text-blurb" id="communityDesc" hidden="true"></description> + <description class="text-blurb" id="contributeDesc" hidden="true"></description> + <description class="text-blurb" id="projectDesc" data-l10n-id="about-dialog-tor-project"> + <label is="text-link" href="https://www.torproject.org/" data-l10n-name="project-link"></label> </description> - <description class="text-blurb" id="contributeDesc" data-l10n-id="helpus"> - <label is="text-link" href="https://foundation.mozilla.org/?form=firefox-about" data-l10n-name="helpus-donateLink"/> - <label is="text-link" href="https://www.mozilla.org/contribute/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog" data-l10n-name="helpus-getInvolvedLink"/> + <description class="text-blurb" id="helpDesc" data-l10n-id="about-dialog-help-out"> + <label is="text-link" href="https://donate.torproject.org/" data-l10n-name="donate-link"></label> + <label is="text-link" href="https://community.torproject.org/" data-l10n-name="community-link"></label> </description> </vbox> </vbox> </hbox> <vbox id="bottomBox"> - <hbox pack="center"> - <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:license" data-l10n-id="bottomLinks-license"/> - <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:rights" data-l10n-id="bottomLinks-rights"/> - <label is="text-link" class="bottom-link" href="https://www.mozilla.org/privacy/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog" data-l10n-id="bottomLinks-privacy"/> + <hbox id="newBottom" pack="center" position="1"> + <label is="text-link" class="bottom-link" href="https://support.torproject.org/" data-l10n-id="about-dialog-questions-link"></label> + <label is="text-link" class="bottom-link" href="https://community.torproject.org/relay/" data-l10n-id="about-dialog-grow-tor-network-link"></label> + <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:license" data-l10n-id="about-dialog-browser-license-link"></label> </hbox> <description id="trademark" data-l10n-id="trademarkInfo"></description> </vbox> diff --git a/browser/base/content/aboutDialogTor.css b/browser/base/content/aboutDialogTor.css new file mode 100644 index 0000000000000000000000000000000000000000..4a3a9d383e0128c31b9eea490ff120352771b574 --- /dev/null +++ b/browser/base/content/aboutDialogTor.css @@ -0,0 +1,29 @@ +#leftBox { + background-image: url('chrome://branding/content/icon256.png'); + background-position: right top; + background-size: 180px; +} + +#rightBox { + background-size: auto; + padding-top: 32px; +} + +#contributeDesc { + display: none; +} + +#communityDesc { + display: none; +} + +#trademark { + font-size: xx-small; + text-align: center; + color: #999999; + margin-block: 10px; +} + +#bottomBox > hbox:not(#newBottom) { + display: none; +} diff --git a/browser/base/content/appmenu-viewcache.inc.xhtml b/browser/base/content/appmenu-viewcache.inc.xhtml index 9633c7d79df7ddccf82a50daa7ce608b1ccae2cd..4b83db0ec7c85126cd4d95acb1586651f9e9028f 100644 --- a/browser/base/content/appmenu-viewcache.inc.xhtml +++ b/browser/base/content/appmenu-viewcache.inc.xhtml @@ -48,6 +48,16 @@ key="key_privatebrowsing" command="Tools:PrivateBrowsing"/> <toolbarseparator/> + <toolbarbutton id="appMenu-new-identity" + class="subviewbutton" + data-l10n-id="appmenuitem-new-identity" + key="new-identity-key"/> + <toolbarbutton id="appMenuNewCircuit" + class="subviewbutton" + key="new-circuit-key" + data-l10n-id="appmenuitem-new-tor-circuit" + oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser.selectedBrowser);"/> + <toolbarseparator/> <toolbarbutton id="appMenu-bookmarks-button" class="subviewbutton subviewbutton-nav" data-l10n-id="library-bookmarks-menu" diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js index 64e7f5897b5c92e1af82642beeed5184b60fcf2a..6774623687e0298fae868e250dfe77fdbb9c8c87 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -28,6 +28,9 @@ ChromeUtils.defineLazyGetter(lazy, "l10n", function () { ); }); +const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript"; +const HIDE_UNIFIED_WHEN_EMPTY_PREF = "extensions.hideUnifiedWhenEmpty"; + /** * Mapping of error code -> [error-id, local-error-id] * @@ -1412,6 +1415,18 @@ var gUnifiedExtensions = { gNavToolbox.addEventListener("customizationstarting", this); CustomizableUI.addListener(this); + // Listen out for changes in extensions.hideNoScript and + // extension.hideUnifiedWhenEmpty, which can effect the visibility of the + // unified-extensions-button. + // See tor-browser#41581. + this._hideNoScriptObserver = () => this._updateVisibility(); + Services.prefs.addObserver(HIDE_NO_SCRIPT_PREF, this._hideNoScriptObserver); + Services.prefs.addObserver( + HIDE_UNIFIED_WHEN_EMPTY_PREF, + this._hideNoScriptObserver + ); + this._updateVisibility(); + this._initialized = true; }, @@ -1427,6 +1442,15 @@ var gUnifiedExtensions = { gNavToolbox.removeEventListener("customizationstarting", this); CustomizableUI.removeListener(this); + + Services.prefs.removeObserver( + HIDE_NO_SCRIPT_PREF, + this._hideNoScriptObserver + ); + Services.prefs.removeObserver( + HIDE_UNIFIED_WHEN_EMPTY_PREF, + this._hideNoScriptObserver + ); }, onLocationChange(browser, webProgress, _request, _uri, flags) { @@ -1512,6 +1536,15 @@ var gUnifiedExtensions = { return false; } + // When an extensions is about to be removed, it may still appear in + // getActiveExtensions. + // This is needed for hasExtensionsInPanel, when called through + // onWidgetDestroy when an extension is being removed. + // See tor-browser#41581. + if (extension.hasShutdown) { + return false; + } + // Ignore hidden and extensions that cannot access the current window // (because of PB mode when we are in a private window), since users // cannot do anything with those extensions anyway. @@ -1526,6 +1559,21 @@ var gUnifiedExtensions = { return policies; }, + /** + * Potentially hide the unified-extensions-button if it would be empty. + */ + // See tor-browser#41581. + // The behaviour overlaps with a proposal in mozilla Bug 1778684, which has + // not yet been implemented as of June 2024 (start of ESR 128). + // See tor-browser#42635 + _updateVisibility() { + this.button.classList.toggle( + "hide-empty", + Services.prefs.getBoolPref(HIDE_UNIFIED_WHEN_EMPTY_PREF, true) && + !this.hasExtensionsInPanel() + ); + }, + /** * Returns true when there are active extensions listed/shown in the unified * extensions panel, and false otherwise (e.g. when extensions are pinned in @@ -1534,7 +1582,13 @@ var gUnifiedExtensions = { * @returns {boolean} Whether there are extensions listed in the panel. */ hasExtensionsInPanel() { - const policies = this.getActivePolicies(); + let policies = this.getActivePolicies(); + // If the NoScript button is hidden, we won't count it towards the list of + // extensions in the panel. + // See tor-browser#41581. + if (Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true)) { + policies = policies.filter(policy => !policy.extension?.isNoScript); + } return !!policies .map(policy => this.browserActionFor(policy)?.widget) @@ -2026,7 +2080,17 @@ var gUnifiedExtensions = { } }, + onWidgetRemoved() { + this._updateVisibility(); + }, + + onWidgetDestroyed() { + this._updateVisibility(); + }, + onWidgetAdded(aWidgetId, aArea) { + this._updateVisibility(); + // When we pin a widget to the toolbar from a narrow window, the widget // will be overflowed directly. In this case, we do not want to change the // class name since it is going to be changed by `onWidgetOverflow()` @@ -2042,6 +2106,8 @@ var gUnifiedExtensions = { }, onWidgetOverflow(aNode) { + this._updateVisibility(); + // We register a CUI listener for each window so we make sure that we // handle the event for the right window here. if (window !== aNode.ownerGlobal) { @@ -2052,6 +2118,8 @@ var gUnifiedExtensions = { }, onWidgetUnderflow(aNode) { + this._updateVisibility(); + // We register a CUI listener for each window so we make sure that we // handle the event for the right window here. if (window !== aNode.ownerGlobal) { diff --git a/browser/base/content/browser-context.js b/browser/base/content/browser-context.js index 767e693d4c8bfb78587339c1785e487b4bcfb701..50daa4c3bd1b8b55c1d2e41cf521e455f083712c 100644 --- a/browser/base/content/browser-context.js +++ b/browser/base/content/browser-context.js @@ -131,7 +131,7 @@ document.addEventListener( gContextMenu.saveMedia(); break; case "context-copyimage-contents": - goDoCommand("cmd_copyImage"); + goDoCommand("cmd_copyImageContents"); break; case "context-copyaudiourl": case "context-copyimage": diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js index a3c3f46dff09b0fb5a18c7f163fba1a97a768c60..2812ba939d255fd988cd7be62716dcc4213a4ad8 100644 --- a/browser/base/content/browser-init.js +++ b/browser/base/content/browser-init.js @@ -238,6 +238,20 @@ var gBrowserInit = { // doesn't flicker as the window is being shown. DownloadsButton.init(); + // Init the SecurityLevelButton + SecurityLevelButton.init(); + + // Init the NewIdentityButton + NewIdentityButton.init(); + + gTorConnectUrlbarButton.init(); + gTorConnectTitlebarStatus.init(); + + // Init the OnionAuthPrompt + OnionAuthPrompt.init(); + + gTorCircuitPanel.init(); + // Certain kinds of automigration rely on this notification to complete // their tasks BEFORE the browser window is shown. SessionStore uses it to // restore tabs into windows AFTER important parts like gMultiProcessBrowser @@ -620,8 +634,6 @@ var gBrowserInit = { CaptivePortalWatcher.delayedStartup(); - ShoppingSidebarManager.ensureInitialized(); - if (Services.prefs.getBoolPref("browser.profiles.enabled", false)) { SelectableProfileService?.init(); } @@ -956,32 +968,48 @@ var gBrowserInit = { let defaultArgs = BrowserHandler.defaultArgs; - // If the given URI is different from the homepage, we want to load it. - if (uri != defaultArgs) { - AboutNewTab.noteNonDefaultStartup(); + // figure out which URI to actually load (or a Promise to get the uri) + uri = (aUri => { + // If the given URI is different from the homepage, we want to load it. + if (aUri != defaultArgs) { + AboutNewTab.noteNonDefaultStartup(); + + if (aUri instanceof Ci.nsIArray) { + // Transform the nsIArray of nsISupportsString's into a JS Array of + // JS strings. + return Array.from( + aUri.enumerate(Ci.nsISupportsString), + supportStr => supportStr.data + ); + } else if (aUri instanceof Ci.nsISupportsString) { + return aUri.data; + } + return aUri; + } - if (uri instanceof Ci.nsIArray) { - // Transform the nsIArray of nsISupportsString's into a JS Array of - // JS strings. - return Array.from( - uri.enumerate(Ci.nsISupportsString), - supportStr => supportStr.data - ); - } else if (uri instanceof Ci.nsISupportsString) { - return uri.data; + // The URI appears to be the the homepage. We want to load it only if + // session restore isn't about to override the homepage. + let willOverride = SessionStartup.willOverrideHomepage; + if (typeof willOverride == "boolean") { + return willOverride ? null : uri; } - return uri; - } + return willOverride.then(willOverrideHomepage => + willOverrideHomepage ? null : uri + ); + })(uri); + + // if using TorConnect, convert these uris to redirects + if (TorConnect.shouldShowTorConnect) { + return Promise.resolve(uri).then(aUri => { + if (aUri == null) { + aUri = []; + } - // The URI appears to be the the homepage. We want to load it only if - // session restore isn't about to override the homepage. - let willOverride = SessionStartup.willOverrideHomepage; - if (typeof willOverride == "boolean") { - return willOverride ? null : uri; + aUri = TorConnect.getURIsToLoad(aUri); + return aUri; + }); } - return willOverride.then(willOverrideHomepage => - willOverrideHomepage ? null : uri - ); + return uri; })()); }, @@ -1043,6 +1071,17 @@ var gBrowserInit = { DownloadsButton.uninit(); + SecurityLevelButton.uninit(); + + NewIdentityButton.uninit(); + + gTorConnectUrlbarButton.uninit(); + gTorConnectTitlebarStatus.uninit(); + + OnionAuthPrompt.uninit(); + + gTorCircuitPanel.uninit(); + if (gToolbarKeyNavEnabled) { ToolbarKeyboardNavigator.uninit(); } diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index 7b8a78623e0ddf4cbcbdf09d14bcd27810e76ce6..18e9852bcb6c4de1c6e2de101c4a8ddb554475cf 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -20,6 +20,13 @@ <menuitem id="menu_newPrivateWindow" command="Tools:PrivateBrowsing" key="key_privatebrowsing" data-l10n-id="menu-file-new-private-window"/> + <menuseparator/> + <menuitem id="menu_newIdentity" + key="new-identity-key" data-l10n-id="menu-new-identity"/> + <menuitem id="menu_newCircuit" + key="new-circuit-key" data-l10n-id="menu-new-tor-circuit" + oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser.selectedBrowser);"/> + <menuseparator/> <menuitem id="menu_openLocation" hidden="true" command="Browser:OpenLocation" @@ -419,7 +426,13 @@ <menupopup id="menu_HelpPopup"> <!-- Note: Items under here are cloned to the AppMenu Help submenu. The cloned items have their strings defined by appmenu-data-l10n-id. --> + <!-- Add Tor Browser manual link --> + <menuitem id="torBrowserUserManual" + oncommand="gBrowser.selectedTab = gBrowser.addTab('about:manual', {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});" + data-l10n-id="menu-open-tor-manual" + appmenu-data-l10n-id="appmenu-open-tor-manual"/> <menuitem id="menu_openHelp" + hidden="true" data-l10n-id="menu-get-help" appmenu-data-l10n-id="appmenu-get-help" #ifdef XP_MACOSX @@ -433,12 +446,15 @@ hidden="true" appmenu-data-l10n-id="menu-report-broken-site"/> <menuitem id="feedbackPage" + hidden="true" data-l10n-id="menu-help-share-ideas" appmenu-data-l10n-id="appmenu-help-share-ideas"/> <menuitem id="helpSafeMode" + hidden="true" data-l10n-id="menu-help-enter-troubleshoot-mode2" appmenu-data-l10n-id="appmenu-help-enter-troubleshoot-mode2"/> <menuitem id="troubleShooting" + hidden="true" data-l10n-id="menu-help-more-troubleshooting-info" appmenu-data-l10n-id="appmenu-help-more-troubleshooting-info"/> <menuitem id="help_reportSiteIssue" @@ -456,6 +472,7 @@ appmenu-data-l10n-id="appmenu-help-not-deceptive" hidden="true"/> <menuitem id="helpSwitchDevice" + hidden="true" data-l10n-id="menu-help-switch-device" appmenu-data-l10n-id="appmenu-help-switch-device"/> <menuseparator id="aboutSeparator"/> diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 62b3665394a8256ebedf88a8f10bb6766977cf57..c30c8d41a532714746a039addee77facbf2c0bc0 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -1438,6 +1438,10 @@ var BookmarkingUI = { newTabURL, "about:home", "chrome://browser/content/blanktab.html", + // Add the "about:tor" uri. See tor-browser#41717. + // NOTE: "about:newtab", "about:welcome", "about:home" and + // "about:privatebrowsing" can also redirect to "about:tor". + "about:tor", ]; if (PrivateBrowsingUtils.isWindowPrivate(window)) { newTabURLs.push("about:privatebrowsing"); diff --git a/browser/base/content/browser-safebrowsing.js b/browser/base/content/browser-safebrowsing.js index 323887f0c59cdae423fc1669eae0ba1e7e0cdb24..bc7bcac2adb19e50d541b93a848209910d3a4831 100644 --- a/browser/base/content/browser-safebrowsing.js +++ b/browser/base/content/browser-safebrowsing.js @@ -7,6 +7,13 @@ var gSafeBrowsing = { setReportPhishingMenu() { + // tor-browser#18905: hide these menu entries + if ( + !Services.prefs.getBoolPref("browser.safebrowsing.phishing.enabled", true) + ) { + return; + } + // In order to detect whether or not we're at the phishing warning // page, we have to check the documentURI instead of the currentURI. // This is because when the DocShell loads an error page, the diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc index 9c085b22b3d46708ea6b7b457705df299a46c82f..50573515fd0e209c17b50e39eb96df815962ff72 100644 --- a/browser/base/content/browser-sets.inc +++ b/browser/base/content/browser-sets.inc @@ -387,4 +387,6 @@ modifiers="accel,alt" internal="true"/> #endif + <key id="new-identity-key" modifiers="accel shift" key="U" oncommand="NewIdentityButton.onCommand(event)"/> + <key id="new-circuit-key" modifiers="accel shift" key="L" oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser.selectedBrowser)"/> </keyset> diff --git a/browser/base/content/browser-siteIdentity.js b/browser/base/content/browser-siteIdentity.js index d0ba6ac670f43e451f3f3c35d0690a9a9deffff9..1a62254c0a7f8ef96c84224af12f684ca383cd29 100644 --- a/browser/base/content/browser-siteIdentity.js +++ b/browser/base/content/browser-siteIdentity.js @@ -150,6 +150,12 @@ var gIdentityHandler = { ); }, + get _uriIsOnionHost() { + return this._uriHasHost + ? this._uri.host.toLowerCase().endsWith(".onion") + : false; + }, + get _isAboutNetErrorPage() { let { documentURI } = gBrowser.selectedBrowser; return documentURI?.scheme == "about" && documentURI.filePath == "neterror"; @@ -811,7 +817,15 @@ var gIdentityHandler = { host = this._uri.specIgnoringRef; } - return host; + // For tor browser we want to shorten onion addresses for the site identity + // panel (gIdentityHandler) to match the circuit display and the onion + // authorization panel. + // See tor-browser#42091 and tor-browser#41600. + // This will also shorten addresses for other consumers of this method, + // which includes the permissions panel (gPermissionPanel) and the + // protections panel (gProtectionsHandler), although the latter is hidden in + // tor browser. + return TorUIUtils.shortenOnionAddress(host); }, /** @@ -822,9 +836,9 @@ var gIdentityHandler = { get pointerlockFsWarningClassName() { // Note that the fullscreen warning does not handle _isSecureInternalUI. if (this._uriHasHost && this._isSecureConnection) { - return "verifiedDomain"; + return this._uriIsOnionHost ? "onionVerifiedDomain" : "verifiedDomain"; } - return "unknownIdentity"; + return this._uriIsOnionHost ? "onionUnknownIdentity" : "unknownIdentity"; }, /** @@ -832,7 +846,11 @@ var gIdentityHandler = { * built-in (returns false) or imported (returns true). */ _hasCustomRoot() { - return !this._secInfo.isBuiltCertChainRootBuiltInRoot; + // HTTP Onion Sites are considered secure, but will not not have _secInfo. + // FIXME: Self-signed HTTPS Onion Sites are also deemed secure, but this + // function will return true for them, creating a warning about an exception + // that cannot be actually removed. + return !!this._secInfo && !this._secInfo.isBuiltCertChainRootBuiltInRoot; }, /** @@ -874,11 +892,17 @@ var gIdentityHandler = { "identity.extension.label", [extensionName] ); - } else if (this._uriHasHost && this._isSecureConnection) { + } else if (this._uriHasHost && this._isSecureConnection && this._secInfo) { // This is a secure connection. - this._identityBox.className = "verifiedDomain"; + // _isSecureConnection implicitly includes onion services, which may not have an SSL certificate + const uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.className = uriIsOnionHost + ? "onionVerifiedDomain" + : "verifiedDomain"; if (this._isMixedActiveContentBlocked) { - this._identityBox.classList.add("mixedActiveBlocked"); + this._identityBox.classList.add( + uriIsOnionHost ? "onionMixedActiveBlocked" : "mixedActiveBlocked" + ); } if (!this._isCertUserOverridden) { // It's a normal cert, verifier is the CA Org. @@ -889,10 +913,15 @@ var gIdentityHandler = { } } else if (this._isBrokenConnection) { // This is a secure connection, but something is wrong. - this._identityBox.className = "unknownIdentity"; + const uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.className = uriIsOnionHost + ? "onionUnknownIdentity" + : "unknownIdentity"; if (this._isMixedActiveContentLoaded) { - this._identityBox.classList.add("mixedActiveContent"); + this._identityBox.classList.add( + uriIsOnionHost ? "onionMixedActiveContent" : "mixedActiveContent" + ); if ( UrlbarPrefs.getScotchBonnetPref("trimHttps") && warnTextOnInsecure @@ -902,11 +931,16 @@ var gIdentityHandler = { } } else if (this._isMixedActiveContentBlocked) { this._identityBox.classList.add( - "mixedDisplayContentLoadedActiveBlocked" + uriIsOnionHost + ? "onionMixedDisplayContentLoadedActiveBlocked" + : "mixedDisplayContentLoadedActiveBlocked" ); } else if (this._isMixedPassiveContentLoaded) { - this._identityBox.classList.add("mixedDisplayContent"); + this._identityBox.classList.add( + uriIsOnionHost ? "onionMixedDisplayContent" : "mixedDisplayContent" + ); } else { + // TODO: ignore weak https cipher for onionsites? this._identityBox.classList.add("weakCipher"); } } else if (this._isCertErrorPage) { @@ -926,6 +960,8 @@ var gIdentityHandler = { // Network errors, blocked pages, and pages associated // with another page get a more neutral icon this._identityBox.className = "unknownIdentity"; + } else if (this._uriIsOnionHost) { + this._identityBox.className = "onionUnknownIdentity"; } else if (this._isPotentiallyTrustworthy) { // This is a local resource (and shouldn't be marked insecure). this._identityBox.className = "localResource"; @@ -941,7 +977,10 @@ var gIdentityHandler = { } if (this._isCertUserOverridden) { - this._identityBox.classList.add("certUserOverridden"); + const uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.classList.add( + uriIsOnionHost ? "onionCertUserOverridden" : "certUserOverridden" + ); // Cert is trusted because of a security exception, verifier is a special string. tooltip = gNavigatorBundle.getString( "identity.identified.verified_by_you" diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 0be3b2c47fb50ab95fa084142cad9ca021244179..9f577bbd22e51b229a72941a7f012e5338c8a20d 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -49,6 +49,7 @@ ChromeUtils.defineESModuleGetters(this, { NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", nsContextMenu: "chrome://browser/content/nsContextMenu.sys.mjs", + OnionLocationParent: "resource:///modules/OnionLocationParent.sys.mjs", OpenInTabsUtils: "resource:///modules/OpenInTabsUtils.sys.mjs", PageActions: "resource:///modules/PageActions.sys.mjs", PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs", @@ -67,13 +68,12 @@ ChromeUtils.defineESModuleGetters(this, { ResetPBMPanel: "resource:///modules/ResetPBMPanel.sys.mjs", SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs", Sanitizer: "resource:///modules/Sanitizer.sys.mjs", - SaveToPocket: "chrome://pocket/content/SaveToPocket.sys.mjs", ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs", SearchUIUtils: "resource:///modules/SearchUIUtils.sys.mjs", SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs", SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs", - ShoppingSidebarParent: "resource:///actors/ShoppingSidebarParent.sys.mjs", - ShoppingSidebarManager: "resource:///actors/ShoppingSidebarParent.sys.mjs", + // Removed ShoppingSidebarParent and ShoppingSidebarManager. + // tor-browser#42831. ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs", SiteDataManager: "resource:///modules/SiteDataManager.sys.mjs", SitePermissions: "resource:///modules/SitePermissions.sys.mjs", @@ -84,6 +84,11 @@ ChromeUtils.defineESModuleGetters(this, { "resource:///modules/firefox-view-tabs-setup-manager.sys.mjs", TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs", ToolbarContextMenu: "resource:///modules/ToolbarContextMenu.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", + TorConnectStage: "resource://gre/modules/TorConnect.sys.mjs", + TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs", + TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", + TorUIUtils: "resource:///modules/TorUIUtils.sys.mjs", TranslationsParent: "resource://gre/actors/TranslationsParent.sys.mjs", UITour: "resource:///modules/UITour.sys.mjs", UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs", @@ -254,6 +259,21 @@ XPCOMUtils.defineLazyScriptGetter( ["DownloadsButton", "DownloadsIndicatorView"], "chrome://browser/content/downloads/indicator.js" ); +XPCOMUtils.defineLazyScriptGetter( + this, + ["SecurityLevelButton"], + "chrome://browser/content/securitylevel/securityLevel.js" +); +XPCOMUtils.defineLazyScriptGetter( + this, + ["NewIdentityButton"], + "chrome://browser/content/newidentity.js" +); +XPCOMUtils.defineLazyScriptGetter( + this, + ["OnionAuthPrompt"], + "chrome://browser/content/onionservices/authPrompt.js" +); XPCOMUtils.defineLazyScriptGetter( this, "gEditItemOverlay", @@ -294,6 +314,21 @@ XPCOMUtils.defineLazyScriptGetter( "gProfiles", "chrome://browser/content/browser-profiles.js" ); +XPCOMUtils.defineLazyScriptGetter( + this, + ["gTorConnectUrlbarButton"], + "chrome://global/content/torconnect/torConnectUrlbarButton.js" +); +XPCOMUtils.defineLazyScriptGetter( + this, + ["gTorConnectTitlebarStatus"], + "chrome://global/content/torconnect/torConnectTitlebarStatus.js" +); +XPCOMUtils.defineLazyScriptGetter( + this, + ["gTorCircuitPanel"], + "chrome://browser/content/torCircuitPanel.js" +); // lazy service getters @@ -711,6 +746,7 @@ async function gLazyFindCommand(cmd, ...args) { } var gPageIcons = { + "about:tor": "chrome://branding/content/icon32.png", "about:home": "chrome://branding/content/icon32.png", "about:newtab": "chrome://branding/content/icon32.png", "about:welcome": "chrome://branding/content/icon32.png", @@ -718,6 +754,8 @@ var gPageIcons = { }; var gInitialPages = [ + "about:tor", + "about:torconnect", "about:blank", "about:home", "about:firefoxview", @@ -3391,8 +3429,6 @@ var XULBrowserWindow = { SafeBrowsingNotificationBox.onLocationChange(aLocationURI); - SaveToPocket.onLocationChange(window); - UrlbarProviderSearchTips.onLocationChange( window, aLocationURI, @@ -3430,6 +3466,7 @@ var XULBrowserWindow = { CFRPageActions.updatePageActions(gBrowser.selectedBrowser); AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser); + OnionLocationParent.updateOnionLocationBadge(gBrowser.selectedBrowser); TranslationsParent.onLocationChange(gBrowser.selectedBrowser); PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser); @@ -3999,6 +4036,16 @@ var CombinedStopReload = { var TabsProgressListener = { onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { + // Clear OnionLocation UI + if ( + aStateFlags & Ci.nsIWebProgressListener.STATE_START && + aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK && + aRequest && + aWebProgress.isTopLevel + ) { + OnionLocationParent.onStateChange(aBrowser); + } + // Collect telemetry data about tab load times. if ( aWebProgress.isTopLevel && @@ -4060,10 +4107,6 @@ var TabsProgressListener = { return; } - // Some shops use pushState to move between individual products, so - // the shopping code needs to be told about all of these. - ShoppingSidebarManager.onLocationChange(aBrowser, aLocationURI, aFlags); - // Filter out location changes caused by anchor navigation // or history.push/pop/replaceState. if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { @@ -7501,6 +7544,11 @@ var FirefoxViewHandler = { } }, openTab(section) { + if (AppConstants.BASE_BROWSER_VERSION) { + // about:firefoxview is disabled. tor-browser#42037. + return; + } + if (!CustomizableUI.getPlacementOfWidget(this.BUTTON_ID)) { CustomizableUI.addWidgetToArea( this.BUTTON_ID, diff --git a/browser/base/content/browser.js.globals b/browser/base/content/browser.js.globals index 3c08424945429f0af8ddd2bd8e4c7780b6b9e6a6..6a6a67935c3b8dd8c5dcf0cac711d68fa14221a3 100644 --- a/browser/base/content/browser.js.globals +++ b/browser/base/content/browser.js.globals @@ -153,13 +153,10 @@ "ResetPBMPanel", "SafeBrowsing", "Sanitizer", - "SaveToPocket", "ScreenshotsUtils", "SearchUIUtils", "SessionStartup", "SessionStore", - "ShoppingSidebarParent", - "ShoppingSidebarManager", "ShortcutUtils", "SiteDataManager", "SitePermissions", @@ -269,5 +266,17 @@ "gFindBarInitialized", "gFindBarPromise", "BrowserSearch", - "SelectableProfileService" + "SelectableProfileService", + "SecurityLevelButton", + "NewIdentityButton", + "TorUIUtils", + "TorDomainIsolator", + "gTorCircuitPanel", + "TorConnect", + "TorConnectStage", + "TorConnectTopics", + "gTorConnectUrlbarButton", + "gTorConnectTitlebarStatus", + "OnionAuthPrompt", + "OnionLocationParent" ] diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml index e6bc6b38c545380886828b7a3a1cf03d7c7216de..93a503da4771adffef150d1f38668523e16be815 100644 --- a/browser/base/content/browser.xhtml +++ b/browser/base/content/browser.xhtml @@ -58,6 +58,16 @@ <link rel="stylesheet" href="chrome://browser/skin/translations/panel.css" /> <link rel="stylesheet" href="chrome://browser/skin/places/tree-icons.css" /> <link rel="stylesheet" href="chrome://browser/skin/places/editBookmark.css" /> + <link + rel="stylesheet" + href="chrome://global/content/resistfingerprinting/letterboxing.css" + /> + + <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelPanel.css" /> + <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelButton.css" /> + <link rel="stylesheet" href="chrome://browser/content/torCircuitPanel.css" /> + <link rel="stylesheet" href="chrome://global/content/torconnect/torConnectTitlebarStatus.css" /> + <link rel="stylesheet" href="chrome://browser/content/onionservices/onionservices.css" /> <link rel="localization" href="branding/brand.ftl"/> <link rel="localization" href="browser/allTabsMenu.ftl"/> @@ -86,6 +96,8 @@ <link rel="localization" href="toolkit/global/contextual-identity.ftl"/> <link rel="localization" href="toolkit/global/textActions.ftl"/> <link rel="localization" href="toolkit/printing/printUI.ftl"/> + <link rel="localization" href="toolkit/global/base-browser.ftl"/> + <link rel="localization" href="toolkit/global/tor-browser.ftl"/> <!-- Untranslated FTL files --> <link rel="localization" href="preview/credentialChooser.ftl" /> <link rel="localization" href="preview/enUS-searchFeatures.ftl" /> @@ -127,7 +139,8 @@ Services.scriptloader.loadSubScript("chrome://browser/content/places/places-menupopup.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this); - Services.scriptloader.loadSubScript("chrome://browser/content/shopping/shopping-sidebar.js", this); + // Removed shopping-sidebar.js. tor-browser#42831. + Services.scriptloader.loadSubScript("chrome://browser/content/languageNotification.js", this); window.onload = gBrowserInit.onLoad.bind(gBrowserInit); window.onunload = gBrowserInit.onUnload.bind(gBrowserInit); diff --git a/browser/base/content/default-bookmarks.html b/browser/base/content/default-bookmarks.html index cbed7b2ccc693466f68b072f44281a2e123f6838..67885db55c556f5cc73acf887d7a2e5e40398fcc 100644 --- a/browser/base/content/default-bookmarks.html +++ b/browser/base/content/default-bookmarks.html @@ -1,56 +1,27 @@ #filter substitution -#define mozilla_icon data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E %3Cpath d='M0 0h16v16H0z'/%3E %3Cpath d='M13.994 10.356H15V12h-3.171V7.741c0-1.308-.435-1.81-1.29-1.81-1.04 0-1.46.737-1.46 1.8v2.63h1.006V12H6.918V7.741c0-1.308-.435-1.81-1.291-1.81-1.039 0-1.459.737-1.459 1.8v2.63h1.441V12H1v-1.644h1.006V6.079H1V4.435h3.168v1.139a2.507 2.507 0 0 1 2.3-1.29A2.452 2.452 0 0 1 8.931 5.91 2.535 2.535 0 0 1 11.4 4.284 2.448 2.448 0 0 1 14 6.9v3.458z' fill='%23fff'/%3E %3C/svg%3E +#define onion_icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8AOwAUDSQAD2QRAA2ZDQAFyw4ABssjAAuQKAAPZAAcAAn///8A////AP///wD///8A////AP///wD///8AIwAMFmtcZP89NDr/TkRJ/ykhJ/8kIij/KAUV/yoAD/9CHy3/EwAMKf///wD///8A////AP///wD///8AHAAACUw4Qf98cnn//Pz8/9TM1/9dPl3/IBYg/y0fKf9bCzT/NQAX/zoeKP8AAAAE////AP///wD///8A////ACgADSYvJSv/2d/h/+Hd4v9sP17/xsHN/1A3Tf8lGSD/YxM9/2sVRP80DB7/Ty44bv///wD///8A////AP///wAwAAUwSERJ/+jx8v/Xx9P/YDVS/7y+zP9BKEH/LiUs/2ceRf91JFT/Ngke/yYACVj///8A////AP///wD///8ANwAJHFNNUv/h6+z/9PD0/31Zev+GeJL/Rj5X/zAjK/9zL1f/ezFd/y0NGv8mAA42////AP///wD///8A////AFUAAAMVAAqge4GF//v8/P/x7/L/hHCN/1NVbf87KDP/g0Fq/14pSP9PLz3/AAAABP///wD///8A////AP///wD///8AOQAcCQcACpWcoqX/+/39/7PJ0v9oeYn/Ry89/5BVff8+IC//IAANKP///wD///8A////AP///wD///8A////AP///wBGABcLCgAHmXFucv/G4eb/SUhS/109UP9WOkf/WEJIhf///wD///8A////AP///wD///8A////AP///wD///8A////AFUAKgYZAAiGRkNJ/0IyO/9XQkj/KQAIHzMAAAX///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AMwANFFxMU/9WQEr/PgAMKf///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AD4AFyFWUln/OW5Y/wCobmQAqnEJ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wCZAGYFQpF3hQteOv8AiVGpGb2BbP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAD//wMAjF2oB35N8gClYpcAuHEk////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AANOEHQCvdn8ArGipALJshwC4ezb///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wAA/78IANmXNgDFgyMAv4AM////AP///wD///8A//8AAPAPAADgBwAA4AcAAOAHAADgBwAA8AcAAPgPAAD8HwAA/j8AAP5/AAD+fwAA/38AAP//AAD//wAA//8AAA== -#define firefox_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHY0lEQVR4Aa3VA5RrSdfG8f+uOidJp/umczm2ffFhbNvG9722bdv22LZt+3I81+04B1XvfpPmWHut3yk06smus1Z4L8uXDv6MHzpowA8eWFS8FaY9eU+cCvxaFfF8W/FWGDy8a6n7DM7/H96DR3ldu0MVb8a0J+9CI1qXJP11a+79GOdP1f11FW/EtCfvQpx8mziFxMHEEEV1KYkrKl6Pea1Nbnrs/7hz7q2KUQsqRcUE/eV1acb/pyFQ7b9N3fguzNTxVsXrMa/avFgPb6SnukY8W6EgXvszrszjivH08F0VLZFK0rbUgRt9H2aS+lORznUxnTMV45kJG6fNPZSGnEodTJwUFGbphqdSll/H/SxWjEc92kYxSoO0uzEcwo90g/9rlKpHpCmX491MxQgzuvjtE0UieyqxhYZA3UGp8CjUtSMR2YrkFdf+/szi9X88+zM3/uncSx/81/f+7/HzPsu8q09i8MUNcCUHUTImceAAL+RC+UW1nMzHuUvxSVGBCloTgMT+GuOLipaGyg/OpLuE/jVI58wHb/zsdxD5tBVbDMQwOPe/8UDqHYuuPJjCZnP5nw/+mfyUPhADRtkAaIfosum23klBxH8b+KzCfuczG8IPXi4C5yHQwvDoPYhCBSkz1n9y1+WLd8xFzVUxxmIRjBIBVHXFZF58aEtW3exxsp0V8Aac8gpBnGQBRNymkP4VXKPdgdj8H2JB/DgMVwreATFhdoCdj/wY8x7+GM8/djyJ81hlnCPTUWfHb/0QlyRUelalEPcCHswIQARJPd64ohh/KHBagPcQB7sggHgIVHcM0wUyWWUAoNaEuobI9bP1dj9lw1nnMvehj/LS0wdinYO4wM1f/h6z3v9n1t3pTnAWBj04ZQA7LFROwMsu7QCpgcjuCh4Asg5Wa0ImgNDqqHTOtDyIgPPKkZ/cZOstzmT+Nw4jcA5JBO9SHjzzWKZt8CRd03ohD/RZALCigIwHawBmKgKSVoAiAi2VDCzsgo0bYB04lSojEAaQDyETsmTZf3PPdZ+irvMgTTF4SAVX7+SRC/dj5/f/C6D9d5UQLBAIFBJILIhtB1g2a8uZq+1+LwiAV8CSTujPwqoRbJjCJMdAeRVue+j/WLh4T2I3jcCEhN4ShmDFYR2IAXC8OHdDaMYAYBxU82AFAgPShHoejAEgUEViy2h5UbS9LLBajf5oMr866wc0wlWQvEEyNQKbIcSSwZBNIfAO41NQ9ZXd0IgBAQdUDAQWpjQhcfi6gCgguDtTm3vIUBdhdwUA/Pggqmy49/n/pr/q8ZMq4DziEwI0QOtpiT1kXUqQRqC8ohaDy0BqoGzxOUE6q9DwMBiOvtzm5OLi3migAFEwpjnOCzmKhZXUkyr1uEwtLqky1aStNk4jqhFFDVZb6ykYMjBodQxw5RAKZUgSqAq+YmmWzFxF0P8L61Z8pHhf5/S+bfHQJm1OLcuzw4YPcWH3/qysTcebFHyESTOkhLjUokt8M8VFCVYDbLXhvdCfARfiG3lkykDr2qhbXJTRUZBAngMwootGI3tbrbcIsR3ugp3Yhbun89l9/ko+qCDVGpQruHKJqDakBmnq2KyXaDZKrDX1KWau+ij0ZqAvgwR1JFuFmihwPTkdDQN9co3C6IMnwujs0sppELcOV+NHVc2wzv2eb+74J6ZP6kGazeEgZZJqiaRWJo6qbDb5MU7c4ixYmYUhC7YJaQxVgYrgSxa3sgNftdww31+usFuvuykfWDzU/4HytL0llTVz+SbiAScTryKxFFc6dlnnQVZP+wEo2grT7ACb5V7g2BnXsVfxHsLEgfGQTYb/1kJqWpKV3VDLM1iXi/a8PDrtqmecl451DwLg8oG1DtnMmcsKq/bQ1V3BmBTsfzgIfHucwINxICivADt8eADkBLJGtcc0ydHsmU7QEXBFfzwTeFwRnLFtDoBD7nv5+vv61v2XXzHlfR7oKtQxLkFcCqkDK8qMHdIex4gSMxaoKZBtS8lQ18NtJsPSmv/Nyfc3nma4RjsA8Jnq1HU+WC9cY01z865pJQrdDcQkrW6IpGOfun3oxLnw6m/SEBIyVFbOIMhmiXJy35oL+vYDBhkuGxY3YaTuy9TLA+Jv2inu2j2ph9NrTUMmCyIGjwEnyiCtUaUWnGlLR1hIlM6rKwpUX5qBiTuI02Du94aqx8zJhEsVI4IPduUZV+7vDC0CDv9GdeolUjObL18ckutqMKkQkc2kiFHOITLCwyiUp1bNUhuYRFrrxPoMzdDM/XbUf/gZvvYsozX+Cl5d5vh690afrk3+0hR4XyoxqYmQICaTSwjClI6cA3EIvhWi0QiIm6rRgaQh1ikfsMK43/xv8YWfASuUe6sBAIzqPmNwjb1nJdnP5PDbOpPgJMXjWhDAC4JgvEWUaQkoib/o/NzQb37S1fP0+Dt/6wHGKqe6v1yZvuG+zc69p3m7d4dnW8TjAaEdwmFKEcztkfSG67KVG346aeV8YEglincRYLQClVcdKsery6lI1VVNJbyF+jdp8gPG4E08mAAAAABJRU5ErkJggg== - -#define bugzilla_icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnYCL7J0pY9wwETY9kYEM9AAAAAEBAYAhVVVUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1bjTOS1Vb/wAA2/8JEqT/Q0g8kQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJnMqoiJtJ/0haST/NEkp/yQnW/8AAPD8AAHY/RsgP/JZUI+GKitih4ObUEAAAAAAAAAAAAAAAAAAAAAAKnouwip5Lv9ooW//a6Jz/y9GIv8JBXb/AADO/gEBvf8AAK7/FRJp/z9BfP8iLGj1AAAAAAAAAAAAAAAAL4YzwiB0I/+UwJ3/bK+C/02eZ/9CTjz/DBa1/wABxf8BAOj/AACp/w8Oc/sJCv//EhCN9AAAAAAAAAAANJA6iC2MMv93tYL/TZ5U/3mzjP9NoWr/NEss/wYIU/8CBOn/ARCX/wwNqP0TD6X/Cgyex5qacDAAAAAAAAAAADKUN/ZirWj/d76R/0SgXf9Ln1P/eLSM/1mda/8rOkb/CQiD/wMQvf8UEnT/MTAt4P//MwUhZyN8AAAAAAAAAAAznDf5UqlZ/228jP9NqnD/Qp9c/0yiVP+Dv5b/VaVw/0VxXf9PZXD/S3pQ/y54Nf8jcCf/I2wn/wAAAAA0ozjIM6E4/zOeOP+Uz6z/XLR+/06scv9BoV3/TqZX/4XBmP9XqHP/hr6Z/yp+Lf8leSr1JXUqbQAAAAA3rTz7Nqo7/zWmOqM3oz7rUK1W/43Mpf9etYD/T61z/0KjXf9Rqln/msup/46/lf8pgy7/JFg6sAAAAAAAAAAAOK8+8jqvOiMAAAAAAAAAADSlOv85pT//kM6o/2K5hP9Ysnv/YLJ2/ziXPv8piS3/V6Ri/yZQQ9wAAAAAAAAAAAAAAAAAAAAAAAAAADetP0E2qzz/OKg98UWsS/+e1K3/pNe4/4XDjv8ojy3/T7df/5fIqv8sjTH/K4kw/yqFLv8AAAAAAAAAAAAAAAA4sT3xN7A8+QAAAAA4qz3yNag6/zSlOf80oTn/csJ+/6/jwv9fjHj/MmRMdQAAAAAAAAAAAAAAAAAAAAAAAAAAOrdA/zm0QHQAAAAAAAAAADasO/k2qTvuRX5lpjqGT/gznDr/O3FXigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq9QiMAAAAAAAAAAAAAAAA4sj7/Nq09s0uOaSI1qTplM6U68wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrc//zu0P0EAAAAAOK4+UjWsPPgAAAAAAAAAAAAAAAAAAAAA/48AAP8HAAD4AQAA8AAAAOAAAADAAQAAwAMAAMAAAACAAwAAAAMAAHADAADwAAAA5AcAAO4HAAD+bwAA/u8AAA== - -#define mdn_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAABgElEQVR4AWPouPiRpmjUAjgatSBj+aG0OVuyVhymsgWl2y475zXySikwwIC4lpFDVk3avG0BrXP9mmeV7bhCvgXuxW3M7JwMeAGfpByZFpjHFzAQB2KmrSfZAtuMKgaiAZ+MUuLc7SRY4FbYwkA60HAJiJm8uubQAwIWeJV1MlAAOAREHDJrcFqQMG+ngIK6oKyykLwqAyMjeXZwiUjgtKD+yGMIwyGzmoGBTAs4hcXrgObgi4OiVkpCiUtYov7YU5wW1B194t0ww69ldvjktYouwWRYIGdkQ1Q+iJ28hp2Xn7B5zKzIPAlNw6S52wlbkL3mJJecOq+CBqeIJC6TjUJTMlcdz9lwLmriSuPgJBVbj/D+5SSXRequQVhNN4nIoEJhV77jKgs7B6bprJw85XtuU8GCpNlbSS3gSA4ii4QiTAvElDWpWeH41kxg5eZDSypUrtFKd1zTcA1EpHRDS5rUyQEts+VN7JjYOGR0TWhY6RdsOhc/Y9NoswUJjVoAAE+h555Rgcg2AAAAAElFTkSuQmCC - -#define addon_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABOFBMVEUAAAAAzdwAydcAyNgA//8AzOYAydcAyNgAyNgA2NgAytoAzNkAytgAydgA29sA0egAyNgAyNgA//8AyNgAydgA//8Ay9cAydcAytkAz90Ay9gA1eoAydgAytsAyNgAytgAydkAydgAydgAyNgAydgAyNcAy9oAydgA//8AytsAy9kAytkAyNgAydgAydkAy9kAzP8AydgAydgAydgAz98AzN0AyNcAyNsAydcAydgAydgAydcAytgAytcAydcAydcAytcAydcAyNcAydcAy9gAztgAydcAydgAzOAAydcAyNgAyNgAytwAyNcAyNgAy9wAyNcAyNcAyNgAydgAyNcAydcAydgA0uEAydkAyNgAyeQA4+MAyNgAydkAzN0AyNsA1f8AyNgAydgAydcA1eMAydgAydcAyNdj6PGJAAAAZ3RSTlMAJFpBAQqm8qwNPiiPygcLv8QEw5cDQMA1JU4MwiuDbl/+6+m4+0XLAj9KePz9cjYFvervEA/IDsfFr+xcgeaOYIDo+ica1OMZ9bXlHe73LM3M35itxs8Rf5ATCbFeHjgGttC5ErzO3WvwaAAAAWxJREFUOMt9kudCwkAQhFcITQWCoaggiBqxoaixYUVsYMMGCmLXff838LIXCJAL84fvmCHsTg4AYMDhlIDkcnu8Po4w6BjiIA0joj+gY1BmGKLEiMIwHNFR9xGjuh8jpMQoYZjRGBGOA8QTHDEUB4hynABwcEqCT8GW2DNSnCYBnJzSoSk0NT2jcphlM/rRXpk5NkRgfmFxSWBml6MrOWNlWBUEEmDKtyYIrGttP66gSP4Nww8mUKzNLd5/zHaJbb1Tl9xnzR2WcGM/5QE8BLvJvf0Dc4HDo8IxUVECL5Vywv7s9Mzwz/WLcFHSsWy8w0sa9+qa/JtbOlUY3mnGLbjnCz9Q4JEfnhCrNb5nXi3w754p8MIPKVWpt6psGJ+vFJBbBUO3GlozzYdsSmCV1NlntiTnegNvPQ29Wx7h7fKrEUvg47PD/6oLpgh8m7//AZEav4b/J/bbb75SAzvR3crY+6y8fLGsQV9ZSvwHF4LQIhDjT+8AAAAASUVORK5CYII= <!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <!DOCTYPE NETSCAPE-Bookmark-file-1> -<html> -<head> - <meta charset="UTF-8"> - <!-- These localization links are not automatically applied to any XHR - response body and must be applied manually as well. They are included - so that viewing the file directly shows the results. --> - <link rel="localization" href="branding/brand.ftl"/> - <link rel="localization" href="browser/profile/default-bookmarks.ftl"/> - <title data-l10n-id="default-bookmarks-title">default-bookmarks-title</title> -</head> -<body> -<h1 data-l10n-id="default-bookmarks-heading">default-bookmarks-heading</h1> + <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> + <TITLE>Bookmarks</TITLE> + <H1>Bookmarks</H1> -<dl><p> -#ifndef NIGHTLY_BUILD - <dt><h3 data-l10n-id="default-bookmarks-firefox-heading">default-bookmarks-firefox-heading</h3></dt> - <dl><p> - <dt><a href="https://support.mozilla.org/products/firefox" icon="@firefox_icon@" data-l10n-id="default-bookmarks-firefox-get-help">default-bookmarks-firefox-get-help</a></dt> - <dt><a href="https://support.mozilla.org/kb/customize-firefox-controls-buttons-and-toolbars?utm_source=firefox-browser&utm_medium=default-bookmarks&utm_campaign=customize" icon="@firefox_icon@" data-l10n-id="default-bookmarks-firefox-customize">default-bookmarks-firefox-customize</a></dt> -#ifdef EARLY_BETA_OR_EARLIER - <dt><a href="https://www.mozilla.org/contribute/?utm_medium=firefox-desktop&utm_source=bookmarks-toolbar&utm_campaign=new-users-beta&utm_content=-global" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-community">default-bookmarks-firefox-community</a></dt> -#else - <dt><a href="https://www.mozilla.org/contribute/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-community">default-bookmarks-firefox-community</a></dt> -#endif - <dt><a href="https://www.mozilla.org/about/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-about">default-bookmarks-firefox-about</a></dt> - </dl><p> -#else - <dt><h3 data-l10n-id="default-bookmarks-nightly-heading">default-bookmarks-nightly-heading</h3></dt> - <dl><p> - <dt><a href="https://www.mozilla.org/contribute/?utm_medium=firefox-desktop&utm_source=bookmarks-toolbar&utm_campaign=new-users-nightly&utm_content=-global" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-community">default-bookmarks-firefox-community</a></dt> - <dt><a href="https://blog.nightly.mozilla.org/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-nightly-blog">default-bookmarks-nightly-blog</a></dt> - <dt><a href="https://bugzilla.mozilla.org/" icon="@bugzilla_icon@" shortcuturl="bz" data-l10n-id="default-bookmarks-bugzilla">default-bookmarks-bugzilla</a></dt> - <dt><a href="https://developer.mozilla.org/" icon="@mdn_icon@" shortcuturl="mdn" data-l10n-id="default-bookmarks-mdn">default-bookmarks-mdn</a></dt> - <dt><a href="https://addons.mozilla.org/firefox/addon/nightly-tester-tools/" icon="@addon_icon@" data-l10n-id="default-bookmarks-nightly-tester-tools">default-bookmarks-nightly-tester-tools</a></dt> - <dt><a href="about:crashes" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-crashes">default-bookmarks-crashes</a></dt> - <dt><a href="https://planet.mozilla.org/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-planet">default-bookmarks-planet</a></dt> - </dl><p> -#endif -</dl> -</body> -</html> + <DL><p> + <DT><H3>Tor Project Bookmarks</H3> + <DD>Helpful bookmarks from the Tor Project + <DL><p> + <DT><A HREF="http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/" ICON="@onion_icon@">Learn more about Tor</A> + <DT><A HREF="http://pzhdfe7jraknpj2qgu5cz2u3i4deuyfwmonvzu5i3nyw4t4bmg7o5pad.onion/" ICON="@onion_icon@">The Tor Blog</A> + <DT><A HREF="http://rzuwtpc4wb3xdzrj3yeajsvm3fkq4vbeubm2tdxaqruzzzgs5dwemlad.onion/" ICON="@onion_icon@">Tor Support portal - Get help</A> + <DT><A HREF="about:manual" ICON="@onion_icon@">Tor Browser Manual</A> + <DT><A HREF="http://xmrhfasfg5suueegrnc4gsgyi2tyclcy5oz7f5drnrodmdtob6t2ioyd.onion/" ICON="@onion_icon@">Tor Community - Get Involved</A> + <DT><A HREF="http://v236xhqtyullodhf26szyjepvkbv6iitrhjgrqj4avaoukebkk6n6syd.onion/" ICON="@onion_icon@">Tor Project Forum</A></DT> + <DT><A HREF="https://donate.torproject.org/" ICON="@onion_icon@">Donate - Keep Tor Strong</A> + <DT><A HREF="http://yq5jjvr7drkjrelzhut7kgclfuro65jjlivyzfmxiq2kyv5lickrl4qd.onion/" ICON="@onion_icon@">Circumvent Censorship, Get Bridges</A> + </DL><p> + <HR> + </DL><p> diff --git a/browser/base/content/languageNotification.js b/browser/base/content/languageNotification.js new file mode 100644 index 0000000000000000000000000000000000000000..2b5bfc2f857595e57eb951dbc1f86e207fca67c2 --- /dev/null +++ b/browser/base/content/languageNotification.js @@ -0,0 +1,67 @@ +"use strict"; + +// Show a prompt to suggest to the user that they can change the UI language. +// Show it only the first time, and then do not show it anymore +window.addEventListener("load", () => { + const PREF_NAME = "intl.language_notification.shown"; + + if (Services.prefs.getBoolPref(PREF_NAME, false)) { + return; + } + + // Already customized, we do not suggest to change it again... + if (Services.prefs.getCharPref("intl.locale.requested", "") !== "") { + // ... and we never show the notification, either + Services.prefs.setBoolPref(PREF_NAME, true); + return; + } + + // In sync with our changes on browser/components/preferences/main.js for + // tor-browser#41369 and tor-browser#41372. + const code = + Services.locale.appLocaleAsBCP47 === "ja-JP-macos" + ? "ja" + : Services.locale.appLocaleAsBCP47; + const language = Services.intl + .getLocaleDisplayNames(undefined, [code], { preferNative: true })[0] + .replace(/\s*\(.+\)$/g, ""); + + // We want to determine whether the current locale was chosen based on the + // system locales, in which case langauge negotiation returns a match, or + // whether it simply defaulted to en-US. + const matchingSystem = !!Services.locale.negotiateLanguages( + // Since intl.locale.requested is empty, we expect requestedLocales to match + // the user's system locales. + Services.locale.requestedLocales, + Services.locale.availableLocales + ).length; + const label = { + "l10n-id": matchingSystem + ? "language-notification-label-system" + : "language-notification-label", + "l10n-args": { language }, + }; + + const buttons = [ + { + "l10n-id": "language-notification-button", + callback() { + openPreferences("general-language"); + }, + }, + ]; + + gNotificationBox.appendNotification( + "language-notification", + { + label, + priority: gNotificationBox.PRIORITY_INFO_HIGH, + }, + buttons + ); + + // We do not wait for the user to either click on the button or dismiss the + // notification: after we have shown it once, we take for granted that the + // user has seen it and we never show it again. + Services.prefs.setBoolPref(PREF_NAME, true); +}); diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml index 51bca05946a8731cb52e99a20b09e1420cf5703d..65efb4c494bf145e7415ef83ee9f5752103db018 100644 --- a/browser/base/content/main-popupset.inc.xhtml +++ b/browser/base/content/main-popupset.inc.xhtml @@ -523,6 +523,9 @@ #include ../../components/translations/content/selectTranslationsPanel.inc.xhtml #include ../../components/translations/content/fullPageTranslationsPanel.inc.xhtml #include ../../components/tabbrowser/content/browser-allTabsMenu.inc.xhtml +#include ../../components/torcircuit/content/torCircuitPanel.inc.xhtml +#include ../../components/securitylevel/content/securityLevelPanel.inc.xhtml +#include ../../components/onionservices/content/authPopup.inc.xhtml <tooltip id="dynamic-shortcut-tooltip"/> diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml index 53f0f67bb53598be70be5f813542e5e5592819d2..0066e03e588ad59c484b350792f45ec36d23572d 100644 --- a/browser/base/content/navigator-toolbox.inc.xhtml +++ b/browser/base/content/navigator-toolbox.inc.xhtml @@ -114,6 +114,12 @@ oncommand="ContentAnalysis.showPanel(this, PanelUI);" class="toolbarbutton-1 content-analysis-indicator-icon"/> + <html:div id="tor-connect-titlebar-status" role="status"> + <html:img alt="" + src="chrome://global/content/torconnect/tor-not-connected-to-connected-animated.svg" /> + <html:span id="tor-connect-titlebar-status-label"></html:span> + </html:div> + #include titlebar-items.inc.xhtml </toolbar> @@ -191,6 +197,17 @@ collapsed="true"> <image id="remote-control-icon"/> </box> + <!-- We follow the surrounding code and use a + - <xul:box role="button"> rather than a more semantic + - <html:button>, <xul:button> or <xul:toolbarbutton> --> + <box id="tor-circuit-button" + role="button" + class="identity-box-button" + align="center" + data-l10n-id="tor-circuit-urlbar-button" + hidden="true"> + <image id="tor-circuit-button-icon"/> + </box> <box id="urlbar-search-button" class="chromeclass-toolbar-additional"/> <!-- Use onclick instead of normal popup= syntax since the popup @@ -286,6 +303,7 @@ data-l10n-id="urlbar-indexed-db-notification-anchor"/> <image id="password-notification-icon" class="notification-anchor-icon" role="button" data-l10n-id="urlbar-password-notification-anchor"/> +#include ../../components/onionservices/content/authNotificationIcon.inc.xhtml <image id="web-notifications-notification-icon" class="notification-anchor-icon desktop-notification-icon" role="button" data-l10n-id="urlbar-web-notification-anchor"/> <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon camera-icon" role="button" @@ -418,6 +436,8 @@ <image class="urlbar-icon" id="translations-button-circle-arrows" /> <html:span id="translations-button-locale" aria-hidden="true" /> </hbox> + <!-- #shopping-sidebar-button should remain hidden. + - tor-browser#42831. --> <hbox id="shopping-sidebar-button" class="urlbar-page-action" role="button" @@ -448,6 +468,15 @@ class="urlbar-icon"/> </hbox> </hbox> + + <hbox id="tor-connect-urlbar-button" + role="button" + class="tor-button tor-urlbar-button" + hidden="true"> + <label id="tor-connect-urlbar-button-label"/> + </hbox> + +#include ../../components/onionservices/content/onionlocation-urlbar.inc.xhtml </hbox> </hbox> <toolbartabstop/> @@ -486,6 +515,8 @@ </box> </toolbarbutton> +#include ../../components/securitylevel/content/securityLevelButton.inc.xhtml + <toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav" badged="true" delegatesanchor="true" @@ -617,6 +648,13 @@ ondragover="newWindowButtonObserver.onDragOver(event)" ondragenter="newWindowButtonObserver.onDragOver(event)"/> + <toolbarbutton id="new-identity-button" class="toolbarbutton-1 chromeclass-toolbar-additional" + data-l10n-id="toolbar-new-identity"/> + + <toolbarbutton id="new-circuit-button" class="toolbarbutton-1 chromeclass-toolbar-additional" + data-l10n-id="toolbar-new-tor-circuit" + oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser.selectedBrowser);"/> + <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional" observes="View:FullScreen" type="checkbox" diff --git a/browser/base/content/pageinfo/pageInfo.xhtml b/browser/base/content/pageinfo/pageInfo.xhtml index cca293c534f5197f83a60b6e44be2039f2eb5fb9..8d24cdf586f675c42bcd49a98d819f3271d5de52 100644 --- a/browser/base/content/pageinfo/pageInfo.xhtml +++ b/browser/base/content/pageinfo/pageInfo.xhtml @@ -27,6 +27,7 @@ <html:link rel="stylesheet" href="chrome://browser/skin/pageInfo.css" /> <html:link rel="localization" href="browser/pageInfo.ftl"/> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl"/> </linkset> #ifdef XP_MACOSX #include ../macWindow.inc.xhtml diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js index 080a390fcd1b643bb602f71f766ff630c5cbdd8d..5cdaf3bce51f6aa4d3df16754ac9baeab3d74202 100644 --- a/browser/base/content/pageinfo/security.js +++ b/browser/base/content/pageinfo/security.js @@ -57,6 +57,15 @@ var security = { (Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT | Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT); var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL; + let uriInformation = new URL(gDocInfo.documentURIObject.spec); + // If the Onion site could not be loaded, the view-source will be also be + // about:neterror. + if (uriInformation.protocol == "view-source:") { + uriInformation = new URL(uriInformation.pathname); + } + const isOnion = + ["http:", "https:"].includes(uriInformation.protocol) && + uriInformation.hostname.endsWith(".onion"); let retval = { cAName: "", @@ -66,6 +75,7 @@ var security = { isBroken, isMixed, isEV, + isOnion, cert: null, certificateTransparency: null, }; @@ -103,6 +113,7 @@ var security = { isBroken, isMixed, isEV, + isOnion, cert, certChain: certChainArray, certificateTransparency: undefined, @@ -344,13 +355,35 @@ async function securityOnLoad(uri, windowInfo) { } msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); } else if (info.encryptionStrength > 0) { - hdr = pkiBundle.getFormattedString( - "pageInfo_EncryptionWithBitsAndProtocol", - [info.encryptionAlgorithm, info.encryptionStrength + "", info.version] - ); + if (!info.isOnion) { + hdr = pkiBundle.getFormattedString( + "pageInfo_EncryptionWithBitsAndProtocol", + [info.encryptionAlgorithm, info.encryptionStrength + "", info.version] + ); + } else { + try { + hdr = await document.l10n.formatValue( + "page-info-onion-site-encryption-with-bits", + { + "encryption-type": info.encryptionAlgorithm, + "encryption-strength": info.encryptionStrength, + "encryption-version": info.version, + } + ); + } catch (err) { + hdr = + "Connection Encrypted (Onion Service, " + + info.encryptionAlgorithm + + ", " + + info.encryptionStrength + + " bit keys, " + + info.version + + ")"; + } + } msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1"); msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2"); - } else { + } else if (!info.isOnion) { hdr = pkiBundle.getString("pageInfo_NoEncryption"); if (windowInfo.hostName != null) { msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [ @@ -360,6 +393,13 @@ async function securityOnLoad(uri, windowInfo) { msg1 = pkiBundle.getString("pageInfo_Privacy_None4"); } msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); + } else { + hdr = await document.l10n.formatValue( + "page-info-onion-site-encryption-plain" + ); + + msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1"); + msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2"); } setText("security-technical-shortform", hdr); setText("security-technical-longform1", msg1); diff --git a/browser/base/content/popup-notifications.inc b/browser/base/content/popup-notifications.inc index 0dc756faf8d2cdebc54034f4002fa1dea75c4e64..3de62ab1d6dd49febb7eab35338da6d707542919 100644 --- a/browser/base/content/popup-notifications.inc +++ b/browser/base/content/popup-notifications.inc @@ -8,6 +8,15 @@ noautofocus="true" role="alert"/> + <!-- Shown when visiting first web page with an onion-available header. + - This allows us to add some extra content to the popup. + - See tor-browser#21952 and tor-browser#41341 --> + <popupnotification id="onion-location-notification" hidden="true"> + <popupnotificationcontent orient="vertical"> + <description id="onion-location-body-text"/> + </popupnotificationcontent> + </popupnotification> + <popupnotification id="webRTC-shareDevices-notification" hidden="true" descriptionid="webRTC-shareDevices-notification-description"> <popupnotificationcontent id="webRTC-selectCamera" orient="vertical"> diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index f5fd891c39b7a974810a507026c334bad51437ce..83d719c2d8c2c78c4ae17b79885f5d888b787e21 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -77,6 +77,7 @@ function isBlankPageURL(aURL) { return ( aURL == "about:blank" || aURL == "about:home" || + aURL == "about:tor" || aURL == BROWSER_NEW_TAB_URL || aURL == "chrome://browser/content/blanktab.html" ); @@ -557,6 +558,9 @@ function makeURLAbsolute(aBase, aUrl) { } function getHelpLinkURL(aHelpTopic) { + if (aHelpTopic === "firefox-help" || aHelpTopic === "firefox-osxkey") { + return "about:manual"; + } var url = Services.urlFormatter.formatURLPref("app.support.baseURL"); return url + aHelpTopic; } diff --git a/browser/base/jar.mn b/browser/base/jar.mn index d1a35b9d48599acb80fba626def9a8627062443d..b912ce341adfef99297cd94e60b9a149106d286d 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -8,6 +8,7 @@ browser.jar: * content/browser/aboutDialog.xhtml (content/aboutDialog.xhtml) content/browser/aboutDialog.js (content/aboutDialog.js) content/browser/aboutDialog.css (content/aboutDialog.css) + content/browser/aboutDialogTor.css (content/aboutDialogTor.css) content/browser/aboutRestartRequired.js (content/aboutRestartRequired.js) content/browser/aboutRestartRequired.xhtml (content/aboutRestartRequired.xhtml) content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml) @@ -100,5 +101,4 @@ browser.jar: content/browser/spotlight.js (content/spotlight.js) * content/browser/default-bookmarks.html (content/default-bookmarks.html) -# L10n resources and overrides. -% override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties + content/browser/languageNotification.js (content/languageNotification.js) diff --git a/browser/base/moz.build b/browser/base/moz.build index af862044d0ba7c0d151ee6a0edc8424ed840267b..ed89458983f0dd9766fa2a6575afd29868c88334 100644 --- a/browser/base/moz.build +++ b/browser/base/moz.build @@ -87,4 +87,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("windows", "gtk", "cocoa"): if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("windows", "gtk"): DEFINES["MENUBAR_CAN_AUTOHIDE"] = 1 +if CONFIG["BASE_BROWSER_UPDATE"]: + DEFINES["BASE_BROWSER_UPDATE"] = True + JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/branding-common.mozbuild b/browser/branding/branding-common.mozbuild index a38663a3dc1ebe0c0817945efc2f72018bc1b3c7..4fe646729eb5a6ab40db37351f387c30ff28fe1d 100644 --- a/browser/branding/branding-common.mozbuild +++ b/browser/branding/branding-common.mozbuild @@ -19,18 +19,17 @@ def FirefoxBranding(): if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": FINAL_TARGET_FILES[".."] += [ "firefox.VisualElementsManifest.xml", - "private_browsing.VisualElementsManifest.xml", ] FINAL_TARGET_FILES.VisualElements += [ - "PrivateBrowsing_150.png", - "PrivateBrowsing_70.png", "VisualElements_150.png", "VisualElements_70.png", ] elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": FINAL_TARGET_FILES.chrome.icons.default += [ + "content/about-logo.svg", "default128.png", "default16.png", + "default256.png", "default32.png", "default48.png", "default64.png", diff --git a/browser/branding/tb-alpha/VisualElements_150.png b/browser/branding/tb-alpha/VisualElements_150.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5b2d5ddff3f719a0bab6615e8d38135fef870a Binary files /dev/null and b/browser/branding/tb-alpha/VisualElements_150.png differ diff --git a/browser/branding/tb-alpha/VisualElements_70.png b/browser/branding/tb-alpha/VisualElements_70.png new file mode 100644 index 0000000000000000000000000000000000000000..61e37b211c2d3be120e4da6c28c99801918a1652 Binary files /dev/null and b/browser/branding/tb-alpha/VisualElements_70.png differ diff --git a/browser/branding/tb-alpha/configure.sh b/browser/branding/tb-alpha/configure.sh new file mode 100644 index 0000000000000000000000000000000000000000..e72252cfdc4700028856f2afabfcb29cce9d6a9e --- /dev/null +++ b/browser/branding/tb-alpha/configure.sh @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOZ_APP_DISPLAYNAME="Tor Browser Alpha" diff --git a/browser/branding/tb-alpha/content/about-logo.png b/browser/branding/tb-alpha/content/about-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7d705be61dfd72e4a8a8a0232ad6aa3d5ab8f01b Binary files /dev/null and b/browser/branding/tb-alpha/content/about-logo.png differ diff --git a/browser/branding/tb-alpha/content/about-logo.svg b/browser/branding/tb-alpha/content/about-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..be77df79b2682217c88d593ecae7cf4352939fdf --- /dev/null +++ b/browser/branding/tb-alpha/content/about-logo.svg @@ -0,0 +1,25 @@ +<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path d="M24 46.5C36.4264 46.5 46.5 36.4264 46.5 24C46.5 11.5736 36.4264 1.5 24 1.5C11.5736 1.5 1.5 11.5736 1.5 24C1.5 36.4264 11.5736 46.5 24 46.5Z" fill="url(#paint0_linear_1920_3895)"/> +<path d="M24 5.54297C34.1935 5.54297 42.457 13.8065 42.457 24C42.457 34.1935 34.1935 42.457 24 42.457V39.6445C32.6402 39.6445 39.6445 32.6402 39.6445 24C39.6445 15.3598 32.6402 8.35547 24 8.35547V5.54297Z" fill="#CCFFEE"/> +<path d="M24 12.4424C30.3831 12.4424 35.5576 17.6169 35.5576 24C35.5576 30.3831 30.3831 35.5576 24 35.5576V32.7451C28.8298 32.7451 32.7451 28.8298 32.7451 24C32.7451 19.1702 28.8298 15.2549 24 15.2549V12.4424Z" fill="#CCFFEE"/> +<path d="M24 19.21C26.6455 19.21 28.79 21.3545 28.79 24C28.79 26.6455 26.6455 28.79 24 28.79V19.21Z" fill="#CCFFEE"/> +<path d="M24 1.5C12.7386 1.5 3.60938 10.6685 3.60938 21.9785C3.60938 33.2885 12.7386 42.457 24 42.457V1.5Z" fill="#0BDA95" fill-opacity="0.4"/> +<path d="M24 1.5C32.2194 1.5 39.4094 5.90728 43.3357 12.4875V21.9785C43.3892 33.2884 34.6788 42.457 24 42.457L24 1.5Z" fill="url(#paint1_linear_1920_3895)"/> +<rect x="5.01562" y="8.9707" width="17.6221" height="16.6113" fill="url(#pattern0)"/> +<defs> +<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1920_3895" transform="scale(0.00249377 0.0026455)"/> +</pattern> +<linearGradient id="paint0_linear_1920_3895" x1="24" y1="46.5" x2="24" y2="1.5" gradientUnits="userSpaceOnUse"> +<stop offset="0.333333" stop-color="#08917A"/> +<stop offset="1" stop-color="#17CF91"/> +</linearGradient> +<linearGradient id="paint1_linear_1920_3895" x1="24" y1="21.9785" x2="43.3359" y2="21.9785" gradientUnits="userSpaceOnUse"> +<stop stop-color="#008055" stop-opacity="0.4"/> +<stop offset="0.166667" stop-color="#008055" stop-opacity="0.4"/> +<stop offset="0.333333" stop-color="#008055" stop-opacity="0.2"/> +<stop offset="0.5" stop-color="#008055" stop-opacity="0"/> +</linearGradient> +<image id="image0_1920_3895" width="401" height="378" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZEAAAF6CAYAAADYomUWAAAACXBIWXMAAAsTAAALEwEAmpwYAACxrUlEQVR4nO19d7wkR3X1qeowMy9t0iqCJIQCGYMQORgwJhg+kknGyGSZZAGSDRiTjcnJYLJJJidjcrDB5AwSCCEZoZxWm3dfnu663x8Vurqne6ZnptO8N+e3s2+mu6q6OtWpc++tKkZEmGKKKaaYYopR4P4S++uuwxRTsLorUACmvbEpNh1Oxza4dVdiig2LjUAMw6DI850S0hQTgymJTDEqNhtJVIkiru2UiKaoBFMSmaIfpkQxuSjj3k2JaYoeTElkCo0pYUwxCJP+jExJsARMSWRzYtIbgymmGAWDnvspyYyAKYlsDkxJY4opBqPfezIlmAxMSWRjYkoaU0xRLLLeqU1PLlMS2RiYksYUU9SDtHdvUxHLlEQmF1PimGKKZiL5bm5oUpmSyGRhShxTTDF52NCkMiWR5mMzEcckn+uGahimKBUbilSmJNJMTHJjmoWNeE42xjm/iW5Ephgb9rMzcc/ClESahY3Q0G6Ec6gaw16ziWtopsiNiSOUKYnUj0ltdCe13hsBU9LZHND3udH3b0oi9WHSGuFJq+8UEUa9d41uvDYRGq1OpiRSLSapIZ6kuk5RDup6BhrXUDYIjVMnUxKpBpPQIE9CHafYHJgqp8FgaMj5TkmkXDS5YW5y3YDm189GI17mKTbd3FeNUCVTEikHTW0Am1KvptSjKEx7zs3HRp6epFYymZJIsWhi41hnnZp4PZqEaZRVvdhQg/5Qk4lrSiLFoGmNZR31ado12IgY5hpPeoNYBzYCqVSuSqYkMh6a1nBWVZ+mnfcUvZgSzvhodGjtAFSmSqYkMjqa0pBWUY+mnGsSZdZr0hqNcTCdsmUwJlGlVEIkUxIZHk1pUMuux2Y3iRVRl0loaMZF0fdsUq7ZpKiU0olkSiL50YQGbiMQRxOuY1WYOs6HxySa4RoRatsHpRLJlETyoe6Gr8zjT2rZGxGT2IDWiaYtWdtkdVIakUxJpD/qbgTLOn4Z5dZ9rTYb8l7vpjVmVaAJY0KaqE5KIZIpiWRjo42vKLrMuq5PnfelSQ1CXkzVjURdjvGmqZPCiWRKIr3YSORRZHlTf8nGH5m+0c/PRh2Ne1PUSaFEMiWRODZK77qo8iZBEU0CNrqDfdJDhKsmlCaQSWFEMiURiSl5FFtGGWVtJmwmE1TTfDtVEkoTyGRsTElk8sdDNIk4NkIIcl405cVvWiNcFuqYobcqQqlrWvdCjrvZSWSSCWTccppEPkWXVQVGqW/d5otBmFSiqSIaq2zVUJcqGZtINiuJTMmjnmMXVcakoum+kUkjxn4oKxpro5LJyNiMJFJ1I9YE8pjEvFNMhqlqUoinaNNUFWRSpR9o5GNtNhKZRAKpoxGvOl/dZY+KpvQWJ81UVXd9iySUMv0mE0Ekm4lEqmyEJpE8qspTRVlVYVJ64cBkqBobVTnSi1QUZaiTupzuubFZSGSzEEgVRNAEh/4kYyP5RZpEiE1SFEU3/FX5SUaq90YnkSl51JO+qLx1HatJPb8mK4gmEU6RjvQiGu1No0o2MolMUuPVRPJogl9kUgeBNrVBb7oDvoze+zjlNpFMyiaSocvfqCRSVeNTl/ooizzq8ItsRPNWU01Wg+pVdy+3LD/IuIRSFJlMCpEMhY1IIpNCIGU32GWqjiaolI2EppiFJs10VjUhjEsmRTvxGxFevNFIZBIIpCnkUQVxFH0/mkhCTXR8V+1/yEKT/SDjqJMiyKTpRJIbG4lEqmhgqlYfdZPHNHJrMJpoumqK2WpS/CCjksI4jXhVEVelY6OQSNMJpMxefF3pRk0/br5JRxNIpykkA2TXpY6Q3VEa9rpVSVlqJHe5G4FENhqBFK0UNoJCqarMPNgM5qsmmKuKHAsybEM/KplsNCLJhUknkbIbkirNM00nj6lpS2KUetXto6hiqvQqjj2ODySZP0/eYRvncZ32TSOSXGVOMok0mUDqDMGdFHUybr5JQt0mrDrNV2WF7aaVXUaDX6UqaYSjfFhMKolsFAKZdPKoy6zVFOKps4df5PGbpmTGNVsNU0ZZZFKXs75yEppEEmkqgdSlPppKMMOmLSJf1dgsCqNus9Uo5ZfV6I9i4ppkIhlY3qSRyGYikCaRx6Q53ZuKqkmnTFPSMMcq4nijmq7K8IOMQlBVEkmlmCQS2QgEUpX6aKo6KfIe1k0+TRjvARRj+imy3GGPN8mmq2Ea+iqJpFICmiQSKRNNIZAqyKGIYxRVl7LyVoGmRGmVRQZ1msqqiLrKkzavKmli6HBlRDIpJFJWg9IU8siTru79RaYZJ/0kY5hzrcKfUdSkhlWUXUZDnSdtUWmS6asag1IE+h5/EkhkoxNI3eRQlUIaJW0V5YyKusd+aEwSEYxT5qhqI0/6ohRH2eatYVEJ+TSdRDYzgdRNHlWavYrMVxUmwZzVRMd8EeRShvkqb5q6iKRuNZKJJpPIlECqzztu2cOmGzX9pGLY8yyTBMYtv+iyk+WVEX1VBFEURTZlpx0nz1BoKolMKoGUbRpqat68aUZJW2YZ46IJJq2yiKAsAhuFHPLmK8phXhTZNIVIikDmcZtKImWg6QRSViNfp6oZNt24eapGE0xaZamNKh3yZfg4BqWrgiiGdbiXhVKJp4kkUkbjMckEUjV51EEck0AYRaFJJq2mEMywqiMvoVRFFBvRKZ8bTSORjUggTVMfZZFHlaTRNNIp84Uu06Q1CY7zQXnzEMogMsmzv2lO+cagSSTSpIahbgLZaOSxUc1ZGqPWtYqxIKMep2y1MUw5RSmPcciiKKIYhLxlDHus0urWJBIpA8O+3EX2pptCBEXmybs/b5pR0m4kDHPeTXKgF6E20sopyjdSJlmMY94qmiAaoVyaQiJNMGM12f9RZJ4yyaMMf0mReatAWS91WWatogihiLJG9Y2MQgjjEk3ZRFIGSjl2E0hksxDIZiWWvGnGSd8k1GnaKlJxlF1WkRFZZRFCnUQyMWqkCSRSNMpqgCaBQKoijyaas6ognrod6Bp1+ziKUC+jqg4AIBespw5BVMSwymPQvqYTSa2om0SKfvFHKa+IBnHSSKIs8ijLnNUUZVJEPcpWHKMcoywfxzDl9JBKGlEk0sbKtdIz+R8jAOhC2OlGadibbtoappxxj9mTv04SmRJIedurMo8N2jdMmoHpnOxGpRCEoCp6faOcQ12mqLLKycybJAIAcLKrwaIvLFZmAEEEYgDggZvtilBGUR5lkcE4JNQI1K1E6kRdBFJUno2gSmJphiUJLtOPTCwiQRqDjp9BMk0hnlGd18PmL6KcgarDvhf6OwOo3z0SgIh+RcQRQBiS8cCZpUyGJYxRiaTw3n8JxxgZdZFI3SqkaQRSpvqoilRy7x/UWPP4fqsxKfa50fUIB7x8mmwy6s3GVDBVjBUZpWEfNn+/cjLzq2vKCOlkof9y8zduqtIQIOKAI+8VIx+MRZ0EDgAsgCAGRh44A2KqpG4iqZoACj1eHSSykQmkSearRigSB4xn7UuSRRpJ8JSGO23bsLBVCLeOm1Qnqmp98yfJZUhSGfZc6nCqj6teepRHmtJwI8Lg8i+YNmWxBKlYBVMIIotsKLo3TAgQuWAsAJELzjJUSZZ5q0lE0liz1qSbszYTgdShPoY+JyfDxJRs+B3L3mDvS6bjKWVRAR2RNDu7kI2bdRzZGHGzP0YcPQomoVjMvoJ9LUWatvqVVxq52B0Lfa1cMMbBmL7f3PxmjAEsqTzsOjhgYACp+8VCgAgggLisCyMXgE0ksvI9ZaY11E0zbfVDLURTNYkUqUI2IoFMJKmkEQdP6WkCxHjCPCG/R3l1j1OAUgilGMd6mtpQ5pBE+dHxhNV7tsiFxcuKd5LTzGBDEMq4NvRxyy2SXHqug22ucsC4RR6wyUMWxhjXNimLUPT1lYQBBjBiADkAQvn8QKUDFFFZREIEYh54nuitookkC1WqkXHKiuWtkkSKJJAyjl0VgVRJFKWRR5I48pEGs23azC6YAJZeRpR2WOjonJS664bHINkrVURhGqs4wTAmrIYxD6mMQCh5z7lKh/io+VmCQGIkwiUxMA4wDs4YoL4zTRr6WYkd2wUjMqpDXmNSysMBhE0kAPG4411XmvKSxihEkoUylUrlamRSzVnDNCp1EEgR2xtHKlZD0KMmIps0eLQvThpRZmZ6ldGB0hsKu/GmWPr+94wGWL1E4kUjq0EngHR9yDJx6TQppGKThCmbxwlFf6cxFUoSg57dKpRHVv5U34djCMOYsGCTh1YezJiypPpI3nNlsiIGCGm7Ylp1gMB4GpE4AIW9ZFIWkZRBFpWTxCBURSJFqpCqFc2kEUih5JFwZKaqBUe2kDGbdoI0GKLGIEYWaaYsArE09ZHmH+mHpNqInyAlSCRSIjbBkGUyierOyN4nScWuL6n6RorFKpJZhGLIQ+dPd+wnCh4O/a5ZqU512/fBpdlKfZfPigPGmVIbmjScGImY58VSvLH7SkyqEabJBNKZrjsRnEvHexiveKQ+guh6N4lIGkcU/TBpSmRYAhlXhVRNFGnby1Afw5BHTHXkIQ6LKLhNGklTlio7qUAYS1QvD3mkyQ71Jva8jIoQrN9k7F7aG5ssVpOBTqvLIEDYJq0koWgTVxqh2H6WJJnoslJOKcelyI1x1Eeq8tBfkqG5vWYrxiz/B5f7wDmYJg/OrePYnQr1RTBjvpJkIv1oAMAEgZh17zmAGJFgPNIokkhGwaDy8h6vkHpVQSJVK4dhjtskAqlTfeQiDyd6oXkacSgiYPp7gjRssmBR+XZ9snwf6b6NPCebkTaW3FYhZJGFLlYRi3rhJBlIOUHEAEcTiiILU4YmAWYaVBN6qsmEAEkg+jrYdvuc6iTl9DJRtmkr5vtQ9Sf97Nh+D0UkXDnVOQOD+qtIJNsXoo9F0sQlAFJxuowJ+axwZvlKVMV7GswgcTr7btjNADASRDuOPtLeOQyRDIuJVyOTpESGbCfGSrMRCSQ3eWSpDt0IJInD9nHo/bps1QCYuH91iDTVoBtsE5XTv+rZsBuPeFlEtmKx0um6KnKI+0Q0Yeh03OTTUUIgnV+VyYQau2ATikUmqeelyITbZcr0fcmkKuWRlb9HfQDafCU7C2q8h/JxMNLEIf8yrtIYAlE+DNMpsQ5Oz3/PW275k4suuPu+xUN/shp0TwxFuFM9iSue513d8v2Lj5jf8uP3Pv+fPn+jI49eS1SUBSCR8D+xfTfsjp8kZ2zv9TcAABJkknY9xlUpEw/2C9pXavk1lDPpBNIo8uinOqKXPiIO3YskaCUSJwxmyrJJo4dUBt1DhgG986TjXKI3T6K3SvFd8S+W8z1FuURkkdxm+1VEogwCkbDyAnEne9p5DKlMxmm4cudNEAgcxBznqgPClPqQZqton61ATAeE2easv3jJc//fxVdf8VfL6+u3YpzJEiztCzClPwAwgsud6+Y7M596xkP+8p2P+7MH7BMAdSFECKIQRAFI7N+9J+pQUMqzIeQ2i0iGIfGytw/al2d/3jSZ+U7HtlJJpCgCGbasHA3Q0Ps3HIEkXnpub7PJI4U4lO26lzjUb24diMX/MkaJ3qW934atGH74u/PmfnLhb3defsN1R+w5eGDrvsMHj10PgrnV9fWFIAzmu2E4GwrRESTaJKhFIJcIagyaalcYCzlj64yxgIGtOJyvO46z5DvuAd/z9vued3jLzOwNW2fn9h2zY+eeu9zyNtff/w53ORRVJ8kwSTLoJZPk9jQysQkhmbcPmdCQRJKGwsil1/8BNc6DaRUCrpSIRSDKjCX9Zjx6lrj1PLB/++Knb/SWz3/itSvB+m3sp1LSDrdymCzW/wTGsH/nwtaXf+117/iPdUUiAYgO7t3HDuzdHzspEYbmvLbs2CbvVfFE0jQSGSZdT75JIZG6CSRre1MIpCry4EyZJZBBHDZp2M7zpIkqizTe/7UvHPvzi393wpU37Lrp/sVDJy6trp6wHgZHd4PuEQKYAQAT85VVWooxLBOGGljiN8AZW3Ud9xrPdXfNtNqXz7baV99o55GX3PakUy5/zsMfewUzzVR/dVIymfRTJWP1MPPCUq+Qf+MEoqOwLP8HU85zHj1XkR8EFh38+Yue/fjfXXnZ88CYzzgHHPV0cg7mONFTqkuD9Wyo8YMk5BXzXfez3/7X9z5FE8ih/QcZAAgh4tczg0gSZq285FC3GploEmkigQxK03QCGUt9ZIXqJpyePEkeHMyxVYcdv6/JIUka6m/PWBC7bv/1o/894nM/+PZtL7/+ulsdWFo8ZWV97eT1oHuMaRhssjCGMesQLF46Y4nTHkQmidfGWDMMJZD5QTEKADzXubLjty7aOjP/uxvvPPJ39z/jLr9/9L3utydKYYqKEUa0LTJl6e8hiChOCGSTjE4DjG3iGqXBSM2TNH9q0nBlR4NccK7NV1bzb0dfmc4JIgJhb/7cx05879f+88WHV1fPMKYr7oC5mkCiUo1ZS9NQz9UX0u0uBDjwk8+/7HX31wSydOiQJBKLOGa3bKEkkaSokaxrUrVKGbQvz/68aVLzbSQS2UgEUjgRZamPvORh9RoZotc1RhyqIeDJY2t8+rvfOuJLP/ne7S659prbHVw6fNvl9bXTCOTZmid5NF18nFSsESj23wSFsV6rWQ8MObBoCwjQ7XFELLpBsn+r5ERgQLfleRctzMz88uY3PvF/n/fIx//ytBufsGaVGPOLZKmS0HzvVR40WJWMa+LKnVdHXQFR6C4AuMrPIbdz23nO1HcHlhJB/G4DAO73wmc9/sKrLjsXnDOmCAOOo0hElebq0mxdYz16jOTFISGvsJBEQmEInzsfeNvjn37O8uFFc9fDIIhIZGGesohkRBIpIu0o2/Puz5smNV9ZJNJEFVIUgWRtr5JARlIf/UxX2vyQRR4cjKeoDmN+sD5GG/zod7+Z+8rPfnD8BZf/8ZaXXHf1/RdXV25HIMc0ObaHxRjMeOp2o0Ls33ZwcJJUoEkk5coYwUHRfluF6Kn7IkkSEYjZr38nv0tScRjbO9tu//Sobdt/fNpxJ/zufqff6Yr7nX7nQ2OoEgiLcHQavT2ebuwIrr55k2NgHETOcz3uQ3dMXKUZuCIMDtuTEZlFAbC3ff4TJ77na59/waGV5TszxgGXg+kSXAfMkUqEOa4xZxmvippZi4HBDGtX94VIAIpAKBSgMMTWVvupz7/bA/5zdXnZnIvn+wIAZuZmaXZhngCgMzdnwq3HJJI61cimJZGNRiCVp8mKukr6PaxZUpkjrc495KGVCqyXnqHX1/GtX/5ky7u+/Ll7Xnr9tX96cOnwnUOi2chgYZODMk9pA0dM66i0eiyz2c57lIfZHzv7DPJIXi7b7GFDyHbDEIP8oaxbNmmI6LsAbDKRdngpVYgInLC4MDP736fd6ISvfuDvX/odwFYY6SYvoYz6ZFVQr5WRVCVD+EmSGKrxsAiEkgSinyXt/1BawSIO4wdR5MHMnXvIS5776F9devGLjOfEUSThOGCOC+Y6gMPBXFdtUz6RmDlLDTNk5qLKKxGSjMcSBAoCUBhChCFuue2o2z/slNtcaZ9fGITUnumQJpIkiQDA9iN3JqdMGYdIiiCXcfYNkyY1XxkkUrUKyZNuWBJpAoGMXO4wpisrYmYo8kBktmIA8IqPvOfmX/n5j/7yhgP7HiAIM7GATVtdaOrSZogYecRHCsTVCOK/gYiIzMnal2MQkSBqrmO/LRNXzBBlaYY0FSIs4jDbROKv3Oc5zjXb5ua+ecZpt/zCa576nN/pIw1HJBFx2IRhkUnPviGQmidLgTBLgdgEEkVfmW26a2AUyKHlJX6vc572qt2HDjyQcUUUjqU6NGm4bqRGnChd9CzpB0HrT8kkJOJKRIhQ/u0GcIm+8+xT7/TYMAjIb7cIAFqdNmURSUkkUkTaftvz7s+bpidPU0mkThUyqQSSVB9pBBIzXemeoY62sp2eiJNHzPGpj3Xpddf45773rQ+66OorHry4sny6NISx+JFsIuEscrHaMyOlEor1XTMF59Cs0eMTMVdhwO8s2G2tpUDiIz4ic5WtMjQ5xAjDUiOGXERyG9D2vF+ceOTRn/rUS1/3eagS9dHsvwLC1ET+zkUkSO7DGD1OTSJJAgEA7UDXPhAnGjToRHffKBDGALzmEx88+X1f/8Lr18PgROnnkMG/3HWN+pAfF8yTpUITCeeSSMxzhLh501w8dS/CUPlFQoggBIIAFAQ4pbXlzvc98sTLwyAgv9Uiv92iQUSy/cidlHId61YjG4ZEmqZC6iaQtG3j/s5MkzRf5VQfunnX6zXodDF7NSyH+Se/882j3/3lzz7yit27Hh4KsSOyS7PIAm6Iw+ox6iNpjwuX45mZJgfHUhraRAFdC9W/tJWJ3pe8HGoTG/B4GJ9HT3OQbMLR42A324Rt0tJkonq+CRUiiUOABNRfYfJ73Ln4uO1HfPLlTzzrs7e96anL9tFtIkmZeViMQCTpl6MPkgSinhcAcQJxFWloArEVCNSzCACP/ecXPvAHvz//1TroV6oNRRCeG/+ricRWIUyG+4IxNYGK9VzYihLM3AMSQpKHEBBBAOoG8EPxr0887pb/EgYhMQZoInE9TwDA9iOPEBlqJA+RbAaTViNJpC4CydreeAIZVX0wy+RASjegV3moMF3GvvfbXy289EPv/qtLd137JAI8E7fPol4hcyzisA0ZVq/RNDF6HLzlypdnZCsR6CpE/d4en0d0SXrCfPMiZtUS8W3JSC2tSoStStBrzgo1wcgmncJQkUtEIElC4cCenQtbP/7k+z/ko4++95/vHUQkNFiR9KiXYa9KBoH0KBBXjfdI84FEd47hXuc87ZmXXn/NU2LmK4tAuKOUhycVifGF6OfKkIdaG9OYNVlUaabvGwOBpBcplNeZwgCiK5UIuuHvn7jjpvcBAM4dAQCtdkQkWo0ceeMbCRGGNCSJlLFtlO2D9g2TpidPkSRSJYHkSTsMUWRtbxKBpB5jEIEosgCPvvfE6yNq2mPkoXuNijwed/kN1z0uJFqImaYcFjlCuQ7FZIpENKloncNh91GNnyRBGEYHGYcHM42EMW3ZBBK7MimXKUksfdtSW51E3+NjSHSor2Xess1dWpHYpCJIkkVoKRfdqGlFIoQxu3Ci5R3zWz78mqc95x23P+VmKzaJyL9DEQmi3zYTDoZNIKqbgDQCcZQhU/3lXIX3wlKzDIzd5+/Pevofrrv66Yxx4yznrqt8Hm7cfKW36U6I6phwY8Lilmseliol81veLk36JGfNCrUS6UIEXdxWzNz61jPb93otnzh3hFYk89u2iDAISasRHfZrmbTSrmOdaqQOEsHp2EaTSCJFq5BxiKUOAmFAPvOV5fh0kuoDli7Q5gZY5PHPH33/af/965/d57Ibrn2MICzIZsIa9KUaAhPLr80S+nuKezUeiQVo41rMMar9IEkiAXpUSGYY76iImUKi3z0+E00gIDXnriYU0UMq2mQlRIp5S1hEEkqbvSQTrUzYrmO2b//3B55xt6+c9f8eeR0Qn04lOVp+TNNWbLtNIPq3azoqZgwISyEQJ64+gJ9c+NuF57zz9efsOrD/wdr/ETnMFXl4CSKJqQ9NS8zoalhPv4HZxuT1188LwVxnEqGM0gpCiG4X29bFY+7nHfEDz/eJcS78VosYA+a2LAitRnYee7QYkUTypsmbd9j8efYNk6YHTSKRKYEM8duaq2ig+cr2fViubodFPUVNHOZtvOvZT3r+lXuu/2u9bFBsxLAmD0dbvZXJwdEKI2pOYlNTOEoTWU5zozBivg4WIwujPnqudJ7bMQwS71BaW6uJQyePKRRr6kXrr6BIkUTKRCjzilQoEAJCjWGAIRT1W4647h65sPXdb3rG89552gknrpqqIFIiGhlEIuJp+pu2LAIxv5MEokdxQN1x+WT0EAj7yDe/fOwrPva+93fD8EgzYNCNEwj3XGO+0vti6oM71pOqn40U8jC/o06HmUZZX3cTodUFBQFm18Pn/Xm48BnX88jzfWp1OqGtRjzfF9qkBQDzWxeERSLm7g/xu4xt/bYXtT8VRZHIJKiQccgi77baCSRpvuJRc55LfTztza+6+3d+84vnrgXBSRHtpJFHPNRSx/drMjGKw6gXTQxKaWgiSRJGZnTViI9YWraRXpVExkQbHDN3kd28W6NBhAo5hTBOeAg9JQdBhKFczNWYtkRENopcOOH6mxx9zOs+/pJ/+cIgEpHf+44jSb0SyVBeexyIq4xJtnlUdxnkaPT4nX39pz586ju/9Jn3CoY5xuIEwj1PKRAvrkQcrnwhyu+hn6FB6sOGHYwBACR9I0aNhIEhkvZa8M8PDObfDQCu59HM/Jzg3BG2b8Q2ac1vXVBO90pMWsOQyDj78uxPxenYRk1YT6QKFZI3/UQSiHyR4+YrHn/J+6qPr/z0+9v/6UPvOnfPoQMPiJultNkhOQDMsdSHY1RHbH06h5mXmYNb/VNuziidNPrcxiq7Kxrm1bIyxupNMRcNoNbbA5NLJmliYQAcAUbcEAp4pES4wwDhGPJgjmrsuAA5XNryw/DoS66/9i33ft5ZD3rLs895zm1veuoqQ7SqIgC1kmLSNBXfxsGYSGkzuHWOSQKx76wO2XUUaSQIhAFgr/nEB09715c/+0Fw5jH9HHlaeXjK9+HG/1rPk9Y7udVHFjT5CETPHHckWXMOwdlOInDGpFrrrq2zVqeD9bU15rdb5LgOixfHWGLaeIb+DXDa/kF5ishbGcYlkSJe6yLQrx5FkkXatsYQyCDzVUQizNGFP+Ll5zz0l5dcdK4AZnWsPnOUPdpLzlnkqukoUsgjFrdvO0CBWASNfXZ2o9DvCtSJgWrGUlNqZ0QqLGYCY0KRCiOASzMXIy5JQ/tJeAgmuGnkJJmEIB6COAdxjuWge7+/fetrv3OzGx3/0g++4OXfyqq6IotMxSFi5JOpQFRkVuRIt0b6OGrwoO3ZYq//5IdPfdeXP/shcOZKApHOcu66lvLw4g505ScBZ+BONBdwbvUxCOpMiAloYxtjDIKzo4Jul3m+B/nXJ8d1mD131vLiEtNToeQ5EkZr5Osmh5GPn/EWV4aiVMgw+cZpouokEO3WZo6yUSt90EMgWi+ol9yVf6Fi+CMC+ZOzHvfGn//h9y8TjM3Kl1iaGbjngPseuOvJXqPvgfk+mK/2+z6Y74P7nuxFetHgMO444K4cGBaZu+Lj4c3HPkv703Qk68sSO+1z5JEJT04myCQR60bTjIVQIa6uZxpW4yvwPDDPU/fGA/c9gPNjfn/1le+737nPfP0vL76wY9eAp1zF9G2mY5JKIOpsuAPuyG6CDOrWd9aal0CrWn7Nnhva7/ryZ94DziWBuJpAPHUeLpgvz0Gfj3l2uBMRSKwDEqnX8Z4PZs5K++GIsR0AQGp59u76OuuurzMiYH11Tb5/rmuOemj/QcaGjyWfhKd6ZIxDIlVdmEHHydo/TP1GURzDph+XQEwElmt5HrSD01XT0znG3GBc3UqFyB4jALz+Ux8++dQnPfwTe5cO3Yc5yrFpXnIPzPMlcbTkRzdcmjwMaWizhOPI+H7dKHKLOJjVqOpTnDTSyINcpGIRih5fY3wAUY+deS6478bIRJK5bIDNfXJdHF5fe/Rz/u1N33nGm//l7qNUO0kg8ZqbubGUCjGjg9QHenyRafL/7B+e8X7BMMe0otXmK9+NOiGGOKxzVF0go5+B8dSHLcB0xJ+mRRNezkGMbUvLnjRjLR063K8Gw7YVGwp1KpEiLnQRPYJR1QrL+F7Y7zQCsSOwtGFJO9BtAlH9fm6pDxaEAbv7857yvLd/8VOfXgm6p9kvMvfcqHeoCCMiDqVGEuTBuVQdMR9JTw8yhTg2AwYSCiSZ8Djlmy6BI693pEZcpQzVfWrp++QBjnPMeZf/8WP3O+eZb/raT3+4ME61bT9IsjugA7mtUAkH8sO/95tfbb3Fkx/5keXu2mkxE5bnxerPrPPRUViR/4OP5//oh4y3nDiOWRRdL+h2met6LOh2WXdtnQHA+toaW1tZZavLy8xWIwVhw7wJdZuzBqFsM9ao28ZROYUSiPZIWA50bb6KqY+3fO5jJ93sKY/8zBW7r39CFGrpRmpCk0RLffddo0jshsAmDxgfSuLlTzNVbWakEYpFsjaZyH5+pFAkyUvykPfEckQnfi8G3b989cc/9JU3f+bjxw1bxaQjncWeM60PpBoBYsEZjAHsqW9+5fuWkgTiWgRombK06dQQiI7ws5Wrfd3GRdINrjs5YCDGd1zj0w4A6Ha7saMNII4y1EeRndzKMKpjfdyTqEOFFHWcYX8PnXdYAlE9Q22j5tYLzgHg8f/y4vt/94JfvZo5nOuQ3SjqKjnIy4rIct2YFZzrOYugj2BVv+ie40aFvja6YdMRaUSmSdbjTRhjMrCLAwiZdMYzDiZCEGOgkIOYdLYTc0A8hAiD4z/7/W//zwWXX/KM9//9S7+dp0opfhDmxvVBYhLF6PliALv10x79b2tBcEIUhaUIRHVMjJ/H92LRfVwHZxiXfAnPEFllqUAHbdoipQYXXWxDgOsBwHW9zCMvHTzIZrdsGdXBnvxdBqo4Rg+arESaoEKK/F00gTh9CMSBeuH/7B+e8eTv/e7Xr2GOIwnEsxSI9n34buKvfPmhicRVL7wZmZ6hPKaqIz96lInugTOr/2/NQqWd8SaiyfZheWC+Y5zw8NzO76++8kMPe8k5TxtUjSw/iFIiViRWNB+WViMAcPezn/wPh1aWTzfq1nOtKCzLhGUTiFsRgaSAJV9JBqw7/IgwCMyO7vp6ag2440yf7hTUQSJlqpCizVjD1GFsRTIkgegxIGkEAgDs/i981pkXX3PFs+0XXJpGfOXgdJXvw48if4zpSr70JmJmSh7lIGnqMgPl0t3aUcSTbKyjj/JheZEjfvfhQy954Aue8zogfV12jaQZy4kII0kgpskHwB7zyhc87Ko9ux5hpjIxUWZe3ISlZ+TVBMIdKwAd1apYbYAzx2JYZ7QTAALLnCUjtAhhEHJAhvnaxezfvSftqR+3DZlIjEIiVZz4MA1wWccr3EzVb98oBIJo8Jf2gRgCucvfPfEfLrz68rNt8wJ3E1E+OtLK8yzHuRuFW7rxaCtZ8pQ8SkMambAEmThWOIXuGGh/SUyhyHu91F3/q/ud+6yP7jl4wEkerleFSDOWJg/tB9E1s8xY7JPf/voxP734ghclpzKJRqLb/poMAgFKMmENtujYptiAYaft/3C9bJPWFL2oWomUeXOKVByFq4x+aW0CiXbkIxAWj8ACAPYnf/u4N1y9b/djoh6iG5mw/GQUlh0x4ylnp2W6SovXH3RWU4yHPmRimnLtrdATGapQbe5bIcFKea6J8F6PfcWLvnLd3t09PlBbhSTNWPrI2oylCQQA/uWTH3gJEpMpRiPRPTU7b+R3M89V2QSSGwycyTXZQ44d2pyVdK4nwTkfpqbjKpWJQBN9IqOokCLNWINu9NAqo19aayS6+a3GgeQmEKj7+LpPffjkm/7NQz+/d/HQfYzZQ398a6yHF/VWmf2yc26pjz7hlhvyVWggkmQCQK9kHg/o5jE1EIVteyZEOGC41V+/+iXfevcXPnNMxqEMiVi0lWrGuvvZT/77Qysrp5v50swytlqBONGzpQnE9oEA1ROIHisCFruuHBzE2LEAoIkkWO8yEQpTwSGjtMauacHllV3u0CQyTkWa2PQMq0qKUiQxArF/q4iYtCisvgTyzx97/83e8cVPfWxdBCdE0VVRD9E4Oz3HKJLkYC9DXaWMFp5iZJjmO2rOI82gPRjK7OhEysA4utX9Dzk75VPf/e9vvPoj7z9ZF22btGwVYkdjQSkVADjrLa++x9V7b/hLvSaIWQ/EDj22pjKxx4FU7URPBdP/RbQpGNsJpJOFPVZk+fAiA+So9Urr3PA3rwkTMNqoWoUMSlOo2Sprn/aDcJgV4rR5IRbGC2O6ihPIR7715WPf89XPf7j/ZHd95ipSZgbTOKla5ar9FNXBbu6JZAgwADAHDARithEqjIhHZeQMEAi2f+vXP/8aCA962d887Y+yNNajQrTmUUdjAHDFruv8b/7yx/8STcYZhYrzBIHISVKcaBxIUwiEpB6JzavJ2HaAtBJhnuf1nypfmrSy0vTbtyFRlTmr7mZoFDNWoaoj+TvNkc4j8jAEwiIrsp5Y0bEJ5Lp9e/xXfPR9744IxIrc8fzIlKV7pNZcRYzHzQw9BDJVH80EA8y69vq+mRgqrUbUCHf1kerTl98dp/Ot837+1dd+4sMnqeLMs6d/a+Jg1hPw8Jed82pizDcOfjdFfVhro+uFpConkNj4JWQ/x0pxE8f2dYZY4EHQ7TI71LeEEesbBsOQSNkXsUwVMkqafulHVh1AdiSW9kSoscpmKhNmhfGqMgyB3Oucp314XQQ3Sp0tVU92Z/k/9HiDXOarKZoNTSZApCM0mehRRLpBd/X65aah73zlpz/8rw987YtHqaL6vkvPeNtr7r5v8fC9NEEZ/4ttOrOXDNAGMT2EMdmw1wFNk0rTaxDYtqu9cIf6ybVz3XEqIY6Jf9Oa6FgfB3WbsQbuS0ZipSwopYxMZlCXZcKKh/H+6blP/9BKsN471YQaOBhTHpaj05ivGhMpM8VY4NoAFRmkYqrEmo3AjB6Xg0m3/Ps3vvyVb/78J1sBrUBYz90ngL75q5+8Mpri05GhxD1Tuku/jJ66JeqgWFKgqmcr5m60pYj8zrTekmvdOEuMtqQVQznChTFce1EXSjOxVUEi4yqDYVRIHpRpxsraZxOIgbQUm6Wc1IqEscFdZnEpm0D2Hz7k3urpj37ncnftZqkEkjbZXdZcRcDUfLURoD0ZOvxXT8tp+y8MkcR8Fztf/akPvy+jVCKA7n72U14ggPl4wEY8eCPyg3C5IiGzOihVE4g5aspxjepWG7lJjDAImR2hVVq1NhjyksgknPioKmSYModSHVll2o70ZCSWXg8EMV9InEDu+Hdnfvzg8tKd+s5V1G+yO2a9SFPz1caB7RaH1rLWeJIeIpEEsC7EHe5+7t9+COhdbvfc97z19OsO7nu0bRqLrUioR6KrY3DjtUvpoFR1Dcx3fVytsdJVCRjWd6zSnmEOM+R4kQ2NspXIpKuQwvYl/SBR0GNPJBZH5AvR/SbTX7rrc5/83tVu92Q7Cit7riIej9PviZKpp4c4RcmIEYmlTIx5K6FIPAcrYXD3e77o2a8DpPlKLtxL4pvn/ez5yfEn0QBHHeWnjLDaJ6Mf117LWPnnrf5GY0KY2qT26aWKTegAwAnXbVvqLoahnj+LUseIDDF31qZ6ozaKTySPChn2xhZtxor5QRSZGEe6HYnFjfkKHGoeXQDsjs8+858W11b+JN9cRQkCaUqc/hTVIEkkjMeWNo4TiXxuDq0uP+zBr/yHsySJkPjsD79zxEoQ3II5lnLR4eOxmZ55FCrOVDeoDj9I7Pz1cVmMXHS9yCQi8BC/zyrGb7UIANozMzQzP0cAsLAt90y+mwJ5SKTMR6AsFTJKmlFNVXnNWABS/SDGka7NWNZ8RZpA8Px3v/n06/bveXicQPrNVbQJCCQxvnqoz2aAPTBRE0ls7q1eH8lVB/Y+76x3vfHuBNCb/+vTz4s/V2qZXmsdTW3m4slAjboc6UkVYo+dQfLey3ni20H4fbsox3XJ9aOxIq1Oe0oafVDmYMPKHp8R0tRsxor8IOoxN5FYCUc6A4Cv/PQHOz77g/95Z2wxKXuuIjUOpGeuoo1CIHkb/ax0aRE2w6SdZDAWDUzkACMOckg/nCZmhxNBMABdhp/98eJ//au3vuolB7sr9+e+Fz2h1lrwdkivMWOlBWpUdY7qL7PIA7D9IHL9EGPOAkF6gAgn7l37BtBrrvJaPm2W/gbGiN5q2oh1jbJVyKj5RzZj5fGDpEViAWBnv/sN7yPGXG7CK23l4cWnntgIBJL15g54o1nixEi/F4NagsR63Jn7JhVJIhFcEQoAlwC40iTBIBe7CsLOBdde9UY4LswQROvZ0/Nl6e6QMWMxVK/ybFOVOoe44mTRNr0glZCLfgkC/G74uR1LwWEAcF2XHNclz/PITYxa78zO0Oz8HAkhN2/ZsT35YEjb2CZEnSRSxNPWFBWS57uZMTXpB2FmKj3jBzGO9Nv+7WPfvBaEJ+qptM1YDzNfUXwMSOPmKsqLtMYnsS1GEj3Je/OztPe65yf1Jw573yQTiiYSMBDn5sowuIATAHDAGYPQJiBB0fky/YRGky1qsxhXSqQWM1aCQKJxMrDMWDKJFCAy9oxAECQAEXZvumvpjQDgOE7s5nq+TwDgt6emrEEYRCKjPgplPEJNUiEDj6PHhKSZsRjAHeV+tE1aqlzjB7njc858iRklPGCyO7g8I4y34QSSbMDTiINFv+w/KT+GhGxUNbGkKpc0QplUMmEMYARGDMSl6YeIw57xgzNXLrdLCRJhLJpL2jxnaoaDOsJ5MwmERW+ZuY+SMuXAQSHjzkhgy+HV5+083D2gi3Qch1wv8of4rRa1Om3yfN841aeIgYD6lMiovf9h0w2jQobZ1zddDjOWWRECcTOWIZDHv+bF979u/96HRRPBR9FY3I7TV9ExUYz+hBBIH/KIiMMmjSSBDPOYpL3/9uLbiRIphVA2CpkweT0kkXAwCBAcdYmlAiEeyvgsdX7RlCp6tmD1nTlxX0il5xD9jRGI9oNYBEKSO6UXhAgkBPy14FO3uuzgtx3fpzAM4bdbwnFdanc6wvU8as92TBGd2RlzoxsemVVL3cogkUlVIXnLykMuA81YvNeMxXS+z33/20d874Jfvya+apyeaqJ3um09F1Z8srt+pp8aEatXBnHYRGETSFoZNrIa9X6vFunyFKkQZG89qVDS1Mkkkol1PRlJHwhzAFLdHeIhmFCmL0WmsXm5rC6RnEe+YhWSRiDamQ7VNTOV0ASizFhCgMIQrBt8/4wLd7+KOw5x1yEA5DgOOZ5LgDRl+a2W8Ytwh7PZ+TmRVhtsUj+IjaY51puiQoY9lkmXx4zFrObemljRqJAXfeDt/wau4vr1qnFqriITkaUHeXFrsjtuOzfTTD81Ijd5JFWIlbZfo03Jt5lSvqXuBtMRO5TYb/Xa5aYM8phIMrGIEwDjDMQEmHAlu6hV2SM+V1FYDNF8WEnFWzWB6H4XS/6Ve20CgfSBgAfBL+/0213P4A4n7Qdpz86QViF+uyW8liQRr+VTu9OhmblZsurAtmzflkYoZaLRD1Y/EinrkRi23DJUyKikkUU8qd8zzFj61TNmLFjhvI999YseuNJdPyVmwjIRWb2TKcYmu4vZgAecSVXIRR7pxNFDGiQVQeyNshvulO9ksQuBwMES9CIbG+hmwSITFmMmMr3uGJlMtJkrmvydGIGR6oSAQMR0FGykOHQHJakCKqlq/DixUF7dHWPcVNiYsEgPnQyBMLzu1hfteTog/R/cdchxHHJdt0eF6NNqz3ZoZn6eSAjMbW20Kas2FK1ExnmiqlQho+wbeNykCpHf5Rcej6hPNWMBwE8vvuCcmB/E8eKDCM18RXKOIu4kJrtrylxYGT6PWGOUojpixEFk0hmTkk0otu+CFAtYjb75rm37sNKbMkkOIFBqRKsOk0332I1Fi0yW2HkmyaTJRGJECDNixHCn+pLq5zD3kEfPl1EHJdfZqkM6geiKc2WRpDiBBMG1p16+/7Eza8EadzhxxyEGoNVuG19IZ25WqpC2dKgvbNsqYipkclHqOTTNnFUFRiWUrHSx72nOdDWfKrNm57WjsYwKudVZj35XSNgup9bW6iMaQCiVhxOtGqc9LU0mkCR5JJVHUnVo6AghlQwEQJClLFQDoQP+Y9t1IbYysb4Y94ftXLdaUmZ/j+ou6yN3xExcujGbVCIBeoiDkLTYpDjQzX0sGZYZK5tAYFSq7B5EBOJ0wx+fetm+c7Ytrh+Gw8nzfcFlJJZwXJdmF+ZDxhjNzM2JzuyMaHXaxow1Mz9PAIwK2bJ9W4Nv6sgY65yqJpFhH7kiVEdVKiQ2hYw9NxYz32PRWIzJMcMMAB70T3/3uIPLS3dijhvNuqpi8rU/xKznkFw1Dmg2gdiqI2a/tvYlFQKZcBoQ07/J8ASEsCKICIxokRHtY4SDDFgBICBMQ+gQMENEcwLYKhjmIA2B+pAWeZiuOBR9gGImnKiZ0gSTuebEJBAJkCATfV59ZkSqijz0sWJ/ET1HPQTCEgQiwLvBD+9y4e5niDAkx3GIO44kEFeasVqdtnA9j+a2LIR+yzdmLDsiq4FoVN2ySKTqpmgUBVD0ccZVIT3OdPW82850x5qeTv1l7Ju//MnW3152yd9rM5UeD2JWorPXbbBmS61tlHAa+qmPBHGYl99SGsZ0pEiBtD0esjEAScVBRHAFXewKcWFL4I+zIS5ZIHb9MaG76wjhLDmutG07MuoGrvqtsY+L1h6xNr9LdI9ZEsGRSwhPWRPiZgHoJiFwMjFFLRl1JmnzUpukLwFMEkl8plir8WsykQCJJzpSJqn7q0TSkZ5XgQgZicWD4Dd3vXD3MwDlA1FmLNd1qNVuC8fzhOt51JmbFX7Lp1anTX67hYVtW0VndpbaikjmtiwQEW1UFTI2ilQigx61jaBCUvPEVQgxDq6d6TzhTNdGgZgz/bnvfuNrTTivHg1smbJgCCTFD2I7N+t+2a3vsdBLdebRi696+zGTFYvMU0RgAhBqYBgELfsh/bATiJ8c02U/v/mac4U9d6jjOOS4LoFnk4cml53A6tGtmZVbATeoNN/U9f350u5jr1xbus2hsHuHFYR3FsDJZAauISJtdRfJNGZqShEhUgiSTQaRJFF3v6QfgaCXQADtRAeIQrAwuPSMi/b8jS6OKzOW32oR51x47ZbwWy0xv21r6Ps+tdpt8tstanc61JmdpZn5ORJCYG7LQtlmrGS5E/agTJZPpMzHepSys1QIs1QIS3OmA2atdDzlTa+85+HVlTvaZizuejBrWTtuNE9Rmh+kKQTST32whD2dyVgnk0+ZpRhBOkQhQILgBuH35rviWzddFN8/LnQOAAwqrh9ARB5pxOHY31XkTZJYkjb+M2Z3XnvG7M5rAXzdcV36yp7Lb7crWL33UtC9j2DsFFIerkgJ6o+MCmJKkWh1woA4mUwakTQEJpQX1jOl/VQ6jbF4hhBC4LZXHjzTC0UIAL7vC+5w4bguuZ5HjueK9kxH+O228H2f5rYsCNd3qd3p0LadR4h2s01ZWai6zuZ4TSCRUZu/YVXIQEUxIF3q9xwqRK31JptSWM0qAHz7/J+/QrreIzOWWbNBm7G0j0TTUVP8IKkE0ksi8cbaCrFVyoMJAIo4hBBoB+Irx62EH77FYfoDEIVj6mw2eSSJI0kYeUZTOwlyAQDX9+ihx57yKwC/8jz/jZ++8sI7Xbu29NDVsPtgMN4hfWfBAK6yayMmAeDKl6LNXNrENSWSwbBNiKmO9CiUV3dHCAQiARIC2w+unLt9qXs4hCQQr+UJgCkTlkvtmY5oz8yIzsyMmNuyIPxOi3zfp9ZMhzpzs6TVsVYhC9u2FnnTNtwDUBSJFN2MVdksjn2sNBXCozVDmCXGYyrkXuc87VkB0RZuT2qXNGNZ4bx6PEgj/CCZBJJUH8p0xWzy0P+RnGZDvvzr7W74n8cvhZ84dZGuAGNmUjxNIGnkoYkjizSSBGGvE9EPnufH0j36+Fv81PW9n/xqzzVv+O6uK5601O0+TnC2NTbQk4RSiRwUkjE3EukxJhuu/SgeuRzpBBPKC2s0uggxu7z2ltteffhbAOD5HqQfxCXGGDmeS7Pz86HX8sXs/JyYmZsTfkeasLyWTzuOOtJEYswuzBMRDSKQSbihpdcxjUTKaJ3GLXPY/LWrEPXI2ypEO9QZA2Ov+uj7b3bprmufYqbWtqKxmOOC8YaasQb6P6yX3azdEBGIfum18mBC7J1fC95308Phfx+3Snt1ubb6cByH/HZLpBGHTRqaMDRRJIkgL4H0w+2POG7f7Y847k2XHNz77u/vuuKuu1aWntgNxZ0YF9LHwwmchFIhKoIOSpXAvi41dwKaiFEc6TqCjwTmltfeeMcrFj8qAHDHIc/zBeOgVqslmMPF7Px86Houzc7PyfEgikDaMx1qWbP1zi7M91MgWc9QVT6TxpVftzmrLFNW2cc3GEKFyF3qmB//7tfloMLYwEKtQLgM522aGSuLQLL8H5yrJ1SFXirfBwkBQKC1Hn7+9rvX3rxlnZYdx6FRyEOvQqcJox9R+L6f64VZX1/ve2V936db7Dxm8RY7j/mm1/K/8fZffvcB160cfp4Iw1MYdyD0sFJHjgInbbzkeuiJZdaakkkqkn4QQ77cUiAgQAgICtFeDT55xysWPwpEBOLIKKwQTA4qdD2XFrZvCx3XofmtW4QQAu2ZDrVnZqg90yEgUiDzzR2d3rh61U0iaSiKINLyj6tCDEZQIXo7+9avfrplcWXl9Eh5WNObWM50Y8biDTBjJQikdxqM9N4iADAIM38REQEiXNq2ErzuTjesfxlQazlYBKLNVq12SwCA32mLLOKwScMmCa8VJwxvAIF0LeJI5jVp1tZZ2r7n3+V+XwPwtZf/75fPPthdfS4TqhtBjvSXWAHfJqoLmKoSGwP8IDaBAHYkFsENxK/veunB1wIyCstxXOG4DnktX4ABM/Nzod9qiYXt20K/5dPM/JwAGLbu2C7aMzMylJfIKJAGE0gjwX5B+3q2DVvGGPvT9g0ikXF+9yOHoU1Z9rgQ1/zmrlpT0JF6Qn6HJBTOwNgZzznzpbsO7X8Yc9TKhL78MN8H9+U2PU8Wdxw5vXudo9JzE4hyeNoEQmr0syAQhfC64fdusXf9VcesiL3a5+G4rlEffqsltM/DJo804tCk4bV8sknCb7fGbgTWV9eGusL6mG/5/tfvcdmBva8SwImMW6ZK3a2w1yFPkO6mRV8zVjQnnCFfgvSjkQCF4eG7Xnroz9rr0XQmruuGXssXrU5beL4fuq5Hs1vmg9n5OTG7ZUGQINqyY5totdsmEkvP0ju3ZcEeqk8p39O25f1exu+sbXn25dnfN9/p2DbxKxsWdYy8agXA0CqEIZojC1/7+Y+2XX9g38PMLLzGHyJHpJtlSBXlQC0eJGtWfzRWGoFE028nHZ7K6SnVB+ZXgzff7fq1jwLp6kObrhw1ktgmj87srFQlvk9aDXi+nOfIrmLyd7/orKyR5uura2xUInrePR7w/UOrK/d99f988WWLwfqZjBzTizbzgakxLsyYZtS1kxUe5bAbBsmZeZOTimozlnak33jfylmdQKwTlBnL9wXjTI5Edz1yXY/mt28NHceh2S0LggFY2LFNtDsdaikT1pwyYelorBRMlUkccV9jYmfdT/C4pqxhVc8w5aXm12uF6Ec/IyJLNbuMvfQj7/k7HfgbOdMVeaht4BzgDjhTa1drl3wd6DEzIJ1AGAAk7NWqx4gw3Hfs4bVzb7MvOA+ICMRr+ZIYWi3RUosCDSIPmzj0X5soWmMsZ7q2usoAoNWRZSRJJq86WWh3wrc88syXvPKrn/3B1YcOvJmEmINSlGYySMZAEJZ5a5M63bPMWPq7bcbSHKwc6Z217gdO3bP2ewBwfU94vi9c16XWTDt0XY9anbbw223heR7NzM0KBnlv2x0ZyiuEwJwyYfUhkDKRR2UUWf6w+3OhbCVS9NswLsmk5RuJqPS6btZU72Z0OlRXM6lCvviT7+24/sDeh+qxH5HRy4kRSuRMR73RWElTS18C0REzlv9DRl9dc9sbVs48ekXsB6Iw3aT68DvyZU+Sx+z8nMgiDk0YutEfF7qctZVVc5U1sej9mfNkpeBlf/Gob3zp/J/f56sXnv+OrgjuyATJToJqGBlxubqgEpikzmvTEYkGsz+RComuOAEQakS62HvG1cvvBNQzpUyjfrslAIZWpy3aszOi3emI2YV54fketTpt2rpjh7AVSLUnODSaXj8A6PGJVOUPybu9Ef4P+7s2ZXEw5skmnyl/iONGBipXWXMdBrjaxHWrsx77tkOrS/dgrisXl/J95Q/xwXxPftRAQ64USWxqkxoJpGfaiSSBMCSm3xbwu8GXzti1+pr5Lq0CcQJJUx+tmY7oRx6DiKM9M9pI49Xl5b5X1iYVIE4sedBqt+lZH33POYfW187W61pqcyZ0hJ6J59tEfpI0FcLt5wswzxYIJOSsvGEYilvuWXvwsftXr3Mc5UAHhN9uiVarJbx2K+zMdMT8tm1hZ3YmbLVb5LV8sXXHDtGenSEi0gtNmYgsRA120X6QIv0jw2zrtz3v/oH56vaJJDHuG5M3/9hvplYh8juUL4QxW4Wo/qV5E9795c/d6ODy4j2i+bEinwg09WgTl/aFJFVIVRibQELMrIcfvOc1K2/XRTquS9r/oQnEVh+d2Vnh+h75voyeSSOPJHFkkYYO1+yH1eUVc1GT5SRJJY/SSSMW27T2b3991pvO+dQHrr9h8fBrwFUAAjlyaVrjDuFRGPBGVyRZKjfVjGUPKBQ4Yrn7ouMXw+tIzspL3OHkep5otVqiPTsj/JYv2jMzqhMiJ1b0Wi3SBGJXY7b5asRGI+vaJBJJYlgVMu4xcqsQjciUpf0gtk8E9na892tfOEv2OK1pTExIr7KXm4VzeXRY+yWrAolGq9+8RZkEsha8857Xrr5fl+G4LnktX6SZr7T60D6P2YV56QPJII804shDGnnyaGIpglSSaHXa9I4nPvOjL/z4v1//xz03fJCBwEh9HEcm0kZQ7XDf6ESikJwup9eMBTkbAAm4QfCdM27ofhNQjvSWJxzHoVarJRzVIWnPzAiv1aLZLXMCgtDqtKnVju63XmhqAIE0ssFOQe31LJNE6nzy+5myCoF2qAMmuFV7MfTrYJjgl3+4aHb3of1/YUwYWSqEJ1SIbrDrQEa8fmwJUgCMROTsFCHmV7pvvNv1ax8H4g50TSCtdlto89Xcli2h63tkm67ykscoxDEIdplZSiXL9JWXWF77V0/571d//hMPOe+qyz4PIi9p7GDEQSQkkbAEkWwULkkzY6lOSnS+MpqNASrKTwBCrN11V/dFugg98aYfmxOrIwlkfk5AEC1s3yranRkTiZWTQDYCSjdladg962Ef0VEf6bR8dZiyRjrfpENdTxTOrBafxbuO7AXvf/ujs1WItfpIUoWMWtNRkRUpE7PVyxc87kQ3BPLaLAKZmZsNNYHIRYAiApldmBd6SdJ2p0ML27YK3SjL0cQz6rucoqIMAkki61i6PqP6XwDgxY943Hl3PunUv0A3XKEgAHUDUDcEhaFcylVEa6gY64tepGujwfCHZcZizCw/rM1YoRDYvtx96WxA64wBcnVCTi2lbD3fJx2FNTs/J+a2LqgVCmfMuiCdbAIZ98qO6pMosg61oc/yZbWiClNWVnlZpizznVvfGaKx5NqURdZE4QTg0uuv/SswlqFCrClP6lQhqTZqmBfcjtePEYiK12+vBR+72/VrnwbSCUSaGTrC9Tya37Y1nJmbFVt3bA9tAumnPqogjiyUQSgvfsyZF97z5rd6EIJwmcIQFATyE4rBRDKxzQ16OyqInnPdHYu82WSZscJf3XFP8C0dieXo6L6W7Jg4rkvtWekH8dq+VLOddh4CGRXjEsck38UYmuwTGRV5/Bwjl2k71GGaV8YY4ESvQfRmPO0t/3z3kMQRzHEBFpmu9LiQxqgQ+5BJR7r14ksCoYhAKIQXiO/+6bWrbwLSCSTN/6Gd53ohoCaSRxrymLzkvl6zVzLNuQ9/7B9W1j/yiJ9ectHXuavZgSBfSwKDAwKBcafXRyJvxGQjQ4Xo72ZkuhB0q/3SjAXGwLkame55wvHkGiF+uyU836PZhXnhqVUKW61iQr9rQtFqqTQ0VYkMg1FepTxE01OuViBJU5ad1jZlEcB+cMH5zwZncg4sNakiXHt8iCaWZqiQVEe6NjHo85I2BhAR/K74xn2vWnmeXVY/ApmdnxNbd+4IbfNVGoFUZbYaB/3qaKuULLXSnunQq5901m/vcNIpf0FBEEg1ElqKRE4XI9eTF3FFAkyeKkl7zhIRgPYzRiQgiLBtJXjpjZbF7qQKcV2XXEUiM3OzYmZeqlrtU9MqxJrapCyzVdl5qyxzaJRFIlktYBH+kMr7XxmmLKZNWSzSEzFT1hs/8x8nLa+vnSZn1eLW3EmONS5ATfFelwrJNGMpP4jaZ55WPfGdILAw/N19rl55kd5lR2FlEUiW+Srp+6jgzAvDsISXTP/apzzzvNvf5OSHC2PSCiWZhKEMayWhnQPyexITdbUULA9iTIUAgJAqBETgYXjwzru7X9EKl7syrNdvt4Se2qSjzFhzW+YFYwwL27aK9uysTSBUAIFMEspyqqeiiUpkHP9HqaYs/T2+0nbUCrMoLQOAH154/m2lslDDDs04EAfgth8E6l2qQYVYSF2/gdmTKZKy0YcgER6+8/UrZ+m8wxBIMvqqyearYWD7TtLOI2276l6wNzz12b8+5ehjnyi0GgkVmYRhpEr03FtmDq4JQh4VQsZYKlWIEJhZDz9iz7PGGDODVF3Po/bsjHCVGQtQ05rECaQIBTKFROp1HJVEmmKNrdSU5UDPKdpjytJviJnihAB2zZ7dt5fEwSRp6GlOtGNdaRhmjy4Z58yGRR8zVmziO8YQm/guDHHiwfWztqzTMtBLII7rUj8CSUZfyb/NN18Ni0GkYgdoAMD7/u4F/3P0wtaXGLNWVyoSqEF2JBSJazuWrUom6cqlqRD1wBMJ2VmBABPi4D13dT8IIDZRp1wvxCPXkypkVvnXGGPwW60UqZaKtCuWd1vRmKS714NoboEpckOAUqOyAPlaAMANB/a5ew4fvC9jWolEY0G08Uuat5ihJYmKb0WGGUv3dIkhaq/UUrYLq8Ebb34guAiI5i3S40B0FFY/AtGHnlTzVRFIEohWt5984Ss+NO+1PiyCIFIjQQiEAghFNKjT+EUmiEj6RmTZREIIQ4EtK9232WYsM9ao0xFyfrUZNUi1ZUVjSRXSabYKqdTcVDbKMGfV5Q8pox/PLH+I9lwYNaIOZAxR1nH5iz/4zrsIoGMPJoQbrZUux4eoHr/WL3aDXjasNmygkxNyJUK5Hkjw47vtWjdjQcxcWNZAQj2NyZRA8oFbd5yDsS+//PUvaYH/ggyRWI72MCX0125zmng1bb5M66yYeAGlQoQAE+LQPfbjPwEV8Qc9uaLM7ur1ZVo+tawgDaAxBFLksZtaFoDm+UTG8YfkKXMsU5bcmT7AUAcn6t+/uOT3D4dWGFybrSyHOvo41MtGqjPdIpK0UEshQKEI77xr/flA72SKrppIUY8D8X05hUmFBEIjfGpBUoWkbX/zU5/1eIRin4zW0hFbgRxDEtq+ESjVOClEkqJClNoFAEECIQkcsRq+SufjVjSWViFtFSo+t2VBgDHY64NUDMr4XuVx82wvDU0jkWFQuQmOgzFtytKbbCe7TverSy6a3b+4eG97iapoplYed6gjepnqsCqmzlukVYg2vctYfSysBq+dC2jNNjHYkykyxmCPA9HnZk9EWCCBFEEIDSCUtE4L2G1vcvLq7W9y8jMoCCBCHforzKh2CkmaF6NufNVVz4ek4rWViFVnggxjZoLghOKSu+yn/9bOdECqEMd1yfM9OTeWUiEA0O60DYFoFaKnNxkRRZubGnpzhkLmOUwyiWShMFOW/d02ZQF69t6YH8Q0xW/67MfuZpzmZnAhM6YsKBNWzJRVdO0Hnp2tRiwC005OImPGAgk4ofjD3W7ofk7n0Y50ezbe1ozsJeqBhGlhvPLvWARSVqNfK5mk4W1nnf2TBb/9UQo0cUSOdohQrRg5SWYt/V/0kEedFRmdJUSII1bDdwGRM10rXcdzCQBczyPPUiFJZ3ofAqnLcb6hMQqJ1OWEz+sPyZtnYHonw+yQDO1F4jr+4bor7xEjiaQpSzvbGQerOrahT8+Qqf2kDHTSjCWdnCcdXH8B0LsAUFoklh6JXiCBVKkYaiETu3Nib//qK9/4YhbSLupKcxZCIf0joVBkIomk0WatWFiv2qS2R3WWnRWQ2HunA/Rt24zluNJ06nmRCtEhvbYKGWc+sxxoytVsHKpSImkt5CD/R9Gtam4fiA07tJcA4w8h2dSm5t13+PBdmFYieqpG25TFIlNWzKFeFWIO/LSeIZm/IIF2EH7p5MPi8iw/iHak234QeyR6AQRSBxqhTBgYu8fNb/V04xsJrUGIoQx2iMJ+0UskdSLNoW4FcJCeCYH0glPA/Lr4qG3GclyX0lSI1/IJCVMpEFMhDbkIA5Gs58QRYdEkUpkxpqLj9BwrMmGZqeD1qAoGgP/LJz54aiDCHWBqsVwuJ1qMTFmoz5TVo0IsX4jez6SXkwnoAV/i9N3d1ydDLQf6QcYnkKa0hoXXQVjOANGnfK12X/ukZ/xmrtX6VDT4MIw52eU06bZZq8zaj4PEAx6LzhIgCunWh/EZAKkqpDXT6VEhfsqA1YajCH9K1U71vuVuNJ9IGf4Q9POHIHENf3jh+WdIZ7o0WcnvDsyAQhWVVZcj3aCfChGAoFCNGA4+skPwxVQnp+UH8VpyPRDtBxmjZqOSR9LRnuczTNmlQgzwjP/HuS95MYTo6tl+ERIgBISO1tKmrTSzVp1ImrJ0h0X73ZTvjQTBD8R3dnSxlKVCPM+PVAjQ85yN6UxPwzgBG5sGG4FExvGHZOqAfv4QWHFViL4wALhqzw13Y9ZgQj2gMJqtF8rwba2JWCWZ9LNPA9DtKyOACXHgrvvEO4FeJ2eWGWtMP8ioamWclz1v/lpaZn2Xjtm6Q9z6Ric+QyglItQkjT2j2WNcRLE/1VY8w5SlYMxvMvwPIMKNVsT7gGwV4voe+VZEVk4VMnWml4waBimMhHHrOLLRSI8P0f6QZDnM2n/lDdf7h1eW7wCwyImuo7MMqdRvysq0T0P5NtW8RVvWwn/rhOimOTkZY3B9jwCgIDPWsMqgjF5nXjIZG4OUhw393P372S/6TsdxfyQCTSShmY7fTM4YGzvSJPQ+4LK+AASBh+KiWy2yi/qpkNjo9HQVMq4CHidP1SamxqCpSqROYjPH5mpN9eQiVCxDpbz9vz59cwJ8PY8vc6J5scwU76zGS5414Evvsyb3YxQu33mf+HyakzM5Kt2OxrIPVwKBVKEG8hyj0DrYfpF+PhIAeMgd7voy2zci1JQoQghAALEp4+2q1qRG0lSvqYoK6yUSmOmK/9FqF4iWvnVdlxxrdLpeK0QX0Zkt3IS1UVHadRq2RRulcR8lMqvoOhQCFiMYMKhgWL39giv+eKu405zF1whRpisT2luDX4TZb7MiDuMLMfZpgU5XfM4DE/bEd0lnOgDotdHTorFyoqmmpNKJJKlG+qkT3ZH5h798/GUzrv9tvQIihQLCmLVCZdbShNKQ9tU2+mpov41STzOC/qB36dHp+lnTitf1PDMexLeIpARfSD8UeaymljVUuU1VIqNgnNY4M2/Sqc4S18xWJbsPHrhFNCGKDu9VjnQV6ps6LKQuU1YSlhI5aYk+bu/S8xbZPUN79lSNIc1YlZmPRkRDWmEJ3Vm5y6m3eDcFAaDWZYcJ9yVDtxSresVqJPm8xb/AhCSbtWmEOGGNnx+pEDemQiJTllz2tq0Ub0kqpEnP20T4c4okkToUQh6nep7vfUGm2TVEYtmAov2Lq8unGn+IcahbaiTLH1I50uzTuqEhuKH4xU1WcL2tQuyeYVKFJNdGz4myCIRyfoYpr8j6xaDVxyAzlgYD2Isfc+ZvQLRmj2KXqyAKtdaLHriHBqgRS23rujCm/OlyMklP0K+O6/L9gJ6TLe53c60pTlqWQx2IpjnJgbovBNCMOhSOSVAilTe3KjLLTLoIROaEJIFofP+C8+bXguAk4w/hiPwh2mxVZ1hvP/u07r0SybDerviubZ8uQYXk2T+Ko72sPKUSybDYOjcfbp+d/6QdnYUwVAP2ogit1HEjVcE8b7DeGD0nm64XARDohPR9W4UkHeqA7LAAMCrEwjgnOUkE1FhMAolUiZ4WPulU118tcwEDgE9+5xu3JJATC9tN9Yew2vwhUW2R4MDIPs2IsC2gX+s9WfZp/VIDQHyN9EIIJC+K8pXkKacSItExVv3SMDD2or/863eQEBQjEv1Rc2opu1a8ilU3hynPG1lmUyLCSavsG0CkQoB4h8VXitfusAwwZTXJJNUElFqnKYlkIGu6bhu2UeqyXdedrMlCjlR3ZArwaK7fJvhDkCAvyz5NgsCEuOF2y+4Fg+zTyYisnM70ogikKPIY9vilvIxZJi3qY4u63+3OODTnt75tTFpCz/CrlpatK9w3hz9E/pEE4ghx6U2Ff53erZ+zWIdlfFPWFKMh1/VtAokME6lVRpObq0wGOf6u1y8isX/p0AlGhegVCx3tZNcKhCEHN5WIFPJAZJ8GEVohfVcn0RFZWfZpe1wIUMjsvEWmGxWDCCprXyn1oj7l3vxGx3/WLFYlosWqoAYeyqniRby0yhH5Q2IDDFXHxRf4uU6pOyzalKVhq94pmoc6SKRsIhjW2Z4Je9JF+Ts7XHl5dfVGxv8RM2khCqfVIqBqHsmwT1teEUBN+z7fpR8lVUjPgC/LoQ4UokLy5q+yMWkMkdiw5mnD6570zO9xoiU5q6+O0grNzL4xNVJlLW3/m9lkd2CglK/ATIDzgXRTVlL1tqPnbZx11PNiGFVa1fNQ23PXD01QIqMiT1M8anNtOdTT/CS921aD7nEAA1lL3ZIiE4L8TmC5Q4dK+TD9V9VDjw0haTgRQohTAvcXQDxKxrZPA4Dfbg370I77kNf1klRmd7dNWvn8ImBHLGwN51qd75kZfZUaEUQQguyIbTUGqMZnDr3PGxHhyJD/Tp+TbcoCgKTqLciUlZavjudrELVPjPoqm0RqDWQdEn3rmjVKHQB+8Yffz3bD4Ghp42IAs9ZPt1UJQ7VO9X72aYr+6FBLV9DFR4fOISCKkpHF9NqnCzRlDdPjG6bMfp9hyyoz/UD0G4R47LYd34WICIQEAaGcBsU4r3MHEBeMHqc6iwiNCIzowC263uVAr+rVz9sQmJhGd6NhkpVILdC+EXvbN3/x42OJ0DIj1O2pRKyG3CwCVRuS9mnrQwRP4DwAZpoTIG7KAiL79BCmrHF688M0DMOQxLCEkpWu9obr0fe4z/dJCIJysJtpTwgZ08NXVGW706InhtRai8l6eITfAb2mLGCs561M1H6/m4imk0jlTa6evTdtjEgW/nj9tcdIn3mkPMz66vqTdqUrPTuW/pNgeq3zIX6ldydNWQBg26crqPCwBFLFcfLmH6nMNMXRL0ILAB51j/vu67je+XJNEWGmhSchTI/fTBFfNgYGjRAkqQjVaaEL7b1GjaQ9b7UOeikEddW/LAuBwTAkMkmmqcJBysORtm/voQM7TVSWbcIyHwB1RWbZTnUbMYO5NDFsD9klQLopa8SorHFUSB6MYp4atZzKGoE041MawWgT69aZ2V9BDzQUYXRf5QRa6p8yb2lUcjZZzx1AJNARuEyvlmk/b0DcH5JEiaG9k05UtaAoJTKpBNO33oMUiDZrLa2u7tBJowabRa6POiOzbMQis5C0Ty+dFLhXpZmyakBek1TVxx2GLMeqX96p4hnAjtm+4wKyBhqSXqRK8YgJ8630biYedGuhLB1OPh+yK+wkWf6QpFN9imah6easMjCwGdfkkfR9ZGFpbXU7s1QHsyK0GsmvlPghB31dPkO8C8Sn4QZ67dMaY9inx1UoZTYojWms8rrDb3fSqf+n/R963qzIjKU+wi6qxFPMUr6IOi36y5FwrwPyP29joDH3dCNikkgkz/iPYfMOcfBsVdINgy3RUVgvedi/6xpsaHwgBIEockeFZ4ETrrFNC2n2aUCG9+Zc/najmhxKPX66X6T/MZ/4Z39xJWc4DLPWup6MUX6v3ZugXCHRD4AR7Tle+HuTz1nyeQP6OtWr8IVV5ZsbFXXf3caRyLgtLMv4XmIdiLphuCUK41VmrVhklg7vrZlAgF4SU2TiEttlb3a8eLw+kD4+ZITQ3nFUSFUvzCjHKdykNQha++5Y2BL6jnuVHGSiOwaIm5Cg/SQVgsk6RMe2Oy1sD1eVS/OH6CIqCuKYYgzUTSINtPUMjyAM5gFNHJDjRNKUR3KsRp2gqFEhAjzCLsd1TailRnJ8yCZC2UEBhYEBrOO1LjfL4wprqVwBY9aqhUhskPqPCJxot/28pflD0ghkE8+X1djzrptERkXRrfBY5YUinIkc61aJyTEiVZJHP7OZ1ZAQyQieFiimRHTvsLfYeGRWgWiKChkHtdVxttW+2pCFUSMppFFVDVMfPzJixAF298s+RqdlEp6TDQW37gpMGiileSZCRw5BVK54+zvU98KiUYuA7JVqAgGF8CBHqtv+EGBkJ2dW2qZcgLyIWfOrLEMAlDFXW2zIqjKUspl2az8oBJEA0z4RIeREOxSqx4+rZ3Gcmo0IrYwgAArBiQ7Zuwd1WiZwmEgV/ppGYFKVSKMgIHz7t606EoPW7UT1Qj+m6uX0CEtJU1aak7MmjNMrLYvBa70myUCP2VZrv7QW6ZguecqxxreuhjilDg7YIpDdadlkmOhzrppE6m46SwERPGtQSGI8SMNOOcP96xNf1T/TnOpJFDz9RBkNfJaje6JfWBu2ItnSmTtsFqKCNfUJYCZfrLJiSQhFbPIPwRG0ktVpATb89O8b6tymSqQQkANAvjzWFWXmP9QX2psJuz0leJytDcoxRHhv01GEaa4hkOEcnZYvOwHKQmk7sRtBnaQixxQYw6q9mzXu/ZgiL6YkMhZUDAyRm268buCLkVxfQk3L7YIFSbv0hIZaTko9C0XHbwU6jNZcgNh9Tob51mva4oSu3pScGaEB5tMphsCURHKi/0R4bGIeerKHrlm15mB5F/qpGmVd20krty8cx+kC2netyaJmwsiCegTTnOkjTAE/Rc2YkkgOWHFW6Q94ctnAlATNAoGE/Gt+c1lJezI8jQkaIzIp9RwZiek8o9GsMZMVxf6YH1VdnRzHSUsyJZDJxJREhoReGcF+JRljYW/KphFHf4REZYd7TxuIMcFSHiqzzdy/6DJLVVKTwMwSQUrQMzaceq95HZEp+mBKIsUgiP1qKn+kWeTULL6hDg4oD029KhOBQTNKr6yveeZHT8Ntf62wLc46lOyBOUC68p1isjAlkRxgA3vRaUpksrBOopXcNoEx+xuGqOyBhtkKRBILB2Nr3XU/maY5SDj8AQjQwPpOUDDHsNgwzykwJZGxQCqGknO2Ht/RsGfE2MtZbIMtTLpEHaDWNUSyUNbFbNhNygfJHDFVwgBgdX19Jp6yabcxDkHU02nph9Xl5Ym8Xzkx0ec2JZECwMBkuGLMzFvzS5xzdLJO1YVo622MsdjArwlD3S9kacfvtxzB8tpqJ2cZxVVoBOiHShC1+yacfIxzoet+hofClEQKAOdsJfqVdv+b1h4nDSQM6xDbJpg4khj0Eg7zkjbihU7Ol6U/ylfCDi8vbU+mZHoS0KwZuKpA7DCk/icIYH5Q1vXVtUZc+yn6o2oSmchGSk8ikVjKyYAztjR0oTVdiVhP1FJO60TbaqiOqUlFZVY8lfJ44Mp0NcipDgBLq2tHRL8yTr3SMyfr04sQtKWkA0/M/R0SjT2vqRLpg/4DDCO4jrOkZ5nQOeWfJnGm9VInVAhjQAAMRSIV26hHPRZLfIpE5S91nAZY7LxW11Z3mK2x3UC8quVXu28EGMkqCNCC47rUQB/cFENiSiIp6LegKItTBRFADncOw9qY8rVWQkl/qVkUAEBACDoiJVEP1lZX87RCkzLqchAqr2+a6uDRcmdg1ncbq931I+U3y3OSSMWqUCP9nnOCJDcCBENZSqRO1PF81/5OTSqJFN0iD12ebdLyXPdwrKefNnq4LiRfagZVP4ptDEgcWXOvsEg/Rl3IMqENDU0mSV+I/mv5QwAA60H36Nhkn3oX5wXXbATEZbrcRMMp3wxU4byehOeuVtRNIo2VsmFG3chMWRjBc9wD8TTxUcONOclUEzUBjBAyOhLIXhxofXWNNcDR2RQTWqn1SFuMiqWQisbPLrpgfj0MjpEJmU5vqhmzbFWFhEtE+vh1D4ZBQBxxOOx6mfmLRd3P7SQi9zWrm0SSGLe9LSLGtiefMFOdpGv1ju/vNznTFgFKa7irRvKQurOqGh0iHHsoXE99qbtr60W+hLU1zpMIbcrq5w/5xi9+fGMiuMbQZf5q6cLM31pgLxPNGMAIBL5wabiUz4S6ksuEWgSmz98IaBqJ9EOfSRRGztuDMEEUon9eIoC2zs3fkDrn3ejVKBGye2j6q2oQIjHMnbe09yZ5SrBf6tXllar9H1W86KMQ3dgGI9s8pSOzVCExf4htymIA++3ll9wsIg+LcrhNPxGxVAstRyL/m67Lru7K8YBWKPmwsrShBx2WgdKv1ySRSFHI3ZILNddtSgExK9VRW7bvjpVuKxLjJqnBrtUjnLRtgUV11J1axrA3XDvRTt3tFqpAbIyrRsp8MWpvpOJkkiSS3vpdt2/vafoeMk01Opg7M1cJyHreTD3sr4TDYfdGg4tsQsfLoAofzMShKBJp1J0eAkPVW48V0b/1U3HjI4/ao5nFUExsGtP6HSOxCC3dMVQ2avmHYUkENx1YTjUvdV1EMqpzv7C6pM2ZFVckkSlLa4uDy4un9ZqyrKQ1mLF6njf93JjnjmEN4vjp5IuTj2FIZFPfbEpRJZoa/vQ2p+/iDCuRPlHek4RXveKVrq0Dx1VRDIxDN0/rIjx1mGJzjBUp2/9RpIGm6JZ25PI0kST9IczartP+39VXtFfX124uuULlZHZOpUoYB1NGstI7xZQgkNhZMRPquw7KNJ921+MqmDHGShyb1ASV0IQ6jISmm7NqJ64MZ7rtZKfbn3yzFYe7u3SOuIM9IhYActW5OmFFyMjHlpT1naEL3CLLPp18qSvAMMcb18wwjvIp5Lokx4fY6oOZO4QevfH+r37hlgLw9RbWo0SsGrLYAcqHIgs5PsV65pSjPwCdlJZtPfGsjTk2adR0ZZczSgesdCU8SrlNJ5EqMbB1tyK0jOFK7/Nc53pNHMbkMyi+txY+ociRqZ2cikhC4PjfHN49MGIm+VL3ca7rA4yyL8/+ZNphutnDph0GI73UHHGHudQTqaYsg99cfsntIorhAOdKkchtjLN6QnwNCGZ6HUupgzGEgk64dOXggp06WO8OrOkQzvVxOxfjpp1YdTEMyiaR2pXEiCABInusSHIUe0JfUMfzr4QgkIiUCAmVQBAgID9U8cfUR5EbWfWAFiMMINk7vHhp/+2SF8PuGZYwVqRIIrHzDPoUUb/CVUiaKSstKgvq9zV7dt8DpPboU2ORc73nlOt43tQzF9VCP2/MuXBx3837XRv9vFUY5rsRUeq1m2QlkkVQlCPNUEiG+aaF/W6dnbvEHFJP0xhzsuvvNSE5ZiVmzVLPGGc4EHbvkae4IV/qsqV/WRiVwEZCpEJY0qthjfyIfCQf+5+vHbO0tnorpkN5HQ7GeSJXmi2rYiizlj4FpkUVZ9jdXTlDJ0uqkD4dliYTSpPrVgrqIJEyWtI8ZeYmF3usiB3mS1Hfyvxm6vfOLduuIJtAtBqB7JH1HrBOkWYziWUoIYY1Cu+clSvtpS7I2VmkzbsolKGQeqCJIxmVpfWE/g2wHhXy6e9+6081gUizVfTdJhGmVUqVdq2egbYU880wtWMN1KN8gfgAVzsicIMvTjWRaIISSbamVXsRhilTmbDifhECcLubnnppjDxImbDSXqYaYeiMgEiOwDQ+IeH4H+6/9vi+ZaQoqgF+EXWwsfbrNFU0IqPWday62VO/p5iyOOKqBH+87pr7a90C7QfhyrPCedwfYtes8mbYeuYMLcpPl8Rtl8KuU/ABp0RTHAZeyyaQSONhR2hZSiSmSp72wIdd7XC+n8gK702IHxrkaC8LPY2+FTFDViujTAzXrC7eMllEQVOfFNW7L7ORqESBAHEVkuZQt3WirUIA4L9++L9HSlMWB7hSIo5jviOhRupqVkk50RlZSkjTIxiIsbnv7bv6VoPKSQZzFDRyvernbUOS25RE4ujbxIuYmSumSjDT7gjfdS+TP0WkRmxnNgjG5JXriAXDPi4j5Q+BFQMkm6tlCm7s+l7fmuUMuxwFw7zYRdYhT3n99peiQriiAyQMVO/+yuf+nyYLxjngqMgszuTMvaah5lbVqjZlJRUIWaasiEh2ra3cOW1VzYLDyiehAU/WMa3OjfMTTQKJ1GX/iUVo2c70FD0hAGDGb/1Bk0ZEIASIxDjFei1akUnL7qGaiB5gWQT3BQDP8/sTiXKuazt1DpMWULz/Y1wyyZu/UALpp0K45dVQKkS/p+Y4l1537cPMoEJu53IsMtElaBVQJyxFAvWsqTouUXAvAMjquGhf3HrieVMo+sSqvFAb4lhFkkgthpoc2/N874ukc936Gytj55bt5ycVSHzMSJJ+arhklLgEFO/nMs6wLui237ruspOziiggzLdoItHp0zwAo6bLW5eRrwU3pNFXhcR8IQyMvfOLnzlhPQyO1r6QyJTFwRzLwY6ISMav7eiI+eEYGUKTzMkQEN3uF/uuPdrOo8PK+z1rNU3GWDcbNw6ToETyYpwWuSdvcjZfO208QkvTBtHdbnHrX8YUCAlrr3qV6grzTRxXGhR0A6NtWdo5y3DhgV1nJ4uwzQsFzKGVl0hGfWmTZDFqWYU3GmmrF/ZRITGtCIB9/NtffxxjHHAYmMPBkqYsHpVWnzMkYdJCRBqRX4RrqmQXLe67Y//iapbvo2MjkE7fcxiWREa5k2l5BkVkVR2hNbB8rUCEUSIgocxYGn//l0+43GFsn00cOlqrxyU/8IgVQNmplYHBGFgY51gl8eeXLu6fTWaxe4a2X2RIk1asBgWmKxqDjju2GctWIdy4w3tUiNETF111eeeafbsfDq5SOZEaAU8xZVXtD8mEOoPIHRL1XRjDiggzla/Ganl+OGC0C1SzxmsGOGq30Dca1M+ZrtNIoxAjAtGM3/6trUZiznWtW+oaeJjoHZKeCl6bs8CU9Z2BMca+evmFfz2oyAJGEg9DJE2yIY9FIPZf6cmIRnroeKukeQsAe8bbXvtUMMajqCwuTVlKkWi/SORzQOQPqbGZs/1wEa1FY1oWw+6Dkz64tIhA7RdZWVpSfxs5bqSJdSoNk2LOGrfFHcsvEkoySZnF1w79ld8XZubOJ5LTn5AQ8q+lSgTIiBPtVKn9wxhINVVkOTwPrq89Nc/1SWJINQIM99KVTSZ5yh/7+NzSfS441+ShPBycm+mVIwL5w9VXti+7/prHgzNFGlJ56MgseR+VhgEHqTio6G/Fn8RgW/mh2DNHijYFY8d95o+/PT3reuX0wxWtbJtABml1yKpX6c9tGiaFRPphLIIYJr1l0tIzBCFp0jrluBv9ggntC4FRJBA6FyVm8q1YkdhqxDLNM1BkWOGqUeJs67vO+/5Dfb83Smt9dY0l7dRjjiYehXiKfCnyljfSMfuZsVjkHs8yYzEAeNIbXv5scMalbpHkwVzXEApzHNWz1wdqQhsYgYhifjgTk6bGtly5vP/x/ULLR1S9zboINTX0BSCzXhuBRMoAAX2d6zqR7eUgAPTsh/zleQACUk51vUJ73KyVdcSKoc1aQGTW4oiaOcfBDatLf9+viLXVVZb2co+gRoDRiIFhdEIZNm9hBKIKU3TAjBLJMGPhqz/9wRFX7939aOZwMFfeGxORpXwh4MrRrkewA40wZQGIOi2x6qhBkmqUzKoQD7ph+bBvZ7ODOVqddswvok1ay4tLdZ/dOJjkugMonkSqagqrbHLt8SKU9IsQyF7tkG55wkkrs632D3rUB7RdmJRrRGAAR5WHxHH1vEqM6eVVoZoyDmLs6Df8+BtP8lr9x4xoVDiXVla+YT6l1ymLQLQZK9J92WYsAOzc9771rVDOc+kHUVObuOq740STL3LWHId6MiowxQ8nOYSDGHP+48Jf/F2yiKQpa72eGX0nvrEvC1UpkbQGKLlt0O8i6zCSCSwxHXxSV5jfR23d/j9y0LoyawlJKGbsiLaA1cQhPWC2GuFWn5gBnGPf2so/XnVwX6v6WjXixR25HmmTK6rtikCMfugxY9lk8sAXPvuJy+trp+pwXm26gusqs5ZjaRh9/xAzVzYCPQEdquNiabBDwdrTr1s82EozofbDhKuRicYoJFJX09fvuEX5RXJUojfUN7l07p/e+nY/JhJSiYQh9HgRmVJ/txcXqWGhEfv46juBoKc40tE9zOEgzvj7fv7dF3l9XuwCTVpJ1EkmIx+3NxIr2w/iyBEfxqxl+UHYZ777raMuvOrSZ8hG1vaFOEqFOFFUFod6o/V9Vt9Zxc9Wv2eNaW5T7n51ptbzxj918a+eDABJ9ZvmXNcmrTFQxbNVxjGyyqzc5zL1iWSDAOMXiRGTbdLS6kNtIwLEuY98/BUed66wHetEUaRWPDSLEkesB3rKEwaAjIFF9mq542ApWD/zixf88ri0vL0rHZYSdlklmYx1rH4E4igqcMCchB9EEwhnkQrByz787rfEyMM40Lk1Z1ZchZiSmoiYHw6RH85akfHA+trfBkKknsDayipbXV1l3dW1nrYroUbGuQCjNsRlXfSm3MzUekwyiYzb5A6lWLRfJGnSUv8liQZbZ+f+B0IAKtRXrm4YIhp4SJFZqy7oU2EMxvGpI3qUUUV+pOP2e5dd9Aq/3aJ4EZUz36g+jUrKzUMg1mgOW4Ho6RRNHR7+0uc/dml99abShOVKxeE6YJ4LuI787jjKsW7dO3M6455NgUjxwxGg/HBcWVKZOhfMvvEn3zwLAPqpX40hOi1NUgSjlNlINI1Ekg9MES3UsOatgWlsk1aKg50IELc8/sT/JooIJD4dCkVHISS/VIvktBRAFBuk52JSA9rWie77/Usu3GZnZ/X2eMdt+AslpLwEYjvSHTBH10ERCAeACy+/dOa8Sy9+phxIqAjDdSPicFzAcVWUFourkEmAdqxbY0UiP5yDg+urz927vOjWXc2SkLxJE3LT0qFJpMgWLKustO3DHrdf+mHJIvfx+pm0VKKe4731rOf93AHbb+jFjtTSKiStF1+XScsmAz35BiB7hmaOJobP/PrH/1pTDQeBjfApBNya40pHYbkmViqdQOTV7HGkq/kCwB71qn94BzHe0gTOFJHA1YrEHqGu3fNafejw3qLOsCDETLe2WUs72TlIRZ4R597bfvTNlwJAUv32w9TBXj2apkTqxEgmLT2SXVGD0GrEdz3aMT//2aQSISIIM+gQkUKpE7YaUaYtPcV4fACig3Wie7zw8//xXPvFbrXbNZ9AfbAnU+wdB9KfQKIpEyMfCAPYbZ/+2Lcvra/ekrlyMCFLKhG9TYf5Kt9VFDY7AdDTnxj9JQmEWyszLgXBX7/9B9+4a1YRdqhvzaHlTUOlzvVRSaQpjUbeemSplGFUUyIBpTrY7SRHbtl2QeQTEfJvqGlGH6Yhl9IewW7F8UejFxwTXrp/beW5b/3GF25XsymrVvSqj95xIEMSCGMAu9OzznzF/uXDZ0CZrJgjfSAReUh/CNxe45hEw3whSaR1mHRQh+64OMyQ5B/37vqXimvYU7uaj98PjahbE5XIOH6R0kxaecqP4rAkO9zntqf/Qv4SVmgvxcaMxEebULE1HxFmPQppz5IRQI4mEvly/+baKz60d/GQq1VIq7N51Ei6+oiF8HIXnEd6IR+B3Pucpz/ruoN772/MV44bEYghEmtgoZn2XVWmqWasJFKmh4+Cm61QA4dDMHbCG771hXsMU3xDTVrj1qkp59RTj7JIpC6/yCjIRRJ6ChTbpBWfS8u8GSbf3z7oEdd1PP+ncrAhGTVi1hdRw0saYdKSFYmbQxSRyNlW9UA3NV8Tc7a+6DMf/ve0YtozMyT/dmInFTW20afM0yka/dSH7f+IBhJGUVjJER1JAnnAC5/1pD9ef80TDFEb05UD5noJU1bcjDWxilDX2x58yDUNR1ftj3t3v/PQ6rLTxzcyygVo+kVrev0MmqhEhsW4Jq2x8iYd7Ak1gpOOPOYThjxEpEjSJ2NsABSZ2bM3GUd7zCjjYF2IP33mv//rcwepkH6EMQmEkk0e6eYrxyIMm0AQd6IbAnnQPz7nzAuvuuwsxiPfB3ddMN8F8zwwT5OKjsayzFhNd6ZnIemHA6wgAaV8mVFc8y/94iffAdSueCfl6uZBgYElGw9lmLQGHsseSgiLSN72jHO+AqI1e7S69pFE4b5WcHBDTFqAVCBxx3o8Uoi5DvavLD//+e9/+wN1nqQKGYYcmkYmyfokySPNfGV7KexVPpBBIH/71lff/YIr/vhMxp2ILDw3/t11AVf6QrhqXGPz+7IJfY2TyhfqopiOCjekuSqCB77oMx96tJ3WzyCUmbnZSSCassN8K3uPmvr0DfKLNMqkJRLpbC/H0dt2BNtn5z+hTVp2tBaRMLmbufwn9SiRyKylHb8cl+/d/d6Xf/wDZ/QjkKgHn/6xj1qnOkkeW9fPjY0Jj8jDAeMeeFIf2HPqOizqW8cI5Imvf9mfffXnP3yjUSDKic5drUC8yC/iyJkDtOM51YzVGPodAmnKV0VrmU6LUmDXHzr4hjd/9fOnt5sRDcgyvmelqaIetcAmkap8E0X4RUbNX4ZJK1WNKMogAHjuQx/zduNc1/Np6VHsqSatJqkR9VePp9ZEYpOJ6+D8Ky/73Ave9447JQnEJol+PpE8hFIWsfSvT7ry0L6PpPPcMcQRjeJg0Uh0rUjYXf/uiS/89vk//2fbhMV8LyIQ7QPxXaP+NC3FBhVOmhmrD2LK1ygSNUmjes5+e+2V//n2r/3nKUkVojswU1SCxDtaHuq8qeOatHLlT1Mj9hgS7R952F3vtXfWa33dKBHSKx+SNYYkPm18I2Dm07L+MhZFazmRrZ67LvvNlZd97m/f+Op72wSii8rjE0k22MMQyzgfXdek6tADBvuRRzQHVmS+sh3omnqh3rWDi4fd2531uDdfvXf3wxjXpisvTiDKhBWNTo88LBuVQABYGo2Z84wNtlSfH/3x4s9/+ze/mk8rIs2UZd9rp0Hm0hHQyLo31ZwFVGPSGpZsyDJpZU58ZftG9La73eLW7ySS40TscSOx6VAG1bAOWGNGYkrE8ovY3y++9qqP/vWr/+nhSfUhv/c3afX2/vsTSxrBDEJa/shU1Usc2crD9n3E1EfMgW5PpvjeL332xDs+6wkf37t06K4ybDfye3DjC1EEovcNcqRvJFgrH+oYtt4OiwNwvvXd3/jif+lsndl0H0iWcnUmn0yKQiHXgP2C9o1T6KD0w9oKBzmbhvndz2aZJ13md8c0ivJNjvqHJlpHWaz1BNcy/x2e9+SvdYGb85YP5nngngfu6YbYNWMxopHHrPfodcBeB8IePBmG8tMNQWEAsd4FBQEoCLBjdu71X3zVm98BxBXJuEj6n9LTUC6nflq9rEVbDYFF1vr4dz1Kw15MKmG+Mjfx2f/6mrt9+ac/eCMY47FGMeYDSRCIFc4Lx1FHR5xA6n42ioZeBRRQz1oICoV6rkJQtwvR7YK6AWZd76Mffu4/vqA9MyMAo0Lse98Tds8SHce0KY2SeQr8Psy+cdLk3Zdnf998p2Pb2EqkSL9I0RjFpJXrobAd7DkKNDNm3ey4E95EguRLIQQgQmPW0qasVAd7E9QIlDnLWqzKBLEqNcKNGcbF3qXFf/jzFzz7X9e666kNdd5PMm8eJeOCcVtRZH3s42hPj3aUK2d5Qm1E37XpKqk+0gjkkS8/9xFf+un33wzOOHMdcFd1IHz5YfrjZRCIViCmc2Eu5IZEPGBA3aGYApbXZylY/+unvv11zwfiZqxh/GZTRTI+xlUiefIMo0YGKY1BaYrYV7gaIZCR1bc/+0m/IIfv1A0Hdz1wX05noaS6av7QLDUCQI+uj1ZsFECgzHJBAAplb1F0pRqhbggXuPAfH3vmYx54p7sdAuI9/ZGrMSKtJo8ZmdmiOuk0turQv7lRlXqCDmas+FD3H9Ex2Nd/9qPt//TBf/uH3YcO3DsW0WabsowjXY1K141kMtaric9DWTArgFJsuiAKQ/l8KbUrn7EAW9qdN/7nq974RgDg8QtDqrMQC36x9+u/YdQhLFOVlPF71O159/fNdzq29ZAIsLFMWsnfRZm7GGB6McphZxoR0+AAsoGyieSv3/Dy+/7umis+AF+bszwZgeNGIbNyHW3WzEaDKObHoVD7eeQLrolEk4gIAjAR7j5u6463fvblr/8YEDXmZURaZSF5rIgcIpLQv9OIpB95aPMW1O8f/PbXC6/9xAf/34VXXvpkwTCLWA/aiZmyIhOW7aqPCGQiZuctA5SIczRkkiAS1WGZcbwPfPiFL3/pzq3bAl2ENrPYJALEJlCdksiEk0jWvjpIJG+6kdSISm9I5U7nPO2/1kF/wvzIrGFIZBLUCNDzgiMMlSJRfhLTWwzNy+4y9n+3PenkV77z7Bf9MKkCNMZRKFlIlplUQ/b+JJmkkYe1n1smNwaAPewlz3v0by77w9ND0Lwxv3C1JogXjQUxpKFJxCYQFca7aQkEyHzOTGclCGNqhIIAXIjfP/4+D3jU0x788L26FKCXRABjip6SSP40qflOxzY4T3/5C5I7RnlMi1Qjg0ghT5oiySJrHyPIRpBg1If6LpMx89s4+RgBOP+P/3fxVXtveCzT4ZraUGIs6tbfppGI9o9Ybb+21zO9XzeziTxC0I5r9+x5xCe//c0bd7vd355x6i2WVEo26GONGBjqk8xnjd1IOMkN+ev+v71wlImyisgj7vt4yQfeeevnv/NN/3jZDdc9Gpy39Iy72s/BPVf6QLQvxHWVD8lTIdIWgei5fzcrgQC9zxlTb5T+EfurCEfQzt/88Q+P/v1lf/ze/c64825TVMqFs1vNMIdvs0Fo1FNwLDqFKJE8eYYhkbTtE6lG5PZIgZDVxN7h7Cf/nFznKKlCBqmRBkbjkHlxI9OWCFXUllYkQpm3AkuhyL9MhOvHbT/izV961VveD9iqYDhlMqxyyVIhluIwLVRSeSBGkcyQx1d/9oMn7Dl88E8ZU+GoRoFwOWW7p4KIXUt1+Mr177pyKhNjvko60RvUgagDichAkHq+LB8JBd2Y6hVB0L3Dyac9+K3POfd8oFeJJM1ZYbqfxP5epPooQnnk3ZZnX579mfmKMmflydNvf9VqpMh0DOj1jejvtlkLiBPJQ15+7pOuPbD/FazlqR6pbzlbtQnECjCN9ezRDBhHuyYSNWBSj4EJQmXDDuTvbhCFBattHvgfb3zEzg+/49n/8JnjjjgyBHob+DxIi+RKlpH+PZs4rHSmPvo4T3zdS//s15dc/LADy4t30volUhLWADkznYle5lYRCefqPuthisw8NY3tONSFZIg5WQEdtulU++OUeeuoLVvP+ewr3/CxfiSSFuJ7+MBBpo5HC9u29uwf8vsw+9J+j5om7748+zPzZZEIMPxjmyf9MGpkXNIY9LsSNSITRk529dt8P+PsJ/+CPPco7rlgnm+FyOppLiy7eFMbFZGwXasx/FqRwKgRa1yJ+iAITI+Sg12/fW7u63c89RZffu1Tn/PbJIHkUSiDt/VEhhlyt39baWLpP/Htbxzz6f/9xr0uuuqKh69012/KGFNEnyQPqTqgiUIvLqVWKoRSKQMd6LEabXLEIrYoitgSIiIPO6hDKZMZ1//Um5/5vHNuddLJXSAenWUpEFo8eMgQR3RI+Z2IaMv2bcOoklHTpf0eNU3efXn2Z+YrkkTy5BmGRNK2l0Ui/faNpEbk73SzlswgW4kz3/jKe194zZUfkTZzP5r227GIRKsRoLmNi577iwBCNCdYNChRveiKMCJikWQiQumY12l9h//hmG1HfOHON7vl91/yhKf9Xz9HeNpvWITDMu5nGnEk0jMAeMd/fuom3znvZ3e47Ppr77l/afEujDEG5cfS03KYBbu0+cpWIVytQqhUBxw5E2+02siUQHLDJpJQdVZ0ZGBomUuDIKZQmKArbnr0sef8+4te8T2WcKIvHTrM0ojD/q7/KiJpKomMsj3v/sx8TSGRrH2DSCFPmsrVCJBu1oI1VgQASOW/57nP+OAqxP24GrHMXT1mwAF0yC9ruBoxryRFRGKbHkLLX6J9JcJ66fU4E0EmykubxDzmXjrf6Zy3bW7ukoWZ2RuO33nUtY+8x30vudPNbrkcVWAo0oht1/jjNVe1v/DD79z4oqsuP27/4UNH3nBg/032Hjp4h5Xu+slMH8K43llsDEc0ZbljfB9yiVc3Rh56bUPGUsxXQHR/m3RvmwbbhKqnDdKRgaqDImxFYsgkxIznf/jPz7jza5/72CfsXjp0mAGgxUOHGVKIQwjZM5rbskA2sWzZvm2Q/2TQvimJ9EHZJJK2rSlqBMgwayGDSDSJ7D54wPmLl//9/zHPbcmpUOxxA8r56sSDhjNrVidsIgHMgEQT7x/GHe92D1IrEWPmshfwChURmRH9AhxsseV6V/muu2um1b6y47f2bZ2d233Ewta9s53OypbZueWZVjvwXTdo+61wbX3dW1pd8Q8vL7UPLS3OLK6szO85fHDnytrqtgOLh09Y7a4fvbrePTEU4RYtdaK4LRZ95zz6ay05Jc1WHIxr8tCqxI2ZrfQE8VP1MSaI1Pw3FDnbRdgzKNEmEAoDiCAEJ9pz8xuf8JiXPu7Jv7HKyyQRACAhaG7rFmO33bJj+yDTVr99TSSRvGl68hRNInnyFW3SypOmNjUCAE40vgBZRPKoV7/4YVfs2/0OPZ9WtBiRtqcza/I9FnW8m9bgpBGJ/m3PuaUnogzV2iphAKGngrF7lSLuqI+RkonW0RPukzlurC5WfXoQu469ww0NgVjBv9HitrYz3bGmgYlUhzRdacXBjfowZQPNIxBdr6ZHvYq4j0QvtWCeoTBEFMEVRGpXkcvx23c+4g1Pffb3V5eWGVmEocmjPTtjFIfeP7d1C1VAInnSTASJAFM1MhKpDCaSKOQXiIjkbn//t18IgDswY9ay1IirnK9NN2sBPUQCxEe4w8wTFoJCMvOHSTIJIURovpsVIGMEJBsMyRnWipAUHdN0LAc1hEyPIGCW+gCYJhIzbJRFJizG4mM5tCpxIvMWHAfcjCTRqxCy5qmP9IC2dDSRVJJBHaazYYUAm7+WMgkFRBDg1sedcM/n3O8hF4dhSGvLKwwA/HZLAECr05aTOs7Pk00yc1sWBAAoIqmLRIbZ1m/7sGl6cDq2kTtKxjFAGO6VyZM+mWaY3/3KH7aufesoQDrEVzCACxDZdvrH3/N+Z33oO1//pe7RUigARwBMAKGcOEWCyaoN0wBUCVW9qEcLQ5/ECGAExghEDIwJeTUUqcBh4CEHCQHmOJH5SxCYIhCme51EYPb0KwTTqLCYIkm86z3XLVJ2cdNVouHnahbd2FDEaFwIGEshD0Smq5jLvmYC6ffsMJZOGE1UKFw+O4wxeYc5BwOTzxa06gujgbxGWYbgHPjd9Vd98eKrrrj1ztZMVxe5tLjI250OhWFoLlLWVPMTBP1WllN4xUqkX5ommLRG3ZdLjQCxyf56orUe8oq/f9Kuw4deJQceWtOEm7DQCTFrafSYlCiuEoTl79BmLjO9hb3fWrBLj0XRoZ4EpUwSaiT5ziR+Ro26ViFqa2wce9T4GKLQjnRNNGY8u2W2mhTyyNMRSZ1VukFtalKBmoGv6pmC5ScxgR3SP0JhCI/whRff/UHP0MU5nisAQISC2p0OtWc71J6ZEbPzcwQAQhAtbJP+kS07tmc52ZO/61Yig/bl2Z+K07GNiiaRPPmqMGnlSZOHEEZJp0ijP5EQtHU8nv/u5z7jK12H/Um0SJEXG2cQjWjmzScRIJVI9Hf5VlrkoBzw5rue4FH7QZKLeFHSdEVxE0dPRaILJTlDX7+IUJimd6ZJId6LZUpxgAFcE4seVmqrlyaRBxAnjAR59KzVrkA9ii7lexNgEYl5rgyZRH44M9LdDEyU0VsnzW378zNvfZffBkGgpCzg+b4AgHanQ367JWbm52h2fo6mJBLHIHNWkeacccodxaQ1DvKauLLS9WzXpqsQEE5kyoJ+Am0yeeid7va3n/nJ935C2nTCwogwBAMDyfmt9T1nrLw7VQRiV0t1+YmMAAAHCOrcSJq7iLgxWzHOjemKBEldbtnApZXPdq7Lv+ZyJNefZCk/mNaCWpUwtVmTQuSPYlplMMSJAwPIo+fYFSKFQJJrdvSARHTrbKLW16RJRKLvmZD1YwCIQZpSwUGcgQnd8QqNiiTGQJzjiqUD/3r44KH7hmFAfqtFfqtFayurrNVp0+rKCgvDkM0oJZITDbo45aOfEgFGe+zz5Gm6Gum3L3e6NDUit+v2UyoSnUEPSHzYq174mOsOHXizXmfCRGy5TsKspccVsNHuVNXo6V+J2D4ZaaN/KOe5WXdeGIIgIpk16UAn21yWdkCN6Hr1KhJmrieDMlNZ+4wyAbO2WWUAzSEPoIdAIvKIXYAUUojuRaRIEmqkqX65lAAL+Qhp02ioZlCQMwCLbhfH+7P/7+HH3+IXugjXdYXfblOr0ybP90VndoZm5ueoMzsrAGBh2xbqo0TyqpK036OmydqWZ1+e/akoy7FeRr+4CjUyrgLpQQgiRSTGsQ6AQsgxJMo4Y/wkQr627PMvee0n7/2C59xnNQgfDAaQXqPPngJFEIhLp2KjX2gb9hUEEo2tkL14B4pQHEAAjGtCkWm1GmHcCh/WhaqvIkYk2fVgVkNqzxYbkYxudFlk4jLkgbjq0NuT51onbHKEfY76PABDIJzBRLwBikBERO76qSeKrltTnzv1TujzJcbBSICY6oCFDECoTl0GetzQXXn48uHFX3m+T17Lp7XVNQYAYRBQq9NmANCe6SR17RSwnLsVowi5l6eMQYw+KnPnsXcSEJ9mOj7xm9zPEJsQzuT7zuve/nRGdE00P1AYOQeTYyaAaOqRSYBqw+LbFFFaPX7m6IF9UoHBLMWr5qRy9SqArlqjXn64qz6eIz+u+sR+u6YMbpURzV0WBTTAKEA9FsR2wFv1zjq3OpBKILbS0hWVRKAthAAi5adUIDOBDMo/BSvxIMKuCwkzZBQ5Zz0/+i93EXD+J6tLy3xlaYmvLq0AkKe2rsgEAJYPLzbhzvbDOPUbOe8gEqnj0cg65iikUdSxhym7L6nYhJEkEusjBIgecLsz/jIaLGXFvGsischkIsGQ0ugmGmalEhhn1orm3JCKIRg9V5X+6KVonbRtboyETBluVKYZZZ5JGinE0ZQmZhCBWGoKjJuHUMoOSSgt8K+DaB+JEER6qhqyIulSOjBNfAzVeXIwE0kHbt1nVwaskMu3AkCw3mUrS0u8u7bO1tckgaytrLLV5WUGAEuH5ESNQgjav3tPnjvexKtSKMpSIlU0+KMep2w10oPkqmn2qmqhUiUspYx/+qsnXX7iEUc+xZ4HCGrKEBMSq+29hMklEyAHoaQoFd5LLnpq9WiVQCfxiVYb1NOWyI9VXsyhnvj0rW8DkEeB8Lh5izGYydJJhPAgzj9r603O3ur67yJBZq6z5MwBJpTWRtMeQdvHpUO09X3m0aqT4LyzurLCAUkk3fV1BgCaSABgeXGpaXe7EajLnDUIZauRUR1fI5u4+hGJ3N9DJAQAH3nBy7+ytTPzxmi0bRAbzU168J22W08ykWgw9Gmk04jF+lgrROpFnno/1v5+ZWXVp6lNyUACAcC4CmZiUQwbQYVQh2BEux7aPvpvwiBgTz3m5h+mIAgo0NP2h9HytCY0G41/7mIh8bpzwB3zDEhly1pBN2CGSLpd1l1bZ0QUM2lloLknXwHKJJGqLmzacYZRG3nLTNs3VLrkMpzadKV/h8qFbH0EAHzxFW9449b2zOtgTyynpnSIzS+1kYjERloj3o9kcn9yZpsE5FEgikDAuAyBVdBTyXCiq+9Ncw/fQc4aAIigi2P9zvMoCOXgvCAEAqsDE1odGFmQ+lvNKY8Cpv9niHUiGHMoDAIWdAPW7XaZrUam6I88JFLmIzGKKWnU+tRh1soikiSZZA5a0quyffHlr3+LS+ynFOg1E+Kz3poR4MkXejNgGN6YZKLIQi4CUTFVjEUPGEF54UJAhEt3XGv99QmsdTDsBuaKPPWU07/WIvpatHpgGFPCerxO7vnKqkIyaowhmkFZEypj0tnOGMCxDMhorKDbZfo7IE1ay4cXq6p5Qy5gfjTVnDUs8qiRIsocdx+ATCLpWfs52idf1xc+5gmPZSK8NlonQY3AtSaek1OBNOyFnqIcGEc54gSi/R6aPHhEIAYEROu+CJyyws88fp2lDhp7wd0e+BwE4UHqdhHrxKgxF3rGgYl43mL8qq4PY2Dgi2EQMnvOrKQSWV1eZsuHF5k9TXwKJuAiFIuySWRcH0aT1cgofhTLB9JDJMZXos1cKi7GEMt9b3fG8qPufp/7IxT7qKsjtqzQ33BKJJsGKYMI7Xm/dEvJ1PgPabqBGclt1isXIbaviZfeZs29RBfneC4BgOf55Ps+HbVtW3Cbo270NxTIgXkywCMEwiAWct7sAI/+kpMz7NHfwyDIJJIpepGXRJr4VCQxqhoZlRyGOVY/Isksg6Uc/6yHPGLXvW552wdAiFXqRmtJmxUDA6VbQj0JHczaC9PPBvmYJ0M2jMywg/XRpELSdENm1DZgJrUMQ8ythu+6x372JQBwXDf2vLm+R17LJwB47v0e8utt7ZnXUzeEfO6kEkZg+Ue0WUtAzYFW/3Uy18Zsl7/NpNjqejkh/XF9ddWc++rKCtKQMv1J8ne/ff3STiyqMGfluXDD3Ihhyi0iX78HYex9Kt4lM59NJDqi66VnPvXy29/klPsjCLvGVh1kKBLol3lDPr+bC1nmK2OfiYdA6+2Rn8wiEBFidj14z3334b2O48TJw3UpSSgA8P5nnPP2Fuf/AxMpqMcuaYOraLZfztYUCZ+JH+IPWdm0b2QCUEs9N4pPRCPtIubZNk6PYRQCTO6jfkSiBx/a+1/+V0+66LYnnPQAhOLaKZFsAgwyX9khvHKWSMuJznoIZH41eNu9bwjfA8bAXYccx6FWuyX8TlswxtCZnRW+79Pswrzw2y1qtdsEAP/5T//yN5xwQTxKMPHMUcPMqbYlS32Pmd6IMLse/n5QMe2ZGRJhWOQJNeDijI9hSKTsEy5KjeTdNihNXlUxTNq+56h9IOrT4xPRCZfk9Av0qic89YJzH/qouzmE8zKJRLYexhbeiJd6ivxIqo+Eyog70fVaMwCgCETdc2nOEoAIV44/1D3zXrvDDzuOJA8gWtFPqxDblMUYQ6vTNg/O5176Lw90QJdHRKJnUtAmVGoekWiQNHIBxrIFAEsn7Fn9nU4SBhFReL68Bvb5a2zbecSmMFcNQlVKpIkXt0iz1jBlj0pOqb/veJNTV/7u/v/vESypSPTUFGa6ChH1SqeYDCTUh/yTYb7izErOVKeBII2gskvCgvCGm+3vPuY2B8UFjuOQViF+qyVc16VBKqQ9M0PtmQ4tzMyKP7317Z4UPW+BdLTrGXITo9oBVEskyfBeudGqi+5cyXpxIf7grXZDO7WrggtsQklBXe1ao9rTppmzqlYj4zbiedMWpXJ6fhMR3eW0Wy4/8V73u7dD+G0U/huFYcZGtifn2kp94aaoFRnqozd8FwllYkdg6Snz1b0Pg8U/2bv++Jsuiqs1gXgtX9hmLM/zqDXTEa7v0cz8nJCHZ6m98H96/JP/cOPtR5xt1IgejNgzJU9NRGIQt2UpaQW7M+UIkekPAQC/1VKEMpRvZBSVMqoVpVYMSyLjnFDjL4ZCUcSR/F0IkSwdOsyQWLaPiOiBt7vjwU/83Yvu5zP+rWhgWDRADCKMEUnqQkNTQqkX/cgDceURma9s/4d2aevGW3rTeBBccqt93Ucdt0J7kwQyMzcb2gTSmZ0Vs/Nzwm+3KE2F2NX9jxe94nM75xdeLp8xYU3JE59ni2wzalVEYq6b/m39tXwhAOCEZEgk7AYmqECbsjRm5mZpdsuWYTqzmwJNUyJA/WpkEOpQK72/U4gEAD767Bc8oc2dD8RDf/UUKfqvZbNOvFBTMqkByWueZrriLEYgPeYr9RcE1XhLFep3g2896Jr1R5+4TLscxyHHdclr+cJvtcTM3GzouC4lCUSbsdqdDqWpECAaz/Spl7z6fdtm5t5kCESHmod9FHClpi30EoiBrFNrPUxVIkEf5UE09klsGNKpmkTKvHB1mrWqUCu9vzOI5L1/86wXb291Xpw6jsR+ofuZG6bqpHykkUdq5BVHuvrgUQy4Vh46JCMMMbfafeefX9d9AQBoAtE+EG3Cas90hCYQ2w9im7HSVIiNz73sNW/e0u68WZpPQ6WArY6LGPCsFX1Nezeav0z/VANFiIBth9cvdhyHwkTklVYifrtFtm9Er7HeBxuGIPJgFBKp4gKNokaKKj8rTXlkMEbeZI9I/37rXz3tAydt3/lIFobXmjBMPYGejqhRiw2RLpSx9Jd7SibFYhB52Kar5PQlMfURN1/piDw3CM8/ZjF45p/eELwfkIMI0wjEViC+79PWnTtCWR0G24w14GwIAH3s3Je+6YjZuZebgYg9RBLNpFBt1JYlQwjGv64HXzIRXnnsvtXdQDTY0vVcCrqBeSUAoD3TodmFecXX/QcJp2BDk0od5qwySWAcc9UoCmWY8gohEvUgDyQSIqIX3v+hP37qXe59L4/o69pPImITN1rmLTNVSh+ymJLJeMhLHgnTlUyTpj6gevjaVBmivR585gHXrD/p9P3hT2zzldfyRWd2JkwjkNn5OaEJpNVpU0utLa6rmaJCyPpgZUku2PSh5/3j+047+thHpxOJZT7VGbM6LQVc5+h6Qj3SBGKRAtds4oT4LdAbheX5PmmHuut5Pcvibj9yZ9EVr5toRj5+E30iGqOeVJFmrUHlF20GG7rsmbnZrN4RhCC6wwk3XXrHo5705AXXfYXQDveuZb8WyhFKUVQNJc1aSUxNXcMhxWHeSx69fg9tukpVH3b0lewQrG9bCV7xZ9d3XwNE5ivtQPfbLdFqt8XM/FyY5gMBegkkoUJixKGhCUSn+efHPemHxyxsfU6MSEJdR2EUSTSOpMBnKPk8svgPZkKjI7OaE4aX2KmUGjGkoYlEv2c5MIqVY5h0dZNND0YlkXFPpCqTVBFlDCtVKycS80OhPStf/s7MDAkh35Z/fsCj3nvz7Uc9iAlxcWxxK2uQmOkpCst+PcjhPiWUdCSvi/U9nTwSfo+Y6Yqr6Z8oUh+I1IcbhN+/5d71h91tT/Bfmjxs89XM3GzYardFq9MWrufR3JYtYdKJniSQVqcjiIjaMx01qCIThlxWluTKf//6lGd9/sTtR5wZzbFlP2tR9FZsNgX7uhUGfc2ta0mAWUyFCN5a8AetQuzpX1zfIwDQZi0AmN2yJW3EelNMWYPuUWloshIBylcjo+at8nfPPm2b1b9n5mZjcjupSoQgEkLQM+923/Nff9+H37fDnHfFne7d+Euune764KrhGhgOvNkJJYs4LNXBrPUsesnD9nvIffF7AKkUI/WxvHWl++oHXLt+9onLdL0dvps0X7VnOsL1PJrftjWcmYsTCGMMrVZL+O2WICJqdToCADqzmf6QVFVi4w1/c9Z/3+6Ek+6HMNxtD4KFFb1lxjAlHe6jPEPWNY+CEux9lmmLyaoTCHMrQSwyi+Jr+8DvtIZpgxqnEqpAnSRStpIo2qzVZCJBkkhaM6ohsEwSeh2EV977Ia8+YXbLYykIDkfrQwRmsBgT+q/8aBMK09EtSXWS9tL327eRkHaO/VRHxkeu+WFaOQCIOaClIziKvPLXg6/9yZ61h959T/g5W33Y5ivXdck2X81v2xr6vk8z83OiMzcbqs4GtVot4SdMWCkEMpA4kmn+8RGP+92jT7/LfR2i80Q34ZNLGQTb43DP8/wkSNtc6x4Voq+pJbCJDh57zcHLAcBx45NQer5PenChdqqLMKQtO7b1ey/Trseo2yYG45BIE2Ranv150o96Y2slkl7FEV8spzXTEXpbqyOdo17LF0IIevad7vODB9/0lnfziT5H3S6o25XrQ4RdaeoSgZm9S5KJnslLqFeU1OgE6xNrA/vsS9s/KZ+080hsi9o+ltjH5Btn/VZ+cglVHjFt5lEhuxQAQpogEQaLW1fWX/Pn13dffPy6s8cmD3v8h/Z/OI4jZubng3anE87MzoSdudnQ9T3BGMOWbVvFwratWQSS/KSCLKTtf8jt77z3A096zoNajH1GBF2pegP9jIXQ41n0LMB6pLtZIDrruiefI8MlVlr7mkKXFf1lYXipIyLlEXS75Hke2U71dqc3tDnDqV50ezgxZFO3OSvvRRn14g2TL89NG+XGFk0k5vfcloXYyzu3ME9pq6612m3lOI1eCCEE3evE0/a9+t4PPfuk+e2PaAEfM053eyJHY+LSRydrrIndHiZHCA9QImk98iYiq46JbTFzVY/q0KYrmN9mtUHT+pFZ9kL6pPQ1VqPOw/DyLavB68/Y3X3IvfazT9umK+465Lpu6Ple6Hpu6Pp+6LdboeM4oj07Kzzfo9n5OTGzMC+8lk/tmQ5tscgDANozMwIAdWZnBvlAgFzkov3+8nl83xOfffaRnbmzzej22AqJoUUeFC+0X/RWwlwYv+7o3W6YRR7HXQ9+GB2GhGNNPrmytBRzqnfm5pIRWqO0SY0kgXHBfkGpK2IOVUZF+Qel67c/bV+Z2/LkKez34sFDjFkt+OKhwwwAOOcMAFYWpcNzbXWVr62syO8rq1EHmMu8HzzvR7e55ODecwLQfZnjgjkc4BxMfWRPmkc9bPVyyqgX9X4kyKDvwN5hwjvLHFOQh8ASaWKEqW+FuSb23/g2xuJ5tKFQ/rCn7ZfEzcJw79y6+NA9dgUf1XkdxyHuOOS48m+r3RJcR2N5Hrm+R+2ZGdGZnRGeGkDotXwzgNA2XwFAZ3bWViBpyLz4y+rZ0ukS0VpYXYr2ry4v423f+cqtLtp93bsEd27KHAfywwHHkc+Yfr64/WyZi95zfHvW4jiBJGc01oQsO0YiCHDM5Xvvc/ye1SsdxyHP9wK/0xbtTkd4LT/0Wy3aftTOsN3p0ML2beHRx99IAMCWHdtIKZFk5y7PNRumEzpu2mH2503Tg9OxjZpAIsOUMSqRDLN91G3D/i6ijKGJZHVlha2vrnIgnUjWV9fZ2371v4/cv77yfMH58eAOmOsAnMXJhFlkonuDhERvPeWMMYBYZIL++8tEBqGwnu3pJJFJHIYrpNwgTbpqjn5SvWNp0gEgQnTWww/dYV/4noUuVoFe8tC+D5s8XNclrT46szOh12pRq90iKPNVGnnI7z3hvLmwvLgU+50kEQBYVWlWV+S+/ctLzsu++pk3rZF4NHMcSSAOjwiF2c+Zun62wzyGeIcmUiA8UniAJGi1HDAFXbBu9/zb/fTKR7m+LxyHh57vC00iM/NzQavdpiOOOSpsz3Ro25FHhPNbtxp/yPYjd+ZRJXmsGHnzjrp90L5R0sXynI5thSgRYHLVSNb2iSUSANBk0o9IVpdXGOeM2URCAIL1LgeArgjZv/76u2ceCrtPJ8aOh8PBeEQm4NGLGjclQPUg5V/zaJqXP/tZHX86ovHRSxZAXGmoL1nfzR8GppmDASCmBrsp1aY5BKT8AaqxE2HY6or/uvFS+NHTDtNlQJw8AMDzfeF6LnHHIb/VCl3PI1eRSGd2Rvi+TzML80KTR1uF76YRCBHREGMgZJUTSKgRSSTWzVxVxKJJRAiitZUV9qr//sJj9q6tvAaO02aO7KxI9WupEq1IYqrEetYQPXNGGRuykddfqzutQijoYuGGQ48/9dL9PyMi0Z7phI7j0ML2bQFjTMzMz4m5hQWxsH2rWNi+LZxdmCNNIiSIdhx9ZJNUyDj7hkmTmq9JJDJMGUUTSdHkUgWRZKbJIhJAkkkeIumurjHGOeuurbNAhOxdv/vxEw6J7hMEZ6dp85Z50VVkEWxCiY4Y6yhGNWUpj239BCKRQhiDflvfe4hDO45kkw1At69k/EsgAiM63O6GX7jJgfBjJyyJ67kasyBVBycAkGYrl1zXJcdzyfVccl2P2rPSdAUAs/NzwlYfCQIhIHKg5ySPgWk0iWj/3GqaGllaZkREK8tynzarfvr8n97oZ1df/obAwb1s0xbntiphAOcAuHykNGFwTRz6PiQIhKmJKc3aOtL/wlfXvv8nP7vyKYzzkDucOjMzod9pC9f1woXtW0PGGLYftTN0XVdsP+pIkTBlDVIhZSmLKYkUXMaUSPqk0UQCSDKxiQQA1pZXOBARCQB019ZMkIUmEgAIugEHgPW1NfaBS3714L3B2rMFZzePyCR6yZPOzZi5S1am1+SlXvYeVMEpPYdNEkSfbRYzZhOHkRsAs6dEJzNvGYQ4ML8mPnjageA/j+ryg0AUbjqIPFxPKg/X9yipPvyWL9qdDrWsKUvsEeh9CGQkVaJW2zTQREIJRZIkEalKVtkrv//lFyyL4Gzmesa0xS2fHLgT+Uo4l1eeq0fWhPLaCgUgxhSBQPqYpApZPem3195ty8G1g9zh5Ld84fm+mF2YD13PC20V4vqe2Hns0WJ+61YCgIVtW0VNKmSU7Xn3502Tmq9IEgEmW40Mu71UEigizzBEAgCryytsbWWVcW4CJQ2RrK+tMU0mAPDhS399333dtb9cY/gzxpkvFQmPTF3GX6J7hfo9t3qOejui79AHriJSK4tAsvb1qA07IYGs7+YPs+eLsoiDCE4oLphbpy/c4qD46vYuloC46nAch6TJKp08Wp126PkyHNVrtWhuy3xsEamcBDJs49E3vUUkBETmUw1NLMtLykeyHA/yePvP/+de1y8vvUpwdjJ3pdNdO9x1kId5tnh8jjGu7hHZfhOh/SHREr4z+w//3SnnX/s11/dEUoV05maEdqgnVcjCtq0CACwSqZIsxlEam45EhimnKiLJm3aUBj9PmpHLtYkEAJYOL/aEdK8tr/C8RLK+ts60fwUAfrTrip2XrRw6bU+w+sA1Ch9M3NnKrJebcRnuGp/W3DJH6N48g+V4ls10+hkVFJHe98mxlIc1txPTdSXLKa4rTtZXY6oCjMNczRXlhfS/c13xrSNXxPknL+EqIDbIzaxxrkJ2yXEccjyXPN83kVeO55oZCmbm54Xf8smeur0PeQzr+5AnMGS6pCJZSZi6bHMqED1zQkTTibzlZ99+8P7u6ouFw080EVycA65jRQlGysR0RAyBRH4QWCP8OwcWz7n5Bdd/iQiCO5y0L6TV6QTtmY7xhczMz4bt2RmaABUyzr5R0vXkK5pEgGrVSJ60G4VIRk6Th0hWl5YZY4zZ5i1NJvrp6q6uMU0kQOSs73a7DAAu3L9r4WeHdz3wsAjv02V0LzDejhGKfsHtkdl29I1NHLGwzeTJZRBMbrA+P1nPJtIbtE+DschMBcu/AcjtBOnnUL95SJe0wvB/j10S/3XqYXGFPT8Tt+dqcl0ZaaV9ISOQBwD4asoSIB5xlYNARjJjJREjEUUcPY53i0hWTOTWikmzvrrGDq2tOu/53Y/PWWH0XOkncY2ZC4ypv8pHAvWcATD+Nm0+FCEQBNct7D78vBN/v+uX3JFqT5uxHNcNW52OWNi+NWy129Se7YTtToe2H3Wk0A71Da5ChknXk6+pJDJMOXnSDUsk45JLlSSRO98gMrGJBIh6iACgySSpSuQ+zjSRdNW28w7u2vG7lQP3WEJ49y5wZ8FwnHG+80ihZCuT+FQVtikp0wyV64lJSaQIQhKban+N45+s7/I3gSE+vVLcZAVB4EL8th3Sd3eu0vdufRi/1ylt0gB6VQcAOJ5Hnu+lkofn+9SZnw31Wh9m3Ee7Te2McN0M8ihLkQAALSVMp0CcSIQQZCK2lpdNx8U8e0vLAAFrq6vss1f87hZXrB1+k3Cc25rILccBHBkdaIcCJ31tJATc1e7Hb3rR9a9rH1hZziIQbcZKUyFhENC2nUcQYEhkXLKoSoXk2Z83TWbeMkgEmCw1krW/KURSaL4eIjl0ODHMPFuVADBjSbQqAQBNJgAQhiHvWr+DbpeFROxL+y6/50EW3nUd4g4BY7cEY76xayfj/5PEoreZM2LWJivNAKSm6vG9SNIwQoMoYdayBwNa+wTtdwWd1wnox8eu0vdPWcLVQDppAIAmDsaZZi0Yv4frShLxPJpRo6Q936fZLXNiGPIAeudTy4lCCCaFSCjpl7OJZPnwYo8aAQGHDx7iYRjQf1zz+4cdRvA3wnHuZAbBOhxgjrJyRp0SgNbdteBzW/cufezEKw9eHAYhcYcTd7i6vv0JZGZujo4+/kYiJ4FkXYOiyGJKIhWVMw6RDEMYWdurJoSxyspr4lpTgxJtVSJBZjyJrUoAoLu+zrjjME0mgVIpwbr8+/u1g9svCRZvtUji1mtM3D4AbkWMHcG41QjoMQEAzORSFpHEfSaKVPI8Ln2TKEliztBy0pCQ39VcHpzoOlfgd62Qzp8P6PzTltgF8yHW0krlrmNUhiYKfTybOACgPTsjPM8jT023MTs/J7y2T4PIA9b0/ypfWWaModMnySRJJCuHFwEAy0tLbG15xSjh9dU1FnQDks/XGuuurbPu+jr7zsFrT7mBB3fqMtwqdPjJYGyWc94Fo8OOwCVeN7xwx77VHx+ze/kGANCTKPotX+gBmkkC8VutHjOWJvARVcikEMgw6VLzlUUiwJRIxt1WdvlYPHiohzjSTFyAnC4FGI5MAEkoYRByoJdMNA6Ide+8lX03PcDCm66QOHkddLJg7MYhw03AMGciunRvU58QS4ioYSO6kukpSSAAiLqc2C4HdIUbiv9rhfjDQoA/3GaR/55nvHxcOcodxzHk0I84tOrQ5CEn//NJk8fa8ookjk6b2p2ZGFkAQE7yGKuhGDd9D5EcPBTbr30kmkiWFiWxrK2sMhCweEg+q6tLK1hZWuLBepd1u10WdLtsfW2Nh92AwjBkYRCwMAgjJRx0yXVdssiDXM8LHdelNALRZqyKCaToPHn3D5suNd9mI5FBaZpGJGnbCi8/r4kLkGaHtdW1nilT9HMYrHd5mpmru75uCCQMFakkyAQAgkBuC4OAXSvWZq/A2o0XRXDkKqPjugxHBoyOCIFjCJgBYx0CWmDkMsZ8AnMB6A8DM/Pl6goK9QkBBIywBsa6jLDGQMsMWOYC1ztgu31B184IdtXRXXbpjVawP1lPnpg23FYagE0agE0cnHEZgeXLMF2v5ZPneaqn3CKv5ZPf9kmrqhHIYyzTRInpKfU5i/+GXtRqZWnZKJK1lVW2srgM/VwtH17kQbfLNJGsraxCkkcQkUe3G78/hri90PPlyP4sAtF+ECBGImlmwbLVxjgEUmSavnnLJBFgSiSjpK2DmICCyWRtZZU5jsPSTF1ARCBZhGKTidnWjb6HQcC8lp9yGr0IrXxpCIL++5MQoTAqAkDP1ZS9XUUmrhzXAQxPHACQJA8ioo7lKB/CbGWjNlWSfMaSimT58CKziUTPy7W2ssrWVlaZTSSry8uRuu0GTD8faysrACIi9zyPSM4Dj86cnJCSMYa5hQXBXS4aSiDj7Muzf9h0mXknhUSGLWtKJGPUZVgyYZyzXjMXAJAhmDDQo96zCUX/FqGImdQ0oahyMkkl4xyHQ/KVGlCqWo8baaQBZBMHAGjyILV8sSSPDulFxJLKY0TyqIowcuc5fOBg7HevqUvuX15cYqtLKzFFsr66aoilu75u/CRBt8vsZWxtMMaEqwZlMsbgt1rEORcL22XYbo0EUnSeYdMMky4zb9kkAtSjRvKkH3V/nUQyzHHGqk+qv0S/7Bah2GQCAIPUCZBOKEA2qWiysAc5ZhGLjWCAAhkWrmWiMuRhEQYAcIcLz/eN8tDf/ZZvCMRrt/QK37DWM6fOTK/JqpMIz80gj3EaglHzj61KDh84aO7P0qHDzF4HZ/mwfNZsIgmDgCSRSEe7nk1lZWkZQPS82GCMCf24avOVrT5m5ubIdqIDEYGEYUhHHndMst51E0gR+0dNm5p3kkhk2LLGVSP99pdFMHUqkNTteckEGI1Q1tfWlNkrnVCAXlIB8hEE55zZZJMFEfYu4mXD9bzU/ZpU0kgDkMRhVEcf4gD6qA7VUiaXQh4RTVMldGj/gaR5q8fcJU1cy0w/V4BWJWtsZWkpddWAFTWtir7+fqtFfqdFrusa9TECgWSdV9VKowmmLJO/ChIBpkSStb0yE9UQaTPLSL7gQH91AgwiFCCNVABAR3TZSCOWtH39kFeduDHHuIRNFvZvjSy1AcSJQ68ymVQZaYMCRySPsXuXJebpSZtGJGSpkqXDi2xZjYLXZKLNTua5iSYLjUi8E1/eNuh2Y+rDNl8BA01YWedZtE+jCIKozJQFVEciQHPNWnnSVE0kadurJo3M7aOoEyAilNXlFcY4T/WhaCRJBYhGw3PHSa1XXiIZBkmi0NCE4aiebcus0xFVodVpU1vNYaUbsiRxAL3kkZM46jBhjZIvd/qD+/ab74uWqUvj8IGD0GSiR7/b6iQMwtRjub4nZubmlKKT5CHTx/0fwNAEMsr2svYNk2aUtJl5J5FERilroxBJWfn7be+bJ6860UiavPSI+HRSAdKIRcMmGI3uWjFE4rWSKqNlfqcRhr19TOIowmyVRNPMWJnpD+7bH1clBw4yIeIGq6VD8pnThBIGAdlTqtjXNghCml2QBKLJQ+exyQNoPIHk2Z83zShpM/NWSSLAlEhG2d4EU1aufWmEAgynUuT3QcSikf0O9M+Xjpa16l+E9GKShAFkk4YQguZS1EVBfg6NOpRJaXkO7o23SYf29yoT7YhfOti7r2P5OWxkkAf1qdeUQAbkn2QSGba8vGmbSCRZ22sljX77BhIK0FepAHFikb9XYr/X19YLmhc+HUlSac90SNvq2xkOcRslEEcRpFOlKhk2X0/ag3v3xe65EILSCMXsD3tNWnpddEoomhHJo9++us1Um4JEgOarkTzpmk4kRW4fZ5/ZPyqpAOlLrQK9JFMk7AWczLY+hAGMRRplmLBGLbdqksvtBN6/e0/m/bZXT+zZp8gjsRZIv2NX7RAvQoUMk27YtH3zTzqJjFJeXUQySp46SGNswsizP4tUNPr5VepGGllolOzbSENdyqYWZTJCmirMUWUSSJFpRkk7MP/p2AZ3zAJHqUCRDcOw5eVNPyhd1v5++YbNk7Zd38C07cOWnVVO2vZB++z9g/JjbstCT71sYhnUGOdRMKPCJom0Hq7epM6hbNRpwioi/7B5i+p1N8FMNW7evGlqR9UkAkyJZFwiydpeJDHkyZO1f5Q0qcRiI4NkesoZFzZvlEgUZZRbJ1mMk79Ic03RfolJIJDaiaYOEikDG4VIkLKv7O158gzKl7U/maZfurS0Jn1FPf9xMCnKpIhyqlInRTSkVe8bN+8wKEvpDYW6SKRoNVJmHcYhEvTZV6RaSTvOqPUaZZ+9v1+aZLpBadPSZ6Go56kuspqqk+Hz1NHQj1NuXjS9wxRDnUqkbrPWMHlGJZJ++0YhmWHzlEEYRZmz0tLmzZO3nCag7Ho1pdFqijopc3/Zx86bZph0o6bPXcZGMWdpTBqR9NtXJMnUqT6GVR5peYbJWwWqJqw6TSBllFFGA1imz6SK/XnTNA51k0gZZq2NRCT99o3j46hTfYxCKll5NwLKOqcmkMU4ZRTZI6+bIIomkEb4QjTqJhFgYxIJMtKUta8KAsq7304zKF0ybd48k4JJMGU1pZwyGtFJI4c8aFxHqgkkAmw8IhmUpgmqZJx99v5+aYZJl5UniToJpo4XuGmmrKLKKbM33QR1kjfNMOnqRGYdm0IiZWGSiQQZ++val7U/b5pkujzp85YxqWiyKasJ5TTRd1LE/irSjpNnKDSJRMpQI6OWWyWRYMD+ppCQvX/cNFnph8nXdFRBdnU38kWXVWYj2RSCqSJtpWgSiQCTSyQYkHZcssjKW1e5w6bRmGRz1qSbsoourw6T1ij5qvKfDHOsYdOOikqe2aaRCDCZRJI37ajKIk9eZOzPqy7qGBOykcaDjIKmm7OKLGvccsryoVSlUEZNO0r6otH3+E0kkTIxCUSCMfePW3ZWmjKUR9bDOenmrKpe+o1IFuOWU7Qze1IJpDLiaSqJlKVGRi07TwM6TPnjkMGg/eMS0aA0oyqPosaDTM1ZzSizSaa2Osxbwx63ivTj5hsJTSURoHlEMky+vKRTtirJs7/sMtLS5s2Tt5xJRZnn0lSyKKrMMhvkutXHqHlqQZNJBJhsIsmbtghVMih/v/3DlJE3zaDjZeXJm6/pmDRz1kb2zdRJHqOkHzVPEXlHKq/pJAJsDiIZlK5IIigy4qroQYbJfEnUTTCTbtKaBLIoosw6nfDjpB81TxF5R8YkkAiwMYgEOdIXRQRNI4qpKSsbTWuAqyyz6PInmTzGyVcrJoVEgOYSCYbIW4Qqybt/UL2GJYCinegb1ZRlYxJ8HlWVW1b5Zff2J4VAaus4TBKJlI1xSKrJqqSIY9lphikvb/qsfKOUUTaq7C1OKlGUeYyqzD1Vkce4eYvIPxYmjUTKVCPjlj9s3iJVCXKmyZuuiapjIqV+H0xyQ15V+UUcY6P7MWon60kjEaAaIsGIxxjFvJUn/WZRHU1RG+NiI6iVsssu+1gbnTwag0kkEaB8Ihn3GGWqEgxIWySZ2OnypB0lfVbeNNRJMnW+9BtBUZR9rKp9EU0gkEYQ0aSSCDAZRIIh8g+TvgwyKTptMv0w+YYpbyNgEsxCTTxWHQ15U8xPjVGgk0wiQPOJZJT8RTvpiyanZNq86dPyjZJ/0lA18W00QirymBvFd9GoztSkkwhQHZFgjOOUqUrypi+TIEb1i2TlH6esqrCRzVtVHaOKYzeh8W/S+RRe/kYgEaAaIiniOKOoEgyRp2in+Sjpk3mGyZenrM2ASTAHNfnYTWn46w4WqAQbhUSAySISDFlGnVFfaemHyZPMN0r+jYSNaN6q+9hN6+mXcd6NVZ8biUSA8c1OVR5nFDIqm0xGKXvYfFn5Ry2nKdgMjXXdxyzr2E12djdSfdjYaCSisZFVySj56nCYj+s/GoSqOgpNwWZSMBqNs/+XXE5V5RZ6rI1KIkC1RIIxj1U1meTNMyqhJPOOkn/Y8icdm01NaEwyOTbdr1PJsTYyiQDVEUlRx6qKTEbJMw6hJPPbmFTz1TDYSKaf6fE3DnkUgo1OIkD1RIICjjdqncchk2HyVRV91WSCadLLXlddmnQNbEyqeWki1ehmIBGgWiLRx8OYxxynjHEVzbB5yzJdNbWRqhoT2bhUhI3QsE90J2CzkAhQXeRW8ph1mbjsvKPkL9IfMkoZmwkT3YhUhEn2ndR5jNKPvZlIRGMSVUkR5RRFRkWVMU5Zk4QN0VBUhLrrO4njWmrHZiQRoHoi0cdEAcct0sFdVBjuZvOJNKkRaFJdstDkOk5MFFSBKLQem5VEgHrMW/q4RfsMiiCDIolg6hMpDk2+Bk2uWxY2u3+p8LpsZhLRmGRVUmR5RRFKsqyiytyoaFIDY6Op9RoWU39ThFLqNCURiTqIRB8XBR67KSazQWXa2Kjk0sRGxEbT6zcq6j6vuo+fhdLqNSWRCHWZt8o4dpmqouqR500imaY2EGmYpLoOi6adW9Pqk0Sp9ZuSSC/qUiX62Cj4+EWrirJJZdDxpoiwUa/NJJzXJNQRqKCeUxJJR52qpMzjV2GmapJymHRMSkOVBxvhXCbtHCqp75RE+qMpZFJGHcoqe7P5PkbFpDVISUx6/fNiEs+z0jpPSSQf6jRx2XUAyqlHmWSVdgwbdV/XojGJjY6NSa//uJj086+8/lMSyY+6VYlG2fWoglCyjtcPdQY8bCRsxHMaFxvhmtR2DlMSGR5NIxOgOvVQ5zlvhBe9CkyvU39sxOtT6zlNSWR0NMHEpVGVepgOIqwfG7ERLAsb/Vo14vymJDIemqJKbFRdpymxFItGNAwTgs16rRp13lMSKQZNJhOgvmldbDTp2tSBRr34Dcb0OmWjkddmSiLFoolkAtRLKGl1SEPTrlleNPLFrhHT61E8Gn1NpyRSDppKJkCznOU2xn1Rilg4a4peTK9TfZiIaz8lkXLRBAUwCE0llWExES9cgzC9Xs3ExN2XKYlUhyarExsbhVQ2OyauMdrEmOh7NSWR6jEpZKIxJZVmYqIbnk2ODXXvpiRSHybB1JWGaeRVNdhQDc0mx4a+l1MSaQYmTZ0k0e8lmdRzKgsbukGZYvPd3ymJNAuTqk76YaOG9trYdA3HFACm9x3AlESajI1IKGkY50UsYy34KaZIw/RZycCURCYDm4VQhsX0xZ6iSEyfpxEwJZHJwzRaaoopRseUKArGlEQmH1OVMsVmx5QYasSURDYWpipliqZg2rBvEkxJZGNjSipTjIMpEUwxEFMS2VyYDhScApiSwxQFYkoiU0yJZeNgSg5TVI4piUyRhqzGaEou9WFKEFM0ElMSmWIYbIbR51ViSgxTTDymJDJFkcjbKG5EspkSwhSbEv8fVN27eXMmtgUAAAAASUVORK5CYII="/> +</defs> +</svg> diff --git a/browser/branding/tb-alpha/content/about-logo@2x.png b/browser/branding/tb-alpha/content/about-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..193c856f3e8c5e85e17d01480cf04c43a98896c3 Binary files /dev/null and b/browser/branding/tb-alpha/content/about-logo@2x.png differ diff --git a/browser/branding/tb-alpha/content/about-wordmark.svg b/browser/branding/tb-alpha/content/about-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..1fd9a2f443e601b3b9701b7378f2bb00cea92352 --- /dev/null +++ b/browser/branding/tb-alpha/content/about-wordmark.svg @@ -0,0 +1,21 @@ +<!-- tor-browser#42319: Make sure all the about wordmark SVGs (release, alpha, + nightly) have the same size. This will likely add some padding to some + channels, so the background-position for RTL languages should be ajusted + accordingly in the respective aboutDialog.css. --> +<svg width="416" height="45" viewBox="0 0 416 45" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M337.358 34V0H341.173V13.6246C341.823 12.5477 342.633 11.678 343.605 11.0154C345.004 10.0617 346.689 9.58485 348.66 9.58485C351.521 9.58485 353.794 10.475 355.479 12.2553C357.164 14.0355 357.99 16.7377 357.959 20.3619V34H354.144V21.7924C354.144 19.4399 353.858 17.6438 353.285 16.4039C352.745 15.1641 351.998 14.3216 351.044 13.8766C350.09 13.3997 349.01 13.1613 347.801 13.1613C345.703 13.1613 344.066 13.9084 342.89 15.4025C341.745 16.8649 341.173 18.9472 341.173 21.6494V34H337.358Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M292.09 34L288.281 24.5105H273.058L269.248 34H264.957L278.547 0.619917H282.743L296.334 34H292.09ZM280.669 5.54972L286.826 20.8864H274.513L280.669 5.54972Z" fill="white"/> +<path d="M299.66 34V0.619917H303.475V34H299.66Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M309.9 10.1571V43.5372H313.715V29.9955C314.454 31.2222 315.376 32.2233 316.48 32.9986C318.006 34.0477 319.771 34.5722 321.774 34.5722C323.904 34.5722 325.779 34.0477 327.401 32.9986C329.022 31.9495 330.278 30.4871 331.168 28.6115C332.09 26.7041 332.551 24.5264 332.551 22.0785C332.551 19.5989 332.09 17.4212 331.168 15.5456C330.278 13.6699 329.022 12.2076 327.401 11.1585C325.779 10.1094 323.904 9.58485 321.774 9.58485C319.771 9.58485 318.006 10.1094 316.48 11.1585C315.367 11.9405 314.438 12.9521 313.696 14.1934L313.476 10.1571H309.9ZM313.715 22.0785C313.715 23.827 314.017 25.3848 314.621 26.7518C315.257 28.1187 316.115 29.1837 317.196 29.9467C318.277 30.7097 319.516 31.0912 320.915 31.0912C322.409 31.0912 323.729 30.7097 324.873 29.9467C326.049 29.1837 326.971 28.1187 327.639 26.7518C328.338 25.3848 328.688 23.827 328.688 22.0785C328.688 20.3301 328.354 18.7723 327.687 17.4053C327.051 16.0383 326.145 14.9734 324.969 14.2104C323.792 13.4474 322.457 13.0659 320.963 13.0659C319.564 13.0659 318.308 13.4474 317.196 14.2104C316.115 14.9734 315.257 16.0383 314.621 17.4053C314.017 18.7723 313.715 20.3301 313.715 22.0785Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M378.009 31.5408L378.159 34H381.688L381.736 21.0771C381.767 18.5339 381.418 16.4198 380.686 14.7349C379.955 13.0182 378.858 11.7307 377.396 10.8724C375.934 10.014 374.106 9.58485 371.912 9.58485C370.386 9.58485 369.019 9.80739 367.811 10.2525C366.635 10.6657 365.602 11.2856 364.712 12.1122C363.822 12.9388 363.059 13.9084 362.423 15.021L365.856 16.4039C366.492 15.2595 367.303 14.417 368.288 13.8766C369.305 13.3361 370.498 13.0659 371.865 13.0659C373.295 13.0659 374.44 13.3838 375.298 14.0196C376.188 14.6237 376.84 15.5456 377.253 16.7854C377.563 17.6254 377.764 18.6268 377.859 19.7896H371.245C368.352 19.7896 366.095 20.4413 364.473 21.7447C362.884 23.0164 362.089 24.8602 362.089 27.2763C362.089 29.5652 362.868 31.3614 364.426 32.6648C366.015 33.9364 368.209 34.5722 371.006 34.5722C373.995 34.5722 376.283 33.6185 377.873 31.7111C377.891 31.6889 377.909 31.6665 377.927 31.6441C377.955 31.6099 377.982 31.5755 378.009 31.5408ZM377.921 23.9383V22.9846H372.103C369.878 22.9846 368.288 23.3502 367.334 24.0813C366.412 24.8125 365.952 25.8616 365.952 27.2286C365.952 28.4684 366.412 29.454 367.334 30.1851C368.256 30.8845 369.544 31.2342 371.197 31.2342C372.564 31.2342 373.756 30.9163 374.773 30.2805C375.791 29.6447 376.57 28.7863 377.11 27.7055C377.65 26.5928 377.921 25.3371 377.921 23.9383Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M99.1943 16.6591C100.019 16.0962 100.72 15.452 101.297 14.7265C102.41 13.3278 102.966 11.7541 102.966 10.0056C102.966 7.93926 102.489 6.20668 101.536 4.80789C100.614 3.40911 99.2945 2.36002 97.5778 1.66063C95.8929 0.929444 93.906 0.563853 91.6171 0.563853L85.0829 0.626673V0.611538H79.1698V33.9916H93.143C95.3684 33.9916 97.2917 33.626 98.913 32.8948C100.566 32.1637 101.838 31.0987 102.728 29.6999C103.65 28.2693 104.111 26.5526 104.111 24.5498C104.111 22.2609 103.475 20.4012 102.203 18.9706C101.413 18.0387 100.41 17.2683 99.1943 16.6591ZM92.5708 28.6031H85.0829V19.4795L86.3902 19.3998H91.9509C93.8265 19.368 95.2889 19.7812 96.338 20.6396C97.4189 21.4661 97.9593 22.6106 97.9593 24.073C97.9593 25.4718 97.4824 26.5844 96.5287 27.411C95.575 28.2057 94.2557 28.6031 92.5708 28.6031ZM85.0829 5.47549H91.331C93.0477 5.4437 94.3829 5.82519 95.3366 6.61995C96.3221 7.41472 96.8148 8.52739 96.8148 9.95796C96.8148 11.3567 96.3698 12.4535 95.4797 13.2483C94.6213 14.0113 93.4451 14.3927 91.9509 14.3927H85.0829V5.47549Z" fill="white"/> +<path d="M11.3982 6.14309V33.9916H17.4066V6.14309H28.8525V0.611538H0V6.14309H11.3982Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M29.0711 32.9902C30.9468 34.0393 33.0926 34.5638 35.5087 34.5638C37.893 34.5638 40.0071 34.0393 41.8509 32.9902C43.6948 31.9093 45.1412 30.4311 46.1903 28.5554C47.2394 26.6798 47.764 24.518 47.764 22.0702C47.764 19.6223 47.2394 17.4605 46.1903 15.5849C45.1412 13.7092 43.6789 12.2469 41.8032 11.1978C39.9594 10.1169 37.8294 9.57648 35.4133 9.57648C33.029 9.57648 30.8991 10.1169 29.0234 11.1978C27.1796 12.2469 25.7331 13.7092 24.684 15.5849C23.6349 17.4605 23.1104 19.6223 23.1104 22.0702C23.1104 24.518 23.6349 26.6798 24.684 28.5554C25.7649 30.4311 27.2273 31.9093 29.0711 32.9902ZM38.799 28.317C37.8453 28.921 36.7485 29.223 35.5087 29.223C34.2689 29.223 33.1562 28.921 32.1707 28.317C31.1852 27.6812 30.4063 26.8387 29.8341 25.7897C29.2937 24.7088 29.0234 23.4689 29.0234 22.0702C29.0234 20.6714 29.2937 19.4315 29.8341 18.3507C30.4063 17.2698 31.1693 16.4273 32.123 15.8233C33.0767 15.2193 34.1735 14.9173 35.4133 14.9173C36.6532 14.9173 37.7499 15.2352 38.7037 15.871C39.6892 16.475 40.4521 17.3175 40.9926 18.3984C41.5648 19.4474 41.8509 20.6714 41.8509 22.0702C41.8509 23.4689 41.5807 24.7088 41.0403 25.7897C40.4998 26.8387 39.7527 27.6812 38.799 28.317Z" fill="white"/> +<path d="M57.4468 33.9916V21.3549C57.4468 19.9879 57.8442 18.8911 58.6389 18.0646C59.4655 17.2062 60.5146 16.5863 61.7862 16.2048C63.0896 15.8233 64.4566 15.6326 65.8872 15.6326V10.0533C64.1705 10.0533 62.5333 10.4666 60.9755 11.2932C59.5835 12.0318 58.4073 13.1132 57.4468 14.5372V10.1487H51.6768V33.9916H57.4468Z" fill="white"/> +<path d="M114.044 33.9916V21.3549C114.044 19.9879 114.441 18.8911 115.236 18.0646C116.063 17.2062 117.112 16.5863 118.383 16.2048C119.687 15.8233 121.054 15.6326 122.484 15.6326V10.0533C120.768 10.0533 119.13 10.4666 117.573 11.2932C116.181 12.0318 115.004 13.1132 114.044 14.5373V10.1487H108.274V33.9916H114.044Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M130.119 32.9902C131.994 34.0393 134.14 34.5638 136.556 34.5638C138.94 34.5638 141.055 34.0393 142.898 32.9902C144.742 31.9093 146.189 30.4311 147.238 28.5554C148.287 26.6798 148.811 24.518 148.811 22.0702C148.811 19.6223 148.287 17.4605 147.238 15.5849C146.189 13.7092 144.726 12.2469 142.851 11.1978C141.007 10.1169 138.877 9.57648 136.461 9.57648C134.076 9.57648 131.947 10.1169 130.071 11.1978C128.227 12.2469 126.781 13.7092 125.731 15.5849C124.682 17.4605 124.158 19.6223 124.158 22.0702C124.158 24.518 124.682 26.6798 125.731 28.5554C126.812 30.4311 128.275 31.9093 130.119 32.9902ZM139.846 28.317C138.893 28.921 137.796 29.223 136.556 29.223C135.316 29.223 134.204 28.921 133.218 28.317C132.233 27.6812 131.454 26.8387 130.882 25.7897C130.341 24.7088 130.071 23.4689 130.071 22.0702C130.071 20.6714 130.341 19.4315 130.882 18.3507C131.454 17.2698 132.217 16.4273 133.17 15.8233C134.124 15.2193 135.221 14.9173 136.461 14.9173C137.701 14.9173 138.797 15.2352 139.751 15.871C140.737 16.475 141.5 17.3175 142.04 18.3984C142.612 19.4474 142.898 20.6714 142.898 22.0702C142.898 23.4689 142.628 24.7088 142.088 25.7897C141.547 26.8387 140.8 27.6812 139.846 28.317Z" fill="white"/> +<path d="M176.559 26.044L181.836 10.1487H187.749L179.643 33.9916H173.92L168.579 17.1966L163.239 33.9916H157.469L149.362 10.1487H155.275L160.481 26.3146L165.718 10.1487H171.441L176.559 26.044Z" fill="white"/> +<path d="M194.088 33.8486C195.423 34.3254 196.869 34.5638 198.427 34.5638C200.239 34.5638 201.845 34.2777 203.243 33.7055C204.674 33.1015 205.803 32.259 206.629 31.1782C207.456 30.0655 207.869 28.7939 207.869 27.3633C207.869 26.3778 207.646 25.3764 207.201 24.3591C206.756 23.3418 206.057 22.4199 205.103 21.5933C204.149 20.7668 202.894 20.1627 201.336 19.7812L198.379 19.0183C197.426 18.7957 196.71 18.5255 196.234 18.2076C195.757 17.8897 195.518 17.4923 195.518 17.0155C195.518 16.2843 195.773 15.7121 196.281 15.2988C196.822 14.8855 197.585 14.6789 198.57 14.6789C199.524 14.6789 200.43 14.8855 201.288 15.2988C202.178 15.7121 202.751 16.2843 203.005 17.0155L207.869 14.8219C207.487 13.7728 206.852 12.8668 205.962 12.1038C205.071 11.3091 203.991 10.6891 202.719 10.2441C201.447 9.79901 200.08 9.57648 198.618 9.57648C195.725 9.57648 193.5 10.2441 191.942 11.5793C190.384 12.8827 189.605 14.7424 189.605 17.1585C189.605 18.8116 190.257 20.2899 191.56 21.5933C192.864 22.8649 194.644 23.8027 196.901 24.4068L199.095 24.979C200.017 25.2015 200.732 25.4876 201.241 25.8373C201.781 26.187 202.051 26.6798 202.051 27.3156C202.051 27.9832 201.718 28.5078 201.05 28.8892C200.382 29.2389 199.492 29.4138 198.379 29.4138C197.235 29.4138 196.218 29.1277 195.328 28.5554C194.469 27.9514 193.802 27.252 193.325 26.4573L188.318 28.6985C188.858 29.9065 189.621 30.9556 190.607 31.8458C191.592 32.7041 192.753 33.3717 194.088 33.8486Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M222.071 34.5638C219.718 34.5638 217.636 34.0393 215.824 32.9902C214.044 31.9093 212.629 30.4311 211.58 28.5554C210.563 26.6798 210.054 24.518 210.054 22.0702C210.054 19.6223 210.578 17.4605 211.628 15.5849C212.677 13.7092 214.123 12.2469 215.967 11.1978C217.811 10.1169 219.925 9.57648 222.309 9.57648C224.407 9.57648 226.331 10.1328 228.079 11.2455C229.828 12.3264 231.211 13.9159 232.228 16.0141C233.277 18.0804 233.801 20.5919 233.801 23.5484H216.053C216.181 24.497 216.455 25.3235 216.873 26.0281C217.477 27.0454 218.288 27.8243 219.305 28.3647C220.322 28.9051 221.435 29.1754 222.643 29.1754C223.978 29.1754 225.059 28.8892 225.886 28.317C226.744 27.713 227.412 26.95 227.888 26.0281L233.277 28.1739C232.641 29.5092 231.783 30.6536 230.702 31.6073C229.653 32.561 228.413 33.2922 226.982 33.8009C225.552 34.3095 223.915 34.5638 222.071 34.5638ZM227.269 18.4937C227.326 18.6467 227.38 18.8056 227.43 18.9706H216.358C216.45 18.6481 216.558 18.3461 216.682 18.0646C217.159 16.9519 217.859 16.1253 218.78 15.5849C219.702 15.0127 220.815 14.7265 222.118 14.7265C223.326 14.7265 224.36 15.0286 225.218 15.6326C226.108 16.2366 226.792 17.1903 227.269 18.4937Z" fill="white"/> +<path d="M242.993 21.3549V33.9916H237.223V10.1487H242.993V14.5372C243.954 13.1132 245.13 12.0318 246.522 11.2932C248.08 10.4666 249.717 10.0533 251.434 10.0533V15.6326C250.003 15.6326 248.636 15.8233 247.333 16.2048C246.061 16.5863 245.012 17.2062 244.185 18.0646C243.391 18.8911 242.993 19.9879 242.993 21.3549Z" fill="white"/> +</svg> diff --git a/browser/branding/tb-alpha/content/about.png b/browser/branding/tb-alpha/content/about.png new file mode 100644 index 0000000000000000000000000000000000000000..3b93625ddd70f32e04152b167e148e63c5fd9233 Binary files /dev/null and b/browser/branding/tb-alpha/content/about.png differ diff --git a/browser/branding/tb-alpha/content/aboutDialog.css b/browser/branding/tb-alpha/content/aboutDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..f8525434604cfde7b66bf89aa2324f32b0904816 --- /dev/null +++ b/browser/branding/tb-alpha/content/aboutDialog.css @@ -0,0 +1,57 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#aboutDialogContainer { + background-color: #20123a; + color: #fff; +} + +#clientBox { + padding: 10px 0 15px; +} + +#leftBox { + background-image: url("chrome://branding/content/about-logo.png"); + background-repeat: no-repeat; + background-size: 192px auto; + background-position: center 20%; + /* min-width and min-height create room for the logo */ + min-width: 210px; + min-height: 210px; + margin-top: 20px; + margin-inline-start: 30px; +} + +@media (min-resolution: 2dppx) { + #leftBox { + background-image: url("chrome://branding/content/about-logo@2x.png"); + } +} + +.text-link { + color: #fff !important; + text-decoration: underline; +} + +.text-link:-moz-focusring { + border-color: #fff; +} + +#rightBox { + margin-inline: 30px; + padding-top: 64px; +} + +#rightBox:-moz-locale-dir(rtl) { + /* tor-browser#42319: re-align the background image after we added some + padding to make all the channel use the same size for the wordmark. + We can remove this it if we stop making the resource accessible from content + (tor-browser#29745) */ + background-position: right -34px top 0; +} + +#bottomBox { + background-color: hsla(235, 43%, 10%, .5); + padding: 15px 10px 15px; +} diff --git a/browser/branding/tb-alpha/content/firefox-wordmark.svg b/browser/branding/tb-alpha/content/firefox-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..65270a3cd9a966cd350ec717758c352661ecca4e --- /dev/null +++ b/browser/branding/tb-alpha/content/firefox-wordmark.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="172" height="42"><path fill="context-fill #20123a" d="M.19 2.82h25.72v7H7.57v9.43h18.34v6.9H7.57v15.14H.19zM34.65.13a4.14 4.14 0 0 1 4.27 4.33 4.12 4.12 0 0 1-4.32 4.32 4.09 4.09 0 0 1-4.27-4.22A4.27 4.27 0 0 1 34.65.13zM31 12.83h7.27v28.46H31zm28.35 7.91a5.89 5.89 0 0 0-3.53-1.27c-3 0-4.64 1.9-4.64 6.06v15.76H44V12.83h6.9v4.11a6.79 6.79 0 0 1 6.8-4.37A8.69 8.69 0 0 1 62.53 14zm3 6.48c0-8.17 6.06-15 14.65-15s14.59 6.06 14.59 14.49v3H69.48c.79 3.58 3.58 6 7.85 6a7.62 7.62 0 0 0 7.06-4.21l6.06 3.63c-3 4.43-7.27 6.75-13.33 6.75-9.22-.01-14.75-6.18-14.75-14.66zM69.59 24h15c-.79-3.63-3.74-5.63-7.59-5.63A7.31 7.31 0 0 0 69.59 24zM93.4 12.83h5.11v-1.42c0-7.75 3.27-11 10.44-11h2.53v6.31h-2.06c-3.37 0-4.11 1.16-4.11 4.69v1.42h6.17v6.54h-6v21.92h-7V19.37H93.4zm19.45 14.23a14.56 14.56 0 0 1 14.85-14.81 14.81 14.81 0 1 1 0 29.62c-8.85 0-14.85-6.49-14.85-14.81zm22.65 0a7.8 7.8 0 1 0-15.59 0 7.8 7.8 0 1 0 15.59 0zm16.86-.32l-10.27-13.91h8.53l6.06 8.75 6.22-8.75h8.38l-10.43 13.86 11 14.6h-8.49L156.53 32l-6.59 9.28h-8.48z"/></svg> \ No newline at end of file diff --git a/browser/branding/tb-alpha/content/jar.mn b/browser/branding/tb-alpha/content/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..11e3e15350dd36f8564bf5fd66f66630a885bf80 --- /dev/null +++ b/browser/branding/tb-alpha/content/jar.mn @@ -0,0 +1,19 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +browser.jar: +% content branding %content/branding/ contentaccessible=yes + content/branding/about.png + content/branding/about-logo.png + content/branding/about-logo.svg + content/branding/about-logo@2x.png + content/branding/about-wordmark.svg + content/branding/firefox-wordmark.svg + content/branding/icon16.png (../default16.png) + content/branding/icon32.png (../default32.png) + content/branding/icon48.png (../default48.png) + content/branding/icon64.png (../default64.png) + content/branding/icon128.png (../default128.png) + content/branding/icon256.png (../default256.png) + content/branding/aboutDialog.css diff --git a/browser/branding/tb-alpha/content/moz.build b/browser/branding/tb-alpha/content/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-alpha/content/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-alpha/default128.png b/browser/branding/tb-alpha/default128.png new file mode 100644 index 0000000000000000000000000000000000000000..4ba356e9a9df0d855bc36628cc4863464b5301dd Binary files /dev/null and b/browser/branding/tb-alpha/default128.png differ diff --git a/browser/branding/tb-alpha/default16.png b/browser/branding/tb-alpha/default16.png new file mode 100644 index 0000000000000000000000000000000000000000..8ac6a5ea6adc71b5d8fb888bda29e4f92697c48f Binary files /dev/null and b/browser/branding/tb-alpha/default16.png differ diff --git a/browser/branding/tb-alpha/default22.png b/browser/branding/tb-alpha/default22.png new file mode 100644 index 0000000000000000000000000000000000000000..78e5ff94f0b3a4371521d7c0f40bf820618678de Binary files /dev/null and b/browser/branding/tb-alpha/default22.png differ diff --git a/browser/branding/tb-alpha/default24.png b/browser/branding/tb-alpha/default24.png new file mode 100644 index 0000000000000000000000000000000000000000..4a90b3e7250e0aa752791aa6ece4d5d2d32ce143 Binary files /dev/null and b/browser/branding/tb-alpha/default24.png differ diff --git a/browser/branding/tb-alpha/default256.png b/browser/branding/tb-alpha/default256.png new file mode 100644 index 0000000000000000000000000000000000000000..5760882e46b9ca728be0bef90a550993bdb3eb7b Binary files /dev/null and b/browser/branding/tb-alpha/default256.png differ diff --git a/browser/branding/tb-alpha/default32.png b/browser/branding/tb-alpha/default32.png new file mode 100644 index 0000000000000000000000000000000000000000..01ae6a7f65e803a18991ccfc2fc3841cdbea035b Binary files /dev/null and b/browser/branding/tb-alpha/default32.png differ diff --git a/browser/branding/tb-alpha/default48.png b/browser/branding/tb-alpha/default48.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce294213a28b5824a75b321f6da43c0334315db Binary files /dev/null and b/browser/branding/tb-alpha/default48.png differ diff --git a/browser/branding/tb-alpha/default64.png b/browser/branding/tb-alpha/default64.png new file mode 100644 index 0000000000000000000000000000000000000000..5f6d17ecc40af1723c00f496aa594081f4738dac Binary files /dev/null and b/browser/branding/tb-alpha/default64.png differ diff --git a/browser/branding/tb-alpha/document.icns b/browser/branding/tb-alpha/document.icns new file mode 100644 index 0000000000000000000000000000000000000000..58433ff4febf0c96ee8cb2984bc3d460f4d501e5 Binary files /dev/null and b/browser/branding/tb-alpha/document.icns differ diff --git a/browser/branding/tb-alpha/document.ico b/browser/branding/tb-alpha/document.ico new file mode 100644 index 0000000000000000000000000000000000000000..2364b03676d88765900c5603f15d3d276d790ba5 Binary files /dev/null and b/browser/branding/tb-alpha/document.ico differ diff --git a/browser/branding/tb-alpha/document_pdf.ico b/browser/branding/tb-alpha/document_pdf.ico new file mode 100644 index 0000000000000000000000000000000000000000..dc74ba85f69daa19d5806c4a5f7491310041c887 Binary files /dev/null and b/browser/branding/tb-alpha/document_pdf.ico differ diff --git a/browser/branding/tb-alpha/firefox.VisualElementsManifest.xml b/browser/branding/tb-alpha/firefox.VisualElementsManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..d55f44fa09273203aca8f77b6b2b7aafd851657a --- /dev/null +++ b/browser/branding/tb-alpha/firefox.VisualElementsManifest.xml @@ -0,0 +1,12 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> + <VisualElements + ShowNameOnSquare150x150Logo='on' + Square150x150Logo='browser\VisualElements\VisualElements_150.png' + Square70x70Logo='browser\VisualElements\VisualElements_70.png' + ForegroundText='light' + BackgroundColor='#0b2316'/> +</Application> diff --git a/browser/branding/tb-alpha/firefox.icns b/browser/branding/tb-alpha/firefox.icns new file mode 100644 index 0000000000000000000000000000000000000000..ad16371fecbb5534b79dc149768d5f4675178702 Binary files /dev/null and b/browser/branding/tb-alpha/firefox.icns differ diff --git a/browser/branding/tb-alpha/firefox.ico b/browser/branding/tb-alpha/firefox.ico new file mode 100644 index 0000000000000000000000000000000000000000..d339493309909149d509ae2a79b7f30d013dfa89 Binary files /dev/null and b/browser/branding/tb-alpha/firefox.ico differ diff --git a/browser/branding/tb-alpha/locales/en-US/brand.ftl b/browser/branding/tb-alpha/locales/en-US/brand.ftl new file mode 100644 index 0000000000000000000000000000000000000000..a8604d3aaedb5bcba4bc62f8a7c7e39cc4279dac --- /dev/null +++ b/browser/branding/tb-alpha/locales/en-US/brand.ftl @@ -0,0 +1,14 @@ +# For Tor Browser, we use a new file (different than the brand.ftl file +# that is used by Firefox) to avoid picking up the -brand-short-name values +# that Mozilla includes in the Firefox language packs. + +-brand-shorter-name = Tor Browser +-brand-short-name = Tor Browser +-brand-full-name = Tor Browser +# This brand name can be used in messages where the product name needs to +# remain unchanged across different versions (Nightly, Beta, etc.). +-brand-product-name = Tor Browser +-vendor-short-name = Tor Project +# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized). +# "The Tor Project, Inc." is an organisation name. +trademarkInfo = “Tor” and the Tor logo are registered trademarks of The Tor Project, Inc. diff --git a/browser/branding/tb-alpha/locales/en-US/brand.properties b/browser/branding/tb-alpha/locales/en-US/brand.properties new file mode 100644 index 0000000000000000000000000000000000000000..59d1fe05cf7ff18af56f3b857f26907c44675a6f --- /dev/null +++ b/browser/branding/tb-alpha/locales/en-US/brand.properties @@ -0,0 +1,8 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +brandShorterName=Tor Browser +brandShortName=Tor Browser +brandFullName=Tor Browser diff --git a/browser/branding/tb-alpha/locales/jar.mn b/browser/branding/tb-alpha/locales/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..2250233dd6245b892292b97d5a32393557b5a6fe --- /dev/null +++ b/browser/branding/tb-alpha/locales/jar.mn @@ -0,0 +1,11 @@ +#filter substitution +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[localization] @AB_CD@.jar: + branding (%*.ftl) + +@AB_CD@.jar: +% locale branding @AB_CD@ %locale/branding/ + locale/branding/brand.properties (%brand.properties) diff --git a/browser/branding/tb-alpha/locales/moz.build b/browser/branding/tb-alpha/locales/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-alpha/locales/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-alpha/moz.build b/browser/branding/tb-alpha/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..dd081ac44496d19d2e8d73a0a10f3d1ad81266b6 --- /dev/null +++ b/browser/branding/tb-alpha/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ["content", "locales"] + +DIST_SUBDIR = "browser" +export("DIST_SUBDIR") + +include("../branding-common.mozbuild") +FirefoxBranding() diff --git a/browser/branding/tb-alpha/newtab.ico b/browser/branding/tb-alpha/newtab.ico new file mode 100644 index 0000000000000000000000000000000000000000..a9b37c08c6e18af5c8b67745c445bad21fd4e791 Binary files /dev/null and b/browser/branding/tb-alpha/newtab.ico differ diff --git a/browser/branding/tb-alpha/newwindow.ico b/browser/branding/tb-alpha/newwindow.ico new file mode 100644 index 0000000000000000000000000000000000000000..55372077102c4ba18ff1b858b78a2e4c735e6988 Binary files /dev/null and b/browser/branding/tb-alpha/newwindow.ico differ diff --git a/browser/branding/tb-alpha/pbmode.ico b/browser/branding/tb-alpha/pbmode.ico new file mode 100644 index 0000000000000000000000000000000000000000..47677c13fba6881d30eef3a16b46b70f3deb5bc9 Binary files /dev/null and b/browser/branding/tb-alpha/pbmode.ico differ diff --git a/browser/branding/tb-alpha/pref/firefox-branding.js b/browser/branding/tb-alpha/pref/firefox-branding.js new file mode 100644 index 0000000000000000000000000000000000000000..d8123ae26b2007329c9bbbf5b5bdc4f1d6a5009f --- /dev/null +++ b/browser/branding/tb-alpha/pref/firefox-branding.js @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file contains branding-specific prefs. + +// Set a generic, default URL that will be opened in a tab after an update. +// Typically, this will not be used; instead, the <update> element within +// each update manifest should contain attributes similar to: +// actions="showURL" +// openURL="https://blog.torproject.org/tor-browser-55a2-released" +pref("startup.homepage_override_url", "https://blog.torproject.org/category/applications"); +pref("startup.homepage_welcome_url", "about:welcome"); +pref("startup.homepage_welcome_url.additional", ""); +// The time interval between checks for a new version (in seconds) +pref("app.update.interval", 43200); // 12 hours +// Give the user x seconds to react before showing the big UI. default=12 hours +pref("app.update.promptWaitTime", 43200); +// URL user can browse to manually if for some reason all update installation +// attempts fail. +pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/nightly/"); +// A default value for the "More information about this update" link +// supplied in the "An update is available" page of the update wizard. +pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/nightly/notes/"); + +pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew"); + +// The number of days a binary is permitted to be old +// without checking for an update. This assumes that +// app.update.checkInstallTime is true. +pref("app.update.checkInstallTime.days", 2); + +// Give the user x seconds to reboot before showing a badge on the hamburger +// button. default=immediately +pref("app.update.badgeWaitTime", 0); + +// Number of usages of the web console. +// If this is less than 5, then pasting code into the web console is disabled +pref("devtools.selfxss.count", 5); diff --git a/browser/branding/tb-nightly/VisualElements_150.png b/browser/branding/tb-nightly/VisualElements_150.png new file mode 100644 index 0000000000000000000000000000000000000000..92e8179cc612f6729a66b8d5cde9933293f19f16 Binary files /dev/null and b/browser/branding/tb-nightly/VisualElements_150.png differ diff --git a/browser/branding/tb-nightly/VisualElements_70.png b/browser/branding/tb-nightly/VisualElements_70.png new file mode 100644 index 0000000000000000000000000000000000000000..4883c2ad27f12945e16f02f6f55eb92f51a1e943 Binary files /dev/null and b/browser/branding/tb-nightly/VisualElements_70.png differ diff --git a/browser/branding/tb-nightly/configure.sh b/browser/branding/tb-nightly/configure.sh new file mode 100644 index 0000000000000000000000000000000000000000..39799c50ef0df3c6e119cb2ab8eb4dcf7b1b3039 --- /dev/null +++ b/browser/branding/tb-nightly/configure.sh @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOZ_APP_DISPLAYNAME="Tor Browser Nightly" diff --git a/browser/branding/tb-nightly/content/about-logo.png b/browser/branding/tb-nightly/content/about-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..de2404af05ebdc9fa7a30de901bd8e2802be8432 Binary files /dev/null and b/browser/branding/tb-nightly/content/about-logo.png differ diff --git a/browser/branding/tb-nightly/content/about-logo.svg b/browser/branding/tb-nightly/content/about-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..800421e718309e779421c3b3b587cb3ab2af134c --- /dev/null +++ b/browser/branding/tb-nightly/content/about-logo.svg @@ -0,0 +1,25 @@ +<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path d="M24 46.5C36.4264 46.5 46.5 36.4264 46.5 24C46.5 11.5736 36.4264 1.5 24 1.5C11.5736 1.5 1.5 11.5736 1.5 24C1.5 36.4264 11.5736 46.5 24 46.5Z" fill="url(#paint0_linear_1920_3996)"/> +<path d="M24 5.54297C34.1935 5.54297 42.457 13.8065 42.457 24C42.457 34.1935 34.1935 42.457 24 42.457V39.6445C32.6402 39.6445 39.6445 32.6402 39.6445 24C39.6445 15.3598 32.6402 8.35547 24 8.35547V5.54297Z" fill="#D4CCFF"/> +<path d="M24 12.4424C30.3831 12.4424 35.5576 17.6169 35.5576 24C35.5576 30.3831 30.3831 35.5576 24 35.5576V32.7451C28.8298 32.7451 32.7451 28.8298 32.7451 24C32.7451 19.1702 28.8298 15.2549 24 15.2549V12.4424Z" fill="#D4CCFF"/> +<path d="M24 19.21C26.6455 19.21 28.79 21.3545 28.79 24C28.79 26.6455 26.6455 28.79 24 28.79V19.21Z" fill="#D4CCFF"/> +<path d="M24 1.5C12.7386 1.5 3.60938 10.6685 3.60938 21.9785C3.60938 33.2885 12.7386 42.457 24 42.457V1.5Z" fill="#7F66FF" fill-opacity="0.4"/> +<path d="M24 1.5C32.2194 1.5 39.4094 5.90728 43.3357 12.4875V21.9785C43.3892 33.2884 34.6788 42.457 24 42.457L24 1.5Z" fill="url(#paint1_linear_1920_3996)"/> +<rect x="5.36719" y="8.26758" width="17.6221" height="16.6113" fill="url(#pattern0)"/> +<defs> +<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1920_3996" transform="scale(0.00249377 0.0026455)"/> +</pattern> +<linearGradient id="paint0_linear_1920_3996" x1="24" y1="46.5" x2="24" y2="1.5" gradientUnits="userSpaceOnUse"> +<stop offset="0.333333" stop-color="#482DD2"/> +<stop offset="1" stop-color="#8B47EB"/> +</linearGradient> +<linearGradient id="paint1_linear_1920_3996" x1="24" y1="21.9785" x2="43.3359" y2="21.9785" gradientUnits="userSpaceOnUse"> +<stop stop-color="#150080" stop-opacity="0.4"/> +<stop offset="0.166667" stop-color="#150080" stop-opacity="0.4"/> +<stop offset="0.333333" stop-color="#150080" stop-opacity="0.2"/> +<stop offset="0.5" stop-color="#150080" stop-opacity="0"/> +</linearGradient> +<image id="image0_1920_3996" width="401" height="378" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZEAAAF6CAYAAADYomUWAAAACXBIWXMAAAsTAAALEwEAmpwYAACLfUlEQVR4nO29ebw8WVnf/3nOOVXdfe/3+52NmWHYBgGBEVkFUYwJ/NC4YPQXTaJGiUuiEokaNe7G6E8witG4I4pBYyAsCoKgsoPsMDPMsAwDDDPDDLMv3/Vu3XXO8/vj1Kk6Xbe6u6q7qrqqb33mded2V506Vd23v+fdn+d5ziliZqyq3/jFq1buo9daReu+gJLq2vUeBa0+kDSrrl1vYf3MC76s0fOpRs/Wq03q0kDcpWs9qsr+jdo+SPvX2/ZrbbV6iBw9dWFA7sI1Oq3zWts8+HUJKu5a23yNrVUPkaOjNg/Mbby2Nl5TVkWvsQ2DYxe++fcwWUI9RDZfbR0M23BdbbiGJjTvda5jwGw7UAjtvK5WqofIZqqtg+O6rqut70cblPfeNDmAthUovSspqB4im6U2DpZNX1Mb34OuaV1gaSNQepgsUA+RzVDbBs4mr6dtr31T1XSivG2Ddx/imqEeIt1W2wbQJq5n3a953eefpaYHuKZcQ5tg0oMkRz1Euqu2DGZ1X0cfDiumdSbPmwBKW2DSlutojXqIdE9tGeTqvI6j4Gia1KzXWsdAWDdQ2jKI964kVg+R7qgNg15XwdGG966NqjuBXidQ2gCTHiToIdIFtWEArOsa6ui3De+Xr7LXs+5Bqa4Eel2D/rphcuRB0kOk3Vr3gNiFQX7TKsGWOUcTie2qzlOXO1nnYH6kQdJDpJ3aNHi0vb+6+61bTSXV6wJK291O0XMfSZD0EGmX1j2ItXWw74IjaqvqyntUCZQ6YNKDpCH1EGmP1jmoVXnuNoKjK8utNDUAVZ33qAooVQ7CPUgaUg+R9auHR7V9VNlP3X2ueo6qw0BV9Luqq6jSlawrvHWkQNJDZL3qyjfkOvvadPjUqbpyIVU4i7bB5MgM6k2rh8h6dNThsUngaauqyoWsCpQqYNJFkBwZcPUQaV7rGLza8k19XeBpc8hwXcuuL3PuVYCwrmOz/fQgqVg9RJpVV9eB6trg36WcyDrnhSzrMlZxJ6vCpGsg2Xj1EGlGXXUfXQFAW8J0TWnWNa4jD7IsFJYdzLsGko2HVg+R+tVF99E0PNYBji7AoqzWmQdZBiZNA6jqPnqhh0jd6uKSHG12EG3Pi6x6jrpX1V3mHGWBsixMmgyLrXLeNp9nLeohUo+OkvuoGwRHKbxV9FzrKt8tM3CXHeTX5Uo2eoBvQj1EqlcbB52q+6j7mD68NV/rLt8tC5MmXEnbQbKxsOohUq26BJC2hZ82LbTVtFYFS515kGVcySaCZCPVQ6Q6NTUwdcF9FG3bFDiq/ts08bde5yKJdYWiygzUTeVWmlTbr28p9RBZXb37KN+2D20t1qJrWCVBXvT4ZZLq63YlqwzUGznI160eIqupK+6ja/DoqkNpUlVVXa0rdFXWlWwKSDYOVD1EltemAqRqeNTlOtZdtVVln1WHrsr0WVcJb5F2bQVJrxLqIbKcugCQrsCjrcn3Ko6v8jxNhq+qrLpa1K7OSq9l1buREuohUl5NDCxtdR/rgEfd7mSV45pUk9VX6whdVQWlZdtWeeyRUg+Rcmo7QDYFHm12J3X0teo9N8r2UwckFrWrMrzVFEh6FVAPkeLaJIBU2bZ3J6urqkqsslAp6k6adBxtAkmdANoYuPUQKaa6B5Quuo+q4NHVyq4mtWwoq+oQVlOOY2MG2KOgHiKLtSkA6SI81g2YOvurYhXaMv21LTRVBUi67kY2Qj1E5qutAGmr+6gCDOvKrVR5bFX915E4rzKEVTco2gKSutS261lKPURmqw2DyKrHtQUebXQvy7ZvUnWHsaoCxbw+2gaSZbQRg31d6iGSrzoHljaFr9YNjyadS9m2dfa16kKBZfoqApQiIFh0rnkDbd2gKdqmTLteBdVD5LB6gNR/fBPwKdOuquOq7L+OGeerwqJOGDQ5uC9zrrqur/NQ6yEyrTYCpEvuY519l223bPumtEwoq6ow1iqwqAskbQhr9cpRD5FURx0gbYVL28JZVfTRxOTCqsJYy+6rq991hrV6SOWoh4hVlwFSt/uo69gmwLHMe9+EM1l0jqpDWas4j2X3uf3rAEnX1OnX1EPkaAOkbYBoKleybPumVFcoa1WYdAUWvRtpUEcdIm0DSFvCV03ua3uSfdVjZ2mZwavo8XXlPJqGzCz1A3mLdJQhsskAqePbfpPwqAIcbXcl885X1VyQOsNYVYJkllbpr3cjDemoQqSrAGmb+2gSHlWCo61hLKcyrsNvvwgWs9pUCYxlBv51h7XaoC5d65SOKkTq0qYBpMpj1pUnKdqmimOWUVnXMe+You6kqjBWlWGvquFTRp0dwNugowiRugaHdQKkDe6jKahUsX/ZtnUo7/x1J9GrDGNVOfjXEVqqCxA9eGIdNYj0AFm8r6pBf1McySrH5alK55FtWzcwZm1fFE4ro7pdR9nz9lqgowSRHiDVH1M3PDbRkcw6T1FQzGtbBzDyjikLmLpdx7rcSNXqynVO6ahApGsAWaXNukJUXcmRrDt8NUtlwlqLvvkvA5Nlwliz+lkVJOsaTMuet5ODftU6KhCpQ+sCyDrDV5sIlUqOCQey1DFUNqxFtv3Bvubc/euruioKjTrPN2970f29ltRRgEgd3zy7BJC2uI+2QGWptmUhMRiI8n9Lmh7kxvsmfc62/WAgKdvO7+9gX5s55yrjJmZtbxIkZdWDYg3adIj0AFl9exfgUVWIMA8WU8/DcDYcgnA2aEo7DwDhCZkcMx7nOxAC8cFBum8wlCJ+OHW+2MHUBYd525dtV8W5ljlu3SGtzoFwkyFyFABS1YBbB1TW4YzK7PeBsRAUWUAEQT5MVEDlwlpEcweMaGLdiFICJGzbSQYoQSgwGZusA6EYLgwAg+HU9VOOYykDmKKDe51wqtvV9CqoTYZI1eoKQJp0H007kpXAEUPjUBsfGj4ssqDwAREEgpg9R5AfYoKaAZs8JcAIRLpxJKEjnuo7CGgKAJMJcxBKGfeR7AsHksaxS3HXtx/nVJxjSbbvJWCqOjRVhfOoUnW4kSOtTYVI1S6kB0i126poO287ACAcSHFoW8ZlOGhYYDABgFTC2zYtpdJtUqVQkXK+A/H3O0dh9DQcBgM5dUwUMROBlbKvU8ftVSAkx4cKIlZBmjuJJvY8RMSTieEgFDQZmySUFQ4kj73w1/6+BhF4OJp2Kvt7uU6lKEiyWuXYeW3b4kaONHQ2ESI9QBZv7wI8lgnVLQRHEEpiZnLbZgHDwcKBwkHAh8H043zHIebAxYeIA0u6z3AYps8jzTyIXYODSWQdCoVSwhg2AKDkFORYEPEkhszEOh3KggQAZZ3KcOTeR+L9vch3KcBip1H1tl4t1qZBpGqALKOjBJAm4VEYHGWhoZQgHxbMICmJHCREPDBLmV6DECkcZoFCUOwKRP6gaMyM7ZpZBWlSnQ04iB9rzRyEYGOYw0G8LTIMQGjNTII4CX/Zq6KBkCABDgKRwGS0paA1Gy/k5V5D4kAsUJiGo3SYiIFSJGS1CgxWCZ8t238V/ValToF00yBStcpCqS0AWaVtm5zLUuBQgRBu2zxoCEECsODwgeFgIQSRA4QDgm0zP3TlA2aWjGEOw8PNjAH7/yqNMSyCOPxlmFVA0Jo54RnDBIGwcInbBAFgDJtwYLfHUCEi61YcMHXERAKsYrhEE8PhQMq8JP3+vt02HClKtu1FfrsiA3+TzqMPaTWkTYLIusNYbQbIOtzHsn3N3F4GHFloCAHhgOKg4YDhBn0hiQQRMTMh5oAQKVAAgHyYiMV/82yYyklmDmXDTETs+jRx0kNIkaTspRJsDLNUtr27DAsXuw+wTkZrJiGItTaMMAmBCa2ZXegrLgwjpcBRZDgIJE0mzCoQUkfGhIOQxgcu3xIJV0m2FyfhR1sWKHu7U+GuqkDSBjfSq4A2BSJHDSBVQ6UNx808Njt3w8FjHjikJCElkVSC8qAhJJExTFIQgQhCpDAhEjE4HEDSfikDDkHFPiuGpwcsv5qLGYyMexFIK7C83EmSu1ChhIMGud8EJiI2gllZN8JSSYBhXB5Faxv6YobRyuVWDEsWHIQCShkHFKkjNkEgyOZSVPzWpNe9t2eT8g4mALC3GwHtCRWtep4eNAW0KRCpUm0BSFOuZN1tZh7rw2MWOABXbssJLLLgCAISIAjpBuoYGkEgiIjIh4WDhIMDMygLDtvFzJBV3oxxyPg1eg4iBRMBnDmOGYnrkkowO2cCIqOZ2TDI8o4d/BxUhLQAcvAxhgkEFkQsJbnkPEkZh7cksQOKCoRRgaBoYlgpSGPYBKGgIDDsEvOZ10hE4Iw7ob3dhaGurNbhRnpVoE2ASNUupOpzdwkgawfKjJAVqUBMJccdOJQDRvw7CKWQEgQiIQQOOQ0HDQcMZpADhoOFD4h52Y2dnUi87c23X3b7F3YuvOfu/YtOnRw/8OBAH9/fNw8Yj835RvMxrc221rwFYKAND8AYMENwnPlwRoYIEyJoIjogwgER7SslzhFhVyo6E4bi/sFA3R8OxMnzzw/vvOgBg3sf+cXH7/6af37ZPSIOmXm5GOmHuIS04AFSwAjBbAzHYTwYaR0KtGZiZgOPYUazUUpQEBmejA0HgZBacwKJ8b7GaGTLkx1MtratO9ndmRnqaoMbqfoaquyvM1DsOkTWGcbqEkDaBIsyIasEHn64Ki9UFYRC+OAQkg5BAwThAyOBhXdmkYON97z7zouuuvLeh97+hZ2Hnzw5fvjurn7w3l50udF8oda4MH1hlPQ13YnbaClF8OGUtmS2P07a+zJ/DhrgCQDg8zgHgPCOt96p/+yPb7hXKXFnGIpbhyNx4/kXhJ9/+Bcd+8yXf+UDbn/SUy48J4SDBlHsVCSYjX1ObDSzACRLYbQGCwky2pCUMHHoC5E1aawCQS7cJSImF+oaDCQdHGgW3ux7F+rKgck8repG6lBnBvN1qesQqVJNA2lVgDQZvqrtmJyQFblZ3j48/HBVOJAiyXEokrPAQUSCBJEgG5IioiSD4cOCBIiN3fOud9zxgA994O5H33rruceeOnnwqN1d/ajJ2DwcsJVcFhSOPYTY6CQvL7Yy6bMpqBAOP5v9MWHv/4d3MBiQYFwajfnSyTh64s454L57xrjh0+fw9jffsRuE8qbhUF5/7Hhw3YMfOvrkc775Idc99ktO7FrYEgMmhgsYICkEG2OYpRSkNUjGrkVKZq0N28S6QBzuIhfqiiczxi9GTYWx9uPlVWKY0O5O6YquMuoH/DWoyxCpctAv29cygFi0fx0AqeKY2uERhkL44SpbaUUiCw4pSRaAxlS47LWvuelhH/7wPU+48/bdJ5w7F33pwb5+lGtDcVNBNlRDPhwAkOUKiFK4pPtSYGRdydwCYLeT/V+ZcTGFSOxc0sYcbwdjK5rw485N9OPOnom+7Y7b9nDlB0+eC0O6frStPnrJJcOrv/KrH/DRb3jOZXcnFWGGhAqsO7F9kmRGDBJJWjMTwTAnz0lrYwABBxPKFAi4566Ca2tbCSLinXOTeRVdh96VnDZlgNFkSOvIqcsQWZdWhVdbAdIEYKZyHrPgoRQJP9cRhkIQkVChsOEqKSj+LYggpLLBKh8ch6ARD5RXfeTe8974+s8/5Zabz335qZPjp4wPzCPclRIIAgLJQJ+EnyjeL6aBkUCD4u1Ij3VX4IEFQAYgiz5KefBIGJIAxg759gu+Ww6F2cHEYiV+fiya8FPPnJo89fTJCT776bP6lf/75o9tHVMfeOhDt973Pf/hEVde9qDRWHiRRWNYBKFgnVSIkTTMxmhm6wyl5ABmMtEMCASAjCL23Ybwy5wdTLaPBQQAHkyqUh1QqApYGyliXv31/sYvXlXBpZTSulxIkbZzv2eW2N4mgDQODxeyUoGQJIgCRcK5DilJEJGQkkQOOKagAQCvfsWNX/T+9931jLtu3/3Kc+eiJ4MRAr6zyINDuo0oJlQCE7eNph4n++Je/W3ufHkhrLiwOHl++J+kyQWHbWvclhQmcTtmt40Tx5JuMwlo3DYh6ORwKN5//oXhPz7z2Ze8/Zv+3wfdazSzEJTMQdGa2REr0oaNZnbzR7Rmnkw0s7H7x+OkoguTsTEH+2leJLs21865SbaqLW9gym6bNXgVObbovjJtlmlbeT8/84Ivq+j0xdRFiPQAKb6tFYDJhK5EUXhIRcJ3HX64SkhrExJwJKW5dkh+5ctvePh7/vHOZ915+96z9nb1Y5PgUgIB5zjsj/DBYCuCbdsEFMI+FvFz5z6cW3H745P4wEnelPh/2fDWfHECjhQinuNItmeAwSbdFo/7zIBh50o4A5np5wBPwoH8x4suCt789Gdc9O5//Z0Pu8MHiRA27BXFyXdmSzqdlBUbE02Yx2NX9WXMQXyTrYP9iIUg9pPtROBzZ6dcSVEQlAHGKiDpITJDRzmcVSWMFvXXxnDVojZVwyNxH7PgoZSQUhE5eChFwuU6EtdhK3NzwfH2t9528etfd/PX3n7rztfu7urHOVcgklBUxmXEA79IoOFBhTxwgCDixIH9Pe1EEMPDXgalv713ZtacRJqxz+R8uUvmK3qOJHEdiQNJIYEEIHabcc/ZuhCD9PH0fgaDg2jMz77j9oNn/81rbue//9s733bxpYPXfft3PeztT3rK+btaM4QkqNj4RdoIBoxUbjqkECowRgWSLEwgBkM3v8RWN2/F800cTI4dtyGuGCarhIU2JaTUidfRNYhUPfBXdd6uAaTW57NCV7PgIQREEErhw0MIki50lec60sUNiX7lF6981qc+efJfnD41+UoCBBBDwA9FxeEoQSlAhA+RuF26LQZHAp2cEJYf3krg4d6RaTQc2r9AMmeb8VINPkTclilX4W+bciUmAYtJ4MEJXNJtU3ChyZi/9rZb9r/2t//7Z85sHZOvf8Sjtl/zUz//2KvcOmIKAsx23kkU50uCUAm7bpe2fzYphVfJBSGIDvYjVwacTFA8djygjCtJ38b1Daplzt2Jwb8qdQ0iVanKMNZRAshSoSsfHgAwGEhhq69I5sHDJcqFtIVXyAHHG1//+Qe98W9ufs7tX9j5pijCAwHEISlMQeMwLIQFjLDbReI8BISQngPBVB/OMYjYZeTBI8GGDxAPHGUgkieRJkKSbX7y3MmwSba7VjaUlQlxsZlyIwlATAoXCxMfLnxib8c89xPXnHnu9//bj3z0ggvDV3zHdz/09U/7igt3jIYQ0p46smt0kVQEi0QNu3qM/X4xHmseDAW5IehgP+KtY4p2z6WuhIhw9sx4mcqtKtr2KqguQaQqF1IlQKo6fxsBUpn7GI6UcLPLw4EUMVxkHjykhLATPKbh4UpFf++3PvbkD7//7m+7776Dr00Gby9vISj7W9rfIgYFSQsNISCFg4ucDmEhDWkhDleJDCxs0jw9/6E3JQOMKj5InAch5kOjojAu2Y44N2LlIOLCXG5b6kRiaAj2tpsYJj5ctIPNk++9Z/zkP/ifN/z8sW31msc/6bw/f96PPuImt0pwpJlVcuMuCQCklPFnwxOGMAf7hgdDRQf7EbaOKTiQxM6mqUG/B8yS6hJE2qiyLqStAKnEfcwKXdmwlbIJcyWkCoUIFAkViJnwEDKe3Cds7dUv//xHnv3xa+//jp1z0eNTV+G5DucmksdqChzOfcjYbWTdiXsMwHsc5zpEuj15A/LAkWzwa7Sq15TvIAJl8ics42CYXdkx2Z7AxcuTEASkzcSDGdBTYSzPiRgD4+BiBAzDh8kFuzv8gx9478kfvPojV7/hix61/Sc//QuPvlLZUFcCEh0xq0CSC29NxobD+M6SLuleoXooNKSuQKSNLqQKgCx7bFMOo4z7SKquRltK+KErlzR38IhLdaVSQrichw8P5zqIQD/9nz/wLZ++7tS/PTgwl+fBIwWHgBAxMATF4BCx45BJjsOHhvQqtARNV2vlAWPqjXHAQRGt+vGdHgunZ57gkOtJIJMBjIOLP5dEZqq1CMLCx3MmhjkGCINZwxjrRoyhdJ+xbaMJf/Onr9v55ud93zVve+Blg5f+8q9d8S4hyQcJkIBFYDI2yQscDBWNxwuXR8mDQw+MNaorEKlCbQRIkWtqI0AWug8XusrmPYJASFdtlQcPl074yR95/7d99vpT/3Y85gcT+VVRHjgSp2FdhySZgEJKmbSzCfL0OFAcJ3NhsDislbzIbFJ8LjDq8BrLnCMdQ6cgE78untofH+Hg480XyUJlOsFuYFjEQJHWnSQuxTmUGDoT/povfH7/a37oe65552UPHvzhL73win/0rzaKmP0kO2DzIm4yopdY7wHRcnUBIk38Ky1zvrIAKdO2jSGree6D3NLsc91HIITLewSBkPPg8XM/+cFvvO7jJ//dwYF5uA8PC40UBMIDhhAS0v2WafhKCJk6DqIYHNlKK0w5Db9kd/5b2zbNuj6O9+aDZWqkdtudUzEGwq7XmAMUhhEGmnkaJmysKyEDwwRj+Fm3fX78rP/4Pde887KHjn7zZ37xkR82BjwZGx6PdTwRkflgP+LdnYh3zk2Siz599m7yr8fp/BOXdqFCq8vnLKW2Q2QdYayqz1HUmbQBIKXDV/PcRxgK6UJXQShjc0AkQBLpsiUEAC96wUe/6oPvv+s/7O5EV7jEdy48hIQgCSlc3kNAOdchPPeRk/PIgsO9uNwbhrQeGkWV9zoyYInhYZLtcSspk7wKs12/froU2FjnIiw4tGDPlTC0gwoBBuZZt31+/Kwf/4+fet2DHhL++vN+5GGfPtg3fLAf8f6eNm75k7M795ExGru7p5IL1ybCse2LkoH0/tO304XnPajtc0haP/hXpbbPWK/iX3LbwlhtzXksFb4aDG2g3Xcf4VBIV3WllFBToSsB6cPj5X/+mUf/7d98/odOnTz4quycjCkoCBmHqySkcLkO5eU75Hx4AAk48t3GpkCjrPL//acLOXLaamqZlOk5JoY12NjnDh7aWKhoxHBx1V0GEJJ//zFXDF/4hKeMdwDg3Ln703PzdJhLmzRP4mBiWHMGJP3M9Vj9jPVUXQ9jVQWQMu3rBkhh96GUUFIJoRRJB4+k/IpAX7jl3NZ/+/kPP++2W3f/DRG8CX+pwzgMDwsQKTyYxAl0IoIUcirH0YOjiLLvQb5LcbPiXdjLffkUMUgEC7DgOK9ikkR7AhKKw18GMGSg2fzIdZ+YfNenP63/v//n6+942d7u6eQKtNHJoDkYbLM2EbZH59lcyc595EBSwJEcGTewTrUZIlVoXWGsouct0q4MJJY5rmj+4xBAZuU+Eveh7LJXU3kPhviF//LBr7/2o/c9X2u+KDtjPEmOCwlBKgZHDA+ZAkWQnecBEpCzQlbIC1X14Jiv/PeHABDZmYRpRsX+FuQvl2JnxWuyz4UwYAPrToyBJgMtDaQ20AIXmkj8ztvf9JDnBoMLfvaxT7zqSgDQ2oa2wnCLD8Y7JGVgAEyBZGvr/B4OLdGmQ6SolnUhq4TKyrqSWlzGrHYOIIvCV4OhVFJRDJDD7sOFrohAr/m/n3v4q19xw38+c3ry9Lwy3dR1KEhBSbhqCh7CgsZNEhR5ruNQNVUPjipE8N5JIQ6Fu9hOhQdDQMYlwYoNjEHiSqZgYgy0EDBGfJk+OPHWT3zkn7zkske+9ZfCcHeiVJhAIgy3xP7+2SmQzLi8HixrUFsh0mQuZJUwVtH2ZR1H9nmTAMnNf7jqKz98FQ6VdJMGF7mP5//AP373DZ85/cOH1qryKqssPAQkxb+lghLT8PDnhOTBowdHdZp6B3Nm4Lv3ngE7u5/5UO7ElQQzC0jD0Jwm3d2P0YyIDLQRP3THDd/4HBGc/MmLH/b6tw8Hx4yDiRCKhsPjPSRaqLZCZFVVNYK0IZG+NoCoQIi8/MdgIJUXvlKu8soupXjYfbzyLz/7i+fORY+z4EhnjE+HrASkCOJqq3SbrcTykuZCLAhZ9fBYVck7OGfpluxSLwlQPJjQFEzspETFApFhSGOgtXUkERmQAYQBtKaHRJMLX3Xvrc/5+gc89E1XDnHMhMGQAWB//ywB1o2cPXsPHT9+cQ+VFqiNEGlyFFj2XE0BpMyxVQJkZv5jXvhKSFIkiISAYAP6sR9+77+5/pMn//PU4oduNrkXulJx3kMplWz3ITLlPGYmynt4rKo8eMwDh2ub/UBRBiZgu/iKq+QSYGj3RcIYkNEQEcGuDK9tP+LgAAAm0QGNJ/skhKTBYPsQNFYs9+1VgdoIkVW1rjDWMuesypEUBU/u41kJdCGFUIpoMJBiOJLKVV/NCl/ZexCCrvzQPRe86IVX/9fTpyZf6S+x7nIYUqik2krFeQ/nPhxESKRJ9h4e9ao0PHLAkT2WYKu4iN1vBhHZuSjCgFkAMCAQmHEPS3OTov1PM+1fLwZ3vy8473WfAk5U+0J71aK2QaQtI0IdYawqcit5+5ZyHe7BLIAMhlLm5T+EElIpIVVAMhu+AkP82q9c/VXvffftv6QNjvuLIgrhl+mq5HcaukrDVg4mfs5D9PCoXEXhQZnnybbcNcXsMxfOcjuTJDwbzZh8Ati/RtPpa/bp5k/uhW+5weDMhEhyoEITqKHR2ZvlzpDnQno3sia1DSKrqioXUua4otsWtVkVDEXbLQcQL/8xK3z1A9/7rv94681nnzu9oq5IgCGEjENXQeo+ZBq+8vMeglJo9DmPajUPHvNcRxFwsFet5cJZhief1rz7wbG5+4M7+uprzpp33SOEZGa7rLBEYIjkFASkUGl1VjDkSE+Wfbll1INoCbUJIm0ZHWZdR1N5kNrCVlgAkGwF1mAgVTgU0uU/vHWvpsJXH/vofSd+9b9e+Wtnzky+bCp8JVSa35DT7kPJ2JHMC1318KhUVcIjC47kaAYMeKJ57wMRn3r3rv7E++6P/vomIsnGREwkWAjJRIKZDaQIjBCSDRs4FyKl4rhrBGpg54wEIx4Oj7Mr8S2YVF8nFI4MkNoEkVVVtwtZVmXzILP2reQ6kAOQWSW8oy0l3fIlUwCJ8x8yENKFr178+5983Bv/5ubfjDSfn87doKSqSooAUrrcRwoQP4GehK5y8x49PKpQXt4ieewDYqrqbXY4KwlXxX8xwwzNe++dmHv+4bR5+9t3zJUnAcCCw0JDysAQidikGCNFwFKFBgACUj5AjJQBDwfHzNbohIn0hI/Pnh/SpNZxDW143XO1SRApokUjUtUupOz5anEdqAoggpSUQrjw1c/8xAe++dqr7/1Z+LkPN/dDKEgR2PCVlFDSPVZT4atsyW7qPnp4VKEi7qMoPJLZ6vGwxgwYHHxqYu5/w1nzwX84a95xp+F0yRJmNkIELIRgIsHGaBZCsJShYbY3jA9UaISQDIaRUrGUAQNgKQN2c0SyLsTNaF9SrR+Uu6a2QGTVEaOKEadMH1XlQWbtq8x1oCBA/BJevwIrm0BP8h//7p3Pv/WWne+aAoiQdqJgHKpSsQsJpPKS6TPcRx+6qlyz3McyzgPMIBCYAGYzjvjs3++bz/71/fyXVxpjmIg4XkDThqxIMMOCQpBgIRSTEhoAhBAMwAghWYqAffcBAIEaGKVCDoMhh+EWSxmwP1PdhbL60t52qC0QaULLjkxVHde460AOQNz2MgARkpTLf7ABfee3vuXXTt4/fqZbumR6gUQXvgqgYgfiSnlJCKg4B+IS59NVVz08qlBR9+Hfoz67LVFsP5gIxkR3RebeV502b//rXf7wPfZYwWTrdyFIMLEwQgimxF3Yda+kkMyI3QZJBpGRQjEIUDJkEJlAhqyCkAVJA9i1s04cv8QMB9tJrdax7YvYsK7y7eq1otoAkTa7kKrCWGUAUgk0/MfzkuhlAHLzjWe3fvz57/293V39OD//4bsP6cHDJs9tGCst8xW9+6hRRdzHIicCwIMHYHj8mbG57S/v0X/yeoM9Y8Eh4uVIJBNZcNg+pBZCsiDJABshJAfBMIYAGRWHrEy8Uq+UAQdqwCTIBGqYbBuE2zwYbPP26DzWJgKAqXuK1OBCelezpNoAkSZU1Qi1bBhrmf7L9rsYJgsA4uaABKFQRBBCxmtgEeidb7vtkt/+9Wv+eDzhywju/h1ukcQ0dKWEQqCCTPhKzam86uFRhWa5j3nAWAyPg+sPzC3/6x7z4r+POzGu9JZImPg3AzDK5TYAI0hyGAyNNhFLGXAYjozRFhpKhaxkyEIIE8TLmWg94TAc8SDYsm2CockutLgAIGXuJbKs1nEfkU6o6xBp2oUs098yTmNen3mPZ+7PLmVyqIzXA0gYWID4JbxgiFe9/IYv+os/u/6PtcFxAsVJcW/SoFRx+EpBKZXMQhdCToWvknuaU95l91pWpdzHDEeSLFNCgOHJLWNzy5/eZX7/9QSRJMaZDUsRGBIuSS5ZCOs8lAyNlIoJZIRUrKzD0O6KSAmjgpDD2G0IqQwADMKtxKmMBsdd5VYyCI9G501NO1zx1rhHanBvSuuGSBOjSNHBedH2usNYRdqVcSq5a2H5VVhFAPLHf/DJL339X9/4YgZJe79yDyCx87ChK+93DJnZ4aseHlVpIUCSsmkkTiQLj/ROhfrMmO94yd3mf/4fIsEEwTIe7AVJTXHiW8nAiGAUJ8mlDoORzWEEQ0NCGCUDhnWrrFTIgRqwMZqDOFEOAEEwSMBhjF/RZdi/VwgzZ8FxlEDQide6boisonWPRKuEm+btqyoPcgggbia6D5A4B5ILkN9+0bVPfcvf3fJ7iF1EmkCPF02UAZQIEKjp/Ee2+qpPntcjHyBl3Qc8eBAzItz/8pP8mhfvm8+eddVVJMlWUMnAGKNZycAoNTAATBAMjBQBE5EJw5FRMmBjDCsV5oIjdRvbbMz07W+3ty9InjugnHf8kn45k45onRDpugtZ1GZVaCx9rFfKm7uUiVJCSu8+ICogGedAEoD8zm9e+xQHEL+EVx1KngeZEl53a9s+fFWXsvmPRQCZFboCAM17V++YD73oLL3peoJgKZShOHwlhNQinmEugpG2SfKBIQgTBkMjVcCChJEy5CAYsBTWtQTBkJUamEHsOoaDbfZDVFtb0/kOZsbxNOdRFhpV5EMWte/zIXPUVSfS5GjUZBirzDGLAEJ5AMkuZaICkkKQlNIuaQKG+MPf/cQT/+FNt/yBD5AUEilAAhUkCXUpJBQpCCmTQasPX1WveeGrWSGrrPsAMwybvQO+5bfuxR++lgiGIFhIZVzeQ0plGJy4DymVlkJxGIyMy3UMh8eMYcOBGnAQDFnJMCnNHYSjqVzGcHjCG1ztw2NbFybLmzSgIze4N6WuQqSIqnIhTV3HsnmQXIAASO4H4vb5AAlDGXhlvAlAXvrH113xt6+76Y9yARKHr5RUMUDsMiYugS6kRJ//qE95AFnGfUR89h2n+G9//YCuvUeSnejn1rQSFGgpg3j5ETJKhSZUQ6NUqAfhVgwJCwilBhzv5yADDmaTgMO5kGNbF5R1G0WqsHqtWeuCyCojS9dcyKx9VT3O3a+C6RtKBQHJ9G6Eh+eBgCFe/YobvuivXvm5P8sDiMoCJK7IcvmPPoFer5YFiO8+wCba51t+7X7xx3/DYLuelVAmnvgXl+iSsTPGA6NkqIVUPAhHRpA0w8Fxo1TIhm2uI5ChCcItHg62YljYMX44PMbuflRxqW7RxHi/NlUHtalOpC4XskoyvaoRtVAi3Z8LMhxJlS7nbtfCIkEEgcSBvP2tX7j0z196/UtdEv0QQGSQzAFxj7MA6RPo9ahIAj0bysq6D8N7V5/BW39pV7z/dkGSmWAE2XWshBC2TFcNDAFmMNjWdhJgqKUMeTg4ZqbzHaEJwxGHySRCYODNKgcSeNStovmQpsqCq3zNnYHbpkKkClWdTJ/Vrszjwol0V8obhEIGoUzvh55ZTJEI9OlPndr+nRdd+6eGMXJVWIccSB5ApEoS6D1A6tFcgGSg4W9zdxNkZkxw75/dK37nj5g1C1J2nSuAg2Co47keRgjFYTCMhLATBYNgpIeDYwYESFImCIYcBAMOgmGSMGc2GA6O2cdgbA3PWzVc1auDWgdE6g5lNeVClk2m15YHmVHKK8NQSCFJBqG0JbygqcUUf+bHP/DHk4gfQKDpdbAOhbBSgEip+hLemlUGIDOS57v7+NTPnhKveJ9dEJFYSGUECVYqjAQJFjLQgQpNEAyNkoEehNtGqoClDOK1rIasZGDCcIsHwYg5tjaDwTa7+NXI5j5mAaGq/EcPnJaqdyLF8h6r9FkVNBfmQbKJ9Ewpr7sjoZSBkA4g/+Zb3vw/9/b1I5OZ6H4Zb5w4XwQQO4D18KhSswCyKP+Rhq/2rzsj3vRf9nD1XYIEkxBMsLmPeIkSI4XiIBhqKRWPhse1IGkGg20TqAHLJGE+5FBNha3S2eRTFVeFVHe4Z52lvUdWXYJIXS5kmXM3Fcaauz+bB8km0rOlvG4uCMWr8X7/d73jJ86cmTzdB0i6iKJKy3il6gHSoMoCJJv/0Hz67+6R/+OXAEDAAkSQZCkDrVRgpAi0EJIH4bYOgoEOg5GRKuRBuKUJgAoGvDU6z4Tx2lbgFB4MdsuTdGUWeV9CXLO6BJE61DYXskwYayoP4ifSpRSklFBSksiW8v7Uj73/X95+2+6/IksW2CXd7Ux0Ow/kcBVWD5D6tSxAKC6HmuCul9wn/+BPAUAKZYjIUBy+cnM+iIQJ1MCMRtZ9DAfHjFIhSxVwqIbs8h8AMAjThPlwcGwqeT5DVeRDjnooq1Ovt2mI1DniVOFCikClThdSav+sCYVBKEWgaCqRDgHrQeL1sD5+7f0/ZVMZdna5itfCkskaWBYg0qvC6gFSr1YCCDMO6KZfOa3+4o0wKUCkVEbKIA5jDUwQDIySoR4NT2ilQg7DkSYQRsPj2i5RMkpmlw8Gx1wKJEmgl1STCfZ1htaOtLriROoYrerus9IEuvc4WVjRbcvLgwglchPpn/jY/cde/9qbfh+EuIzXK+UVCkqEyVIms8p4e4BUr6UAAsQJdMY+feJHz6q/+oBdusTe30MIaaQMzCDc0kRkBuG2DoOhUWqoh4NtI2VgVDCwM87VgMNwlMIj1pLwyNM6yl+7WNrbOXUFIquoDS6kjBaFsabyIP58EH9CYRgIKSWEW1TR5UF+8ac/9HvMGIj4joRJOa8MoGSIQMVrYcUz0f17gfQAqUfLJNGTWlo2e7vifT+wI9/26XjZdg0AQTDUUigdBCMt7Wq6ejg8rpUMeDQ6TxMIUgW8PTrfhMEwqbpyq+wOw+2i4aZlciN9KGuD1CRElh15Vk2o16V5QKnahUxt88NY+fNBbB5EiOlVeb//u97xE3t7+rFuMiEJkd4LRKg4F+LNEaHDEwl7VSsfIMk2Dxzu91QVVixms7sj3v49u/K9N7tl25kNgmCobf5jqO2cj3TZkjDcsuGr0QkTqEGSPHfwAKYAskryvC63UMUEw74qq0JtuhOZNeotA6aiOZcqkulzq7HcNj+MFQRShKGQSpGSSgihSMT/ERjihb9y1Ve7RLqbC6LiuxLKOJFu74ceTC+mmJkN3buQ+pR1Hu53PkD02bPizf/uQH74NgcQQYKFCnUYjLSSoVHx/I/hYDsahNtmODxmGOBADXh7dL5x5VxBvOZVDI86BtB+UC6uzr1XmwCRKka1VQb+ou2Wdh7A4WqsbBgrHAopJJFSQihF0s+DXPmhe85/77vu+DWKE+nTs9Jt7kOp2Im4+4H0iynWrmwYa95EwiQHAoDZnD0r3/TdB+LqO+KFE+29zNVQS6m0kqEJgoEZhFs6DLdMGIzMcHjMgAhbwxPG3l3Qha9GzFgYvvLV9VBW1X12btCvWm2HyLoS6nW6kJVgMiuM5cp58+aDvPCXr/wtBuRUIl3KKQfiQlpJJRbQA6RGzQSI9zwfIBydE2/7PgcQJQMDIg7U0M0BMYPBtg5UqMNwywzCLTMYbCcACdQwgYe7lgIA2aRQ1jLn6DVHTUGkDTmLVdut0u+iYwon04H5YSwSRH4Y60ef957v2t3VV7g8iL21rbsLYRiX8tpt5G4+FZfy9gCpR3mJdPfYlVFPASSeSMjM2BXv/d59+f5bHECkDIwQSisVmCAYRoEaGpcH2d46Xytp7zJoq7CG8VLuQzcHZN43/zZWZfVqodruRBapDgC00oVkk+l+NVZeGAvM4g1/c/NDPnP96edP39rWAcRLpMv0roTklnTvAVKLchNg2fAVvCqseB6ILeO99vm78u2f8QES3/vDhOFIKzkwYTA0YTgyW6PzLEDsqrscBkNmzgXIsqWsVc8b6UNZHVWbIbLK6LUpLmRqTkjupEKvGssPYwFEf/aST/2mzYPQVB7E3h9dxpMJg6TUN70nSJ9Er1Vekjx3/Su/XexAxnTjL59Tf/MRBxAiwTFAdBiOdKhGJl6i3Wxvna+lCDhZtj2pwEoAUmTmeRlVnRsp2n7TQlnrPv9SajNEFqkLLmSZxHpuGMutjRVvTycVSpJSCQsPL4z1w//+3f/+4MBcnswHSVbmlUlZbwIUIVMHgsOVQL2q0aw8SLLNf/+9tbAmuPtPz6i//DsfIErZ6isplAnVyATB0ATBwAEkXrp9yIEKXQUWgzkvhJWnqsJabRoU23QtG6UmINLWEamu6yrT7yFwzOrHT6YLAZHcpVCSkBLWhRARmMXfv+nWB934ubP/fmo+iJtQ6CqykjwIpXkQ2ER6+ZfRa5Hm5kGQ40iSxRTPvuVU8OI/BQAhJDuABMFQKzUwg2CkgySEdUIrOWClQt4anRe7DXYA4QUAKZNcX9V5LApdlQVd2Wsp2l+V7TdWbXUiTYSyFh1X1JVUkQs5tG+eCwkCuzaWECSDQEggdSEE0J/80SdfQAQIihdWTFbotTAJ4jWxRJ8HWZtm5UH8SizD4xvvD37rFwEgXf8qtMuVKFvCG6iBA0ik5ICDYMij4XEHEA7cUib5AOlKjqAfsFustkJkkerKZaza3zK5kJWS6UKSEETCJdN/4ac/9Jz9Pf1YIgEhKAaHm/8RL6oYuxBFIs2D9ACpTbPCWH44y0+kx3mQ6Ix81Q8BKUCEkCztDaJ0DBB9KAcSr74LxCEsAINgq4xzaDqUVVVCfRWXVeW52tRnIxKLm3RKVSXUy+RGypyrlAtx24QUQinrRlwyXQiSLpmOmAP33rMfXn3VfT8FxGGs5D7p7iZTthrLlfmSkFPfhHtVr0UA8W9t6yfS9+ljPz4RnztNJDgPIFIqDsORGYTbRskUIIEM7b3QXRJ9GiCztM5QVpljl+1jmXP0Kqi6ncgyY1NTrmHZcxZJllfqQoKASEqiIKAkme5cCIFISiHYMP2XH33/T4I5tGGs+EZTXlJdKQXhJhT2eZC1aW4ehBkR7n3ZOfW6D7lEegqQkQ5UaKRUPBoc12G4ZYaDLROoIUsLkDiJfgggTQ/EbRqU23QtG6kuhrNWHemaDIVV5kJcSa+UgmwyPS3pBbP4m7+++fK779r7ZkocSLxCr5Txelgq3RYn29GHsWrVPBeS/JEzlXAG4+tPBX/44mwpr1KhCdTASBFwGIzMYLBtBuHIgAgyGJgcgOSV8TYVyip6zmUS7JuYUO806DYpnFVXQn3WvkZdiBAQh0p6QUTCjkIv//PP/BxgXYUQdma6EOlNpVwYSwjRh7GaUl41lp8H8doxAMOMM/J1PwZMV2LZn4EJ1NAMh8fi5UxGGkQYDc9LABLm50AWqYpQVl1zQ1ZVpwfnrmiTIJKnpl3LMv0sdCFT62P5Jb2xC/md3/zY03Z2Jk90dymU8RpZSogkD5JUY9H0worVvsxeToe+meRUYflhLGLGhG5+wURcfzKbSE8qsYKBkULxINwyCUBUChAGcw5Alvnm3taE+ia6kM6rbRApm/Busv+yLmSm05jXf54LkZLIdyHMcT1P7ELe+fbbf4YgkmS6vRNhkPzI+M6ELozVV2PVq4XVWJnHDCDi3Y+cUX/xBiLBwq7M64WxbB4kDEZma+t8HaiQAzngQIXMzJzjQJoGR5E+mx6wuzLgd+U6Z6pOiDQ5OlUVyqpDhWBSxoXI+EZTbJh+9Zeu+meTsX5wsrSJNydESYHAuRBykOnDWOuQnwPJhrGYmc+qV//svDzIaHBcDwbbJlAhKzXg0ehEvJiiBUgYjJYZjKoOZXUpXNX5wbstapsTqVLrTMAXdSGH8iNlXAgR6CMfvPu/ENJ7hKTVWAqCVJwf8VwI+jBWncpzIVO/MR3GYmZMcMuLtLz1jJ8HEUKynweRKuThYNtIC5GppHkMkKqS0HUk1Msm0FcNW/XJ7wbVJYhUDYWqE+pFzjn3GLfU+ywXIggkJQkIEBum//ZzH/naKOIHuPBUMis9BkleMj29gB4gdWrq3c1bXJERJ9PHnzsTvOyvAcDlQYgEJxMKvTyIVOH0eljxwooFtAw42ug8fPUupCVqE0TaHJIqo6LXk5dQR54LIUAIO6lDEGITQqCPXnXv8wkujGWrspwLkd4NpgTJnDkhvaqW70LsQ899YNqFMAHMjD3xvl9Ibi4FOzvdzQchEFw5b6BCJhACOfABwjlhrHVVShWFS+9C6u+3UW3qiFJXKKvOst6pNbLc7HQpLEjsvBAi2IiU+OWf/8jXRBFfSvGNpuxPOplQSZEk00U8JyQtK20bdzdLRVwImKFx5k0HwXs/lw1jCaFYioD9MJaKbywFpA7EA0jbQllt7nMjBu42qS6ItG2UqiqUtco5c/dlXUhy29uAYmyQUEoIEiApyK7UC+CjV9//gy6ZLgTFLoSS5d5TsIjkW7Bo3Z9lczTXhWRKeplsNOucetWLhJBJNda8MJZd0mRgp7SjVCK9TKhq0f6q54ksW9ZbRdt19llnv42rK06kK6PfSmW9/kq9QggKFAmp4nuEwOZCAIjf/o1rnz4Z64e6sl7nQqRQST5ExEub+DPTF19Or1WV60Jicfw/m0y/68Va3LkrSDDFELH3B5FcIIyVdJdRG76h113W24bX2MtTWyBS5bf9KkNZy84HWdRv7j5mkH+/EAZICCLpcuPxV9kPvO/uf+8qsnwXIhIXItKSXqTx+F71qKgLIWbrQow5czb8k5c59+FPKlRqYIJgYKaqsVwYKzwUxgJWC2VVUeK7rI6yC9kotQUidWqVUFZV58zdNy+hLgRIKiH8sl5mplf/3889fHdn8gR7v5DehbRJC10IyLoQuu3Ffhgrb1LhILRrXwXBkJ0LAXNeIn2emsiLFAVNFedt0oXUCZCNgtNRgEidKjo3pHBCXUhKFloUhHiBLIqNB9GbXn/LdycuhHwXIhJ49C6kORWtyEpdiD51bvDnf2XbCgbsOlkumR4GI1vKG08qTMJY4XAZ91FkX5H9VasLLqRXQXUBIkUqpeo4V5VzQw7tm5VQD0Ph7lAolBICFN83ChA33nBmdN+9e1+fuJAEGnZNLFuRFa+N1buQ9csl0u0TsGFM6LY/muVChJScTaYDM8NYs1RHwn3V5HrvQprpey2qAyJlR6sqR7eyoaqqzr30a1aB8MGSJNRJulnptgYLAP7wdz/xTWChkrWvkgmGdsXe5Ha4JHsX0rD86qtDs9OZ46pec2539IrX+cn0rAvJS6YDsNn4wyo7cDc1gK16nipdyMYN2m1TF5xIlaoTWLP2z2yXnaEeL/dODCQz1K0XsX3c+Llz/wqEOJTl5oHEa2VJtwR8fKtV91PoUnsto2woK9nmbed4GzMjorv/N2ASgLi5Ib4LkTLgJVzIKjCpwpHM06LcSN0upKx6F1JSRw0i81QkbFZLKOvQOllE5GaoxweKl/3pp68YH+jLBVGylIkDiFsfy8HFfRPu54U0I9+FZKFiXQiBmfXe4I3/V3h5EDu5cLELCdXCfEiRfYtU1bFddiEbOcjXrbZDpM58SKEBvwblhrKkEiSEIDdDPRvKes+77/wWN7kwdSL2txTTkwt7F9KQclzIobJeWBeicfoNRty957sQISQXcSEzVEUoq+4S3zpdSB/Gaom6eHvcWVpHKe+sflcKZQl7nxALeAEaH2hx7937/5xgzUmaVHe3vLVhLGFjXb0LaUBF3t1kViAzxsE1LxdT1VjFciGxC2kSJlWV+C6jdQ78dZ97Y6HWdifSlMqGsuaBo3D/80JZwq3czqDfftHHv5INtm1VVuxC3ETD5EZT7qd3IU0qL6HuHoMZYMDQ+BNR+MGblsmFZFQEGOtMqM87Z5tdSA+QFbRuJ9LGUa7WUJbLh8wKZbmqLHshNp513cdPfoM1GQJELgdiy3qlFHFVFiX3C+ldSL1alFAn2FHDjRyabn+V253nQty8kAW5EF9VDEpNlvguez29OqB1Q2RdqrO0d2Hfi6qyAAgiIsNM9999EJ48Ofnq9J4haWI9dSD2vuo9OtaonIQ6MWDYHBwM3/K2eS5k1rwQ19OcszaRF1lGvQtprv+1q+pwVhMltEUG7jrzIUX7mtvOhbIAQMbuIxvKEoLoJX/4qWeAeWhvJuKS6pTcwTC97W2fUG9aU6EsYDqUBcAAiHDurSxOjt0xzoVYJ6K4hAupMpS1qS6kbQA5EupzImsq7XWy62QJayq8UJbTDZ85888onhuS3DtEpJVZ5BxIn1BvTkVDWczQ8uY3+IssCiHZX6lXyYABoGBFFrD8t/h15UqadCFtU9eudyn1EJlW/aW9zJRdK0sqIrBdJwsA/NLek/cfPAN+Mt3lRUjFz+Nt6F1IEyr0zrpQFsx94+HfXeXvUmpgbzwlJQOAS6jP6mneWYpdcWlVXdZbdfu2nXdd/bdGRxEiTeRDZpf2xm7ELfuehLIkTZX2Gmb6o9+77olG8/luwcVk6fc4N5JWZIlDIfle9WrWBEM3chgAhs6+izJlvQCwREK9yVBWES2bs6nLhbQNIEdK64RIF4e9stdcqLQXsJn0qdJeAB+/5v5npCuYiNh9pKEs4YWygD6UtQ5R9ofIhrOYocXt7wAsQFxCXSYgWZhQz1PbQ1l1DeZVXus6Qngbra45kaqT6nXnQ5I2efkQAJiVDxGC6L77Dr4CSS7EJdbdzPR05nofympGeaW96c54OzOYGcxmJxq+/cN+EyEUu5tOAUAQh7EKlvX6qgsmVSbUq3QhVR3TA6QGtRUi6xgJ6z9nnA8R0pX4TudD2LANdRnQhz949wX7u9EVh6uyRLw2fB/KaoVmvPmG9j7AtKddGEup0AAAgSBlwIPBdvJ8huaFqZZps2jbqlqHC+kB0gId1Xkiq2qlfAgAuHwIALh8iFsvCwT6u7/9wlOSCYZIy3jT5HofylqXsqW9TsmIzoChUx9K2nvrZAE2lFVynSy/+1XbFDm2Ky6kTer69S+ttjqRurTKSFvJKJ3Nh7j5IQAgPBJ84ZZzT/IT6jTlQPpQVhuUfdddxQQD0OqzH05np6dzQ7KhLF9rDmWtoqPuQo4sQICjB5GyqmR+yDy5fIjIzA85fXr8JCIb7iDyQlpu2XeXyu250Zzm5EPcHptUn9ymBx+51e4SSVWWC2W5kt5DN55KVQYUVYeyuuBC2gSQI68qIdKG4azqpHoVskn1OB/iNgpJQghB4OR8yb1DPnbN/SfG+/qL03upZ+4Vkkw+TO+g16teLXqPGbasl5lhsDc1N8RNMARsKKvEBMMioMi2Lapl5oBUfd4q+62rjzaco9XqkhMpUpnVhJa6DpcPcUl1AJDKlfdOH/+Wf/jC4xgUr+xOUwCRcY7Ebbcn7zHSlKbe6dyZ6wQjzn7CnxdiQ1nzJxg2FMpqesCrMvRWps8y7ZYVN3COTmhdEGnbqFfnBMRDyibVAcAv77318ztf4sJY9rdLqnv5kCSc1edDmlZeUh2MuLSXwfKOj7vNPkjmrZVVUsuGsha1qzqUtew1rao+B9KguuRE1qlKJxkChxddBOxyJwBw6tTBY/y74wlCnBPJ3jekR8e6NAvdDHPGjD7yWSDNh7i1sqQMklDWHNU9V2LZc9TRT10upE614RpapTaW+NY1Llae61j2wMSFzKjL3dvRjwLSSYaUAIS8CEofxGpUcybjuFHFMMPw+LOI54cA2eVOVDIAVZwPyR6zaFuZfqpKqNcBnFXa1XkNR0q9E5mtKsbo3JnqzCAhBDHbyizAVu8yg97z7jsvGo/NQ9PKrDQHItxjoM+HNKi57zBN/wWYDj7rHrvSXgBoKB9S9vhVkutNu5Bl+6xKPUBmqIfItOoZkTMz1V1CPe9kV33k3i+KMyHemlkpSNyKvn0+pEVitvNDDINp53OADWW53S4fAuQvdVL2bJnf89qU3VeVqj5HE5BdV9+dVxvDWcuqivLesuco1FfufUS8yix/jsgdt+8+3AHCzUpPJxz2uFin5lVmuVIdFqducdvmzQ+pUFUDo4mEelcG5a5c51rVZSfSaEVVVf3kVWb5Only/Agiu4xJvhtJ18vqgdK8aE5uBABY3fkFPx/i5ocAQDapnpMPWaUUt8mqqToG10W5oWWOXUU9QAqqyxDpnFxlFjBd0utrb1c/xJVdOYCkEwybu9ZexZQ4EGYw6/t58Kk7Af82uLOT6gW7939XqboGya66Dl9dvOa1qSsQWefwWVl5L2Ars2SOA3E62NcPckl1xMubuAyKNzsEbkuv9SjvnWfSdwipdTYfUkFSPTlF5ve8NmX3FTlvFX1WnVBfR/6ll6euQKRtKjJ6L2zj5oiQIGID+synT29FE74UiPMgLnwFeyMqN4MdJHpbskYdLrdzI090l9skvDCW70JariI5kCZfS9PvW1f+Tq3SUYFIJW6iCnG8VhaRfe+ZOTnXNVfddykDI4qrr6bXyEr/a+hSeznNA3a8aq/9Hd176ND47+NmqgMrVWYdOvuS+5Zp13RfTZ+vB8iSOioQWZ9iSHC60CKEELmj0m1f2L0EQFyRhSR0RTlT03t0tEu27Gp8r39P9WTRRS+hXlMIsixMmpqxXiQ/snbH87MvfGoPkBW0Doi0dfyr/Lpcaa+/eq8r7c3T/fcdXJROIaTpxDoEDs9a79UmMSYngelQVq/aVMl73ANkdbXNiXRteCx8vVLluw9fuzvRA+AgkYAD0/MKO/cWdVulJhuJyankYaYyq+by3mwfVWpjB9keINWobRBpQlVONFypT/KqtAwz7+3pCygJYLkQlsuD9LVYbVRa3stgOjiX3e8qs5bsukotUwW2Sh+tVg+Q6rSpEOnkeDsem/OBNAeSOJFkGyVZ+R4p61dqHeJHdLALTC//nj2mxByR7GnqVtXrVtWZD+kB0CJtKkSKqvaROG/Jk1knjiJzwu1MciIguDy8A0ivduhQPSxN9ma1lYuXgF/mtL2WUO9CqtWmQKQTI6takBfRER9LJxPS9E+/2GKrFUNkMi+pXtFEwyrVD6a9VtamQKQtKjTCz6rQMoa3E4RMzRHp0dF+MUDjMdCKiYZNnLMHUC8APUQaV96SJ2yYAcAYjFwyfZ4o51GvNSmZbDi92d3NsFevTVcPkRaJGSEwe6JhPyi1UP338V5HXD1E5qu5UZsBwzyYCl65dAhoKrTVq50iItNPNOx11FQVRJoe2zZqLDXx0ijk3ySM0vkhvbohNoEC8kt7G1YTH5r+g9kLQO9E1iId2RwIa54abJgdRJzj6J1HG+XuIZJucHmRYFDjaev4KBzJj9ev/8KVR/J116UeIg1Lx+CY/VW1B0ebVGjWWzLrcFAnRJz6j0evVqmHSNtUeGpirzaJGAAHI//WuFV1XVE/dZ9n0T0K8vqfdc5F17Lye9K7kerUQ2TNMgbMJlk3IzPRsFdr5Uci4zmkbMLtMl2Mo/3K12OrqL9lB/dOqQdJNeoh0qCiyMz8dmqYmQgRgLQ4a2qyev95X5t4nqngNJxlgvNWOEsVSxL0eZOS6kGyuqqCSJfvaLZ2ESWvJ1rrhfRaKPaAMv0hZADhBQ1fziZobSEtpx4kq6l3IvNVK6wMT3/FFYIO0mf957oT8r4BMKuL5jXV0biuP2rZsFhV11E2D9LmD3Wbr63V6iGyJhl9OEZChIO8tlYbZb46qVl/AQLABMDIixfNEYkmBwQAk/HcfEhRVZFTKXsdTQ62jbkRr78eJiXVQ2QNMibNjRjDVgZMQtilxOO9nPndqz06/CchAPLi5q+kUlGBx3Wft8ljm+xzY9VDpFodGlvGB3pqm5tomCdB2OXk89uTo/Xy/pQEACwfNKup1pMqBsoiyfcmK76K9NmlkJav3pUU1KZApPUjrs6pzMqGtKQSh26vmrtEbK9WiOD+Ms4yikvHZx9+YcWnqEvryM8sc1yR/rr4Pm2MNgUiy2oto7PWzCZe/p0N2MTzRJSiU97NVguoh0sTOnSf1xlmkohktHfpQ/1t2kSHBqGJPlg0YC4zcK3iQMqGsaqemFhF+7pB0sNkhjYVIq0aXaPJ7PkhToaZw0Ccts84+YbbqhdylDULHEhvHgYAJjr2sLndZP6iCyYcFlFTlVllzrNsCKtpOLWt/05qUyEyT8uOywtmnB1WNh8CpGtnGX34++xgJO/3e5wKlaBHSht06L7q3jMigKPRI2XOkifRajkRX6vmRZZpV/WxyxzfFIiK9N/DxFPbINK1UXKp69VeLkSbNLS1NZL3TK8OixgmDOb4p3Nv0YYrXsE3Wa6Gwy/ONnEhrUlmnkjJMt+6B+0iIa11u5G2gMSdo4cJ1gORto6CtV7XZGx4Mpk2H35inQ3z+ReEdxMoZgenS47nXFkPk/aIGOD4hmGG1WPmtdXRmNxckUXdZn4XupQVtq1Dm5AQb8t7uTa1zYlsnojsaB9PbHbrZ6WJdZMswPjAy0b3ZtYWRx5Benw0r5nJdSJAkP2HRABBXrZz32MeYo9hGK0JKDVbvaqkepXnK5pgb5MbKdt2FR1pV3JUIFJ23K1tnCYC64iZyPKDYsgYA37Ck86/k4j3AJvHTX7qvKBexZWTXOd4uwtpCQCT3cu+1G/j5oj4c0X8Cq0lkuvLVnEtG9Iq00dZLXOeNoKk6XO1RkcFIlWryJh+OKnuzRXxb06ljYXKox97YkcqcWeaUPd++mnrrZH/l0hHc7KuhAgcbT1p/vGl/5ZloNF0SKsKN1J1SXMV/S+rI+dKugKRdY6gK7uYQ7PWvQqtbNsgFLeDfXxwuvwJALDpbUlL5EJa2RGDzeApRfuYkVyvMx+y6NhVE+xlz1dFu6b7auP51qauQKTzys4VmSr1jfMixoBHQ3kzx87DVmTZ9sk2IONKeqKsW+4vYOeMAGD1uIOzDzsv2y7SE3IVWgWT6/M0DzRFwbQuN1KkjyLH1lUmXJWOhCvpMkSqGj1r7SfrQvwKLZdc93XsuPy87cxNFGEYNkjrtXqtSz7Ap/4SZGvqyAa1QATauf/yp7nd2kTkz1zPS7IXyIsUcSdVzftokxupup91DOwbDZIuQySrQwU0Jdoue45SfU3GJqnQcgsxGsOsDVjHQLnwosFNvvtwIZO8lEgPlfaI4xnrDiR6cuwZlBk7dDSmWcn1HK2aB5m3r45BrYpcyLLJ/LpzKlVoY0GySRCpQvWMypkyX6cos6KvMcxPfuqFn4U3rZDZhbEMmK0r6eHRHjFz8tXWLX9CRIAZPHPucd7fcIl7iyzrShZtW9WNVDHY9yDpmHqIzFYVI3VuhRYRWGtmIcBGMxPAbAwLIv7qZ15yrwrkLexmqoNhcmp8e4ysRzNDWvGWBCbAZfff/qVXuD15S8Fn8yIlQlpl21TtRoqGtaq83iL99SBZg9oIkbrGx6r7LdXf+EBzXnLdz4u4JVAGIX0G8OeKcAKU/LP3SFmnplZBI0pAMt55wLOzbV1yveDkwzKOYxV4VJkDqSKstYp6kDSsNkKkjap0suJkwhxF03c31CY95thx9Uk3iyT5zwOKLfPtwdEqxXNE7EKMNjPC0fDrFx3m8iIrhLSK7luXG1l0bNk2q+aIqjxmFW0MSNYFkbaNgI1VaLnkOmDvchhFzEbb2l1b6st8yaXD69wEQwsQlwcx/ez1FigvpOXnRUDxb8hHnbzjMY90x2kTkZ9cz8ttzQlpFXEcXXEjRY6Zd1wPkhapS05kpcqoCrXadRBYR4ajyLDOmWwIAF/1Ty/+JACThLK835mlGfske0vkh7QIsGEtIuyffeA3zTuuwHyRZXMOq8KjSL9lkuxVh7V6kLREVUKkDaNZFWW+9eROiNh3JEFg33pmNsYwM7PRBszM5suedsFJFdCn3VyRZCn4uEKLmXtH0iIlfwevOsuuy0gwevQvs+2zeZElQlpNhLKqcCBVtF81cb+MnLFsSp0GSZecyDq0aJwuDSmXXHd5ERfSyh6xtSWvnnYhnCzGmH+GHilN6vDKAd4yKEQQMUwE5APvvukJT53dT6GQVttCWctWZ1Ud1iqidR17ZHTUILLKSLvSKD0rL+Lk1tHSxqZGHnDJ4EpX5mvYwMQgQfK7T663Tf7XV5cfISIc7Fz0XL9ddtLhkkugrDuxPqufusJaTedHmlYXrjFXRw0iVWleXqTQyO7nRUxc2steue+znn3phy1A0hxIEtLKnKTPi6xRGRPJzIdCWuDg686duuhE9tB5Ia0CCfai+5pwI6tq1b7qBEkf1lqgtkKkLQnzahXnRaLIGMDmRaLIsNFsoojZ2OnoMAzz1KdfcH8Q0CemwlmYTq4fhkcPkyaV+26TXZYgDWkBggTdd9ujvgNIb5Xr33O94JeAJkJZZVVVkn1R30WO2xSQdE5thcgsFamMqjq5vkpeZGabvNvlAoDvRo6dUO9zuRDNxpb6JvmR+Btwz43WiBGHseK/WRrSAnQ0+t5s+xVCWnVVZVWZAylbdVYF9DYBJJ0D1joh0sXhb6VJh4fuK5IT0nJHacN8+cO335MswshxaMuBBOjzIi1QXoIdMTicGxE2wf6Amz/5+K+TQh36g5UIaTVdlVWkTZWVWz1Imj1PJeqaE6lCdU4sLJ4X8RZj9Ku0jF33HUTE3/uDD7+KCKeYEQPETjdMS379E/cwaYP8yYdAXKEl7M94//iPuXYJOOLfFd/tcNU8SNH9864r75hlwlp1qe0g6YyOIkTmqc6ReGq+SLqOll3hNw6lI0mwM6AU8Wgk3+Uqs8xUOMskK/pyzml6NadcNwL3PSEGCQHE4otvvv7RT3f7o8yijNHkgFroRqoMcRVRU26kTLuqjmvbOSpRD5H68yIz903GhrMhLSC96yEAXPaQwds4CWUxjHEVWyWurlfzitfSsjerEiAIKCGwd+a8n/abubxIwQUZZ56tom11JNkXXUNdRQGdGYS7rqohUuVwVmZG+SrJ9bIq2lduu2xexCk78dC5ke/63oe9G+A9BxA+lGBP8yJ9SGt9ynMjSWIdgEwWaJRPvPlTX/w0v50f0vIT7AXcSJ1VWXUm2asMa21yfqQTIDyqTqSJvMhseaW+duIhuVBWugSKZiYivvjiwWS4Jd5pkhCWX/KbnrIPabVTrjoLcW5EEmH37IlfmnfMgjsezjxVRdvqGtCr6KuuQbXNIGm91g2RNo529edFMnIhLfs440YAPPihoze4kJZhv0rL5UVqvupehZR1I+zdW8RWaQkIIUCsrrjxk499ZvZ4HY0p+3VgycmHdSfWm3IjXciP1K22XleidUOkLSqbFynrQOaW+roWDiT2/iLxKr8M87wfecQ/MvichYeeWgalD2m1UG4NLXhzRwhpua8Q2Dt37IWuefauh36CfY6aCmUVUVX5kHWGteo475HQJkGkybzIon4Xl/pmQ1pEHEUmKfE1GsY1DQLSx46rNzl4uNyI6UNardOhd90l2N3sdSEghYCAvPS6jzz637lmkzmJ9Q64kXladZCtKqzV9fxIa9V2iJRJrlfVd1X9l+pbxy7EJdin3AiAx1xx7FV+dZbhbKlvzVfdq5w8N+J+i7jU17mRycHoF07dt73lH+ZCWi1zI0XgVTR0VZUbqStn0kYgtPGaErUdIk2q0VJfF9IaH2ieTHQyU92/WZXRMNoYZgPz3O9/2CeFxE3GA8d0WCsvpNVTZR1K3nWXHyGy+RFKJx9KISBJqJuue9ALpQwW/qHW7EYWHb9KuyLHlumrD2s1rKMGkSZLfQuFtOwv4snYsNY2lKW1Mc6NuKZGgy96wOAVho11I4YPVWnlLcnYaz3y/w6EdIRJ8iIESCHAJviW66+59Ill+s6ApE1lvlUl2RcdX+a4ZY5pIxDaeE0A6oFI2XGszoF9FeewynkLtZ+VYAfSCYcmsmEtAPi2b3/QawDWJp69rll7FVuxEzG9G2mVPDcylR8RAkIQSEicuu/YH/qHzAppFbjzYR1upKlkd1NJ9jr7aO1AX6e64ETqzIvM67NMZdasPgrt8xPsURTf8dC5EYYxEbNhY774Mcd2RyP5BudG2NhqrTTJ3gOjTfLDWs6NuJCWjPMiShAEyQdf+Y+X/1SZvueEteZp1W/zVbqRZVTm+tcV1jpy6gJE2qyiZb+z98UhLSeilAVaM+vIC2kZw0952vkvscl1A+1CW/4M9h4lrdJUfsSbN5KChCAFIZqoH77umgsem9dHATeyap5j0TFtKvlte1jryOVdjgJE1lH6u3SC3XcjUWT3OTcCAn/Lv7r0czLAVSap1DKxI0lh0oe02iX37ieVWn5Ii2zJrxQS9965/dLp43jufUZmuJGiIa9lIbHukt8yWteg28rBvi61BSLLjnLLLTtSvM8qwluL23kJdvvbjv9a2+VPdMSsDbOJXckXPWL0e4kbMWmllo+OHhstVI4bcfNGpBAQQjzkvW+77FeX7L2Ob+h1uZFVS37b7kaOlNoCkUXqypi41Ez2WW4EAKJIs1tHCwCMZvOD/+ny95PALVNhrdiJGGaATe9GWqbEjTiQ+DesEqkbMZF67lXvv+SZ2eNnhbRKuJG8gbtJN7KuRPm6kux1qU3XAqA+iLRtxFolpFWlS1q4L8+NAHZNLe2Wio+YL3tQ+JvahbRMWp3lHEnvRtonHyQEgDgt+ZXCLhWvhMC5U+FLb/nc8KIlTtFmN1L0HEXP0/Yke+sG+7rUFSdSVlWGtGZtX6Zia2GCfZ4bcSAhAv+nn3j43wO42ybXNYxhaGO8iYf95MM2amr+iCAQ4ruNOEciJaQU6obrjr2c4nEoLy9SgRvJ27ZON7JM+fIq7crqyEChrNoEkTq+8a9DS+VIZt1nxLmRKNJsDIzvSC59YPBbxgAJSOLEuvaWQWnbm9MrXZQRzMl6WoIEpPuREgLyinf+3YUvAgAVDFb9M66SgJ/3eNlzr7pvmWvZJDfSKqC1CSKLVLW7WDakteqckYUJ9snYmMlEczQxJoqytzG0MszmP/3k5X8FMncZY/Mi2jC00YkbYXDvRloqF7O080d4OqwVg8Ro+e3veet5zy3Z9TLf6NvqRpYJc5VpV1atGrzboi5BpKzqCmkVaV8UHlMj+0w3gsNuxG2/9IHhf9cGMMbYn+R+7PZ370ZarqkVfr11tYSAEhL7e+oF73/X4CuW7b3C/etwI6v23eR1NN1va1QnRJocu9ocCqvMjdgbVqX5ESLw83/i8r8lwTdrw+nkw7jst3cj3ZFfrUWCIKUFihISp+5Vr/zYVcHlZboruK3M/iLHrcuN9CW/a1TbnMgy4aGm+q9i/kjhcl+nyUTzZJIk2ZP5JEmiPWJ+xCOHP6+NzYtoo21OZGq5+B4bbRaTHZcItlpLxTkSJQWkFFBCii/cFL7+5s/hxBLdLxO+KgKGNrmRMloHBOo4Z2tg1jaIVK2mQ1rL9HNo33hsDGDdCACQ18a5EQcSIvB3f/+DP6gUX6m93EjqRmL29G6ktSIA/gKNDiRSSCghbcWWEBdee5V8/c4O1KqnWmF/keN6N3LEtEkQqSqkVaUbmddHYacyFdYC2IEESFf7ffLTjv+0iXMj7IWz0nW1emy0WQ4k5Fb6tTPYbW5EWqAIyEe99Y3ytdljQzXM+9PWlQ9ZRUfZjWysugiRdSbMVznXSm4EAFxYi+P8iNZ2nzFsvu45F980HNErjbFLoURm+i6Izo3YR70baaPI/Xj5kSTJLiWUFBAknvz6V4tXBmEuOAAAKhCkAkFB+iOCQFQ1gJcNdXXRjdShtlxH5aobIsuMUlWPbEX6K3POxt3IZGx4MtHswlpE9reOF2p0277zex74y5rNgY4rtVyehNk+tywpY7x6NS5vba10SRSZLIuihARYfNVr/vLgFcBhF6LmwMIBxT9b3hUs2L+quuBGuhLSasM1dNKJzNNSE/0K7F+rG3H78pLsRrNxIHnQQwYHFz0g+EUdL8yYLM7oZrKDk876BePbqSSsBcxwI/aHIP7pa/7y4DX+sVmA8IxBJggFBeEh2FRR7tsGN1L2HL1WVFch0mRIqkx/dbqRJMnuh7WA1JFobczzfuwhfwXBH9PxDHa3rpafG+ndSLvl50coAxIpCUqKGCT0lS9/2enXHxywyAIkCWWlwEj326W7ZsEEqH/Q3ZR5I1VWqHVWbYVIVd/8Vzmu6EhbNly2rBsBYN2Ie6w1m3hR2OTmVVFk+ClP236+NgaRNogSR2Irtpwf6d1Iu+VGm+yS8SoOaSlhHQlAT331y0//w403HBwDUnhk+3PAyHMgc2DiX0rRx0WOrVK9G1mzmoBIW0equq5rmfzKXDcyHptkAiIARBNtJhOTQMMHCRH42V934a3HjovfNsnckenZ7HYmexYhbf0zHV1RTn7ELtIYh7aERCAkBInHvettO2/7wHt2HpbtI14wOOkSiIGSA5sgFCKcDZPCl13BMfPgU7VDaEuOZlmt/Rrb6kSKqI6QVhXlvkXazIPGXKBMYqA4kLil4/3QltFsnvdjl/2uAW5yTkQbHa/26/IjiEHSw6PVyoBEEtlEu0xzJIFNvD/kU5/Yf8vr/+rk0wBAKUHuR3o/bhscUAJBWXCEoaAwnJmAX2XQqsuZrNONHPmQVpsh0kRIq67cyjK5kbxtvhtJkuwOJIAt+3X3HMn2dcWXDv+DNjOS7JyGtYpfaq+m5Sfak7DWLJBIeezO2/VrX/G/7/v2Rf0qJUgFkgDrVmJwkJ+Md9sWXV6Jx/O0SoK9bH+9KlSbIVJEXXAjZdoXCmu5bdFE27kkE5OU+gLxJHUQf+O3XHDD1rb4HzoOabkZ7Q4kiH9M6ZfRq0nNAonIgETZe5HgzCnzP/70j+78eSDOkSg7TyT7AwAqkOR+AAsOLz+SbAsHsi/3Xa3NxqopiKxjZNoUN5K7zQtrxbkRW+rrYGL5QPy8H3vg75PAR7Ux0NrLkbi1tVzjXq1WcZAoKClxcEDP+6PfvfP/XPfJ3eOuD6WIpCIhbTgLgSIRBERBQFNAAXIqt5gpHEgHk7oS7Edl8mEbrqEytd2J1DG6bYwbiUHCPkgAwM1ktyL+Z1974vu00VEUV2zlhbV6N9J+WZCIBCRSyAQkSkoEyY9CICXY0D/9hzfe/65Xvvzur1CKpgaubI5EKUrcigqkCAJJQSATcPhOJPt83uUWfVkr9lGF2nIdy2it19d2iBRRFSNe026kNDy8xzwPJJNJfB92bYyOXcmTnrJ98uLLguclYS1toLWGnrrvSJ9i74KyjsTNZheu/NcLbQVSQQr5gNtvnbzqD377Cz8WH3roB3CJeCKlKJlfEm9P5qBkcyQOJoPyoa5NLPdtO2hq0yZAZJ6qmtux6JhVvsbngmJBfz5IpkJbRGAHEgDQkWEdsfmO5z7gLcEQL9NGI2KTlv36joR9P9Ijpa0i0KGqLZGARMQACZKEu5ISuzv4id/8tVtf9dY33/8QgKcGvAQm8Y8NewkabikRxOCI1+MSwOHqLQZokMKkT7AXU1uvq7SahMiyo9IyA34TmgeZVR4vtc2bQ5KAZBIlVVsggH/oRy79b0z8CT/R7nIjLj/CbLJd92qhfJAIEums9jikpaSwAFGBnU8iBaDFV1z5wZ1/fPHv3fZcafMjJCQJ91hKEkoJ2ymYgoCS0mDnQra2AxGEkoJQ0mAgkh93XYOBpMHQ/pR6Ocvtq1ptuY5OadOdCLBagn2RG2kqZ7PIjWSrtlKXEnEyMZEA/qpnHvsOrc1+xB5IsmW/faK9E/JDW4LEoUUblVIIhESgJJQMECgBJaQ8fdK84Nd/5ea/eOPr73kEACglKf2ZmksCm3gXNBwpIZUgFT+3PzL5CYci+XHX52AyAyqbmGA/kqDpCkTWlWBfpc+q3UhuqCsnrGVzIpFOLQURTyaGJxPDj3vC6PSDHqa+Q2s7ATFZY8vPj0ydpAdKe5WGtAiAjB1J6kqEBUmcaLc/AoGUMJqeec1Hzr3zd170+R/N9qqmEu6CmDmZmKiUEKMtKVRANNySMllORUkRhpLCUFI4EMKFtwYDmYwxg6EUw5Ek91PqhfZapLW9R01DpM4RqWjOomwfVbmRVeEx85xjDx6TsUnAoiNtElcSz2wngP/Ft55/1fYJ/HykbZI90tP5EcOmT7R3RnbscDezEpTezEqSW7RRxaW/QexKXMhLYucs/+Qv/9xn3/KSP7jla6QkyvsZDKQ47FCsGxltKaECQaNtlYS5to+Fwq/qGg7TH//KhyNF3o8YbamqBsJV+mkypLURcKQqQhe/8YtXlTrnkqdZNYlWpIZ91rZVnlfxuND+0FutlYGkksatn6RUmgyNIoP//dKTv6on4vvcN1UlBYSQ8fIaIr3L3mZ81jdcnoOMJ5C6EKVhjqvy7NI3kYnsl4ckN2aXw1Ehv/UxVxz7red+/0Oud726ZXWIwO4umvbWzNOhVB0xk3DhVLscjwujCkE8PtDJseODiP3+9/Z0cg7/FfnPd3eiqYVIsdyXu1W2FdlXps0ybQv19TMv+LIKu1ysLkGk6LFlQbLstmXAUbRdKXj4jxeBJHvMy15y6i+FEc9Syn47lUIm5aIuTNKDpCuaDxLjraEWGW1LvU0a1nQwGW6LVzzjn1zw+1/3nEvuICKW0hYCG5NWXQhB7r4204BxeTltWMQAmkwMkyCOJukN1MYH8eMYPON9WxDiv5r9fT0FDgc01wcAnDs7yQvz5j1fdVuRfWXaLNO2UF89RFY/dlPdiP947v5s+SUAzLmjHb3sxSffKkldkSyd4cIhUyARPUY6IS+bFS+wmUwoTW4JkEIjBYkPEwOGiba25cue8dUX/K9v+BeX3gFMOwMS6YDOMVyiiFnE26PIsBCU3PTGQseFWVMYeeu+AZi+HbQ7x8F+lDgat29vNzoEmLNnxlW5k3nbF+0rsn/ZtoX6OgoQAboBkqrB0lhYC0hBwpl23vLfBNgcyk2fmxx/3zv33qOkvMQtMS6kgCLrSsg5Eer9SDc0XRbh5v9MuRKtoVkny+Akk1CdS3GrGhiORsfEXz79GRe87Fv/9WW3uH79AZ0EsZvYSoISV+KDw29vPHA42AD2s+jDaTIxLET6Yibj9LiD/SgJn+2ei5JQGQB4MFmXGyk7qFYFkrVARDV6tm6JsRhY2TZFjsm2K/O48P7x2JgwFIIA9kDCk0ny75ARh7i+6JHBuXvujp7zmU9G7wJo2wID0EIAzLb6gggU37ikV9vlPgpIXCTYTH0JIClBhmCIQGQg3I8hkCEIo6GJoInV/q75vne+5d7v++B773vNox69/X/+448+8mPkLatFBIjQrQjMxoW/AEBKaQALEZdHiQARBNYYKy0SiEilWcoUItFEsJApYIZDEuOxK19XkJKwtzfhrWOKHEhaovQPcATOu6lOZFG7LruRWY9z989yJMkjL1fyjrfsfPHtt5h3Bd5CfnZJDZts92+S1KsrSv99G3BSdZe4kuSGZWmCXRuXdLeOxF/dwLBBEOJ9F18yeOWv/PfHvdH17Ye6HBS05iln4c9kNd5jZkyFpnzX4va5KkNmmPGB4fHYAudg3/Dens2L7O3YHEpFTmTe9kX7iuxftu3Cvo5KOAvoRkir6Lai4Ji3r64QVyGQxJU09I437z753rv4TQ4iSshkfSbqQdJR5Ye34M0NcoAw8byhyNhtkdFpDiXOp7gkPQm+ffuYfOPjn3jeX//ADz/iM+4cwk+AxyEnY9J8iTt10l4QG2OmIOSHxAALpChiZmNXqx4fGNbamIN9e9ze3oRzIDL94vOfz9veQ6SANhkii9q1wY3M27cyPLJtszcdctsn4+kc5dv+bvfp99+L1ympEEgBKVSSbO9B0lVN/zuf5UpszsRzJGwSiLhtrmSYWSeTVIOArj7/AvXGpz/jwn/49u+6/A53HhKHHUpyCZ4sSFJwGJ0sJMpCijghbziKWEfx/XMcSE6dPDCAzY2cOztZVAq86rYi+4rsX7X9zH56iFR7fFvcSPZ5kcez9q0MmiB2JvEM90Ntx5M98c43m688fb/4q8ALa/Ug2QQdDm+5rZzrSpwjMTDxUjkmSbynwDHxAp6GGYOBeO+J84J3X/GlJ979wz/6qM+689E0RKag4nIfzrE4iMRgMUazS9KbKGLe34vM+MDw7k6k9/YmHAOE3Qs8deYuAgDDNgx24XkPmudOymwrsq9Mm2Xazu3nKEEE6I4bydtWtk2rciWz2o4ne8njd/6D+SdnTspXHS797UHSbc12Je531pVY96Hj3EkWJC5fYqHDJp2johRdt70t33fJZYMPfNO3PPjKZ3z1xWfdeYWXRJ+q9kJ8XxwDNpqZCGYytvGu8YE2k7HRuzuRGY81nz0z1g4gp8/endYUu9fG6TpyHkg2OS/SQ6SG47vgRubtayzcBVgX4h5PJvviA+9WX3bynuCvlZRqHkj68t8uan6IC5gBE9YWHkbH7sSBJG4XP06cDTjOqfNuEIhrjx1XV1186fDqp375Bdf96++8/C4gUwLMYAKbLESiyPDBgTGTsdbnzk7MmVNjs7cbGQeQ3d1TpM10ldax7Ys4x41scl7kyEEE6LYbydtWRViraLtlgDG3j4PJLlFcxzse7xER0dUfVI++67bgtVLI832QuFu0ogdJx+Un3qcdSXqvmTRcxTFENGcqu5JQWAoTNmnyntmkQGF7Vinx2cFQfGo0Uteff0F4w2O+5MRnnvzUC+/+8qdfeFYbcDQxBoDRmnl3J9L7e5HZ2430mVNjc89de+b02buxu3sq+dhlIQIAW1vnJ3mSGCSbDBH8zAu+rNEy365DpOjxi9oUBUkdYKkKKpWA5GCya3kAovF4L2YD0ac+Jh9482fD10khH+pAomKQiIwj6dVFcebZYZgAAMfQcAt1pqEs51Y4CWv5zsRNckwnPBowx+dhA4CSmfUEnBWSPq+kuFMpdZMQuEeF8gtKibsIdJJA96og2jl2/GDnEY++d3d39/TUtatgYABge3RenJyf8PHjFxdxIz1EltBRmWzoJ5Cr7qeqvrN9le131rFlHifb2GZc7WNmfuzjozsufAA/+6MfHLwq0niy+8wrABDi0IRE11mvrsj/KAButTR3D8TkwyEECAJsDIgFBBsYcpAQMIJhWFqwCANm4QHFeG4mnT3PLozGLsGP4zD0pZHBl07GBiAB3jGYypqANPFw/zOfesgZFVzyq49/6vtfAQBhuMWRHif/bhxI1qQy/ww6+0+mDRBZdRCuYhCf1UdRaGS3lXledF9Tj90HOfsYl1ymd579zae/+R1vPPGSiVbf6EysBAEECGF/EzPYC2118l/GkdV8mCSthF1LjQ1BsADDhrdkDActHDDi/Ijw71mTgsQ4ePiOhwE7B9bOYCS2dcIMAsWgAUEyYxvAttHDF+7unXmlUiEDQKQn4vixB2RLfXvVpDZApCktC5uqjisDkln9rP0xg/n/+aYzP/Suvz/+X3UU/GCCCiEAA4h4nUei9KAeJl3UYpgQAJYyCXUJY5KJjOTuSZMAxVu3i91zBxP7YXGuhEEAiwQsYJq6nBQ2BAOGVKefv39wTsgoYABGCMkHBzsEVOJEOusQmlJbINJmN1K0bZHjl4HFvH3VP2ZmV7MbhEMzGe8Lv00gQ57oMZ75DWd/9X1v3b5xvDf49WSviH8RQRiARPxNkgj+WvT9v8guKR8mIDuAuy8JDICkBMeDv2CRwEJAWri4MBb8/AiBOZ556IW0wIQ0L5OEuexjio815k4a3Prc0YWv/ZjWIwKAKBpTGI4wnuzRYLDdf9QaUFsg0pQWDfR1h7UW9bt2dzIIt/lgvIN08sfUqotTjuTpz7zvFdd++PxPn75/66VMfBEzIG3gHABAnAIkqdzqYdJRZT+mgLs5QOJO4u8fnHxpEGlCPlPtZT9B8PMgMSxc+9htEGKn4pa1t47FYPJ+bL35+9To+jNGa9JiQlIGPIkOCEQUBsP+49WQNgkiRZ1EFa6ljMqEteYd25g78UEShCOejPeQDxLwE7/81FW333LwzBuvP+8lrPGMeEgAx7dp9RPuHFdx2V56mHRX0x9D353YLQDDxOEv9/eOf7ENV3H8909CU4hBQhxTKQ5zwcEHaTgMZ/90Z/DC/49IMiIpBEmtTdTkv+lentoEkaYH91mq2o3kbSvjQNbnTuLQVhYkgQzNRI+FCgYcTQ5w2cP2Tl384FPf+ZF3PfRnJjr4YWZAxqEtxOAQXsWWu+1ufI4eJp3W4Y8jASCSANK/qVvkl93NCWIlNYDxA46hxN5zhgt76WhsvvDjp/hFfytNQDb9Jl3mJFEYDDkMRjwcHu8/Ug1ILG7SKRX90Cz74co7rui2RW14iX3LtCv0eBBup3EIAEE4Yv9ffyBDk3yFtM34ac+89TdGx3a/NzL6TKQ1tNbJgn1JZQ7S0AYAC5MYKH4Svlf3RYjzY0Qgb06RP1lVSTvfSEl7e+bkR6l4n0RAEoIm1+7w2772Pv6NvwMAZk3peQhSKPs5VYMeHA2rbRBpywdg3nUsC5Kyr63oNTQGknjzFEyUCg0ABGrIzMxPePqd73zoo+5+JmPyrshoRCa9H0WaWAWQ/f7oYOLW40IPlC7KuhCacpvkbXdQEd5kVSklVAwWO5GVksmsUhA0nfqTzx/8p391MnrtF6bORZKFkAwAUgYsZcCuzHcw2GZXmZUz0bBXhWobRKpQVW6kjg/cIrBU4U7mnXMZkNh6e2YOgqFXe8/svvU5kMTN+LKHnr33ac+6+XtUePDLkdaIdAoTdj/+chrZK+7dSafkQ8JfscDf7i/WSUQQ8WMZPxZCgES8Pc6lMaI7dqJrv++m3Z/8HwAgSDBRAg0jheRADU0QDIyUAQdqwDWEsnrwLFAbIdLkH20dYa2yICnati53ggQkAGaBhNmwkjFM4mKaJ3/VrS+74JJTX2s4ukrH4a3IpBPNnKGhPJAAPUxaruRvUgIesx7D74sZEz79Vzed+2/fcNv+730g6ZeIhRAsZWCIJCs1MNpMOAy3jJQBb41OmDDcYt+FHNu+qCsupLPQayNEqlATf5CmQLJs2ypAkrvvMEhCE8QllQlIYEHyqMfd++mnPevGb6Xg4FcjbVgb60ymb7nK2SjZtHJCXb3Wpyrh4Vd1AYDm6K6zk08+/zNnfvS/jvmOfSEEEwmWQhrrPgIjZWAG4ZYOg6EZDU9oKQMeDY8bwDqUFiXU23IdtaqtEKnizV9XWKvpRPu8tsuC5NC+OD8yAyRAFiQMP+kOfso/ueWlF1x277M0R++JjEGk41uwMtKJZ3HjmTAB+rzJGpUHD//vUAQY2cU6GUhc6YG57y9uPPdz//yWnRe9g0iwlMoIIY2SoZYyMIEa6jAc6q3hiSgMhsY5kPOOX6zDYMjHj11shsPjRVzIkRjcm1KbSnzXKcb88WjW/kXHzWubd+y8NouOn9W2snbJ/BErCoKhGY/3kzEhsLkRMZnsU6AGPIkO4JaVZwY/7IvvvOnyR9/93E9++OH/Mtof/QJDPoCZIYQAEyCI0wHHn6CInH/1/jdgv2Q0267XSkpLoCh/OzAdjso+9/6GyRwhoqlwpjb7156NrvqNO/Zfeg3BwoNIsIjdB7MxQTDSgQqNIKmlVByGW2Y0OGbCcKTDcIsH4TYPBts8jGepO4Ccf+LSfg2tmrXpECkzyFd5jqLnLdKuDEjmHYcZ/ZRqF4MkmfIRhkMej/fhg4TZUBSNhQOJncksSMkBR/oAX/K0G197+v7hm2+5/vKfjnT4vZIZLASYCIIAIobwB63MfUpmAqWfc1KJpj5QM+Dh383yECyyzz2ouNns1oHoU/v61t+9efdXXmX3C5ZSGmY2Nu8hWAoVkZA8CEc6DEYGgJEy4OPHLtSBGrKUAZ84folJln03kQ+QMh+D/iOzpNoMkSYAUOZ8RQfsVbeVvY6m3QoG4TYAIHYlCUgAO3bES04YDyTEbNgDCW2fOLv7JU+/7lduvv5Br945deFPGh08WzqQuEUcpy4HuTmRqX/5M9zJoXa9DqkIOOyu5eHhV+RNzP1/fufBn/3BvrlhlyDY5j6IAdJKhUbJwEgZGiGEDtTQhMHQKBUyiMxoeMwEashbo/O1n0Tf2jqf3e1xSwJkGfUfqVhthkhVWiXktEpfs9ovA5KycACWA0QpOPnhrTAcYjzeT1Y3cSCJ2wsHEgBQcgAAiKIJLn/MF67T5uYfuOkTj33mZO/YjxuWjxfMkFJAwM4piGNdtuwzE+YqAhSgD3nlqSg47O7y8HD9JutlMSPic39/evLeP7xv8robiQQDzFJKJpJxGIu0lBYiQTA0UigtpWIlQx4m4asRD4ItVsGwboD0H5UCajtEqnIj6wprzdpeN0iyz0s5jTL7/PCWDxIACIMhxpN9Ui5XEh2QXanVsBQBQ0FE0YSkUObhj/vUO4noXTd+7IpvifaP/RizfLiUBCZ7L3dhCMZPygJw5aDIXJh/sfDbuodH1KXMg0Zem0PgyG6bkQtJ+vfgoXnvH3f0x//kzoM/u5pIsCABEoKZybgciJKhIRJaqdCEamCkDLRSIbvqKyGkCcMRnzh+iRkNjrP7UrK1dX4ZeDT15z4yobS2QwToflirTD/rBAlmtF143CDchgcSBkAOJmEwdMcZMNNEj22sihlSBMaBRMmAIz3Bw77kmtcTiTd8/hNP+jd6svVDBvLhIsmXUJp4d8l3IPkWzEsABdhcqJSFhm12GBx5rsPfT9m+GXB3K9TY/8hu9Ok/uTv6k/cB8YTBuGyXiLSDh5SBAdgMw20tZMCDcGSM0TwcHDOj0QkTBEMOZGgGw2M8GhyfggcAnHf8krw/26b8KYtqLa+3CxCpSk2FtYo6j6LX1BRI5rXNg8zUcw8kwAxXEssAwESPhQMJSyatI6FkwACg9RgPe9zVryISr/78J570r/Vk63sMySsEpfdzF1lXAkwNdkAKlbw/xpTyQjk5ZcZtHpEOfYhmQCOvbRYC2fCUv80/3h2XfFAY8bLwDM3779+LPvPnd0UveS8ACJJsWLOQii04lGFmY/MfoQmCoQGzCcORkXHoSghhgmDIx7YvNIPBNg+CraTSajQ6kTyeAZAyavOftvXqCkTWEdZqCiTLHLuOnMnCtvFcEvJdyTi+qVXGlQCAGesDIgYpGbKSoY7vjS0AQOsxMRt+2OOufjWReM2t1z3hm6Lx9nMNq6cKEsmy8iILEiAd7DKD4yyo+G9Kto+pTfELyVPdo9DMD84cWMw6LhcacV9FwQHEf3yOV90l+/5G5uyb9sx1L79Pv/xaAEaQBBExiCCYjJLKkJAsSGgi6SaqGiUDLWXISoU8HB4zUigTBEMexDPQHUC2ty9gADBGZ+FR9Z9gXn89dDx1BSJtVRUgaUvOBMiHx0IXku3XdyVhODTwwluBGvq3X8dYx3NJmKFkyAAMsyEgnILJQ6645m+N0W+663OP//Lx3gXfaXTwL4SweZLElXBaGkzuQmclfDE7/OW/QYdUJCw0b7JkGS0AxNxrmOpmBhDjcywCh99H6jrsI3tTKX0yMqfecFZ/8JWnzT/cEldaGde/cKErIVnJ0AiSLITQQTA0UgYchiNjtA1dbcUOYzQ6YQaD7SR0ZYxOAAIUch99eKshdQkibXQjVZ2/DSDJPi/rWKbaLnIlgRoyAHdPEvJdCQAoQEfRmIBQaOtQIIQ0lzziYx8C8KH7b3/4b++dftC3sR7+SwP5YBmXBhtmOwbS4Ys9NGDmDK6LwDLV3yyVHPzLal7vea9p6pgc5+aDw28703UAMTwOPjY2d772pPnrN43x+R0AkNIuyc4wkEIZCxTJQkgtSLJSoZFSaQePQIZMJM3WcQuPIBjy9vYF2sEDmA5dHbdzQLJv/ypwqAMsZfrsPNi6BJEqtc6w1qztbQRJ9nkZsAAxTA7GOwJIXAkcTAKVLJ2S3Md9rA9IyTDtIRobZkVEgrQek5SKtY7owgfdfIu+9LO/QyR+967PPfWfR+MT30o6fJYgElMJ+PiWren3aPcKZgy2cwBQFDBNaN51Tu3JC/dhNjj8vi0N3ATOxHWcjfjs3+/zp//mJL/qWgAQUjAZwUJIJhJsjOZAKqYYGmAYpUITBkMjpGKlQh3IkJUasFIhu9BVmISuRskbvbV1HjOzg0evFqprEKnDGVRx3i6CBFgBDguO9Z+7VYDJD3GNx3vkRrFADQ3bJwTYEBeYIWXASoYU6TFF0ZiYFWk9ISnTj63WE1zyiA+/WZvoLTv3P+LSvZOXP0dHo28E1BMPV3PBW7cJh6q7fOWNWPMG7jxxibBW2b6T46Y7ObzNbzcDGu787mqZ05n/YMAArHnnXWPc8caz+Nt3H5hb94SwZbqxjJQBEwlm1hzYiYEGAARJ7eAxCLeMIGEAwnB4zARqwFIGycq7o8E2G+PKds+LGcacAUiRN3XVUFYX8yFru66uQaRKVQ2kNoAEmA8C5GxbFg6lwTTtSkYMgB1MQhveYgZoKxiQC3ExM0tbtSWUCjmKxhTpySGYAMD2hTfetX3hjf9L6+hlO/c8/lGTnQd+jdGjryNWj7PwIJCIgWJ8h5J5MX758AwV+Re7LBim+sjvePY+/7gCM8+d23ALYBIAwwCBJ5r33j/BvW/bw5Xv26MP3WWbGhZCwM71sBVX8TpXHIPDCJIcBAMjRcAgmEG4ZWzlHSEMRyZQA3bOIwiGZhSvdwWk8ACAY1sX5oWusupyKGsj1EWIVDn4V50fWTdIstvKgqPs89L9u3uTHIaJDXH5MAnjMNdYH5CdRwAg3hbPKyFmJn+704kHfuqzWn/8BgB/vHvP4x813r30n7He+ioY9TQCDfJWls17YfbVHR60p970mhLpRT6YPvhm7su2yd4MjO2dzZn1SYP9D0e497174kPv3sNV92V6MFIETEIwABhjXYcQkkWc95BSsRQBh8HQkBBGySA/bBVu8SAcJbmO4fAEuzcyhgewXO6jThdStTYCOF2ECLB5ICnatslwV9nwV5nnOTBx+RLPmaihHkf7h2AiZYAoOiAAwsEEgBFCQtvHCVC0jmjr4o/fsIWP3wDgz/bPXHb++Mwjv9xMjn8lzODpAupRHK8eDGAqjzJ1wVn5+2tOpE9dR8FJg+za+su9xI+935ox+bjGuY9EuOND58TfXWXo1ASwgHC3nrXLkyRL2EDJwIAorrKSHIMjBojiwWDLGKMTeEyFrcItHg62k9nmFh6pPIAUUdOD8EYM+lWrqxBZp1YFWFEQlGlbFUiAOQN/HX0Owm2zP95J8iFhOOLxeM81m4KJihdBGesDsgPUQEfRATEzKRlQDBNIGWitJ8RsSKgQho3QOiIAGJ6449TwxB1vMSZ6KwDs3veEy/X+pU9hvfUU4vDxZOSjiUi6sZqQjtv+tlkveKph3r4Z27LHzRMhM5pxfB2UPLW/jZlqx8znGJPPaOxcq3HvNQfi4x/bp6vuSU8v2K5QBhMEduKnIMGRnkDJwAihWAhpE+fBwAghWYqAiciE4cgoGbCUITMb3t66IKm2CoMRB8HQDL2w1WF4XJBdsr0qF1JF23X22Xp1GSLrciNF2i+zf10gQYE2q7iShX0M4xteOZjEIS5kYRKqIc+ACQOAjA5I60B4MGEA0HrCggRpo4mISOuIhLClqFsXfezzAD7PwOsAYP/0wy/Wuw95DEcnHg8ePAasHg1WjyCAnDux9wf3Xk0WGsyA8HIOM178IRWat5ImwL0ExtTh1mnwjkF0M+PgeoNz12u65zP76kPXaXGbe1NhjGZJMSyEYMOGhXUdcPM7ADLD+P1VKjREZKQI2LmOIBho+16HHAQDDtQghoyFR5gTtnIuBACObV3A896SOSp6zLrBsvHqMkSqVpVQKtJfFSABVodCkTalwVDg+aFty8AEAKJ4CRXnTmR0QFGkKNJjIhIJUHSckBcqhDaatJ6QXcNJkDGxUznv5ntw3s33GBO9z13k+PQjLjbjSx9iovMeATN8lOHgQWD1RcTiIoK46FDoS9jEva9FSfZsfVhuYJ+98dbaEc0w97GO7mQa3wo6uJlp99ZI3PnZifzkbVrcusNeGMoeJkDxNqlUchoGsxIBCyHZARY2RJgAg0gYKRRLFbASAZOQhkBQgQ1ZBcGQ3e2RwxlhK/c8hscstdGFVA2YKvtbK/y6DpGmB/6ybesGSdE+VnYLK7YpckyybRZMAFfNBYRqCAeTIBjqyWSfJtEBEVHiTuK8CRxQmA1JGRAAaD0hLSRpowkA21ny8Zd7o0mQTBIj4Xk33gPceI/R+hr4YiUmZ694kImOX8R6+xLw8FLi4DwYdRGEuIBYHAfENiC2wBgRRAggACgAIDOvPyKwBngfxGMAe4DZAXiXYU6DJqcY4/uYJqeYdu5gcfZ+I++8J1IfuwcAjDEk4oS3fa45BgZcbsMYHbsOmZBIShuecuCwEJGsZKDtc8VKBkxCGCUClirkQIVs2HAQO5QgsGBXmZAVs2E/bLU9Oi/vLoOLgJHL05xteWrShRxZF9N1iADVg6Tqc7cFJHnb6gSH36aMa0q2Db37us9yJ6EasIsnBcGQJ5N9AoBJdEBK2fuWOKBE0cQ5F5svERIhCXJAAYAYKsn1OKBY10LJQGHbjbU8fu2tAG5NDuD0eJeHcTIxqHxpEx3axgUmmLhv9CJmUQ4okm2CJEd6giAYxM+Vi4wZ9/5IYd2GYQsUJYMpxxGoeCUBNWBmw8MYHEG4xQDgh6wAYDA4ljx39/zIexmLXmfBY7rmQjZKmwCRqlUWSnWCBDO21wmSWW2y11LaYRRs429Lts8JdRHAHMbfikM1pNidTAGFGRgOjzEAzAIKAJCekFIh2GihjSYXBvMG6Zl/R5tzkcm1KyXZhwoAzoJFCmUAwHjtZoW+2KQxMiK/opmSAVuo1OAIodgdM4jfr3hWuZFpyApCKlZCMUlplLA5EqlCDuSADUdJzsktxw4AQbjFw8FWHKLiOGR1LH5u/34ZeCzjMFYZvNs88Lf52kprUyCyzrBW0fbLgGTW9jKAWQUSeduWPc7fVvS4Q9t9mABAGI6ShnOBomy4CwCYbY4kCAZIQ14TivQ4gQZkoAMAUQwVoycUGU1SSJh4m5NzEwLJnBW4HAsRTfkKKQPMkw8pPwENe4Lptpn9Ukj/uc17BEMW3nYiYVQMEKniaiqj2UHDNrLrlAHAINjmMF6GRKmBceBwGgy2pxzI1nCpkNWybWZtm6UqHVGVx3damwIR4OiBZNb2otApAom8bcuCI29bIReStz2GCVAYKAOMowMBABM17VAACxUpAzAYgohyoMIOG5GekIkrwCKjScRVYG6blQ2lZcNVs5xMFI3tC/NCZkQuVOUlwFknjwNvu5SKXSjLvR4gBYsQ0sh4cUsAUCpkJUPrVAhuBWV7rAqMA0cYjjgMhofAkAMPxvKDfNWDcJX9tR0Qa7++TYJIHeoySDBje12upOw2v79CLmTW9mJAAUI1MPFvjCf7FARD8oECANHkgJjBPlQAQEfjOPw1oVAoGBnYSZLxOSI9IcT3S/FhEsXQ4HiA1zicAwEAGeY7FEbGjSCYggoAiHjZdRm/D+7mXoB1Kw4Y6TsGSLJhNIg4TBUMmJnZhQkHoQtVpecfDuJwVVxMHIMjvdS8y1+8bRXHUQZadbmQslr7oF+1Ng0iVbuRuq6hCZDM2l7ltlVcSd72Qi5k3vY8oAThiCnenwAlsMurhHHyfRznT8Zyj4hEEvoCLFhUMldi4EL+xoEFAIRQaXuSyeO8f2DaTHL/9ofCVxlJkcIh21aqIAZIyOytoBh4DgMApMtpxEn2MIZFrtsItw5tGw1PFAlXldlWZ1+rah0uqnPaNIgA6w9rFT1m3SABqgNC1TAp29bfnuzzgIL98Q4AC5S4ATmgAAlUkt8OKoAFC5C6FSJBPlgACxd7EYzBYDu5EB80AMDMPNHjUp+nQIZsvDCWf77kxeIwWJR7TWrIhjU7YACAW26dMV0JNhhsc3b54VFaplu3a1gVFm13IRupTYQI0INkle1VhqnKbFvUtuj27D5gOoeC/fEOMcBBOv8EADAZ7yWpawcT/7EPFgyB8SSFkO9cAOtegDQ34UupcOHgdchp5PxTVXEICkgWrgQABKF37eqwwwAsPAbenA7vxDzKLEmC1cNGywJklrrqQqq+7lZAcFMhUoe6BBLk7Ju3vQ4Y1Ok2FrqQOfsxDLendnphr0MD7ni8a90HiHywANOgmQIMAIymITNTZW46EksFg0PXOXVtfHhwccDIOg8AiO8iWDUUlmlb9XmW2d6rpDYZIlW7kWX7rBskmLOviUT8rOPrdBulXAgOKwuVQ68pTdAnIaCpYxxcnFyOIbMt59TltShXYhvZ68t1F0jh4d92Ntk1q8fi2+sAUJ1hrGX765WjTYYIcDRAMm9fVeEtoDggqnIVRd1GKRcyo82hdl74axFc5ioLm3maB4tBXBmVOWBm+2Havu5v7k1BZd72sqqin3WHslqjTYcI0IOkykF8HSGqZV7TrOOybea1y23v51by5CDjVBQ2heVmh+dBxWtV8b42A6TqMFZXBvvWXOdRgEhdWidIMKNN3W6lTQ6kzL68/bPazWu7UIsgU1JVhHSK7G+LW6kaCHWpNQN4G3RUIFKHG1m236IgwYJ2ZZ3HMseU2d52aJRxIIsGiSo/S6sMSKt+q15mcK7TrZS9lrLHrMuFbDR0jgpEgO6BpEi7KsNbi44p2lcd0FiU61h1/7x2eWrzN+CmwdJUmKmufspqo4GwjI4SRIAeJEX2LZujWGeuoywwyoS25rWvS1UNqGXarMuVVLl9njbJhbQKZEcNIsDmggQz2qyyr+5E/bLXhRX2Z9ssajur/TpV9HraEu5qAlDLHlNGbfsctEJHESJ1ap0gWdSmydBX3jFV50DK7p/VZlbbIsc0oTa5knn7qnQTVR5TRD0cVtBRhUhdbmTZvsuABAvargKSWX0vC5m8fW1yIGXe83la9rPU9DfkOuAxb18bAFJVGKuOENpG6KhCBOguSIq0XXagntd31SGzKoBRBBZl3ccyn4kmB4umnUkbBvy6ANJFte41HWWIAO0ECQoeV3d4a9Z11AWTVfoscvy8NvPalzm2Si07WHQtX7JKf/NURVhvlWto3WBfl446RID2gaTMcVWABAv2twE0/r5Z+5dps6htkWPboCoHwzrgsexxVYWiqj62l6ceIlZdBwkWtK0LFov217HP31+0zbx2eW0XtV+n6ghnFWlXR0ipLoBUCYg2uZBWgq+HSKoug6Ro27pgsUrf84BQlfvItlvUNq99VnVCZtXBoilnsg7wrHps0TZl2h1p9RCZVltBgoLHVuVKlt3fRN9Fjp/XJq9tkfaLjl+n6nAndYaZugCQZdWmz0Uj6iFyWG0ESdljV3Ulq+6vCiaz2lQdzsprX/S4plVnorlIu3UBYtW+i7ZZpm0Tatv1JOohkq+6QYIl+68DJPOupan9dfeRbbeo7bzj8lTlZ6WqwaLKAbPOhHwV+6seYOsG9Uaph8hs1QmSVfovCxIUaL8psFglnFXkmDJ9Na2mQ1pF29Tdx1HIb7T62nuIzFebQYISxxY9TxUhrkXX1RQslnEeXQhprTKgNJVwL9qm7txM2XZl21ZxXOfVQ2Sx2gqSssc25UrW1cZpnfNDqvicrCs00zXA9ABpiXqIFFMTIMGS56jTlczrtw4IVB2mqrtCa1F/TauOkFaZtm0BTNl2Zds2qbZeV6IeIsVVN0hWPUcdrqRIv1WBouq+sm2XaV/m2KbVxLfmNrqYtgGk9YN83eohUk5dAAlKHF9ViKuuvsq0K3PuMsfMO3bZvqo4V519tREeVZ+vCtV9nk4AqodIeTUFEqxwnrLXWFWIq2ibZdpV3TbvmLLHFumraR1Vh1K23bLte2XUQ2Q5NQGSVc9Tlysp2nbdkFgl39H2Kq2qBr66Btx1wKNs22XaV3VsG/qvTD1EllcXQLLM8XXBpEify5x7mfZFj1nUxyK1bSmVOkNbdbQ9qgDplHqIrKYmQYIVzrXM8VXDZJl2Zc9ftH32mLLHFtU6B5smB8kuwWPZY6o4tk3nqEw9RFbXqgN82XOt6kpQso91wsRvu0z7osfMOnbZfppWFYNOW1zKUQdI59RDpDp1xZW4PpYJtdRV9VWk7TLts8eUOW5RP3mq4+9f18DVRAK+TPu6w1Grvo+bUvFVuXqIVKumQFLFuep2JX77Isc05TjqDGO1eQBo+ht4W+Cx7DG9CqqHSPVqGiRY8XyrwKTMcXWGsJY9Ju9YX20OYc3TusJbZY/rCkB6FzJHPUTqUZN5Ene+qpbsWHYArmuwb2sIa92AqWPAaVuIa9n2qx5XdR9tOk/l6iFSr7rmSlw/Tazhtcwxy7qNOkJYnf1H76mtIa51HFNHH208V+XqIVK/mgSJOx9WPOcqfTQdHit7rrzjV+mnK+pCBdc6j6u6jyOjHiLNqOnwljvnukJcqxzbxvBVl+BS9QDYJQh0ESCdB1YPkWbVRVeyaj9VJbxXCV81Ebpqsry7refo4rF19NPW89WiHiLNq2mQuHOigvNWFUJaJ4yWPX/Zc3RF654/0QZ4VN1XG89Xm3qIrEfrCG9Vfd51ASF7/DJ9bELYahm15Rt7m8JO6xjMNwYgQA+RdWsdrsSdFxWde9W+VgVKto8q+1m1v3WpTeW/beyjjr7afM5a1UNk/VqXK6n63FVWhVXZz6p95fU3S5uSF6nyPG3rp+q+unDeWtVDpD1alytx50ZF568DBHVAoM+LpGpLRVeX+urSuWtVD5F2aZ2upI7z15HQr6K/vD6r6rftqmswa/tg3wOkJvUQaac2FSZV9Vl1f3n9ZtUlwHQt5FVXf3X12aXz164eIu3WOkNc7vyo+BrqBEpVfRY5zzxtaqisS4P8ut+vdZ+/MfUQab/W7UrqvIY6HEUbwlSbMoB0cYBvw3vfhmtoTD1EuqM2wQToBlDy+q7rHF1X3QNf1/svojZcQ+PqIdI9tQEmQL3XUSdQ8s7ha93va91qcqA7CuBwatO1NKoeIt3VuvMlTnUP+E3lPGadL6s2vOfztO7BrO3re1WtNl3LWtRDpNtqiytxauJ6mobKovMX1ar3P2mruloJtqradj1rUw+RzVBbYQI07xza8h5ktQmDTr9MSPuuZ+3qIbJZahtMgGaBkj1fk+fdRPXLg6Rq4zW1Qj1ENlNND9xFta7rOqpJ9KJqwwDZhmvIU1uvqzXqIbL5aqM7AdoBuk2ZoV5EbRsM23Y9WbX9+lqjHiJHR22FCdDOvEabVu6dpy4Ndl241i5cY6vUQ+Toqc0wcWojVGapH3RmqyvvTVeus5XqIXJ01YZwUlF1CSpHWV0bjLt2va1UD5FeQDfcia8eKutXVwfgrl53a9VDpJevLrkTX331Vb3ahIF3E15DK/X/A7UO12VjUjBcAAAAAElFTkSuQmCC"/> +</defs> +</svg> diff --git a/browser/branding/tb-nightly/content/about-logo@2x.png b/browser/branding/tb-nightly/content/about-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1df472e725ad1a16fc3a208ddef5c8a65d69ac09 Binary files /dev/null and b/browser/branding/tb-nightly/content/about-logo@2x.png differ diff --git a/browser/branding/tb-nightly/content/about-wordmark.svg b/browser/branding/tb-nightly/content/about-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..6fd0edf1bb01ca0250dd5e5d7105485aa8995c75 --- /dev/null +++ b/browser/branding/tb-nightly/content/about-wordmark.svg @@ -0,0 +1,24 @@ +<!-- tor-browser#42319: Make sure all the about wordmark SVGs (release, alpha, + nightly) have the same size. This will likely add some padding to some + channels, so the background-position for RTL languages should be ajusted + accordingly in the respective aboutDialog.css. --> +<svg width="416" height="45" viewBox="0 0 416 45" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M303.369 4.05329C303.845 4.53015 304.402 4.76858 305.038 4.76858C305.705 4.76858 306.262 4.53015 306.707 4.05329C307.183 3.57644 307.422 3.0201 307.422 2.38429C307.422 1.71669 307.183 1.16035 306.707 0.715287C306.262 0.238429 305.705 0 305.038 0C304.402 0 303.845 0.238429 303.369 0.715287C302.892 1.16035 302.653 1.71669 302.653 2.38429C302.653 3.0201 302.892 3.57644 303.369 4.05329Z" fill="white"/> +<path d="M340.961 34.1431V0.143055H344.776V13.7676C345.425 12.6907 346.236 11.821 347.208 11.1585C348.607 10.2048 350.292 9.72791 352.263 9.72791C355.124 9.72791 357.397 10.618 359.082 12.3983C360.767 14.1786 361.593 16.8808 361.561 20.5049V34.1431H357.746V21.9355C357.746 19.583 357.46 17.7868 356.888 16.547C356.348 15.3072 355.601 14.4647 354.647 14.0196C353.693 13.5428 352.612 13.3043 351.404 13.3043C349.306 13.3043 347.669 14.0514 346.493 15.5456C345.348 17.0079 344.776 19.0902 344.776 21.7924V34.1431H340.961Z" fill="white"/> +<path d="M303.082 34.1431L303.178 10.3001H306.993L306.897 34.1431H303.082Z" fill="white"/> +<path d="M292.442 34.1431L272.509 7.19473V34.1431H268.456V0.762972H272.557L292.442 27.6056V0.762972H296.495V34.1431H292.442Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M322.988 44.2525C321.462 44.2525 320.063 44.0935 318.791 43.7756C317.551 43.4895 316.486 43.1557 315.596 42.7742C314.738 42.4245 314.118 42.1225 313.737 41.8682L315.167 38.7686C315.58 38.9911 316.169 39.2613 316.931 39.5792C317.694 39.9289 318.585 40.215 319.602 40.4376C320.651 40.6919 321.764 40.8191 322.94 40.8191C324.466 40.8191 325.833 40.5012 327.041 39.8654C328.281 39.2613 329.234 38.2917 329.902 36.9565C330.601 35.6531 330.951 33.9682 330.951 31.9018V29.364C330.196 30.6211 329.242 31.6419 328.09 32.4264C326.596 33.4437 324.847 33.9523 322.845 33.9523C320.715 33.9523 318.839 33.4437 317.218 32.4264C315.596 31.4091 314.325 29.9944 313.403 28.1823C312.513 26.3385 312.068 24.2403 312.068 21.8878C312.068 19.4717 312.513 17.3576 313.403 15.5456C314.325 13.7017 315.596 12.2712 317.218 11.2539C318.839 10.2366 320.715 9.72791 322.845 9.72791C324.847 9.72791 326.596 10.2366 328.09 11.2539C329.242 12.0383 330.196 13.0686 330.951 14.3446V10.3001H334.766V31.8541C334.766 34.5881 334.257 36.877 333.24 38.7209C332.223 40.5647 330.824 41.9476 329.044 42.8696C327.263 43.7915 325.245 44.2525 322.988 44.2525ZM323.751 30.662C325.149 30.662 326.389 30.2805 327.47 29.5175C328.551 28.7546 329.393 27.7214 329.997 26.418C330.601 25.0827 330.903 23.5409 330.903 21.7924C330.903 20.1075 330.586 18.6134 329.95 17.31C329.346 15.9748 328.503 14.9416 327.422 14.2104C326.373 13.4474 325.133 13.0659 323.703 13.0659C322.209 13.0659 320.874 13.4474 319.697 14.2104C318.553 14.9416 317.647 15.9748 316.979 17.31C316.343 18.6134 316.025 20.1075 316.025 21.7924C316.025 23.5409 316.359 25.0827 317.027 26.418C317.694 27.7214 318.6 28.7546 319.745 29.5175C320.921 30.2805 322.256 30.662 323.751 30.662Z" fill="white"/> +<path d="M384.62 0.762972V34.1431H388.435V0.762972H384.62Z" fill="white"/> +<path d="M394.668 43.871C395.463 44.1253 396.162 44.2525 396.767 44.2525C398.197 44.2525 399.373 43.9822 400.295 43.4418C401.217 42.9014 401.996 42.1225 402.632 41.1052C403.299 40.0879 403.935 38.8798 404.539 37.4811L415.984 10.3001H411.883L403.855 29.6545L395.765 10.3001H391.712L401.997 34.1076L400.343 38.0533C399.961 38.9116 399.485 39.5633 398.912 40.0084C398.372 40.4853 397.673 40.7237 396.814 40.7237C396.496 40.7237 396.051 40.6442 395.479 40.4853C394.939 40.3263 394.303 40.0879 393.572 39.77L392.141 42.9649C393.031 43.3464 393.874 43.6484 394.668 43.871Z" fill="white"/> +<path d="M373.328 10.3292H379.664V13.7155H373.317V27.4477C373.317 28.6557 373.635 29.5936 374.271 30.2612C374.938 30.897 375.86 31.2149 377.036 31.2149C377.418 31.2149 377.783 31.1672 378.133 31.0718C378.515 30.9447 379.007 30.6585 379.611 30.2135L381.09 33.3131C380.263 33.8535 379.516 34.2191 378.848 34.4098C378.181 34.6324 377.497 34.7436 376.798 34.7436C374.477 34.7436 372.681 34.1396 371.409 32.9316C370.138 31.7235 369.502 30.0227 369.502 27.8292V13.7155H364.064V10.3292H364.678C367.359 10.3292 369.528 8.14673 369.511 5.46568L369.502 3.93667V2.88952H373.328V10.3292Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M99.1943 16.8102C100.019 16.2473 100.72 15.6031 101.297 14.8777C102.41 13.4789 102.966 11.9052 102.966 10.1568C102.966 8.09037 102.489 6.35779 101.536 4.959C100.614 3.56022 99.2945 2.51113 97.5778 1.81174C95.8929 1.08055 93.906 0.714963 91.6171 0.714963L85.0829 0.777784V0.762649H79.1698V34.1427H93.143C95.3684 34.1427 97.2917 33.7771 98.913 33.046C100.566 32.3148 101.838 31.2498 102.728 29.851C103.65 28.4204 104.111 26.7037 104.111 24.7009C104.111 22.412 103.475 20.5523 102.203 19.1217C101.413 18.1899 100.41 17.4194 99.1943 16.8102ZM92.5708 28.7542H85.0829V19.6306L86.3902 19.5509H91.9509C93.8265 19.5191 95.2889 19.9324 96.338 20.7907C97.4189 21.6173 97.9593 22.7617 97.9593 24.2241C97.9593 25.6229 97.4824 26.7355 96.5287 27.5621C95.575 28.3569 94.2557 28.7542 92.5708 28.7542ZM85.0829 5.6266H91.331C93.0477 5.59481 94.3829 5.9763 95.3366 6.77107C96.3221 7.56583 96.8148 8.6785 96.8148 10.1091C96.8148 11.5079 96.3698 12.6046 95.4797 13.3994C94.6213 14.1624 93.4451 14.5439 91.9509 14.5439H85.0829V5.6266Z" fill="white"/> +<path d="M11.3982 6.2942V34.1427H17.4066V6.2942H28.8525V0.762649H0V6.2942H11.3982Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M29.0711 33.1413C30.9468 34.1904 33.0926 34.715 35.5087 34.715C37.893 34.715 40.0071 34.1904 41.8509 33.1413C43.6948 32.0604 45.1412 30.5822 46.1903 28.7065C47.2394 26.8309 47.764 24.6691 47.764 22.2213C47.764 19.7734 47.2394 17.6116 46.1903 15.736C45.1412 13.8604 43.6789 12.398 41.8032 11.3489C39.9594 10.268 37.8294 9.72759 35.4133 9.72759C33.029 9.72759 30.8991 10.268 29.0234 11.3489C27.1796 12.398 25.7331 13.8604 24.684 15.736C23.6349 17.6116 23.1104 19.7734 23.1104 22.2213C23.1104 24.6691 23.6349 26.8309 24.684 28.7065C25.7649 30.5822 27.2273 32.0604 29.0711 33.1413ZM38.799 28.4681C37.8453 29.0721 36.7485 29.3741 35.5087 29.3741C34.2689 29.3741 33.1562 29.0721 32.1707 28.4681C31.1852 27.8323 30.4063 26.9899 29.8341 25.9408C29.2937 24.8599 29.0234 23.6201 29.0234 22.2213C29.0234 20.8225 29.2937 19.5827 29.8341 18.5018C30.4063 17.4209 31.1693 16.5784 32.123 15.9744C33.0767 15.3704 34.1735 15.0684 35.4133 15.0684C36.6532 15.0684 37.7499 15.3863 38.7037 16.0221C39.6892 16.6261 40.4521 17.4686 40.9926 18.5495C41.5648 19.5986 41.8509 20.8225 41.8509 22.2213C41.8509 23.6201 41.5807 24.8599 41.0403 25.9408C40.4998 26.9899 39.7527 27.8323 38.799 28.4681Z" fill="white"/> +<path d="M57.4468 34.1427V21.506C57.4468 20.139 57.8442 19.0422 58.6389 18.2157C59.4655 17.3573 60.5146 16.7374 61.7862 16.3559C63.0896 15.9744 64.4566 15.7837 65.8872 15.7837V10.2044C64.1705 10.2044 62.5333 10.6177 60.9755 11.4443C59.5835 12.1829 58.4073 13.2643 57.4468 14.6884V10.2998H51.6768V34.1427H57.4468Z" fill="white"/> +<path d="M114.044 34.1427V21.506C114.044 20.139 114.441 19.0422 115.236 18.2157C116.063 17.3573 117.112 16.7374 118.383 16.3559C119.687 15.9744 121.054 15.7837 122.484 15.7837V10.2044C120.768 10.2044 119.13 10.6177 117.573 11.4443C116.181 12.1829 115.004 13.2643 114.044 14.6884V10.2998H108.274V34.1427H114.044Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M130.119 33.1413C131.994 34.1904 134.14 34.715 136.556 34.715C138.94 34.715 141.055 34.1904 142.898 33.1413C144.742 32.0604 146.189 30.5822 147.238 28.7065C148.287 26.8309 148.811 24.6691 148.811 22.2213C148.811 19.7734 148.287 17.6116 147.238 15.736C146.189 13.8604 144.726 12.398 142.851 11.3489C141.007 10.268 138.877 9.72759 136.461 9.72759C134.076 9.72759 131.947 10.268 130.071 11.3489C128.227 12.398 126.781 13.8604 125.731 15.736C124.682 17.6116 124.158 19.7734 124.158 22.2213C124.158 24.6691 124.682 26.8309 125.731 28.7065C126.812 30.5822 128.275 32.0604 130.119 33.1413ZM139.846 28.4681C138.893 29.0721 137.796 29.3741 136.556 29.3741C135.316 29.3741 134.204 29.0721 133.218 28.4681C132.233 27.8323 131.454 26.9899 130.882 25.9408C130.341 24.8599 130.071 23.6201 130.071 22.2213C130.071 20.8225 130.341 19.5827 130.882 18.5018C131.454 17.4209 132.217 16.5784 133.17 15.9744C134.124 15.3704 135.221 15.0684 136.461 15.0684C137.701 15.0684 138.797 15.3863 139.751 16.0221C140.737 16.6261 141.5 17.4686 142.04 18.5495C142.612 19.5986 142.898 20.8225 142.898 22.2213C142.898 23.6201 142.628 24.8599 142.088 25.9408C141.547 26.9899 140.8 27.8323 139.846 28.4681Z" fill="white"/> +<path d="M176.559 26.1951L181.836 10.2998H187.749L179.643 34.1427H173.92L168.579 17.3477L163.239 34.1427H157.469L149.362 10.2998H155.275L160.481 26.4658L165.718 10.2998H171.441L176.559 26.1951Z" fill="white"/> +<path d="M194.088 33.9997C195.423 34.4765 196.869 34.715 198.427 34.715C200.239 34.715 201.845 34.4288 203.243 33.8566C204.674 33.2526 205.803 32.4101 206.629 31.3293C207.456 30.2166 207.869 28.945 207.869 27.5144C207.869 26.5289 207.646 25.5275 207.201 24.5102C206.756 23.4929 206.057 22.571 205.103 21.7444C204.149 20.9179 202.894 20.3138 201.336 19.9324L198.379 19.1694C197.426 18.9468 196.71 18.6766 196.234 18.3587C195.757 18.0408 195.518 17.6434 195.518 17.1666C195.518 16.4354 195.773 15.8632 196.281 15.4499C196.822 15.0366 197.585 14.83 198.57 14.83C199.524 14.83 200.43 15.0366 201.288 15.4499C202.178 15.8632 202.751 16.4354 203.005 17.1666L207.869 14.973C207.487 13.9239 206.852 13.0179 205.962 12.2549C205.071 11.4602 203.991 10.8403 202.719 10.3952C201.447 9.95012 200.08 9.72759 198.618 9.72759C195.725 9.72759 193.5 10.3952 191.942 11.7304C190.384 13.0338 189.605 14.8935 189.605 17.3096C189.605 18.9627 190.257 20.441 191.56 21.7444C192.864 23.016 194.644 23.9539 196.901 24.5579L199.095 25.1301C200.017 25.3526 200.732 25.6388 201.241 25.9885C201.781 26.3382 202.051 26.8309 202.051 27.4667C202.051 28.1343 201.718 28.6589 201.05 29.0403C200.382 29.39 199.492 29.5649 198.379 29.5649C197.235 29.5649 196.218 29.2788 195.328 28.7065C194.469 28.1025 193.802 27.4031 193.325 26.6084L188.318 28.8496C188.858 30.0576 189.621 31.1067 190.607 31.9969C191.592 32.8552 192.753 33.5228 194.088 33.9997Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M222.071 34.715C219.718 34.715 217.636 34.1904 215.824 33.1413C214.044 32.0604 212.629 30.5822 211.58 28.7065C210.563 26.8309 210.054 24.6691 210.054 22.2213C210.054 19.7734 210.578 17.6116 211.628 15.736C212.677 13.8604 214.123 12.398 215.967 11.3489C217.811 10.268 219.925 9.72759 222.309 9.72759C224.407 9.72759 226.331 10.2839 228.079 11.3966C229.828 12.4775 231.211 14.067 232.228 16.1652C233.277 18.2316 233.801 20.743 233.801 23.6995H216.053C216.181 24.6481 216.455 25.4746 216.873 26.1792C217.477 27.1965 218.288 27.9754 219.305 28.5158C220.322 29.0562 221.435 29.3265 222.643 29.3265C223.978 29.3265 225.059 29.0403 225.886 28.4681C226.744 27.8641 227.412 27.1011 227.888 26.1792L233.277 28.3251C232.641 29.6603 231.783 30.8047 230.702 31.7584C229.653 32.7122 228.413 33.4433 226.982 33.952C225.552 34.4606 223.915 34.715 222.071 34.715ZM227.269 18.6448C227.326 18.7978 227.38 18.9568 227.43 19.1217H216.358C216.45 18.7992 216.558 18.4972 216.682 18.2157C217.159 17.103 217.859 16.2764 218.78 15.736C219.702 15.1638 220.815 14.8777 222.118 14.8777C223.326 14.8777 224.36 15.1797 225.218 15.7837C226.108 16.3877 226.792 17.3414 227.269 18.6448Z" fill="white"/> +<path d="M242.993 21.506V34.1427H237.223V10.2998H242.993V14.6884C243.954 13.2643 245.13 12.1829 246.522 11.4443C248.08 10.6177 249.717 10.2044 251.434 10.2044V15.7837C250.003 15.7837 248.636 15.9744 247.333 16.3559C246.061 16.7374 245.012 17.3573 244.185 18.2157C243.391 19.0422 242.993 20.139 242.993 21.506Z" fill="white"/> +</svg> diff --git a/browser/branding/tb-nightly/content/about.png b/browser/branding/tb-nightly/content/about.png new file mode 100644 index 0000000000000000000000000000000000000000..29cecfc95b61d643baf635c93be729e70f3011e0 Binary files /dev/null and b/browser/branding/tb-nightly/content/about.png differ diff --git a/browser/branding/tb-nightly/content/aboutDialog.css b/browser/branding/tb-nightly/content/aboutDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..2dcdd22cfa88b3781628167124431ec149ee25f6 --- /dev/null +++ b/browser/branding/tb-nightly/content/aboutDialog.css @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#aboutDialogContainer { + background-color: #20123a; + color: #fff; + color-scheme: dark; +} + +#clientBox { + padding: 10px 0 15px; +} + +#leftBox { + background-image: url("chrome://branding/content/about-logo.png"); + background-repeat: no-repeat; + background-size: 192px auto; + background-position: center 20%; + /* min-width and min-height create room for the logo */ + min-width: 210px; + min-height: 210px; + margin-top: 20px; + margin-inline-start: 30px; +} + +@media (min-resolution: 2dppx) { + #leftBox { + background-image: url("chrome://branding/content/about-logo@2x.png"); + } +} + +.text-link { + color: #fff !important; + text-decoration: underline; +} + +#rightBox { + margin-inline: 30px; + padding-top: 64px; +} + +#bottomBox { + background-color: hsla(235, 43%, 10%, .5); + padding: 15px 10px 15px; +} diff --git a/browser/branding/tb-nightly/content/firefox-wordmark.svg b/browser/branding/tb-nightly/content/firefox-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..65270a3cd9a966cd350ec717758c352661ecca4e --- /dev/null +++ b/browser/branding/tb-nightly/content/firefox-wordmark.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="172" height="42"><path fill="context-fill #20123a" d="M.19 2.82h25.72v7H7.57v9.43h18.34v6.9H7.57v15.14H.19zM34.65.13a4.14 4.14 0 0 1 4.27 4.33 4.12 4.12 0 0 1-4.32 4.32 4.09 4.09 0 0 1-4.27-4.22A4.27 4.27 0 0 1 34.65.13zM31 12.83h7.27v28.46H31zm28.35 7.91a5.89 5.89 0 0 0-3.53-1.27c-3 0-4.64 1.9-4.64 6.06v15.76H44V12.83h6.9v4.11a6.79 6.79 0 0 1 6.8-4.37A8.69 8.69 0 0 1 62.53 14zm3 6.48c0-8.17 6.06-15 14.65-15s14.59 6.06 14.59 14.49v3H69.48c.79 3.58 3.58 6 7.85 6a7.62 7.62 0 0 0 7.06-4.21l6.06 3.63c-3 4.43-7.27 6.75-13.33 6.75-9.22-.01-14.75-6.18-14.75-14.66zM69.59 24h15c-.79-3.63-3.74-5.63-7.59-5.63A7.31 7.31 0 0 0 69.59 24zM93.4 12.83h5.11v-1.42c0-7.75 3.27-11 10.44-11h2.53v6.31h-2.06c-3.37 0-4.11 1.16-4.11 4.69v1.42h6.17v6.54h-6v21.92h-7V19.37H93.4zm19.45 14.23a14.56 14.56 0 0 1 14.85-14.81 14.81 14.81 0 1 1 0 29.62c-8.85 0-14.85-6.49-14.85-14.81zm22.65 0a7.8 7.8 0 1 0-15.59 0 7.8 7.8 0 1 0 15.59 0zm16.86-.32l-10.27-13.91h8.53l6.06 8.75 6.22-8.75h8.38l-10.43 13.86 11 14.6h-8.49L156.53 32l-6.59 9.28h-8.48z"/></svg> \ No newline at end of file diff --git a/browser/branding/tb-nightly/content/jar.mn b/browser/branding/tb-nightly/content/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..11e3e15350dd36f8564bf5fd66f66630a885bf80 --- /dev/null +++ b/browser/branding/tb-nightly/content/jar.mn @@ -0,0 +1,19 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +browser.jar: +% content branding %content/branding/ contentaccessible=yes + content/branding/about.png + content/branding/about-logo.png + content/branding/about-logo.svg + content/branding/about-logo@2x.png + content/branding/about-wordmark.svg + content/branding/firefox-wordmark.svg + content/branding/icon16.png (../default16.png) + content/branding/icon32.png (../default32.png) + content/branding/icon48.png (../default48.png) + content/branding/icon64.png (../default64.png) + content/branding/icon128.png (../default128.png) + content/branding/icon256.png (../default256.png) + content/branding/aboutDialog.css diff --git a/browser/branding/tb-nightly/content/moz.build b/browser/branding/tb-nightly/content/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-nightly/content/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-nightly/default128.png b/browser/branding/tb-nightly/default128.png new file mode 100644 index 0000000000000000000000000000000000000000..bf25fbcfaa46ea29334e02982befe873eacfda21 Binary files /dev/null and b/browser/branding/tb-nightly/default128.png differ diff --git a/browser/branding/tb-nightly/default16.png b/browser/branding/tb-nightly/default16.png new file mode 100644 index 0000000000000000000000000000000000000000..3819aaf6eef379f645a6ae4c603dd9038306a7f0 Binary files /dev/null and b/browser/branding/tb-nightly/default16.png differ diff --git a/browser/branding/tb-nightly/default22.png b/browser/branding/tb-nightly/default22.png new file mode 100644 index 0000000000000000000000000000000000000000..00ae0950760666ce4d2dba6bd0bbbe700dedea3b Binary files /dev/null and b/browser/branding/tb-nightly/default22.png differ diff --git a/browser/branding/tb-nightly/default24.png b/browser/branding/tb-nightly/default24.png new file mode 100644 index 0000000000000000000000000000000000000000..f4e6dd45d08869afce3796e123a5643b0d901304 Binary files /dev/null and b/browser/branding/tb-nightly/default24.png differ diff --git a/browser/branding/tb-nightly/default256.png b/browser/branding/tb-nightly/default256.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c1a5f530aefc1472888c7e49fbcf6b13a4275e Binary files /dev/null and b/browser/branding/tb-nightly/default256.png differ diff --git a/browser/branding/tb-nightly/default32.png b/browser/branding/tb-nightly/default32.png new file mode 100644 index 0000000000000000000000000000000000000000..17ff1c3c7b9a39d7831da52afd6abc0e78cd303b Binary files /dev/null and b/browser/branding/tb-nightly/default32.png differ diff --git a/browser/branding/tb-nightly/default48.png b/browser/branding/tb-nightly/default48.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf5ce3c5c9bbc198ad88266d149664e9e42dbd4 Binary files /dev/null and b/browser/branding/tb-nightly/default48.png differ diff --git a/browser/branding/tb-nightly/default64.png b/browser/branding/tb-nightly/default64.png new file mode 100644 index 0000000000000000000000000000000000000000..25ae65fb0d6176760933ad2d013d67758233c97c Binary files /dev/null and b/browser/branding/tb-nightly/default64.png differ diff --git a/browser/branding/tb-nightly/document.icns b/browser/branding/tb-nightly/document.icns new file mode 100644 index 0000000000000000000000000000000000000000..f447d8c5c3c7be896d0d599d09b3ec6df540b626 Binary files /dev/null and b/browser/branding/tb-nightly/document.icns differ diff --git a/browser/branding/tb-nightly/document.ico b/browser/branding/tb-nightly/document.ico new file mode 100644 index 0000000000000000000000000000000000000000..cebf189247e9c75530294e434429bc29fb91299e Binary files /dev/null and b/browser/branding/tb-nightly/document.ico differ diff --git a/browser/branding/tb-nightly/document_pdf.ico b/browser/branding/tb-nightly/document_pdf.ico new file mode 100644 index 0000000000000000000000000000000000000000..dc74ba85f69daa19d5806c4a5f7491310041c887 Binary files /dev/null and b/browser/branding/tb-nightly/document_pdf.ico differ diff --git a/browser/branding/tb-nightly/firefox.VisualElementsManifest.xml b/browser/branding/tb-nightly/firefox.VisualElementsManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e68b02962b3857626ce94ef94f101530be8315df --- /dev/null +++ b/browser/branding/tb-nightly/firefox.VisualElementsManifest.xml @@ -0,0 +1,12 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> + <VisualElements + ShowNameOnSquare150x150Logo='on' + Square150x150Logo='browser\VisualElements\VisualElements_150.png' + Square70x70Logo='browser\VisualElements\VisualElements_70.png' + ForegroundText='light' + BackgroundColor='#191339'/> +</Application> diff --git a/browser/branding/tb-nightly/firefox.icns b/browser/branding/tb-nightly/firefox.icns new file mode 100644 index 0000000000000000000000000000000000000000..a711ba509a6b238ffd54d555f66066fa9a21abf8 Binary files /dev/null and b/browser/branding/tb-nightly/firefox.icns differ diff --git a/browser/branding/tb-nightly/firefox.ico b/browser/branding/tb-nightly/firefox.ico new file mode 100644 index 0000000000000000000000000000000000000000..1d0f345dc351b8e9d52cea5c16ead5250e29eeb0 Binary files /dev/null and b/browser/branding/tb-nightly/firefox.ico differ diff --git a/browser/branding/tb-nightly/locales/en-US/brand.ftl b/browser/branding/tb-nightly/locales/en-US/brand.ftl new file mode 100644 index 0000000000000000000000000000000000000000..a8604d3aaedb5bcba4bc62f8a7c7e39cc4279dac --- /dev/null +++ b/browser/branding/tb-nightly/locales/en-US/brand.ftl @@ -0,0 +1,14 @@ +# For Tor Browser, we use a new file (different than the brand.ftl file +# that is used by Firefox) to avoid picking up the -brand-short-name values +# that Mozilla includes in the Firefox language packs. + +-brand-shorter-name = Tor Browser +-brand-short-name = Tor Browser +-brand-full-name = Tor Browser +# This brand name can be used in messages where the product name needs to +# remain unchanged across different versions (Nightly, Beta, etc.). +-brand-product-name = Tor Browser +-vendor-short-name = Tor Project +# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized). +# "The Tor Project, Inc." is an organisation name. +trademarkInfo = “Tor” and the Tor logo are registered trademarks of The Tor Project, Inc. diff --git a/browser/branding/tb-nightly/locales/en-US/brand.properties b/browser/branding/tb-nightly/locales/en-US/brand.properties new file mode 100644 index 0000000000000000000000000000000000000000..59d1fe05cf7ff18af56f3b857f26907c44675a6f --- /dev/null +++ b/browser/branding/tb-nightly/locales/en-US/brand.properties @@ -0,0 +1,8 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +brandShorterName=Tor Browser +brandShortName=Tor Browser +brandFullName=Tor Browser diff --git a/browser/branding/tb-nightly/locales/jar.mn b/browser/branding/tb-nightly/locales/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..2250233dd6245b892292b97d5a32393557b5a6fe --- /dev/null +++ b/browser/branding/tb-nightly/locales/jar.mn @@ -0,0 +1,11 @@ +#filter substitution +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[localization] @AB_CD@.jar: + branding (%*.ftl) + +@AB_CD@.jar: +% locale branding @AB_CD@ %locale/branding/ + locale/branding/brand.properties (%brand.properties) diff --git a/browser/branding/tb-nightly/locales/moz.build b/browser/branding/tb-nightly/locales/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-nightly/locales/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-nightly/moz.build b/browser/branding/tb-nightly/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..dd081ac44496d19d2e8d73a0a10f3d1ad81266b6 --- /dev/null +++ b/browser/branding/tb-nightly/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ["content", "locales"] + +DIST_SUBDIR = "browser" +export("DIST_SUBDIR") + +include("../branding-common.mozbuild") +FirefoxBranding() diff --git a/browser/branding/tb-nightly/newtab.ico b/browser/branding/tb-nightly/newtab.ico new file mode 100644 index 0000000000000000000000000000000000000000..a9b37c08c6e18af5c8b67745c445bad21fd4e791 Binary files /dev/null and b/browser/branding/tb-nightly/newtab.ico differ diff --git a/browser/branding/tb-nightly/newwindow.ico b/browser/branding/tb-nightly/newwindow.ico new file mode 100644 index 0000000000000000000000000000000000000000..55372077102c4ba18ff1b858b78a2e4c735e6988 Binary files /dev/null and b/browser/branding/tb-nightly/newwindow.ico differ diff --git a/browser/branding/tb-nightly/pbmode.ico b/browser/branding/tb-nightly/pbmode.ico new file mode 100644 index 0000000000000000000000000000000000000000..47677c13fba6881d30eef3a16b46b70f3deb5bc9 Binary files /dev/null and b/browser/branding/tb-nightly/pbmode.ico differ diff --git a/browser/branding/tb-nightly/pref/firefox-branding.js b/browser/branding/tb-nightly/pref/firefox-branding.js new file mode 100644 index 0000000000000000000000000000000000000000..97584009f7c836304b1788816626b1d8b3c86303 --- /dev/null +++ b/browser/branding/tb-nightly/pref/firefox-branding.js @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file contains branding-specific prefs. + +// Set a generic, default URL that will be opened in a tab after an update. +// Typically, this will not be used; instead, the <update> element within +// each update manifest should contain attributes similar to: +// actions="showURL" +// openURL="https://blog.torproject.org/tor-browser-55a2-released" +pref("startup.homepage_override_url", "https://blog.torproject.org/category/applications"); +pref("startup.homepage_welcome_url", "about:welcome"); +pref("startup.homepage_welcome_url.additional", ""); +// The time interval between checks for a new version (in seconds) +pref("app.update.interval", 14400); // 4 hours +// Give the user x seconds to react before showing the big UI. default=12 hours +pref("app.update.promptWaitTime", 43200); +// URL user can browse to manually if for some reason all update installation +// attempts fail. +pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/nightly/?reason=manual-update"); +// A default value for the "More information about this update" link +// supplied in the "An update is available" page of the update wizard. +pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/nightly/notes/"); + +pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew"); +pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog"); + +// The number of days a binary is permitted to be old +// without checking for an update. This assumes that +// app.update.checkInstallTime is true. +pref("app.update.checkInstallTime.days", 2); + +// Give the user x seconds to reboot before showing a badge on the hamburger +// button. default=immediately +pref("app.update.badgeWaitTime", 0); + +// Number of usages of the web console. +// If this is less than 5, then pasting code into the web console is disabled +pref("devtools.selfxss.count", 5); diff --git a/browser/branding/tb-release/VisualElements_150.png b/browser/branding/tb-release/VisualElements_150.png new file mode 100644 index 0000000000000000000000000000000000000000..dc1e1358ee98e640ee8988d728c351bff02bfd01 Binary files /dev/null and b/browser/branding/tb-release/VisualElements_150.png differ diff --git a/browser/branding/tb-release/VisualElements_70.png b/browser/branding/tb-release/VisualElements_70.png new file mode 100644 index 0000000000000000000000000000000000000000..8237c4e8ef05787bb44024870bf40fc3ee96cf74 Binary files /dev/null and b/browser/branding/tb-release/VisualElements_70.png differ diff --git a/browser/branding/tb-release/configure.sh b/browser/branding/tb-release/configure.sh new file mode 100644 index 0000000000000000000000000000000000000000..243091484f758f1ea979726096cdd2ee3806950c --- /dev/null +++ b/browser/branding/tb-release/configure.sh @@ -0,0 +1,5 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOZ_APP_DISPLAYNAME="Tor Browser" diff --git a/browser/branding/tb-release/content/about-logo.png b/browser/branding/tb-release/content/about-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b37e61c59fde65116e678d0ef45293ff0c87863c Binary files /dev/null and b/browser/branding/tb-release/content/about-logo.png differ diff --git a/browser/branding/tb-release/content/about-logo.svg b/browser/branding/tb-release/content/about-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc36fd18cbb9547bf51db82ff28961425090e423 --- /dev/null +++ b/browser/branding/tb-release/content/about-logo.svg @@ -0,0 +1,20 @@ +<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M24 46.5C36.4264 46.5 46.5 36.4264 46.5 24C46.5 11.5736 36.4264 1.5 24 1.5C11.5736 1.5 1.5 11.5736 1.5 24C1.5 36.4264 11.5736 46.5 24 46.5Z" fill="url(#paint0_linear_1920_3864)"/> +<path d="M24 5.54297C34.1935 5.54297 42.457 13.8065 42.457 24C42.457 34.1935 34.1935 42.457 24 42.457V39.6445C32.6402 39.6445 39.6445 32.6402 39.6445 24C39.6445 15.3598 32.6402 8.35547 24 8.35547V5.54297Z" fill="#EACCFF"/> +<path d="M24 12.4424C30.3831 12.4424 35.5576 17.6169 35.5576 24C35.5576 30.3831 30.3831 35.5576 24 35.5576V32.7451C28.8298 32.7451 32.7451 28.8298 32.7451 24C32.7451 19.1702 28.8298 15.2549 24 15.2549V12.4424Z" fill="#EACCFF"/> +<path d="M24 19.21C26.6455 19.21 28.79 21.3545 28.79 24C28.79 26.6455 26.6455 28.79 24 28.79V19.21Z" fill="#EACCFF"/> +<path d="M24 1.5C12.7386 1.5 3.60938 10.6685 3.60938 21.9785C3.60938 33.2885 12.7386 42.457 24 42.457V1.5Z" fill="#BE6EF7" fill-opacity="0.4"/> +<path d="M24 1.5C32.2194 1.5 39.4094 5.90728 43.3357 12.4875V21.9785C43.3892 33.2884 34.6788 42.457 24 42.457L24 1.5Z" fill="url(#paint1_linear_1920_3864)"/> +<defs> +<linearGradient id="paint0_linear_1920_3864" x1="24" y1="46.5" x2="24" y2="1.5" gradientUnits="userSpaceOnUse"> +<stop offset="0.333333" stop-color="#730BDA"/> +<stop offset="1" stop-color="#B83DF5"/> +</linearGradient> +<linearGradient id="paint1_linear_1920_3864" x1="24" y1="21.9785" x2="43.3357" y2="21.9785" gradientUnits="userSpaceOnUse"> +<stop stop-color="#550080" stop-opacity="0.4"/> +<stop offset="0.166667" stop-color="#550080" stop-opacity="0.4"/> +<stop offset="0.333333" stop-color="#550080" stop-opacity="0.2"/> +<stop offset="0.5" stop-color="#550080" stop-opacity="0"/> +</linearGradient> +</defs> +</svg> diff --git a/browser/branding/tb-release/content/about-logo@2x.png b/browser/branding/tb-release/content/about-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ca067c1af0499b6346df662e9153345788acdbf Binary files /dev/null and b/browser/branding/tb-release/content/about-logo@2x.png differ diff --git a/browser/branding/tb-release/content/about-wordmark.svg b/browser/branding/tb-release/content/about-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..a75fad4b9b2e35d1844e2d0ae11929e815cac24e --- /dev/null +++ b/browser/branding/tb-release/content/about-wordmark.svg @@ -0,0 +1,16 @@ +<!-- tor-browser#42319: Make sure all the about wordmark SVGs (release, alpha, + nightly) have the same size. This will likely add some padding to some + channels, so the background-position for RTL languages should be ajusted + accordingly in the respective aboutDialog.css. --> +<svg width="416" height="45" viewBox="0 0 416 45" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M11.3982 33.4278V2.81346H17.4066V33.4278H11.3982ZM0 5.57924V0.0476854H28.8525V5.57924H0Z" fill="white"/> +<path d="M35.5087 34C33.0926 34 30.9468 33.4755 29.0711 32.4264C27.2273 31.3455 25.7649 29.8672 24.684 27.9916C23.6349 26.1159 23.1104 23.9542 23.1104 21.5063C23.1104 19.0584 23.6349 16.8967 24.684 15.021C25.7331 13.1454 27.1796 11.683 29.0234 10.6339C30.8991 9.55306 33.029 9.01262 35.4133 9.01262C37.8294 9.01262 39.9594 9.55306 41.8032 10.6339C43.6789 11.683 45.1412 13.1454 46.1903 15.021C47.2394 16.8967 47.764 19.0584 47.764 21.5063C47.764 23.9542 47.2394 26.1159 46.1903 27.9916C45.1412 29.8672 43.6948 31.3455 41.8509 32.4264C40.0071 33.4755 37.893 34 35.5087 34ZM35.5087 28.6592C36.7485 28.6592 37.8453 28.3572 38.799 27.7532C39.7527 27.1173 40.4998 26.2749 41.0403 25.2258C41.5807 24.1449 41.8509 22.9051 41.8509 21.5063C41.8509 20.1075 41.5648 18.8836 40.9926 17.8345C40.4521 16.7536 39.6892 15.9112 38.7037 15.3072C37.7499 14.6713 36.6532 14.3534 35.4133 14.3534C34.1735 14.3534 33.0767 14.6554 32.123 15.2595C31.1693 15.8635 30.4063 16.7059 29.8341 17.7868C29.2937 18.8677 29.0234 20.1075 29.0234 21.5063C29.0234 22.9051 29.2937 24.1449 29.8341 25.2258C30.4063 26.2749 31.1852 27.1173 32.1707 27.7532C33.1562 28.3572 34.2689 28.6592 35.5087 28.6592Z" fill="white"/> +<path d="M55.6347 20.8387C55.6347 18.2637 56.1275 16.1496 57.113 14.4965C58.1303 12.8116 59.4178 11.5559 60.9755 10.7293C62.5333 9.90276 64.1705 9.48948 65.8872 9.48948V15.0687C64.4566 15.0687 63.0896 15.2595 61.7862 15.641C60.5146 16.0224 59.4655 16.6424 58.6389 17.5007C57.8442 18.3273 57.4468 19.424 57.4468 20.791L55.6347 20.8387ZM51.6768 33.4278V9.58485H57.4468V33.4278H51.6768Z" fill="white"/> +<path d="M81.8879 33.4278V28.0393H92.5708C94.2557 28.0393 95.575 27.6419 96.5287 26.8471C97.4825 26.0206 97.9593 24.9079 97.9593 23.5091C97.9593 22.0467 97.4189 20.9023 96.338 20.0757C95.2889 19.2174 93.8265 18.8041 91.9509 18.8359H81.8879V14.0673L88.9467 14.1627C91.9986 14.1627 94.6531 14.5124 96.9102 15.2118C99.1991 15.8794 100.964 16.9444 102.203 18.4067C103.475 19.8373 104.111 21.6971 104.111 23.986C104.111 25.9888 103.65 27.7055 102.728 29.136C101.838 30.5348 100.566 31.5998 98.913 32.331C97.2917 33.0622 95.3684 33.4278 93.143 33.4278H81.8879ZM79.1698 33.4278V0.0476854H85.0829V33.4278H79.1698ZM81.6972 19.122V13.8289H91.9509C93.4451 13.8289 94.6213 13.4474 95.4797 12.6844C96.3698 11.8897 96.8148 10.7929 96.8148 9.39411C96.8148 7.96353 96.3221 6.85087 95.3366 6.0561C94.3829 5.26134 93.0477 4.87985 91.331 4.91164H81.6972V0.0953709L91.6171 0C93.906 0 95.8929 0.365591 97.5778 1.09677C99.2945 1.79617 100.614 2.84525 101.536 4.24404C102.489 5.64282 102.966 7.37541 102.966 9.4418C102.966 11.1903 102.41 12.7639 101.297 14.1627C100.185 15.5615 98.611 16.6583 96.5764 17.453C94.5736 18.2478 92.2211 18.6452 89.5189 18.6452L81.6972 19.122Z" fill="white"/> +<path d="M112.232 20.8387C112.232 18.2637 112.725 16.1496 113.71 14.4965C114.727 12.8116 116.015 11.5559 117.573 10.7293C119.13 9.90276 120.768 9.48948 122.484 9.48948V15.0687C121.054 15.0687 119.687 15.2595 118.383 15.641C117.112 16.0224 116.063 16.6424 115.236 17.5007C114.441 18.3273 114.044 19.424 114.044 20.791L112.232 20.8387ZM108.274 33.4278V9.58485H114.044V33.4278H108.274Z" fill="white"/> +<path d="M136.556 34C134.14 34 131.994 33.4755 130.119 32.4264C128.275 31.3455 126.812 29.8672 125.731 27.9916C124.682 26.1159 124.158 23.9542 124.158 21.5063C124.158 19.0584 124.682 16.8967 125.731 15.021C126.781 13.1454 128.227 11.683 130.071 10.6339C131.947 9.55306 134.076 9.01262 136.461 9.01262C138.877 9.01262 141.007 9.55306 142.851 10.6339C144.726 11.683 146.189 13.1454 147.238 15.021C148.287 16.8967 148.811 19.0584 148.811 21.5063C148.811 23.9542 148.287 26.1159 147.238 27.9916C146.189 29.8672 144.742 31.3455 142.898 32.4264C141.055 33.4755 138.94 34 136.556 34ZM136.556 28.6592C137.796 28.6592 138.893 28.3572 139.846 27.7532C140.8 27.1173 141.547 26.2749 142.088 25.2258C142.628 24.1449 142.898 22.9051 142.898 21.5063C142.898 20.1075 142.612 18.8836 142.04 17.8345C141.5 16.7536 140.737 15.9112 139.751 15.3072C138.797 14.6713 137.701 14.3534 136.461 14.3534C135.221 14.3534 134.124 14.6554 133.17 15.2595C132.217 15.8635 131.454 16.7059 130.882 17.7868C130.341 18.8677 130.071 20.1075 130.071 21.5063C130.071 22.9051 130.341 24.1449 130.882 25.2258C131.454 26.2749 132.233 27.1173 133.218 27.7532C134.204 28.3572 135.316 28.6592 136.556 28.6592Z" fill="white"/> +<path d="M173.92 33.4278L181.836 9.58485H187.749L179.643 33.4278H173.92ZM157.993 33.4278L165.718 9.58485H170.821L163.239 33.4278H157.993ZM157.469 33.4278L149.362 9.58485H155.275L162.952 33.4278H157.469ZM173.92 33.4278L166.338 9.58485H171.441L179.118 33.4278H173.92Z" fill="white"/> +<path d="M198.427 34C196.869 34 195.423 33.7616 194.088 33.2847C192.753 32.8079 191.592 32.1402 190.607 31.2819C189.621 30.3918 188.858 29.3427 188.318 28.1346L193.325 25.8934C193.802 26.6882 194.469 27.3876 195.328 27.9916C196.218 28.5638 197.235 28.8499 198.379 28.8499C199.492 28.8499 200.382 28.6751 201.05 28.3254C201.717 27.9439 202.051 27.4194 202.051 26.7518C202.051 26.1159 201.781 25.6232 201.241 25.2735C200.732 24.9238 200.017 24.6377 199.095 24.4151L196.901 23.8429C194.644 23.2389 192.864 22.3011 191.56 21.0295C190.257 19.726 189.605 18.2478 189.605 16.5947C189.605 14.1786 190.384 12.3188 191.942 11.0154C193.5 9.68022 195.725 9.01262 198.618 9.01262C200.08 9.01262 201.447 9.23516 202.719 9.68022C203.991 10.1253 205.071 10.7452 205.962 11.54C206.852 12.3029 207.487 13.209 207.869 14.2581L203.005 16.4516C202.751 15.7204 202.178 15.1482 201.288 14.7349C200.43 14.3216 199.524 14.115 198.57 14.115C197.585 14.115 196.822 14.3216 196.281 14.7349C195.773 15.1482 195.518 15.7204 195.518 16.4516C195.518 16.9285 195.757 17.3259 196.234 17.6438C196.71 17.9617 197.426 18.2319 198.379 18.4544L201.336 19.2174C202.894 19.5989 204.149 20.2029 205.103 21.0295C206.057 21.856 206.756 22.7779 207.201 23.7952C207.646 24.8125 207.869 25.8139 207.869 26.7994C207.869 28.23 207.456 29.5016 206.629 30.6143C205.803 31.6952 204.674 32.5376 203.243 33.1417C201.845 33.7139 200.239 34 198.427 34Z" fill="white"/> +<path d="M222.071 34C219.718 34 217.636 33.4755 215.824 32.4264C214.044 31.3455 212.629 29.8672 211.58 27.9916C210.563 26.1159 210.054 23.9542 210.054 21.5063C210.054 19.0584 210.578 16.8967 211.628 15.021C212.677 13.1454 214.123 11.683 215.967 10.6339C217.811 9.55306 219.925 9.01262 222.309 9.01262C224.407 9.01262 226.331 9.56896 228.079 10.6816C229.828 11.7625 231.211 13.352 232.228 15.4502C233.277 17.5166 233.801 20.028 233.801 22.9846H227.936C227.968 20.8864 227.745 19.2015 227.269 17.9299C226.792 16.6265 226.108 15.6727 225.218 15.0687C224.36 14.4647 223.326 14.1627 222.118 14.1627C220.815 14.1627 219.702 14.4488 218.78 15.021C217.859 15.5615 217.159 16.388 216.682 17.5007C216.205 18.5816 215.967 19.9645 215.967 21.6494C215.967 23.1753 216.269 24.4469 216.873 25.4642C217.477 26.4815 218.288 27.2604 219.305 27.8008C220.322 28.3413 221.435 28.6115 222.643 28.6115C223.978 28.6115 225.059 28.3254 225.886 27.7532C226.744 27.1491 227.412 26.3862 227.888 25.4642L233.277 27.6101C232.641 28.9453 231.783 30.0898 230.702 31.0435C229.653 31.9972 228.413 32.7284 226.982 33.237C225.552 33.7457 223.915 34 222.071 34ZM213.869 22.9846L213.916 18.4067H230.845V22.9846H213.869Z" fill="white"/> +<path d="M241.181 20.8387C241.181 18.2637 241.674 16.1496 242.659 14.4965C243.677 12.8116 244.964 11.5559 246.522 10.7293C248.08 9.90276 249.717 9.48948 251.434 9.48948V15.0687C250.003 15.0687 248.636 15.2595 247.333 15.641C246.061 16.0224 245.012 16.6424 244.185 17.5007C243.391 18.3273 242.993 19.424 242.993 20.791L241.181 20.8387ZM237.223 33.4278V9.58485H242.993V33.4278H237.223Z" fill="white"/> +</svg> diff --git a/browser/branding/tb-release/content/about.png b/browser/branding/tb-release/content/about.png new file mode 100644 index 0000000000000000000000000000000000000000..bec6b90de5cd8f10fdc9a037b6ff67f69135cff7 Binary files /dev/null and b/browser/branding/tb-release/content/about.png differ diff --git a/browser/branding/tb-release/content/aboutDialog.css b/browser/branding/tb-release/content/aboutDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..c9c8bc587429c29c250ebac0a1def444f0dbb967 --- /dev/null +++ b/browser/branding/tb-release/content/aboutDialog.css @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#aboutDialogContainer { + background-color: #20123a; + color: #fff; + color-scheme: dark; +} + +#clientBox { + padding: 10px 0 15px; +} + +#leftBox { + background-image: url("chrome://branding/content/about-logo.png"); + background-repeat: no-repeat; + background-size: 192px auto; + background-position: center 20%; + /* min-width and min-height create room for the logo */ + min-width: 210px; + min-height: 210px; + margin-top: 20px; + margin-inline-start: 30px; +} + +@media (min-resolution: 2dppx) { + #leftBox { + background-image: url("chrome://branding/content/about-logo@2x.png"); + } +} + +.text-link { + color: #fff !important; + text-decoration: underline; +} + +#rightBox { + margin-inline: 30px; +} + +#rightBox:-moz-locale-dir(rtl) { + /* tor-browser#42319: re-align the background image after we added some + padding to make all the channel use the same size for the wordmark. + We can remove this it if we stop making the resource accessible from content + (tor-browser#29745) */ + background-position: right -164px top 0; +} + +#bottomBox { + background-color: hsla(235, 43%, 10%, .5); + padding: 15px 10px 15px; +} + +#trademark { + font-size: xx-small; + text-align: center; + color: #999999; + margin-block: 10px; +} diff --git a/browser/branding/tb-release/content/firefox-wordmark.svg b/browser/branding/tb-release/content/firefox-wordmark.svg new file mode 100644 index 0000000000000000000000000000000000000000..65270a3cd9a966cd350ec717758c352661ecca4e --- /dev/null +++ b/browser/branding/tb-release/content/firefox-wordmark.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="172" height="42"><path fill="context-fill #20123a" d="M.19 2.82h25.72v7H7.57v9.43h18.34v6.9H7.57v15.14H.19zM34.65.13a4.14 4.14 0 0 1 4.27 4.33 4.12 4.12 0 0 1-4.32 4.32 4.09 4.09 0 0 1-4.27-4.22A4.27 4.27 0 0 1 34.65.13zM31 12.83h7.27v28.46H31zm28.35 7.91a5.89 5.89 0 0 0-3.53-1.27c-3 0-4.64 1.9-4.64 6.06v15.76H44V12.83h6.9v4.11a6.79 6.79 0 0 1 6.8-4.37A8.69 8.69 0 0 1 62.53 14zm3 6.48c0-8.17 6.06-15 14.65-15s14.59 6.06 14.59 14.49v3H69.48c.79 3.58 3.58 6 7.85 6a7.62 7.62 0 0 0 7.06-4.21l6.06 3.63c-3 4.43-7.27 6.75-13.33 6.75-9.22-.01-14.75-6.18-14.75-14.66zM69.59 24h15c-.79-3.63-3.74-5.63-7.59-5.63A7.31 7.31 0 0 0 69.59 24zM93.4 12.83h5.11v-1.42c0-7.75 3.27-11 10.44-11h2.53v6.31h-2.06c-3.37 0-4.11 1.16-4.11 4.69v1.42h6.17v6.54h-6v21.92h-7V19.37H93.4zm19.45 14.23a14.56 14.56 0 0 1 14.85-14.81 14.81 14.81 0 1 1 0 29.62c-8.85 0-14.85-6.49-14.85-14.81zm22.65 0a7.8 7.8 0 1 0-15.59 0 7.8 7.8 0 1 0 15.59 0zm16.86-.32l-10.27-13.91h8.53l6.06 8.75 6.22-8.75h8.38l-10.43 13.86 11 14.6h-8.49L156.53 32l-6.59 9.28h-8.48z"/></svg> \ No newline at end of file diff --git a/browser/branding/tb-release/content/jar.mn b/browser/branding/tb-release/content/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..11e3e15350dd36f8564bf5fd66f66630a885bf80 --- /dev/null +++ b/browser/branding/tb-release/content/jar.mn @@ -0,0 +1,19 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +browser.jar: +% content branding %content/branding/ contentaccessible=yes + content/branding/about.png + content/branding/about-logo.png + content/branding/about-logo.svg + content/branding/about-logo@2x.png + content/branding/about-wordmark.svg + content/branding/firefox-wordmark.svg + content/branding/icon16.png (../default16.png) + content/branding/icon32.png (../default32.png) + content/branding/icon48.png (../default48.png) + content/branding/icon64.png (../default64.png) + content/branding/icon128.png (../default128.png) + content/branding/icon256.png (../default256.png) + content/branding/aboutDialog.css diff --git a/browser/branding/tb-release/content/moz.build b/browser/branding/tb-release/content/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-release/content/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-release/default128.png b/browser/branding/tb-release/default128.png new file mode 100644 index 0000000000000000000000000000000000000000..801b470e404529f61fbdf617e2d972cbcda6ec90 Binary files /dev/null and b/browser/branding/tb-release/default128.png differ diff --git a/browser/branding/tb-release/default16.png b/browser/branding/tb-release/default16.png new file mode 100644 index 0000000000000000000000000000000000000000..82c1a708d20c2a924cd7ccc397c13afd38645700 Binary files /dev/null and b/browser/branding/tb-release/default16.png differ diff --git a/browser/branding/tb-release/default22.png b/browser/branding/tb-release/default22.png new file mode 100644 index 0000000000000000000000000000000000000000..8df3f05d89852c21cf5a14ac7d83a41d6df05268 Binary files /dev/null and b/browser/branding/tb-release/default22.png differ diff --git a/browser/branding/tb-release/default24.png b/browser/branding/tb-release/default24.png new file mode 100644 index 0000000000000000000000000000000000000000..607e078f3091b052caecb2d864eac5d3fb96bca6 Binary files /dev/null and b/browser/branding/tb-release/default24.png differ diff --git a/browser/branding/tb-release/default256.png b/browser/branding/tb-release/default256.png new file mode 100644 index 0000000000000000000000000000000000000000..89ac159eb972f9a2ce58b6c5222c8615a7aa84d9 Binary files /dev/null and b/browser/branding/tb-release/default256.png differ diff --git a/browser/branding/tb-release/default32.png b/browser/branding/tb-release/default32.png new file mode 100644 index 0000000000000000000000000000000000000000..ad7e8d1d3e70ad8a3262ccc4a4baacf91a2131b5 Binary files /dev/null and b/browser/branding/tb-release/default32.png differ diff --git a/browser/branding/tb-release/default48.png b/browser/branding/tb-release/default48.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc712bad3208d9776212f97b8a555f03f443044 Binary files /dev/null and b/browser/branding/tb-release/default48.png differ diff --git a/browser/branding/tb-release/default64.png b/browser/branding/tb-release/default64.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac77fa541a933e1e61e8d1ba962d77738f372c2 Binary files /dev/null and b/browser/branding/tb-release/default64.png differ diff --git a/browser/branding/tb-release/document.icns b/browser/branding/tb-release/document.icns new file mode 100644 index 0000000000000000000000000000000000000000..e7ae23fd824586978cdee2b05f1d85df319eb022 Binary files /dev/null and b/browser/branding/tb-release/document.icns differ diff --git a/browser/branding/tb-release/document.ico b/browser/branding/tb-release/document.ico new file mode 100644 index 0000000000000000000000000000000000000000..c86815d81f6f53abac9468c0c42c7279fe2a7f7c Binary files /dev/null and b/browser/branding/tb-release/document.ico differ diff --git a/browser/branding/tb-release/document_pdf.ico b/browser/branding/tb-release/document_pdf.ico new file mode 100644 index 0000000000000000000000000000000000000000..dc74ba85f69daa19d5806c4a5f7491310041c887 Binary files /dev/null and b/browser/branding/tb-release/document_pdf.ico differ diff --git a/browser/branding/tb-release/firefox.VisualElementsManifest.xml b/browser/branding/tb-release/firefox.VisualElementsManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b88a0c12f37f36bcde98b47258fce3dcd03351d3 --- /dev/null +++ b/browser/branding/tb-release/firefox.VisualElementsManifest.xml @@ -0,0 +1,12 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> + <VisualElements + ShowNameOnSquare150x150Logo='on' + Square150x150Logo='browser\VisualElements\VisualElements_150.png' + Square70x70Logo='browser\VisualElements\VisualElements_70.png' + ForegroundText='light' + BackgroundColor='#271339'/> +</Application> diff --git a/browser/branding/tb-release/firefox.icns b/browser/branding/tb-release/firefox.icns new file mode 100644 index 0000000000000000000000000000000000000000..d33af7a48e5fa29590eed9c20062bd2bb1723d78 Binary files /dev/null and b/browser/branding/tb-release/firefox.icns differ diff --git a/browser/branding/tb-release/firefox.ico b/browser/branding/tb-release/firefox.ico new file mode 100644 index 0000000000000000000000000000000000000000..3e7ab03463f8f0e54edb7ebd75e5eaed1893c541 Binary files /dev/null and b/browser/branding/tb-release/firefox.ico differ diff --git a/browser/branding/tb-release/locales/en-US/brand.ftl b/browser/branding/tb-release/locales/en-US/brand.ftl new file mode 100644 index 0000000000000000000000000000000000000000..a8604d3aaedb5bcba4bc62f8a7c7e39cc4279dac --- /dev/null +++ b/browser/branding/tb-release/locales/en-US/brand.ftl @@ -0,0 +1,14 @@ +# For Tor Browser, we use a new file (different than the brand.ftl file +# that is used by Firefox) to avoid picking up the -brand-short-name values +# that Mozilla includes in the Firefox language packs. + +-brand-shorter-name = Tor Browser +-brand-short-name = Tor Browser +-brand-full-name = Tor Browser +# This brand name can be used in messages where the product name needs to +# remain unchanged across different versions (Nightly, Beta, etc.). +-brand-product-name = Tor Browser +-vendor-short-name = Tor Project +# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized). +# "The Tor Project, Inc." is an organisation name. +trademarkInfo = “Tor” and the Tor logo are registered trademarks of The Tor Project, Inc. diff --git a/browser/branding/tb-release/locales/en-US/brand.properties b/browser/branding/tb-release/locales/en-US/brand.properties new file mode 100644 index 0000000000000000000000000000000000000000..59d1fe05cf7ff18af56f3b857f26907c44675a6f --- /dev/null +++ b/browser/branding/tb-release/locales/en-US/brand.properties @@ -0,0 +1,8 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +brandShorterName=Tor Browser +brandShortName=Tor Browser +brandFullName=Tor Browser diff --git a/browser/branding/tb-release/locales/jar.mn b/browser/branding/tb-release/locales/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..2250233dd6245b892292b97d5a32393557b5a6fe --- /dev/null +++ b/browser/branding/tb-release/locales/jar.mn @@ -0,0 +1,11 @@ +#filter substitution +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[localization] @AB_CD@.jar: + branding (%*.ftl) + +@AB_CD@.jar: +% locale branding @AB_CD@ %locale/branding/ + locale/branding/brand.properties (%brand.properties) diff --git a/browser/branding/tb-release/locales/moz.build b/browser/branding/tb-release/locales/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..d988c0ff9b162c1f83ac1fbaf05ae59d090aa8b7 --- /dev/null +++ b/browser/branding/tb-release/locales/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/branding/tb-release/moz.build b/browser/branding/tb-release/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..dd081ac44496d19d2e8d73a0a10f3d1ad81266b6 --- /dev/null +++ b/browser/branding/tb-release/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ["content", "locales"] + +DIST_SUBDIR = "browser" +export("DIST_SUBDIR") + +include("../branding-common.mozbuild") +FirefoxBranding() diff --git a/browser/branding/tb-release/newtab.ico b/browser/branding/tb-release/newtab.ico new file mode 100644 index 0000000000000000000000000000000000000000..a9b37c08c6e18af5c8b67745c445bad21fd4e791 Binary files /dev/null and b/browser/branding/tb-release/newtab.ico differ diff --git a/browser/branding/tb-release/newwindow.ico b/browser/branding/tb-release/newwindow.ico new file mode 100644 index 0000000000000000000000000000000000000000..55372077102c4ba18ff1b858b78a2e4c735e6988 Binary files /dev/null and b/browser/branding/tb-release/newwindow.ico differ diff --git a/browser/branding/tb-release/pbmode.ico b/browser/branding/tb-release/pbmode.ico new file mode 100644 index 0000000000000000000000000000000000000000..47677c13fba6881d30eef3a16b46b70f3deb5bc9 Binary files /dev/null and b/browser/branding/tb-release/pbmode.ico differ diff --git a/browser/branding/tb-release/pref/firefox-branding.js b/browser/branding/tb-release/pref/firefox-branding.js new file mode 100644 index 0000000000000000000000000000000000000000..8e4c137aea293a1e2adada1c8e0a3a88e22dd7fd --- /dev/null +++ b/browser/branding/tb-release/pref/firefox-branding.js @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file contains branding-specific prefs. + +// Set a generic, default URL that will be opened in a tab after an update. +// Typically, this will not be used; instead, the <update> element within +// each update manifest should contain attributes similar to: +// actions="showURL" +// openURL="https://blog.torproject.org/tor-browser-55a2-released" +pref("startup.homepage_override_url", "https://blog.torproject.org/category/applications"); +pref("startup.homepage_welcome_url", "about:welcome"); +pref("startup.homepage_welcome_url.additional", ""); +// Interval: Time between checks for a new version (in seconds) +pref("app.update.interval", 43200); // 12 hours +// Give the user x seconds to react before showing the big UI. default=192 hours +pref("app.update.promptWaitTime", 691200); +// app.update.url.manual: URL user can browse to manually if for some reason +// all update installation attempts fail. +// app.update.url.details: a default value for the "More information about this +// update" link supplied in the "An update is available" page of the update +// wizard. +#if MOZ_UPDATE_CHANNEL == beta + pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/beta?reason=manual-update"); + pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/beta/notes"); + pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew"); + pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog"); +#elifdef MOZ_ESR + pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/enterprise?reason=manual-update"); + pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/organizations/notes"); + pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew"); + pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog"); +#else + pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/new?reason=manual-update"); + pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/notes"); + pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew"); + pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog"); +#endif + +// The number of days a binary is permitted to be old +// without checking for an update. This assumes that +// app.update.checkInstallTime is true. +pref("app.update.checkInstallTime.days", 63); + +// Give the user x seconds to reboot before showing a badge on the hamburger +// button. default=4 days +pref("app.update.badgeWaitTime", 345600); + +// Number of usages of the web console. +// If this is less than 5, then pasting code into the web console is disabled +pref("devtools.selfxss.count", 0); diff --git a/browser/components/BrowserContentHandler.sys.mjs b/browser/components/BrowserContentHandler.sys.mjs index 7356e0bc7f81d9c5885499bcc83c5f87c607a3e7..a170a11b78dc929f1981314ea5eb7efc5a0d1ec2 100644 --- a/browser/components/BrowserContentHandler.sys.mjs +++ b/browser/components/BrowserContentHandler.sys.mjs @@ -42,6 +42,9 @@ ChromeUtils.defineLazyGetter(lazy, "gWindowsAlertsService", () => { ?.QueryInterface(Ci.nsIWindowsAlertsService); }); +const FORK_VERSION_PREF = + "browser.startup.homepage_override.torbrowser.version"; + // One-time startup homepage override configurations const ONCE_DOMAINS = ["mozilla.org", "firefox.com"]; const ONCE_PREF = "browser.startup.homepage_override.once"; @@ -116,7 +119,7 @@ const OVERRIDE_NEW_BUILD_ID = 3; * if this is the first run with a new profile. * OVERRIDE_NEW_MSTONE * if this is the first run with a build with a different Gecko milestone - * (i.e. right after an upgrade). + * or fork version (i.e. right after an upgrade). * OVERRIDE_NEW_BUILD_ID * if this is the first run with a new build ID of the same Gecko * milestone (i.e. after a nightly upgrade). @@ -135,6 +138,8 @@ function needHomepageOverride(updateMilestones = true) { var mstone = Services.appinfo.platformVersion; + var savedForkVersion = Services.prefs.getCharPref(FORK_VERSION_PREF, null); + var savedBuildID = Services.prefs.getCharPref( "browser.startup.homepage_override.buildID", "" @@ -163,10 +168,28 @@ function needHomepageOverride(updateMilestones = true) { "browser.startup.homepage_override.buildID", buildID ); + Services.prefs.setCharPref( + FORK_VERSION_PREF, + AppConstants.BASE_BROWSER_VERSION + ); } return savedmstone ? OVERRIDE_NEW_MSTONE : OVERRIDE_NEW_PROFILE; } + if (AppConstants.BASE_BROWSER_VERSION != savedForkVersion) { + if (updateMilestones) { + Services.prefs.setCharPref( + "browser.startup.homepage_override.buildID", + buildID + ); + Services.prefs.setCharPref( + FORK_VERSION_PREF, + AppConstants.BASE_BROWSER_VERSION + ); + } + return OVERRIDE_NEW_MSTONE; + } + if (buildID != savedBuildID) { if (updateMilestones) { Services.prefs.setCharPref( @@ -805,6 +828,10 @@ nsBrowserContentHandler.prototype = { "browser.startup.homepage_override.buildID", "unknown" ); + + // We do the same for the fork version. + let old_forkVersion = Services.prefs.getCharPref(FORK_VERSION_PREF, null); + override = needHomepageOverride(); if (override != OVERRIDE_NONE) { switch (override) { @@ -916,9 +943,10 @@ nsBrowserContentHandler.prototype = { } } + let old_version = old_forkVersion ? old_forkVersion : old_mstone; if ( update && - Services.vc.compare(update.appVersion, old_mstone) > 0 + Services.vc.compare(update.appVersion, old_version) > 0 ) { overridePage = getPostUpdateOverridePage( update, @@ -963,6 +991,31 @@ nsBrowserContentHandler.prototype = { ); overridePage = overridePage.replace("%OLD_VERSION%", old_mstone); + overridePage = overridePage.replace( + "%OLD_BASE_BROWSER_VERSION%", + old_forkVersion + ); + if (overridePage && AppConstants.BASE_BROWSER_UPDATE) { + // Tor Browser: Instead of opening the post-update "override page" + // directly, we ensure that about:tor will be opened, which should + // notify the user that their browser was updated. + // + // The overridePage comes from the openURL attribute within the + // updates.xml file or, if no showURL action is present, from the + // startup.homepage_override_url pref. + Services.prefs.setCharPref( + "torbrowser.post_update.url", + overridePage + ); + Services.prefs.setBoolPref( + "torbrowser.post_update.shouldNotify", + true + ); + // If the user's homepage is about:tor, we will inform them + // about the update on that page; otherwise, we arrange to + // open about:tor in a secondary tab. + overridePage = startPage === "about:tor" ? "" : "about:tor"; + } break; } case OVERRIDE_NEW_BUILD_ID: { diff --git a/browser/components/BrowserGlue.sys.mjs b/browser/components/BrowserGlue.sys.mjs index f9638a7ad797bb5542b54eb13a623a93cf10a023..67b03f37d055144fc8355bffb1daa0dd0a3afb62 100644 --- a/browser/components/BrowserGlue.sys.mjs +++ b/browser/components/BrowserGlue.sys.mjs @@ -8,12 +8,8 @@ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { - AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", AWToolbarButton: "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs", ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs", - ASRouterDefaultConfig: - "resource:///modules/asrouter/ASRouterDefaultConfig.sys.mjs", - ASRouterNewTabHook: "resource:///modules/asrouter/ASRouterNewTabHook.sys.mjs", ActorManagerParent: "resource://gre/modules/ActorManagerParent.sys.mjs", AddonManager: "resource://gre/modules/AddonManager.sys.mjs", AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs", @@ -41,6 +37,7 @@ ChromeUtils.defineESModuleGetters(lazy, { DoHController: "resource:///modules/DoHController.sys.mjs", DownloadsViewableInternally: "resource:///modules/DownloadsViewableInternally.sys.mjs", + DragDropFilter: "resource://gre/modules/DragDropFilter.sys.mjs", E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs", ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs", FeatureGate: "resource://featuregates/FeatureGate.sys.mjs", @@ -62,6 +59,7 @@ ChromeUtils.defineESModuleGetters(lazy, { NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", Normandy: "resource://normandy/Normandy.sys.mjs", + OnionAliasStore: "resource:///modules/OnionAliasStore.sys.mjs", OnboardingMessageProvider: "resource:///modules/asrouter/OnboardingMessageProvider.sys.mjs", OsEnvironment: "resource://gre/modules/OsEnvironment.sys.mjs", @@ -79,8 +77,6 @@ ChromeUtils.defineESModuleGetters(lazy, { PluginManager: "resource:///actors/PluginParent.sys.mjs", PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.sys.mjs", - PublicSuffixList: - "resource://gre/modules/netwerk-dns/PublicSuffixList.sys.mjs", QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs", RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", RemoteSecuritySettings: @@ -90,7 +86,6 @@ ChromeUtils.defineESModuleGetters(lazy, { SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs", Sanitizer: "resource:///modules/Sanitizer.sys.mjs", SandboxUtils: "resource://gre/modules/SandboxUtils.sys.mjs", - SaveToPocket: "chrome://pocket/content/SaveToPocket.sys.mjs", ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs", SearchSERPCategorization: "resource:///modules/SearchSERPTelemetry.sys.mjs", SearchSERPTelemetry: "resource:///modules/SearchSERPTelemetry.sys.mjs", @@ -98,12 +93,15 @@ ChromeUtils.defineESModuleGetters(lazy, { SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs", ShellService: "resource:///modules/ShellService.sys.mjs", ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs", - ShoppingUtils: "resource:///modules/ShoppingUtils.sys.mjs", + // Removed ShoppingUtils. tor-browser#42831. SpecialMessageActions: "resource://messaging-system/lib/SpecialMessageActions.sys.mjs", TRRRacer: "resource:///modules/TRRPerformance.sys.mjs", TabCrashHandler: "resource:///modules/ContentCrashHandlers.sys.mjs", TabUnloader: "resource:///modules/TabUnloader.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", + TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", UIState: "resource://services-sync/UIState.sys.mjs", UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs", UrlbarSearchTermsPersistence: @@ -114,6 +112,7 @@ ChromeUtils.defineESModuleGetters(lazy, { WindowsLaunchOnLogin: "resource://gre/modules/WindowsLaunchOnLogin.sys.mjs", WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs", WindowsGPOParser: "resource://gre/modules/policies/WindowsGPOParser.sys.mjs", + checkHomepageOverride: "resource:///modules/HomepageOverride.sys.mjs", clearTimeout: "resource://gre/modules/Timer.sys.mjs", setTimeout: "resource://gre/modules/Timer.sys.mjs", }); @@ -188,6 +187,166 @@ let gThisInstanceIsLaunchOnLogin = false; // a taskbar tab shortcut will contain the "taskbar-tab" flag. let gThisInstanceIsTaskbarTab = false; +// Empty clipboard content from private windows on exit +// (tor-browser#42154) +const ClipboardPrivacy = { + _lastClipboardHash: null, + _globalActivation: false, + _isPrivateClipboard: false, + _hasher: null, + _shuttingDown: false, + + _createTransferable() { + const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + return trans; + }, + _computeClipboardHash() { + const flavors = ["text/x-moz-url", "text/plain"]; + if ( + !Services.clipboard.hasDataMatchingFlavors( + flavors, + Ci.nsIClipboard.kGlobalClipboard + ) + ) { + return null; + } + const trans = this._createTransferable(); + flavors.forEach(trans.addDataFlavor); + try { + Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard); + const clipboardContent = {}; + trans.getAnyTransferData({}, clipboardContent); + const { data } = clipboardContent.value.QueryInterface( + Ci.nsISupportsString + ); + const bytes = new TextEncoder().encode(data); + const hasher = (this._hasher ||= Cc[ + "@mozilla.org/security/hash;1" + ].createInstance(Ci.nsICryptoHash)); + hasher.init(hasher.SHA256); + hasher.update(bytes, bytes.length); + return hasher.finish(true); + } catch (e) {} + return null; + }, + + startup() { + this._lastClipboardHash = this._computeClipboardHash(); + + // Here we track changes in active window / application, + // by filtering focus events and window closures. + const handleActivation = (win, activation) => { + if (activation) { + if (!this._globalActivation) { + // focus changed within this window, bail out. + return; + } + this._globalActivation = false; + } else if (!Services.focus.activeWindow) { + // focus is leaving this window: + // let's track whether it remains within the browser. + lazy.setTimeout(() => { + this._globalActivation = !Services.focus.activeWindow; + }, 100); + } + + const checkClipboardContent = () => { + const clipboardHash = this._computeClipboardHash(); + if (clipboardHash !== this._lastClipboardHash) { + this._isPrivateClipboard = + !activation && + (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing || + lazy.PrivateBrowsingUtils.isWindowPrivate(win)); + this._lastClipboardHash = clipboardHash; + lazy.log.debug( + `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.` + ); + } + }; + + if (win.closed) { + checkClipboardContent(); + } else { + // defer clipboard access on DOM events to work-around tor-browser#42306 + lazy.setTimeout(checkClipboardContent, 0); + } + }; + const focusListener = e => + e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin"); + const initWindow = win => { + for (const e of ["focusin", "focusout"]) { + win.addEventListener(e, focusListener); + } + }; + for (const w of Services.ww.getWindowEnumerator()) { + initWindow(w); + } + Services.ww.registerNotification((win, event) => { + switch (event) { + case "domwindowopened": + initWindow(win); + break; + case "domwindowclosed": + handleActivation(win, false); + if ( + this._isPrivateClipboard && + lazy.PrivateBrowsingUtils.isWindowPrivate(win) && + (this._shuttingDown || + !Array.from(Services.ww.getWindowEnumerator()).find( + w => + lazy.PrivateBrowsingUtils.isWindowPrivate(w) && + // We need to filter out the HIDDEN WebExtensions window, + // which might be private as well but is not UI-relevant. + !w.location.href.startsWith("chrome://extensions/") + )) + ) { + // no more private windows, empty private content if needed + this.emptyPrivate(); + } + } + }); + + lazy.AsyncShutdown.quitApplicationGranted.addBlocker( + "ClipboardPrivacy: removing private data", + () => { + this._shuttingDown = true; + this.emptyPrivate(); + } + ); + }, + emptyPrivate() { + if ( + this._isPrivateClipboard && + !Services.prefs.getBoolPref( + "browser.privatebrowsing.preserveClipboard", + false + ) && + this._lastClipboardHash === this._computeClipboardHash() + ) { + // nsIClipboard.emptyClipboard() does nothing in Wayland: + // we'll set an empty string as a work-around. + const trans = this._createTransferable(); + const flavor = "text/plain"; + trans.addDataFlavor(flavor); + const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + emptyString.data = ""; + trans.setTransferData(flavor, emptyString); + const { clipboard } = Services, + { kGlobalClipboard } = clipboard; + clipboard.setData(trans, null, kGlobalClipboard); + clipboard.emptyClipboard(kGlobalClipboard); + this._lastClipboardHash = null; + this._isPrivateClipboard = false; + lazy.log.info("Private clipboard emptied."); + } + }, +}; + /** * Fission-compatible JSProcess implementations. * Each actor options object takes the form of a ProcessActorOptions dictionary. @@ -307,52 +466,6 @@ let JSWINDOWACTORS = { matches: ["about:messagepreview", "about:messagepreview?*"], }, - AboutNewTab: { - parent: { - esModuleURI: "resource:///actors/AboutNewTabParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/AboutNewTabChild.sys.mjs", - events: { - DOMDocElementInserted: {}, - DOMContentLoaded: {}, - load: { capture: true }, - unload: { capture: true }, - pageshow: {}, - visibilitychange: {}, - }, - }, - // The wildcard on about:newtab is for the # parameter - // that is used for the newtab devtools. The wildcard for about:home - // is similar, and also allows for falling back to loading the - // about:home document dynamically if an attempt is made to load - // about:home?jscache from the AboutHomeStartupCache as a top-level - // load. - matches: ["about:home*", "about:welcome", "about:newtab*"], - remoteTypes: ["privilegedabout"], - }, - - AboutPocket: { - parent: { - esModuleURI: "resource:///actors/AboutPocketParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/AboutPocketChild.sys.mjs", - - events: { - DOMDocElementInserted: { capture: true }, - }, - }, - - remoteTypes: ["privilegedabout"], - matches: [ - "about:pocket-saved*", - "about:pocket-signup*", - "about:pocket-home*", - "about:pocket-style-guide*", - ], - }, - AboutPrivateBrowsing: { parent: { esModuleURI: "resource:///actors/AboutPrivateBrowsingParent.sys.mjs", @@ -414,20 +527,25 @@ let JSWINDOWACTORS = { matches: ["about:tabcrashed*"], }, - AboutWelcomeShopping: { + AboutTor: { parent: { - esModuleURI: "resource:///actors/AboutWelcomeParent.sys.mjs", + esModuleURI: "resource:///actors/AboutTorParent.sys.mjs", }, child: { - esModuleURI: "resource:///actors/AboutWelcomeChild.sys.mjs", + esModuleURI: "resource:///actors/AboutTorChild.sys.mjs", + events: { - Update: {}, + DOMContentLoaded: {}, + L10nMutationsFinished: {}, + SubmitSearchOnionize: { wantUntrusted: true }, }, }, - matches: ["about:shoppingsidebar"], - remoteTypes: ["privilegedabout"], + + matches: ["about:tor"], }, + // Removed AboutWelcomeShopping. tor-browser#42831. + AboutWelcome: { parent: { esModuleURI: "resource:///actors/AboutWelcomeParent.sys.mjs", @@ -577,6 +695,24 @@ let JSWINDOWACTORS = { }, messageManagerGroups: ["browsers"], + + allFrames: true, + }, + + CryptoSafety: { + parent: { + esModuleURI: "resource:///actors/CryptoSafetyParent.sys.mjs", + }, + + child: { + esModuleURI: "resource:///actors/CryptoSafetyChild.sys.mjs", + group: "browsers", + events: { + copy: { mozSystemGroup: true }, + cut: { mozSystemGroup: true }, + }, + }, + allFrames: true, }, @@ -691,6 +827,19 @@ let JSWINDOWACTORS = { messageManagerGroups: ["browsers"], }, + OnionLocation: { + parent: { + esModuleURI: "resource:///modules/OnionLocationParent.sys.mjs", + }, + child: { + esModuleURI: "resource:///modules/OnionLocationChild.sys.mjs", + events: { + pageshow: { mozSystemGroup: true }, + }, + }, + messageManagerGroups: ["browsers"], + }, + PageInfo: { child: { esModuleURI: "resource:///actors/PageInfoChild.sys.mjs", @@ -789,6 +938,19 @@ let JSWINDOWACTORS = { enablePreference: "accessibility.blockautorefresh", }, + Rulesets: { + parent: { + esModuleURI: "resource:///modules/RulesetsParent.sys.mjs", + }, + child: { + esModuleURI: "resource:///modules/RulesetsChild.sys.mjs", + events: { + DOMWindowCreated: {}, + }, + }, + matches: ["about:rulesets*"], + }, + ScreenshotsComponent: { parent: { esModuleURI: "resource:///modules/ScreenshotsUtils.sys.mjs", @@ -853,27 +1015,7 @@ let JSWINDOWACTORS = { matches: ["about:studies*"], }, - ShoppingSidebar: { - parent: { - esModuleURI: "resource:///actors/ShoppingSidebarParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/ShoppingSidebarChild.sys.mjs", - events: { - ContentReady: { wantUntrusted: true }, - PolledRequestMade: { wantUntrusted: true }, - // This is added so the actor instantiates immediately and makes - // methods available to the page js on load. - DOMDocElementInserted: {}, - ReportProductAvailable: { wantUntrusted: true }, - AdClicked: { wantUntrusted: true }, - AdImpression: { wantUntrusted: true }, - DisableShopping: { wantUntrusted: true }, - }, - }, - matches: ["about:shoppingsidebar"], - remoteTypes: ["privilegedabout"], - }, + // Removed ShoppingSidebar. tor-browser#42831. SpeechDispatcher: { parent: { @@ -889,22 +1031,6 @@ let JSWINDOWACTORS = { allFrames: true, }, - ASRouter: { - parent: { - esModuleURI: "resource:///actors/ASRouterParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/ASRouterChild.sys.mjs", - events: { - // This is added so the actor instantiates immediately and makes - // methods available to the page js on load. - DOMDocElementInserted: {}, - }, - }, - matches: ["about:asrouter*", "about:welcome*", "about:privatebrowsing*"], - remoteTypes: ["privilegedabout"], - }, - SwitchDocumentDirection: { child: { esModuleURI: "resource:///actors/SwitchDocumentDirectionChild.sys.mjs", @@ -1522,6 +1648,13 @@ BrowserGlue.prototype = { // handle any UI migration this._migrateUI(); + // Base Browser-specific version of _migrateUI. + this._migrateUIBB(); + + // Handle any TBB-specific migration before showing the UI. Keep after + // _migrateUI to make sure this._isNewProfile has been defined. + this._migrateUITBB(); + if (!Services.prefs.prefHasUserValue(PREF_PDFJS_ISDEFAULT_CACHE_STATE)) { lazy.PdfJs.checkIsDefault(this._isNewProfile); } @@ -1547,10 +1680,10 @@ BrowserGlue.prototype = { lazy.Normandy.init(); } - lazy.SaveToPocket.init(); - lazy.ResetPBMPanel.init(); + lazy.checkHomepageOverride(); + AboutHomeStartupCache.init(); Services.obs.notifyObservers(null, "browser-ui-startup-complete"); @@ -1777,6 +1910,11 @@ BrowserGlue.prototype = { return false; } + // We don't want to mess up with RFP new window / letterboxing machinery. + if (Services.prefs.getBoolPref("privacy.resistFingerprinting", false)) { + return false; + } + let width = getValue("width"); let height = getValue("height"); @@ -1908,8 +2046,6 @@ BrowserGlue.prototype = { // the first browser window has finished initializing _onFirstWindowLoaded: function BG__onFirstWindowLoaded(aWindow) { - lazy.AboutNewTab.init(); - lazy.TabCrashHandler.init(); lazy.ProcessHangMonitor.init(); @@ -1961,6 +2097,12 @@ BrowserGlue.prototype = { lazy.DoHController.init(); + lazy.DragDropFilter.init(); + + lazy.TorProviderBuilder.firstWindowLoaded(); + + ClipboardPrivacy.startup(); + this._firstWindowTelemetry(aWindow); this._firstWindowLoaded(); @@ -2252,10 +2394,12 @@ BrowserGlue.prototype = { () => lazy.PageDataService.uninit(), () => lazy.PageThumbs.uninit(), () => lazy.NewTabUtils.uninit(), - () => lazy.Normandy.uninit(), + () => { + if (AppConstants.MOZ_NORMANDY) { + lazy.Normandy.uninit(); + } + }, () => lazy.RFPHelper.uninit(), - () => lazy.ShoppingUtils.uninit(), - () => lazy.ASRouterNewTabHook.destroy(), () => { if (AppConstants.MOZ_UPDATER) { lazy.UpdateListener.reset(); @@ -2267,6 +2411,7 @@ BrowserGlue.prototype = { Services.fog; }, () => lazy.UrlbarSearchTermsPersistence.uninit(), + () => lazy.OnionAliasStore.uninit(), ]; for (let task of tasks) { @@ -2347,19 +2492,21 @@ BrowserGlue.prototype = { // There is no pref for this add-on because it shouldn't be disabled. const ID = "addons-search-detection@mozilla.com"; - let addon = await lazy.AddonManager.getAddonByID(ID); + try { + let addon = await lazy.AddonManager.getAddonByID(ID); - // first time install of addon and install on firefox update - addon = - (await lazy.AddonManager.maybeInstallBuiltinAddon( - ID, - "2.0.0", - "resource://builtin-addons/search-detection/" - )) || addon; + // first time install of addon and install on firefox update + addon = + (await lazy.AddonManager.maybeInstallBuiltinAddon( + ID, + "2.0.0", + "resource://builtin-addons/search-detection/" + )) || addon; - if (!addon.isActive) { - addon.enable(); - } + if (addon && !addon.isActive) { + addon.enable(); + } + } catch (e) {} }, _monitorHTTPSOnlyPref() { @@ -2966,6 +3113,30 @@ BrowserGlue.prototype = { }, }, + { + task: () => { + if (!lazy.TorConnect.shouldShowTorConnect) { + // we will take this path when the user is using the legacy tor launcher or + // when Tor Browser didn't launch its own tor. + lazy.OnionAliasStore.init(); + } else { + // this path is taken when using about:torconnect, we wait to init + // after we are bootstrapped and connected to tor + const topic = lazy.TorConnectTopics.BootstrapComplete; + let bootstrapObserver = { + observe(aSubject, aTopic) { + if (aTopic === topic) { + lazy.OnionAliasStore.init(); + // we only need to init once, so remove ourselves as an obvserver + Services.obs.removeObserver(this, topic); + } + }, + }; + Services.obs.addObserver(bootstrapObserver, topic); + } + }, + }, + { name: "TabUnloader.init", task: () => { @@ -3079,13 +3250,6 @@ BrowserGlue.prototype = { }, }, - { - name: "ASRouterNewTabHook.createInstance", - task: () => { - lazy.ASRouterNewTabHook.createInstance(lazy.ASRouterDefaultConfig()); - }, - }, - { name: "BackgroundUpdate", condition: AppConstants.MOZ_UPDATE_AGENT, @@ -3189,13 +3353,6 @@ BrowserGlue.prototype = { }, }, - { - name: "ShoppingUtils.init", - task: () => { - lazy.ShoppingUtils.init(); - }, - }, - { // Starts the JSOracle process for ORB JavaScript validation, if it hasn't started already. name: "start-orb-javascript-oracle", @@ -3322,14 +3479,15 @@ BrowserGlue.prototype = { this._addBreachesSyncHandler(); }.bind(this), - function PublicSuffixListInit() { - lazy.PublicSuffixList.init(); - }, - function RemoteSecuritySettingsInit() { lazy.RemoteSecuritySettings.init(); }, + function RemoteSettingsPollChanges() { + // Support clients that use the "sync" event or "remote-settings:changes-poll-end". + lazy.RemoteSettings.pollChanges({ trigger: "timer" }); + }, + function BrowserUsageTelemetryReportProfileCount() { lazy.BrowserUsageTelemetry.reportProfileCount(); }, @@ -4649,6 +4807,156 @@ BrowserGlue.prototype = { Services.prefs.setIntPref("browser.migration.version", UI_VERSION); }, + _migrateUIBB() { + // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override + // for tor-browser#41739. + // Version 2: 14.0a5: Reset the privacy tracking headers preferences since + // the UI is hidden. tor-browser#42777. + // Also, do not set + // dom.security.https_only_mode_send_http_background_request in + // the security level anymore (tor-browser#42149). + // Also, reset security.xfocsp.errorReporting.automatic since we + // hid its neterror checkbox. tor-browser#42653. + // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070. + const MIGRATION_VERSION = 3; + const MIGRATION_PREF = "basebrowser.migration.version"; + // We do not care whether this is a new or old profile, since in version 1 + // we just quickly clear a user preference, which should not do anything to + // new profiles. + // Shall we ever raise the version number and have a watershed, we can add + // a check easily (any version > 0 will be an old profile). + const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0); + if (currentVersion < 1) { + Services.prefs.clearUserPref( + "layout.css.prefers-color-scheme.content-override" + ); + } + if (currentVersion < 2) { + for (const prefName of [ + "privacy.globalprivacycontrol.enabled", + "privacy.donottrackheader.enabled", + // Telemetry preference for if the user changed the value. + "privacy.globalprivacycontrol.was_ever_enabled", + // The next two preferences have no corresponding UI, but are related. + "privacy.globalprivacycontrol.functionality.enabled", + "privacy.globalprivacycontrol.pbmode.enabled", + "dom.security.https_only_mode_send_http_background_request", + "security.xfocsp.errorReporting.automatic", + ]) { + Services.prefs.clearUserPref(prefName); + } + } + if (currentVersion < 3) { + Services.prefs.clearUserPref("general.smoothScroll"); + } + Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION); + }, + + // Use this method for any TBB migration that can be run just before showing + // the UI. + // Anything that critically needs to be migrated earlier should not use this. + _migrateUITBB() { + // Version 1: Tor Browser 12.0. We use it to remove langpacks, after the + // migration to packaged locales. + // Version 2: Tor Browser 13.0/13.0a1: tor-browser#41845. Also, removed some + // torbutton preferences that are not used anymore. + // Version 3: Tor Browser 13.0.7/13.5a3: Remove blockchair + // (tor-browser#42283). + // Version 4: Tor Browser 14.0a4 (2024-09-02): Remove Twitter, Yahoo and + // YouTube search engines (tor-browser#41835). + // Version 5: Tor Browser 14.0a5: Clear user preference for CFR settings + // since we hid the UI (tor-browser#43118). + // Version 6: Tor Browser 14.5a3: Clear preference for TorSettings that is + // no longer used (tor-browser#41921). + const TBB_MIGRATION_VERSION = 6; + const MIGRATION_PREF = "torbrowser.migration.version"; + + // If we decide to force updating users to pass through any version + // following 12.0, we can remove this check, and check only whether + // MIGRATION_PREF has a user value, like Mozilla does. + if (this._isNewProfile) { + // Do not migrate fresh profiles + Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION); + return; + } else if (this._isNewProfile === undefined) { + // If this happens, check if upstream updated their function and do not + // set this member anymore! + console.error("_migrateUITBB: this._isNewProfile is undefined."); + } + + const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0); + const removeLangpacks = async () => { + for (const addon of await AddonManager.getAddonsByTypes(["locale"])) { + await addon.uninstall(); + } + }; + if (currentVersion < 1) { + removeLangpacks().catch(err => { + console.error("Could not remove langpacks", err); + }); + } + if (currentVersion < 2) { + const prefToClear = [ + // tor-browser#41845: We were forcing these value by check the value of + // automatic PBM. We decided not to change + "browser.cache.disk.enable", + "places.history.enabled", + "security.nocertdb", + "permissions.memory_only", + // Old torbutton preferences not used anymore. + "extensions.torbutton.loglevel", + "extensions.torbutton.logmethod", + "extensions.torbutton.pref_fixup_version", + "extensions.torbutton.resize_new_windows", + "extensions.torbutton.startup", + "extensions.torlauncher.prompt_for_locale", + "extensions.torlauncher.loglevel", + "extensions.torlauncher.logmethod", + "extensions.torlauncher.torrc_fixup_version", + ]; + for (const pref of prefToClear) { + if (Services.prefs.prefHasUserValue(pref)) { + Services.prefs.clearUserPref(pref); + } + } + } + const dropAddons = async list => { + for (const id of list) { + try { + const engine = await lazy.AddonManager.getAddonByID(id); + await engine?.uninstall(); + } catch {} + } + }; + if (currentVersion < 3) { + dropAddons([ + "blockchair@search.mozilla.org", + "blockchair-onion@search.mozilla.org", + ]); + } + if (currentVersion < 4) { + dropAddons([ + "twitter@search.mozilla.org", + "yahoo@search.mozilla.org", + "youtube@search.mozilla.org", + ]); + } + if (currentVersion < 5) { + for (const pref of [ + "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", + "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", + ]) { + Services.prefs.clearUserPref(pref); + } + } + + if (currentVersion < 6) { + Services.prefs.clearUserPref("torbrowser.settings.enabled"); + } + + Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION); + }, + async _showUpgradeDialog() { const data = await lazy.OnboardingMessageProvider.getUpgradeMessage(); const { gBrowser } = lazy.BrowserWindowTracker.getTopWindow(); @@ -6324,12 +6632,8 @@ export var AboutHomeStartupCache = { return { pageInputStream: null, scriptInputStream: null }; } - let state = lazy.AboutNewTab.activityStream.store.getState(); - return new Promise(resolve => { - this._cacheDeferred = resolve; - this.log.trace("Parent is requesting cache streams."); - this._procManager.sendAsyncMessage(this.CACHE_REQUEST_MESSAGE, { state }); - }); + this.log.error("Activity Stream is disabled."); + return { pageInputStream: null, scriptInputStream: null }; }, /** diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp index fb633050cbf40bc285b1f7b9c5d82840affe95f0..dca73464b7db5774d21757ecc486a513c8d06409 100644 --- a/browser/components/about/AboutRedirector.cpp +++ b/browser/components/about/AboutRedirector.cpp @@ -15,6 +15,11 @@ #include "mozilla/StaticPrefs_browser.h" #include "mozilla/dom/ContentChild.h" +// For Tor Browser manual +#include "nsTHashSet.h" +#include "mozilla/intl/LocaleService.h" +#include "mozilla/Omnijar.h" + namespace mozilla { namespace browser { @@ -74,12 +79,9 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::IS_SECURE_CHROME_UI}, - {"firefoxview", "chrome://browser/content/firefoxview/firefoxview.html", - nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI | - nsIAboutModule::HIDE_FROM_ABOUTABOUT}, {"policies", "chrome://browser/content/policies/aboutPolicies.html", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, - {"privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.html", + {"privatebrowsing", "about:blank", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS}, @@ -89,18 +91,20 @@ static const RedirEntry kRedirMap[] = { {"rights", "chrome://global/content/aboutRights.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, +#ifndef BASE_BROWSER_VERSION {"robots", "chrome://browser/content/aboutRobots.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT}, - {"sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml", - nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT | - nsIAboutModule::IS_SECURE_CHROME_UI}, - {"shoppingsidebar", "chrome://browser/content/shopping/shopping.html", - nsIAboutModule::URI_MUST_LOAD_IN_CHILD | +#endif + {"rulesets", "chrome://browser/content/rulesets/aboutRulesets.html", + nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT | nsIAboutModule::IS_SECURE_CHROME_UI}, + {"sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml", + nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT | + nsIAboutModule::IS_SECURE_CHROME_UI}, + // Removed about:shoppingsidebar. tor-browser#42831. {"tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, @@ -121,6 +125,7 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, +#ifndef BASE_BROWSER_VERSION {"pocket-saved", "chrome://pocket/content/panels/saved.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | @@ -141,6 +146,7 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, +#endif {"settings", "chrome://browser/content/preferences/preferences.xhtml", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, @@ -155,11 +161,6 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::HIDE_FROM_ABOUTABOUT}, {"restartrequired", "chrome://browser/content/aboutRestartRequired.xhtml", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, - {"protections", "chrome://browser/content/protections.html", - nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | - nsIAboutModule::IS_SECURE_CHROME_UI}, #ifdef MOZ_SELECTABLE_PROFILES {"profilemanager", "chrome://browser/content/profiles/profiles.html", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI | @@ -175,6 +176,12 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS}, #endif + // The correct URI must be obtained by GetManualChromeURI + {"manual", "about:blank", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | + nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | + nsIAboutModule::IS_SECURE_CHROME_UI}, }; static nsAutoCString GetAboutModuleName(nsIURI* aURI) { @@ -191,6 +198,50 @@ static nsAutoCString GetAboutModuleName(nsIURI* aURI) { return path; } +static nsTHashSet<nsCStringHashKey> GetManualLocales() { + nsTHashSet<nsCStringHashKey> locales; + RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::APP); + UniquePtr<nsZipFind> find; + const nsAutoCString prefix("chrome/browser/content/browser/manual/"); + nsAutoCString needle = prefix; + needle.Append("*.html"); + if (NS_SUCCEEDED(zip->FindInit(needle.get(), getter_Transfers(find)))) { + const char* entryName; + uint16_t entryNameLen; + while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) { + // 5 is to remove the final `.html` + const size_t length = entryNameLen - prefix.Length() - 5; + locales.Insert(nsAutoCString(entryName + prefix.Length(), length)); + } + } + return locales; +} + +static nsAutoCString GetManualChromeURI() { + static nsTHashSet<nsCStringHashKey> locales = GetManualLocales(); + + nsAutoCString reqLocale; + intl::LocaleService::GetInstance()->GetAppLocaleAsBCP47(reqLocale); + // Check every time the URL is needed in case the locale has changed. + // It might help also if we start allowing to change language, e.g., with a + // get parameter (see tor-browser#42675). + if (!locales.Contains(reqLocale) && reqLocale.Length() > 2 && + reqLocale[2] == '-') { + // At the moment, codes in our manual output are either 2 letters (en) or + // 5 letters (pt-BR) + reqLocale.SetLength(2); + } + if (!locales.Contains(reqLocale)) { + reqLocale = "en"; + } + + // %s is the language + constexpr char model[] = "chrome://browser/content/manual/%s.html"; + nsAutoCString url; + url.AppendPrintf(model, reqLocale.get()); + return url; +} + NS_IMETHODIMP AboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** result) { @@ -228,7 +279,8 @@ AboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, // enabled about:newtab. Disabled about:newtab page uses fallback. if (path.EqualsLiteral("home") || (StaticPrefs::browser_newtabpage_enabled() && - path.EqualsLiteral("newtab"))) { + path.EqualsLiteral("newtab")) || + path.EqualsLiteral("privatebrowsing")) { nsCOMPtr<nsIAboutNewTabService> aboutNewTabService = do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv); NS_ENSURE_SUCCESS(rv, rv); @@ -244,6 +296,10 @@ AboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, NS_ENSURE_SUCCESS(rv, rv); } + if (path.EqualsLiteral("manual")) { + url = GetManualChromeURI(); + } + // fall back to the specified url in the map if (url.IsEmpty()) { url.AssignASCII(redir.url); @@ -302,6 +358,10 @@ AboutRedirector::GetChromeURI(nsIURI* aURI, nsIURI** chromeURI) { nsAutoCString name = GetAboutModuleName(aURI); + if (name.EqualsLiteral("manual")) { + return NS_NewURI(chromeURI, GetManualChromeURI()); + } + for (const auto& redir : kRedirMap) { if (name.Equals(redir.id)) { return NS_NewURI(chromeURI, redir.url); diff --git a/browser/components/about/components.conf b/browser/components/about/components.conf index 0002130a7a17100f79fd5da1ce87fb0eb5e38195..2d7b4b2a3e77c3a43fb498550ce2c963d023a059 100644 --- a/browser/components/about/components.conf +++ b/browser/components/about/components.conf @@ -13,25 +13,21 @@ pages = [ 'home', 'logins', 'loginsimportreport', - 'firefoxview', + 'manual', 'messagepreview', 'newtab', - 'pocket-home', - 'pocket-saved', - 'pocket-signup', - 'pocket-style-guide', 'policies', 'preferences', 'privatebrowsing', - 'protections', 'profiling', 'reader', 'restartrequired', 'rights', - 'robots', + # Removed 'robots'. tor-browser#42831. + 'rulesets', 'sessionrestore', 'settings', - 'shoppingsidebar', + # Removed 'shoppingsidebar'. tor-browser#42831. 'tabcrashed', 'unloads', 'welcome', diff --git a/browser/components/aboutlogins/AboutLoginsParent.sys.mjs b/browser/components/aboutlogins/AboutLoginsParent.sys.mjs index 91967e381ebb7ef806fbc3c047e4538eb49239ae..514620cdec7bc8368e2610c7574586a1af93e3d8 100644 --- a/browser/components/aboutlogins/AboutLoginsParent.sys.mjs +++ b/browser/components/aboutlogins/AboutLoginsParent.sys.mjs @@ -49,6 +49,7 @@ ChromeUtils.defineLazyGetter(lazy, "AboutLoginsL10n", () => { const ABOUT_LOGINS_ORIGIN = "about:logins"; const AUTH_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes const PRIMARY_PASSWORD_NOTIFICATION_ID = "primary-password-login-required"; +const NOCERTDB_PREF = "security.nocertdb"; // about:logins will always use the privileged content process, // even if it is disabled for other consumers such as about:newtab. @@ -320,6 +321,7 @@ export class AboutLoginsParent extends JSWindowActorParent { Services.policies.isAllowed("profileImport") && AppConstants.platform != "linux", preselectedLogin: this.preselectedLogin, + canCreateLogins: !Services.prefs.getBoolPref(NOCERTDB_PREF, false), }); await AboutLogins.sendAllLoginRelatedObjects( diff --git a/browser/components/aboutlogins/content/aboutLogins.css b/browser/components/aboutlogins/content/aboutLogins.css index 6b4a16451c19038560966a6915c91ba6d946372d..f49abe6da8b4335033192d7216e1596d58b80fe5 100644 --- a/browser/components/aboutlogins/content/aboutLogins.css +++ b/browser/components/aboutlogins/content/aboutLogins.css @@ -62,6 +62,11 @@ login-item[data-editing="true"] + login-intro, display: none; } +/* Do not promote Mozilla Sync. */ +login-intro { + display: none !important; +} + .heading-wrapper { display: flex; justify-content: center; diff --git a/browser/components/aboutlogins/content/aboutLogins.mjs b/browser/components/aboutlogins/content/aboutLogins.mjs index 6287850ee25a0d9faa0e6b0d67f26949b87bb5f9..d4a8fde8dd71838aed385515fb5479ab8e8cad4f 100644 --- a/browser/components/aboutlogins/content/aboutLogins.mjs +++ b/browser/components/aboutlogins/content/aboutLogins.mjs @@ -24,6 +24,9 @@ const gElements = { ".menuitem-remove-all-logins" ); }, + get createNewLoginButton() { + return this.loginList.shadowRoot.querySelector(".create-login-button"); + }, }; let numberOfLogins = 0; @@ -129,6 +132,9 @@ window.addEventListener("AboutLoginsChromeToContent", event => { gElements.loginList.setSortDirection(event.detail.value.selectedSort); document.documentElement.classList.add("initialized"); gElements.loginList.classList.add("initialized"); + if (!event.detail.value.canCreateLogins) { + gElements.createNewLoginButton.disabled = true; + } break; } case "ShowLoginItemError": { diff --git a/browser/components/aboutlogins/content/components/fxaccounts-button.css b/browser/components/aboutlogins/content/components/fxaccounts-button.css index a6d136ff70642b5cc1bec76b5494b7d278e19909..86aff6c126f3d71291c7071c9b0798233d450883 100644 --- a/browser/components/aboutlogins/content/components/fxaccounts-button.css +++ b/browser/components/aboutlogins/content/components/fxaccounts-button.css @@ -8,6 +8,11 @@ align-items: center; } +/* Do not promote Mozilla Sync. */ +.logged-out-view { + display: none !important; +} + .fxaccounts-extra-text { /* Only show at most 3 lines of text to limit the text from overflowing the header. */ diff --git a/browser/components/abouttor/AboutTorChild.sys.mjs b/browser/components/abouttor/AboutTorChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..202803a6f84fa1ba7d0391d540145ebf452247cd --- /dev/null +++ b/browser/components/abouttor/AboutTorChild.sys.mjs @@ -0,0 +1,27 @@ +/** + * Actor child class for the about:tor page. + */ +export class AboutTorChild extends JSWindowActorChild { + handleEvent(event) { + switch (event.type) { + case "DOMContentLoaded": + this.sendQuery("AboutTor:GetInitialData").then(data => { + const initialDataEvent = new this.contentWindow.CustomEvent( + "InitialData", + { detail: Cu.cloneInto(data, this.contentWindow) } + ); + this.contentWindow.dispatchEvent(initialDataEvent); + }); + break; + case "SubmitSearchOnionize": + this.sendAsyncMessage("AboutTor:SetSearchOnionize", !!event.detail); + break; + case "L10nMutationsFinished": + // Pass on chrome-only event for completed localization to content. + this.contentWindow.dispatchEvent( + new this.contentWindow.CustomEvent("L10nMutationsFinished") + ); + break; + } + } +} diff --git a/browser/components/abouttor/AboutTorMessage.sys.mjs b/browser/components/abouttor/AboutTorMessage.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..dd215599f3aa0af5db66fffcab964747c3265a2c --- /dev/null +++ b/browser/components/abouttor/AboutTorMessage.sys.mjs @@ -0,0 +1,43 @@ +// about:tor should cycle its displayed message on each load, this keeps track +// of which message to show globally. + +/** + * @typedef {object} MessageData + * + * @property {string} [updateVersion] - The update version to show. If this is + * defined, the update message should be shown. + * @property {string} [updateURL] - The update URL to use when updateVersion is + * given. + * @property {integer} [number] - The number of the message to show, when + * updateVersion is not given. This always increases, so the caller should + * take its remainder to cycle messages. + */ +export const AboutTorMessage = { + // NOTE: We always start the count at 0 with every session so that the first + // message is always shown first. + _count: 0, + + /** + * Get details about which message to show on the next about:tor page. + * + * @returns {MessageData} Details about the message to show. + */ + getNext() { + const shouldNotifyPref = "torbrowser.post_update.shouldNotify"; + if (Services.prefs.getBoolPref(shouldNotifyPref, false)) { + Services.prefs.clearUserPref(shouldNotifyPref); + return { + updateVersion: Services.prefs.getCharPref( + "browser.startup.homepage_override.torbrowser.version" + ), + updateURL: + Services.prefs.getCharPref("torbrowser.post_update.url", "") || + Services.urlFormatter.formatURLPref("startup.homepage_override_url"), + }; + } + const number = this._count; + // Assume the count will not exceed Number.MAX_SAFE_INTEGER. + this._count++; + return { number }; + }, +}; diff --git a/browser/components/abouttor/AboutTorParent.sys.mjs b/browser/components/abouttor/AboutTorParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..ad11331f31bbbde5d36a392e2c710c729fdb515b --- /dev/null +++ b/browser/components/abouttor/AboutTorParent.sys.mjs @@ -0,0 +1,30 @@ +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + AboutTorMessage: "resource:///modules/AboutTorMessage.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", +}); + +/** + * Actor parent class for the about:tor page. + */ +export class AboutTorParent extends JSWindowActorParent { + receiveMessage(message) { + const onionizePref = "torbrowser.homepage.search.onionize"; + switch (message.name) { + case "AboutTor:GetInitialData": + return Promise.resolve({ + torConnectEnabled: lazy.TorConnect.enabled, + messageData: lazy.AboutTorMessage.getNext(), + isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release", + searchOnionize: Services.prefs.getBoolPref(onionizePref, false), + }); + case "AboutTor:SetSearchOnionize": + Services.prefs.setBoolPref(onionizePref, message.data); + break; + } + return undefined; + } +} diff --git a/browser/components/abouttor/HomepageOverride.sys.mjs b/browser/components/abouttor/HomepageOverride.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..2d653deea24d2993bf4225e68b0b0fac76607820 --- /dev/null +++ b/browser/components/abouttor/HomepageOverride.sys.mjs @@ -0,0 +1,18 @@ +// FIXME: Eventually drop this entirely. It is only known to be used by Whonix, +// which could set their default home page using "browser.startup.homepage". +// See https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/13835#note_2928881 +export function checkHomepageOverride() { + // tor-browser#13835: Allow overriding the default homepage by setting a + // custom environment variable. + if (Services.env.exists("TOR_DEFAULT_HOMEPAGE")) { + const prefName = "browser.startup.homepage"; + // if the user has set this value in a previous installation, don't + // override it + if (!Services.prefs.prefHasUserValue(prefName)) { + Services.prefs.setCharPref( + prefName, + Services.env.get("TOR_DEFAULT_HOMEPAGE") + ); + } + } +} diff --git a/browser/components/abouttor/content/1f4e3-megaphone.svg b/browser/components/abouttor/content/1f4e3-megaphone.svg new file mode 100644 index 0000000000000000000000000000000000000000..f8c09e7dc16d457708398f3234b4630fe2645076 --- /dev/null +++ b/browser/components/abouttor/content/1f4e3-megaphone.svg @@ -0,0 +1,3 @@ +<!-- FROM https://github.com/twitter/twemoji + - licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/ --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3B88C3" d="M14 19c-3.314 0-6 2.687-6 6s2.686 6 6 6 6-2.687 6-6-2.687-6-6-6zm0 10c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z"/><path fill="#55ACEE" d="M1.783 14.023v.02C.782 14.263 0 15.939 0 18s.782 3.737 1.783 3.956v.021l28.701 7.972V6.064L1.783 14.023z"/><ellipse fill="#269" cx="31" cy="18" rx="5" ry="12"/></svg> diff --git a/browser/components/abouttor/content/26a1-high-voltage.svg b/browser/components/abouttor/content/26a1-high-voltage.svg new file mode 100644 index 0000000000000000000000000000000000000000..762209a2f3421bc9c23e88f4b6d875a944a51a16 --- /dev/null +++ b/browser/components/abouttor/content/26a1-high-voltage.svg @@ -0,0 +1,3 @@ +<!-- FROM https://github.com/twitter/twemoji + - licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/ --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M32.938 15.651C32.792 15.26 32.418 15 32 15H19.925L26.89 1.458c.219-.426.106-.947-.271-1.243C26.437.071 26.218 0 26 0c-.233 0-.466.082-.653.243L18 6.588 3.347 19.243c-.316.273-.43.714-.284 1.105S3.582 21 4 21h12.075L9.11 34.542c-.219.426-.106.947.271 1.243.182.144.401.215.619.215.233 0 .466-.082.653-.243L18 29.412l14.653-12.655c.317-.273.43-.714.285-1.106z"/></svg> diff --git a/browser/components/abouttor/content/2728-sparkles.svg b/browser/components/abouttor/content/2728-sparkles.svg new file mode 100644 index 0000000000000000000000000000000000000000..057cdbb6742c642e09377073d5cf6242ee7853a2 --- /dev/null +++ b/browser/components/abouttor/content/2728-sparkles.svg @@ -0,0 +1,3 @@ +<!-- FROM https://github.com/twitter/twemoji + - licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/ --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M34.347 16.893l-8.899-3.294-3.323-10.891c-.128-.42-.517-.708-.956-.708-.439 0-.828.288-.956.708l-3.322 10.891-8.9 3.294c-.393.146-.653.519-.653.938 0 .418.26.793.653.938l8.895 3.293 3.324 11.223c.126.424.516.715.959.715.442 0 .833-.291.959-.716l3.324-11.223 8.896-3.293c.391-.144.652-.518.652-.937 0-.418-.261-.792-.653-.938z"/><path fill="#FFCC4D" d="M14.347 27.894l-2.314-.856-.9-3.3c-.118-.436-.513-.738-.964-.738-.451 0-.846.302-.965.737l-.9 3.3-2.313.856c-.393.145-.653.52-.653.938 0 .418.26.793.653.938l2.301.853.907 3.622c.112.444.511.756.97.756.459 0 .858-.312.97-.757l.907-3.622 2.301-.853c.393-.144.653-.519.653-.937 0-.418-.26-.793-.653-.937zM10.009 6.231l-2.364-.875-.876-2.365c-.145-.393-.519-.653-.938-.653-.418 0-.792.26-.938.653l-.875 2.365-2.365.875c-.393.146-.653.52-.653.938 0 .418.26.793.653.938l2.365.875.875 2.365c.146.393.52.653.938.653.418 0 .792-.26.938-.653l.875-2.365 2.365-.875c.393-.146.653-.52.653-.938 0-.418-.26-.792-.653-.938z"/></svg> diff --git a/browser/components/abouttor/content/2764-red-heart.svg b/browser/components/abouttor/content/2764-red-heart.svg new file mode 100644 index 0000000000000000000000000000000000000000..b4887d856200a90fdb88357983a7b8801d05b96f --- /dev/null +++ b/browser/components/abouttor/content/2764-red-heart.svg @@ -0,0 +1,3 @@ +<!-- FROM https://github.com/twitter/twemoji + - licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/ --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z"/></svg> diff --git a/browser/components/abouttor/content/aboutTor.css b/browser/components/abouttor/content/aboutTor.css new file mode 100644 index 0000000000000000000000000000000000000000..5b4c8c550561fbe23832badb4af0fb6f67a898b7 --- /dev/null +++ b/browser/components/abouttor/content/aboutTor.css @@ -0,0 +1,239 @@ +@import url("chrome://global/skin/tor-colors.css"); +@import url("chrome://global/skin/onion-pattern.css"); + +body { + margin: 0; + min-height: 100vh; + display: grid; + --form-max-width: 600px; + grid-template: + /* Start space: unfilled. */ + ". . ." 1fr + "heading heading heading" auto + "tor-check tor-check tor-check" auto + ". form ." min-content + "message message message" auto + /* End space: unfilled. + * Reserve 150px for background image. + * NOTE: Since the body has "auto" height, the other "1fr" flex row will + * not shrink to zero, but will instead shrink to a minimum size of + * 75px = (150px * 1fr / 2fr) */ + ". . ." minmax(var(--onion-pattern-height), 2fr) + /* NOTE: "form" will be given a maximum width of --form-max-width. */ + / 1fr minmax(max-content, var(--form-max-width)) 1fr; + justify-items: center; + padding-inline: 20px; +} + +body:not(.initialized) { + /* Hide the components before the page is initialized. + * NOTE: The layout can still be adjusted or measured in this time since we + * use visibility rather than `display: none`. */ + visibility: hidden; +} + +h1 { + grid-area: heading; + display: flex; + align-items: center; + gap: 16px; + font-size: 40px; + margin-block-start: 0; + margin-block-end: 40px; + margin-inline: 20px; +} + +#tor-browser-logo { + height: 80px; + flex: 0 0 auto; +} + +body.is-testing #tor-browser-home-heading-stable { + display: none; +} + +body:not(.is-testing) #tor-browser-home-heading-testing { + display: none; +} + +#tor-check { + grid-area: tor-check; + max-width: var(--form-max-width); + box-sizing: border-box; + display: flex; + gap: 10px; + align-items: center; + padding-inline: 23px; + padding-block: 11px; + border: 1px solid var(--in-content-box-border-color); + border-radius: 8px; + background-color: var(--in-content-box-info-background); + margin-block-start: 0; + margin-block-end: 30px; +} + +body:not(.show-tor-check) #tor-check { + display: none; +} + +#tor-check-icon { + flex: 0 0 auto; + width: 16px; + height: 16px; + -moz-context-properties: fill; + fill: currentColor; +} + +.home-message:not(.shown-message) { + display: none; +} + +.home-message { + grid-area: message; + font-weight: 400; + text-align: center; + margin-block-start: 1.6em; + margin-block-end: 1em; +} + +.message-emoji { + height: 1em; + vertical-align: sub; + margin-inline-end: 0.3em; +} + +#search-form { + grid-area: form; + /* Occupy the entire "form" block. */ + justify-self: stretch; + background: var(--in-content-page-background); + display: flex; + align-items: stretch; + /* Padding between elements. */ + --form-padding: 12px; + --form-border-width: 1px; + /* Padding between elements and the parent's border edge. */ + --form-outer-padding: calc(var(--form-padding) - var(--form-border-width)); + --form-radius: 7px; + --logo-size: 30px; + border-radius: calc(var(--form-radius) + var(--form-border-width)); + border-width: var(--form-border-width); + border-style: solid; + border-color: var(--in-content-box-border-color); +} + +#search-form:has(#search-input:focus-visible) { + outline: var(--focus-outline); +} + +#dax-logo { + width: var(--logo-size); + flex: 0 0 auto; + align-self: center; + margin-inline-start: var(--form-outer-padding); + /* Does not occupy any layout width. */ + margin-inline-end: calc(-1 * (var(--logo-size) + var(--form-outer-padding))) +} + +#search-input { + flex: 1 0 auto; + min-width: 200px; + min-height: var(--logo-size); + box-sizing: content-box; + margin: 0; + padding-block: var(--form-outer-padding); + padding-inline-end: var(--form-padding); + padding-inline-start: calc( + var(--form-outer-padding) + var(--logo-size) /* logo */ + + var(--form-padding) /* padding after logo. */ + ); + /* Make sure clickable area does not extend beyond the form's border. */ + border-start-start-radius: var(--form-radius); + border-end-start-radius: var(--form-radius); + border-start-end-radius: 0; + border-end-end-radius: 0; + /* Focus and outline styling move to the parent. */ + background: none; + border: none; + outline: none; +} + +#onionize-toggle { + flex: 0 0 auto; + font-weight: 500; + justify-content: center; + padding-block: var(--form-outer-padding); + padding-inline-end: var(--form-outer-padding); + border-start-end-radius: var(--form-radius); + border-end-end-radius: var(--form-radius); + border-start-start-radius: 0; + border-end-start-radius: 0; + padding-inline-start: 0; + /* Non-clickable gap between input and toggle. */ + margin-inline-start: 0.5em; +} + +@media not ((prefers-contrast) or (forced-colors)) { + /* Force the page to follow the same Tor theme, regardless of + * prefers-color-scheme. */ + + /* On dark background */ + :root { + background-color: #2C0449; + --focus-outline-color: var(--tor-focus-outline-color-dark); + --focus-outline: var(--focus-outline-width) solid var(--focus-outline-color); + --in-content-focus-outline-color: var(--focus-outline-color); + --in-content-focus-outline: var(--focus-outline); + --onion-pattern-stroke-color: #3e0663; + --onion-pattern-fill-color: #350556; + } + + #tor-check { + background-color: #1f0333; + border-color: transparent; + } + + body > :not(#search-form) { + /* Same as --in-content-page-color when "prefers-color-scheme: dark" */ + --in-content-page-color-dark: var(--color-gray-05); + color: var(--in-content-page-color-dark); + --link-color: var(--tor-link-color-dark); + --link-color-hover: var(--tor-link-color-hover-dark); + --link-color-active: var(--tor-link-color-active-dark); + } + + #search-form { + /* Use light color for background and moz-toggle shadow root. */ + color-scheme: light; + /* Same as --in-content-page-color when "prefers-color-scheme: light" */ + --in-content-page-color-light: var(--color-gray-100); + color: var(--in-content-page-color-light); + border-color: transparent; + } + + #search-form:has(#search-input:focus-visible) { + /* Use a light-themed inner-border to contrast with the dark-themed + * focus outline. */ + border-color: var(--tor-focus-outline-color-light); + } + + #search-form.onionized-search:has(#search-input:not(:focus-visible)) { + box-shadow: 0 4px 40px #9400ff66, 0 4px 16px #9400ff33; + } + + /* Light background. */ + #search-form > * { + --focus-outline-color: var(--tor-focus-outline-color-light); + --focus-outline: var(--focus-outline-width) solid var(--focus-outline-color); + --in-content-focus-outline-color: var(--focus-outline-color); + --in-content-focus-outline: var(--focus-outline); + /* Variables used for --toggle- variables. */ + --color-accent-primary: var(--tor-button-background-color-light); + --color-accent-primary-hover: var(--tor-button-background-color-hover-light); + --color-accent-primary-active: var(--tor-button-background-color-active-light); + } + + #search-form.onionized-search #onionize-toggle { + color: var(--tor-link-color-light); + } +} diff --git a/browser/components/abouttor/content/aboutTor.html b/browser/components/abouttor/content/aboutTor.html new file mode 100644 index 0000000000000000000000000000000000000000..4801706f40d61e3af249bcba08deb304856d55ae --- /dev/null +++ b/browser/components/abouttor/content/aboutTor.html @@ -0,0 +1,136 @@ +<!DOCTYPE html> + +<html> + <head> + <meta + http-equiv="Content-Security-Policy" + content="default-src chrome:; object-src 'none'" + /> + <title data-l10n-id="newtab-page-title"></title> + <link + rel="icon" + type="image/png" + href="chrome://branding/content/icon32.png" + /> + <!-- We need common.css to get styling for the moz-toggle. --> + <link rel="stylesheet" href="chrome://global/skin/in-content/common.css" /> + <link + rel="stylesheet" + href="chrome://browser/content/abouttor/aboutTor.css" + /> + + <link rel="localization" href="browser/newtab/newtab.ftl" /> + <link rel="localization" href="toolkit/global/tor-browser.ftl" /> + + <script + type="module" + src="chrome://global/content/elements/moz-toggle.mjs" + ></script> + <script src="chrome://browser/content/abouttor/aboutTor.js"></script> + </head> + <body class="onion-pattern-background"> + <h1> + <img + id="tor-browser-logo" + alt="" + src="chrome://branding/content/about-logo.svg" + /> + <span + id="tor-browser-home-heading-stable" + data-l10n-id="tor-browser-home-heading-stable" + ></span> + <span + id="tor-browser-home-heading-testing" + data-l10n-id="tor-browser-home-heading-testing" + ></span> + </h1> + <p id="tor-check"> + <img + id="tor-check-icon" + alt="" + src="chrome://global/skin/icons/info.svg" + /> + <span data-l10n-id="tor-browser-home-tor-check-warning"> + <a + data-l10n-name="tor-check-link" + href="https://check.torproject.org/" + target="_blank" + ></a> + </span> + </p> + <form id="search-form" method="get" rel="noreferrer"> + <img + id="dax-logo" + alt="" + src="chrome://browser/content/abouttor/dax-logo.svg" + /> + <input + id="search-input" + name="q" + autocomplete="off" + type="text" + data-l10n-id="tor-browser-home-duck-duck-go-input" + /> + <moz-toggle + id="onionize-toggle" + data-l10n-id="tor-browser-home-onionize-toggle" + data-l10n-attrs="label" + ></moz-toggle> + </form> + <p id="home-message-updated" class="home-message"> + <img + class="message-emoji" + alt="" + src="chrome://browser/content/abouttor/2728-sparkles.svg" + /> + <span> + <a data-l10n-name="update-link" target="_blank"></a> + </span> + </p> + <p class="home-message home-message-rotating-stable"> + <span data-l10n-id="tor-browser-home-message-introduction"></span> + </p> + <p class="home-message home-message-rotating-stable"> + <img + class="message-emoji" + alt="" + src="chrome://browser/content/abouttor/2764-red-heart.svg" + /> + <span data-l10n-id="tor-browser-home-message-donate"> + <a + data-l10n-name="donate-link" + href="https://donate.torproject.org" + target="_blank" + ></a> + </span> + </p> + <p class="home-message home-message-rotating-stable"> + <img + class="message-emoji" + alt="" + src="chrome://browser/content/abouttor/1f4e3-megaphone.svg" + /> + <span data-l10n-id="tor-browser-home-message-news"> + <a + data-l10n-name="news-link" + href="https://newsletter.torproject.org" + target="_blank" + ></a> + </span> + </p> + <p class="home-message home-message-rotating-testing"> + <img + class="message-emoji" + alt="" + src="chrome://browser/content/abouttor/26a1-high-voltage.svg" + /> + <span data-l10n-id="tor-browser-home-message-testing"> + <a + data-l10n-name="learn-more-link" + href="https://community.torproject.org/user-research/become-tester/" + target="_blank" + ></a> + </span> + </p> + </body> +</html> diff --git a/browser/components/abouttor/content/aboutTor.js b/browser/components/abouttor/content/aboutTor.js new file mode 100644 index 0000000000000000000000000000000000000000..ee924f1abcdadc383e35e818f115a269fc7a625e --- /dev/null +++ b/browser/components/abouttor/content/aboutTor.js @@ -0,0 +1,180 @@ +"use strict"; + +const SearchWidget = { + _initialized: false, + _initialOnionize: false, + + /** + * Initialize the search form elements. + */ + init() { + this._initialized = true; + + this.searchForm = document.getElementById("search-form"); + this.onionizeToggle = document.getElementById("onionize-toggle"); + this.onionizeToggle.pressed = this._initialOnionize; + this._updateOnionize(); + this.onionizeToggle.addEventListener("toggle", () => + this._updateOnionize() + ); + + // If the user submits, save the onionize search state for the next about:tor + // page. + this.searchForm.addEventListener("submit", () => { + dispatchEvent( + new CustomEvent("SubmitSearchOnionize", { + detail: this.onionizeToggle.pressed, + bubbles: true, + }) + ); + }); + + // By default, Enter on the onionizeToggle will toggle the button rather + // than submit the <form>. + // Moreover, our <form> has no submit button, so can only be submitted by + // pressing Enter. + // For keyboard users, Space will also toggle the form. We do not want to + // require users to have to Tab back to the search input in order to press + // Enter to submit the form. + // For mouse users, clicking the toggle button will give it focus, so they + // would have to Tab back or click the search input in order to submit the + // form. + // So we want to intercept the Enter keydown event to submit the form. + this.onionizeToggle.addEventListener( + "keydown", + event => { + if (event.key !== "Enter") { + return; + } + event.preventDefault(); + event.stopPropagation(); + this.searchForm.requestSubmit(); + }, + { capture: true } + ); + }, + + _updateOnionize() { + // Change submit URL based on the onionize toggle. + this.searchForm.action = this.onionizeToggle.pressed + ? "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion" + : "https://duckduckgo.com"; + this.searchForm.classList.toggle( + "onionized-search", + this.onionizeToggle.pressed + ); + }, + + /** + * Set what the "Onionize" toggle state. + * + * @param {boolean} state - Whether the "Onionize" toggle should be switched + * on. + */ + setOnionizeState(state) { + if (!this._initialized) { + this._initialOnionize = state; + return; + } + this.onionizeToggle.pressed = state; + this._updateOnionize(); + }, +}; + +const MessageArea = { + _initialized: false, + _messageData: null, + _isStable: null, + _torConnectEnabled: null, + + /** + * Initialize the message area and heading once elements are available. + */ + init() { + this._initialized = true; + this._update(); + }, + + /** + * Set the message data and stable release flag. + * + * @param {MessageData} messageData - The message data, indicating which + * message to show. + * @param {boolean} isStable - Whether this is the stable release version. + * @param {boolean} torConnectEnabled - Whether TorConnect is enabled, and + * therefore the Tor process was configured with about:torconnect. + */ + setMessageData(messageData, isStable, torConnectEnabled) { + this._messageData = messageData; + this._isStable = isStable; + this._torConnectEnabled = torConnectEnabled; + this._update(); + }, + + _update() { + if (!this._initialized) { + return; + } + + document + .querySelector(".home-message.shown-message") + ?.classList.remove("shown-message"); + + if (!this._messageData) { + return; + } + + // Set heading. + document.body.classList.toggle("is-testing", !this._isStable); + + document.body.classList.toggle("show-tor-check", !this._torConnectEnabled); + + const { updateVersion, updateURL, number } = this._messageData; + + if (updateVersion) { + const updatedElement = document.getElementById("home-message-updated"); + updatedElement.querySelector("a").href = updateURL; + document.l10n.setAttributes( + updatedElement.querySelector("span"), + "tor-browser-home-message-updated", + { version: updateVersion } + ); + updatedElement.classList.add("shown-message"); + } else { + const messageElements = document.querySelectorAll( + this._isStable + ? ".home-message-rotating-stable" + : ".home-message-rotating-testing" + ); + messageElements[number % messageElements.length].classList.add( + "shown-message" + ); + } + + // In the case where we set the update message, we are still waiting for the + // l10n message to complete. We wait until then before showing the content. + if (document.hasPendingL10nMutations) { + window.addEventListener( + "L10nMutationsFinished", + () => { + document.body.classList.add("initialized"); + }, + { once: true } + ); + } else { + document.body.classList.add("initialized"); + } + }, +}; + +window.addEventListener("DOMContentLoaded", () => { + SearchWidget.init(); + MessageArea.init(); +}); + +window.addEventListener("InitialData", event => { + const { torConnectEnabled, isStable, searchOnionize, messageData } = + event.detail; + SearchWidget.setOnionizeState(!!searchOnionize); + MessageArea.setMessageData(messageData, !!isStable, !!torConnectEnabled); +}); diff --git a/browser/components/abouttor/content/dax-logo.svg b/browser/components/abouttor/content/dax-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..94ad7c356329ff46a9b0e7403ff2d8c8b0f090d8 --- /dev/null +++ b/browser/components/abouttor/content/dax-logo.svg @@ -0,0 +1 @@ +<svg width="120" height="120" viewbox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle id="a" cx="50.833" cy="50.833" r="50.25"/><linearGradient x1="3.084%" y1="49.368%" x2="100.592%" y2="49.368%" id="c"><stop stop-color="#6176B9" offset=".56%"/><stop stop-color="#394A9F" offset="69.1%"/></linearGradient><linearGradient x1="-.006%" y1="49.006%" x2="98.932%" y2="49.006%" id="d"><stop stop-color="#6176B9" offset=".56%"/><stop stop-color="#394A9F" offset="69.1%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><circle fill="#FFF" cx="60" cy="60" r="57.5"/><ellipse fill="#DE5833" cx="60" cy="60" rx="50.25" ry="50.25"/><path d="M60 120C26.917 120 0 93.083 0 60S26.917 0 60 0s60 26.917 60 60-26.917 60-60 60zM60 4.917C29.667 4.917 4.917 29.583 4.917 60c0 30.333 24.666 55.083 55.083 55.083 30.417 0 55.083-24.666 55.083-55.083 0-30.333-24.75-55.083-55.083-55.083z" fill="#DE5833"/><g transform="translate(9.167 9.167)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><use fill="#DE5833" xlink:href="#a"/><g mask="url(#b)"><path d="M71.917 127.25c-1.75-8.25-12.25-27.167-16.334-35.083-3.916-7.917-7.916-19.084-6.083-26.417.417-1.417-3.333-11.417-2.333-12 8.5-5.5 10.666.583 14-1.75 1.75-1.167 4.166 1 4.75-1 2.166-7.667-2.917-20.917-8.834-26.583-2-2-4.75-3.167-8.083-3.75-1.167-1.75-3.333-3.334-6.083-4.917-3.167-1.75-10.25-3.917-13.834-4.5-2.583-.417-3.166.167-4.166.417 1 0 5.75 2.333 6.666 2.583-1 .583-3.583 0-5.333.75-.75.417-1.583 2-1.583 2.583 4.916-.583 12.583 0 17.166 2-3.583.417-9.083.75-11.416 2.167-6.917 3.583-9.834 12-8.084 22.25 1.75 10.083 9.834 47.083 12.25 59.333 2.584 12.25-5.5 20.334-10.416 22.5l5.5.417-1.75 3.917c6.5.75 13.833-1.417 13.833-1.417-1.417 3.917-11.25 5.5-11.25 5.5s4.75 1.417 12.25-1.417c7.667-2.916 12.25-4.75 12.25-4.75l7.5 9.417 2.917-6.917 6.916 7.25c-.25-.5 1.334-2.25-.416-10.583z" fill="#D5D7D8"/><path d="M74.083 125.5c-1.75-8.25-12.25-27.167-16.333-35.083C53.833 82.5 49.833 71.333 51.667 64c.416-1.417.416-6.667 1.416-7.5 8.5-5.5 7.917-.167 11.25-2.583 1.75-1.167 3.167-2.75 3.75-4.917 2.167-7.667-2.916-20.917-8.833-26.583-2-2-4.75-3.167-8.083-3.75-1.167-1.75-3.334-3.334-6.084-4.917-5.333-2.917-12-3.917-18.333-2.917 1 0 3.333 2.167 4.167 2.334-1.417 1-5.084.75-5.084 2.916 4.917-.416 10.25.167 15 2.334-3.583.416-6.916 1.416-9.25 2.583-6.916 3.583-8.666 10.833-6.916 20.917C26.417 52 34.5 89 36.917 101.25c2.583 12.25-5.5 20.333-10.417 22.5l5.5.417-1.75 3.916c6.5.75 13.833-1.416 13.833-1.416-1.416 3.916-11.25 5.5-11.25 5.5s4.75 1.416 12.25-1.417c7.667-2.917 12.25-4.75 12.25-4.75l3.584 9.417 6.916-6.917 2.917 7.25c-.417 0 5.083-1.75 3.333-10.25z" fill="#FFF"/><path d="M32.5 42.583c0-2.166 1.75-3.75 3.75-3.75 2.167 0 3.75 1.75 3.75 3.75 0 2.167-1.75 3.75-3.75 3.75-2.167 0-3.75-1.583-3.75-3.75z" fill="#2D4F8E"/><path d="M36.833 41.167c0-.584.417-1 1-1 .584 0 1 .416 1 1 0 .583-.416 1-1 1-.416 0-1-.417-1-1z" fill="#FFF"/><path d="M58.333 40.167c0-1.75 1.417-3.334 3.334-3.334 1.75 0 3.333 1.417 3.333 3.334 0 1.75-1.417 3.333-3.333 3.333-1.75.083-3.334-1.333-3.334-3.333z" fill="#2D4F8E"/><path d="M62.25 39.167c0-.417.417-.75.75-.75.417 0 .75.416.75.75 0 .416-.417.75-.75.75-.333.083-.75-.334-.75-.75z" fill="#FFF"/><path d="M15.583 21.5s-2.916-1.417-5.75.417c-2.75 1.75-2.75 3.583-2.75 3.583S5.5 22.167 9.417 20.583c4.416-1.583 6.166.917 6.166.917z" fill="url(#c)" transform="translate(21.667 10)"/><path d="M42 21.333s-2-1.166-3.75-1.166c-3.333 0-4.167 1.583-4.167 1.583s.584-3.583 4.75-2.75c2.334.167 3.167 2.333 3.167 2.333z" fill="url(#d)" transform="translate(21.667 10)"/><path d="M47.917 57.167c.416-2.334 6.333-6.667 10.416-6.917 4.167-.167 5.5-.167 9.084-1C71 48.5 80 46.083 82.583 44.917c2.584-1.167 13.167.583 5.75 4.75-3.166 1.75-12 5.083-18.333 7.083-6.333 1.75-10.083-1.75-12 1.417-1.583 2.333-.417 5.75 7.083 6.5 10.084 1 19.667-4.5 20.667-1.584 1 2.917-8.667 6.5-14.583 6.667-5.917.167-17.917-3.917-19.667-5.083-1.833-1.584-4.25-4.417-3.583-7.5z" fill="#FDD20A"/></g></g><path d="M61.583 94.917s-14.166-7.5-14.416-4.5C47 93.583 47.167 106 48.75 107c1.583 1 13.417-6.083 13.417-6.083l-.584-6zm5.5-.667S76.75 87 78.917 87.333c2.166.417 2.583 15.584.75 16.334-1.917.833-13-3.667-13-3.667l.416-5.75z" fill="#65BC46"/><path d="M58.25 95.667c0 4.916-.75 7.083 1.417 7.5 2.166.416 6.083 0 7.5-1 1.416-1 .166-7.25-.167-8.5-.667-1.167-8.75-.167-8.75 2z" fill="#43A244"/><path d="M59 94.5c0 4.917-.75 7.083 1.417 7.5 2.166.417 6.083 0 7.5-1 1.416-1 .166-7.25-.167-8.5-.5-1-8.75-.167-8.75 2z" fill="#65BC46"/></g></svg> \ No newline at end of file diff --git a/browser/components/abouttor/jar.mn b/browser/components/abouttor/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..c8f783d2e0f94df5961297ad5d86ea6b1713aa31 --- /dev/null +++ b/browser/components/abouttor/jar.mn @@ -0,0 +1,9 @@ +browser.jar: + content/browser/abouttor/aboutTor.css (content/aboutTor.css) + content/browser/abouttor/aboutTor.js (content/aboutTor.js) + content/browser/abouttor/aboutTor.html (content/aboutTor.html) + content/browser/abouttor/dax-logo.svg (content/dax-logo.svg) + content/browser/abouttor/1f4e3-megaphone.svg (content/1f4e3-megaphone.svg) + content/browser/abouttor/26a1-high-voltage.svg (content/26a1-high-voltage.svg) + content/browser/abouttor/2728-sparkles.svg (content/2728-sparkles.svg) + content/browser/abouttor/2764-red-heart.svg (content/2764-red-heart.svg) diff --git a/browser/components/abouttor/moz.build b/browser/components/abouttor/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..e0394340455a5a9ef45b39c3ff008d8d70d6fd60 --- /dev/null +++ b/browser/components/abouttor/moz.build @@ -0,0 +1,11 @@ +JAR_MANIFESTS += ["jar.mn"] + +EXTRA_JS_MODULES += [ + "AboutTorMessage.sys.mjs", + "HomepageOverride.sys.mjs", +] + +FINAL_TARGET_FILES.actors += [ + "AboutTorChild.sys.mjs", + "AboutTorParent.sys.mjs", +] diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs index 55f1c8194445ee5b72da718a83887d401bdf8d9a..89245e0d28a83e01cf73c509d18d80cec449067f 100644 --- a/browser/components/customizableui/CustomizableUI.sys.mjs +++ b/browser/components/customizableui/CustomizableUI.sys.mjs @@ -65,6 +65,17 @@ const kSubviewEvents = ["ViewShowing", "ViewHiding"]; */ var kVersion = 20; +/** + * The current version for base browser. + */ +var kVersionBaseBrowser = 2; +const NoScriptId = "_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action"; + +/** + * The current version for tor browser. + */ +var kVersionTorBrowser = 1; + /** * Buttons removed from built-ins by version they were removed. kVersion must be * bumped any time a new id is added to this. Use the button id as key, and @@ -291,6 +302,8 @@ var CustomizableUIInternal = { this._updateForNewVersion(); this._updateForNewProtonVersion(); this._markObsoleteBuiltinButtonsSeen(); + this._updateForBaseBrowser(); + this._updateForTorBrowser(); this.registerArea( CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, @@ -320,10 +333,17 @@ var CustomizableUIInternal = { ? null : "home-button", lazy.sidebarRevampEnabled ? "sidebar-button" : null, - "spring", + // Don't want springs either side of the urlbar. tor-browser#41736 "urlbar-container", - "spring", - "save-to-pocket-button", + // save-to-pocket-button is entirely disabled. See tor-browser#18886 and + // tor-browser#31602. + // Base-browser additions tor-browser#41736. If you want to add to, remove + // from, or rearrange this list, then bump the kVersionBaseBrowser and + // update existing saved states in _updateForBaseBrowser. + // Or if the change is only meant for tor-browser, bump kVersionTorBrowser + // instead and update the existing saved states in _updateForTorBrowser. + "security-level-button", + "new-identity-button", "downloads-button", AppConstants.MOZ_DEV_EDITION ? "developer-button" : null, "fxa-toolbar-menu-button", @@ -345,6 +365,10 @@ var CustomizableUIInternal = { }, true ); + // navbarPlacements does not match the initial default XHTML layout. + // Therefore we always need to rebuild the navbar area when + // registerToolbarNode is called. tor-browser#41736 + gDirtyAreaCache.add(CustomizableUI.AREA_NAVBAR); if (AppConstants.MENUBAR_CAN_AUTOHIDE) { this.registerArea( @@ -863,6 +887,174 @@ var CustomizableUIInternal = { } }, + _updateForBaseBrowser() { + if (!gSavedState) { + // Use the defaults. + return; + } + + const currentVersion = gSavedState.currentVersionBaseBrowser; + + if (currentVersion < 1) { + // NOTE: In base-browser/tor-browser version 12.5a5, and earlier, the + // toolbar was configured by setting the full JSON string for the default + // "browser.uiCustomization.state" preference value. The disadvantage is + // that we could not update this value in a way that existing users (who + // would have non-default preference values) would also get the desired + // change (e.g. for adding or removing a button). + // + // With tor-browser#41736 we want to switch to changing the toolbar + // dynamically like firefox. Therefore, this first version transfer simply + // gets the toolbar into the same state we wanted before, away from the + // default firefox state. + // + // If an existing user state aligned with the previous default + // "browser.uiCustomization.state" then this shouldn't visibly change + // anything. + // If a user explicitly customized the toolbar to go back to the firefox + // default, then this may undo those changes. + const navbarPlacements = + gSavedState.placements[CustomizableUI.AREA_NAVBAR]; + if (navbarPlacements) { + const getBeforeAfterUrlbar = () => { + // NOTE: The urlbar is non-removable from the navbar, so should have + // an index. + const index = navbarPlacements.indexOf("urlbar-container"); + let after = index + 1; + if ( + after < navbarPlacements.length && + navbarPlacements[after] === "search-container" + ) { + // Skip past the search-container. + after++; + } + return { before: index - 1, after }; + }; + + // Remove the urlbar springs either side of the urlbar. + const { before, after } = getBeforeAfterUrlbar(); + if ( + after < navbarPlacements.length && + this.matchingSpecials(navbarPlacements[after], "spring") + ) { + // Remove the spring after. + navbarPlacements.splice(after, 1); + // NOTE: The `before` index does not change. + } + if ( + before >= 0 && + this.matchingSpecials(navbarPlacements[before], "spring") + ) { + // Remove the spring before. + navbarPlacements.splice(before, 1); + } + + // Make sure the security-level-button and new-identity-button appears + // in the toolbar. + for (const id of ["new-identity-button", "security-level-button"]) { + let alreadyAdded = false; + for (const placements of Object.values(gSavedState.placements)) { + if (placements.includes(id)) { + alreadyAdded = true; + break; + } + } + if (alreadyAdded) { + continue; + } + + // Add to the nav-bar, after the urlbar-container. + // NOTE: We have already removed the spring after the urlbar. + navbarPlacements.splice(getBeforeAfterUrlbar().after, 0, id); + } + } + + // Remove save-to-pocket-button. See tor-browser#18886 and + // tor-browser#31602. + for (const placements of Object.values(gSavedState.placements)) { + let buttonIndex = placements.indexOf("save-to-pocket-button"); + if (buttonIndex != -1) { + placements.splice(buttonIndex, 1); + } + } + + // Remove unused fields that used to be part of + // "browser.uiCustomization.state". + delete gSavedState.placements["PanelUI-contents"]; + delete gSavedState.placements["addon-bar"]; + } + + if (currentVersion < 2) { + // Matches against kVersion 19, i.e. when the unified-extensions-button + // was introduced and extensions were moved from the palette to + // AREA_ADDONS. + // For base browser, we want the NoScript addon to be moved from the + // default palette to AREA_NAVBAR, so that if it becomes shown through the + // preference extensions.hideNoScript it will appear in the toolbar. + // If the NoScript addon is already in AREA_NAVBAR, we instead flip the + // extensions.hideNoScript preference so that it remains visible. + // See tor-browser#41581. + const navbarPlacements = + gSavedState.placements[CustomizableUI.AREA_NAVBAR]; + if (navbarPlacements) { + let noScriptVisible = false; + for (const [area, placements] of Object.entries( + gSavedState.placements + )) { + const index = placements.indexOf(NoScriptId); + if (index === -1) { + continue; + } + if (area === CustomizableUI.AREA_ADDONS) { + // Has been placed in the ADDONS area. + // Most likely, this is an alpha or nightly user who received the + // firefox update in a run before this one. In this case, we want to + // match the same behaviour as a stable user: hide the button and + // move it to the NAVBAR instead. + placements.splice(index, 1); + } else { + // It is in an area other than the ADDON (and not in the palette). + noScriptVisible = true; + } + } + if (noScriptVisible) { + // Keep the button where it is and make sure it is visible. + Services.prefs.setBoolPref("extensions.hideNoScript", false); + } else { + // Should appear just before unified-extensions-button, which is + // currently not part of the default placements. + const placeIndex = navbarPlacements.indexOf( + "unified-extensions-button" + ); + if (placeIndex === -1) { + navbarPlacements.push(NoScriptId); + } else { + navbarPlacements.splice(placeIndex, 0, NoScriptId); + } + } + } + } + }, + + _updateForTorBrowser() { + if (!gSavedState) { + // Use the defaults. + return; + } + + const currentVersion = gSavedState.currentVersionTorBrowser; + + if (currentVersion < 1) { + // Remove torbutton-button, which no longer exists. + for (const placements of Object.values(gSavedState.placements)) { + let buttonIndex = placements.indexOf("torbutton-button"); + if (buttonIndex != -1) { + placements.splice(buttonIndex, 1); + } + } + } + }, + _placeNewDefaultWidgetsInArea(aArea) { let futurePlacedWidgets = gFuturePlacements.get(aArea); let savedPlacements = @@ -2769,6 +2961,14 @@ var CustomizableUIInternal = { gSavedState.currentVersion = 0; } + if (!("currentVersionBaseBrowser" in gSavedState)) { + gSavedState.currentVersionBaseBrowser = 0; + } + + if (!("currentVersionTorBrowser" in gSavedState)) { + gSavedState.currentVersionTorBrowser = 0; + } + gSeenWidgets = new Set(gSavedState.seen || []); gDirtyAreaCache = new Set(gSavedState.dirtyAreaCache || []); gNewElementCount = gSavedState.newElementCount || 0; @@ -2957,6 +3157,8 @@ var CustomizableUIInternal = { seen: gSeenWidgets, dirtyAreaCache: gDirtyAreaCache, currentVersion: kVersion, + currentVersionBaseBrowser: kVersionBaseBrowser, + currentVersionTorBrowser: kVersionTorBrowser, newElementCount: gNewElementCount, }; @@ -3587,7 +3789,17 @@ var CustomizableUIInternal = { CustomizableUI.isWebExtensionWidget(widgetId) && !oldAddonPlacements.includes(widgetId) ) { - this.addWidgetToArea(widgetId, CustomizableUI.AREA_ADDONS); + // When resetting, NoScript goes to the toolbar instead. This matches + // its initial placement anyway. And since the button may be hidden by + // default by extensions.hideNoScript, we want to make sure that if it + // becomes unhidden it is shown rather than in the unified extensions + // panel. See tor-browser#41581. + this.addWidgetToArea( + widgetId, + widgetId === NoScriptId + ? CustomizableUI.AREA_NAVBAR + : CustomizableUI.AREA_ADDONS + ); } } }, diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml index 7607f59ec4b72c37ec32901711b4f1781b7b4c7b..f0de65b9e3aa4b94a4d1c0e92a71b2b07f30854a 100644 --- a/browser/components/customizableui/content/panelUI.inc.xhtml +++ b/browser/components/customizableui/content/panelUI.inc.xhtml @@ -200,7 +200,7 @@ hasicon="true" hidden="true"> <popupnotificationcontent id="update-restart-notification-content" orient="vertical"> - <description id="update-restart-description" data-lazy-l10n-id="appmenu-update-restart-message2"></description> + <description id="update-restart-description"> </description> </popupnotificationcontent> </popupnotification> diff --git a/browser/components/downloads/DownloadSpamProtection.sys.mjs b/browser/components/downloads/DownloadSpamProtection.sys.mjs index a05c508e628fd8202b260d3a7c1a853f31bfccc2..9e890edc2830ef4d9005bb3a89eb5438b3ff8105 100644 --- a/browser/components/downloads/DownloadSpamProtection.sys.mjs +++ b/browser/components/downloads/DownloadSpamProtection.sys.mjs @@ -89,8 +89,9 @@ class WindowSpamProtection { * Add a blocked download to the spamList or increment the count of an * existing blocked download, then notify listeners about this. * @param {String} url + * @param {DownloadSpamEnabler} enabler */ - addDownloadSpam(url) { + addDownloadSpam(url, enabler) { this._blocking = true; // Start listening on registered downloads views, if any exist. this._maybeAddViews(); @@ -104,7 +105,7 @@ class WindowSpamProtection { } // Otherwise, create a new DownloadSpam object for the URL, add it to the // spamList, and open the downloads panel. - let downloadSpam = new DownloadSpam(url); + let downloadSpam = new DownloadSpam(url, enabler); this.spamList.add(downloadSpam); this._downloadSpamForUrl.set(url, downloadSpam); this._notifyDownloadSpamAdded(downloadSpam); @@ -188,6 +189,39 @@ class WindowSpamProtection { } } +/** + * Helper to grant a certain principal permission for automatic downloads + * and to clear its download spam messages from the UI + */ +class DownloadSpamEnabler { + /** + * Constructs a DownloadSpamEnabler object + * @param {nsIPrincipal} principal + * @param {DownloadSpamProtection} downloadSpamProtection + */ + constructor(principal, downloadSpamProtection) { + this.principal = principal; + this.downloadSpamProtection = downloadSpamProtection; + } + /** + * Allows a DownloadSpam item + * @param {DownloadSpam} downloadSpam + */ + allow(downloadSpam) { + const pm = Services.perms; + pm.addFromPrincipal( + this.principal, + "automatic-download", + pm.ALLOW_ACTION, + pm.EXPIRE_SESSION + ); + downloadSpam.hasBlockedData = downloadSpam.hasPartialData = false; + const { url } = downloadSpam.source; + for (let window of lazy.BrowserWindowTracker.orderedWindows) { + this.downloadSpamProtection.removeDownloadSpamForWindow(url, window); + } + } +} /** * Responsible for detecting events related to downloads spam and notifying the * relevant window's WindowSpamProtection object. This is a singleton object, @@ -205,9 +239,11 @@ export class DownloadSpamProtection { * download was blocked. This is invoked when a download is blocked by * nsExternalAppHandler::IsDownloadSpam * @param {String} url - * @param {Window} window + * @param {nsILoadInfo} loadInfo */ - update(url, window) { + update(url, loadInfo) { + loadInfo = loadInfo.QueryInterface(Ci.nsILoadInfo); + const window = loadInfo.browsingContext.topChromeWindow; if (window == null) { lazy.DownloadsCommon.log( "Download spam blocked in a non-chrome window. URL: ", @@ -221,7 +257,10 @@ export class DownloadSpamProtection { let wsp = this._forWindowMap.get(window) ?? new WindowSpamProtection(window); this._forWindowMap.set(window, wsp); - wsp.addDownloadSpam(url); + wsp.addDownloadSpam( + url, + new DownloadSpamEnabler(loadInfo.triggeringPrincipal, this) + ); } /** @@ -280,8 +319,9 @@ export class DownloadSpamProtection { * @extends Download */ class DownloadSpam extends Download { - constructor(url) { + constructor(url, downloadSpamEnabler) { super(); + this._downloadSpamEnabler = downloadSpamEnabler; this.hasBlockedData = true; this.stopped = true; this.error = new DownloadError({ @@ -292,4 +332,13 @@ class DownloadSpam extends Download { this.source = { url }; this.blockedDownloadsCount = 1; } + + /** + * Allows the principal which triggered this download to perform automatic downloads + * and clears the UI from messages reporting this download spam + */ + allow() { + this._downloadSpamEnabler.allow(this); + this._notifyChange(); + } } diff --git a/browser/components/downloads/DownloadsTorWarning.sys.mjs b/browser/components/downloads/DownloadsTorWarning.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..8ab534bdfbb4e2d41b08d4424f266ea7e8d0332f --- /dev/null +++ b/browser/components/downloads/DownloadsTorWarning.sys.mjs @@ -0,0 +1,152 @@ +/* import-globals-from /browser/base/content/utilityOverlay.js */ + +const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning"; + +/** + * Manages an instance of a tor warning. + */ +export class DownloadsTorWarning { + /** + * Observer for showing or hiding the warning. + * + * @type {function} + */ + #torWarningPrefObserver; + + /** + * Whether the warning is active. + * + * @type {boolean} + */ + #active = false; + + /** + * The moz-message-bar element that should show the warning. + * + * @type {MozMessageBar} + */ + #warningElement; + + /** + * The dismiss button for the warning. + * + * @type {HTMLButton} + */ + #dismissButton; + + /** + * Attach to an instance of the tor warning. + * + * @param {MozMessageBar} warningElement - The warning element to initialize + * and attach to. + * @param {boolean} isChrome - Whether the element belongs to the chrome. + * Otherwise it belongs to content. + * @param {function} moveFocus - Callback to move the focus out of the warning + * when it is hidden. + * @param {function} [onLinkClick] - Callback that is called when a link is + * about to open. + */ + constructor(warningElement, isChrome, moveFocus, onLinkClick) { + const doc = warningElement.ownerDocument; + this.#warningElement = warningElement; + warningElement.setAttribute( + "data-l10n-id", + "downloads-tor-warning-message-bar" + ); + warningElement.setAttribute("data-l10n-attrs", "heading, message"); + + // Observe changes to the tor warning pref. + this.#torWarningPrefObserver = () => { + if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) { + warningElement.hidden = false; + } else { + const hadFocus = warningElement.contains(doc.activeElement); + warningElement.hidden = true; + if (hadFocus) { + moveFocus(); + } + } + }; + + const tailsLink = doc.createElement("a"); + tailsLink.setAttribute("slot", "support-link"); + tailsLink.href = "https://tails.net/"; + tailsLink.target = "_blank"; + tailsLink.setAttribute("data-l10n-id", "downloads-tor-warning-tails-link"); + if (isChrome) { + // Intercept clicks on the tails link. + tailsLink.addEventListener("click", event => { + event.preventDefault(); + onLinkClick?.(); + doc.defaultView.openWebLinkIn(tailsLink.href, "tab"); + }); + } + + const dismissButton = doc.createElement("button"); + dismissButton.setAttribute("slot", "actions"); + dismissButton.setAttribute( + "data-l10n-id", + "downloads-tor-warning-dismiss-button" + ); + if (isChrome) { + dismissButton.classList.add("footer-button"); + } + + dismissButton.addEventListener("click", () => { + Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false); + }); + + warningElement.append(tailsLink); + warningElement.append(dismissButton); + + this.#dismissButton = dismissButton; + } + + /** + * Whether the warning is hidden by the preference. + * + * @type {boolean} + */ + get hidden() { + return this.#warningElement.hidden; + } + + /** + * The dismiss button for the warning. + * + * @type {HTMLButton} + */ + get dismissButton() { + return this.#dismissButton; + } + + /** + * Activate the instance. + */ + activate() { + if (this.#active) { + return; + } + this.#active = true; + Services.prefs.addObserver( + PREF_SHOW_DOWNLOAD_WARNING, + this.#torWarningPrefObserver + ); + // Initialize. + this.#torWarningPrefObserver(); + } + + /** + * Deactivate the instance. + */ + deactivate() { + if (!this.#active) { + return; + } + this.#active = false; + Services.prefs.removeObserver( + PREF_SHOW_DOWNLOAD_WARNING, + this.#torWarningPrefObserver + ); + } +} diff --git a/browser/components/downloads/content/contentAreaDownloadsView.js b/browser/components/downloads/content/contentAreaDownloadsView.js index 3f9c4ad956d7e5f40f00172e8486e0e7e9538c09..cd35a4351a0577d2d8dc2be659e78892e2d7d6d0 100644 --- a/browser/components/downloads/content/contentAreaDownloadsView.js +++ b/browser/components/downloads/content/contentAreaDownloadsView.js @@ -8,18 +8,52 @@ const { PrivateBrowsingUtils } = ChromeUtils.importESModule( "resource://gre/modules/PrivateBrowsingUtils.sys.mjs" ); +const { DownloadsTorWarning } = ChromeUtils.importESModule( + "resource:///modules/DownloadsTorWarning.sys.mjs" +); + var ContentAreaDownloadsView = { init() { let box = document.getElementById("downloadsListBox"); + + const torWarning = new DownloadsTorWarning( + document.getElementById("aboutDownloadsTorWarning"), + false, + () => { + // Try and focus the downloads list. + // NOTE: If #downloadsListBox is still hidden, this will do nothing. + // But in this case there are no other focusable targets within the + // view, so we just leave it up to the focus handler. + box.focus({ preventFocusRing: true }); + } + ); + torWarning.activate(); + window.addEventListener("unload", () => { + torWarning.deactivate(); + }); + let suppressionFlag = DownloadsCommon.SUPPRESS_CONTENT_AREA_DOWNLOADS_OPEN; box.addEventListener( "InitialDownloadsLoaded", () => { // Set focus to Downloads list once it is created // And prevent it from showing the focus ring around the richlistbox (Bug 1702694) - document - .getElementById("downloadsListBox") - .focus({ focusVisible: false }); + // Prevent focusing the list whilst the tor browser warning is shown. + // Some screen readers (tested with Orca and NVDA) will not read out + // alerts if they are already present on page load. In that case, a + // screen reader user may not be aware of the warning before they + // interact with the downloads list, which we do not want. + // Some hacky workarounds were tested with Orca to get it to read back + // the alert before the focus is read, but this was inconsistent and the + // experience was bad. + // Without auto-focusing the downloads list, a screen reader should not + // skip beyond the alert's content. + if (torWarning.hidden) { + document + .getElementById("downloadsListBox") + .focus({ focusVisible: false }); + } + // Pause the indicator if the browser is active. if (document.visibilityState === "visible") { DownloadsCommon.getIndicatorData(window).attentionSuppressed |= diff --git a/browser/components/downloads/content/contentAreaDownloadsView.xhtml b/browser/components/downloads/content/contentAreaDownloadsView.xhtml index 2ff9deb34d301d20e3ac6f9bb1cd2e3794f52a3d..db2d2eb15947b1b763f3d77cb4e414860e528486 100644 --- a/browser/components/downloads/content/contentAreaDownloadsView.xhtml +++ b/browser/components/downloads/content/contentAreaDownloadsView.xhtml @@ -33,6 +33,7 @@ <html:link rel="localization" href="toolkit/global/textActions.ftl"/> <html:link rel="localization" href="browser/downloads.ftl" /> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> </linkset> <script src="chrome://global/content/globalOverlay.js"/> @@ -48,6 +49,8 @@ </keyset> #endif + <html:moz-message-bar id="aboutDownloadsTorWarning"></html:moz-message-bar> + <richlistbox flex="1" seltype="multiple" id="downloadsListBox" diff --git a/browser/components/downloads/content/downloads.css b/browser/components/downloads/content/downloads.css index baaa3e5d9fb371fa640019ca01c92531ffd817b7..895fa9b17374e8801b649ef4099c0194391b6386 100644 --- a/browser/components/downloads/content/downloads.css +++ b/browser/components/downloads/content/downloads.css @@ -94,6 +94,17 @@ padding: 0.62em; } +#downloadsPanelTorWarning { + margin-block-end: var(--arrowpanel-menuitem-padding-block); +} + +#downloadsPanelTorWarningWrapper { + /* The wrapper element has its `width` attribute set by mozilla localisers. + * We want to ensure the element occupies the available width when the + * localiser width is smaller. See tor-browser#43312. */ + min-width: 100%; +} + #downloadsHistory, #downloadsFooterButtons { margin: 0; diff --git a/browser/components/downloads/content/downloads.js b/browser/components/downloads/content/downloads.js index 3dce85103552edfd06bc6af367d4ff05de5631e3..bbb8b2ccdcc0e618d39fc8b75456760a6bb52340 100644 --- a/browser/components/downloads/content/downloads.js +++ b/browser/components/downloads/content/downloads.js @@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(this, { FileUtils: "resource://gre/modules/FileUtils.sys.mjs", NetUtil: "resource://gre/modules/NetUtil.sys.mjs", PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", + DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs", }); const { Integration } = ChromeUtils.importESModule( @@ -73,6 +74,13 @@ var DownloadsPanel = { /** The panel will be shown as soon as data is available. */ _waitingDataForOpen: false, + /** + * Tracks whether to show the tor warning or not. + * + * @type {?DownloadsTorWarning} + */ + _torWarning: null, + /** * Starts loading the download data in background, without opening the panel. * Use showPanel instead to load the data and open the panel at the same time. @@ -89,6 +97,21 @@ var DownloadsPanel = { ); } + if (!this._torWarning) { + this._torWarning = new DownloadsTorWarning( + document.getElementById("downloadsPanelTorWarning"), + true, + () => { + // Re-assign focus that was lost. + this._focusPanel(true); + }, + () => { + this.hidePanel(); + } + ); + } + this._torWarning.activate(); + if (this._initialized) { DownloadsCommon.log("DownloadsPanel is already initialized."); return; @@ -157,6 +180,8 @@ var DownloadsPanel = { DownloadIntegration.downloadSpamProtection.unregister(window); } + this._torWarning?.deactivate(); + this._initialized = false; DownloadsSummary.active = false; @@ -486,24 +511,38 @@ var DownloadsPanel = { /** * Move focus to the main element in the downloads panel, unless another * element in the panel is already focused. + * + * @param {bool} [forceFocus=false] - Whether to force move the focus. */ - _focusPanel() { - // We may be invoked while the panel is still waiting to be shown. - if (this.panel.state != "open") { - return; - } + _focusPanel(forceFocus = false) { + if (!forceFocus) { + // We may be invoked while the panel is still waiting to be shown. + if (this.panel.state != "open") { + return; + } - if ( - document.activeElement && - (this.panel.contains(document.activeElement) || - this.panel.shadowRoot.contains(document.activeElement)) - ) { - return; + if ( + document.activeElement && + (this.panel.contains(document.activeElement) || + this.panel.shadowRoot.contains(document.activeElement)) + ) { + return; + } } + let focusOptions = {}; if (this._preventFocusRing) { focusOptions.focusVisible = false; } + + // Focus the "Got it" button if it is visible. + // This should ensure that the alert is read aloud by Orca when the + // downloads panel is opened. See tor-browser#42642. + if (!this._torWarning?.hidden) { + this._torWarning.dismissButton.focus(focusOptions); + return; + } + if (DownloadsView.richListBox.itemCount > 0) { if (DownloadsView.canChangeSelectedItem) { DownloadsView.richListBox.selectedIndex = 0; diff --git a/browser/components/downloads/content/downloadsPanel.inc.xhtml b/browser/components/downloads/content/downloadsPanel.inc.xhtml index 55b8eebb4f2f6db714f52d75cb9276759f90c9a2..04c9fa2f05f794899663b93e348ca417e76f0977 100644 --- a/browser/components/downloads/content/downloadsPanel.inc.xhtml +++ b/browser/components/downloads/content/downloadsPanel.inc.xhtml @@ -104,6 +104,25 @@ disablekeynav="true"> <panelview id="downloadsPanel-mainView"> + <!-- We add a wrapper around the #downloadsPanelTorWarning and give it the + - same Fluent ID as #downloadsListBox. This Fluent message allows + - Firefox localisers to set the width of the #downloadsListBox using + - the style attribute. We want the same width set for our downloads + - warning. Otherwise the warning will occupy its max-content width. + - NOTE: We require a wrapper element since #downloadsPanelTorWarning + - needs its own Fluent attributes. + - NOTE: This only works if #downloadsPanelTorWarningWrapper and + - #downloadsListBox share the same padding relative to their common + - ancestor. + - See tor-browser#43312. --> + <html:div + id="downloadsPanelTorWarningWrapper" + data-l10n-id="downloads-panel-items" + data-l10n-attrs="style" + > + <html:moz-message-bar id="downloadsPanelTorWarning"> + </html:moz-message-bar> + </html:div> <vbox class="panel-view-body-unscrollable"> <richlistbox id="downloadsListBox" data-l10n-id="downloads-panel-items" diff --git a/browser/components/downloads/moz.build b/browser/components/downloads/moz.build index a71810b5e6cd2bf31a867388c1ca01b5bb47f4e2..42d871d74c620d961782d96545c8800308c38f02 100644 --- a/browser/components/downloads/moz.build +++ b/browser/components/downloads/moz.build @@ -15,6 +15,7 @@ EXTRA_JS_MODULES += [ "DownloadsCommon.sys.mjs", "DownloadSpamProtection.sys.mjs", "DownloadsTaskbar.sys.mjs", + "DownloadsTorWarning.sys.mjs", "DownloadsViewableInternally.sys.mjs", "DownloadsViewUI.sys.mjs", ] diff --git a/browser/components/extensions/parent/ext-browserAction.js b/browser/components/extensions/parent/ext-browserAction.js index 521a1195bb421d1caa96e7bc58ad6e0c74a4d11d..a1dda8ee608fc7fa5e622d6cb530a1921c005111 100644 --- a/browser/components/extensions/parent/ext-browserAction.js +++ b/browser/components/extensions/parent/ext-browserAction.js @@ -270,6 +270,22 @@ this.browserAction = class extends ExtensionAPIPersistent { node.append(button, menuButton); node.viewButton = button; + if (extension.isNoScript) { + // Hide NoScript by default. + // See tor-browser#41581. + const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript"; + const changeNoScriptVisibility = () => { + node.hidden = Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true); + }; + // Since we expect the NoScript widget to only be destroyed on exit, + // we do not set up to remove the observer. + Services.prefs.addObserver( + HIDE_NO_SCRIPT_PREF, + changeNoScriptVisibility + ); + changeNoScriptVisibility(); + } + return node; }, diff --git a/browser/components/extensions/schemas/chrome_settings_overrides.json b/browser/components/extensions/schemas/chrome_settings_overrides.json index 59b8b3a0576cc0cf807bd2ad87670664c021c17f..61bc358be8ba9c7d9d84f03ace23efc08157e672 100644 --- a/browser/components/extensions/schemas/chrome_settings_overrides.json +++ b/browser/components/extensions/schemas/chrome_settings_overrides.json @@ -45,7 +45,7 @@ "search_url": { "type": "string", "format": "url", - "pattern": "^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", + "pattern": "^(https://|http://(.+\\.onion|localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", "preprocess": "localize" }, "favicon_url": { @@ -66,7 +66,7 @@ "suggest_url": { "type": "string", "optional": true, - "pattern": "^$|^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", + "pattern": "^$|^(https://|http://(.+\\.onion|localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", "preprocess": "localize" }, "instant_url": { @@ -123,7 +123,7 @@ "type": "string", "optional": true, "format": "url", - "pattern": "^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", + "pattern": "^(https://|http://(.+\\.onion|localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d*)?(/|$)).*$", "preprocess": "localize", "deprecated": "Unsupported on Firefox at this time." }, diff --git a/browser/components/migration/ChromeMigrationUtils.sys.mjs b/browser/components/migration/ChromeMigrationUtils.sys.mjs index 88ae3addfcefebfce4d5312952a58a58cf2e7417..b4f2decda4aa2c743649e732274577b63a3659c5 100644 --- a/browser/components/migration/ChromeMigrationUtils.sys.mjs +++ b/browser/components/migration/ChromeMigrationUtils.sys.mjs @@ -342,6 +342,8 @@ export var ChromeMigrationUtils = { if (rootDir == SNAP_REAL_HOME) { targetPath = Services.env.get("SNAP_REAL_HOME"); + } else if (rootDir === "Home" && Services.env.get("BB_ORIGINAL_HOME")) { + targetPath = Services.env.get("BB_ORIGINAL_HOME"); } else { targetPath = Services.dirsvc.get(rootDir, Ci.nsIFile).path; } diff --git a/browser/components/migration/content/migration-wizard.mjs b/browser/components/migration/content/migration-wizard.mjs index 3f3a5215aada208ec44f5e8c83303d349ae84513..54be3c5b6c62e497e6bc082956b42ac7361aa083 100644 --- a/browser/components/migration/content/migration-wizard.mjs +++ b/browser/components/migration/content/migration-wizard.mjs @@ -481,7 +481,10 @@ export class MigrationWizard extends HTMLElement { } let key = panelItem.getAttribute("key"); - let resourceTypes = panelItem.resourceTypes; + const allowedTypes = ["BOOKMARKS"]; + let resourceTypes = panelItem.resourceTypes.filter(t => + allowedTypes.includes(t) + ); for (let child of this.#resourceTypeList.querySelectorAll( "label[data-resource-type]" diff --git a/browser/components/moz.build b/browser/components/moz.build index 0fbba3346c537858e1e52a81465362ec58e103bb..82ee7f24cfb4ec7e2b13ee88a19934b02404a886 100644 --- a/browser/components/moz.build +++ b/browser/components/moz.build @@ -29,6 +29,7 @@ with Files("controlcenter/**"): DIRS += [ "about", "aboutlogins", + "abouttor", "aboutwelcome", "asrouter", "attribution", @@ -40,24 +41,25 @@ DIRS += [ "downloads", "enterprisepolicies", "extensions", - "firefoxview", "genai", "messagepreview", "migration", + "newidentity", "newtab", + "onionservices", "originattributes", "pagedata", "places", - "pocket", "preferences", "privatebrowsing", "prompts", - "protections", "protocolhandler", "reportbrokensite", "resistfingerprinting", + "rulesets", "screenshots", "search", + "securitylevel", "sessionstore", "shell", "shopping", @@ -70,6 +72,8 @@ DIRS += [ "translations", "uitour", "urlbar", + "torcircuit", + "torpreferences", ] DIRS += ["build"] diff --git a/browser/components/newidentity/content/newIdentityDialog.css b/browser/components/newidentity/content/newIdentityDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..850e7c7da625c616e9e71a44aac65391298eb656 --- /dev/null +++ b/browser/components/newidentity/content/newIdentityDialog.css @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#infoTitle { + font-weight: 600; +} diff --git a/browser/components/newidentity/content/newIdentityDialog.js b/browser/components/newidentity/content/newIdentityDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..113cf236f7de00592491339c894731171cb30273 --- /dev/null +++ b/browser/components/newidentity/content/newIdentityDialog.js @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +document.addEventListener("dialogaccept", () => { + const retvals = window.arguments[0]; + retvals.confirmed = true; + retvals.neverAskAgain = document.getElementById("neverAskAgain").checked; +}); + +document.addEventListener("DOMContentLoaded", () => { + const dialog = document.getElementById("newIdentityDialog"); + + const accept = dialog.getButton("accept"); + document.l10n.setAttributes(accept, "new-identity-dialog-confirm"); + accept.classList.add("danger-button"); +}); diff --git a/browser/components/newidentity/content/newIdentityDialog.xhtml b/browser/components/newidentity/content/newIdentityDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..f90271ada4aec81c95b3a927e0d782c5498e7139 --- /dev/null +++ b/browser/components/newidentity/content/newIdentityDialog.xhtml @@ -0,0 +1,63 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!-- based on resetProfile.xhtml --> + +<window + id="newIdentityDialogWindow" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + aria-labelledby="infoTitle" + aria-describedby="infoBody" +> + <dialog id="newIdentityDialog" buttons="accept,cancel" defaultButton="accept"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://global/content/commonDialog.css" + /> + <html:link + rel="stylesheet" + href="chrome://global/skin/commonDialog.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/newIdentityDialog.css" + /> + + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link rel="localization" href="toolkit/global/base-browser.ftl" /> + </linkset> + + <div xmlns="http://www.w3.org/1999/xhtml"> + <div id="dialogGrid"> + <div class="dialogRow" id="infoRow"> + <div id="iconContainer"> + <xul:image id="infoIcon" /> + </div> + <div id="infoContainer"> + <xul:description + id="infoTitle" + data-l10n-id="new-identity-dialog-title" + /> + <xul:description + id="infoBody" + data-l10n-id="new-identity-dialog-description" + /> + <xul:checkbox + id="neverAskAgain" + data-l10n-id="new-identity-dialog-never-ask-checkbox" + /> + </div> + </div> + </div> + </div> + + <script src="chrome://browser/content/newIdentityDialog.js" /> + </dialog> +</window> diff --git a/browser/components/newidentity/content/newidentity.js b/browser/components/newidentity/content/newidentity.js new file mode 100644 index 0000000000000000000000000000000000000000..dffe198a38b03ad4adf8fbfa38aece72716d7d2c --- /dev/null +++ b/browser/components/newidentity/content/newidentity.js @@ -0,0 +1,572 @@ +"use strict"; + +/* eslint-env mozilla/browser-window */ + +// Use a lazy getter because NewIdentityButton is declared more than once +// otherwise. +ChromeUtils.defineLazyGetter(this, "NewIdentityButton", () => { + // Logger adapted from CustomizableUI.jsm + const logger = (() => { + const consoleOptions = { + maxLogLevelPref: "browser.new_identity.log_level", + prefix: "NewIdentity", + }; + return console.createInstance(consoleOptions); + })(); + + const topics = Object.freeze({ + newIdentityRequested: "new-identity-requested", + }); + + /** + * This class contains the actual implementation of the various step involved + * when running new identity. + */ + class NewIdentityImpl { + async run() { + this.disableAllJS(); + await this.clearState(); + await this.openNewWindow(); + this.closeOldWindow(); + this.broadcast(); + } + + // Disable JS (as a defense-in-depth measure) + + disableAllJS() { + logger.info("Disabling JavaScript"); + const enumerator = Services.wm.getEnumerator("navigator:browser"); + while (enumerator.hasMoreElements()) { + const win = enumerator.getNext(); + this.disableWindowJS(win); + } + } + + disableWindowJS(win) { + const browsers = win.gBrowser?.browsers || []; + for (const browser of browsers) { + if (!browser) { + continue; + } + this.disableBrowserJS(browser); + try { + browser.webNavigation?.stop(browser.webNavigation.STOP_ALL); + } catch (e) { + logger.warn("Could not stop navigation", e, browser.currentURI); + } + } + } + + disableBrowserJS(browser) { + if (!browser) { + return; + } + // Does the following still apply? + // Solution from: https://bugzilla.mozilla.org/show_bug.cgi?id=409737 + // XXX: This kills the entire window. We need to redirect + // focus and inform the user via a lightbox. + const eventSuppressor = browser.contentWindow?.windowUtils; + if (browser.browsingContext) { + browser.browsingContext.allowJavascript = false; + } + try { + // My estimation is that this does not get the inner iframe windows, + // but that does not matter, because iframes should be destroyed + // on the next load. + // Should we log when browser.contentWindow is null? + if (browser.contentWindow) { + browser.contentWindow.name = null; + browser.contentWindow.window.name = null; + } + } catch (e) { + logger.warn("Failed to reset window.name", e); + } + eventSuppressor?.suppressEventHandling(true); + } + + // Clear state + + async clearState() { + logger.info("Clearing the state"); + this.closeTabs(); + this.clearSearchBar(); + this.clearPrivateSessionHistory(); + this.clearHTTPAuths(); + this.clearCryptoTokens(); + this.clearOCSPCache(); + this.clearSecuritySettings(); + this.clearImageCaches(); + this.clearStorage(); + this.clearPreferencesAndPermissions(); + await this.clearData(); + await this.reloadAddons(); + this.clearConnections(); + this.clearPrivateSession(); + } + + clearSiteSpecificZoom() { + Services.prefs.setBoolPref( + "browser.zoom.siteSpecific", + !Services.prefs.getBoolPref("browser.zoom.siteSpecific") + ); + Services.prefs.setBoolPref( + "browser.zoom.siteSpecific", + !Services.prefs.getBoolPref("browser.zoom.siteSpecific") + ); + } + + closeTabs() { + if ( + !Services.prefs.getBoolPref("browser.new_identity.close_newnym", true) + ) { + logger.info("Not closing tabs"); + return; + } + // TODO: muck around with browser.tabs.warnOnClose.. maybe.. + logger.info("Closing tabs..."); + const enumerator = Services.wm.getEnumerator("navigator:browser"); + const windowsToClose = []; + while (enumerator.hasMoreElements()) { + const win = enumerator.getNext(); + const browser = win.gBrowser; + if (!browser) { + logger.warn("No browser for possible window to close"); + continue; + } + const tabsToRemove = []; + for (const b of browser.browsers) { + const tab = browser.getTabForBrowser(b); + if (tab) { + tabsToRemove.push(tab); + } else { + logger.warn("Browser has a null tab", b); + } + } + if (win == window) { + browser.addWebTab("about:blank"); + } else { + // It is a bad idea to alter the window list while iterating + // over it, so add this window to an array and close it later. + windowsToClose.push(win); + } + // Close each tab except the new blank one that we created. + tabsToRemove.forEach(aTab => browser.removeTab(aTab)); + } + // Close all XUL windows except this one. + logger.info("Closing windows..."); + windowsToClose.forEach(aWin => aWin.close()); + logger.info("Closed all tabs"); + + // This clears the undo tab history. + const tabs = Services.prefs.getIntPref( + "browser.sessionstore.max_tabs_undo" + ); + Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", 0); + Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", tabs); + } + + clearSearchBar() { + logger.info("Clearing searchbox"); + // Bug #10800: Trying to clear search/find can cause exceptions + // in unknown cases. Just log for now. + try { + const searchBar = window.document.getElementById("searchbar"); + if (searchBar) { + searchBar.textbox.reset(); + } + } catch (e) { + logger.error("Exception on clearing search box", e); + } + try { + if (gFindBarInitialized) { + const findbox = gFindBar.getElement("findbar-textbox"); + findbox.reset(); + gFindBar.close(); + } + } catch (e) { + logger.error("Exception on clearing find bar", e); + } + } + + clearPrivateSessionHistory() { + logger.info("Emitting Private Browsing Session clear event"); + Services.obs.notifyObservers(null, "browser:purge-session-history"); + } + + clearHTTPAuths() { + if ( + !Services.prefs.getBoolPref( + "browser.new_identity.clear_http_auth", + true + ) + ) { + logger.info("Skipping HTTP Auths, because disabled"); + return; + } + logger.info("Clearing HTTP Auths"); + const auth = Cc["@mozilla.org/network/http-auth-manager;1"].getService( + Ci.nsIHttpAuthManager + ); + auth.clearAll(); + } + + clearCryptoTokens() { + logger.info("Clearing Crypto Tokens"); + // Clear all crypto auth tokens. This includes calls to PK11_LogoutAll(), + // nsNSSComponent::LogoutAuthenticatedPK11() and clearing the SSL session + // cache. + const sdr = Cc["@mozilla.org/security/sdr;1"].getService( + Ci.nsISecretDecoderRing + ); + sdr.logoutAndTeardown(); + } + + clearOCSPCache() { + // nsNSSComponent::Observe() watches security.OCSP.enabled, which calls + // setValidationOptions(), which in turn calls setNonPkixOcspEnabled() which, + // if security.OCSP.enabled is set to 0, calls CERT_DisableOCSPChecking(), + // which calls CERT_ClearOCSPCache(). + // See: https://mxr.mozilla.org/comm-esr24/source/mozilla/security/manager/ssl/src/nsNSSComponent.cpp + const ocsp = Services.prefs.getIntPref("security.OCSP.enabled"); + Services.prefs.setIntPref("security.OCSP.enabled", 0); + Services.prefs.setIntPref("security.OCSP.enabled", ocsp); + } + + clearSecuritySettings() { + // Clear site security settings + const sss = Cc["@mozilla.org/ssservice;1"].getService( + Ci.nsISiteSecurityService + ); + sss.clearAll(); + } + + clearImageCaches() { + logger.info("Clearing Image Cache"); + // In Firefox 18 and newer, there are two image caches: one that is used + // for regular browsing, and one that is used for private browsing. + this.clearImageCacheRB(); + this.clearImageCachePB(); + } + + clearImageCacheRB() { + try { + const imgTools = Cc["@mozilla.org/image/tools;1"].getService( + Ci.imgITools + ); + const imgCache = imgTools.getImgCacheForDocument(null); + // Evict all but chrome cache + imgCache.clearCache(false); + } catch (e) { + // FIXME: This can happen in some rare cases involving XULish image data + // in combination with our image cache isolation patch. Sure isn't + // a good thing, but it's not really a super-cookie vector either. + // We should fix it eventually. + logger.error("Exception on image cache clearing", e); + } + } + + clearImageCachePB() { + const imgTools = Cc["@mozilla.org/image/tools;1"].getService( + Ci.imgITools + ); + try { + // Try to clear the private browsing cache. To do so, we must locate a + // content document that is contained within a private browsing window. + let didClearPBCache = false; + const enumerator = Services.wm.getEnumerator("navigator:browser"); + while (!didClearPBCache && enumerator.hasMoreElements()) { + const win = enumerator.getNext(); + let browserDoc = win.document.documentElement; + if (!browserDoc.hasAttribute("privatebrowsingmode")) { + continue; + } + const tabbrowser = win.gBrowser; + if (!tabbrowser) { + continue; + } + for (const browser of tabbrowser.browsers) { + const doc = browser.contentDocument; + if (doc) { + const imgCache = imgTools.getImgCacheForDocument(doc); + // Evict all but chrome cache + imgCache.clearCache(false); + didClearPBCache = true; + break; + } + } + } + } catch (e) { + logger.error("Exception on private browsing image cache clearing", e); + } + } + + clearStorage() { + logger.info("Clearing Disk and Memory Caches"); + try { + Services.cache2.clear(); + } catch (e) { + logger.error("Exception on cache clearing", e); + } + + logger.info("Clearing Cookies and DOM Storage"); + Services.cookies.removeAll(); + } + + clearPreferencesAndPermissions() { + logger.info("Clearing Content Preferences"); + ChromeUtils.defineESModuleGetters(this, { + PrivateBrowsingUtils: + "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", + }); + const pbCtxt = PrivateBrowsingUtils.privacyContextFromWindow(window); + const cps = Cc["@mozilla.org/content-pref/service;1"].getService( + Ci.nsIContentPrefService2 + ); + cps.removeAllDomains(pbCtxt); + this.clearSiteSpecificZoom(); + + logger.info("Clearing permissions"); + try { + Services.perms.removeAll(); + } catch (e) { + // Actually, this catch does not appear to be needed. Leaving it in for + // safety though. + logger.error("Cannot clear permissions", e); + } + + logger.info("Syncing prefs"); + // Force prefs to be synced to disk + Services.prefs.savePrefFile(null); + } + + async clearData() { + logger.info("Calling the clearDataService"); + const flags = + Services.clearData.CLEAR_ALL ^ Services.clearData.CLEAR_PASSWORDS; + return new Promise(resolve => { + Services.clearData.deleteData(flags, { + onDataDeleted(code) { + if (code !== Cr.NS_OK) { + logger.error(`Error while calling the clearDataService: ${code}`); + } + // We always resolve, because we do not want to interrupt the new + // identity procedure. + resolve(); + }, + }); + }); + } + + clearConnections() { + logger.info("Closing open connections"); + // Clear keep-alive + Services.obs.notifyObservers(this, "net:prune-all-connections"); + } + + clearPrivateSession() { + logger.info("Ending any remaining private browsing sessions."); + Services.obs.notifyObservers(null, "last-pb-context-exited"); + } + + async reloadAddons() { + logger.info("Reloading add-ons to clear their temporary state."); + // Reload all active extensions except search engines, which would throw. + const addons = await AddonManager.getAddonsByTypes(["extension"]); + const isSearchEngine = async addon => + (await (await fetch(addon.getResourceURI("manifest.json").spec)).json()) + ?.chrome_settings_overrides?.search_provider; + const reloadIfNeeded = async addon => + addon.isActive && !(await isSearchEngine(addon)) && addon.reload(); + await Promise.all(addons.map(addon => reloadIfNeeded(addon))); + } + + // Broadcast as a hook to clear other data + + broadcast() { + logger.info("Broadcasting the new identity"); + Services.obs.notifyObservers({}, topics.newIdentityRequested); + } + + // Window management + + openNewWindow() { + logger.info("Opening a new window"); + return new Promise(resolve => { + // Open a new window forcing the about:privatebrowsing page (tor-browser#41765) + // unless user explicitly overrides this policy (tor-browser #42236) + const trustedHomePref = "browser.startup.homepage.new_identity"; + const homeURL = HomePage.get(); + const defaultHomeURL = HomePage.getDefault(); + const isTrustedHome = + homeURL === defaultHomeURL || + homeURL === "chrome://browser/content/blanktab.html" || // about:blank + homeURL === Services.prefs.getStringPref(trustedHomePref, ""); + const isCustomHome = + Services.prefs.getIntPref("browser.startup.page") === 1; + const win = OpenBrowserWindow({ + private: isCustomHome && isTrustedHome ? "private" : "no-home", + }); + // This mechanism to know when the new window is ready is used by + // OpenBrowserWindow itself (see its definition in browser.js). + win.addEventListener( + "MozAfterPaint", + () => { + resolve(); + if (isTrustedHome || !isCustomHome) { + return; + } + const tbl = win.TabsProgressListener; + const { onLocationChange } = tbl; + tbl.onLocationChange = (...args) => { + tbl.onLocationChange = onLocationChange; + tbl.onLocationChange(...args); + let displayAddress; + try { + const url = new URL(homeURL); + displayAddress = url.hostname; + if (!displayAddress) { + // no host, use full address and truncate if too long + const MAX_LEN = 32; + displayAddress = url.href; + if (displayAddress.length > MAX_LEN) { + displayAddress = `${displayAddress.substring(0, MAX_LEN)}…`; + } + } + } catch (e) { + // malformed URL, bail out + return; + } + const callback = () => { + Services.prefs.setStringPref(trustedHomePref, homeURL); + win.BrowserHome(); + }; + const notificationBox = win.gBrowser.getNotificationBox(); + notificationBox.appendNotification( + "new-identity-safe-home", + { + label: { + "l10n-id": "new-identity-blocked-home-notification", + "l10n-args": { url: displayAddress }, + }, + priority: notificationBox.PRIORITY_INFO_MEDIUM, + }, + [ + { + "l10n-id": "new-identity-blocked-home-ignore-button", + callback, + }, + ] + ); + }; + }, + { once: true } + ); + }); + } + + closeOldWindow() { + logger.info("Closing the old window"); + + // Run garbage collection and cycle collection after window is gone. + // This ensures that blob URIs are forgotten. + window.addEventListener("unload", function () { + logger.debug("Initiating New Identity GC pass"); + // Clear out potential pending sInterSliceGCTimer: + window.windowUtils.runNextCollectorTimer(); + // Clear out potential pending sICCTimer: + window.windowUtils.runNextCollectorTimer(); + // Schedule a garbage collection in 4000-1000ms... + window.windowUtils.garbageCollect(); + // To ensure the GC runs immediately instead of 4-10s from now, we need + // to poke it at least 11 times. + // We need 5 pokes for GC, 1 poke for the interSliceGC, and 5 pokes for + // CC. + // See nsJSContext::RunNextCollectorTimer() in + // https://mxr.mozilla.org/mozilla-central/source/dom/base/nsJSEnvironment.cpp#1970. + // XXX: We might want to make our own method for immediate full GC... + for (let poke = 0; poke < 11; poke++) { + window.windowUtils.runNextCollectorTimer(); + } + // And now, since the GC probably actually ran *after* the CC last time, + // run the whole thing again. + window.windowUtils.garbageCollect(); + for (let poke = 0; poke < 11; poke++) { + window.windowUtils.runNextCollectorTimer(); + } + logger.debug("Completed New Identity GC pass"); + }); + + // Close the current window for added safety + window.close(); + } + } + + let newIdentityInProgress = false; + return { + topics, + + init() { + // We first search in the DOM for the identity button. If it does not + // exist it may be in the toolbox palette. In the latter case we still + // need to initialize the button in case it is added back later through + // customization. + const button = + document.getElementById("new-identity-button") || + window.gNavToolbox.palette.querySelector("#new-identity-button"); + button?.addEventListener("command", () => { + this.onCommand(); + }); + document + .getElementById("appMenu-viewCache") + .content.querySelector("#appMenu-new-identity") + ?.addEventListener("command", () => { + this.onCommand(); + }); + document + .getElementById("menu_newIdentity") + ?.addEventListener("command", () => { + this.onCommand(); + }); + }, + + uninit() {}, + + async onCommand() { + try { + // Ignore if there's a New Identity in progress to avoid race + // conditions leading to failures (see bug 11783 for an example). + if (newIdentityInProgress) { + return; + } + newIdentityInProgress = true; + + const prefConfirm = "browser.new_identity.confirm_newnym"; + const shouldConfirm = Services.prefs.getBoolPref(prefConfirm, true); + if (shouldConfirm) { + const params = { + confirmed: false, + neverAskAgain: false, + }; + await window.gDialogBox.open( + "chrome://browser/content/newIdentityDialog.xhtml", + params + ); + Services.prefs.setBoolPref(prefConfirm, !params.neverAskAgain); + if (!params.confirmed) { + return; + } + } + + const impl = new NewIdentityImpl(); + await impl.run(); + } catch (e) { + // If something went wrong make sure we have the New Identity button + // enabled (again). + logger.error("Unexpected error", e); + window.alert("New Identity unexpected error: " + e); + } finally { + newIdentityInProgress = false; + } + }, + }; +}); diff --git a/browser/components/newidentity/jar.mn b/browser/components/newidentity/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..6e4642e1f5f34edf07d2a6cfce88ff718206577a --- /dev/null +++ b/browser/components/newidentity/jar.mn @@ -0,0 +1,5 @@ +browser.jar: + content/browser/newidentity.js (content/newidentity.js) + content/browser/newIdentityDialog.xhtml (content/newIdentityDialog.xhtml) + content/browser/newIdentityDialog.css (content/newIdentityDialog.css) + content/browser/newIdentityDialog.js (content/newIdentityDialog.js) diff --git a/browser/components/newidentity/moz.build b/browser/components/newidentity/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..2661ad7cb9f3df2b3953a6e1e999aee82d29be78 --- /dev/null +++ b/browser/components/newidentity/moz.build @@ -0,0 +1 @@ +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/components/newtab/AboutNewTabService.sys.mjs b/browser/components/newtab/AboutNewTabService.sys.mjs index 37adc25f6eb9725460ea6b2d7ccf315d3ca2a3f6..96db931e5ea3e460016bfe11718faa7294ae44ed 100644 --- a/browser/components/newtab/AboutNewTabService.sys.mjs +++ b/browser/components/newtab/AboutNewTabService.sys.mjs @@ -421,20 +421,19 @@ class BaseAboutNewTabService { * the newtab page has no effect on the result of this function. */ get defaultURL() { - // Generate the desired activity stream resource depending on state, e.g., - // "resource://activity-stream/prerendered/activity-stream.html" - // "resource://activity-stream/prerendered/activity-stream-debug.html" - // "resource://activity-stream/prerendered/activity-stream-noscripts.html" - return [ - "resource://activity-stream/prerendered/", - "activity-stream", - // Debug version loads dev scripts but noscripts separately loads scripts - this.activityStreamDebug && !this.privilegedAboutProcessEnabled - ? "-debug" - : "", - this.privilegedAboutProcessEnabled ? "-noscripts" : "", - ".html", - ].join(""); + // NOTE: We return "about:tor" rather than the "chrome:" path + // "chrome://browser/content/abouttor/aboutTor.html" + // The result is that the channel created in NewChannel in + // browser/components/about/AboutRedirector.cpp will have its + // resultPrincipalURI set to "about:tor". + // What this means in practice is that the loaded document's documentURI and + // currentURI will be "about:tor" rather than "about:newtab", "about:home", + // "about:welcome" or "about:privatebrowsing". + // The disadvantage of this is that we often need to add "about:tor" to + // places where "about:newtab" or other URIs appear. + // The advantage is that we maintain more control against changes in + // mozilla-central. + return "about:tor"; } get welcomeURL() { diff --git a/browser/components/onionservices/OnionAliasStore.sys.mjs b/browser/components/onionservices/OnionAliasStore.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..6a744c4c14d7dd347b6e8a5d882f7c8c4dbe935e --- /dev/null +++ b/browser/components/onionservices/OnionAliasStore.sys.mjs @@ -0,0 +1,551 @@ +// Copyright (c) 2022, The Tor Project, Inc. + +import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + JSONFile: "resource://gre/modules/JSONFile.sys.mjs", + TorRequestWatch: "resource:///modules/TorRequestWatch.sys.mjs", +}); + +/* OnionAliasStore observer topics */ +export const OnionAliasStoreTopics = Object.freeze({ + ChannelsChanged: "onionaliasstore:channels-changed", +}); + +const SECURE_DROP = { + name: "SecureDropTorOnion2021", + pathPrefix: "https://securedrop.org/https-everywhere-2021/", + jwk: { + kty: "RSA", + e: "AQAB", + n: "vsC7BNafkRe8Uh1DUgCkv6RbPQMdJgAKKnWdSqQd7tQzU1mXfmo_k1Py_2MYMZXOWmqSZ9iwIYkykZYywJ2VyMGve4byj1sLn6YQoOkG8g5Z3V4y0S2RpEfmYumNjTzfq8nxtLnwjaYd4sCUd5wa0SzeLrpRQuXo2bF3QuUF2xcbLJloxX1MmlsMMCdBc-qGNonLJ7bpn_JuyXlDWy1Fkeyw1qgjiOdiRIbMC1x302zgzX6dSrBrNB8Cpsh-vCE0ZjUo8M9caEv06F6QbYmdGJHM0ZZY34OHMSNdf-_qUKIV_SuxuSuFE99tkAeWnbWpyI1V-xhVo1sc7NzChP8ci2TdPvI3_0JyAuCvL6zIFqJUJkZibEUghhg6F09-oNJKpy7rhUJq7zZyLXJsvuXnn0gnIxfjRvMcDfZAKUVMZKRdw7fwWzwQril4Ib0MQOVda9vb_4JMk7Gup-TUI4sfuS4NKwsnKoODIO-2U5QpJWdtp1F4AQ1pBv8ajFl1WTrVGvkRGK0woPWaO6pWyJ4kRnhnxrV2FyNNt3JSR-0JEjhFWws47kjBvpr0VRiVRFppKA-plKs4LPlaaCff39TleYmY3mETe3w1GIGc2Lliad32Jpbx496IgDe1K3FMBEoKFZfhmtlRSXft8NKgSzPt2zkatM9bFKfaCYRaSy7akbk", + }, + scope: /^https?:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)*\.securedrop\.tor\.onion\//, + enabled: true, + mappings: [], + currentTimestamp: 0, +}; + +const kPrefOnionAliasEnabled = "browser.urlbar.onionRewrites.enabled"; + +const log = console.createInstance({ + maxLogLevelPref: "browser.onionalias.log_level", + prefix: "OnionAlias", +}); + +// Inspired by aboutMemory.js and PingCentre.jsm +function gunzip(buffer) { + return new Promise(resolve => { + const listener = Cc["@mozilla.org/network/stream-loader;1"].createInstance( + Ci.nsIStreamLoader + ); + listener.init({ + onStreamComplete(loader, context, status, length, result) { + resolve(String.fromCharCode(...result)); + }, + }); + const scs = Cc["@mozilla.org/streamConverters;1"].getService( + Ci.nsIStreamConverterService + ); + const converter = scs.asyncConvertData( + "gzip", + "uncompressed", + listener, + null + ); + const stream = Cc[ + "@mozilla.org/io/arraybuffer-input-stream;1" + ].createInstance(Ci.nsIArrayBufferInputStream); + stream.setData(buffer, 0, buffer.byteLength); + converter.onStartRequest(null, null); + converter.onDataAvailable(null, stream, 0, buffer.byteLength); + converter.onStopRequest(null, null, null); + }); +} + +/** + * A channel that distributes Onion aliases. + * + * Each channel needs: + * - a name + * - a key used to sign the rules + * - a path prefix that will be used to build the URLs used to fetch updates + * - a scope (the apex domain for all aliases, and it must be a subdomain of + * .tor.onion). + */ +class Channel { + static get SIGN_ALGORITHM() { + return { + name: "RSA-PSS", + saltLength: 32, + hash: { name: "SHA-256" }, + }; + } + + constructor(name, pathPrefix, jwk, scope, enabled) { + this.name = name; + this.pathPrefix = pathPrefix; + this.jwk = jwk; + this.scope = scope; + this._enabled = enabled; + + this.mappings = []; + this.currentTimestamp = 0; + this.latestTimestamp = 0; + } + + async updateLatestTimestamp() { + const timestampUrl = this.pathPrefix + "/latest-rulesets-timestamp"; + log.debug(`Updating ${this.name} timestamp from ${timestampUrl}`); + const response = await fetch(timestampUrl); + if (!response.ok) { + throw Error(`Could not fetch timestamp for ${this.name}`, { + cause: response.status, + }); + } + const timestampStr = await response.text(); + const timestamp = parseInt(timestampStr); + // Avoid hijacking, sanitize the timestamp + if (isNaN(timestamp)) { + throw Error("Latest timestamp is not a number"); + } + log.debug(`Updated ${this.name} timestamp: ${timestamp}`); + this.latestTimestamp = timestamp; + } + + async makeKey() { + return crypto.subtle.importKey( + "jwk", + this.jwk, + Channel.SIGN_ALGORITHM, + false, + ["verify"] + ); + } + + async downloadVerifiedRules() { + log.debug(`Downloading and verifying ruleset for ${this.name}`); + + const key = await this.makeKey(); + const signatureUrl = + this.pathPrefix + `/rulesets-signature.${this.latestTimestamp}.sha256`; + const signatureResponse = await fetch(signatureUrl); + if (!signatureResponse.ok) { + throw Error("Could not fetch the rules signature"); + } + const signature = await signatureResponse.arrayBuffer(); + + const rulesUrl = + this.pathPrefix + `/default.rulesets.${this.latestTimestamp}.gz`; + const rulesResponse = await fetch(rulesUrl); + if (!rulesResponse.ok) { + throw Error("Could not fetch rules"); + } + const rulesGz = await rulesResponse.arrayBuffer(); + + if ( + !(await crypto.subtle.verify( + Channel.SIGN_ALGORITHM, + key, + signature, + rulesGz + )) + ) { + throw Error("Could not verify rules signature"); + } + log.debug( + `Downloaded and verified rules for ${this.name}, now uncompressing` + ); + this._makeMappings(JSON.parse(await gunzip(rulesGz))); + } + + _makeMappings(rules) { + const toTest = /^https?:\/\/[a-zA-Z0-9\.]{56}\.onion$/; + const mappings = []; + rules.rulesets.forEach(rule => { + if (rule.rule.length != 1) { + log.warn(`Unsupported rule lenght: ${rule.rule.length}`); + return; + } + if (!toTest.test(rule.rule[0].to)) { + log.warn( + `Ignoring rule, because of a malformed to: ${rule.rule[0].to}` + ); + return; + } + let toHostname; + try { + const toUrl = new URL(rule.rule[0].to); + toHostname = toUrl.hostname; + } catch (err) { + log.error( + "Cannot detect the hostname from the to rule", + rule.rule[0].to, + err + ); + } + let fromRe; + try { + fromRe = new RegExp(rule.rule[0].from); + } catch (err) { + log.error("Malformed from field", rule.rule[0].from, err); + return; + } + for (const target of rule.target) { + if ( + target.endsWith(".tor.onion") && + this.scope.test(`http://${target}/`) && + fromRe.test(`http://${target}/`) + ) { + mappings.push([target, toHostname]); + } else { + log.warn("Ignoring malformed rule", rule); + } + } + }); + this.mappings = mappings; + this.currentTimestamp = rules.timestamp; + log.debug(`Updated mappings for ${this.name}`, mappings); + } + + async updateMappings(force) { + force = force === undefined ? false : !!force; + if (!this._enabled && !force) { + return; + } + await this.updateLatestTimestamp(); + if (this.latestTimestamp <= this.currentTimestamp && !force) { + log.debug( + `Rules for ${this.name} are already up to date, skipping update` + ); + return; + } + await this.downloadVerifiedRules(); + } + + get enabled() { + return this._enabled; + } + set enabled(enabled) { + this._enabled = enabled; + if (!enabled) { + this.mappings = []; + this.currentTimestamp = 0; + this.latestTimestamp = 0; + } + } + + toJSON() { + let scope = this.scope.toString(); + scope = scope.substr(1, scope.length - 2); + return { + name: this.name, + pathPrefix: this.pathPrefix, + jwk: this.jwk, + scope, + enabled: this._enabled, + mappings: this.mappings, + currentTimestamp: this.currentTimestamp, + }; + } + + static fromJSON(obj) { + let channel = new Channel( + obj.name, + obj.pathPrefix, + obj.jwk, + new RegExp(obj.scope), + obj.enabled + ); + if (obj.enabled) { + channel.mappings = obj.mappings; + channel.currentTimestamp = obj.currentTimestamp; + } + return channel; + } +} + +/** + * The manager of onion aliases. + * It allows creating, reading, updating and deleting channels and it keeps them + * updated. + * + * This class is a singleton which should be accessed with OnionAliasStore. + */ +class _OnionAliasStore { + static get RULESET_CHECK_INTERVAL() { + return 86400 * 1000; // 1 day, like HTTPS-Everywhere + } + + constructor() { + this._channels = new Map(); + this._rulesetTimeout = null; + this._lastCheck = 0; + this._storage = null; + } + + async init() { + lazy.TorRequestWatch.start(); + await this._loadSettings(); + if (this.enabled) { + await this._startUpdates(); + } + Services.prefs.addObserver(kPrefOnionAliasEnabled, this); + } + + uninit() { + this._clear(); + if (this._rulesetTimeout) { + clearTimeout(this._rulesetTimeout); + } + this._rulesetTimeout = null; + Services.prefs.removeObserver(kPrefOnionAliasEnabled, this); + lazy.TorRequestWatch.stop(); + } + + async getChannels() { + if (this._storage === null) { + await this._loadSettings(); + } + return Array.from(this._channels.values(), ch => ch.toJSON()); + } + + async setChannel(chanData) { + const name = chanData.name?.trim(); + if (!name) { + throw Error("Name cannot be empty"); + } + + new URL(chanData.pathPrefix); + const scope = new RegExp(chanData.scope); + const ch = new Channel( + name, + chanData.pathPrefix, + chanData.jwk, + scope, + !!chanData.enabled + ); + // Call makeKey to make it throw if the key is invalid + await ch.makeKey(); + this._channels.set(name, ch); + this._applyMappings(); + this._saveSettings(); + setTimeout(this._notifyChanges.bind(this), 1); + return ch; + } + + enableChannel(name, enabled) { + const channel = this._channels.get(name); + if (channel !== null) { + channel.enabled = enabled; + this._applyMappings(); + this._saveSettings(); + this._notifyChanges(); + if (this.enabled && enabled && !channel.currentTimestamp) { + this.updateChannel(name); + } + } + } + + async updateChannel(name) { + if (!this.enabled) { + throw Error("Onion Aliases are disabled"); + } + const channel = this._channels.get(name); + if (channel === null) { + throw Error("Channel not found"); + } + await channel.updateMappings(true); + this._saveSettings(); + this._applyMappings(); + setTimeout(this._notifyChanges.bind(this), 1); + return channel; + } + + deleteChannel(name) { + if (this._channels.delete(name)) { + this._saveSettings(); + this._applyMappings(); + this._notifyChanges(); + } + } + + async _loadSettings() { + if (this._storage !== null) { + return; + } + this._channels = new Map(); + this._storage = new lazy.JSONFile({ + path: PathUtils.join( + Services.dirsvc.get("ProfD", Ci.nsIFile).path, + "onion-aliases.json" + ), + dataPostProcessor: this._settingsProcessor.bind(this), + }); + await this._storage.load(); + log.debug("Loaded settings", this._storage.data, this._storage.path); + this._applyMappings(); + this._notifyChanges(); + } + + _settingsProcessor(data) { + if ("lastCheck" in data) { + this._lastCheck = data.lastCheck; + } else { + data.lastCheck = 0; + } + if (!("channels" in data) || !Array.isArray(data.channels)) { + data.channels = [SECURE_DROP]; + // Force updating + data.lastCheck = 0; + } + const channels = new Map(); + data.channels = data.channels.filter(ch => { + try { + channels.set(ch.name, Channel.fromJSON(ch)); + } catch (err) { + log.error("Could not load a channel", err, ch); + return false; + } + return true; + }); + this._channels = channels; + return data; + } + + _saveSettings() { + if (this._storage === null) { + throw Error("Settings have not been loaded"); + } + this._storage.data.lastCheck = this._lastCheck; + this._storage.data.channels = Array.from(this._channels.values(), ch => + ch.toJSON() + ); + this._storage.saveSoon(); + } + + _addMapping(shortOnionHost, longOnionHost) { + const service = Cc["@torproject.org/onion-alias-service;1"].getService( + Ci.IOnionAliasService + ); + service.addOnionAlias(shortOnionHost, longOnionHost); + } + + _clear() { + const service = Cc["@torproject.org/onion-alias-service;1"].getService( + Ci.IOnionAliasService + ); + service.clearOnionAliases(); + } + + _applyMappings() { + this._clear(); + for (const ch of this._channels.values()) { + if (!ch.enabled) { + continue; + } + for (const [short, long] of ch.mappings) { + this._addMapping(short, long); + } + } + } + + async _periodicRulesetCheck() { + if (!this.enabled) { + log.debug("Onion Aliases are disabled, not updating rulesets."); + return; + } + log.debug("Begin scheduled ruleset update"); + this._lastCheck = Date.now(); + let anyUpdated = false; + for (const ch of this._channels.values()) { + if (!ch.enabled) { + log.debug(`Not updating ${ch.name} because not enabled`); + continue; + } + log.debug(`Updating ${ch.name}`); + try { + await ch.updateMappings(); + anyUpdated = true; + } catch (err) { + log.error(`Could not update mappings for channel ${ch.name}`, err); + } + } + if (anyUpdated) { + this._saveSettings(); + this._applyMappings(); + this._notifyChanges(); + } else { + log.debug("No channel has been updated, avoid saving"); + } + this._scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL); + } + + async _startUpdates() { + // This is a "private" function, so we expect the callers to verify wheter + // onion aliases are enabled. + // Callees will also do, so we avoid an additional check here. + const dt = Date.now() - this._lastCheck; + let force = false; + for (const ch of this._channels.values()) { + if (ch.enabled && !ch.currentTimestamp) { + // Edited while being offline or some other error happened + force = true; + break; + } + } + if (dt > _OnionAliasStore.RULESET_CHECK_INTERVAL || force) { + log.debug( + `Mappings are stale (${dt}), or force check requested (${force}), checking them immediately` + ); + await this._periodicRulesetCheck(); + } else { + this._scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL - dt); + } + } + + _scheduleCheck(dt) { + if (this._rulesetTimeout) { + log.warn("The previous update timeout was not null"); + clearTimeout(this._rulesetTimeout); + } + if (!this.enabled) { + log.warn( + "Ignoring the scheduling of a new check because the Onion Alias feature is currently disabled." + ); + this._rulesetTimeout = null; + return; + } + log.debug(`Scheduling ruleset update in ${dt}`); + this._rulesetTimeout = setTimeout(() => { + this._rulesetTimeout = null; + this._periodicRulesetCheck(); + }, dt); + } + + _notifyChanges() { + Services.obs.notifyObservers( + Array.from(this._channels.values(), ch => ch.toJSON()), + OnionAliasStoreTopics.ChannelsChanged + ); + } + + get enabled() { + return Services.prefs.getBoolPref(kPrefOnionAliasEnabled, true); + } + + observe(aSubject, aTopic) { + if (aTopic === "nsPref:changed") { + if (this.enabled) { + this._startUpdates(); + } else if (this._rulesetTimeout) { + clearTimeout(this._rulesetTimeout); + this._rulesetTimeout = null; + } + } + } +} + +export const OnionAliasStore = new _OnionAliasStore(); diff --git a/browser/components/onionservices/OnionLocationChild.sys.mjs b/browser/components/onionservices/OnionLocationChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..9b2a9ff353b58d8d9f565a4866dfae7b9ca1d375 --- /dev/null +++ b/browser/components/onionservices/OnionLocationChild.sys.mjs @@ -0,0 +1,45 @@ +// Copyright (c) 2020, The Tor Project, Inc. + +/** + * This class contains the child part of Onion Location. + */ +export class OnionLocationChild extends JSWindowActorChild { + handleEvent(event) { + this.onPageShow(event); + } + + onPageShow(event) { + if (event.target != this.document) { + return; + } + const onionLocationURI = this.document.onionLocationURI; + if (onionLocationURI) { + this.sendAsyncMessage("OnionLocation:Set"); + } + } + + receiveMessage(aMessage) { + if (aMessage.name == "OnionLocation:Refresh") { + const doc = this.document; + const docShell = this.docShell; + let onionLocationURI = doc.onionLocationURI; + const refreshURI = docShell.QueryInterface(Ci.nsIRefreshURI); + if (onionLocationURI && refreshURI) { + const docUrl = new URL(doc.URL); + let onionUrl = new URL(onionLocationURI.asciiSpec); + // Keep consistent with Location + if (!onionUrl.hash && docUrl.hash) { + onionUrl.hash = docUrl.hash; + onionLocationURI = Services.io.newURI(onionUrl.toString()); + } + refreshURI.refreshURI( + onionLocationURI, + doc.nodePrincipal, + 0, + false, + true + ); + } + } + } +} diff --git a/browser/components/onionservices/OnionLocationParent.sys.mjs b/browser/components/onionservices/OnionLocationParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..d30e6a7defdab0856c47288c085fdcec01b4ee4c --- /dev/null +++ b/browser/components/onionservices/OnionLocationParent.sys.mjs @@ -0,0 +1,165 @@ +// Copyright (c) 2020, The Tor Project, Inc. + +import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs"; + +// Prefs + +// We keep the "prioritizeonions" name, even if obsolete, in order to +// prevent the notification from being shown again to upgrading users. +const NOTIFICATION_PREF = "privacy.prioritizeonions.showNotification"; + +// Element IDs +const ONIONLOCATION_BOX_ID = "onion-location-box"; +const ONIONLOCATION_LABEL_ID = "onion-label"; + +// Notification IDs +const NOTIFICATION_ID = "onion-location"; +const NOTIFICATION_ANCHOR_ID = "onion-location-box"; + +// Strings +const STRING_ONION_AVAILABLE = TorStrings.onionLocation.onionAvailable; +const NOTIFICATION_CANCEL_LABEL = TorStrings.onionLocation.notNow; +const NOTIFICATION_CANCEL_ACCESSKEY = TorStrings.onionLocation.notNowAccessKey; +const NOTIFICATION_OK_LABEL = TorStrings.onionLocation.loadOnion; +const NOTIFICATION_OK_ACCESSKEY = TorStrings.onionLocation.loadOnionAccessKey; +const NOTIFICATION_TITLE = TorStrings.onionLocation.tryThis; +const NOTIFICATION_DESCRIPTION = TorStrings.onionLocation.description; +const NOTIFICATION_LEARN_MORE_URL = + TorStrings.onionLocation.learnMoreURLNotification; + +/** + * This class contains the parent part of Onion Location. + */ +export class OnionLocationParent extends JSWindowActorParent { + // Listeners are added in BrowserGlue.jsm + receiveMessage(aMsg) { + switch (aMsg.name) { + case "OnionLocation:Set": + let browser = this.browsingContext.embedderElement; + OnionLocationParent.setOnionLocation(browser); + break; + } + } + + static buttonClick(event) { + if (event.button !== 0) { + return; + } + const win = event.target.ownerGlobal; + if (win.gBrowser) { + const browser = win.gBrowser.selectedBrowser; + OnionLocationParent.redirect(browser); + } + } + + static redirect(browser) { + let windowGlobal = browser.browsingContext.currentWindowGlobal; + let actor = windowGlobal.getActor("OnionLocation"); + if (actor) { + actor.sendAsyncMessage("OnionLocation:Refresh", {}); + OnionLocationParent.setDisabled(browser); + } + } + + static onStateChange(browser) { + delete browser._onionLocation; + OnionLocationParent.hideNotification(browser); + } + + static setOnionLocation(browser) { + browser._onionLocation = true; + let tabBrowser = browser.getTabBrowser(); + if (tabBrowser && browser === tabBrowser.selectedBrowser) { + OnionLocationParent.updateOnionLocationBadge(browser); + } + } + + static hideNotification(browser) { + const win = browser.ownerGlobal; + if (browser._onionLocationPrompt) { + win.PopupNotifications.remove(browser._onionLocationPrompt); + } + } + + static showNotification(browser) { + const mustShow = Services.prefs.getBoolPref(NOTIFICATION_PREF, true); + if (!mustShow) { + return; + } + + const win = browser.ownerGlobal; + Services.prefs.setBoolPref(NOTIFICATION_PREF, false); + + const mainAction = { + label: NOTIFICATION_OK_LABEL, + accessKey: NOTIFICATION_OK_ACCESSKEY, + callback() { + OnionLocationParent.redirect(browser); + }, + }; + + const cancelAction = { + label: NOTIFICATION_CANCEL_LABEL, + accessKey: NOTIFICATION_CANCEL_ACCESSKEY, + callback: () => {}, + }; + + win.document.getElementById("onion-location-body-text").textContent = + NOTIFICATION_DESCRIPTION; + + const options = { + autofocus: true, + persistent: true, + removeOnDismissal: false, + eventCallback(aTopic) { + if (aTopic === "removed") { + delete browser._onionLocationPrompt; + } + }, + learnMoreURL: NOTIFICATION_LEARN_MORE_URL, + hideClose: true, + popupOptions: { + position: "bottomright topright", + }, + }; + + // A hacky way of setting the popup anchor outside the usual url bar icon + // box, similar to CRF and addons. + // See: https://searchfox.org/mozilla-esr115/rev/7962d6b7b17ee105ad64ab7906af2b9179f6e3d2/toolkit/modules/PopupNotifications.sys.mjs#46 + browser[NOTIFICATION_ANCHOR_ID + "popupnotificationanchor"] = + win.document.getElementById(NOTIFICATION_ANCHOR_ID); + + browser._onionLocationPrompt = win.PopupNotifications.show( + browser, + NOTIFICATION_ID, + NOTIFICATION_TITLE, + NOTIFICATION_ANCHOR_ID, + mainAction, + [cancelAction], + options + ); + } + + static setEnabled(browser) { + const win = browser.ownerGlobal; + const label = win.document.getElementById(ONIONLOCATION_LABEL_ID); + label.textContent = STRING_ONION_AVAILABLE; + const elem = win.document.getElementById(ONIONLOCATION_BOX_ID); + elem.removeAttribute("hidden"); + } + + static setDisabled(browser) { + const win = browser.ownerGlobal; + const elem = win.document.getElementById(ONIONLOCATION_BOX_ID); + elem.setAttribute("hidden", true); + } + + static updateOnionLocationBadge(browser) { + if (browser._onionLocation) { + OnionLocationParent.setEnabled(browser); + OnionLocationParent.showNotification(browser); + } else { + OnionLocationParent.setDisabled(browser); + } + } +} diff --git a/browser/components/onionservices/TorRequestWatch.sys.mjs b/browser/components/onionservices/TorRequestWatch.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..fb671774a06fa9a82ccba1837b083b99b9d27c95 --- /dev/null +++ b/browser/components/onionservices/TorRequestWatch.sys.mjs @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const log = console.createInstance({ + maxLogLevelPref: "browser.torRequestWatch.log_level", + prefix: "TorRequestWatch", +}); + +/** + * This request observer blocks all the cross-site requests to *.tor.onion + * domains to prevent fingerprinting Onion alias mechanisms (or their lack). + */ +class RequestObserver { + static #topics = [ + "http-on-modify-request", + "http-on-examine-response", + "http-on-examine-cached-response", + "http-on-examine-merged-response", + ]; + #asObserver(addOrRemove) { + const action = Services.obs[`${addOrRemove}Observer`].bind(Services.obs); + for (const topic of RequestObserver.#topics) { + action(this, topic); + } + } + + start() { + this.#asObserver("add"); + log.debug("Started"); + } + stop() { + this.#asObserver("remove"); + log.debug("Stopped"); + } + + // nsIObserver implementation + observe(subject, topic) { + try { + let channel = ChannelWrapper.get( + subject.QueryInterface(Ci.nsIHttpChannel) + ); + switch (topic) { + case "http-on-modify-request": + this.onRequest(channel); + break; + case "http-on-examine-cached-response": + case "http-on-examine-merged-response": + channel.isCached = true; + // falls through + case "http-on-examine-response": + this.onResponse(channel); + break; + } + } catch (e) { + log.error(e); + } + } + + onRequest(channel) { + if (this.shouldBlind(channel, channel.documentURL)) { + log.warn(`Blocking cross-site ${channel.finalURL} ${channel.type} load.`); + channel.cancel(Cr.NS_ERROR_ABORT); + } + } + onResponse(channel) { + if (!channel.documentURL && this.shouldBlind(channel, channel.originURL)) { + const COOP = "cross-origin-opener-policy"; + // we break window.opener references if needed to mitigate XS-Leaks + for (let h of channel.getResponseHeaders()) { + if (h.name.toLowerCase() === COOP && h.value === "same-origin") { + log.debug(`${COOP} is already same-origin, nothing to do.`); + return; + } + } + log.warn(`Blinding cross-site ${channel.finalURL} load.`); + channel.setResponseHeader(COOP, "same-origin-allow-popups"); + } + } + + isCrossOrigin(url1, url2) { + return new URL(url1).origin !== new URL(url2).origin; + } + shouldBlindCrossOrigin(uri) { + try { + let { host } = uri; + if (host.endsWith(".onion")) { + const previousPart = host.slice(-10, -6); + return ( + previousPart && (previousPart === ".tor" || previousPart === ".bit") + ); + } + } catch (e) { + // no host + } + return false; + } + shouldBlind(channel, sourceURL) { + return ( + sourceURL && + this.shouldBlindCrossOrigin(channel.finalURI) && + this.isCrossOrigin(channel.finalURL, sourceURL) + ); + } +} + +let observer; +export const TorRequestWatch = { + start() { + if (!observer) { + (observer = new RequestObserver()).start(); + } + }, + stop() { + if (observer) { + observer.stop(); + observer = null; + } + }, +}; diff --git a/browser/components/onionservices/content/authNotificationIcon.inc.xhtml b/browser/components/onionservices/content/authNotificationIcon.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..70f43dbd295a81fc9035e6ada288e41b6dbbb3e2 --- /dev/null +++ b/browser/components/onionservices/content/authNotificationIcon.inc.xhtml @@ -0,0 +1,6 @@ +# Copyright (c) 2020, The Tor Project, Inc. + +<image id="tor-clientauth-notification-icon" + class="notification-anchor-icon tor-clientauth-icon" + role="button" + data-l10n-id="onion-site-authentication-urlbar-button"/> diff --git a/browser/components/onionservices/content/authPopup.inc.xhtml b/browser/components/onionservices/content/authPopup.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..feceb7d4b6526c95d3425596212a6378170e1f10 --- /dev/null +++ b/browser/components/onionservices/content/authPopup.inc.xhtml @@ -0,0 +1,41 @@ +# Copyright (c) 2020, The Tor Project, Inc. + +<popupnotification id="tor-clientauth-notification" hidden="true"> + <popupnotificationcontent orient="vertical"> + <description id="tor-clientauth-notification-desc" /> + <label + class="text-link popup-notification-learnmore-link" + is="text-link" + href="about:manual#onion-services_onion-service-authentication" + useoriginprincipal="true" + data-l10n-id="onion-site-authentication-prompt-learn-more" + /> + <html:div> + <!-- NOTE: Orca 46.2 will not say "invalid" for "type=password". See + - https://gitlab.gnome.org/GNOME/orca/-/issues/550 + - Moreover, it will ignore the aria-errormessage relation when we are + - not in a document context. See related bugzilla bug 1820765. --> + <html:input + id="tor-clientauth-notification-key" + type="password" + data-l10n-id="onion-site-authentication-prompt-key-input" + aria-errormessage="tor-clientauth-warning" + /> + <html:div + id="tor-clientauth-warning" + role="alert" + aria-labelledby="tor-clientauth-warning-text" + > + <!-- NOTE: Orca 46.2 treats this notification as non-document context. + - As such it seems to only read out the alert content if it contains + - a <xul:label>, <html:label> or if it has an accessible name. + - We use aria-labelledby here. --> + <html:span id="tor-clientauth-warning-text"></html:span> + </html:div> + <checkbox + id="tor-clientauth-persistkey-checkbox" + data-l10n-id="onion-site-authentication-prompt-remember-checkbox" + /> + </html:div> + </popupnotificationcontent> +</popupnotification> diff --git a/browser/components/onionservices/content/authPreferences.css b/browser/components/onionservices/content/authPreferences.css new file mode 100644 index 0000000000000000000000000000000000000000..de5bb30b2f217c78a76dfe4ad322c96cf0df3377 --- /dev/null +++ b/browser/components/onionservices/content/authPreferences.css @@ -0,0 +1,37 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ + +#onionservices-savedkeys-dialog { + min-width: 45em; +} + +#onionservices-savedkeys-tree treechildren::-moz-tree-cell-text { + font-size: 80%; +} + +#onionservices-savedkeys-errorContainer { + margin-block-start: 4px; + min-height: 3em; +} + +#onionservices-savedkeys-errorContainer:not(.show-error) { + visibility: hidden; +} + +#onionservices-savedkeys-errorIcon { + margin-inline-end: 4px; + list-style-image: url("chrome://global/skin/icons/warning.svg"); + -moz-context-properties: fill; + fill: var(--in-content-warning-icon-color); +} + +/* Make a button appear disabled, whilst still allowing it to keep keyboard + * focus. + * Duplicate of rule in torPreferences.css. + * TODO: Replace with moz-button when it handles this for us. See + * tor-browser#43275. */ +button.spoof-button-disabled { + /* Borrow the :disabled rule from common-shared.css */ + opacity: 0.4; + /* Also ensure it does not get hover or active styling. */ + pointer-events: none; +} diff --git a/browser/components/onionservices/content/authPreferences.inc.xhtml b/browser/components/onionservices/content/authPreferences.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..136fa01ce9ddf30590ca6c9f011f6d73fbaf6046 --- /dev/null +++ b/browser/components/onionservices/content/authPreferences.inc.xhtml @@ -0,0 +1,34 @@ +# Copyright (c) 2020, The Tor Project, Inc. + +<groupbox id="torOnionServiceKeys" orient="vertical" + data-category="panePrivacy" hidden="true"> + <label><html:h2 + data-l10n-id="onion-site-authentication-preferences-heading" + ></html:h2></label> + <hbox> + <description + class="description-deemphasized description-with-side-element" + flex="1" + > + <html:span + id="torOnionServiceKeys-overview" + data-l10n-id="onion-site-authentication-preferences-overview" + ></html:span> + <label + id="torOnionServiceKeys-learnMore" + class="learnMore text-link" + is="text-link" + href="about:manual#onion-services_onion-service-authentication" + useoriginprincipal="true" + data-l10n-id="onion-site-authentication-preferences-learn-more" + /> + </description> + <vbox align="end"> + <html:button + id="torOnionServiceKeys-savedKeys" + class="accessory-button" + data-l10n-id="onion-site-authentication-preferences-saved-keys-button" + ></html:button> + </vbox> + </hbox> +</groupbox> diff --git a/browser/components/onionservices/content/authPreferences.js b/browser/components/onionservices/content/authPreferences.js new file mode 100644 index 0000000000000000000000000000000000000000..be27974adaa8e39de48fafe030f274e88c1fb5de --- /dev/null +++ b/browser/components/onionservices/content/authPreferences.js @@ -0,0 +1,20 @@ +// Copyright (c) 2020, The Tor Project, Inc. + +"use strict"; + +/* import-globals-from /browser/components/preferences/preferences.js */ + +/** + * Onion site preferences. + */ +var OnionServicesAuthPreferences = { + init() { + document + .getElementById("torOnionServiceKeys-savedKeys") + .addEventListener("click", () => { + gSubDialog.open( + "chrome://browser/content/onionservices/savedKeysDialog.xhtml" + ); + }); + }, +}; diff --git a/browser/components/onionservices/content/authPrompt.js b/browser/components/onionservices/content/authPrompt.js new file mode 100644 index 0000000000000000000000000000000000000000..a209317dc5ed09e6762f083e0ae5570133e3e4dc --- /dev/null +++ b/browser/components/onionservices/content/authPrompt.js @@ -0,0 +1,435 @@ +/* eslint-env mozilla/browser-window */ + +"use strict"; + +var OnionAuthPrompt = { + // Only import to our internal scope, rather than the global scope of + // browser.xhtml. + _lazy: {}, + + /** + * The topics to listen to. + * + * @type {{[key: string]: string}} + */ + _topics: { + clientAuthMissing: "tor-onion-services-clientauth-missing", + clientAuthIncorrect: "tor-onion-services-clientauth-incorrect", + }, + + /** + * @typedef {object} PromptDetails + * + * @property {Browser} browser - The browser this prompt is for. + * @property {string} cause - The notification that cause this prompt. + * @property {string} onionHost - The onion host name. + * @property {nsIURI} uri - The browser URI when the notification was + * triggered. + * @property {string} onionServiceId - The onion service ID for this host. + * @property {Notification} [notification] - The notification instance for + * this prompt. + */ + + /** + * The currently shown details in the prompt. + * + * @type {?PromptDetails} + */ + _shownDetails: null, + + /** + * Used for logging to represent PromptDetails. + * + * @param {PromptDetails} details - The details to represent. + * @returns {string} - The representation of these details. + */ + _detailsRepr(details) { + if (!details) { + return "none"; + } + return `${details.browser.browserId}:${details.onionHost}`; + }, + + /** + * Show a new prompt, using the given details. + * + * @param {PromptDetails} details - The details to show. + */ + show(details) { + this._logger.debug(`New Notification: ${this._detailsRepr(details)}`); + + // NOTE: PopupNotifications currently requires the accesskey and label to be + // set for all actions, and does not accept fluent IDs in their place. + // Moreover, there doesn't appear to be a simple way to work around this, so + // we have to fetch the strings here before calling the show() method. + // NOTE: We avoid using the async formatMessages because we don't want to + // race against the browser's location changing. + // In principle, we could check that the details.browser.currentURI still + // matches details.uri or use a LocationChange listener. However, we expect + // that PopupNotifications will eventually change to accept fluent IDs, so + // we won't have to use formatMessages here at all. + // Moreover, we do not expect this notification to be common, so this + // shouldn't be too expensive. + // NOTE: Once we call PopupNotifications.show, PopupNotifications should + // take care of listening for changes in locations for us and remove the + // notification. + let [okButtonMsg, cancelButtonMsg] = this._lazy.SyncL10n.formatMessagesSync( + [ + "onion-site-authentication-prompt-ok-button", + "onion-site-authentication-prompt-cancel-button", + ] + ); + + // Get an attribute string from a L10nMessage. + // We wrap the return value as a String to prevent the notification from + // throwing (and not showing) if a locale is unexpectedly missing a value. + const msgAttribute = (msg, name) => + String((msg.attributes ?? []).find(attr => attr.name === name)?.value); + + let mainAction = { + label: msgAttribute(okButtonMsg, "label"), + accessKey: msgAttribute(okButtonMsg, "accesskey"), + leaveOpen: true, // Callback is responsible for closing the notification. + callback: () => this._onDone(), + }; + + // The first secondarybuttoncommand (cancelAction) should be triggered when + // the user presses "Escape". + let cancelAction = { + label: msgAttribute(cancelButtonMsg, "label"), + accessKey: msgAttribute(cancelButtonMsg, "accesskey"), + callback: () => this._onCancel(), + }; + + let options = { + autofocus: true, + hideClose: true, + persistent: true, + removeOnDismissal: false, + eventCallback: topic => { + if (topic === "showing") { + this._onPromptShowing(details); + } else if (topic === "shown") { + this._onPromptShown(); + } else if (topic === "removed") { + this._onPromptRemoved(details); + } + }, + }; + + details.notification = PopupNotifications.show( + details.browser, + "tor-clientauth", + "", + "tor-clientauth-notification-icon", + mainAction, + [cancelAction], + options + ); + }, + + /** + * Callback when the prompt is about to be shown. + * + * @param {PromptDetails?} details - The details to show, or null to shown + * none. + */ + _onPromptShowing(details) { + if (details === this._shownDetails) { + // The last shown details match this one exactly. + // This happens when we switch tabs to a page that has no prompt and then + // switch back. + // We don't want to reset the current state in this case. + // In particular, we keep the current _keyInput value and _persistCheckbox + // the same. + this._logger.debug(`Already showing: ${this._detailsRepr(details)}`); + return; + } + + this._logger.debug(`Now showing: ${this._detailsRepr(details)}`); + + this._shownDetails = details; + + // Clear the key input. + // In particular, clear the input when switching tabs. + this._keyInput.value = ""; + this._persistCheckbox.checked = false; + + document.l10n.setAttributes( + this._descriptionEl, + "onion-site-authentication-prompt-description", + { + onionsite: TorUIUtils.shortenOnionAddress( + this._shownDetails?.onionHost ?? "" + ), + } + ); + + this._showWarning(null); + }, + + /** + * Callback after the prompt is shown. + */ + _onPromptShown() { + this._keyInput.focus(); + }, + + /** + * Callback when a Notification is removed. + * + * @param {PromptDetails} details - The details for the removed notification. + */ + _onPromptRemoved(details) { + if (details !== this._shownDetails) { + // Removing the notification for some other page. + // For example, closing another tab that also requires authentication. + this._logger.debug(`Removed not shown: ${this._detailsRepr(details)}`); + return; + } + this._logger.debug(`Removed shown: ${this._detailsRepr(details)}`); + // Reset the prompt as a precaution. + // In particular, we want to clear the input so that the entered key does + // not persist. + this._onPromptShowing(null); + }, + + /** + * Callback when the user submits the key. + */ + async _onDone() { + this._logger.debug( + `Sumbitting key: ${this._detailsRepr(this._shownDetails)}` + ); + + // Grab the details before they might change as we await. + const details = this._shownDetails; + const { browser, onionServiceId, notification } = details; + const isPermanent = this._persistCheckbox.checked; + + const base64key = this._keyToBase64(this._keyInput.value); + if (!base64key) { + this._showWarning("onion-site-authentication-prompt-invalid-key"); + return; + } + + try { + const provider = await this._lazy.TorProviderBuilder.build(); + await provider.onionAuthAdd(onionServiceId, base64key, isPermanent); + } catch (e) { + this._logger.error(`Failed to set key for ${onionServiceId}`, e); + if (details === this._shownDetails) { + // Notification has not been replaced. + this._showWarning( + "onion-site-authentication-prompt-setting-key-failed" + ); + } + return; + } + + notification.remove(); + // Success! Reload the page. + browser.reload(); + }, + + /** + * Callback when the user dismisses the prompt. + */ + _onCancel() { + // Arrange for an error page to be displayed: + // we build a short script calling docShell.displayError() + // and we pass it as a data: URI to loadFrameScript(), + // which runs it in the content frame which triggered + // this authentication prompt. + this._logger.debug(`Cancelling: ${this._detailsRepr(this._shownDetails)}`); + + const { browser, cause, uri } = this._shownDetails; + const errorCode = + cause === this._topics.clientAuthMissing + ? Cr.NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH + : Cr.NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH; + browser.messageManager.loadFrameScript( + `data:application/javascript,${encodeURIComponent( + `docShell.displayLoadError(${errorCode}, Services.io.newURI(${JSON.stringify( + uri.spec + )}), undefined, undefined);` + )}`, + false + ); + }, + + /** + * Show a warning message to the user or clear the warning. + * + * @param {?string} warningMessageId - The l10n ID for the message to show, or + * null to clear the current message. + */ + _showWarning(warningMessageId) { + this._logger.debug(`Showing warning: ${warningMessageId}`); + + if (warningMessageId) { + document.l10n.setAttributes(this._warningTextEl, warningMessageId); + this._warningEl.removeAttribute("hidden"); + this._keyInput.classList.add("invalid"); + this._keyInput.setAttribute("aria-invalid", "true"); + } else { + this._warningTextEl.removeAttribute("data-l10n-id"); + this._warningTextEl.textContent = ""; + this._warningEl.setAttribute("hidden", "true"); + this._keyInput.classList.remove("invalid"); + this._keyInput.removeAttribute("aria-invalid"); + } + }, + + /** + * Convert the user-entered key into base64. + * + * @param {string} keyString - The key to convert. + * @returns {?string} - The base64 representation, or undefined if the given + * key was not the correct format. + */ + _keyToBase64(keyString) { + if (!keyString) { + return undefined; + } + + let base64key; + if (keyString.length === 52) { + // The key is probably base32-encoded. Attempt to decode. + // Although base32 specifies uppercase letters, we accept lowercase + // as well because users may type in lowercase or copy a key out of + // a tor onion-auth file (which uses lowercase). + let rawKey; + try { + rawKey = this._lazy.CommonUtils.decodeBase32(keyString.toUpperCase()); + } catch (e) {} + + if (rawKey) { + try { + base64key = btoa(rawKey); + } catch (e) {} + } + } else if ( + keyString.length === 44 && + /^[a-zA-Z0-9+/]*=*$/.test(keyString) + ) { + // The key appears to be a correctly formatted base64 value. If not, + // tor will return an error when we try to add the key via the + // control port. + base64key = keyString; + } + + return base64key; + }, + + /** + * Initialize the authentication prompt. + */ + init() { + this._logger = console.createInstance({ + prefix: "OnionAuthPrompt", + maxLogLevelPref: "browser.onionAuthPrompt.loglevel", + }); + + ChromeUtils.defineESModuleGetters(this._lazy, { + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + CommonUtils: "resource://services-common/utils.sys.mjs", + }); + // Allow synchornous access to the localized strings. Used only for the + // button actions, which is currently a hard requirement for + // PopupNotifications.show. Hopefully, PopupNotifications will accept fluent + // ids in their place, or get replaced with something else that does. + ChromeUtils.defineLazyGetter(this._lazy, "SyncL10n", () => { + return new Localization(["toolkit/global/tor-browser.ftl"], true); + }); + + this._keyInput = document.getElementById("tor-clientauth-notification-key"); + this._persistCheckbox = document.getElementById( + "tor-clientauth-persistkey-checkbox" + ); + this._warningEl = document.getElementById("tor-clientauth-warning"); + this._warningTextEl = document.getElementById( + "tor-clientauth-warning-text" + ); + this._descriptionEl = document.getElementById( + "tor-clientauth-notification-desc" + ); + + this._keyInput.addEventListener("keydown", event => { + if (event.key === "Enter") { + event.preventDefault(); + this._onDone(); + } + }); + this._keyInput.addEventListener("input", () => { + // Remove the warning. + this._showWarning(null); + }); + + // Force back focus on click: tor-browser#41856 + document + .getElementById("tor-clientauth-notification") + .addEventListener("click", () => { + window.focus(); + }); + + Services.obs.addObserver(this, this._topics.clientAuthMissing); + Services.obs.addObserver(this, this._topics.clientAuthIncorrect); + }, + + /** + * Un-initialize the authentication prompt. + */ + uninit() { + Services.obs.removeObserver(this, this._topics.clientAuthMissing); + Services.obs.removeObserver(this, this._topics.clientAuthIncorrect); + }, + + observe(subject, topic, data) { + if ( + topic !== this._topics.clientAuthMissing && + topic !== this._topics.clientAuthIncorrect + ) { + return; + } + + // "subject" is the DOM window or browser where the prompt should be shown. + let browser; + if (subject instanceof Ci.nsIDOMWindow) { + let contentWindow = subject.QueryInterface(Ci.nsIDOMWindow); + browser = contentWindow.docShell.chromeEventHandler; + } else { + browser = subject.QueryInterface(Ci.nsIBrowser); + } + + if (!gBrowser.browsers.includes(browser)) { + // This window does not contain the subject browser. + this._logger.debug( + `Window ${window.docShell.outerWindowID}: Ignoring ${topic}` + ); + return; + } + this._logger.debug( + `Window ${window.docShell.outerWindowID}: Handling ${topic}` + ); + + const onionHost = data; + // ^(subdomain.)*onionserviceid.onion$ (case-insensitive) + const onionServiceId = onionHost + .match(/^(.*\.)?(?<onionServiceId>[a-z2-7]{56})\.onion$/i) + ?.groups.onionServiceId.toLowerCase(); + if (!onionServiceId) { + this._logger.error(`Malformed onion address: ${onionHost}`); + return; + } + + const details = { + browser, + cause: topic, + onionHost, + uri: browser.currentURI, + onionServiceId, + }; + this.show(details); + }, +}; diff --git a/browser/components/onionservices/content/onionlocation-urlbar.inc.xhtml b/browser/components/onionservices/content/onionlocation-urlbar.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..e4b2f69460171fc077f8b5c7366c78d5b2e34c1e --- /dev/null +++ b/browser/components/onionservices/content/onionlocation-urlbar.inc.xhtml @@ -0,0 +1,10 @@ +# Copyright (c) 2020, The Tor Project, Inc. + +<hbox id="onion-location-box" + class="tor-button tor-urlbar-button" + role="button" + hidden="true" + onclick="OnionLocationParent.buttonClick(event);"> + <image id="onion-location-button" role="presentation"/> + <label id="onion-label"/> +</hbox> diff --git a/browser/components/onionservices/content/onionlocation.css b/browser/components/onionservices/content/onionlocation.css new file mode 100644 index 0000000000000000000000000000000000000000..4985848285e140cc96b51e679631f17f85fe5cc4 --- /dev/null +++ b/browser/components/onionservices/content/onionlocation.css @@ -0,0 +1,7 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ + +#onion-location-button { + list-style-image: url(chrome://global/skin/icons/onion-site.svg); + -moz-context-properties: fill; + fill: currentColor; +} diff --git a/browser/components/onionservices/content/onionservices.css b/browser/components/onionservices/content/onionservices.css new file mode 100644 index 0000000000000000000000000000000000000000..6968271df11bb54be25e70ea07b162930136fc3e --- /dev/null +++ b/browser/components/onionservices/content/onionservices.css @@ -0,0 +1,67 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ + +#tor-clientauth-notification-desc { + font-weight: bold; +} + +#tor-clientauth-notification-key { + box-sizing: border-box; + width: 100%; + margin-top: 15px; + padding: 6px; +} + +/* Start of rules adapted from + * browser/components/newtab/css/activity-stream-mac.css (linux and windows + * use the same rules). + */ +#tor-clientauth-notification-key.invalid { + border: 1px solid #D70022; + box-shadow: 0 0 0 1px #D70022, 0 0 0 4px rgba(215, 0, 34, 0.3); +} + +#tor-clientauth-warning { + display: inline-block; + animation: fade-up-tt 450ms; + background: #D70022; + border-radius: 2px; + color: #FFF; + inset-inline-start: 3px; + padding: 5px 12px; + position: relative; + top: 6px; + z-index: 1; +} + +#tor-clientauth-warning[hidden] { + display: none; +} + +#tor-clientauth-warning::before { + background: #D70022; + bottom: -8px; + content: '.'; + height: 16px; + inset-inline-start: 12px; + position: absolute; + text-indent: -999px; + top: -7px; + transform: rotate(45deg); + white-space: nowrap; + width: 16px; + z-index: -1; +} + +@keyframes fade-up-tt { + 0% { + opacity: 0; + transform: translateY(15px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} +/* End of rules adapted from + * browser/components/newtab/css/activity-stream-mac.css + */ diff --git a/browser/components/onionservices/content/savedKeysDialog.js b/browser/components/onionservices/content/savedKeysDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..2357223e36c20a5f2a9e90b7773f1512af7d5d40 --- /dev/null +++ b/browser/components/onionservices/content/savedKeysDialog.js @@ -0,0 +1,291 @@ +// Copyright (c) 2020, The Tor Project, Inc. + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", +}); + +var gOnionServicesSavedKeysDialog = { + _tree: undefined, + _busyCount: 0, + get _isBusy() { + // true when loading data, deleting a key, etc. + return this._busyCount > 0; + }, + + /** + * Whether the "remove selected" button is disabled. + * + * @type {boolean} + */ + _removeSelectedDisabled: true, + + /** + * Whether the "remove all" button is disabled. + * + * @type {boolean} + */ + _removeAllDisabled: true, + + async _deleteSelectedKeys() { + this._showError(null); + this._withBusy(async () => { + const indexesToDelete = []; + const count = this._tree.view.selection.getRangeCount(); + for (let i = 0; i < count; ++i) { + const minObj = {}; + const maxObj = {}; + this._tree.view.selection.getRangeAt(i, minObj, maxObj); + for (let idx = minObj.value; idx <= maxObj.value; ++idx) { + indexesToDelete.push(idx); + } + } + + if (indexesToDelete.length) { + const provider = await TorProviderBuilder.build(); + try { + // Remove in reverse index order to avoid issues caused by index + // changes. + for (let i = indexesToDelete.length - 1; i >= 0; --i) { + await this._deleteOneKey(provider, indexesToDelete[i]); + } + // If successful and the user focus is still on the buttons move focus + // to the table with the updated state. We do this before calling + // _updateButtonState and potentially making the buttons disabled. + if ( + this._removeButton.contains(document.activeElement) || + this._removeAllButton.contains(document.activeElement) + ) { + this._tree.focus(); + } + } catch (e) { + console.error("Removing a saved key failed", e); + this._showError( + "onion-site-saved-keys-dialog-remove-keys-error-message" + ); + } + } + }); + }, + + async _deleteAllKeys() { + this._tree.view.selection.selectAll(); + await this._deleteSelectedKeys(); + }, + + /** + * Show the given button as being disabled or enabled. + * + * @param {Button} button - The button to change. + * @param {boolean} disable - Whether to show the button as disabled or + * enabled. + */ + _disableButton(button, disable) { + // If we are disabled we show the button as disabled, and we also remove it + // from the tab focus cycle using `tabIndex = -1`. + // This is similar to using the `disabled` attribute, except that + // `tabIndex = -1` still allows the button to be focusable. I.e. not part of + // the focus cycle but can *keep* existing focus when the button becomes + // disabled to avoid loosing focus to the top of the dialog. + // TODO: Replace with moz-button when it handles this for us. See + // tor-browser#43275. + button.classList.toggle("spoof-button-disabled", disable); + button.tabIndex = disable ? -1 : 0; + if (disable) { + this._removeButton.setAttribute("aria-disabled", "true"); + } else { + this._removeButton.removeAttribute("aria-disabled"); + } + }, + + _updateButtonsState() { + const haveSelection = this._tree.view.selection.getRangeCount() > 0; + this._removeSelectedDisabled = this._isBusy || !haveSelection; + this._removeAllDisabled = this._isBusy || this.rowCount === 0; + this._disableButton(this._removeButton, this._removeSelectedDisabled); + this._disableButton(this._removeAllButton, this._removeAllDisabled); + }, + + // Private functions. + _onLoad() { + document.mozSubdialogReady = this._init(); + }, + + _init() { + this._populateXUL(); + window.addEventListener("keypress", this._onWindowKeyPress.bind(this)); + this._loadSavedKeys(); + }, + + _populateXUL() { + this._errorMessageContainer = document.getElementById( + "onionservices-savedkeys-errorContainer" + ); + this._errorMessageEl = document.getElementById( + "onionservices-savedkeys-errorMessage" + ); + this._removeButton = document.getElementById( + "onionservices-savedkeys-remove" + ); + this._removeButton.addEventListener("click", () => { + if (this._removeSelectedDisabled) { + return; + } + this._deleteSelectedKeys(); + }); + this._removeAllButton = document.getElementById( + "onionservices-savedkeys-removeall" + ); + this._removeAllButton.addEventListener("click", () => { + if (this._removeAllDisabled) { + return; + } + this._deleteAllKeys(); + }); + + this._tree = document.getElementById("onionservices-savedkeys-tree"); + this._tree.addEventListener("select", () => { + this._updateButtonsState(); + }); + }, + + async _loadSavedKeys() { + this._showError(null); + this._withBusy(async () => { + try { + this._tree.view = this; + + const provider = await TorProviderBuilder.build(); + const keyInfoList = await provider.onionAuthViewKeys(); + if (keyInfoList) { + // Filter out temporary keys. + this._keyInfoList = keyInfoList.filter(aKeyInfo => + aKeyInfo.flags?.includes("Permanent") + ); + // Sort by the .onion address. + this._keyInfoList.sort((aObj1, aObj2) => { + const hsAddr1 = aObj1.address.toLowerCase(); + const hsAddr2 = aObj2.address.toLowerCase(); + if (hsAddr1 < hsAddr2) { + return -1; + } + return hsAddr1 > hsAddr2 ? 1 : 0; + }); + } + + // Render the tree content. + this._tree.rowCountChanged(0, this.rowCount); + } catch (e) { + console.error("Failed to load keys", e); + this._showError( + "onion-site-saved-keys-dialog-fetch-keys-error-message" + ); + } + }); + }, + + // This method may throw; callers should catch errors. + async _deleteOneKey(provider, aIndex) { + const keyInfoObj = this._keyInfoList[aIndex]; + await provider.onionAuthRemove(keyInfoObj.address); + this._tree.view.selection.clearRange(aIndex, aIndex); + this._keyInfoList.splice(aIndex, 1); + this._tree.rowCountChanged(aIndex + 1, -1); + }, + + async _withBusy(func) { + this._busyCount++; + if (this._busyCount === 1) { + this._updateButtonsState(); + } + try { + await func(); + } finally { + this._busyCount--; + if (this._busyCount === 0) { + this._updateButtonsState(); + } + } + }, + + _onWindowKeyPress(event) { + if (this._isBusy) { + return; + } + if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) { + window.close(); + } else if (event.keyCode === KeyEvent.DOM_VK_DELETE) { + this._deleteSelectedKeys(); + } + }, + + /** + * Show an error, or clear it. + * + * @param {?string} messageId - The l10n ID of the message to show, or null to + * clear it. + */ + _showError(messageId) { + this._errorMessageContainer.classList.toggle("show-error", !!messageId); + if (messageId) { + document.l10n.setAttributes(this._errorMessageEl, messageId); + } else { + // Clean up. + this._errorMessageEl.removeAttribute("data-l10n-id"); + this._errorMessageEl.textContent = ""; + } + }, + + // XUL tree widget view implementation. + get rowCount() { + return this._keyInfoList?.length ?? 0; + }, + + getCellText(aRow, aCol) { + if (this._keyInfoList && aRow < this._keyInfoList.length) { + const keyInfo = this._keyInfoList[aRow]; + if (aCol.id.endsWith("-siteCol")) { + return keyInfo.address; + } else if (aCol.id.endsWith("-keyCol")) { + // keyType is always "x25519", so do not show it. + return keyInfo.keyBlob; + } + } + return ""; + }, + + isSeparator(_index) { + return false; + }, + + isSorted() { + return false; + }, + + isContainer(_index) { + return false; + }, + + setTree(_tree) {}, + + getImageSrc(_row, _column) {}, + + getCellValue(_row, _column) {}, + + cycleHeader(_column) {}, + + getRowProperties(_row) { + return ""; + }, + + getColumnProperties(_column) { + return ""; + }, + + getCellProperties(_row, _column) { + return ""; + }, +}; + +window.addEventListener("load", () => gOnionServicesSavedKeysDialog._onLoad()); diff --git a/browser/components/onionservices/content/savedKeysDialog.xhtml b/browser/components/onionservices/content/savedKeysDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..5719b75cf7441de1ace0761215cb36acc8befee6 --- /dev/null +++ b/browser/components/onionservices/content/savedKeysDialog.xhtml @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<!-- Copyright (c) 2020, The Tor Project, Inc. --> + +<window + id="onionservices-savedkeys-dialog" + windowtype="OnionServices:SavedKeys" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="onion-site-saved-keys-dialog-title" +> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/onionservices/authPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/onionservices/savedKeysDialog.js" /> + + <vbox id="onionservices-savedkeys" class="contentPane" flex="1"> + <label + id="onionservices-savedkeys-intro" + control="onionservices-savedkeys-tree" + data-l10n-id="onion-site-saved-keys-dialog-intro" + /> + <separator class="thin" /> + <tree id="onionservices-savedkeys-tree" flex="1" hidecolumnpicker="true"> + <treecols> + <treecol + id="onionservices-savedkeys-siteCol" + flex="1" + persist="width" + data-l10n-id="onion-site-saved-keys-dialog-table-header-site" + /> + <splitter class="tree-splitter" /> + <treecol + id="onionservices-savedkeys-keyCol" + flex="1" + persist="width" + data-l10n-id="onion-site-saved-keys-dialog-table-header-key" + /> + </treecols> + <treechildren /> + </tree> + <hbox + id="onionservices-savedkeys-errorContainer" + align="center" + role="alert" + > + <image id="onionservices-savedkeys-errorIcon" /> + <description id="onionservices-savedkeys-errorMessage" flex="1" /> + </hbox> + <separator class="thin" /> + <hbox id="onionservices-savedkeys-buttons"> + <html:button + id="onionservices-savedkeys-remove" + data-l10n-id="onion-site-saved-keys-dialog-remove-button" + ></html:button> + <html:button + id="onionservices-savedkeys-removeall" + data-l10n-id="onion-site-saved-keys-dialog-remove-all-button" + ></html:button> + </hbox> + </vbox> +</window> diff --git a/browser/components/onionservices/jar.mn b/browser/components/onionservices/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..842af75c8c3e1b3d1d756453ea936f3a6ccb151d --- /dev/null +++ b/browser/components/onionservices/jar.mn @@ -0,0 +1,8 @@ +browser.jar: + content/browser/onionservices/authPreferences.css (content/authPreferences.css) + content/browser/onionservices/authPreferences.js (content/authPreferences.js) + content/browser/onionservices/authPrompt.js (content/authPrompt.js) + content/browser/onionservices/onionservices.css (content/onionservices.css) + content/browser/onionservices/savedKeysDialog.js (content/savedKeysDialog.js) + content/browser/onionservices/savedKeysDialog.xhtml (content/savedKeysDialog.xhtml) + skin/classic/browser/onionlocation.css (content/onionlocation.css) diff --git a/browser/components/onionservices/moz.build b/browser/components/onionservices/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..7fd02d04a5df0a711ac60c9f3f74108b2c07fdc6 --- /dev/null +++ b/browser/components/onionservices/moz.build @@ -0,0 +1,8 @@ +JAR_MANIFESTS += ["jar.mn"] + +EXTRA_JS_MODULES += [ + "OnionAliasStore.sys.mjs", + "OnionLocationChild.sys.mjs", + "OnionLocationParent.sys.mjs", + "TorRequestWatch.sys.mjs", +] diff --git a/browser/components/places/PlacesUIUtils.sys.mjs b/browser/components/places/PlacesUIUtils.sys.mjs index 0f79ba5dd42116d626445b86f6b24731d2fa8aad..126b682a6cc4d5ad10642fe8a4436f4fd6946b8e 100644 --- a/browser/components/places/PlacesUIUtils.sys.mjs +++ b/browser/components/places/PlacesUIUtils.sys.mjs @@ -1804,7 +1804,11 @@ ChromeUtils.defineLazyGetter(PlacesUIUtils, "URI_FLAVORS", () => { ]; }); ChromeUtils.defineLazyGetter(PlacesUIUtils, "SUPPORTED_FLAVORS", () => { - return [...PlacesUIUtils.PLACES_FLAVORS, ...PlacesUIUtils.URI_FLAVORS]; + return [ + ...PlacesUIUtils.PLACES_FLAVORS, + ...PlacesUIUtils.URI_FLAVORS, + "application/x-torbrowser-opaque", + ]; }); ChromeUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function () { diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index a7d7f2b2a564d93c3069815b54a714dce9b1fcf6..2a7efe658827e0085bb6362063120c193fc8b002 100644 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -1283,6 +1283,7 @@ PlacesController.prototype = { [ PlacesUtils.TYPE_X_MOZ_PLACE, PlacesUtils.TYPE_X_MOZ_URL, + "application/x-torbrowser-opaque", PlacesUtils.TYPE_PLAINTEXT, ].forEach(type => xferable.addDataFlavor(type)); diff --git a/browser/components/places/content/places.css b/browser/components/places/content/places.css index f78bb42d6d875f99ac70a445518243005374391c..ed22e9d06d8ac99c6028c700e3cce365575f3d31 100644 --- a/browser/components/places/content/places.css +++ b/browser/components/places/content/places.css @@ -47,3 +47,7 @@ tree[is="places-tree"] > treechildren::-moz-tree-cell { .places-tooltip-box { display: block; } + +#placesDownloadsTorWarning:not(.downloads-visible) { + display: none; +} diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 9e2abaafcc10e4ebba6edbf530fe30f858aaae6e..a6c3564a308c1e2b08d31484a5734862cbe9e943 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -17,6 +17,7 @@ ChromeUtils.defineESModuleGetters(this, { PlacesBackups: "resource://gre/modules/PlacesBackups.sys.mjs", PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs", + DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs", }); XPCOMUtils.defineLazyScriptGetter( this, @@ -157,6 +158,20 @@ var PlacesOrganizer = { "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING; + const torWarning = new DownloadsTorWarning( + document.getElementById("placesDownloadsTorWarning"), + true, + () => { + document + .getElementById("downloadsListBox") + .focus({ preventFocusRing: true }); + } + ); + torWarning.activate(); + window.addEventListener("unload", () => { + torWarning.deactivate(); + }); + ContentArea.setContentViewForQueryString( DOWNLOADS_QUERY, () => @@ -1410,9 +1425,21 @@ var ContentArea = { oldView.associatedElement.hidden = true; aNewView.associatedElement.hidden = false; + // Hide the Tor warning when not in the downloads view. + const isDownloads = aNewView.associatedElement.id === "downloadsListBox"; + const torWarningMessage = document.getElementById( + "placesDownloadsTorWarning" + ); + const torWarningLoosingFocus = + torWarningMessage.contains(document.activeElement) && !isDownloads; + torWarningMessage.classList.toggle("downloads-visible", isDownloads); + // If the content area inactivated view was focused, move focus // to the new view. - if (document.activeElement == oldView.associatedElement) { + if ( + document.activeElement == oldView.associatedElement || + torWarningLoosingFocus + ) { aNewView.associatedElement.focus(); } } diff --git a/browser/components/places/content/places.xhtml b/browser/components/places/content/places.xhtml index e2d47a009f5684468fce4bc6578d61e9f2d11897..7815312125389c291cd299fcd326bf4a64b79a97 100644 --- a/browser/components/places/content/places.xhtml +++ b/browser/components/places/content/places.xhtml @@ -64,6 +64,7 @@ <html:link rel="localization" href="browser/places.ftl"/> <html:link rel="localization" href="browser/downloads.ftl"/> <html:link rel="localization" href="browser/editBookmarkOverlay.ftl"/> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl"/> </linkset> <script src="chrome://browser/content/places/places.js"/> @@ -362,6 +363,8 @@ </tree> <splitter collapse="none" persist="state"></splitter> <vbox id="contentView"> + <html:moz-message-bar id="placesDownloadsTorWarning"> + </html:moz-message-bar> <vbox id="placesViewsBox" flex="1"> <tree id="placeContent" class="placesTree" diff --git a/browser/components/preferences/home.inc.xhtml b/browser/components/preferences/home.inc.xhtml index 611e82a909c14355480ada5a18b99959e79d10c6..1394b296d5dc6fd84da0a26947390e713549b8c5 100644 --- a/browser/components/preferences/home.inc.xhtml +++ b/browser/components/preferences/home.inc.xhtml @@ -33,7 +33,7 @@ class="check-home-page-controlled" data-preference-related="browser.startup.homepage"> <menupopup> - <menuitem value="0" data-l10n-id="home-mode-choice-default-fx" /> + <menuitem value="0" data-l10n-id="home-mode-choice-tor" /> <menuitem value="2" data-l10n-id="home-mode-choice-custom" /> <menuitem value="1" data-l10n-id="home-mode-choice-blank" /> </menupopup> @@ -82,7 +82,7 @@ Preferences so we need to handle setting the pref manually.--> <menulist id="newTabMode" flex="1" data-preference-related="browser.newtabpage.enabled"> <menupopup> - <menuitem value="0" data-l10n-id="home-mode-choice-default-fx" /> + <menuitem value="0" data-l10n-id="home-mode-choice-tor" /> <menuitem value="1" data-l10n-id="home-mode-choice-blank" /> </menupopup> </menulist> diff --git a/browser/components/preferences/home.js b/browser/components/preferences/home.js index 093248cff6227dd04f7f92eb44974b0191e6818a..23f7eefa17a5c1e4a03469dfca2fbc7ec81c1afc 100644 --- a/browser/components/preferences/home.js +++ b/browser/components/preferences/home.js @@ -387,10 +387,14 @@ var gHomePane = { if (controllingExtension && controllingExtension.id) { newValue = controllingExtension.id; - } else if (isDefault) { - newValue = this.HOME_MODE_FIREFOX_HOME; } else if (isBlank) { + // For base-browser, we want to check isBlank first since the default page + // is also the blank page, but we only have a menu option for + // HOME_MODE_BLANK, rather than HOME_MODE_FIREFOX_HOME. + // See tor-browser#41609. newValue = this.HOME_MODE_BLANK; + } else if (isDefault) { + newValue = this.HOME_MODE_FIREFOX_HOME; } else { newValue = this.HOME_MODE_CUSTOM; } diff --git a/browser/components/preferences/jar.mn b/browser/components/preferences/jar.mn index 3b60d18e483bc3c4e9b4309f0dc1e4231b7116b1..c67abf098d73c2e199bb11e1b5858415bcf8577c 100644 --- a/browser/components/preferences/jar.mn +++ b/browser/components/preferences/jar.mn @@ -23,3 +23,10 @@ browser.jar: content/browser/preferences/more-from-mozilla-qr-code-simple-cn.svg content/browser/preferences/web-appearance-dark.svg content/browser/preferences/web-appearance-light.svg + + content/browser/preferences/letterboxing.js + content/browser/preferences/letterboxing.css + content/browser/preferences/letterboxing-middle-dark.svg + content/browser/preferences/letterboxing-middle-light.svg + content/browser/preferences/letterboxing-top-dark.svg + content/browser/preferences/letterboxing-top-light.svg diff --git a/browser/components/preferences/letterboxing-middle-dark.svg b/browser/components/preferences/letterboxing-middle-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..1caeb1feb752ad67300b90bca6f66b8b4cd0cbb4 --- /dev/null +++ b/browser/components/preferences/letterboxing-middle-dark.svg @@ -0,0 +1,35 @@ +<svg width="62" height="50" viewBox="0 0 62 50" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2272_529)"> +<g clip-path="url(#clip0_2272_529)"> +<path d="M58 3H4V45H58V3Z" fill="#42414D"/> +<path d="M58 3H4V14H58V3Z" fill="#42414D"/> +<path d="M58 3H4V8H58V3Z" fill="#2B2A33"/> +<path d="M20 5H10C9.44772 5 9 5.44772 9 6C9 6.55228 9.44772 7 10 7H20C20.5523 7 21 6.55228 21 6C21 5.44772 20.5523 5 20 5Z" fill="white"/> +<path d="M56 11C56 10.4477 55.5523 10 55 10C54.4477 10 54 10.4477 54 11C54 11.5523 54.4477 12 55 12C55.5523 12 56 11.5523 56 11Z" fill="white"/> +<path d="M8 11C8 10.4477 7.55228 10 7 10C6.44772 10 6 10.4477 6 11C6 11.5523 6.44772 12 7 12C7.55228 12 8 11.5523 8 11Z" fill="white"/> +<path d="M12 11C12 10.4477 11.5523 10 11 10C10.4477 10 10 10.4477 10 11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11Z" fill="white"/> +<path d="M51 10H15C14.4477 10 14 10.4477 14 11C14 11.5523 14.4477 12 15 12H51C51.5523 12 52 11.5523 52 11C52 10.4477 51.5523 10 51 10Z" fill="white"/> +<path d="M58 14H4V45H58V14Z" fill="#5B5B66"/> +<rect x="8" y="18" width="46" height="23" rx="2" fill="#3A3944"/> +<path d="M38 22H13C12.4477 22 12 22.4477 12 23C12 23.5523 12.4477 24 13 24H38C38.5523 24 39 23.5523 39 23C39 22.4477 38.5523 22 38 22Z" fill="white"/> +<path d="M27 26H13C12.4477 26 12 26.4477 12 27C12 27.5523 12.4477 28 13 28H27C27.5523 28 28 27.5523 28 27C28 26.4477 27.5523 26 27 26Z" fill="white"/> +<path d="M42 30H13C12.4477 30 12 30.4477 12 31C12 31.5523 12.4477 32 13 32H42C42.5523 32 43 31.5523 43 31C43 30.4477 42.5523 30 42 30Z" fill="white"/> +</g> +<rect x="4.5" y="3.5" width="53" height="41" rx="1.5" stroke="#8F8F9D" shape-rendering="crispEdges"/> +</g> +<defs> +<filter id="filter0_d_2272_529" x="0" y="0" width="62" height="50" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="2"/> +<feComposite in2="hardAlpha" operator="out"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.0470588 0 0 0 0 0.0470588 0 0 0 0 0.0509804 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2272_529"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2272_529" result="shape"/> +</filter> +<clipPath id="clip0_2272_529"> +<rect x="4" y="3" width="54" height="42" rx="2" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/browser/components/preferences/letterboxing-middle-light.svg b/browser/components/preferences/letterboxing-middle-light.svg new file mode 100644 index 0000000000000000000000000000000000000000..a11c4060e601bd13d6389c5b725f6fde0840753d --- /dev/null +++ b/browser/components/preferences/letterboxing-middle-light.svg @@ -0,0 +1,35 @@ +<svg width="62" height="50" viewBox="0 0 62 50" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_202_960)"> +<g clip-path="url(#clip0_202_960)"> +<path d="M58 3H4V45H58V3Z" fill="#F0F0F4"/> +<path d="M58 3H4V14H58V3Z" fill="#F0F0F4"/> +<path d="M58 3H4V8H58V3Z" fill="#E0E0E6"/> +<path d="M20 5H10C9.44772 5 9 5.44772 9 6C9 6.55228 9.44772 7 10 7H20C20.5523 7 21 6.55228 21 6C21 5.44772 20.5523 5 20 5Z" fill="#52525E"/> +<path d="M56 11C56 10.4477 55.5523 10 55 10C54.4477 10 54 10.4477 54 11C54 11.5523 54.4477 12 55 12C55.5523 12 56 11.5523 56 11Z" fill="#52525E"/> +<path d="M8 11C8 10.4477 7.55228 10 7 10C6.44772 10 6 10.4477 6 11C6 11.5523 6.44772 12 7 12C7.55228 12 8 11.5523 8 11Z" fill="#52525E"/> +<path d="M12 11C12 10.4477 11.5523 10 11 10C10.4477 10 10 10.4477 10 11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11Z" fill="#52525E"/> +<path d="M51 10H15C14.4477 10 14 10.4477 14 11C14 11.5523 14.4477 12 15 12H51C51.5523 12 52 11.5523 52 11C52 10.4477 51.5523 10 51 10Z" fill="#52525E"/> +<path d="M58 14H4V45H58V14Z" fill="#CFCFD8"/> +<rect x="8" y="18" width="46" height="23" rx="2" fill="white"/> +<path d="M38 22H13C12.4477 22 12 22.4477 12 23C12 23.5523 12.4477 24 13 24H38C38.5523 24 39 23.5523 39 23C39 22.4477 38.5523 22 38 22Z" fill="#52525E"/> +<path d="M27 26H13C12.4477 26 12 26.4477 12 27C12 27.5523 12.4477 28 13 28H27C27.5523 28 28 27.5523 28 27C28 26.4477 27.5523 26 27 26Z" fill="#52525E"/> +<path d="M42 30H13C12.4477 30 12 30.4477 12 31C12 31.5523 12.4477 32 13 32H42C42.5523 32 43 31.5523 43 31C43 30.4477 42.5523 30 42 30Z" fill="#52525E"/> +</g> +<rect x="4.5" y="3.5" width="53" height="41" rx="1.5" stroke="#8F8F9D" shape-rendering="crispEdges"/> +</g> +<defs> +<filter id="filter0_d_202_960" x="0" y="0" width="62" height="50" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="2"/> +<feComposite in2="hardAlpha" operator="out"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.0470588 0 0 0 0 0.0470588 0 0 0 0 0.0509804 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_202_960"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_202_960" result="shape"/> +</filter> +<clipPath id="clip0_202_960"> +<rect x="4" y="3" width="54" height="42" rx="2" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/browser/components/preferences/letterboxing-top-dark.svg b/browser/components/preferences/letterboxing-top-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..01fbe0cb4ed678411d0c3a8caa5a1297f836c0b1 --- /dev/null +++ b/browser/components/preferences/letterboxing-top-dark.svg @@ -0,0 +1,35 @@ +<svg width="62" height="50" viewBox="0 0 62 50" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2272_508)"> +<g clip-path="url(#clip0_2272_508)"> +<path d="M58 3H4V45H58V3Z" fill="#52525E"/> +<path d="M58 3H4V14H58V3Z" fill="#42414D"/> +<path d="M58 3H4V8H58V3Z" fill="#2B2A33"/> +<path d="M20 5H10C9.44772 5 9 5.44772 9 6C9 6.55228 9.44772 7 10 7H20C20.5523 7 21 6.55228 21 6C21 5.44772 20.5523 5 20 5Z" fill="white"/> +<path d="M56 11C56 10.4477 55.5523 10 55 10C54.4477 10 54 10.4477 54 11C54 11.5523 54.4477 12 55 12C55.5523 12 56 11.5523 56 11Z" fill="white"/> +<path d="M8 11C8 10.4477 7.55228 10 7 10C6.44772 10 6 10.4477 6 11C6 11.5523 6.44772 12 7 12C7.55228 12 8 11.5523 8 11Z" fill="white"/> +<path d="M12 11C12 10.4477 11.5523 10 11 10C10.4477 10 10 10.4477 10 11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11Z" fill="white"/> +<path d="M51 10H15C14.4477 10 14 10.4477 14 11C14 11.5523 14.4477 12 15 12H51C51.5523 12 52 11.5523 52 11C52 10.4477 51.5523 10 51 10Z" fill="white"/> +<path d="M58 14H4V45H58V14Z" fill="#5B5B66"/> +<path d="M8 14H55V39C55 40.1046 54.1046 41 53 41H10C8.89543 41 8 40.1046 8 39V14Z" fill="#3A3944"/> +<path d="M38 18H13C12.4477 18 12 18.4477 12 19C12 19.5523 12.4477 20 13 20H38C38.5523 20 39 19.5523 39 19C39 18.4477 38.5523 18 38 18Z" fill="white"/> +<path d="M27 22H13C12.4477 22 12 22.4477 12 23C12 23.5523 12.4477 24 13 24H27C27.5523 24 28 23.5523 28 23C28 22.4477 27.5523 22 27 22Z" fill="white"/> +<path d="M42 26H13C12.4477 26 12 26.4477 12 27C12 27.5523 12.4477 28 13 28H42C42.5523 28 43 27.5523 43 27C43 26.4477 42.5523 26 42 26Z" fill="white"/> +</g> +<rect x="4.5" y="3.5" width="53" height="41" rx="3.5" stroke="#8F8F9D" shape-rendering="crispEdges"/> +</g> +<defs> +<filter id="filter0_d_2272_508" x="0" y="0" width="62" height="50" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="2"/> +<feComposite in2="hardAlpha" operator="out"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.0470588 0 0 0 0 0.0470588 0 0 0 0 0.0509804 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2272_508"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2272_508" result="shape"/> +</filter> +<clipPath id="clip0_2272_508"> +<rect x="4" y="3" width="54" height="42" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/browser/components/preferences/letterboxing-top-light.svg b/browser/components/preferences/letterboxing-top-light.svg new file mode 100644 index 0000000000000000000000000000000000000000..4000d671c8eb1add01a86527b0a04751fd2cf528 --- /dev/null +++ b/browser/components/preferences/letterboxing-top-light.svg @@ -0,0 +1,35 @@ +<svg width="62" height="50" viewBox="0 0 62 50" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_202_926)"> +<g clip-path="url(#clip0_202_926)"> +<path d="M58 3H4V45H58V3Z" fill="#F0F0F4"/> +<path d="M58 3H4V14H58V3Z" fill="#F0F0F4"/> +<path d="M58 3H4V8H58V3Z" fill="#E0E0E6"/> +<path d="M20 5H10C9.44772 5 9 5.44772 9 6C9 6.55228 9.44772 7 10 7H20C20.5523 7 21 6.55228 21 6C21 5.44772 20.5523 5 20 5Z" fill="#52525E"/> +<path d="M56 11C56 10.4477 55.5523 10 55 10C54.4477 10 54 10.4477 54 11C54 11.5523 54.4477 12 55 12C55.5523 12 56 11.5523 56 11Z" fill="#52525E"/> +<path d="M8 11C8 10.4477 7.55228 10 7 10C6.44772 10 6 10.4477 6 11C6 11.5523 6.44772 12 7 12C7.55228 12 8 11.5523 8 11Z" fill="#52525E"/> +<path d="M12 11C12 10.4477 11.5523 10 11 10C10.4477 10 10 10.4477 10 11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11Z" fill="#52525E"/> +<path d="M51 10H15C14.4477 10 14 10.4477 14 11C14 11.5523 14.4477 12 15 12H51C51.5523 12 52 11.5523 52 11C52 10.4477 51.5523 10 51 10Z" fill="#52525E"/> +<path d="M58 14H4V45H58V14Z" fill="#CFCFD8"/> +<path d="M8 14H55V39C55 40.1046 54.1046 41 53 41H10C8.89543 41 8 40.1046 8 39V14Z" fill="white"/> +<path d="M38 18H13C12.4477 18 12 18.4477 12 19C12 19.5523 12.4477 20 13 20H38C38.5523 20 39 19.5523 39 19C39 18.4477 38.5523 18 38 18Z" fill="#52525E"/> +<path d="M27 22H13C12.4477 22 12 22.4477 12 23C12 23.5523 12.4477 24 13 24H27C27.5523 24 28 23.5523 28 23C28 22.4477 27.5523 22 27 22Z" fill="#52525E"/> +<path d="M42 26H13C12.4477 26 12 26.4477 12 27C12 27.5523 12.4477 28 13 28H42C42.5523 28 43 27.5523 43 27C43 26.4477 42.5523 26 42 26Z" fill="#52525E"/> +</g> +<rect x="4.5" y="3.5" width="53" height="41" rx="3.5" stroke="#8F8F9D" shape-rendering="crispEdges"/> +</g> +<defs> +<filter id="filter0_d_202_926" x="0" y="0" width="62" height="50" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="2"/> +<feComposite in2="hardAlpha" operator="out"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.0470588 0 0 0 0 0.0470588 0 0 0 0 0.0509804 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_202_926"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_202_926" result="shape"/> +</filter> +<clipPath id="clip0_202_926"> +<rect x="4" y="3" width="54" height="42" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/browser/components/preferences/letterboxing.css b/browser/components/preferences/letterboxing.css new file mode 100644 index 0000000000000000000000000000000000000000..e79abb0c7a6f3e07eeae701aff43b445b9079ab4 --- /dev/null +++ b/browser/components/preferences/letterboxing.css @@ -0,0 +1,72 @@ +.letterboxing-overview { + margin-block-end: 32px; +} + +.letterboxing-search-overview { + margin-block-end: 16px; +} +#letterboxingAligner { + display: flex; + justify-content: start; + gap: 16px; + margin-block: 12px; + + --letterboxing-alignment-img-top: url("chrome://browser/content/preferences/letterboxing-top-light.svg"); + --letterboxing-alignment-img-middle: url("chrome://browser/content/preferences/letterboxing-middle-light.svg"); +} + +@media (prefers-color-scheme: dark) { + #letterboxingAligner { + --letterboxing-alignment-img-top: url("chrome://browser/content/preferences/letterboxing-top-dark.svg"); + --letterboxing-alignment-img-middle: url("chrome://browser/content/preferences/letterboxing-middle-dark.svg"); + } +} + +#letterboxingAligner .letterboxing-align-top img { + content: var(--letterboxing-alignment-img-top); +} +#letterboxingAligner .letterboxing-align-middle img { + content: var(--letterboxing-alignment-img-middle); +} + +#letterboxingAligner label { + width: 200px; + flex: 0 0 auto; +} + +#letterboxingAligner img { + border: none; + box-shadow: none; +} + +/* Hide letterboxing options depending on whether ResistFingerprinting or + * Letterboxing is enabled. */ +#letterboxingCategory:not(.rfp-enabled), +#letterboxingCategory:not(.rfp-enabled) ~ #letterboxingDisabled, +#letterboxingCategory.letterboxing-enabled ~ #letterboxingDisabled, +#letterboxingCategory:not(.rfp-enabled.letterboxing-enabled) ~ .letterboxing-category { + display: none; +} + +/* We duplicate the Letterboxing overview to appear in search results. + * We want to hide them whenever they are *not* part of a search result. */ +:is( + /* Hide the duplicates when the category is *not* hidden. */ + #letterboxingCategory:not(.visually-hidden) ~ .letterboxing-category, + /* Also hide the duplicated overview for subsequence search results if a + * previous groupbox is *not* hidden. */ + .letterboxing-category:not(.visually-hidden) ~ .letterboxing-category, +) .letterboxing-search-overview { + display: none; +} + +/* Similarly for #letterboxingDisabled, but we also want to hide its + * "Letterboxing" heading. + * NOTE: This should only appear in isolation, so we do not need to worry about + * subsequent groupboxes. */ +#letterboxingCategory:not(.visually-hidden) ~ #letterboxingDisabled :is( + .letterboxing-search-heading, + .letterboxing-search-overview +) { + display: none; +} diff --git a/browser/components/preferences/letterboxing.inc.xhtml b/browser/components/preferences/letterboxing.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..906fe51ae2d3ac769342d7f082db1bf6ba88f185 --- /dev/null +++ b/browser/components/preferences/letterboxing.inc.xhtml @@ -0,0 +1,114 @@ +<script src="chrome://browser/content/preferences/letterboxing.js" /> +<vbox + id="letterboxingCategory" + class="subcategory" + hidden="true" + data-category="paneGeneral" +> + <html:h1 data-l10n-id="letterboxing-header" /> + <description class="letterboxing-overview description-deemphasized"> + <html:span data-l10n-id="letterboxing-overview"></html:span> + <html:a + is="moz-support-link" + tor-manual-page="anti-fingerprinting_letterboxing" + data-l10n-id="letterboxing-learn-more" + ></html:a> + </description> +</vbox> +<groupbox + class="letterboxing-category" + data-category="paneGeneral" + hidden="true" +> + <label><html:h2 + data-l10n-id="letterboxing-window-size-header"/></label> + <description class="letterboxing-search-overview description-deemphasized"> + <html:span data-l10n-id="letterboxing-overview"></html:span> + <html:a + is="moz-support-link" + tor-manual-page="anti-fingerprinting_letterboxing" + data-l10n-id="letterboxing-learn-more" + ></html:a> + </description> + <checkbox + id="letterboxingRememberSize" + data-l10n-id="letterboxing-remember-size" + preference="privacy.resistFingerprinting.letterboxing.rememberSize" + /> +</groupbox> +<groupbox + class="letterboxing-category" + data-category="paneGeneral" + hidden="true" +> + <label><html:h2 + data-l10n-id="letterboxing-alignment-header" + /></label> + <description class="letterboxing-search-overview description-deemphasized"> + <html:span data-l10n-id="letterboxing-overview"></html:span> + <html:a + is="moz-support-link" + tor-manual-page="anti-fingerprinting_letterboxing" + data-l10n-id="letterboxing-learn-more" + ></html:a> + </description> + <description + id="letterboxingAlignmentDesc" + flex="1" + data-l10n-id="letterboxing-alignment-description" + /> + <form + xmlns="http://www.w3.org/1999/xhtml" + id="letterboxingAligner" + autocomplete="off" + aria-labelledby="letterboxingAlignmentDesc" + > + <label class="web-appearance-choice letterboxing-align-top"> + <div class="web-appearance-choice-image-container"> + <img role="presentation" /> + </div> + <div class="web-appearance-choice-footer"> + <input type="radio" name="alignment" value="top" /> + <span data-l10n-id="letterboxing-alignment-top"></span> + </div> + </label> + <label class="web-appearance-choice letterboxing-align-middle"> + <div class="web-appearance-choice-image-container"> + <img role="presentation" /> + </div> + <div class="web-appearance-choice-footer"> + <input type="radio" name="alignment" value="middle" /> + <span data-l10n-id="letterboxing-alignment-middle"></span> + </div> + </label> + </form> +</groupbox> +<groupbox + id="letterboxingDisabled" + data-category="paneGeneral" + hidden="true" +> + <label class="letterboxing-search-heading"><html:h2 + data-l10n-id="letterboxing-header"/></label> + <description class="letterboxing-search-overview description-deemphasized"> + <html:span data-l10n-id="letterboxing-overview"></html:span> + <html:a + is="moz-support-link" + tor-manual-page="anti-fingerprinting_letterboxing" + data-l10n-id="letterboxing-learn-more" + ></html:a> + </description> + <hbox align="center"> + <label + class="face-sad" + flex="1" + data-l10n-id="letterboxing-disabled-description" + /> + <button + id="letterboxingEnableButton" + class="accessory-button" + is="highlightable-button" + data-l10n-id="letterboxing-enable-button" + /> + </hbox> +</groupbox> diff --git a/browser/components/preferences/letterboxing.js b/browser/components/preferences/letterboxing.js new file mode 100644 index 0000000000000000000000000000000000000000..4cd7810d355cf9d9064c7f3f21b4c1d48363fb6a --- /dev/null +++ b/browser/components/preferences/letterboxing.js @@ -0,0 +1,113 @@ +/* import-globals-from /browser/components/preferences/preferences.js */ +/* import-globals-from /browser/components/preferences/findInPage.js */ +/* import-globals-from /toolkit/content/preferencesBindings.js */ + +Preferences.addAll([ + { + id: "privacy.resistFingerprinting.letterboxing.rememberSize", + type: "bool", + }, +]); + +{ + const lbEnabledPref = "privacy.resistFingerprinting.letterboxing"; + const visibilityPrefs = ["privacy.resistFingerprinting", lbEnabledPref]; + const alignMiddlePref = "privacy.resistFingerprinting.letterboxing.vcenter"; + + const hideFromSearchIf = (mustHide, ...elements) => { + for (const element of elements) { + if (mustHide) { + element.setAttribute("data-hidden-from-search", "true"); + } else { + element.removeAttribute("data-hidden-from-search"); + } + } + }; + + const syncVisibility = () => { + const [rfpEnabled, letterboxingEnabled] = visibilityPrefs.map(pref => + Services.prefs.getBoolPref(pref, false) + ); + const categoryElement = document.getElementById("letterboxingCategory"); + const { classList } = categoryElement; + + // Show the letterboxing section only if resistFingerprinting is enabled + classList.toggle("rfp-enabled", rfpEnabled); + classList.toggle("letterboxing-enabled", letterboxingEnabled); + + // To ensure the hidden parts do not contribute to search results, we need + // to add "data-hidden-from-search". + hideFromSearchIf( + !rfpEnabled || !letterboxingEnabled, + ...document.querySelectorAll(".letterboxing-category") + ); + hideFromSearchIf( + !rfpEnabled || letterboxingEnabled, + document.getElementById("letterboxingDisabled") + ); + }; + + const onVisibilityPrefChange = () => { + syncVisibility(); + // NOTE: Firefox does not expect "data-hidden-from-search" to change + // dynamically after page initialization. So we need to manually recall the + // methods that use "data-hidden-from-search". I.e. the "search" method, + // using the currently shown category. + // NOTE: We skip this if we are just initializing on page load. + // NOTE: data-hidden-from-search is also used when the user has entered a + // search term. We do not update the results in this case. Instead, it will + // update when the search term changes or is cleared. + if (!gSearchResultsPane.query) { + search(gLastCategory.category, "data-category"); + } + }; + + const alignerId = "letterboxingAligner"; + const syncAligner = () => { + const value = Services.prefs.getBoolPref(alignMiddlePref) + ? "middle" + : "top"; + document.querySelector( + `#${alignerId} input[value="${value}"]` + ).checked = true; + }; + + var gLetterboxingPrefs = { + init() { + syncVisibility(); + document + .getElementById("letterboxingEnableButton") + .addEventListener("command", () => { + Services.prefs.setBoolPref(lbEnabledPref, true); + // Button should have focus when activated but will be hidden now, + // so re-assign focus to the newly revealed options. + Services.focus.moveFocus( + window, + document.querySelector(".letterboxing-category"), + Services.focus.MOVEFOCUS_FIRST, + 0 + ); + }); + for (const pref of visibilityPrefs) { + Services.prefs.addObserver(pref, onVisibilityPrefChange); + } + + syncAligner(); + document.getElementById(alignerId).addEventListener("change", e => { + // NOTE: the "change" event is only fired on the checked input. + Services.prefs.setBoolPref( + alignMiddlePref, + e.target.value === "middle" + ); + }); + Services.prefs.addObserver(alignMiddlePref, syncAligner); + }, + + destroy() { + for (const pref of visibilityPrefs) { + Services.prefs.removeObserver(pref, onVisibilityPrefChange); + } + Services.prefs.removeObserver(alignMiddlePref, syncAligner); + }, + }; +} diff --git a/browser/components/preferences/main.inc.xhtml b/browser/components/preferences/main.inc.xhtml index 4c2637db10b7ad5d253d9588be3610c1ec5ad330..731c5fd73f48f39e135dae34cb211b95012d4464 100644 --- a/browser/components/preferences/main.inc.xhtml +++ b/browser/components/preferences/main.inc.xhtml @@ -155,6 +155,9 @@ </vbox> </groupbox> +<!-- Letterboxing --> +#include ./letterboxing.inc.xhtml + <hbox id="languageAndAppearanceCategory" class="subcategory" hidden="true" @@ -163,7 +166,7 @@ </hbox> <!-- Website appearance --> -<groupbox id="webAppearanceGroup" data-category="paneGeneral" hidden="true"> +<groupbox id="webAppearanceGroup" data-category="paneGeneral" hidden="true" data-hidden-from-search="true"> <html:h2 data-l10n-id="preferences-web-appearance-header"/> <html:div id="webAppearanceSettings"> <description class="description-deemphasized" data-l10n-id="preferences-web-appearance-description"/> @@ -333,7 +336,7 @@ </groupbox> <!-- Languages --> -<groupbox id="languagesGroup" data-category="paneGeneral" hidden="true"> +<groupbox id="languagesGroup" data-category="paneGeneral" hidden="true" data-subcategory="language"> <label><html:h2 data-l10n-id="language-header"/></label> <vbox id="browserLanguagesBox" align="start" hidden="true"> @@ -354,6 +357,7 @@ </hbox> <hbox id="languagesBox" align="center"> + <!-- <description flex="1" control="chooseLanguage" data-l10n-id="choose-language-description"/> <button id="chooseLanguage" is="highlightable-button" @@ -368,6 +372,9 @@ languages-customize-select-language.placeholder, languages-customize-add.label, " /> + --> + <checkbox id="spoofEnglish" + data-l10n-id="languages-customize-spoof-english"/> </hbox> <checkbox id="useSystemLocale" hidden="true" @@ -724,7 +731,8 @@ preference="general.autoScroll"/> <checkbox id="useSmoothScrolling" data-l10n-id="browsing-use-smooth-scrolling" - preference="general.smoothScroll"/> + preference="general.smoothScroll" + hidden="true"/> #ifdef MOZ_WIDGET_GTK <checkbox id="useOverlayScrollbars" data-l10n-id="browsing-gtk-use-non-overlay-scrollbars" @@ -745,7 +753,8 @@ #endif <checkbox id="alwaysUnderlineLinks" data-l10n-id="browsing-always-underline-links" - preference="layout.css.always_underline_links"/> + preference="layout.css.always_underline_links" + hidden="true"/> <checkbox id="searchStartTyping" data-l10n-id="browsing-search-on-start-typing" preference="accessibility.typeaheadfind"/> @@ -769,7 +778,7 @@ support-page="media-keyboard-control" /> </hbox> - <hbox align="center" data-subcategory="cfraddons"> + <hbox align="center" data-subcategory="cfraddons" hidden="true"> <checkbox id="cfrRecommendations" class="tail-with-learn-more" data-l10n-id="browsing-cfr-recommendations" @@ -779,7 +788,7 @@ support-page="extensionrecommendations" /> </hbox> - <hbox align="center" data-subcategory="cfrfeatures"> + <hbox align="center" data-subcategory="cfrfeatures" hidden="true"> <checkbox id="cfrRecommendations-features" class="tail-with-learn-more" data-l10n-id="browsing-cfr-features" @@ -794,12 +803,13 @@ <hbox id="networkProxyCategory" class="subcategory" hidden="true" + data-hidden-from-search="true" data-category="paneGeneral"> <html:h1 data-l10n-id="network-settings-title"/> </hbox> <!-- Network Settings--> -<groupbox id="connectionGroup" data-category="paneGeneral" hidden="true"> +<groupbox id="connectionGroup" data-category="paneGeneral" data-hidden-from-search="true" hidden="true"> <label class="search-header" hidden="true"><html:h2 data-l10n-id="network-settings-title"/></label> <hbox align="center" diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js index 68740bf08645759f8aae6ef1b668786da5d45d47..494f65429106c742bcf536ad96fbb09d756e8124 100644 --- a/browser/components/preferences/main.js +++ b/browser/components/preferences/main.js @@ -3,6 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ /* import-globals-from extensionControlled.js */ +/* import-globals-from letterboxing.js */ /* import-globals-from preferences.js */ /* import-globals-from /toolkit/mozapps/preferences/fontbuilder.js */ /* import-globals-from /browser/base/content/aboutDialog-appUpdater.js */ @@ -479,7 +480,23 @@ var gMainPane = { "command", makeDisableControllingExtension(PREF_SETTING_TYPE, CONTAINERS_KEY) ); - setEventListener("chooseLanguage", "command", gMainPane.showLanguages); + // setEventListener("chooseLanguage", "command", gMainPane.showLanguages); + { + const spoofEnglish = document.getElementById("spoofEnglish"); + const kPrefSpoofEnglish = "privacy.spoof_english"; + const preference = Preferences.add({ + id: kPrefSpoofEnglish, + type: "int", + }); + const spoofEnglishChanged = () => { + spoofEnglish.checked = preference.value == 2; + }; + spoofEnglishChanged(); + preference.on("change", spoofEnglishChanged); + setEventListener("spoofEnglish", "command", () => { + preference.value = spoofEnglish.checked ? 2 : 1; + }); + } // TODO (Bug 1817084) Remove this code when we disable the extension setEventListener( "fxtranslateButton", @@ -569,16 +586,10 @@ var gMainPane = { .setAttribute("style", "display: none !important"); } // Initialize the Firefox Updates section. - let version = AppConstants.MOZ_APP_VERSION_DISPLAY; + let version = AppConstants.BASE_BROWSER_VERSION; - // Include the build ID if this is an "a#" (nightly) build - if (/a\d+$/.test(version)) { - let buildID = Services.appinfo.appBuildID; - let year = buildID.slice(0, 4); - let month = buildID.slice(4, 6); - let day = buildID.slice(6, 8); - version += ` (${year}-${month}-${day})`; - } + // Base Browser and derivatives: do not include the build ID in our alphas, + // since they are not actually related to the build date. // Append "(32-bit)" or "(64-bit)" build architecture to the version number: let bundle = Services.strings.createBundle( @@ -760,6 +771,7 @@ var gMainPane = { ); AppearanceChooser.init(); + gLetterboxingPrefs.init(); // Notify observers that the UI is now ready Services.obs.notifyObservers(window, "main-pane-loaded"); @@ -1426,8 +1438,30 @@ var gMainPane = { available, { preferNative: true } ); - let locales = available.map((code, i) => ({ code, name: localeNames[i] })); - locales.sort((a, b) => a.name > b.name); + let locales = available.map((code, i) => { + let name = localeNames[i].replace(/\s*\(.+\)$/g, ""); + if (code === "ja-JP-macos") { + // Mozilla codebases handle Japanese in macOS in different ways, + // sometimes they call it ja-JP-mac and sometimes they call it + // ja-JP-macos. The former is translated to Japanese when specifying + // preferNative to true, the latter is not. Since seeing ja-JP-macos + // would be confusing anyway, we treat it as a special case. + // See tor-browser#41372 and Bug 1726586. + name = + Services.intl.getLocaleDisplayNames(undefined, ["ja"], { + preferNative: true, + })[0] + " (ja)"; + } else { + name += ` (${code})`; + } + return { + code, + name, + }; + }); + // tor-browser#42335: Sort language codes independently from the locale, + // so do not use localeCompare. + locales.sort((a, b) => a.code > b.code); let fragment = document.createDocumentFragment(); for (let { code, name } of locales) { @@ -1727,7 +1761,9 @@ var gMainPane = { let defaultBrowserBox = document.getElementById("defaultBrowserBox"); let isInFlatpak = gGIOService?.isRunningUnderFlatpak; // Flatpak does not support setting nor detection of default browser - if (!shellSvc || isInFlatpak) { + // tor-browser#41822 disable making Tor Browser the default browser + // eslint-disable-next-line no-constant-condition + if (shellSvc || isInFlatpak || true) { defaultBrowserBox.hidden = true; return; } @@ -2606,6 +2642,7 @@ var gMainPane = { Services.prefs.removeObserver(PREF_CONTAINERS_EXTENSION, this); Services.obs.removeObserver(this, AUTO_UPDATE_CHANGED_TOPIC); Services.obs.removeObserver(this, BACKGROUND_UPDATE_CHANGED_TOPIC); + gLetterboxingPrefs.destroy(); AppearanceChooser.destroy(); }, diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js index bdfd45b6d5c2cf91e542fe31ed54b03545890de4..8e76fef489daf075a753f8cb3cfca6382ec37de2 100644 --- a/browser/components/preferences/preferences.js +++ b/browser/components/preferences/preferences.js @@ -15,6 +15,7 @@ /* import-globals-from findInPage.js */ /* import-globals-from /browser/base/content/utilityOverlay.js */ /* import-globals-from /toolkit/content/preferencesBindings.js */ +/* import-globals-from ../torpreferences/content/connectionPane.js */ "use strict"; @@ -227,6 +228,14 @@ function init_all() { register_module("paneSync", gSyncPane); } register_module("paneSearchResults", gSearchResultsPane); + if (gConnectionPane.enabled) { + document.getElementById("category-connection").hidden = false; + register_module("paneConnection", gConnectionPane); + } else { + // Remove the pane from the DOM so it doesn't get incorrectly included in search results. + document.getElementById("template-paneConnection").remove(); + } + gSearchResultsPane.init(); gMainPane.preInit(); @@ -448,6 +457,26 @@ async function scrollAndHighlight(subcategory) { } let header = getClosestDisplayedHeader(element); + // We assign a tabindex=-1 to the element so that we can focus it. This allows + // us to move screen reader's focus to an arbitrary position on the page. + // See tor-browser#41454 and mozilla bug 1799153. + const doFocus = () => { + element.setAttribute("tabindex", "-1"); + Services.focus.setFocus(element, Services.focus.FLAG_NOSCROLL); + // Immediately remove again now that it has focus. + element.removeAttribute("tabindex"); + }; + // The element is not always immediately focusable, so we wait until document + // load. + if (document.readyState === "complete") { + doFocus(); + } else { + // Wait until document load to move focus. + // NOTE: This should be called after DOMContentLoaded, where the searchInput + // is focused. + window.addEventListener("load", doFocus, { once: true }); + } + scrollContentTo(header); element.classList.add("spotlight"); } diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml index 53bdc9c912a6cd0c787dbcf41f2a82b7169d5aa7..b4303cf5b263d0239fd2ef38f5c64226eea8d317 100644 --- a/browser/components/preferences/preferences.xhtml +++ b/browser/components/preferences/preferences.xhtml @@ -42,6 +42,14 @@ href="chrome://browser/skin/preferences/containers.css" /> <link rel="stylesheet" href="chrome://browser/skin/preferences/privacy.css" /> + <link + rel="stylesheet" + href="chrome://browser/content/preferences/letterboxing.css" + /> + + <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelPreferences.css" /> + <link rel="stylesheet" href="chrome://browser/content/torpreferences/torPreferences.css" /> + <link rel="stylesheet" href="chrome://browser/content/onionservices/authPreferences.css" /> <link rel="localization" href="branding/brand.ftl"/> <link rel="localization" href="browser/browser.ftl"/> @@ -73,6 +81,8 @@ <link rel="localization" href="security/certificates/certManager.ftl"/> <link rel="localization" href="security/certificates/deviceManager.ftl"/> <link rel="localization" href="toolkit/updates/history.ftl"/> + <link rel="localization" href="toolkit/global/base-browser.ftl"/> + <link rel="localization" href="toolkit/global/tor-browser.ftl"/> <link rel="shortcut icon" href="chrome://global/skin/icons/settings.svg"/> @@ -83,6 +93,7 @@ <script src="chrome://browser/content/preferences/findInPage.js"/> <script src="chrome://browser/content/migration/migration-wizard.mjs" type="module"></script> <script type="module" src="chrome://browser/content/backup/backup-settings.mjs"></script> + <script src="chrome://browser/content/torpreferences/bridgemoji/BridgeEmoji.js"/> </head> <html:body xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" @@ -195,6 +206,8 @@ value="paneTranslations" helpTopic="prefs-translations"/> +#include ../torpreferences/content/connectionCategory.inc.xhtml + </richlistbox> <spacer flex="1"/> @@ -246,6 +259,7 @@ #include sync.inc.xhtml #include experimental.inc.xhtml #include moreFromMozilla.inc.xhtml +#include ../torpreferences/content/connectionPane.xhtml </vbox> </vbox> </vbox> diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml index a9e8501afcff1c022e4cb1855015d0c4148a1a68..d9571f3a7f700d2697787d61aa00854eff8f51be 100644 --- a/browser/components/preferences/privacy.inc.xhtml +++ b/browser/components/preferences/privacy.inc.xhtml @@ -15,7 +15,7 @@ </hbox> <!-- Tracking / Content Blocking --> -<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" aria-describedby="contentBlockingDescription" class="highlighting-group"> +<groupbox id="trackingGroup" data-category="panePrivacy" data-hidden-from-search="true" hidden="true" aria-describedby="contentBlockingDescription" class="highlighting-group"> <label id="contentBlockingHeader"><html:h2 data-l10n-id="content-blocking-enhanced-tracking-protection"/></label> <vbox data-subcategory="trackingprotection"> <hbox align="start"> @@ -358,7 +358,7 @@ </vbox> </vbox> </groupbox> -<groupbox id="nonTechnicalPrivacyGroup" data-category="panePrivacy" data-subcategory="nontechnicalprivacy" hidden="true"> +<groupbox id="nonTechnicalPrivacyGroup" data-category="panePrivacy" data-subcategory="nontechnicalprivacy" data-hidden-from-search="true" hidden="true"> <label id="nonTechnicalPrivacyHeader"><html:h2 data-l10n-id="non-technical-privacy-header"/></label> <vbox id="nonTechnicalPrivacyBox"> <hbox id="globalPrivacyControlBox" flex="1" align="center" hidden="true"> @@ -607,6 +607,8 @@ <label id="fips-desc" hidden="true" data-l10n-id="forms-master-pw-fips-desc"></label> </groupbox> +#include ../onionservices/content/authPreferences.inc.xhtml + <!-- The form autofill section is inserted in to this box after the form autofill extension has initialized. --> <groupbox id="formAutofillGroupBox" @@ -1062,6 +1064,8 @@ <html:h1 data-l10n-id="security-header"/> </hbox> +#include ../securitylevel/content/securityLevelPreferences.inc.xhtml + <!-- addons, forgery (phishing) UI Security --> <groupbox id="browsingProtectionGroup" data-category="panePrivacy" hidden="true"> <label><html:h2 data-l10n-id="security-browsing-protection"/></label> @@ -1186,11 +1190,12 @@ <hbox id="DoHCategory" class="subcategory" hidden="true" - data-category="panePrivacy"> + data-category="panePrivacy" + data-hidden-from-search="true"> <html:h1 data-l10n-id="preferences-doh-header"/> </hbox> -<groupbox id="dohBox" data-category="panePrivacy" data-subcategory="doh" hidden="true" class="highlighting-group"> +<groupbox id="dohBox" data-category="panePrivacy" data-subcategory="doh" data-hidden-from-search="true" hidden="true" class="highlighting-group"> <label class="search-header" searchkeywords="doh trr" hidden="true"><html:h2 data-l10n-id="preferences-doh-header"/></label> <vbox flex="1"> <description id="dohDescription" class="tail-with-learn-more description-deemphasized" data-l10n-id="preferences-doh-description2"></description> diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js index 433faf6680fb74800dac847f6800063a51f352f3..787acec244734fcb8d0edb215f0c4bd9f5954004 100644 --- a/browser/components/preferences/privacy.js +++ b/browser/components/preferences/privacy.js @@ -61,6 +61,19 @@ XPCOMUtils.defineLazyServiceGetter( "nsIParentalControlsService" ); +XPCOMUtils.defineLazyScriptGetter( + this, + ["OnionServicesAuthPreferences"], + "chrome://browser/content/onionservices/authPreferences.js" +); + +// TODO: module import via ChromeUtils.defineModuleGetter +XPCOMUtils.defineLazyScriptGetter( + this, + ["SecurityLevelPreferences"], + "chrome://browser/content/securitylevel/securityLevel.js" +); + XPCOMUtils.defineLazyPreferenceGetter( this, "gIsFirstPartyIsolated", @@ -369,6 +382,16 @@ function initTCPStandardSection() { var gPrivacyPane = { _pane: null, + /** + * Show the Security Level UI + */ + _initSecurityLevel() { + SecurityLevelPreferences.init(); + window.addEventListener("unload", () => SecurityLevelPreferences.uninit(), { + once: true, + }); + }, + /** * Whether the prompt to restart Firefox should appear when changing the autostart pref. */ @@ -488,7 +511,8 @@ var gPrivacyPane = { let canConfigureThirdPartyCerts = (AppConstants.platform == "win" || AppConstants.platform == "macosx") && typeof Services.policies.getActivePolicies()?.Certificates - ?.ImportEnterpriseRoots == "undefined"; + ?.ImportEnterpriseRoots == "undefined" && + !AppConstants.BASE_BROWSER_VERSION; document.getElementById("certEnableThirdPartyToggleBox").hidden = !canConfigureThirdPartyCerts; @@ -991,6 +1015,8 @@ var gPrivacyPane = { this.networkCookieBehaviorReadPrefs(); this._initTrackingProtectionExtensionControl(); this._initThirdPartyCertsToggle(); + OnionServicesAuthPreferences.init(); + this._initSecurityLevel(); Services.telemetry.setEventRecordingEnabled("privacy.ui.fpp", true); @@ -3058,8 +3084,12 @@ var gPrivacyPane = { }, _updateRelayIntegrationUI() { - document.getElementById("relayIntegrationBox").hidden = - !FirefoxRelay.isAvailable; + // In Base Browser, we always hide the integration checkbox since + // FirefoxRelay should remain disabled. + // See tor-browser#43109 and tor-browser#42814. + // NOTE: FirefoxRelay.isAvailable will be true whenever + // FirefoxRelay.isDisabled is true. + document.getElementById("relayIntegrationBox").hidden = true; document.getElementById("relayIntegration").checked = FirefoxRelay.isAvailable && !FirefoxRelay.isDisabled; }, diff --git a/browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js b/browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js index 69443db930748dca90ebf149a70995512b54906a..e901742c35a10f6ff57a1f248fab0942a717eb6b 100644 --- a/browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js +++ b/browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js @@ -53,8 +53,8 @@ function checkForDefaultSetting( aRealHeight ) { // We can get the rounded size by subtracting twice the margin. - let targetWidth = aRealWidth - 2 * RFPHelper.steppedRange(aRealWidth); - let targetHeight = aRealHeight - 2 * RFPHelper.steppedRange(aRealHeight); + let targetWidth = aRealWidth - 2 * RFPHelper.steppedSize(aRealWidth, true); + let targetHeight = aRealHeight - 2 * RFPHelper.steppedSize(aRealHeight); // This platform-specific code is explained in the large comment below. if (getPlatform() != "linux") { @@ -82,7 +82,7 @@ async function test_dynamical_window_rounding(aWindow, aCheckFunc) { // We need to wait for the updating the margins for the newly opened tab, or // it will affect the following tests. let promiseForTheFirstRounding = TestUtils.topicObserved( - "test:letterboxing:update-margin-finish" + "test:letterboxing:update-size-finish" ); info("Open a content tab for testing."); @@ -108,7 +108,7 @@ async function test_dynamical_window_rounding(aWindow, aCheckFunc) { let caseString = "Case " + width + "x" + height + ": "; // Create a promise for waiting for the margin update. let promiseRounding = TestUtils.topicObserved( - "test:letterboxing:update-margin-finish" + "test:letterboxing:update-size-finish" ); let { containerWidth, containerHeight } = getContainerSize(tab); @@ -316,7 +316,7 @@ async function test_findbar(aWindow) { ); let promiseRounding = TestUtils.topicObserved( - "test:letterboxing:update-margin-finish" + "test:letterboxing:update-size-finish" ); let findBarOpenPromise = BrowserTestUtils.waitForEvent( @@ -330,7 +330,7 @@ async function test_findbar(aWindow) { ok(true, "Margin updated when findbar opened"); promiseRounding = TestUtils.topicObserved( - "test:letterboxing:update-margin-finish" + "test:letterboxing:update-size-finish" ); let findBarClosePromise = BrowserTestUtils.waitForEvent( diff --git a/browser/components/rulesets/RulesetsChild.sys.mjs b/browser/components/rulesets/RulesetsChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..dfbb018d7c55b051dcba4999f764c3c78ee8ba4d --- /dev/null +++ b/browser/components/rulesets/RulesetsChild.sys.mjs @@ -0,0 +1,9 @@ +// Copyright (c) 2022, The Tor Project, Inc. + +import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs"; + +/** + * The child actor part for about:rulesets. + * It does not do anything, as all the communication happens with RPM* calls. + */ +export class RulesetsChild extends RemotePageChild {} diff --git a/browser/components/rulesets/RulesetsParent.sys.mjs b/browser/components/rulesets/RulesetsParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..c408247ce9cc905aecfe6f5b6fcfd22ea855e0a4 --- /dev/null +++ b/browser/components/rulesets/RulesetsParent.sys.mjs @@ -0,0 +1,75 @@ +// Copyright (c) 2022, The Tor Project, Inc. + +import { + OnionAliasStore, + OnionAliasStoreTopics, +} from "resource:///modules/OnionAliasStore.sys.mjs"; + +const kShowWarningPref = "torbrowser.rulesets.show_warning"; + +/** + * This class relays the changes the user's changes from about:rulesets to the + * rulesets database. + */ +export class RulesetsParent extends JSWindowActorParent { + constructor(...args) { + super(...args); + + const self = this; + this.observer = { + observe(aSubject, aTopic) { + const obj = aSubject?.wrappedJSObject; + if (aTopic === OnionAliasStoreTopics.ChannelsChanged && obj) { + self.sendAsyncMessage("rulesets:channels-change", obj); + } + }, + }; + Services.obs.addObserver( + this.observer, + OnionAliasStoreTopics.ChannelsChanged + ); + } + + didDestroy() { + Services.obs.removeObserver( + this.observer, + OnionAliasStoreTopics.ChannelsChanged + ); + } + + async receiveMessage(message) { + switch (message.name) { + // RPMSendAsyncMessage + case "rulesets:delete-channel": + OnionAliasStore.deleteChannel(message.data); + break; + case "rulesets:enable-channel": + OnionAliasStore.enableChannel(message.data.name, message.data.enabled); + break; + case "rulesets:set-show-warning": + Services.prefs.setBoolPref(kShowWarningPref, message.data); + break; + // RPMSendQuery + case "rulesets:get-channels": + return OnionAliasStore.getChannels(); + case "rulesets:get-init-args": + return { + showWarning: Services.prefs.getBoolPref(kShowWarningPref, true), + }; + case "rulesets:set-channel": + const ch = await OnionAliasStore.setChannel(message.data); + return ch; + case "rulesets:update-channel": + // We need to catch any error in this way, because in case of an + // exception, RPMSendQuery does not return on the other side + try { + const channel = await OnionAliasStore.updateChannel(message.data); + return channel; + } catch (err) { + console.error("Cannot update the channel", err); + return { error: err.toString() }; + } + } + return undefined; + } +} diff --git a/browser/components/rulesets/content/aboutRulesets.css b/browser/components/rulesets/content/aboutRulesets.css new file mode 100644 index 0000000000000000000000000000000000000000..94ca5629bef2ad17c3037eb77757b8f91f259b58 --- /dev/null +++ b/browser/components/rulesets/content/aboutRulesets.css @@ -0,0 +1,306 @@ +/* Copyright (c) 2022, The Tor Project, Inc. */ + +/* General rules */ + +html, body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; +} + +body { + font: message-box; + background-color: var(--in-content-page-background); + color: var(--in-content-page-color); + font-size: 15px; + cursor: default; +} + +label { + display: flex; + align-items: center; + padding: 6px 0; +} + +input[type=text] { + margin: 0; + width: 360px; + max-width: 100%; +} + +textarea { + margin: 0; + width: var(--content-width); + max-width: 100%; + box-sizing: border-box; +} + +select, option { + font-weight: 700; +} + +dt { + margin: var(--ruleset-vmargin) 0 0 0; + padding: 0; + color: var(--text-color-deemphasized); + font-size: 85%; +} + +dd { + margin: 8px 0 0 0; + padding: 0; + max-width: 600px; + box-sizing: border-box; +} + +hr { + width: 40px; + margin: 0; + border: none; + border-top: 1px solid var(--in-content-border-color); +} + +.hidden { + display: none !important; +} + +/* Initial warning */ + +#warning-wrapper { + display: none; +} + +.state-warning #warning-wrapper { + display: flex; + align-items: center; + height: 100%; +} + +#warning { + margin-top: -20vh; + padding: 0 160px; + background-image: url("chrome://global/skin/icons/warning.svg"); + background-position: 84px 0; + background-repeat: no-repeat; + background-size: 48px; + fill: #ffbd4f; + -moz-context-properties: fill; +} + +#warning:dir(rtl) { + background-position: right 84px top 0; +} + +#warning-description { + margin: 30px 0 16px 0; +} + +#warning-buttonbar { + margin-top: 30px; + text-align: right; +} + +/* Actual content */ + +:root { + --sidebar-width: 320px; + --content-width: 600px; + --ruleset-vmargin: 40px; +} + +#main-content { + display: flex; + height: 100%; +} + +.state-warning #main-content { + display: none; +} + +section { + display: none; + flex: 1 0 auto; + padding: 40px; +} + +.title { + display: flex; + align-items: center; + width: var(--content-width); + max-width: 100%; + padding-bottom: 16px; + border-bottom: 1px solid var(--in-content-border-color); +} + +.title h1 { + margin: 0; + padding: 0; + padding-inline-start: 35px; + font-size: 20px; + font-weight: 700; + background-image: url("chrome://browser/content/rulesets/securedrop.svg"); + background-position: 0 center; + background-size: 22px; + min-height: 22px; + background-repeat: no-repeat; +} + +#main-content h1:dir(rtl) { + background-position: right 0 top 4px; +} + +/* Ruleset list */ + +aside { + display: flex; + flex-direction: column; + flex: 0 0 var(--sidebar-width); + box-sizing: border-box; + + border-inline-end: 1px solid var(--in-content-border-color); + background-color: var(--in-content-box-background); +} + +#ruleset-heading { + padding: 16px; + text-align: center; + font-weight: 700; + border-bottom: 1px solid var(--in-content-border-color); +} + +#ruleset-list-container { + flex: 1; +} + +#ruleset-list-empty { + padding: 16px; + text-align: center; +} + +#ruleset-list-empty-description { + font-size: 80%; +} + +#ruleset-list { + margin: 0; + padding: 0; +} + +#ruleset-list li { + display: flex; + align-items: center; + margin: 0; + padding: 10px 18px; + list-style: none; + border-inline-start: 4px solid transparent; + border-bottom: 1px solid var(--in-content-border-color); +} + +#ruleset-list li:last-child { + border-bottom: none; +} + +#ruleset-list .icon { + width: 16px; + height: 16px; + margin-inline-end: 12px; + background-image: url("chrome://browser/content/rulesets/securedrop.svg"); + background-size: 16px; +} + +#ruleset-list .icon.has-favicon { + background: transparent; +} + +#ruleset-list .name { + font-weight: 700; +} + +#ruleset-list .description { + font-size: 85%; + color: var(--text-color-deemphasized); +} + +#ruleset-list .selected { + border-inline-start-color: var(--in-content-accent-color); +} + +#ruleset-list .selected.disabled { + border-inline-start-color: var(--in-content-border-color); +} + +#ruleset-list li:not(.selected):hover { + background-color: var(--in-content-button-background-hover); + color: var(--in-content-button-text-color-hover); +} + +#ruleset-list li:not(.selected):hover:active { + background-color: var(--in-content-button-background-active); +} + +#ruleset-list #ruleset-template { + display: none; +} + +/* Ruleset details */ + +.state-details #ruleset-details { + display: block; +} + +#ruleset-jwk-value { + padding: 8px; + border-radius: 2px; + background-color: var(--in-content-box-background); + font-size: 85%; + line-break: anywhere; + /* ASCII-only text, so can set line-height. */ + line-height: 1.4; +} + +#ruleset-edit { + margin-inline-start: auto; + padding-inline-start: 32px; + background-image: url("chrome://global/skin/icons/edit.svg"); + background-repeat: no-repeat; + background-position: 8px; + -moz-context-properties: fill; + fill: currentColor; + min-width: auto; + flex: 0 0 auto; +} + +#ruleset-enable { + margin-top: var(--ruleset-vmargin); +} + +#ruleset-buttonbar { + margin: var(--ruleset-vmargin) 0; +} + +#ruleset-updated { + margin-top: 24px; + color: var(--text-color-deemphasized); + font-size: 85%; +} + +/* Edit ruleset */ + +.state-edit #edit-ruleset { + display: block; +} + +#edit-ruleset label { + color: var(--text-color-deemphasized); + display: block; +} + +#edit-ruleset label, #edit-buttonbar { + margin-top: var(--ruleset-vmargin); +} + +label#edit-enable { + display: flex; + align-items: center; +} diff --git a/browser/components/rulesets/content/aboutRulesets.html b/browser/components/rulesets/content/aboutRulesets.html new file mode 100644 index 0000000000000000000000000000000000000000..cd572da52cb4f0b61bc5c7618e09b688bcbc05ee --- /dev/null +++ b/browser/components/rulesets/content/aboutRulesets.html @@ -0,0 +1,182 @@ +<!-- Copyright (c) 2022, The Tor Project, Inc. --> +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta + http-equiv="Content-Security-Policy" + content="default-src chrome:; object-src 'none'" + /> + <link rel="stylesheet" href="chrome://global/skin/in-content/common.css" /> + <link + rel="stylesheet" + href="chrome://browser/content/rulesets/aboutRulesets.css" + /> + + <link rel="localization" href="branding/brand.ftl" /> + <link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </head> + <body> + <!-- Warning --> + <div id="warning-wrapper"> + <div id="warning"> + <h1 id="warning-title" data-l10n-id="rulesets-warning-heading"></h1> + <p + id="warning-description" + data-l10n-id="rulesets-warning-description" + ></p> + <p> + <label> + <input + id="warning-enable-checkbox" + type="checkbox" + checked="checked" + /> + <span + id="warning-enable-label" + data-l10n-id="rulesets-warning-checkbox" + ></span> + </label> + </p> + <div id="warning-buttonbar"> + <button + id="warning-button" + autofocus="autofocus" + data-l10n-id="rulesets-warning-continue-button" + ></button> + </div> + </div> + </div> + + <div id="main-content"> + <!-- Ruleset list --> + <aside> + <div + id="ruleset-heading" + data-l10n-id="rulesets-side-panel-heading" + ></div> + <div id="ruleset-list-container"> + <div id="ruleset-list-empty"> + <p + id="ruleset-list-empty-title" + data-l10n-id="rulesets-side-panel-no-rules" + ></p> + <p + id="ruleset-list-empty-description" + data-l10n-id="rulesets-side-panel-no-rules-description" + ></p> + </div> + <ul id="ruleset-list"> + <li id="ruleset-template"> + <div class="icon"></div> + <div> + <div class="name"></div> + <div class="description"></div> + </div> + </li> + </ul> + </div> + </aside> + + <!-- Ruleset details --> + <section id="ruleset-details"> + <div class="title"> + <h1 id="ruleset-title"></h1> + <button + id="ruleset-edit" + class="ghost-button" + data-l10n-id="rulesets-details-edit-button" + ></button> + </div> + <dl> + <dt id="ruleset-jwk-label" data-l10n-id="rulesets-details-jwk"></dt> + <dd id="ruleset-jwk-value"></dd> + <dt + id="ruleset-path-prefix-label" + data-l10n-id="rulesets-details-path" + ></dt> + <dd> + <a id="ruleset-path-prefix-value" target="_blank"></a> + </dd> + <dt + id="ruleset-scope-label" + data-l10n-id="rulesets-details-scope" + ></dt> + <dd id="ruleset-scope-value"></dd> + </dl> + <label id="ruleset-enable"> + <input type="checkbox" id="ruleset-enable-checkbox" /> + <span + id="ruleset-enable-label" + data-l10n-id="rulesets-details-enable-checkbox" + ></span> + </label> + <div id="ruleset-buttonbar"> + <button + id="ruleset-update-button" + data-l10n-id="rulesets-details-update-button" + ></button> + </div> + <hr /> + <p id="ruleset-updated"></p> + </section> + + <!-- Edit ruleset --> + <section id="edit-ruleset"> + <div class="title"> + <h1 id="edit-title"></h1> + </div> + <form id="edit-ruleset-form"> + <label> + <div id="edit-jwk-label" data-l10n-id="rulesets-details-jwk"></div> + <textarea + id="edit-jwk-textarea" + rows="10" + data-l10n-id="rulesets-details-jwk-input" + ></textarea> + </label> + <label> + <div + id="edit-path-prefix-label" + data-l10n-id="rulesets-details-path" + ></div> + <input + id="edit-path-prefix-input" + type="text" + data-l10n-id="rulesets-details-path-input" + /> + </label> + <label> + <div + id="edit-scope-label" + data-l10n-id="rulesets-details-scope" + ></div> + <input + id="edit-scope-input" + type="text" + data-l10n-id="rulesets-details-scope-input" + /> + </label> + <label id="edit-enable"> + <input type="checkbox" id="edit-enable-checkbox" /> + <span + id="edit-enable-label" + data-l10n-id="rulesets-details-enable-checkbox" + ></span> + </label> + <div id="edit-buttonbar"> + <button + id="edit-save" + class="primary" + data-l10n-id="rulesets-details-save-button" + ></button> + <button + id="edit-cancel" + data-l10n-id="rulesets-details-cancel-button" + ></button> + </div> + </form> + </section> + </div> + <script src="chrome://browser/content/rulesets/aboutRulesets.js"></script> + </body> +</html> diff --git a/browser/components/rulesets/content/aboutRulesets.js b/browser/components/rulesets/content/aboutRulesets.js new file mode 100644 index 0000000000000000000000000000000000000000..86e1b622f9a837ba32c60642ea1bc6b2cb88ebb8 --- /dev/null +++ b/browser/components/rulesets/content/aboutRulesets.js @@ -0,0 +1,448 @@ +"use strict"; + +/* eslint-env mozilla/remote-page */ + +const Orders = Object.freeze({ + Name: "name", + NameDesc: "name-desc", + LastUpdate: "last-update", +}); + +const States = Object.freeze({ + Warning: "warning", + Details: "details", + Edit: "edit", + NoRulesets: "noRulesets", +}); + +function setUpdateDate(ruleset, element) { + if (!ruleset.enabled) { + document.l10n.setAttributes(element, "rulesets-update-rule-disabled"); + return; + } + if (!ruleset.currentTimestamp) { + document.l10n.setAttributes(element, "rulesets-update-never"); + return; + } + + document.l10n.setAttributes(element, "rulesets-update-last", { + date: ruleset.currentTimestamp * 1000, + }); +} + +// UI states + +/** + * This is the initial warning shown when the user opens about:rulesets. + */ +class WarningState { + elements = { + enableCheckbox: document.getElementById("warning-enable-checkbox"), + button: document.getElementById("warning-button"), + }; + + constructor() { + this.elements.enableCheckbox.addEventListener( + "change", + this.onEnableChange.bind(this) + ); + + this.elements.button.addEventListener( + "click", + this.onButtonClick.bind(this) + ); + } + + show() { + this.elements.button.focus(); + } + + hide() {} + + onEnableChange() { + RPMSendAsyncMessage( + "rulesets:set-show-warning", + this.elements.enableCheckbox.checked + ); + } + + onButtonClick() { + gAboutRulesets.selectFirst(); + } +} + +/** + * State shown when the user clicks on a channel to see its details. + */ +class DetailsState { + elements = { + title: document.getElementById("ruleset-title"), + jwkValue: document.getElementById("ruleset-jwk-value"), + pathPrefixValue: document.getElementById("ruleset-path-prefix-value"), + scopeValue: document.getElementById("ruleset-scope-value"), + enableCheckbox: document.getElementById("ruleset-enable-checkbox"), + updateButton: document.getElementById("ruleset-update-button"), + updated: document.getElementById("ruleset-updated"), + }; + + constructor() { + document + .getElementById("ruleset-edit") + .addEventListener("click", this.onEdit.bind(this)); + this.elements.enableCheckbox.addEventListener( + "change", + this.onEnable.bind(this) + ); + this.elements.updateButton.addEventListener( + "click", + this.onUpdate.bind(this) + ); + } + + show(ruleset) { + const elements = this.elements; + elements.title.textContent = ruleset.name; + elements.jwkValue.textContent = JSON.stringify(ruleset.jwk); + elements.pathPrefixValue.setAttribute("href", ruleset.pathPrefix); + elements.pathPrefixValue.textContent = ruleset.pathPrefix; + elements.scopeValue.textContent = ruleset.scope; + elements.enableCheckbox.checked = ruleset.enabled; + if (ruleset.enabled) { + elements.updateButton.removeAttribute("disabled"); + } else { + elements.updateButton.setAttribute("disabled", "disabled"); + } + setUpdateDate(ruleset, elements.updated); + this._showing = ruleset; + + gAboutRulesets.list.setItemSelected(ruleset.name); + } + + hide() { + this._showing = null; + } + + onEdit() { + gAboutRulesets.setState(States.Edit, this._showing); + } + + async onEnable() { + await RPMSendAsyncMessage("rulesets:enable-channel", { + name: this._showing.name, + enabled: this.elements.enableCheckbox.checked, + }); + } + + async onUpdate() { + try { + await RPMSendQuery("rulesets:update-channel", this._showing.name); + } catch (err) { + console.error("Could not update the rulesets", err); + } + } +} + +/** + * State to edit a channel. + */ +class EditState { + elements = { + form: document.getElementById("edit-ruleset-form"), + title: document.getElementById("edit-title"), + jwkTextarea: document.getElementById("edit-jwk-textarea"), + pathPrefixInput: document.getElementById("edit-path-prefix-input"), + scopeInput: document.getElementById("edit-scope-input"), + enableCheckbox: document.getElementById("edit-enable-checkbox"), + }; + + constructor() { + document + .getElementById("edit-save") + .addEventListener("click", this.onSave.bind(this)); + document + .getElementById("edit-cancel") + .addEventListener("click", this.onCancel.bind(this)); + } + + show(ruleset) { + const elements = this.elements; + elements.form.reset(); + elements.title.textContent = ruleset.name; + elements.jwkTextarea.value = JSON.stringify(ruleset.jwk); + elements.pathPrefixInput.value = ruleset.pathPrefix; + elements.scopeInput.value = ruleset.scope; + elements.enableCheckbox.checked = ruleset.enabled; + this._editing = ruleset; + } + + hide() { + this.elements.form.reset(); + this._editing = null; + } + + async onSave(e) { + e.preventDefault(); + const elements = this.elements; + + let valid = true; + const name = this._editing.name; + + let jwk; + try { + jwk = JSON.parse(elements.jwkTextarea.value); + await crypto.subtle.importKey( + "jwk", + jwk, + { + name: "RSA-PSS", + saltLength: 32, + hash: { name: "SHA-256" }, + }, + true, + ["verify"] + ); + elements.jwkTextarea.setCustomValidity(""); + } catch (err) { + console.error("Invalid JSON or invalid JWK", err); + elements.jwkTextarea.setCustomValidity( + await document.l10n.formatValue("rulesets-details-jwk-input-invalid") + ); + valid = false; + } + + const pathPrefix = elements.pathPrefixInput.value.trim(); + try { + const url = new URL(pathPrefix); + if (url.protocol !== "http:" && url.protocol !== "https:") { + elements.pathPrefixInput.setCustomValidity( + await document.l10n.formatValue("rulesets-details-path-input-invalid") + ); + valid = false; + } else { + elements.pathPrefixInput.setCustomValidity(""); + } + } catch (err) { + console.error("The path prefix is not a valid URL", err); + elements.pathPrefixInput.setCustomValidity( + await document.l10n.formatValue("rulesets-details-path-input-invalid") + ); + valid = false; + } + + let scope; + try { + scope = new RegExp(elements.scopeInput.value.trim()); + elements.scopeInput.setCustomValidity(""); + } catch (err) { + elements.scopeInput.setCustomValidity( + await document.l10n.formatValue("rulesets-details-scope-input-invalid") + ); + valid = false; + } + + if (!valid) { + return; + } + + const enabled = elements.enableCheckbox.checked; + + const rulesetData = { name, jwk, pathPrefix, scope, enabled }; + const ruleset = await RPMSendQuery("rulesets:set-channel", rulesetData); + gAboutRulesets.setState(States.Details, ruleset); + if (enabled) { + try { + await RPMSendQuery("rulesets:update-channel", name); + } catch (err) { + console.warn("Could not update the ruleset after adding it", err); + } + } + } + + onCancel(e) { + e.preventDefault(); + if (this._editing === null) { + gAboutRulesets.selectFirst(); + } else { + gAboutRulesets.setState(States.Details, this._editing); + } + } +} + +/** + * State shown when no rulesets are available. + * Currently, the only way to reach it is to delete all the channels manually. + */ +class NoRulesetsState { + show() {} + hide() {} +} + +/** + * Manages the sidebar with the list of the various channels, and keeps it in + * sync with the data we receive from the backend. + */ +class RulesetList { + elements = { + list: document.getElementById("ruleset-list"), + emptyContainer: document.getElementById("ruleset-list-empty"), + itemTemplate: document.getElementById("ruleset-template"), + }; + + nameAttribute = "data-name"; + + rulesets = []; + + constructor() { + RPMAddMessageListener( + "rulesets:channels-change", + this.onRulesetsChanged.bind(this) + ); + } + + getSelectedRuleset() { + const name = this.elements.list + .querySelector(".selected") + ?.getAttribute(this.nameAttribute); + for (const ruleset of this.rulesets) { + if (ruleset.name == name) { + return ruleset; + } + } + return null; + } + + isEmpty() { + return !this.rulesets.length; + } + + async update() { + this.rulesets = await RPMSendQuery("rulesets:get-channels"); + await this._populateRulesets(); + } + + setItemSelected(name) { + name = name.replace(/["\\]/g, "\\$&"); + const item = this.elements.list.querySelector( + `.item[${this.nameAttribute}="${name}"]` + ); + this._selectItem(item); + } + + async _populateRulesets() { + if (this.isEmpty()) { + this.elements.emptyContainer.classList.remove("hidden"); + } else { + this.elements.emptyContainer.classList.add("hidden"); + } + + const list = this.elements.list; + const selName = list + .querySelector(".item.selected") + ?.getAttribute(this.nameAttribute); + const items = list.querySelectorAll(".item"); + for (const item of items) { + item.remove(); + } + + for (const ruleset of this.rulesets) { + const item = this._addItem(ruleset); + if (ruleset.name === selName) { + this._selectItem(item); + } + } + } + + _addItem(ruleset) { + const item = this.elements.itemTemplate.cloneNode(true); + item.removeAttribute("id"); + item.classList.add("item"); + item.querySelector(".name").textContent = ruleset.name; + const descr = item.querySelector(".description"); + setUpdateDate(ruleset, descr); + item.classList.toggle("disabled", !ruleset.enabled); + item.setAttribute(this.nameAttribute, ruleset.name); + item.addEventListener("click", () => { + this.onRulesetClick(ruleset); + }); + this.elements.list.append(item); + return item; + } + + _selectItem(item) { + this.elements.list.querySelector(".selected")?.classList.remove("selected"); + item?.classList.add("selected"); + } + + onRulesetClick(ruleset) { + gAboutRulesets.setState(States.Details, ruleset); + } + + onRulesetsChanged(data) { + this.rulesets = data.data; + this._populateRulesets(); + const selected = this.getSelectedRuleset(); + if (selected !== null) { + gAboutRulesets.setState(States.Details, selected); + } + } +} + +/** + * The entry point of about:rulesets. + * It initializes the various states and allows to switch between them. + */ +class AboutRulesets { + _state = null; + + async init() { + const args = await RPMSendQuery("rulesets:get-init-args"); + const showWarning = args.showWarning; + + this.list = new RulesetList(); + this._states = {}; + this._states[States.Warning] = new WarningState(); + this._states[States.Details] = new DetailsState(); + this._states[States.Edit] = new EditState(); + this._states[States.NoRulesets] = new NoRulesetsState(); + + await this.refreshRulesets(); + + if (showWarning) { + this.setState(States.Warning); + } else { + this.selectFirst(); + } + } + + setState(state, ...args) { + document.querySelector("body").className = `state-${state}`; + this._state?.hide(); + this._state = this._states[state]; + this._state.show(...args); + } + + async refreshRulesets() { + await this.list.update(); + if (this._state === this._states[States.Details]) { + const ruleset = this.list.getSelectedRuleset(); + if (ruleset !== null) { + this.setState(States.Details, ruleset); + } else { + this.selectFirst(); + } + } else if (this.list.isEmpty()) { + this.setState(States.NoRulesets); + } + } + + selectFirst() { + if (this.list.isEmpty()) { + this.setState(States.NoRulesets); + } else { + this.setState("details", this.list.rulesets[0]); + } + } +} + +const gAboutRulesets = new AboutRulesets(); +gAboutRulesets.init(); diff --git a/browser/components/rulesets/content/securedrop.svg b/browser/components/rulesets/content/securedrop.svg new file mode 100644 index 0000000000000000000000000000000000000000..69cd584ac1edf89ad9649623db19fc8a7ebd51eb --- /dev/null +++ b/browser/components/rulesets/content/securedrop.svg @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 23.0.5, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> + +<svg + version="1.1" + id="Layer_1" + x="0px" + y="0px" + viewBox="0 0 423.3 423.3" + xml:space="preserve" + width="423.29999" + height="423.29999" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"><defs + id="defs49"> + + + + + + + + + + + <defs + id="defs24"> + <filter + id="Adobe_OpacityMaskFilter_1_" + filterUnits="userSpaceOnUse" + x="-66" + y="-0.89999998" + width="183.3" + height="318.20001"> + <feColorMatrix + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" + id="feColorMatrix21" /> + </filter> + </defs> + <mask + maskUnits="userSpaceOnUse" + x="-66" + y="-0.9" + width="183.3" + height="318.2" + id="mask-4_1_"> + <g + class="st4" + id="g27"> + <polygon + id="path-3_1_" + class="st2" + points="117.3,-0.9 117.3,317.3 -66,317.3 -66,-0.9 " /> + </g> + </mask> + + + + <defs + id="defs36"> + <filter + id="Adobe_OpacityMaskFilter_2_" + filterUnits="userSpaceOnUse" + x="-66" + y="-1" + width="366.29999" + height="211.3"> + <feColorMatrix + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" + id="feColorMatrix33" /> + </filter> + </defs> + <mask + maskUnits="userSpaceOnUse" + x="-66" + y="-1" + width="366.3" + height="211.3" + id="mask-6_1_"> + <g + class="st6" + id="g39"> + <polygon + id="path-5_1_" + class="st2" + points="300.3,-1 300.3,210.3 -66,210.3 -66,-1 " /> + </g> + </mask> + + + + + <defs + id="defs11"> + <filter + id="Adobe_OpacityMaskFilter" + filterUnits="userSpaceOnUse" + x="-65.199997" + y="-0.89999998" + width="183.5" + height="318.20001"> + <feColorMatrix + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" + id="feColorMatrix8" /> + </filter> + </defs> + <mask + maskUnits="userSpaceOnUse" + x="-65.2" + y="-0.9" + width="183.5" + height="318.2" + id="mask-2_1_"> + <g + class="st1" + id="g14"> + <polygon + id="path-1_1_" + class="st2" + points="-65.2,317.3 -65.2,-0.9 118.3,-0.9 118.3,317.3 " /> + </g> + </mask> + + + + </defs> +<style + type="text/css" + id="style2"> + .st0{fill-rule:evenodd;clip-rule:evenodd;fill:#055FB4;} + .st1{filter:url(#Adobe_OpacityMaskFilter);} + .st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;} + .st3{mask:url(#mask-2_1_);fill-rule:evenodd;clip-rule:evenodd;fill:#055FB4;} + .st4{filter:url(#Adobe_OpacityMaskFilter_1_);} + .st5{mask:url(#mask-4_1_);fill-rule:evenodd;clip-rule:evenodd;fill:#093D70;} + .st6{filter:url(#Adobe_OpacityMaskFilter_2_);} + .st7{mask:url(#mask-6_1_);fill-rule:evenodd;clip-rule:evenodd;fill:#2E8AE8;} +</style> +<title + id="title4">Big Logo HP</title> +<circle + style="fill:#ffffff;stroke:none;stroke-width:2.66667" + id="path1626" + r="176.46054" + cy="211.64999" + cx="211.64999" /><path + id="Fill-1" + class="st0" + d="m 327.99999,225.5 -41.8,23.9 0.2,58.5 42.5,-23.6 c 5.1,-2.8 8.3,-8.3 8.3,-14 v -39.7 c -0.2,-0.9 -0.2,-2.1 -0.9,-2.8 -1.9,-2.8 -5.6,-3.9 -8.3,-2.3" /><path + id="Fill-3" + class="st3" + d="m 85.9,173.2 c 0,9.9 -5.3,19 -14,24.1 l -90.7,52.3 V 127.3 l 84,-48.6 c 2.1,-1.1 4.4,-1.8 6.9,-1.8 7.6,0 13.8,6.2 13.8,13.8 z M -65.2,104.9 V 317.3 L 118.3,211.5 V -0.9 Z" + mask="url(#mask-2_1_)" + transform="translate(276.49999,106)" /><path + id="Fill-7" + class="st5" + d="M 71.7,158.3 3.3,118.8 v 14 l 68.4,39.5 v 73.9 L -22.2,192 v -30.1 l 64,37.2 v -13.8 l -64,-37.2 V 75 l 93.8,54.2 v 29.1 z M -66,-0.9 V 211.5 L 117.3,317.3 V 104.9 Z" + mask="url(#mask-4_1_)" + transform="translate(94.499994,106)" /><path + id="Fill-10" + class="st7" + d="m 135,143.2 55.3,-31.1 -62.2,-17.2 c 1.1,-2.1 1.8,-4.4 1.8,-6.6 0,-11.5 -16.7,-21.1 -37.4,-21.1 -20.6,0 -37.4,9.4 -37.4,21.1 0,11.7 16.7,21.1 37.4,21.1 2.8,0 5.3,-0.2 8,-0.5 z M 117,210.3 -66,104.7 117,-1 300.3,104.7 Z" + mask="url(#mask-6_1_)" + transform="translate(94.499994,1)" /> +<metadata + id="metadata866"><rdf:RDF><cc:Work + rdf:about=""><dc:title>Big Logo HP</dc:title></cc:Work></rdf:RDF></metadata></svg> diff --git a/browser/components/rulesets/jar.mn b/browser/components/rulesets/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..e0b67442d89c0e4a170599adf2131047c0a6f996 --- /dev/null +++ b/browser/components/rulesets/jar.mn @@ -0,0 +1,5 @@ +browser.jar: + content/browser/rulesets/aboutRulesets.css (content/aboutRulesets.css) + content/browser/rulesets/aboutRulesets.html (content/aboutRulesets.html) + content/browser/rulesets/aboutRulesets.js (content/aboutRulesets.js) + content/browser/rulesets/securedrop.svg (content/securedrop.svg) diff --git a/browser/components/rulesets/moz.build b/browser/components/rulesets/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..2484c62d97ac6d2b4b751f7e46763558be3faf7e --- /dev/null +++ b/browser/components/rulesets/moz.build @@ -0,0 +1,6 @@ +JAR_MANIFESTS += ["jar.mn"] + +EXTRA_JS_MODULES += [ + "RulesetsChild.sys.mjs", + "RulesetsParent.sys.mjs", +] diff --git a/browser/components/search/SearchSERPTelemetry.sys.mjs b/browser/components/search/SearchSERPTelemetry.sys.mjs index 5aac240e8707086e66b4248436ef93cf2c82ddaa..3d97c927049dfd85c592873b5eb328f59f843e8a 100644 --- a/browser/components/search/SearchSERPTelemetry.sys.mjs +++ b/browser/components/search/SearchSERPTelemetry.sys.mjs @@ -236,7 +236,8 @@ class TelemetryHandler { * can be tracked. */ async init() { - if (this._initialized) { + // eslint-disable-next-line no-constant-condition + if (this._initialized || true) { return; } @@ -915,7 +916,7 @@ class TelemetryHandler { * @returns {Array | null} Returns an array of provider name and the provider information. */ _getProviderInfoForURL(url) { - return this._searchProviderInfo.find(info => + return this._searchProviderInfo?.find(info => info.searchPageRegexp.test(url) ); } @@ -2715,6 +2716,8 @@ class DomainToCategoriesMap { * reuse the store if the version in each record matches the store. */ async #setupClientAndStore() { + return; + // eslint-disable-next-line no-unreachable if (this.#client && !this.empty) { return; } diff --git a/browser/components/search/extensions/ddg-onion/favicon.ico b/browser/components/search/extensions/ddg-onion/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..13c325f6585f6f39107e470b70674eb16352c14e Binary files /dev/null and b/browser/components/search/extensions/ddg-onion/favicon.ico differ diff --git a/browser/components/search/extensions/ddg-onion/manifest.json b/browser/components/search/extensions/ddg-onion/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..2bcc199dc50a376167d899c7f7588a79a478d1eb --- /dev/null +++ b/browser/components/search/extensions/ddg-onion/manifest.json @@ -0,0 +1,26 @@ +{ + "name": "DuckDuckGo (.onion)", + "description": "Duck Duck Go Onion", + "manifest_version": 2, + "version": "1.0", + "applications": { + "gecko": { + "id": "ddg-onion@search.mozilla.org" + } + }, + "hidden": true, + "icons": { + "16": "favicon.ico" + }, + "web_accessible_resources": ["favicon.ico"], + "chrome_settings_overrides": { + "search_provider": { + "name": "DuckDuckGo (.onion)", + "search_url": "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion", + "search_form": "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/?q={searchTerms}", + "search_url_get_params": "q={searchTerms}", + "suggest_url": "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/ac/", + "suggest_url_get_params": "q={searchTerms}&type=list" + } + } +} diff --git a/browser/components/search/extensions/ddg/manifest.json b/browser/components/search/extensions/ddg/manifest.json index 104eee64576588168f531140b93b2a8963b0199c..9a63a5e0e616df5e010c761292212cd87e627e3a 100644 --- a/browser/components/search/extensions/ddg/manifest.json +++ b/browser/components/search/extensions/ddg/manifest.json @@ -14,7 +14,7 @@ "keyword": ["@duckduckgo", "@ddg"], "name": "DuckDuckGo", "search_url": "https://duckduckgo.com/", - "search_url_get_params": "t=ffab&q={searchTerms}", + "search_url_get_params": "q={searchTerms}", "suggest_url": "https://ac.duckduckgo.com/ac/", "suggest_url_get_params": "q={searchTerms}&type=list" } diff --git a/browser/components/search/extensions/startpage-onion/favicon.png b/browser/components/search/extensions/startpage-onion/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..30ed2cd3a65a0ff09fec246e5dab662a297bacb9 Binary files /dev/null and b/browser/components/search/extensions/startpage-onion/favicon.png differ diff --git a/browser/components/search/extensions/startpage-onion/manifest.json b/browser/components/search/extensions/startpage-onion/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..3f4798d321d8fb365fe3ab9305ebcf60707c0ca2 --- /dev/null +++ b/browser/components/search/extensions/startpage-onion/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "Startpage (.onion)", + "description": "Startpage Onion", + "manifest_version": 2, + "version": "1.0", + "applications": { + "gecko": { + "id": "startpage-onion@search.mozilla.org" + } + }, + "hidden": true, + "icons": { + "16": "favicon.png" + }, + "web_accessible_resources": ["favicon.png"], + "chrome_settings_overrides": { + "search_provider": { + "name": "Startpage (.onion)", + "search_url": "http://startpagel6srwcjlue4zgq3zevrujfaow726kjytqbbjyrswwmjzcqd.onion/sp/search", + "search_form": "http://startpagel6srwcjlue4zgq3zevrujfaow726kjytqbbjyrswwmjzcqd.onion/sp/search/", + "search_url_post_params": "q={searchTerms}" + } + } +} diff --git a/browser/components/search/extensions/startpage/favicon.png b/browser/components/search/extensions/startpage/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..30ed2cd3a65a0ff09fec246e5dab662a297bacb9 Binary files /dev/null and b/browser/components/search/extensions/startpage/favicon.png differ diff --git a/browser/components/search/extensions/startpage/manifest.json b/browser/components/search/extensions/startpage/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..137f2de1f72413275708c36f54f6c117b8a3090a --- /dev/null +++ b/browser/components/search/extensions/startpage/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "Startpage", + "description": "Startpage", + "manifest_version": 2, + "version": "1.0", + "applications": { + "gecko": { + "id": "startpage@search.mozilla.org" + } + }, + "hidden": true, + "icons": { + "16": "favicon.png" + }, + "web_accessible_resources": ["favicon.png"], + "chrome_settings_overrides": { + "search_provider": { + "name": "Startpage", + "search_url": "https://www.startpage.com/sp/search", + "search_form": "https://www.startpage.com/sp/search/", + "search_url_post_params": "q={searchTerms}" + } + } +} diff --git a/browser/components/securitylevel/content/securityLevel.js b/browser/components/securitylevel/content/securityLevel.js new file mode 100644 index 0000000000000000000000000000000000000000..326f3df6a4b6f33956b2a6c13f8a43b05783a438 --- /dev/null +++ b/browser/components/securitylevel/content/securityLevel.js @@ -0,0 +1,389 @@ +"use strict"; + +/* global AppConstants, Services, openPreferences, XPCOMUtils */ + +ChromeUtils.defineESModuleGetters(this, { + SecurityLevelPrefs: "resource://gre/modules/SecurityLevel.sys.mjs", +}); + +/* + Security Level Button Code + + Controls init and update of the security level toolbar button +*/ + +var SecurityLevelButton = { + _securityPrefsBranch: null, + /** + * Whether we have added popup listeners to the panel. + * + * @type {boolean} + */ + _panelPopupListenersSetup: false, + /** + * The toolbar button element. + * + * @type {Element} + */ + _button: null, + /** + * The button that the panel should point to. Either the toolbar button or the + * overflow button. + * + * @type {Element} + */ + _anchorButton: null, + + _configUIFromPrefs() { + const level = SecurityLevelPrefs.securityLevel; + if (!level) { + return; + } + const custom = SecurityLevelPrefs.securityCustom; + this._button.setAttribute("level", custom ? `${level}_custom` : level); + + let l10nIdLevel; + switch (level) { + case "standard": + l10nIdLevel = "security-level-toolbar-button-standard"; + break; + case "safer": + l10nIdLevel = "security-level-toolbar-button-safer"; + break; + case "safest": + l10nIdLevel = "security-level-toolbar-button-safest"; + break; + default: + throw Error(`Unhandled level: ${level}`); + } + if (custom) { + // Don't distinguish between the different levels when in the custom + // state. We just want to emphasise that it is custom rather than any + // specific level. + l10nIdLevel = "security-level-toolbar-button-custom"; + } + document.l10n.setAttributes(this._button, l10nIdLevel); + }, + + /** + * Open the panel popup for the button. + */ + openPopup() { + const overflowPanel = document.getElementById("widget-overflow"); + if (overflowPanel.contains(this._button)) { + // We are in the overflow panel. + // We first close the overflow panel, otherwise focus will not return to + // the nav-bar-overflow-button if the security level panel is closed with + // "Escape" (the navigation toolbar does not track focus when a panel is + // opened whilst another is already open). + // NOTE: In principle, using PanelMultiView would allow us to open panels + // from within another panel. However, when using panelmultiview for the + // security level panel, tab navigation was broken within the security + // level panel. PanelMultiView may be set up to work with a menu-like + // panel rather than our dialog-like panel. + overflowPanel.hidePopup(); + this._anchorButton = document.getElementById("nav-bar-overflow-button"); + } else { + this._anchorButton = this._button; + } + + const panel = SecurityLevelPanel.panel; + if (!this._panelPopupListenersSetup) { + this._panelPopupListenersSetup = true; + // NOTE: We expect the _anchorButton to not change whilst the popup is + // open. + panel.addEventListener("popupshown", () => { + this._anchorButton.setAttribute("open", "true"); + }); + panel.addEventListener("popuphidden", () => { + this._anchorButton.removeAttribute("open"); + }); + } + + panel.openPopup( + this._anchorButton.icon, + "bottomright topright", + 0, + 0, + false + ); + }, + + init() { + // We first search in the DOM for the security level button. If it does not + // exist it may be in the toolbox palette. We still want to return the + // button in the latter case to allow it to be initialized or adjusted in + // case it is added back through customization. + this._button = + document.getElementById("security-level-button") || + window.gNavToolbox.palette.querySelector("#security-level-button"); + // Set a label to be be used as the accessible name, and to be shown in the + // overflow menu and during customization. + this._button.addEventListener("command", () => this.openPopup()); + // set the initial class based off of the current pref + this._configUIFromPrefs(); + + this._securityPrefsBranch = Services.prefs.getBranch( + "browser.security_level." + ); + this._securityPrefsBranch.addObserver("", this); + + SecurityLevelPanel.init(); + }, + + uninit() { + this._securityPrefsBranch.removeObserver("", this); + this._securityPrefsBranch = null; + + SecurityLevelPanel.uninit(); + }, + + observe(subject, topic, data) { + switch (topic) { + case "nsPref:changed": + if (data === "security_slider" || data === "security_custom") { + this._configUIFromPrefs(); + } + break; + } + }, +}; /* SecurityLevelButton */ + +/* + Security Level Panel Code + + Controls init and update of the panel in the security level hanger +*/ + +var SecurityLevelPanel = { + _securityPrefsBranch: null, + _populated: false, + + _populateXUL() { + this._elements = { + panel: document.getElementById("securityLevel-panel"), + background: document.getElementById("securityLevel-background"), + levelName: document.getElementById("securityLevel-level"), + customName: document.getElementById("securityLevel-custom"), + summary: document.getElementById("securityLevel-summary"), + restoreDefaultsButton: document.getElementById( + "securityLevel-restoreDefaults" + ), + settingsButton: document.getElementById("securityLevel-settings"), + }; + + const learnMoreEl = document.getElementById("securityLevel-learnMore"); + learnMoreEl.addEventListener("click", () => { + this.hide(); + }); + + this._elements.restoreDefaultsButton.addEventListener("command", () => { + this.restoreDefaults(); + }); + this._elements.settingsButton.addEventListener("command", () => { + this.openSecuritySettings(); + }); + + this._elements.panel.addEventListener("popupshown", () => { + // Bring focus into the panel by focusing the default button. + this._elements.panel.querySelector('button[default="true"]').focus(); + }); + + this._populated = true; + this._configUIFromPrefs(); + }, + + _configUIFromPrefs() { + if (!this._populated) { + return; + } + + // get security prefs + const level = SecurityLevelPrefs.securityLevel; + const custom = SecurityLevelPrefs.securityCustom; + + // only visible when user is using custom settings + this._elements.customName.hidden = !custom; + this._elements.restoreDefaultsButton.hidden = !custom; + if (custom) { + this._elements.settingsButton.removeAttribute("default"); + this._elements.restoreDefaultsButton.setAttribute("default", "true"); + } else { + this._elements.settingsButton.setAttribute("default", "true"); + this._elements.restoreDefaultsButton.removeAttribute("default"); + } + + // Descriptions change based on security level + this._elements.background.setAttribute("level", level); + let l10nIdLevel; + let l10nIdSummary; + switch (level) { + case "standard": + l10nIdLevel = "security-level-panel-level-standard"; + l10nIdSummary = "security-level-summary-standard"; + break; + case "safer": + l10nIdLevel = "security-level-panel-level-safer"; + l10nIdSummary = "security-level-summary-safer"; + break; + case "safest": + l10nIdLevel = "security-level-panel-level-safest"; + l10nIdSummary = "security-level-summary-safest"; + break; + default: + throw Error(`Unhandled level: ${level}`); + } + if (custom) { + l10nIdSummary = "security-level-summary-custom"; + } + + document.l10n.setAttributes(this._elements.levelName, l10nIdLevel); + document.l10n.setAttributes(this._elements.summary, l10nIdSummary); + }, + + /** + * The popup element. + * + * @type {MozPanel} + */ + get panel() { + if (!this._populated) { + this._populateXUL(); + } + return this._elements.panel; + }, + + init() { + this._securityPrefsBranch = Services.prefs.getBranch( + "browser.security_level." + ); + this._securityPrefsBranch.addObserver("", this); + }, + + uninit() { + this._securityPrefsBranch.removeObserver("", this); + this._securityPrefsBranch = null; + }, + + hide() { + this._elements.panel.hidePopup(); + }, + + restoreDefaults() { + SecurityLevelPrefs.securityCustom = false; + // Move focus to the settings button since restore defaults button will + // become hidden. + this._elements.settingsButton.focus(); + }, + + openSecuritySettings() { + openPreferences("privacy-securitylevel"); + this.hide(); + }, + + // callback when prefs change + observe(subject, topic, data) { + switch (topic) { + case "nsPref:changed": + if (data == "security_slider" || data == "security_custom") { + this._configUIFromPrefs(); + } + break; + } + }, +}; /* SecurityLevelPanel */ + +/* + Security Level Preferences Code + + Code to handle init and update of security level section in about:preferences#privacy +*/ + +var SecurityLevelPreferences = { + _securityPrefsBranch: null, + /** + * The notification box shown when the user has a custom security setting. + * + * @type {Element} + */ + _customNotification: null, + /** + * The radiogroup for this preference. + * + * @type {Element} + */ + _radiogroup: null, + /** + * A list of radio options and their containers. + * + * @type {Array<object>} + */ + _radioOptions: null, + + _populateXUL() { + this._customNotification = document.getElementById( + "securityLevel-customNotification" + ); + document + .getElementById("securityLevel-restoreDefaults") + .addEventListener("command", () => { + SecurityLevelPrefs.securityCustom = false; + }); + + this._radiogroup = document.getElementById("securityLevel-radiogroup"); + + this._radioOptions = Array.from( + this._radiogroup.querySelectorAll(".securityLevel-radio-option"), + container => { + return { container, radio: container.querySelector("radio") }; + } + ); + + this._radiogroup.addEventListener("select", () => { + SecurityLevelPrefs.securityLevel = this._radiogroup.value; + }); + }, + + _configUIFromPrefs() { + this._radiogroup.value = SecurityLevelPrefs.securityLevel; + const isCustom = SecurityLevelPrefs.securityCustom; + this._radiogroup.disabled = isCustom; + this._customNotification.hidden = !isCustom; + // Have the container's selection CSS class match the selection state of the + // radio elements. + for (const { container, radio } of this._radioOptions) { + container.classList.toggle("selected", radio.selected); + } + }, + + init() { + // populate XUL with localized strings + this._populateXUL(); + + // read prefs and populate UI + this._configUIFromPrefs(); + + // register for pref chagnes + this._securityPrefsBranch = Services.prefs.getBranch( + "browser.security_level." + ); + this._securityPrefsBranch.addObserver("", this); + }, + + uninit() { + // unregister for pref change events + this._securityPrefsBranch.removeObserver("", this); + this._securityPrefsBranch = null; + }, + + // callback for when prefs change + observe(subject, topic, data) { + switch (topic) { + case "nsPref:changed": + if (data == "security_slider" || data == "security_custom") { + this._configUIFromPrefs(); + } + break; + } + }, +}; /* SecurityLevelPreferences */ diff --git a/browser/components/securitylevel/content/securityLevelButton.css b/browser/components/securitylevel/content/securityLevelButton.css new file mode 100644 index 0000000000000000000000000000000000000000..542412c2c705023ecc2b918bb174af93a7d52044 --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelButton.css @@ -0,0 +1,18 @@ +toolbarbutton#security-level-button[level="standard"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard"); +} +toolbarbutton#security-level-button[level="safer"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer"); +} +toolbarbutton#security-level-button[level="safest"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest"); +} +toolbarbutton#security-level-button[level="standard_custom"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard_custom"); +} +toolbarbutton#security-level-button[level="safer_custom"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer_custom"); +} +toolbarbutton#security-level-button[level="safest_custom"] { + list-style-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest_custom"); +} diff --git a/browser/components/securitylevel/content/securityLevelButton.inc.xhtml b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..8e20fb40895fc50a0e8312cdf5078bd1af3066c4 --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml @@ -0,0 +1,4 @@ +<toolbarbutton id="security-level-button" + class="toolbarbutton-1 chromeclass-toolbar-additional" + removable="true" + cui-areatype="toolbar"/> diff --git a/browser/components/securitylevel/content/securityLevelIcon.svg b/browser/components/securitylevel/content/securityLevelIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..38cdbcb68afc3ed075c8f8244053d3f2de794e93 --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelIcon.svg @@ -0,0 +1,40 @@ +<svg width="16" height="16" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <style> + use:not(:target) { + display: none; + } + </style> + <defs> + <g id="standard_icon" stroke="none" stroke-width="1"> + <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd" /> + </g> + <g id="safer_icon" stroke="none" stroke-width="1"> + <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd"/> + <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4-2.28572c.16666-.09523.37403.02511.37403.21707v10.0766c-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/> + </g> + <g id="safest_icon" stroke="none" stroke-width="1"> + <path clip-rule="evenodd" d="m8.49614.283505c-.30743-.175675-.68485-.175675-.99228.000001l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 4.0133-.9164 7-6 7-10v-1.41968c0-.35886-.1923-.6902-.5039-.86824zm-.49614 1.216495-5.75 3.28571v1.2746c0 1.71749.65238 3.7522 1.78726 5.46629 1.07287 1.6204 2.47498 2.8062 3.96274 3.2425 1.48776-.4363 2.8899-1.6221 3.9627-3.2425 1.1349-1.71409 1.7873-3.7488 1.7873-5.46629v-1.2746z" fill-rule="evenodd"/> + <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4.25-2.42857c.07685-.04392.17121-.04392.24806 0l4.24997 2.42857c.0779.04451.126.12734.126.21706v.40411c0 1.43511-.5582 3.23363-1.5795 4.77628-.8665 1.3087-1.90846 2.2025-2.9205 2.6105-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/> + </g> + <g id="standard_custom_icon" stroke="none" stroke-width="1"> + <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/> + <circle cx="13" cy="3" fill="#ffbd2e" r="3"/> + </g> + <g id="safer_custom_icon" stroke="none" stroke-width="1"> + <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/> + <path d="m3.5 6.12062v-.40411c0-.08972.04807-.17255.12597-.21706l4-2.28572c.16666-.09523.37403.02511.37403.21707v10.0766c-1.01204-.408-2.054-1.3018-2.92048-2.6105-1.02134-1.54265-1.57952-3.34117-1.57952-4.77628z"/> + <circle cx="13" cy="3" fill="#ffbd2e" r="3"/> + </g> + <g id="safest_custom_icon" stroke="none" stroke-width="1"> + <path d="m9.37255.784312-.87641-.500806c-.30743-.175676-.68485-.175676-.99228 0l-6 3.428574c-.31157.17804-.50386.50938-.50386.86824v1.41968c0 4 2.98667 9.0836 7 10 3.7599-.8585 6.6186-5.3745 6.9647-9.23043-.4008.20936-.8392.35666-1.3024.42914-.2132 1.43414-.8072 2.98009-1.6996 4.32789-1.0728 1.6204-2.47494 2.8062-3.9627 3.2425-1.48776-.4363-2.88987-1.6221-3.96274-3.2425-1.13488-1.71409-1.78726-3.7488-1.78726-5.46629v-1.2746l5.75-3.28571.86913.49664c.10502-.43392.27664-.84184.50342-1.212328z"/> + <path d="m8.77266 3.44151-.64863-.37064c-.07685-.04392-.17121-.04392-.24806 0l-4.25 2.42857c-.0779.04451-.12597.12735-.12597.21706v.40412c0 1.4351.55818 3.23362 1.57952 4.77618.86648 1.3087 1.90844 2.2026 2.92048 2.6106 1.01204-.408 2.054-1.3018 2.9205-2.6106.7761-1.17217 1.2847-2.49215 1.4843-3.68816-1.9219-.26934-3.43158-1.82403-3.63214-3.76713z"/> + <circle cx="13" cy="3" fill="#ffbd2e" r="3"/> + </g> + </defs> + <use id="standard" fill="context-fill" fill-opacity="context-fill-opacity" href="#standard_icon" /> + <use id="safer" fill="context-fill" fill-opacity="context-fill-opacity" href="#safer_icon" /> + <use id="safest" fill="context-fill" fill-opacity="context-fill-opacity" href="#safest_icon" /> + <use id="standard_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#standard_custom_icon" /> + <use id="safer_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#safer_custom_icon" /> + <use id="safest_custom" fill="context-fill" fill-opacity="context-fill-opacity" href="#safest_custom_icon" /> +</svg> diff --git a/browser/components/securitylevel/content/securityLevelPanel.css b/browser/components/securitylevel/content/securityLevelPanel.css new file mode 100644 index 0000000000000000000000000000000000000000..549cc770a557738bcf660c44a2e9f2d62a6c6b6a --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelPanel.css @@ -0,0 +1,67 @@ +/* Security Level CSS */ + +#securityLevel-background { + min-height: 10em; + padding-inline: 16px; + padding-block: 16px 8px; + gap: 16px; + background-repeat: no-repeat; + background-position-y: top 0.4em; + /* Icon center should be in-line with end padding. + * We set the right-to-left position here, and the left-to-right position + * below. */ + --background-inline-offset: calc(16px - 4.5em); + background-position-x: left var(--background-inline-offset); + background-size: 9em 9em; + -moz-context-properties: fill, fill-opacity; + fill-opacity: 1; + fill: var(--button-bgcolor); +} + +/* NOTE: Use ":dir" instead of ":-moz-locale-dir" when panel switches to HTML. */ +#securityLevel-background:-moz-locale-dir(ltr) { + background-position-x: right var(--background-inline-offset); +} + +#securityLevel-background[level="standard"] { + background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#standard"); +} + +#securityLevel-background[level="safer"] { + background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safer"); +} + +#securityLevel-background[level="safest"] { + background-image: url("chrome://browser/content/securitylevel/securityLevelIcon.svg#safest"); +} + +#securityLevel-background p { + margin: 0; +} + +/* Override margin in panelUI-shared.css */ +#securityLevel-panel toolbarseparator#securityLevel-separator { + margin-inline: 16px; +} + +#securityLevel-level { + font-size: 1.25em; + font-weight: 600; +} + +#securityLevel-custom { + border-radius: 4px; + background-color: var(--warning-icon-bgcolor); + color: black; + padding: 0.4em 0.5em; + margin-inline-start: 1em; +} + +#securityLevel-summary { + padding-inline-end: 5em; + max-width: 20em; +} + +#securityLevel-learnMore { + align-self: start; +} diff --git a/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..aea0aef900194d68c721fcc3b5731ad279868c26 --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml @@ -0,0 +1,43 @@ +<panel id="securityLevel-panel" + role="dialog" + aria-labelledby="securityLevel-header" + aria-describedby="securityLevel-subheading securityLevel-summary" + type="arrow" + orient="vertical" + class="cui-widget-panel panel-no-padding"> + <box class="panel-header"> + <html:h1 + id="securityLevel-header" + data-l10n-id="security-level-panel-heading" + ></html:h1> + </box> + <toolbarseparator id="securityLevel-separator"></toolbarseparator> + <vbox id="securityLevel-background" class="panel-subview-body"> + <html:p id="securityLevel-subheading"> + <html:span id="securityLevel-level"></html:span> + <html:span + id="securityLevel-custom" + data-l10n-id="security-level-panel-custom-badge" + ></html:span> + </html:p> + <html:p id="securityLevel-summary"></html:p> + <html:a + is="moz-support-link" + id="securityLevel-learnMore" + tor-manual-page="security-settings" + data-l10n-id="security-level-panel-learn-more-link" + ></html:a> + </vbox> + <html:moz-button-group class="panel-footer"> + <button + id="securityLevel-settings" + class="footer-button" + data-l10n-id="security-level-panel-open-settings-button" + /> + <button + id="securityLevel-restoreDefaults" + class="footer-button" + data-l10n-id="security-level-restore-defaults-button" + /> + </html:moz-button-group> +</panel> diff --git a/browser/components/securitylevel/content/securityLevelPreferences.css b/browser/components/securitylevel/content/securityLevelPreferences.css new file mode 100644 index 0000000000000000000000000000000000000000..1cbec2ca7e03132ec6aa93bdc1c851d49a5b082e --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelPreferences.css @@ -0,0 +1,26 @@ +#securityLevel-groupbox { + --section-highlight-background-color: color-mix(in srgb, var(--in-content-accent-color) 20%, transparent); +} + +#securityLevel-customNotification { + /* Spacing similar to #fpiIncompatibilityWarning. */ + margin-block: 16px; +} + +.info-icon.securityLevel-custom-warning-icon { + list-style-image: url("chrome://global/skin/icons/warning.svg"); +} + +#securityLevel-customHeading { + font-weight: bold; +} + +#securityLevel-radiogroup[disabled] { + opacity: 0.5; +} + +/* Overwrite the rule in common-shared.css so we don't get 0.25 opacity overall + * on the radio text. */ +#securityLevel-radiogroup[disabled] radio[disabled] .radio-label-box { + opacity: 1.0; +} diff --git a/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..51d03a23324c83156ceb17a98c98948c113247be --- /dev/null +++ b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml @@ -0,0 +1,128 @@ +<groupbox id="securityLevel-groupbox" + data-category="panePrivacy" + data-subcategory="securitylevel" + hidden="true"> + <label> + <html:h2 data-l10n-id="security-level-preferences-heading"></html:h2> + </label> + <vbox flex="1"> + <description class="description-deemphasized" flex="1"> + <html:span + id="securityLevel-overview" + data-l10n-id="security-level-preferences-overview" + ></html:span> + <html:a + is="moz-support-link" + tor-manual-page="security-settings" + data-l10n-id="security-level-preferences-learn-more-link" + ></html:a> + </description> + <hbox + id="securityLevel-customNotification" + class="info-box-container" + flex="1" + > + <hbox class="info-icon-container"> + <image class="info-icon securityLevel-custom-warning-icon"/> + </hbox> + <vbox flex="1"> + <label + id="securityLevel-customHeading" + data-l10n-id="security-level-preferences-custom-heading" + /> + <description + id="securityLevel-customDescription" + data-l10n-id="security-level-summary-custom" + flex="1" + /> + </vbox> + <hbox align="center"> + <button + id="securityLevel-restoreDefaults" + data-l10n-id="security-level-restore-defaults-button" + /> + </hbox> + </hbox> + <radiogroup id="securityLevel-radiogroup"> + <vbox class="securityLevel-radio-option privacy-detailedoption info-box-container"> + <radio + value="standard" + data-l10n-id="security-level-preferences-level-standard" + aria-describedby="securityLevelSummary-standard" + /> + <vbox id="securityLevelSummary-standard" class="indent"> + <label data-l10n-id="security-level-summary-standard" /> + </vbox> + </vbox> + <vbox class="securityLevel-radio-option privacy-detailedoption info-box-container"> + <!-- NOTE: We point the accessible description to the wrapping vbox + - rather than its first description element. This means that when the + - privacy-extra-information is shown or hidden, its text content is + - included or excluded from the accessible description, respectively. + --> + <radio + value="safer" + data-l10n-id="security-level-preferences-level-safer" + aria-describedby="securityLevelSummary-safer" + /> + <vbox id="securityLevelSummary-safer" class="indent"> + <label data-l10n-id="security-level-summary-safer" /> + <vbox class="privacy-extra-information"> + <vbox class="indent"> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-https-only-javascript" + /> + </hbox> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-limit-font-and-symbols" + /> + </hbox> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-limit-media" + /> + </hbox> + </vbox> + </vbox> + </vbox> + </vbox> + <vbox class="securityLevel-radio-option privacy-detailedoption info-box-container"> + <radio + value="safest" + data-l10n-id="security-level-preferences-level-safest" + aria-describedby="securityLevelSummary-safest" + /> + <vbox id="securityLevelSummary-safest" class="indent"> + <label data-l10n-id="security-level-summary-safest" /> + <vbox class="privacy-extra-information"> + <vbox class="indent"> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-disabled-javascript" + /> + </hbox> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-limit-font-and-symbols-and-images" + /> + </hbox> + <hbox class="extra-information-label"> + <label + class="content-blocking-label" + data-l10n-id="security-level-preferences-bullet-limit-media" + /> + </hbox> + </vbox> + </vbox> + </vbox> + </vbox> + </radiogroup> + </vbox> +</groupbox> diff --git a/browser/components/securitylevel/jar.mn b/browser/components/securitylevel/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..61aa4169f9ece228fdfa46bf7d14ef25076eb484 --- /dev/null +++ b/browser/components/securitylevel/jar.mn @@ -0,0 +1,6 @@ +browser.jar: + content/browser/securitylevel/securityLevel.js (content/securityLevel.js) + content/browser/securitylevel/securityLevelPanel.css (content/securityLevelPanel.css) + content/browser/securitylevel/securityLevelButton.css (content/securityLevelButton.css) + content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css) + content/browser/securitylevel/securityLevelIcon.svg (content/securityLevelIcon.svg) diff --git a/browser/components/securitylevel/moz.build b/browser/components/securitylevel/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..2661ad7cb9f3df2b3953a6e1e999aee82d29be78 --- /dev/null +++ b/browser/components/securitylevel/moz.build @@ -0,0 +1 @@ +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/components/shopping/jar.mn b/browser/components/shopping/jar.mn index 25fe1b1c0e941474ce283c22fa672a947dc66c68..06cfce0a718653f1dadb3909872983e5500a92c5 100644 --- a/browser/components/shopping/jar.mn +++ b/browser/components/shopping/jar.mn @@ -2,30 +2,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -browser.jar: - content/browser/shopping/onboarding.mjs (content/onboarding.mjs) - content/browser/shopping/shopping.html (content/shopping.html) - content/browser/shopping/shopping-container.css (content/shopping-container.css) - content/browser/shopping/shopping-page.css (content/shopping-page.css) - content/browser/shopping/shopping-sidebar.js (content/shopping-sidebar.js) - content/browser/shopping/shopping-message-bar.css (content/shopping-message-bar.css) - content/browser/shopping/shopping-message-bar.mjs (content/shopping-message-bar.mjs) - content/browser/shopping/highlights.mjs (content/highlights.mjs) - content/browser/shopping/highlight-item.css (content/highlight-item.css) - content/browser/shopping/highlight-item.mjs (content/highlight-item.mjs) - content/browser/shopping/shopping-card.css (content/shopping-card.css) - content/browser/shopping/shopping-card.mjs (content/shopping-card.mjs) - content/browser/shopping/letter-grade.css (content/letter-grade.css) - content/browser/shopping/letter-grade.mjs (content/letter-grade.mjs) - content/browser/shopping/settings.mjs (content/settings.mjs) - content/browser/shopping/settings.css (content/settings.css) - content/browser/shopping/shopping-container.mjs (content/shopping-container.mjs) - content/browser/shopping/adjusted-rating.mjs (content/adjusted-rating.mjs) - content/browser/shopping/reliability.mjs (content/reliability.mjs) - content/browser/shopping/analysis-explainer.css (content/analysis-explainer.css) - content/browser/shopping/analysis-explainer.mjs (content/analysis-explainer.mjs) - content/browser/shopping/unanalyzed.css (content/unanalyzed.css) - content/browser/shopping/unanalyzed.mjs (content/unanalyzed.mjs) - content/browser/shopping/recommended-ad.css (content/recommended-ad.css) - content/browser/shopping/recommended-ad.mjs (content/recommended-ad.mjs) - content/browser/shopping/assets/ (content/assets/*) +# Removed desktop shopping-sidebar content. tor-browser#42831. diff --git a/browser/components/shopping/moz.build b/browser/components/shopping/moz.build index 1db819a6317b14436ed4c4bdace3d367de571ab4..18fa6f7bd4da11bd640a39a0f2270397f3fb91fd 100644 --- a/browser/components/shopping/moz.build +++ b/browser/components/shopping/moz.build @@ -6,14 +6,8 @@ JAR_MANIFESTS += ["jar.mn"] -FINAL_TARGET_FILES.actors += [ - "ShoppingSidebarChild.sys.mjs", - "ShoppingSidebarParent.sys.mjs", -] - -EXTRA_JS_MODULES += [ - "ShoppingUtils.sys.mjs", -] +# Removed ShoppingSidebarParent, ShoppingSidebarChild and ShoppingUtils. +# tor-browser#42831. BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.toml"] diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..e204b73d71bab42b080830a494d18b0f8c8b2b31 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -2274,6 +2274,10 @@ stack.className = "browserStack"; stack.appendChild(b); + let decorator = document.createXULElement("hbox"); + decorator.className = "browserDecorator"; + stack.appendChild(decorator); + let browserContainer = document.createXULElement("vbox"); browserContainer.className = "browserContainer"; browserContainer.appendChild(stack); diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..53f90dc480f4a22a5d5f25318583333ba3ab6ac3 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#288548" d="M29.159 16.209l-1.53 3.927-1.53-3.927 1.53-3.927z"/><path fill="#FFF" d="M24.353 17.574s.273.591.91.591 1.001-.455 1.001-.455l.637.819s-.409.273-.409.592c0 0-.273-.273-.182-.501 0 0-.183.183-.318.228 0 0-.046-.273.045-.409 0 0-.318.182-.728.182s-.819-.272-.91-.5c-.091-.228-.046-.547-.046-.547zm2.547-.592c0 .15-.121.272-.273.272H26.4c-.15 0-.273-.122-.273-.272 0-.15.123-.273.273-.273h.227c.152 0 .273.123.273.273zm1.412-.364c0 .151-.122.273-.273.273h-.229c-.15 0-.272-.122-.272-.273 0-.15.122-.273.272-.273h.228c.152.001.274.123.274.273z"/><path fill="#6488BD" d="M27.076 17.188c-.127.08-.296.043-.377-.085l-.097-.153c-.081-.128-.043-.296.084-.377l.039-.024c.127-.081.296-.043.376.085l.098.153c.081.127.043.296-.084.377l-.039.024zm1.547-.182c-.127.081-.296.043-.376-.084l-.098-.154c-.081-.127-.043-.296.084-.376l.039-.024c.127-.081.296-.043.377.084l.097.154c.081.127.043.296-.084.376l-.039.024z"/><path fill="#297F47" d="M27.622 17.098c-.127.08-.296.043-.376-.085l-.098-.153c-.081-.128-.043-.297.084-.377l.039-.024c.127-.081.296-.043.377.085l.097.153c.081.127.043.296-.084.377l-.039.024zm1.337.133c-.15-.005-.269-.131-.264-.282l.006-.182c.005-.15.132-.269.282-.264l.045.002c.151.005.27.131.264.281l-.006.183c-.005.15-.131.269-.281.264l-.046-.002z"/><path fill="#689F9E" d="M27.629 16.709c.591-.027 1.456 1.684 1.502 1.911.045.228-.273.864-.501 1.001-.228.137-1.274.273-1.547.046-.273-.227-.318-.819-.364-1.001-.045-.183-.501-.819-.501-.819l-.5-.091.182-.182.592.045.046-.182h-.273c-.001.001.409-.682 1.364-.728z"/><path fill="#481918" d="M27.447 19.53c.228-.274 1.046-.955 1.319-.818.273.136.228.409-.046.682-.272.273-1.273.136-1.273.136z"/><path fill="#FFF" d="M27.629 19.44h-2.731v2.411c0 1.639.615 2.503 1.115 2.958.501.455 1.615.864 1.615.864s1.114-.409 1.615-.864c.5-.455 1.115-1.319 1.115-2.958V19.44h-2.729z"/><path d="M29.631 24.08c-.364 0-.637.41-1.001.41-.364 0-.637-.364-.955-.364-.318 0-.592.364-.956.364-.363 0-.637-.41-1.001-.41-.079 0-.165.026-.252.065.175.284.369.5.548.663.501.455 1.615.864 1.615.864s1.114-.409 1.615-.864c.186-.169.386-.394.566-.693-.062-.021-.122-.035-.179-.035zm0-1.956c-.364 0-.637.409-1.001.409-.364 0-.637-.364-.955-.364-.318 0-.592.364-.956.364-.363 0-.637-.409-1.001-.409-.251 0-.567.26-.783.376.032.29.085.55.153.783.176-.125.357-.249.585-.249.454 0 .773.409 1.092.409.318 0 .592-.318.91-.318.318 0 .591.318.909.318.318 0 .638-.409 1.093-.409.194 0 .355.091.508.195.065-.232.115-.491.144-.779-.209-.128-.478-.326-.698-.326zm0-1.957c-.364 0-.637.41-1.001.41-.364 0-.637-.364-.955-.364-.318 0-.592.364-.956.364-.363 0-.637-.41-1.001-.41-.265 0-.603.29-.819.395v.894c.241-.147.466-.378.774-.378.454 0 .773.41 1.092.41.318 0 .592-.319.91-.319.318 0 .591.319.909.319.318 0 .638-.41 1.093-.41.268 0 .475.176.683.318v-.884c-.214-.126-.499-.345-.729-.345z" fill="#3AB1D6"/><path fill="#288548" d="M25.13 23.415c.135.409.316.73.508.981l1.991-2.228 1.991 2.228c.191-.251.373-.572.508-.981l-2.499-2.701-2.499 2.701z"/><path fill="#74948F" d="M23.534 23.898c.146-.009.466-.012.591.045.379.174.638.592.638.592s.546.409.592.683c0 0 .409.183.409.364 0 .182-.592.363-.774.318-.183-.046-.683-.182-.865-.091-.182.091-.728.227-.955.182-.228-.046-.5 0-.683 0-.182 0-.409-.182-.683-.272-.273-.092-.91.091-1.001-.183-.091-.272.637-.546.91-.546.274 0 1.048-1.047 1.821-1.092z"/><path fill="#CFDCD9" d="M23.033 24.126s.228.045.273.045c.045 0 .318-.091.409-.045.091.045.046.182.182.228.137.046.183.091.092.228l-.183.272s-.5.091-.683.183c-.182.091-.546.228-.136.272.409.046 1.001.228.909.273-.091.045-.637 0-.818 0-.183 0-.546.091-.638.091-.091 0-.363.046-.227.137.136.091-.183-.046-.364-.091-.182-.046-.592-.183-.318-.274.273-.091.5-.045.637-.045s.318-.183.182-.228c-.136-.046.137-.364.41-.41.272-.045.728-.137.363-.227-.362-.091-.408-.227-.09-.409z"/><path fill="#CFDCD9" d="M23.352 25.036c.183-.046.638.045.592.137-.046.091-.091.182-.228.136-.137-.045-.364-.273-.364-.273z"/><path fill="#3C4544" d="M25.354 25.218c-.046-.274-.592-.683-.592-.683s-.242-.391-.602-.573c-.135.05-.189.163-.036.255.228.137.228.227.137.273-.091.045-.182.136-.227.228-.045.091.137-.046.364 0 .228.045.228.045.409.091.183.045.364.228.274.273-.091.046.091.092.136.227.046.137-.091.092-.273.092-.182 0-.683 0-.729.045-.045.046.865.046.865.137 0 .091-.501 0-.637.045-.137.046-.592.137-.773.092-.183-.046-.547-.092-.638-.046-.091.046-.318.091-.045.137.272.045.727.045 1.001 0 .272-.046.455-.228.728-.137.141.047.148.13.16.199l.113.028c.108.027.359-.026.547-.111.072-.045.142-.094.203-.143.015-.021.024-.043.024-.064.001-.183-.409-.365-.409-.365z"/><path fill="#288548" d="M23.762 23.717s-.091-.41 0-.455c.091-.046.228.137.228.137s0-.501.136-.456c.137.046.183.228.183.228s.137-.363.272-.272c.137.091 0 .364 0 .364s.318.137.228.273c-.091.137-.546.137-.637.183-.091.045-.046.182.045.136.092-.045.547-.228.501-.045-.045.182-.137.228-.318.228-.183 0-.501-.092-.501-.092l-.409.273-.046-.046.318-.456zm-.774-.455c.045.182.091.228.272.228.182 0 .318.091.228.182-.091.091-.318.091-.318.091l.137.364-.046.045-.182-.363-.183.228s-.272-.183-.182-.274c.091-.091.274-.091.182-.182-.091-.091-.227-.364.046-.318.273.045-.182.137-.182.137m-2.502 1.773c.046-.092.318-.183.318-.183s.046-.364.183-.364c.136 0 .272.273.272.273s.046-.182.137-.137c.091.046.318.273.272.364-.045.091-.091.409-.272.455-.182.045-.364-.273-.364-.273s-.091.046-.272.046c-.183 0-.274-.181-.274-.181zm4.14-.729s.137-.409.274-.364c.136.046.136.228.136.228s.409-.045.592.092c.182.136.182.409-.045.5-.229.091-.547-.091-.592-.137-.046-.045-.046.501-.227.501-.183 0-.274-.228-.228-.364.045-.137 0-.273 0-.273s-.364 0-.455.183c0 0 .091-.137.272-.227l.273-.139z"/><path fill="#D1BEA7" d="M24.171 17.893s-.137-.273-.592-.091c-.455.182-.546.5-.591.728-.046.227.091.455-.228.683-.319.228-.546 1.638-.183 1.593.364-.046.455-.091.638.045.182.137.591.183.864-.136 0 0 .272.409.272.637 0 .228-.091.864.183.955 0 0 .409-.546.409-1.092s-.137-1.138-.592-1.41c0 0 .183-.137.319-.319s.226-.136.5-.136h.728s-.182-.41-.409-.501c-.228-.091-.637-.318-1.046 0-.41.318-.683.546-.683.546l-.046-.318s.091-.182.274-.363c.182-.183.182-.455.182-.592l.001-.229z"/><path fill="#937A61" d="M24.944 18.666c.774 0 1.001.728 1.001.728h-.819s-.136-.045-.228-.045c-.091 0-.409.228-.546.5-.137.274-.818-.045-.682-.272.137-.228.455-.911 1.274-.911z"/><path fill="#AF987E" d="M23.352 19.53c.019-.076.156-.09.318-.058.177.034.342.187.501.24.409.136.864.727.864 1.273s-.409 1.183-.455 1.319c-.045.137-.136 0-.182-.137-.046-.136-.046-.454-.046-.727 0-.273-.137-.683-.363-.819-.227-.136-.819-.363-.637-1.091zm-.682 3.732c0 .111.146.504.136.909 0 .031-.044.243-.045.273-.014.395-.142.599-.228.729 0 0-.227-.092-.455-.41-.228-.318-.273-.637-.137-.91.137-.273.729-.591.729-.591z"/><path fill="#D1BEA7" d="M22.396 22.761c.045 0 .16.951.091 1.319-.137.729-.683 1.547-1.047 1.456-.363-.091-.136-.318-.045-.5.091-.183.227-.592.137-.91-.092-.318.864-1.365.864-1.365z"/><path fill="#BA8F69" d="M23.124 20.668c.137.272.455.5.819.091 0 0 .137.683-.137 1.138-.272.455-1.319 1.638-1.319 1.638l-.137-.774.774-2.093z"/><path fill="#BB6C3F" d="M22.441 19.121c.319-.137.774.091.819.363.046.273.091.91.046 1.184-.046.272 0 .728-.091.955-.092.228-.455.455-.501.774-.045.318-.318.591-.727 1.046-.41.455-1.047 1.183-1.229 1.092-.183-.091-.41-1.729.136-3.14.546-1.41 1.547-2.274 1.547-2.274z"/><path fill="#020202" d="M23.625 17.938c.182-.091.318-.045.182.092-.136.135-.365-.001-.182-.092z"/><path fill="#74948F" d="M31.724 23.898c-.146-.009-.466-.012-.591.045-.379.174-.638.592-.638.592s-.546.409-.592.683c0 0-.409.183-.409.364 0 .182.592.363.773.318.183-.046.683-.182.865-.091.182.091.728.227.955.182.228-.046.5 0 .683 0 .182 0 .409-.182.683-.272.273-.092.91.091 1.001-.183.091-.272-.637-.546-.91-.546s-1.047-1.047-1.82-1.092z"/><path fill="#CFDCD9" d="M32.225 24.126s-.228.045-.273.045c-.045 0-.318-.091-.409-.045-.091.045-.046.182-.182.228-.137.046-.183.091-.092.228l.183.272s.5.091.683.183c.182.091.546.228.136.272-.409.046-1.001.228-.909.273.091.045.637 0 .818 0 .183 0 .546.091.638.091.091 0 .363.046.227.137-.136.091.183-.046.364-.091.182-.046.592-.183.318-.274-.273-.091-.5-.045-.637-.045s-.318-.183-.182-.228c.136-.046-.137-.364-.41-.41-.272-.045-.728-.137-.363-.227.362-.091.408-.227.09-.409z"/><path fill="#CFDCD9" d="M31.906 25.036c-.183-.046-.638.045-.592.137.046.091.091.182.227.136.138-.045.365-.273.365-.273z"/><path fill="#3C4544" d="M29.903 25.218c.046-.274.592-.683.592-.683s.242-.391.602-.573c.135.05.189.163.036.255-.227.137-.227.227-.137.273.091.045.182.136.228.228.045.091-.137-.046-.364 0-.228.045-.228.045-.409.091-.183.045-.364.228-.273.273.091.046-.091.092-.136.227-.046.137.091.092.272.092.182 0 .683 0 .729.045.045.046-.865.046-.865.137 0 .091.501 0 .637.045.137.046.592.137.773.092.183-.046.547-.092.638-.046.091.046.318.091.045.137-.272.045-.728.045-1.001 0-.273-.046-.455-.228-.728-.137-.141.047-.148.13-.16.199l-.113.028c-.107.027-.359-.026-.547-.111-.072-.045-.142-.094-.203-.143-.015-.021-.023-.043-.023-.064-.002-.183.407-.365.407-.365z"/><path fill="#288548" d="M31.496 23.717s.091-.41 0-.455c-.091-.046-.227.137-.227.137s0-.501-.136-.456c-.137.046-.183.228-.183.228s-.137-.363-.272-.272c-.137.091 0 .364 0 .364s-.318.137-.228.273c.091.137.546.137.637.183.091.045.046.182-.045.136-.092-.045-.547-.228-.501-.045.045.182.137.228.318.228.183 0 .501-.092.501-.092l.409.273.046-.046-.319-.456zm.774-.455c-.045.182-.091.228-.272.228-.182 0-.318.091-.228.182.091.091.318.091.318.091l-.137.364.046.045.182-.363.183.228s.272-.183.182-.274c-.091-.091-.273-.091-.182-.182.091-.091.227-.364-.046-.318-.272.045.182.137.182.137M35 25.173c-.046-.092-.318-.183-.318-.183s-.046-.364-.183-.364c-.136 0-.272.273-.272.273s-.046-.182-.137-.137c-.091.046-.318.273-.272.364.045.091.091.409.272.455.182.045.364-.273.364-.273s.091.046.272.046c.183 0 .274-.181.274-.181zm-4.141-.729s-.137-.409-.274-.364c-.136.046-.136.228-.136.228s-.409-.045-.592.092c-.182.136-.182.409.045.5.229.091.547-.091.592-.137.046-.045.046.501.228.501.183 0 .273-.228.227-.364-.045-.137 0-.273 0-.273s.364 0 .455.183c0 0-.091-.137-.273-.227l-.272-.139z"/><path fill="#D1BEA7" d="M31.087 17.893s.137-.273.592-.091c.455.182.546.5.591.728.046.227-.091.455.228.683.319.228.546 1.638.183 1.593-.364-.046-.455-.091-.637.045-.183.137-.592.183-.865-.136 0 0-.272.409-.272.637 0 .228.091.864-.183.955 0 0-.409-.546-.409-1.092s.137-1.138.592-1.41c0 0-.183-.137-.319-.319s-.226-.136-.5-.136h-.727s.182-.41.409-.501c.228-.091.637-.318 1.046 0 .41.318.683.546.683.546l.046-.318s-.091-.182-.273-.363c-.182-.183-.182-.455-.182-.592s-.003-.229-.003-.229z"/><path fill="#937A61" d="M30.313 18.666c-.773 0-1.001.728-1.001.728h.819s.136-.045.228-.045c.091 0 .409.228.546.5.137.274.818-.045.682-.272-.136-.228-.454-.911-1.274-.911z"/><path fill="#AF987E" d="M31.906 19.53c-.02-.076-.156-.09-.318-.058-.177.034-.342.187-.501.24-.409.136-.864.727-.864 1.273s.409 1.183.455 1.319c.045.137.136 0 .182-.137.046-.136.046-.454.046-.727 0-.273.137-.683.363-.819.227-.136.819-.363.637-1.091zm.682 3.732c0 .111-.146.504-.136.909.001.031.044.243.045.273.014.395.142.599.228.729 0 0 .227-.092.455-.41.228-.318.273-.637.137-.91-.137-.273-.729-.591-.729-.591z"/><path fill="#D1BEA7" d="M32.861 22.761c-.045 0-.16.951-.091 1.319.137.729.683 1.547 1.047 1.456.363-.091.136-.318.045-.5-.091-.183-.228-.592-.137-.91.092-.318-.864-1.365-.864-1.365z"/><path fill="#BA8F69" d="M32.134 20.668c-.137.272-.455.5-.819.091 0 0-.137.683.137 1.138.272.455 1.319 1.638 1.319 1.638l.137-.774-.774-2.093z"/><path fill="#BB6C3F" d="M32.816 19.121c-.319-.137-.773.091-.819.363-.046.273-.091.91-.046 1.184.046.272 0 .728.092.955.091.228.454.455.5.774.045.318.318.591.728 1.046.41.455 1.047 1.183 1.229 1.092.183-.091.41-1.729-.136-3.14-.547-1.41-1.548-2.274-1.548-2.274z"/><path fill="#020202" d="M31.633 17.938c-.182-.091-.318-.045-.182.092.136.135.364-.001.182-.092z"/><path fill="#FFF" d="M23.216 14.753s.182.455.728.409c.546-.045.955-.182 1.092.318 0 0-.318.046-.455.273-.136.227.228.819.228.819s-.363 0-.5-.228c0 0-.046.409-.318.683-.116.115-.41.136-.41.136l.455-.91c.091-.182.182-.409-.228-.136-.409.272-.955.5-1.273.136 0 0 1.319-.591 1.592-.728-.454 0-.5-.046-.909 0-.244.027-.501.137-.501.137s-.045-.364.455-.364c.318 0-.046-.091-.091-.272-.048-.182.135-.273.135-.273zm6.961 3.73s1.001-.136.865-1.046c-.137-.91-.819-1.547-.683-2.093 0 0-.325.089-.41.363-.182.592.396 1.072.501 1.229.182.273.273.592.273.592s-.5-.409-.774 0c0 0 .318-.046.455.091s.227.318.091.501c-.136.182-.318.363-.318.363zm2.866-3.093s.455.183.455.455c0 .274-.228.364-.591.364 0 0 .182-.137.228-.318.045-.183-.092-.501-.092-.501z"/><path fill="#905F41" d="M26.036 15.071s.683.455.864.501c.183.045.91 0 .91 0l.137-.319s.364-.091.592-.091c.227 0 .501.046.501.046l.091.273-.364.819h-1.229c-.182 0-.592-.137-.683-.318-.091-.183-.455-.409-.546-.546-.091-.137-.591-.501-.273-.365z"/><path fill="#905F41" d="M27.901 15.562c0 .056-.04.101-.091.101-.05 0-.091-.045-.091-.101V13.76c0-.055.041-.1.091-.1.051 0 .091.045.091.1v1.802zm-.818.055c0 .051-.041.091-.091.091-.051 0-.092-.04-.092-.091v-1.638c0-.05.041-.091.092-.091.05 0 .091.041.091.091v1.638zm1.319 0c0 .051-.041.091-.091.091-.05 0-.091-.04-.091-.091v-1.638c0-.05.041-.091.091-.091.05 0 .091.041.091.091v1.638z"/><path fill="#FFF" d="M27.265 14.435c0 .05-.163.091-.364.091-.2 0-.363-.041-.363-.091 0-.051.163-.091.363-.091.201 0 .364.04.364.091zm.182.455c0 .05-.214.091-.479.091-.264 0-.478-.041-.478-.091 0-.051.214-.091.478-.091.265 0 .479.04.479.091zm.683-.615c0 .037-.163.068-.364.068-.201 0-.364-.031-.364-.068 0-.038.163-.068.364-.068.201 0 .364.03.364.068z"/><path fill="#FFF" d="M28.676 14.252c0 .025-.133.046-.296.046-.164 0-.296-.021-.296-.046 0-.024.132-.045.296-.045.163 0 .296.02.296.045zm-.638.455c0 .051-.132.092-.296.092-.163 0-.295-.041-.295-.092 0-.05.132-.091.295-.091.164 0 .296.041.296.091zm.638 0c0 .04-.133.071-.296.071-.164 0-.296-.031-.296-.071 0-.039.132-.07.296-.07.163 0 .296.031.296.07z"/><path fill="#8FD2E2" d="M26.127 16.437s.364-.046.183-.364c0 0 .182-.091.409.137.228.228.638 0 .364-.273 0 0 .227-.137.409.046.183.182.501.228.364-.137 0 0 .318-.091.455.183.137.273.637.227.409-.137 0 0 .228-.046.319.137.091.182.182.227.182.227s.182-.227.363 0c.183.227.092.455-.227.501-.318.045-.456-.318-.456-.318s-.136.182-.363.137c-.228-.046-.364-.228-.364-.228s-.266.136-.409.136c-.228 0-.398-.221-.455-.136-.091.136-.364.273-.637.136 0 0-.227.364-.501.364-.273 0-.546-.164-.546-.409 0-.228.137-.318.272-.273.138.043.229.271.229.271z"/><path fill="#288548" d="M25.49 17.392s-.5.137-.546.41c-.046.272-.091.318-.091.318s-.228-.091-.364-.273c-.137-.182-.182-.592-.137-.728.046-.137.228-.546.41-.773.182-.227.273-.683.228-.865-.046-.182-.273-.363-.273-.363s.592 0 .683.363c.091.364-.091.638-.091.638s.091.045.228-.137c0 0 .045.455-.228.546 0 0-.183.273-.273.501-.091.227-.248.499-.137.409.227-.183.591-.046.591-.046zm-3.003-1.866s-.182.227-.182.364c0 .137.182.455.455.546 0 0-.819-.318-.819-.592 0-.272.365-.318.546-.318zm7.416.273s.092-.682.592-.637c.501.046 1.229.183 1.365.046.137-.137.091-.409.091-.409s.273.045.318.182c.046.137-.136.318-.136.318s.228-.046.363.091c.137.137.273.318.273.318s-.455-.136-.683-.136c-.227 0-.864-.046-.864-.046s.637.364 1.001.501c.363.136.637.273 1.092.136 0 0-.455.273-.592.364-.137.091-.363.091-.637-.046-.272-.136-.727-.454-.727-.454s0 .318.136.637c.137.318.364.546.364.546s-.409-.091-.592-.273c-.182-.182-.182-.591-.182-.591s-.228.318-.546.228c0 0 .137-.092.228-.319s.227-.409.091-.591c-.137-.183-.318-.364-.546-.318-.226.044-.409.453-.409.453zm-1.637.91c-.409.183-.683.455-.637 1.138 0 0 .227-.455.455-.592 0 0 0 .41.137.774.137.363.5.637.773.683 0 0-.318-.501-.318-.91 0 0 .272.682.727 1.092l.046-.318s-.183-.183-.227-.41c0 0 .272.364.637.364s.637-.228.683-.546c0 0-.182.091-.5.137-.319.045-.683-.137-.956-.501-.273-.364-.318-.683-.318-.683l-.502-.228z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..be10594767d724750b76dfad57932d4e4e319a60 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D01C3A" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#0020A8" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FEDF00" d="M12 5h12v26H12z"/><path fill="#C7B37F" d="M23.035 19.641c-.159-.472-.563-.382-.563-.225 0 0-.539-.39-.135-1.104 0 0 .786.093.337-.514 0 0 .674-.382.696-1.168.022-.787-.876-1.281-1.258-.967 0 0-.023-.314-.18-.314s-.247.202-.247.202.023-.517.359-.809c.337-.292 1.033-1.079-.428-1.528-1.46-.449-1.527.473-1.303.675 0 0-.359.201-.764.179-.404-.021-.113-.493-.023-.696.09-.202.023-.921-.473-.898-.494.022-.517.225-.696.292-.177.066-.357.021-.357.021s-.18.045-.36-.023c-.179-.067-.202-.269-.696-.292-.495-.023-.562.696-.472.898.09.203.382.675-.023.696-.404.022-.764-.179-.764-.179.225-.202.157-1.124-1.303-.675-1.46.449-.764 1.236-.427 1.528.337.292.36.809.36.809s-.09-.202-.248-.202c-.157 0-.179.314-.179.314-.382-.314-1.281.18-1.259.967.023.786.697 1.168.697 1.168-.45.606.337.514.337.514.404.715-.135 1.104-.135 1.104 0-.157-.404-.247-.564.225-.159.472.316.629.316.629-.629.81-.225 1.573.382 2.022.607.449 1.775.383 2.359.427.584.045.697.337.697.337-.449.428.225.765.225.765.135.449.674-.045.674-.045l.383.338.382-.337s.54.494.674.045c0 0 .675-.337.225-.765 0 0 .113-.292.697-.337.584-.044 1.753.022 2.359-.427.606-.449 1.011-1.213.382-2.022 0 .001.475-.157.316-.628z"/><path fill="#D01C3A" d="M17.82 17.641v-2.966h-2.966v2.966h2.966z"/><path fill="#FEDF00" d="M15.933 16.506l-.882.91.138.157.744-.82zm1.449-1.157s.391.102.391-.247-.234-.349-.312-.349c-.079 0-.438.057-.45.202-.011.146.141.236.059.315-.081.078-.302.273-.302.273l.131.156s.188-.156.337-.373c.076-.11.018-.378.09-.394.213-.044.292.057.281.136-.011.078-.146.157-.146.157l-.079.124z"/><path fill="#FFF" d="M16.652 16.91s.056.416.258.438c.202.022.27-.646.601-.646.332 0 .365.579 0 .669l-.05-.168s.236-.236.067-.271c-.168-.033-.247.18-.269.271-.023.09-.158.325-.36.325-.337 0-.382-.309-.433-.547-.05-.239.186-.071.186-.071zm-.6 0s-.056.416-.259.438c-.202.022-.27-.646-.601-.646-.332 0-.366.579 0 .669l.05-.168s-.236-.236-.067-.271c.168-.033.247.18.269.271.023.09.157.325.359.325.337 0 .382-.309.433-.547.052-.239-.184-.071-.184-.071z"/><path fill="#FFF" d="M16.394 14.798l.865 1.101-.433 1.18s-.174-.102-.433-.102-.461.102-.461.102l-.46-1.191.922-1.09z"/><path fill="#FEDF00" d="M16.466 15.18l.604.725-.306.927-.292-.09zm-.199 0l-.604.725.306.927.292-.09zm-1.413 2.73v1.843c0 1.214.886 1.381 1.648 1.214.614-.136 1.318 0 1.318 0V17.91h-2.966z"/><path d="M16.502 20.967l.06-.012V17.91h-.45v3.108c.131-.005.262-.024.39-.051zm.959-.046V17.91h-.45v2.998c.165-.005.32.002.45.013zm-1.798.058V17.91h-.449v2.841c.127.115.282.189.449.228z" fill="#D01C3A"/><path fill="#FEDF00" d="M18.18 17.641v-2.966h2.966v2.966H18.18z"/><path fill="#D01C3A" d="M18.539 14.675h.45v2.966h-.45zm.899 0h.45v2.966h-.45zm.899 0h.449v2.966h-.449z"/><path fill="#FEDF00" d="M21.146 17.91v1.843c0 1.214-.886 1.381-1.648 1.214-.614-.136-1.318 0-1.318 0V17.91h2.966z"/><path fill="#D01C3A" d="M18.629 18.404l.281-.225h.348v.181s.495-.008.899-.049c.404-.042.528.262.404.34-.123.079.022.383 0 .528-.022.146-.292.359-.225.236.067-.124 0-.461 0-.461s-.078.259-.146.337c-.068.079-.304.09-.214.023s.18-.213.101-.292c-.078-.078-.431-.09-.446-.056-.014.033-.081.426-.126.449-.046.022-.102-.034-.068-.157.034-.124 0-.337 0-.337s-.235-.012-.225.09c.012.101.113.146.091.225-.023.078-.169.18-.18.045-.012-.135-.236-.225-.135-.292.101-.067.203-.173.203-.173s-.127-.029-.216-.153c-.09-.123-.166-.112-.346-.112-.09 0 0-.147 0-.147zm0 1.349l.281-.225h.348v.18s.495-.007.899-.049c.404-.041.528.262.404.341-.123.079.022.382 0 .528-.022.146-.292.358-.225.236.067-.124 0-.461 0-.461s-.078.258-.146.337c-.068.079-.304.09-.214.022.09-.067.18-.214.101-.292-.078-.078-.431-.09-.446-.057-.014.034-.081.427-.126.45-.046.021-.102-.034-.068-.158.034-.123 0-.337 0-.337s-.235-.011-.225.09c.012.101.113.146.091.225-.023.079-.169.181-.18.045-.012-.134-.236-.225-.135-.292.101-.067.203-.173.203-.173s-.127-.029-.216-.152c-.09-.124-.166-.112-.346-.112-.09 0 0-.146 0-.146z"/><path fill="#AF9167" d="M14.629 21.191c0 .033 1.652.482 1.837.517.186.033.118.415-.129.393-.247-.021-1.472-.291-1.629-.37-.157-.08-.079-.54-.079-.54zm2.27.556s.495.067.921.085c.427.017.719-.02.719-.02l.304.412s-.528.057-.888.057c-.359 0-.944-.057-.944-.057l-.112-.477zm2.157 0s.708-.129 1.136-.231c.427-.101.988-.303 1.135-.325.146-.023.247.241.291.277l.045.037s-.741.348-1.101.449c-.359.102-1.506.259-1.506.259s-.164-.436 0-.466z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..be8e114a9fb5c7c0985f1f01d0c610ae95e70b5e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#068241" d="M32 5H9v9h27V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M9 14h27v8H9z"/><path fill="#141414" d="M9 31h23c2.209 0 4-1.791 4-4v-5H9v9z"/><path fill="#EC2028" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h5V5H4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..769efcadf37608991e9aecc0464b6fdd47accd3c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M36 26.999c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-18c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#007A36" d="M32 4.999c2.209 0 4 1.791 4 4v18c0 2.209-1.791 4-4 4h-8v-26h8z"/><path fill="#D32011" d="M12 4.999h12v26H12z"/><path fill="#FFF" d="M22.048 23.783c-.032.08-.141.151-.227.117-.086-.034-.116-.161-.084-.241.032-.08.277-.319.303-.309.026.01.04.353.008.433zm.061.075c-.085.014-.179.104-.164.196.015.091.131.149.217.135.085-.014.372-.201.368-.228-.005-.027-.336-.116-.421-.103zm.352-.401c-.03.074-.131.14-.21.109s-.108-.149-.078-.224.257-.296.281-.287.036.328.007.402zm.056.07c-.079.013-.166.097-.152.182.014.085.122.138.201.125s.345-.186.341-.212-.311-.107-.39-.095zm-1.831.538c-.019.102-.13.212-.24.192-.109-.02-.175-.162-.157-.264.019-.102.251-.442.284-.436s.131.406.113.508zm.089.074c-.097.036-.186.166-.147.27.039.104.19.144.288.108.097-.036.391-.325.379-.357-.012-.031-.423-.057-.52-.021zm.265-.483c-.015.085-.108.176-.199.16s-.146-.135-.13-.22c.015-.085.209-.368.236-.363s.109.338.093.423zm.074.062c-.081.03-.154.138-.122.224s.158.12.239.09.325-.271.315-.297c-.009-.025-.351-.047-.432-.017zm.266-.462c-.014.079-.1.163-.185.148-.084-.015-.135-.125-.121-.204.014-.079.194-.341.219-.337.025.005.101.314.087.393zm.069.057c-.075.028-.143.128-.113.208.03.08.147.111.222.083s.301-.251.293-.275-.327-.044-.402-.016zm.225-.402c-.013.071-.091.148-.167.134-.076-.014-.122-.113-.109-.184.013-.071.175-.309.198-.304.022.003.091.283.078.354zm.062.052c-.068.025-.13.115-.102.188.027.073.133.1.201.075.068-.025.273-.227.265-.249s-.296-.039-.364-.014zm-.097 1.755c-.076.07-.231.091-.307.009-.076-.082-.043-.235.033-.305s.467-.202.489-.178-.139.404-.215.474zm.026.113c-.1-.029-.248.021-.279.127-.032.107.066.229.165.259.1.029.508-.025.517-.057.01-.031-.303-.299-.403-.329zm.503-.226c-.063.059-.192.076-.255.008s-.036-.195.028-.254c.063-.059.388-.168.407-.148.018.02-.117.335-.18.394zm.022.094c-.083-.025-.206.017-.232.106-.026.089.054.191.137.215.083.025.422-.021.43-.047.008-.027-.253-.25-.335-.274zm.49-.21c-.059.054-.178.07-.237.007-.058-.063-.033-.181.026-.235s.36-.156.377-.137c.018.018-.107.31-.166.365zm.021.087c-.077-.023-.191.016-.216.098-.024.082.051.177.127.2.077.023.392-.019.399-.044s-.234-.231-.31-.254zm.421-.186c-.053.049-.161.064-.214.007-.053-.057-.03-.164.023-.213.053-.049.326-.141.341-.124.016.017-.097.281-.15.33zm.019.079c-.069-.021-.173.014-.195.089-.022.074.046.16.115.181.069.021.354-.017.361-.04.006-.022-.212-.209-.281-.23zm.343-2.771c.013.103-.061.241-.172.254-.11.013-.215-.103-.228-.206s.109-.497.142-.501c.033-.004.245.35.258.453zm.107.044c-.082.063-.128.213-.06.301s.224.081.307.018c.082-.063.277-.427.257-.453-.022-.026-.422.071-.504.134zm.11-.54c.01.086-.051.2-.143.212-.092.011-.179-.085-.19-.171-.01-.086.091-.413.118-.417.028-.003.205.29.215.376zm.089.037c-.068.053-.107.177-.05.25.057.073.187.067.255.015.068-.053.23-.355.213-.377-.016-.021-.349.06-.418.112zm.117-.52c.01.079-.047.186-.133.196s-.166-.079-.176-.159c-.01-.079.084-.383.109-.386.026-.003.19.269.2.349zm.083.034c-.063.049-.099.164-.046.232s.173.063.236.014.214-.329.198-.349-.325.054-.388.103zm.095-.45c.009.072-.043.168-.12.178-.077.009-.15-.072-.159-.144-.009-.072.076-.347.099-.349.023-.004.172.243.18.315zm.075.031c-.057.044-.089.149-.042.21s.157.057.214.012c.057-.044.193-.298.179-.316-.014-.018-.293.049-.351.094zm.428 1.705c-.052.09-.194.156-.29.1-.096-.056-.11-.212-.059-.301.052-.09.386-.332.414-.315s-.013.426-.065.516zm.058.1c-.104.001-.231.093-.229.204s.131.2.234.198c.104-.001.478-.174.477-.208.001-.032-.378-.195-.482-.194zm.413-.365c-.043.075-.161.129-.241.083s-.092-.176-.049-.251.321-.276.345-.262-.011.355-.055.43zm.049.083c-.086.001-.192.078-.191.17s.109.166.195.165.397-.145.397-.173c0-.027-.315-.163-.401-.162zm.406-.346c-.04.069-.15.12-.224.077-.074-.043-.085-.163-.045-.232s.297-.256.32-.243-.011.329-.051.398zm.046.077c-.08.001-.178.072-.177.158s.101.154.181.153c.08-.001.368-.135.368-.16s-.292-.152-.372-.151zm.347-.302c-.036.063-.135.109-.203.07-.067-.039-.077-.148-.041-.21s.269-.231.289-.22c.021.011-.009.297-.045.36zm.041.07c-.072.001-.161.065-.16.143.001.078.091.139.164.138s.333-.122.333-.145c0-.023-.264-.137-.337-.136zm-1.051-.555c-.002.104-.096.23-.207.227-.111-.003-.198-.133-.196-.236s.179-.476.212-.475c.034 0 .194.38.191.484zm.1.06c-.09.051-.158.192-.103.289s.21.113.301.062.335-.382.319-.411-.427.009-.517.06zm.187-.519c-.002.086-.079.191-.172.189s-.165-.11-.163-.197c.002-.086.149-.396.177-.395.027.001.16.317.158.403zm.082.05c-.075.042-.131.16-.086.241.045.081.175.094.25.051.075-.042.279-.318.265-.342-.012-.025-.353.007-.429.05zm.191-.499c-.002.08-.074.177-.159.175-.086-.002-.153-.102-.151-.182.002-.08.138-.367.164-.367.025.001.148.294.146.374zm.077.046c-.07.039-.122.148-.079.223s.162.087.232.047.259-.295.246-.317c-.013-.022-.33.008-.399.047zm-.845-1.708c.041.096.007.249-.095.292s-.235-.039-.276-.135-.033-.508-.002-.521c.031-.012.333.269.373.364zm.115.014c-.061.084-.064.24.025.306.09.066.238.016.299-.068s.148-.486.122-.506-.384.184-.446.268zm-.043-.55c.034.079.006.207-.079.243-.085.036-.196-.033-.229-.112s-.027-.422-.002-.433c.026-.011.277.223.31.302zm.096.011c-.051.07-.054.2.021.255.075.055.198.013.249-.056.051-.07.123-.405.101-.421s-.32.153-.371.222zm-.031-.532c.031.074.006.192-.073.225s-.182-.03-.213-.104-.025-.391-.001-.401c.023-.01.256.206.287.28zm.089.01c-.047.065-.05.185.019.236.069.051.184.012.231-.052.047-.065.114-.375.094-.39-.021-.016-.297.142-.344.206zm-.033-.46c.028.067.005.173-.066.204-.071.03-.164-.027-.193-.094-.028-.067-.023-.354-.001-.363.022-.009.232.187.26.253zm.081.01c-.043.058-.045.168.018.214s.166.011.209-.047.104-.339.085-.353c-.019-.015-.269.127-.312.186zm.881 1.521c-.025.101-.144.203-.251.176s-.165-.173-.139-.274c.025-.101.279-.425.311-.417.032.008.104.414.079.515zm.084.08c-.099.03-.196.153-.164.26.032.107.181.156.28.126.099-.03.411-.3.401-.331-.008-.033-.417-.085-.517-.055zm.297-.465c-.021.084-.119.169-.209.147s-.137-.144-.116-.228c.021-.084.232-.354.259-.347.026.007.086.344.066.428zm.069.066c-.083.025-.163.127-.136.216.027.089.15.13.233.105s.342-.249.334-.276c-.008-.026-.348-.069-.431-.045zm.295-.444c-.019.078-.111.157-.194.136-.083-.021-.127-.133-.108-.211.019-.078.215-.328.24-.322s.082.319.062.397zm.065.062c-.077.023-.151.118-.126.2.025.082.139.12.216.097.077-.023.317-.231.31-.256-.008-.024-.323-.065-.4-.041zm.251-.387c-.018.07-.1.142-.175.123-.075-.019-.115-.121-.097-.191.018-.07.195-.297.217-.291.022.005.072.289.055.359zm.059.056c-.069.021-.137.107-.114.181.022.074.126.109.195.088s.287-.209.28-.231c-.007-.023-.292-.059-.361-.038zM25.8 16.98c.026.1-.028.247-.136.275-.108.028-.227-.073-.254-.173-.026-.1.041-.507.073-.515s.291.312.317.413zm.112.029c-.073.074-.098.228-.019.306.079.078.233.05.306-.024.073-.074.217-.46.193-.483-.023-.023-.407.128-.48.201zm.037-.55c.022.084-.024.205-.113.229-.089.023-.189-.06-.211-.144-.022-.084.034-.422.061-.429.026-.006.241.261.263.344zm.093.025c-.061.062-.082.19-.016.255s.194.042.255-.02.18-.383.161-.402-.339.106-.4.167zm.046-.531c.02.077-.022.191-.105.212-.083.022-.175-.056-.196-.134-.02-.077.032-.391.056-.398.025-.006.224.242.245.32zm.086.023c-.056.057-.076.176-.015.236s.18.039.236-.018c.056-.057.167-.355.149-.373-.018-.018-.314.098-.37.155zm-1.336-1.141c.09.035.169.157.131.253s-.179.13-.268.095c-.09-.035-.357-.308-.345-.337.011-.029.392-.046.482-.011zm.084-.068c.015.095.117.199.219.182.102-.017.165-.147.15-.242-.015-.095-.225-.414-.256-.409-.031.005-.129.374-.113.469zm-.392-.328c.074.029.141.13.109.21-.031.08-.149.108-.223.079-.074-.029-.297-.256-.287-.28.009-.024.327-.039.401-.009zm.07-.056c.013.079.097.165.182.151.085-.014.137-.122.125-.201s-.187-.344-.213-.34c-.026.004-.107.311-.094.39zm-.373-.326c.069.027.131.121.101.195s-.138.1-.207.073-.275-.238-.266-.26c.009-.022.303-.035.372-.008zm.065-.052c.012.073.09.153.169.14.079-.013.127-.113.116-.187-.012-.073-.174-.319-.197-.316-.025.005-.1.29-.088.363zm-.325-.277c.062.025.118.109.092.176-.026.067-.125.091-.187.066s-.249-.215-.241-.235.273-.032.336-.007zm.058-.047c.011.066.082.139.153.127.071-.012.115-.103.105-.169-.011-.066-.157-.289-.178-.286-.022.004-.09.262-.08.328zm1.579.405c.05.082.041.227-.047.281-.088.054-.221-.004-.271-.086-.05-.082-.1-.461-.073-.477s.34.2.391.282zm.107-.003c-.045.085-.026.229.065.277.091.048.22-.018.265-.103s.069-.466.042-.481c-.027-.015-.327.221-.372.307zm-.115-.498c.042.068.034.189-.039.234s-.184-.003-.226-.071c-.042-.068-.083-.383-.061-.397.022-.014.284.165.326.234zm.09-.003c-.037.071-.022.191.054.23.076.04.183-.015.221-.086.037-.071.057-.388.035-.4-.023-.012-.273.185-.31.256zm-.103-.484c.039.063.032.175-.036.217-.068.042-.171-.003-.209-.066-.039-.063-.077-.355-.057-.368s.263.153.302.217zm.083-.003c-.035.066-.02.177.05.214.07.037.17-.014.205-.08.035-.066.053-.36.032-.371s-.252.171-.287.237zm-.093-.417c.035.057.029.158-.033.196-.061.038-.154-.002-.189-.06-.035-.057-.07-.322-.051-.333.018-.011.238.14.273.197zm.075-.002c-.031.059-.018.16.046.193s.154-.013.185-.072.048-.325.029-.335-.228.154-.26.214zm-.916.611c.084.048.145.179.094.269-.051.089-.196.103-.279.055-.084-.048-.309-.356-.293-.383.014-.027.394.011.478.059zm.092-.055c.002.096.087.213.19.212.103-.002.185-.122.183-.218-.002-.096-.163-.442-.194-.442-.03.001-.18.352-.179.448zm-.34-.381c.069.04.121.149.078.224-.042.074-.162.085-.232.045-.069-.04-.257-.296-.244-.319.013-.022.329.01.398.05zm.077-.046c.001.08.072.178.158.176.086-.001.154-.101.152-.181-.001-.08-.136-.368-.161-.367-.025 0-.15.292-.149.372zm-.322-.375c.064.037.112.138.072.207-.04.069-.151.08-.215.043-.064-.037-.238-.275-.226-.296.012-.021.305.009.369.046zm.072-.043c.001.074.067.165.147.163.08-.001.142-.094.141-.168s-.126-.341-.15-.341-.139.272-.138.346z"/><path fill="#FFF" d="M25.46 23.116s-.716-.008-1.328-.421c-.612-.413-1.865-1.173-2.868-.188 0 0 .7-.118 1.226.319.526.438 1.341.951 2.027.894.686-.056.943-.604.943-.604z"/><path fill="#FF5B57" d="M13.013 12.188l-.884-.884c1.581-1.581 3.682-2.451 5.917-2.451s4.336.871 5.917 2.451l-.885.884c-1.344-1.344-3.131-2.085-5.032-2.085s-3.689.741-5.033 2.085z"/><path fill="#FFF" d="M14.579 21.801l-.008-.632h6.789l.027.646z"/><g fill="#FFF"><path d="M21.387 15.549l-.57-.071v-1.335c0-.03-.01-.057-.017-.085h.027c.087 0 .159-.071.159-.159 0-.087-.071-.159-.159-.159h-.707c-.087 0-.159.071-.159.159 0 .087.071.159.159.159h.027c-.007.028-.017.055-.017.085v1.25l-.261-.032-.518-.557c.103-.155.167-.328.167-.515 0-.62-.641-1.122-1.433-1.122s-1.433.502-1.433 1.122c0 .185.063.358.164.512l-.521.561-.262.032v-1.25c0-.03-.01-.057-.017-.085h.027c.087 0 .159-.071.159-.159 0-.087-.071-.159-.159-.159h-.706c-.087 0-.159.071-.159.159 0 .087.071.159.159.159h.027c-.007.028-.017.055-.017.085v1.335l-.569.07.472.707h.074v.978h.731v-.978h4.053v.978h.731v-.978h.076l.472-.707z"/><path d="M20.473 13.624c.27 0 .488-.116.488-.259 0-.078-.069-.146-.173-.194l-.316-.453-.315.453c-.104.047-.173.115-.173.194.001.143.22.259.489.259zm-2.447-.593c.28 0 .507-.14.507-.312 0-.092-.067-.172-.169-.229l-.338-.486-.338.486c-.102.057-.169.138-.169.229 0 .172.227.312.507.312zm-2.337.593c.27 0 .488-.116.488-.259 0-.078-.069-.146-.173-.194l-.315-.453-.315.453c-.104.047-.173.115-.173.194 0 .143.218.259.488.259z"/></g><g fill="#FFF"><path d="M21.32 20.864l-.481-.52v-.911h-.731v.874h-.294l-1.884-2.61-1.438-.077-.073 2.225 1.889.019.888.443v.557z"/><path d="M16.054 19.433h-.73v.954l-.442.477h2.123v-.557h-.951zm-1.971-3.595l-.224.196s-.969.706-.647 1.388c-.18.251-.588.753-.275 1.263.314.51.612.965.416 1.443.588-.306.855-.871.674-1.506-.151-.533.597-.941.844-1.06l.452.682v.628h.731v-1.078h-.633l-1.338-1.956zm8.867 1.585c.322-.682-.647-1.388-.647-1.388l-.224-.196-1.338 1.956h-.633v1.078h.731v-.628l.452-.682c.246.118.995.526.844 1.06-.18.635.086 1.2.674 1.506-.196-.478.102-.933.416-1.443.313-.51-.095-1.012-.275-1.263z"/></g><path fill="#FFF" d="M21.672 26.085c0 .192-.156.348-.348.348-.192 0-1.289-.156-1.289-.348 0-.192 1.097-.348 1.289-.348.193 0 .348.156.348.348z"/><path fill="#FFF" d="M22.922 26.111c.98-.183 1.019-.713 1.019-.713s-.533.339-1.16.214-1.193-.105-1.193-.105.597.662.095.991c-.222.146-.837.084-1.105.025-.268-.059-.845-.166-.971-.166-.192 0-.348.156-.348.348 0 .192.156.348.348.348.128 0 .698-.106.995-.174s.505-.1.728-.146c.267-.055.824.016 1.522.071.698.055 1.208-.267 1.443-.549-.495.157-1.146-.031-1.373-.144zm4.706-7.901c.039-.095-.856.573-1.467.498-.611-.075-1.785-.242-2.025.214-.241.455-.456.927-.456.927s.407-.237.934-.24c.529-.003 1.64-.054 2.077-.2.439-.147.781-.824.937-1.199zm-.845-2.954c-.011-.199-.407-.115-.489-.28-.081-.165.222-.516.054-.635-.167-.119-1.019.644-1.493 1.155-.474.512-.606 1.329-.453 1.57.151.241.054.021.054.021s.3-.595.781-.838c.481-.242 1.546-.993 1.546-.993zm-12.902 8.527c.032.08.141.151.227.117.086-.034.116-.161.084-.241-.032-.08-.277-.319-.303-.309s-.04.353-.008.433zm-.06.075c.085.014.179.104.164.196-.015.091-.131.149-.217.135s-.372-.201-.368-.228c.005-.027.336-.116.421-.103zm-.352-.401c.03.074.131.14.21.109s.108-.149.078-.224-.257-.296-.281-.287-.037.328-.007.402zm-.056.07c.079.013.166.097.152.182-.014.085-.122.138-.201.125-.079-.013-.345-.186-.341-.212s.311-.107.39-.095zm1.831.538c.019.102.13.212.24.192.109-.02.175-.162.157-.264-.019-.102-.251-.442-.284-.436s-.132.406-.113.508zm-.089.074c.097.036.186.166.147.27-.039.104-.19.144-.288.108-.097-.036-.391-.325-.379-.357.011-.031.423-.057.52-.021zm-.266-.483c.015.085.108.176.199.16.091-.017.146-.135.13-.22-.015-.085-.209-.368-.236-.363s-.108.338-.093.423zm-.074.062c.081.03.154.138.122.224s-.158.12-.239.09-.325-.271-.315-.297c.009-.025.351-.047.432-.017zm-.266-.462c.014.079.1.163.185.148.084-.015.135-.125.121-.204s-.194-.341-.219-.337c-.025.005-.101.314-.087.393zm-.068.057c.075.028.143.128.113.208s-.147.111-.222.083-.301-.251-.293-.275c.01-.024.327-.044.402-.016zm-.225-.402c.013.071.091.148.167.134.076-.014.122-.113.109-.184s-.175-.309-.198-.304c-.023.003-.091.283-.078.354zm-.063.052c.068.025.13.115.102.188-.027.073-.133.1-.201.075-.068-.025-.273-.227-.265-.249.01-.021.297-.039.364-.014zm.098 1.755c.076.07.231.091.307.009.076-.082.043-.235-.033-.305s-.467-.202-.489-.178c-.024.025.138.404.215.474zm-.027.113c.1-.029.248.021.279.127.032.107-.066.229-.165.259-.1.029-.508-.025-.517-.057s.304-.299.403-.329zm-.502-.226c.063.059.192.076.255.008s.036-.195-.028-.254c-.063-.059-.388-.168-.407-.148-.019.02.116.335.18.394zm-.022.094c.083-.025.206.017.232.106s-.054.191-.137.215c-.083.025-.422-.021-.43-.047-.008-.027.252-.25.335-.274zm-.491-.21c.059.054.178.07.237.007.058-.063.033-.181-.026-.235s-.36-.156-.377-.137c-.018.018.107.31.166.365zm-.02.087c.077-.023.191.016.216.098.024.082-.051.177-.127.2-.077.023-.392-.019-.399-.044s.233-.231.31-.254zm-.422-.186c.053.049.161.064.214.007.053-.057.03-.164-.023-.213-.053-.049-.326-.141-.341-.124-.016.017.097.281.15.33zm-.018.079c.069-.021.173.014.195.089.022.074-.046.16-.115.181s-.354-.017-.361-.04c-.007-.022.211-.209.281-.23zm-.343-2.771c-.013.103.061.241.172.254.11.013.215-.103.228-.206s-.109-.497-.142-.501c-.033-.004-.246.35-.258.453zm-.107.044c.082.063.128.213.06.301s-.224.081-.307.018c-.082-.063-.277-.427-.257-.453.021-.026.421.071.504.134zm-.111-.54c-.01.086.051.2.143.212.092.011.179-.085.19-.171.01-.086-.091-.413-.118-.417-.028-.003-.204.29-.215.376zm-.089.037c.068.053.107.177.05.25-.057.073-.187.067-.255.015-.068-.053-.23-.355-.213-.377.017-.021.35.06.418.112zm-.117-.52c-.01.079.047.186.133.196s.166-.079.176-.159c.01-.079-.084-.383-.109-.386s-.19.269-.2.349zm-.082.034c.063.049.099.164.046.232-.052.068-.173.063-.236.014s-.214-.329-.198-.349.324.054.388.103zm-.096-.45c-.009.072.043.168.12.178.077.009.15-.072.159-.144.009-.072-.076-.347-.099-.349-.023-.004-.171.243-.18.315zm-.075.031c.057.044.089.149.042.21-.047.061-.157.057-.214.012-.057-.044-.193-.298-.179-.316.014-.018.294.049.351.094zm-.427 1.705c.052.09.194.156.29.1.096-.056.11-.212.059-.301s-.386-.332-.414-.315.013.426.065.516zm-.059.1c.104.001.231.093.229.204s-.131.2-.234.198c-.104-.001-.478-.174-.477-.208 0-.032.378-.195.482-.194zm-.413-.365c.043.075.161.129.241.083s.092-.176.049-.251c-.043-.075-.321-.276-.345-.262-.023.014.012.355.055.43zm-.049.083c.086.001.192.078.191.17-.001.093-.109.166-.195.165-.086-.001-.397-.145-.397-.173 0-.027.315-.163.401-.162zm-.406-.346c.04.069.15.12.224.077.074-.043.085-.163.045-.232-.04-.069-.297-.256-.32-.243s.011.329.051.398zm-.045.077c.08.001.178.072.177.158-.001.086-.101.154-.181.153-.08-.001-.368-.135-.368-.16s.292-.152.372-.151zm-.348-.302c.036.063.135.109.203.07.067-.039.077-.148.041-.21s-.269-.231-.289-.22c-.021.011.009.297.045.36zm-.041.07c.072.001.161.065.16.143-.001.078-.091.139-.164.138s-.333-.122-.333-.145c.001-.023.265-.137.337-.136zm1.051-.555c.002.104.096.23.207.227s.198-.133.196-.236-.179-.476-.212-.475c-.034 0-.193.38-.191.484zm-.099.06c.09.051.158.192.103.289s-.21.113-.301.062c-.09-.051-.335-.382-.319-.411.016-.03.426.009.517.06zm-.187-.519c.002.086.079.191.172.189s.165-.11.163-.197c-.002-.086-.149-.396-.177-.395-.028.001-.16.317-.158.403zm-.083.05c.075.042.131.16.086.241-.045.081-.175.094-.25.051s-.279-.318-.265-.342c.013-.025.354.007.429.05zm-.19-.499c.002.08.074.177.159.175.086-.002.153-.102.151-.182s-.138-.367-.164-.367c-.025.001-.148.294-.146.374zm-.077.046c.07.039.122.148.079.223s-.162.087-.232.047c-.07-.039-.259-.295-.246-.317.013-.022.329.008.399.047zm.844-1.708c-.041.096-.007.249.095.292s.235-.039.276-.135c.041-.096.033-.508.002-.521-.031-.012-.332.269-.373.364zm-.115.014c.061.084.064.24-.025.306-.09.066-.238.016-.3-.068-.061-.084-.148-.486-.122-.506s.386.184.447.268zm.043-.55c-.034.079-.006.207.079.243.085.036.196-.033.229-.112s.027-.422.002-.433c-.025-.011-.276.223-.31.302zm-.096.011c.051.07.054.2-.021.255-.075.055-.198.013-.249-.056-.051-.07-.123-.405-.101-.421.022-.017.32.153.371.222zm.032-.532c-.031.074-.006.192.073.225s.182-.03.213-.104.025-.391.001-.401c-.023-.01-.256.206-.287.28zm-.089.01c.047.065.05.185-.019.236-.069.051-.184.012-.231-.052-.047-.065-.114-.375-.094-.39.02-.016.296.142.344.206zm.032-.46c-.028.067-.005.173.066.204.071.03.164-.027.193-.094.028-.067.023-.354.001-.363-.021-.009-.232.187-.26.253zm-.081.01c.043.058.045.168-.018.214-.063.046-.166.011-.209-.047s-.104-.339-.085-.353c.02-.015.27.127.312.186zm-.881 1.521c.025.101.144.203.251.176.108-.027.165-.173.139-.274-.025-.101-.279-.425-.311-.417s-.104.414-.079.515zm-.084.08c.099.03.196.153.164.26-.032.107-.181.156-.28.126s-.411-.3-.401-.331c.009-.033.418-.085.517-.055zm-.296-.465c.021.084.119.169.209.147.09-.022.137-.144.116-.228-.021-.084-.232-.354-.259-.347-.027.007-.087.344-.066.428zm-.07.066c.083.025.163.127.136.216-.027.089-.15.13-.233.105s-.342-.249-.334-.276c.008-.026.348-.069.431-.045zm-.295-.444c.019.078.111.157.194.136.083-.021.127-.133.108-.211-.019-.078-.215-.328-.24-.322s-.081.319-.062.397zm-.065.062c.077.023.151.118.126.2-.025.082-.139.12-.216.097-.077-.023-.317-.231-.31-.256.008-.024.323-.065.4-.041zm-.25-.387c.018.07.1.142.175.123.075-.019.115-.121.097-.191-.018-.07-.195-.297-.217-.291-.023.005-.073.289-.055.359zm-.059.056c.069.021.137.107.114.181-.022.074-.126.109-.195.088-.069-.021-.287-.209-.28-.231.006-.023.291-.059.361-.038zm1.163-.243c-.026.1.028.247.136.275s.227-.073.254-.173c.026-.1-.041-.507-.073-.515-.032-.009-.29.312-.317.413zm-.112.029c.073.074.098.228.019.306s-.233.05-.306-.024-.217-.46-.193-.483c.024-.023.407.128.48.201zm-.036-.55c-.022.084.024.205.113.229.089.023.189-.06.211-.144.022-.084-.034-.422-.061-.429s-.242.261-.263.344zm-.094.025c.061.062.082.19.016.255s-.194.042-.255-.02-.18-.383-.161-.402.34.106.4.167zm-.045-.531c-.02.077.022.191.105.212.083.022.175-.056.196-.134.02-.077-.032-.391-.056-.398-.026-.006-.225.242-.245.32zm-.087.023c.056.057.076.176.015.236s-.18.039-.236-.018c-.056-.057-.167-.355-.149-.373.018-.018.314.098.37.155zm1.337-1.141c-.09.035-.169.157-.131.253s.179.13.268.095.357-.308.345-.337c-.011-.029-.393-.046-.482-.011zm-.084-.068c-.015.095-.117.199-.219.182-.102-.017-.165-.147-.15-.242.015-.095.225-.414.256-.409.03.005.128.374.113.469zm.391-.328c-.074.029-.141.13-.109.21.031.08.149.108.223.079.074-.029.297-.256.287-.28-.009-.024-.326-.039-.401-.009zm-.069-.056c-.013.079-.097.165-.182.151-.085-.014-.137-.122-.125-.201.013-.079.187-.344.213-.34.025.004.106.311.094.39zm.372-.326c-.069.027-.131.121-.101.195s.138.1.207.073c.069-.027.275-.238.266-.26-.008-.022-.303-.035-.372-.008zm-.064-.052c-.012.073-.09.153-.169.14-.079-.013-.127-.113-.116-.187.012-.073.174-.319.197-.316.024.005.1.29.088.363zm.325-.277c-.062.025-.118.109-.092.176.026.067.125.091.187.066s.249-.215.241-.235-.274-.032-.336-.007zm-.059-.047c-.011.066-.082.139-.153.127-.071-.012-.115-.103-.105-.169s.157-.289.178-.286c.023.004.091.262.08.328zm-1.578.405c-.05.082-.041.227.047.281.088.054.221-.004.271-.086.05-.082.1-.461.073-.477-.026-.016-.341.2-.391.282zm-.108-.003c.045.085.026.229-.065.277-.091.048-.22-.018-.265-.103s-.069-.466-.042-.481c.027-.015.327.221.372.307zm.115-.498c-.042.068-.034.189.039.234.073.045.184-.003.226-.071.042-.068.083-.383.061-.397-.022-.014-.284.165-.326.234zm-.089-.003c.037.071.022.191-.054.23-.076.04-.183-.015-.221-.086-.037-.071-.057-.388-.035-.4.023-.012.273.185.31.256zm.102-.484c-.039.063-.032.175.036.217.068.042.171-.003.209-.066.039-.063.077-.355.057-.368-.02-.013-.263.153-.302.217zm-.083-.003c.035.066.02.177-.05.214-.07.037-.17-.014-.205-.08-.035-.066-.053-.36-.032-.371.021-.011.253.171.287.237zm.093-.417c-.035.057-.029.158.033.196s.154-.002.189-.06.07-.322.051-.333c-.018-.011-.238.14-.273.197zm-.075-.002c.031.059.018.16-.046.193s-.154-.013-.185-.072-.048-.325-.029-.335c.019-.011.229.154.26.214zm.917.611c-.084.048-.145.179-.094.269.051.089.196.103.279.055.084-.048.309-.356.293-.383-.015-.027-.395.011-.478.059zm-.093-.055c-.002.096-.087.213-.19.212-.103-.002-.185-.122-.183-.218.002-.096.163-.442.194-.442.031.001.181.352.179.448zm.34-.381c-.069.04-.121.149-.078.224.043.074.163.086.232.046s.257-.296.244-.319c-.012-.023-.329.009-.398.049zm-.077-.046c-.001.08-.072.178-.158.176-.086-.001-.154-.101-.152-.181.001-.08.136-.368.161-.367.025 0 .15.292.149.372zm.322-.375c-.064.037-.112.138-.072.207.04.069.151.08.215.043.064-.037.238-.275.226-.296-.011-.021-.305.009-.369.046zm-.071-.043c-.001.074-.067.165-.147.163-.08-.001-.142-.094-.141-.168.001-.074.126-.341.15-.341s.139.272.138.346z"/><path fill="#FFF" d="M10.469 23.116s.716-.008 1.328-.421c.612-.413 1.865-1.173 2.868-.188 0 0-.7-.118-1.226.319-.526.438-1.341.951-2.027.894-.685-.056-.943-.604-.943-.604zm9.849 1.449s-1.2.353-2.353.329c-1.153.024-2.353-.329-2.353-.329l-1.106 1.059s.424-.129 1.129.188c.66.297 1.424.608 2.329.608s1.67-.311 2.329-.608c.706-.318 1.129-.188 1.129-.188l-1.104-1.059z"/><path fill="#FFF" d="M14.257 26.085c0 .192.156.348.348.348s1.289-.156 1.289-.348c0-.192-1.097-.348-1.289-.348s-.348.156-.348.348z"/><path fill="#FFF" d="M13.008 26.111c-.98-.183-1.019-.713-1.019-.713s.533.339 1.16.214 1.193-.105 1.193-.105-.597.662-.095.991c.222.146.837.084 1.105.025.268-.059.845-.166.971-.166.192 0 .348.156.348.348 0 .192-.156.348-.348.348-.128 0-.698-.106-.995-.174s-.505-.1-.728-.146c-.267-.055-.824.016-1.522.071-.698.055-1.208-.267-1.443-.549.494.157 1.145-.031 1.373-.144zM8.301 18.21c-.039-.095.856.573 1.467.498.611-.075 1.785-.242 2.025.214.241.455.456.927.456.927s-.407-.237-.934-.24c-.529-.003-1.64-.054-2.077-.2-.438-.147-.781-.824-.937-1.199zm.845-2.954c.011-.199.407-.115.489-.28s-.222-.516-.054-.635c.167-.119 1.019.644 1.493 1.155.474.512.606 1.329.453 1.57-.151.241-.054.021-.054.021s-.3-.595-.781-.838c-.481-.242-1.546-.993-1.546-.993zm11.054 7.82c-.196.048-.44.292-.669.633-.024-.332-.294-.595-.631-.595-.081 0-.157.019-.229.046-.084-.118-.215-.199-.371-.199-.121 0-.229.049-.312.125-.083-.076-.191-.125-.312-.125-.156 0-.287.082-.371.199-.071-.028-.148-.046-.229-.046-.35 0-.633.282-.638.631-.236-.359-.488-.619-.691-.668-.335-.082-.594-.435-.818-.594 0 0 .021.607.624 1.041.4.288.294.953.294.953s.729.182 1.059.218c-.05-.147-.115-.281-.177-.416.058.039.121.067.19.085l.186.347s.428.039.881.039.884-.039.884-.039l.186-.347c.053-.014.103-.031.15-.057-.058.127-.118.252-.165.389.329-.035 1.059-.218 1.059-.218s-.106-.665.294-.953c.602-.434.624-1.041.624-1.041-.224.157-.483.51-.818.592z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..271661726c878b90bce23c2732b2229e8c2c1e6e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFF" d="M11.077 21L18 31l6.923-10z"/><path fill="#141414" d="M10.279 15l-.105-.022 3.988-.827-3.392-2.417 3.977.889-2.28-3.64 3.36 2.47-.821-4.308 2.232 3.675L18 6.5l.763 4.321 2.232-3.675-.821 4.308 3.36-2.47-2.28 3.64 3.977-.889-3.392 2.417 3.988.827-.106.021h3.356l5.956-8.603C34.299 5.543 33.214 5 32 5H4C2.786 5 1.701 5.543.967 6.397L6.923 15h3.356z"/><path fill="#FCD116" d="M25.826 14.978l-3.988-.827 3.392-2.417-3.976.889 2.28-3.64-3.36 2.47.821-4.308-2.232 3.676L18 6.5l-.763 4.321-2.232-3.676.821 4.308-3.36-2.47 2.28 3.64-3.976-.889 3.392 2.417-3.988.827.105.022h15.442z"/><path fill="#0072C6" d="M10.279 15H6.923l4.154 6h13.846l4.154-6h-3.356z"/><path fill="#CE1126" d="M29.077 15l-4.154 6L18 31h14c2.209 0 4-1.791 4-4V9c0-.995-.366-1.903-.967-2.603L29.077 15zM6.923 15L.967 6.397C.366 7.097 0 8.005 0 9v18c0 2.209 1.791 4 4 4h14l-6.923-10-4.154-6z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..6a91dd9d7885a6ad219502ff4c1caa8235fde9ae --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#CCCC32" d="M33.938 12.324s-1.468.51-3.112.51c-1.643 0-2.879-.854-2.879-.854s-1.232.854-2.877.854c-1.644 0-3.194-.51-3.194-.51-.154 4.121.1 8.458 1.609 10.73C25.108 25.498 27.946 27 27.946 27s2.754-1.502 4.378-3.946c1.512-2.272 1.768-6.61 1.614-10.73z"/><path fill="#FFF" d="M33.416 12.811s-1.175.439-2.734.439c-1.562 0-2.735-.78-2.735-.78s-1.171.78-2.732.78c-1.562 0-2.731-.439-2.731-.439-.148 3.901 0 7.901 1.512 9.998 1.513 2.099 3.951 3.561 3.951 3.561s2.443-1.463 3.956-3.561c1.51-2.096 1.659-6.096 1.513-9.998z"/><path fill="#F90" d="M26.58 13.397s.049.683.341.926c0 0 .732-.146 1.317.098.463.193 1.317.536 1.756.39.438-.146.829-.292.928-.195.097.097-.489.244-.587.341-.098.098-.438.196-.243.488.196.293.537.537.439.83 0 0-.439-.341-.634-.634-.196-.293-.635-.537-1.367-.439-.732.098-1.316.488-1.413.927-.098.438.438.39.877.487 0 0-.634.244-.975.244 0 0-.293.537-.586 1.024-.292.488-.342.781-.487.732-.146-.049-.196-.732-.098-1.122 0 0-.341-.195-.293-1.17.042-.833.634-1.61.634-1.61s-.048-.292 0-.634c.05-.342.391-.683.391-.683z"/><path fill="#FFF" d="M26.044 16.835c0 .095-.076.171-.171.171-.095 0-.171-.076-.171-.171 0-.094.076-.17.171-.17.095 0 .171.076.171.17z"/><path fill="#F90" d="M25.024 21.728s.499-.47.502-.85c0 0-.575-.475-.757-1.083-.144-.48-.417-1.359-.808-1.607-.392-.248-.751-.458-.738-.595.015-.137.498.224.636.238.137.014.428.217.532-.119.104-.336.076-.755.364-.865 0 0 .014.556-.09.892-.104.335-.015.83.522 1.335.539.505 1.211.712 1.613.509.402-.201.025-.585-.178-.988 0 0 .591.337.807.603 0 0 .601-.113 1.163-.195.563-.082.82-.229.875-.084.055.144-.443.613-.809.785 0 0 .066.387-.721.966-.673.495-1.649.527-1.649.527s-.194.223-.491.4c-.292.179-.773.131-.773.131z"/><path fill="#FFF" d="M28.027 19.969c.073-.059.182-.048.24.025.061.072.049.181-.024.24-.073.059-.18.048-.239-.024-.061-.073-.049-.182.023-.241z"/><path fill="#F90" d="M32.781 18.83s-.637-.256-.983-.1c0 0-.188.721-.664 1.141-.377.334-1.059.95-1.12 1.408-.06.459-.1.874-.229.919-.13.045-.006-.545-.051-.676-.045-.13.017-.48-.332-.433-.348.047-.718.247-.938.032 0 0 .5-.246.848-.294.348-.046.76-.335.993-1.034.232-.702.138-1.398-.215-1.678-.351-.28-.543.224-.823.577 0 0 .059-.679.208-.985 0 0-.354-.498-.664-.975-.31-.477-.553-.648-.444-.759.107-.109.744.145 1.051.404 0 0 .326-.222 1.182.249.731.403 1.168 1.275 1.168 1.275s.285.084.571.278c.284.194.442.651.442.651z"/><path fill="#FFF" d="M29.925 16.841c-.085-.041-.121-.143-.079-.228.041-.085.143-.12.229-.079.084.042.119.143.077.228-.041.085-.144.121-.227.079z"/><path fill="#9CF" d="M23.771 22.47c.071.118.146.232.225.34 1.513 2.099 3.951 3.561 3.951 3.561s2.443-1.463 3.956-3.561c.078-.108.152-.222.224-.34h-8.356z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..2c8655dddac0c6f71f74aadd665a0dd163c3822d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E41E20" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M25.335 21.202c-.082-.012-.141-.051-.199-.105-.161-.151-.333-.162-.522-.047-.064.039-.122.085-.174.142-.032.035-.067.049-.114.05l-.777.021c-.02.001-.045.013-.059-.016.116-.112.237-.222.352-.335.058-.058.112-.074.196-.054.255.062.446-.019.548-.224.059-.117.152-.181.271-.213.053-.014.107-.019.171-.032-.154-.147-.319-.146-.492-.077-.052.021-.095.03-.15.01-.241-.092-.352-.04-.445.199-.018.045-.035.09-.081.119-.24.157-.479.316-.718.478-.041.029-.08.035-.13.02-.325-.088-.652-.17-.978-.256-.207-.054-.413-.109-.645-.173.127-.126.241-.235.353-.347.091-.091.065-.19-.059-.226-.102-.029-.205-.05-.309-.076-.812-.196-1.326-.708-1.574-1.498-.028-.088-.045-.175-.019-.267.019-.061.053-.108.119-.119.062-.01.11.025.14.074.031.05.055.105.077.159.145.347.336.656.648.879.079.057.162.077.255.068.078-.007.166-.016.195-.102.028-.085-.038-.142-.101-.184-.272-.189-.411-.46-.484-.774-.035-.145.034-.289.162-.324.117-.032.238.052.283.198.055.179.103.36.168.535.154.418.438.722.846.907.15.069.333.023.436-.095.079-.089.079-.19-.001-.278-.049-.054-.112-.088-.179-.116-.223-.096-.429-.22-.578-.418-.164-.22-.215-.468-.171-.734.022-.138.102-.169.224-.106.057.028.102.072.145.119.49.539.977 1.081 1.499 1.587.269.263.604.374.979.3.231-.045.443-.138.569-.355.054-.093.085-.194.017-.292-.068-.097-.173-.105-.279-.094-.507.06-.959-.076-1.354-.393-.373-.3-.651-.678-.899-1.082-.061-.096-.097-.205-.096-.32.003-.098.047-.122.134-.076.062.032.108.081.151.136.277.345.605.629.998.836.31.164.634.266.989.222.261-.032.382-.118.431-.442.033-.22-.077-.309-.287-.245-.443.135-.863.071-1.263-.153-.385-.217-.686-.53-.953-.874-.077-.1-.106-.226-.091-.355.011-.083.062-.119.146-.109.075.008.133.048.189.094.31.25.638.471 1.003.631.254.112.513.203.797.158.265-.041.462-.272.443-.52-.009-.144-.095-.236-.237-.254-.083-.009-.162.005-.243.014-.413.046-.802-.015-1.155-.248-.264-.175-.506-.377-.744-.584-.021-.018-.04-.04-.054-.064-.054-.082-.064-.191-.016-.226.073-.055.137-.003.195.034.323.203.669.347 1.041.431.286.065.572.103.862.029.198-.05.32-.176.357-.378.041-.222-.108-.375-.331-.341-.071.012-.14.032-.203.067-.261.147-.535.171-.824.097-.284-.073-.539-.209-.786-.363-.125-.077-.256-.146-.359-.253-.083-.088-.092-.196-.033-.272.057-.072.139-.08.255-.021.142.072.284.142.435.196.357.129.72.206 1.102.143.401-.066.696-.352.763-.736.011-.054.011-.105-.004-.158-.033-.12-.121-.173-.242-.145-.095.022-.168.078-.241.138-.367.306-.783.394-1.245.269-.214-.057-.404-.158-.592-.274-.095-.058-.175-.119-.209-.227-.036-.117.013-.184.136-.183.046 0 .092.006.139.015.486.097.973.128 1.455-.014.385-.113.679-.326.787-.737.037-.138-.008-.295-.109-.363-.093-.064-.21-.048-.336.049-.059.046-.113.099-.17.147-.48.401-1.052.42-1.634.392-.151-.007-.252-.152-.237-.287.014-.122.111-.186.273-.197.725-.05 1.353-.332 1.893-.808.188-.166.315-.38.37-.628.045-.196-.009-.373-.15-.516-.119-.12-.257-.108-.361.024-.033.042-.058.089-.088.133-.444.671-1.063 1.082-1.854 1.24-.085.017-.127-.004-.174-.073-.083-.125-.159-.152-.266-.111-.596.232-1.175.506-1.737.81-.061.033-.083.079-.081.144.003.099.031.191.062.282.065.2.05.395-.022.587-.094.254-.312.39-.594.377-.227-.01-.429-.186-.493-.435-.065-.258-.045-.513.081-.747.216-.4.532-.699.954-.874.318-.133.658-.191.992-.268.181-.04.363-.067.518-.181.05-.037.094-.078.103-.156-.141.042-.269.087-.4.12-.179.045-.325-.025-.458-.144.047-.012.092-.014.137-.012.274.014.548.02.82-.037.226-.047.438-.106.574-.312.029-.046.05-.093.049-.148-.001-.125-.085-.175-.194-.111-.077.045-.133.114-.188.182-.106.129-.243.203-.401.242-.179.046-.361.065-.547.053-.049-.003-.096-.01-.15-.035.11-.115.22-.211.358-.269.157-.065.253-.044.372.078.013.013.021.041.049.031.041-.229-.068-.383-.297-.423-.132-.022-.262-.009-.393.005-.023.002-.056.026-.068-.018-.038-.121-.146-.158-.248-.192-.301-.099-.6-.073-.889.044-.256.103-.518.179-.79.227-.161.029-.323.047-.494.072.148.143.322.237.488.364-.298.126-.539.305-.727.551l.006.032h.454l-.002.026c-.141.051-.283.097-.421.153-.142.058-.268.141-.377.265.078.019.147.034.216.052.055.014.066.045.022.084-.198.173-.363.379-.543.569-.046.048-.069.027-.104-.009-.177-.184-.337-.386-.531-.555-.056-.049-.032-.079.028-.094.065-.017.13-.031.205-.048-.218-.247-.517-.318-.802-.417l.007-.032h.475c-.208-.274-.451-.451-.746-.578.166-.128.343-.22.489-.37-.459-.042-.891-.132-1.306-.3-.3-.122-.607-.135-.915-.022-.079.03-.161.064-.192.151-.017.047-.037.05-.082.044-.154-.021-.31-.036-.464.013-.186.059-.271.222-.217.415.068-.067.128-.142.229-.153.161-.019.459.158.528.312-.125.038-.254.033-.382.022-.297-.024-.573-.099-.76-.359-.023-.033-.054-.061-.085-.085-.056-.043-.117-.089-.186-.039-.067.049-.059.127-.038.198.018.058.057.104.097.148.113.122.259.178.417.215.304.071.612.078.922.058.043-.003.091-.012.14.017-.181.154-.373.188-.589.109-.089-.033-.177-.071-.276-.088.006.076.05.115.098.151.104.079.226.117.351.146.247.057.492.115.739.168.501.109.912.36 1.227.768.207.268.301.564.25.902-.042.284-.248.512-.498.519-.332.009-.537-.125-.626-.423-.055-.179-.065-.361-.003-.543.032-.094.061-.19.061-.292-.001-.055-.019-.096-.069-.123-.571-.311-1.157-.587-1.763-.824-.064-.025-.122-.013-.175.03-.042.034-.079.073-.103.119-.025.047-.055.055-.107.046-.599-.099-1.105-.375-1.537-.798-.16-.155-.29-.333-.406-.524-.132-.218-.325-.221-.466-.008-.101.154-.13.322-.073.501.122.381.381.648.713.85.491.298 1.008.522 1.597.53.09.001.161.051.197.136.036.085.021.166-.038.237-.06.073-.14.115-.235.116-.15.001-.3.002-.45-.004-.47-.02-.896-.154-1.241-.493-.051-.05-.11-.093-.179-.119-.129-.047-.243-.001-.305.122-.04.08-.046.164-.026.247.061.243.191.438.404.576.233.151.494.221.766.251.371.042.735.008 1.099-.067.085-.017.185-.048.248.048.039.059-.008.194-.085.271-.009.009-.018.018-.029.024-.145.084-.284.182-.44.246-.549.227-1.06.188-1.521-.213-.061-.054-.132-.094-.213-.112-.116-.026-.203.026-.236.141-.016.055-.016.11-.005.167.079.432.444.73.916.751.34.016.664-.056.98-.174.152-.057.296-.131.441-.204.07-.035.14-.035.2.022.061.059.066.131.036.207-.023.059-.065.108-.118.143-.249.172-.505.334-.785.454-.391.169-.78.214-1.166-.018-.06-.036-.13-.045-.199-.05-.191-.013-.323.135-.292.333.033.206.154.337.355.391.171.046.346.049.521.03.505-.056.97-.227 1.398-.497.019-.012.037-.024.057-.032.042-.016.084-.031.124.002.039.032.037.078.029.122-.012.077-.055.137-.113.188-.177.154-.359.302-.544.444-.366.281-.774.425-1.24.381-.084-.008-.168-.018-.252-.024-.218-.019-.346.108-.327.326.019.219.206.409.438.449.174.031.343.001.508-.049.486-.149.899-.428 1.293-.738.048-.038.095-.073.153-.089.114-.033.187.015.189.135.002.121-.025.239-.102.334-.21.269-.445.516-.722.718-.335.245-.703.387-1.125.364-.142-.008-.277-.044-.413-.08-.116-.031-.203.014-.232.113-.065.22.1.514.322.567.287.071.566.02.834-.085.507-.196.914-.531 1.255-.949.046-.057.093-.111.159-.143.082-.043.126-.017.127.075.002.126-.04.241-.105.345-.216.345-.456.672-.757.949-.385.355-.833.543-1.362.518-.069-.003-.137-.017-.205-.013-.187.008-.275.139-.215.314.03.091.081.168.159.227.49.376 1.071.242 1.413-.089.526-.508 1.014-1.053 1.506-1.593.044-.049.091-.095.15-.125.119-.059.196-.027.22.103.036.194.014.386-.069.567-.136.297-.39.462-.676.588-.06.026-.119.055-.167.102-.101.098-.103.216 0 .31.124.112.268.152.425.079.403-.189.688-.491.841-.91.065-.179.113-.363.17-.545.042-.132.164-.214.275-.185.118.028.202.163.173.293-.068.31-.188.59-.461.78-.041.026-.079.06-.107.102-.054.079-.04.147.049.182.121.048.243.05.358-.028.325-.222.52-.539.668-.895.023-.054.047-.109.078-.158.031-.05.08-.082.142-.07.062.012.096.057.113.113.027.091.012.18-.016.268-.25.798-.768 1.311-1.59 1.505-.101.023-.201.047-.3.074-.118.035-.142.134-.057.221.094.097.19.19.284.287.019.018.047.03.045.067-.026.01-.052.018-.079.024-.504.133-1.008.264-1.511.399-.054.014-.093.009-.139-.023-.204-.138-.408-.277-.616-.409-.095-.06-.164-.13-.204-.241-.059-.161-.164-.222-.324-.169-.125.04-.229.023-.348-.013-.142-.044-.274-.008-.389.109.023.005.034.008.046.009.181.016.327.083.411.262.06.126.172.194.313.208.084.009.168.007.25-.019.053-.017.092-.008.133.032.123.12.251.235.376.353.004.004.003.016.002.007-.247 0-.494-.003-.74.001-.103.003-.178-.027-.256-.099-.229-.214-.469-.25-.702.006-.029.031-.063.035-.1.04-.134.018-.229.088-.281.23.188-.126.344-.043.5.054.01.008.022.011.034.016.198.081.389.086.565-.056.021-.017.044-.022.069-.021.301.02.603.037.923.059-.068.07-.143.094-.203.138-.124.092-.248.127-.412.094-.218-.047-.426.017-.541.227-.116.215-.196.444-.187.695.001.017-.006.037.014.053.027-.053.05-.107.08-.157.075-.127.165-.228.337-.167.031.012.067.009.102.009.205-.002.335-.095.375-.284.017-.086.061-.131.132-.164.051-.024.1-.052.151-.075.16-.07.328-.122.472-.227.031-.022.058-.011.088-.001l.514.174c.03.009.054.021.071.053.144.271.263.329.567.289.108-.014.212-.006.31.047.086.046.08.138.099.223.102-.138.089-.298-.037-.418-.063-.062-.117-.125-.162-.201-.085-.146-.232-.2-.387-.139-.093.038-.167.023-.249-.016-.125-.06-.244-.135-.398-.184.102-.032.181-.059.262-.08.445-.121.901-.199 1.342-.34.046-.014.075.003.108.032.119.105.237.212.359.315.107.087.188.073.263-.041.043-.065.085-.133.127-.198.169-.272.309-.563.49-.83.175-.256.369-.5.628-.675.237-.158.457-.063.515.213.05.242-.006.471-.104.692-.24.546-.63.952-1.143 1.248-.179.103-.361.149-.565.11-.131-.024-.261-.024-.386.032-.129.058-.155.153-.076.271.072.106.176.162.294.203.329.11.632.101.888-.17.062-.066.132-.123.202-.182.056-.046.12-.051.185-.017.063.036.089.093.083.165-.003.049-.025.09-.055.126-.101.12-.206.235-.324.338-.216.188-.46.31-.753.314-.068.001-.136.021-.196.057-.099.054-.115.138-.044.224.043.053.099.086.158.114.293.134.566.072.829-.085.165-.099.299-.235.433-.37.054-.056.116-.148.201-.095.083.051.061.158.035.241-.049.169-.12.328-.226.47-.107.142-.247.236-.42.28-.085.021-.173.021-.261.026-.146.01-.201.115-.13.242.014.025.03.048.049.068.192.217.497.249.726.073.231-.176.364-.423.486-.678.035-.072.066-.163.165-.154.101.009.125.102.15.182.016.048.021.098.02.148-.006.214-.072.404-.191.579-.107.159-.243.295-.387.42-.041.034-.047.06-.017.107.351.527.7 1.057 1.047 1.586.03.046.046.038.07-.002.065-.104.13-.206.198-.308.279-.422.557-.844.839-1.265.038-.056.035-.086-.018-.129-.1-.081-.188-.174-.273-.272-.181-.212-.297-.452-.295-.738 0-.094.022-.182.079-.256.056-.074.126-.076.189-.008.032.036.051.079.071.121.122.255.256.502.49.674.244.179.592.118.753-.127.091-.141.033-.267-.132-.265-.416.006-.668-.213-.819-.578-.044-.105-.099-.21-.087-.331.004-.043.006-.091.05-.114.049-.026.093.002.126.033.076.07.147.145.223.215.194.184.406.332.679.372.204.029.393-.012.555-.142.126-.102.106-.22-.042-.279-.052-.019-.108-.037-.164-.038-.499-.017-.808-.332-1.094-.685-.063-.079-.045-.182.021-.238.068-.06.155-.053.236.019.094.082.186.167.282.246.082.067.171.123.281.138.211.03.409-.011.603-.094.077-.033.136-.086.186-.151.095-.126.065-.227-.079-.288-.127-.055-.257-.048-.387-.026-.189.035-.367.004-.53-.1-.122-.08-.25-.154-.366-.243-.412-.311-.705-.713-.866-1.204-.061-.186-.087-.38-.019-.57.073-.206.249-.275.444-.179.067.032.129.076.183.129.189.183.368.374.511.596.21.325.378.675.595.997.09.134.167.144.29.038.113-.097.227-.194.338-.296.038-.036.073-.049.124-.032.315.1.639.169.961.243.205.047.409.098.627.174-.17.05-.297.143-.441.202-.061.024-.113.029-.178.002-.16-.065-.308-.024-.396.112-.057.088-.119.163-.192.238-.115.117-.119.281-.024.394.033-.256.157-.259.368-.266.031-.001.061.008.093.012.236.034.409-.058.508-.275.02-.045.049-.065.093-.081.146-.046.292-.091.434-.145.082-.031.147-.036.225.021.07.05.155.079.234.114.121.053.243.097.356.166.047.028.077.059.089.121.035.188.139.276.329.303.079.012.157.004.232-.017.066-.018.107.006.15.044.092.08.141.187.194.292.01-.045.01-.087.01-.131 0-.16-.063-.305-.109-.453-.092-.289-.287-.441-.586-.391-.204.033-.352-.027-.505-.129-.044-.029-.099-.045-.134-.103.309-.019.604-.039.9-.059.028-.001.054-.002.079.017.21.172.436.145.646.019.148-.09.285-.109.439-.039.004.002.01-.005.019-.01-.041-.091-.114-.17-.232-.187z"/><path fill-rule="evenodd" clip-rule="evenodd" fill="#E41E20" d="M20.308 10.618c.086-.053.183-.059.28-.059.09 0 .18.008.261.055.097.055.099.133.008.198-.124.089-.427.092-.556.005-.089-.06-.086-.143.007-.199zm-4.732.204c-.175.085-.355.083-.531-.004-.043-.021-.079-.056-.078-.108.002-.054.042-.082.084-.103.08-.04.167-.05.221-.048.128 0 .221.006.305.055.102.06.105.157-.001.208z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..0a966ab8bdefffb730ac4231a5f5f2536e9e8e5a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D90012" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#F2A800" d="M4 31h28c2.209 0 4-1.791 4-4v-4H0v4c0 2.209 1.791 4 4 4z"/><path fill="#0033A0" d="M0 13h36v10H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..65803b64a5c74c425e595c7be49f9eae0bc060d0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M0 18v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0z"/><path fill="#CE1B26" d="M36 18V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v9h36z"/><path fill="#F9D616" d="M17.452 13.646l.602 1.221 1.348.196-.975.951.231 1.343-1.206-.634-1.206.634.23-1.343-.976-.951 1.349-.196zm-2.296 3.542c.344.562 3.172 3.516 5.922 5.234.359.234 1.344.984 1.719 1.25-.156.203-.375.5-.609.75-.391-.312-3.969-2.516-5.141-3.109-1.172-.594-2.234-1.625-2.234-2.609-.001-.985.343-1.516.343-1.516zm7.828 6.609c-.172.25-.438.594-.594.781.312.047 1.109.438 1.516 1.281.406.844 1.141.406 1.078-.047s-.953-1.437-2-2.015z"/><circle fill="#292F33" cx="23.258" cy="24.492" r=".18"/><circle fill="#292F33" cx="24.258" cy="25.492" r=".18"/><path fill="#292F33" d="M22.547 24.041c-.029 0-.059-.009-.084-.026l-4.657-3.172c-.068-.047-.086-.14-.04-.208.047-.069.141-.087.208-.04l4.656 3.172c.069.047.087.14.04.208-.028.043-.075.066-.123.066z"/><path d="M24.826 18.648l.008-1.295-1.085.007c-.041-.417-.126-.82-.244-1.208l.972-.39-.438-1.219-1.046.416c-.178-.322-.384-.625-.614-.909l.699-.798-.994-.831-.625.71c-.31-.25-.641-.472-.994-.661l.454-.967-1.213-.457-.442.935c-.357-.103-.725-.176-1.104-.214l-.138 1.347c2.495.257 4.447 2.34 4.447 4.902 0 1.509-.688 2.842-1.751 3.751l.553.382 1.365 1.016.531-.578-.833-.618c.252-.303.476-.627.668-.974l1.006.408.5-1.195-1.001-.406c.112-.369.196-.751.238-1.146l1.081-.008zm-4.93 5.12l-.412-.799-.51-.243c-.464.144-.947.243-1.458.243-1.198 0-2.282-.442-3.139-1.15l-.832.979c.308.255.646.473.999.665l-.446.959 1.194.503.45-.972c.346.104.701.176 1.069.219l-.007 1.01 1.295-.014.007-.961c.404-.038.797-.114 1.175-.226l.344.994.688-.203-.431-.999.014-.005z" fill="#F9D616"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd29680f5b52b90eae265153b35bd1b626bc3635 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#265FB5" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFF" d="M27.532 18.933c-.051-.525.801-1.828.117-1.734-.837.114-1.491-.462-1.774-.448.906-1.281.233-1.607.031-2.438-.356-1.458.781-2.172-1.25-2.484-1.321-.203-2.233-.066-2.63-1.575-.583.409-1.275.511-1.932.224-.42-.183-.551-.532-.946-.701-.299-.127-.925-.126-1.26-.179-.923-.146-1.399.264-2.227.127.079.12.091.274.146.402-.511.018-.821.36-.876.837-.747-.075-.937.898-.853 1.512L14 12.5l.031.031c-.157 1.625-.818 2.438-2.483 2.693-1.096.168-2.07-.56-3.017-1.146-.208-.128-.571-.409-.766-.625-.28-.311-.478-.747-.75-.969-.125-.102-.391-.188-.354.021-.172 1.078.615 2.421 1.522 2.939-1.242.573.314.916.537 1.111.005.004.54.74.544.768.085.526-.278.466-.316.887-.039.437-.039.787.107 1.222l-.031.031c.006.35-.259.225-.603.146.047 1.062 1.059 1.154 1.228 1.362.545.669.357 1.642.993 2.265 1.564 1.532 3.346.628 5.117.885.994.145 1.846.979 2.747.037 1.059 1.16-.815 2.535-.357 2.927.131.112.269.159.41.167-.026.071-.067.136-.085.211 1.272.12 2.612.424 3.802-.202-.002.191.126.423.133.524.292-.349.52-.329.892-.515.466-.232 1.286-.511 1.595-.976.368-.554-.21-1.319.948-1.082.09-.4.127-.358.34-.624-.319-.8.629-1.34.914-1.912.057-.116.061-.652.137-.854.144-.385.556-.599.67-1.081.208-.887-.299-1.04-.373-1.808z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..e8e60efdf7d43ef7d0b4e67aabfc31d9aa9be3a8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#75AADB" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#FCBF49" d="M18 13l.488 2.548 1.426-2.167-.525 2.54 2.146-1.457-1.457 2.147 2.541-.524-2.167 1.425L23 18l-2.548.488 2.167 1.426-2.541-.525 1.457 2.146-2.146-1.457.525 2.541-1.426-2.167L18 23l-.488-2.548-1.425 2.167.524-2.541-2.147 1.457 1.457-2.146-2.54.525 2.167-1.426L13 18l2.548-.488-2.167-1.425 2.54.524-1.457-2.147 2.147 1.457-.524-2.54 1.425 2.167z"/><path fill="#843511" d="M18 14.33l.242 1.265.116.605.339-.514.708-1.076-.261 1.261-.125.604.51-.346 1.066-.723-.723 1.066-.346.51.603-.125 1.262-.26-1.076.708-.515.337.605.116L21.67 18l-1.265.242-.605.116.514.339 1.076.708-1.262-.261-.604-.125.346.51.723 1.065-1.065-.723-.51-.346.125.604.261 1.262-.708-1.076-.338-.515-.116.605L18 21.67l-.242-1.265-.116-.605-.339.515-.708 1.076.26-1.262.125-.603-.51.346-1.066.723.723-1.066.346-.51-.604.125-1.261.261 1.076-.708.514-.339-.605-.116L14.33 18l1.265-.242.605-.116-.515-.339-1.076-.708 1.261.26.603.125-.346-.51-.724-1.066 1.066.724.51.346-.125-.603-.26-1.261.708 1.076.339.515.116-.605L18 14.33M18 13l-.488 2.548-1.425-2.167.524 2.541-2.147-1.457 1.457 2.147-2.54-.524 2.167 1.425L13 18l2.548.488-2.167 1.426 2.54-.525-1.457 2.146 2.147-1.457-.524 2.541 1.425-2.167L18 23l.488-2.548 1.426 2.167-.525-2.541 2.146 1.457-1.457-2.146 2.541.525-2.167-1.426L23 18l-2.548-.488 2.167-1.425-2.541.524 1.457-2.147-2.146 1.457.525-2.541-1.426 2.167L18 13zm1.914.381h.005-.005zm1.621 1.083h.005-.005zm1.084 1.623h.005-.005z"/><circle fill="#FCBF49" cx="18" cy="18" r="2"/><path fill="#843511" d="M18 20.125c-1.172 0-2.125-.953-2.125-2.125s.953-2.125 2.125-2.125 2.125.953 2.125 2.125-.953 2.125-2.125 2.125zm0-4c-1.034 0-1.875.841-1.875 1.875s.841 1.875 1.875 1.875 1.875-.841 1.875-1.875-.841-1.875-1.875-1.875z"/><path fill="#C16540" d="M17.801 17.774c0 .155-.261.28-.583.28-.323 0-.584-.125-.584-.28 0-.155.261-.28.584-.28.322 0 .583.125.583.28zm1.553-.024c0-.161-.266-.292-.594-.292-.328 0-.594.13-.594.292s.266.292.594.292c.329 0 .594-.131.594-.292z"/><path fill="#ED8662" d="M17.463 18.874c0-.126.246-.229.548-.229.303 0 .548.102.548.229 0 .126-.246.229-.548.229-.303 0-.548-.103-.548-.229z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b275322a5dbb19a8b6e9119583e09cac1b4d0d2 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#BD1721" d="M34.184 5.654L0 17.966v.04l34.185 12.338C35.276 29.631 36 28.401 36 27V9c0-1.402-.725-2.631-1.816-3.346z"/><path fill="#EEE" d="M35.271 29.293c.456-.65.729-1.439.729-2.293V9c0-.856-.274-1.645-.732-2.296L3.944 17.986l31.327 11.307z"/><path fill="#D89500" d="M22 19.537s.767.121 1.089 0c.323-.121.726-.242.726-.242l.605.645.242-.605.444.121-.041.202s.363.121.363.161c0 .04-.04.363-.04.363l1.129.282.202-.443s.726.645 1.009.685c.281.041 1.129 0 1.29.121.161.122.524.363.524.363s2.864.646 2.864.687c0 .04-.04.281-.282.241-.242-.04-3.953-.767-4.438-.928-.484-.161-1.21.161-1.21.161v-.443l-1.251-.363-.12.323h-.323l-.121.282-.443-.121.08-.606s-.362-.04-.523.081c-.162.121-.403.242-.403.242s-.242-.443-.606-.686c-.363-.241-.766-.523-.766-.523z"/><path fill="#D89500" d="M26.114 21.675s5.405.443 5.729.483c.322.041.322.323 0 .363-.323.041-5.729-.403-5.729-.403s-.242.242-.242.323c0 .08 2.138.121 2.138.121l-.201.201s.847.04 1.17-.04c.322-.081.362-.322.403-.242.04.081-.242.403-.161.403.08 0 .968-.081.968-.081l-.646.323.969.363s-.484.121-.687.121c-.201 0-.524-.081-.524-.081s.323.443.565.524c0 0-.807-.202-.929-.323-.12-.12.242.606-.483-.04-.726-.646-.726-.322-.726-.322l.241.403s-.604 0-1.009-.242c-.403-.242-.887-.363-1.25-.484s-.685-.242-.968-.403c-.282-.161-.888-.524-.767-.887s.604-.242.604-.242.323-.081.565-.041c.242.041.403-.282.646-.161.244.122.324.364.324.364z"/><path fill="#FFF" d="M31.722 15.422c.483.121 1.371-.04 1.774-.121.403-.081.685-.202.847-.04.162.161.122.242.122.242s.241.121.241.242v.121s.162.282 0 .403c0 0 .162.444-.121.524 0 0 .202.363-.12.403l-.122.403-2.662-.444.041-1.733z"/><path fill="#66757F" d="M34.396 17.686l-2.791-.465.001-.065.043-1.828.092.023c.229.057.72.083 1.741-.122.085-.017.165-.036.239-.053.289-.069.52-.124.675.034.112.11.144.196.148.252.084.049.237.156.237.284v.102c.062.118.12.317.011.444.026.091.067.285-.006.428-.023.047-.059.084-.102.112.03.078.062.203.011.304-.023.046-.071.102-.172.127l-.127.423zm-2.639-.593l2.533.422.117-.387.048-.006c.084-.011.101-.044.106-.055.032-.064-.015-.188-.042-.237l-.046-.083.091-.026c.042-.012.07-.034.088-.07.054-.105.006-.293-.017-.356l-.02-.053.045-.033c.105-.079-.019-.304-.021-.306l-.01-.017v-.141c0-.042-.105-.127-.199-.175l-.067-.033.033-.066c-.003 0-.004-.054-.107-.157-.093-.094-.256-.061-.534.006-.076.018-.158.037-.245.055-.774.156-1.353.202-1.716.139l-.037 1.579z"/><path fill="#FFC220" d="M28.857 19.819c-.016.037-.322.807-.484.928-.161.121-.524.403-.685.443-.161.041-.161.202-.161.202s-.363.202-.484.282c-.121.081-.242.081.081.121.322.04.403.081.403.081s-.242.241-.161.363c.08.12.407.142.807.241.322.081.646-.04.646-.161s-.081-.443-.081-.403c0 .04.242-.121.484-.242s.362-.403.282-.606c-.081-.201 0-.524.201-.887.202-.363-.04-.807-.241-.848-.203-.038-.526.284-.607.486z"/><path fill="#9C3900" d="M25.711 16.431c.363-.242.686-.726.686-.726s-.121-.162-.564.04c-.443.202-1.009.444-1.251.162-.37-.434.171-.98.605-1.13 1.291-.443-.524-.927 1.009-1.613.643-.288 1.896-.484 2.138-.605s.604-.565.604-.524c0 .04.041.323.041.323s.888-.242 1.17-.363c.282-.121.524-.443.524-.443l.08.282s.727-.081 1.009-.282c.282-.202.484-.04.484-.04s.807-.202 1.129-.363c.323-.161.767-.242.686.041-.08.282-.564 1.694-.767 1.977-.201.282-.161.726-.403.928-.241.202-1.895 1.129-1.895 1.129s.807.04 1.13.162c.322.121.161.524.161.524s.081.161.081.322c0 .162-.202.202-.202.202s.202.081.161.242c-.04.162-.403.162-.322.162.081 0 .403.322.363.443-.041.121-.686-.161-.969-.08 0 0 .041.202.282.323.242.121.242.202.041.323-.202.121-.404.282-.202.282s.282.121.161.202c-.121.08.484 0 .121.282-.362.283-.443.283-.443.283s.363.443.201.484c-.161.04-.686-.243-.686-.243s.121.404.323.525c0 0-.444.281-.686-.041 0 0 .04.444.161.565 0 0-.242.04-.444-.121 0 0-.161.322-.08.524l-.403-.646-.565-.16-.322.564s-.202-.404-.161-.767c.04-.362 0-.887-.041-1.089-.04-.202-.524-.766-.927-.847-.404-.081-1.171-.081-1.171-.081l-.928-1.13"/><path fill="#FFC220" d="M23.653 18.69s.848.282 1.13-.283c.282-.564-.685-.766-1.049-.564-.362.202-.646.564-.604.847.04.282.403.404.403.404l.12-.404z"/><path fill="#FFF" d="M23.573 17.923l.202.484h1.008s.928-.766 1.654-.807c.726-.04 1.25-.403.443-.444 0 0 1.089-.484-.081-.403 0 0 .767-.524-.242-.323 0 0 .888-.605-.282-.322l.121-.444s-.483.564-.807.726c-.322.161-1.331.646-1.573.726-.241.081-.201.202-.241.403-.041.203-.202.404-.202.404z"/><path fill="#66757F" d="M24.811 18.482h-1.085l-.238-.571.027-.035c.002-.002.15-.19.188-.372.007-.037.012-.072.016-.104.019-.142.036-.275.275-.355.231-.077 1.213-.547 1.563-.722.306-.153.778-.703.783-.708l.217-.253-.176.645c.411-.089.525-.048.563.041.035.079-.025.174-.119.266.187-.017.285.013.318.092.035.082-.03.178-.118.263h.009c.245 0 .356.042.379.133.022.091-.069.194-.273.31.123.028.223.081.223.182 0 .204-.478.357-.921.381-.693.039-1.602.782-1.61.79l-.021.017zm-.986-.15h.932c.146-.118.986-.768 1.677-.806.463-.026.757-.176.778-.233-.008 0-.065-.047-.335-.061l-.313-.016.287-.127c.185-.083.361-.19.406-.246-.036-.013-.141-.035-.452-.014l-.274.019.228-.156c.112-.077.219-.177.241-.224-.029-.01-.13-.023-.427.037l-.361.072.305-.208c.13-.089.255-.202.283-.256-.038-.01-.161-.016-.506.068l-.123.03.072-.267c-.173.18-.421.415-.619.514-.293.147-1.326.645-1.583.73-.149.05-.156.1-.173.232-.005.035-.01.073-.019.114-.033.167-.14.329-.189.399l.165.399z"/><path d="M24.523 17.519c.038.077-.021.186-.134.242-.112.057-.235.039-.274-.038-.038-.077.021-.186.134-.242.112-.057.235-.04.274.038z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..bfe1ec7f1116d1c71a829fcebdfb19a633b98432 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#ED2939" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4zM4 31h28c2.209 0 4-1.791 4-4v-4H0v4c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..989da76df59d5d1f7767b43222f4146775f5f773 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M9 26.023l-1.222 1.129.121-1.66-1.645-.251 1.373-.94-.829-1.443 1.591.488L9 21.797l.612 1.549 1.591-.488-.83 1.443 1.374.94-1.645.251.121 1.66zM27.95 9.562l-.799.738.079-1.086-1.077-.164.899-.615-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.615-1.076.164.079 1.086zm-4 6l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zm9-2l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zm-5 14l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zM31 16l.294.596.657.095-.475.463.112.655L31 17.5l-.588.309.112-.655-.475-.463.657-.095z" fill="#FFF"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..f3839512602712dccb8b7c6f09ff3eabb05e320a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4189DD" d="M32 5H4C1.791 5 0 6.791 0 9v13.055h36V9c0-2.209-1.791-4-4-4zM6.276 11.276l-.943 3.057-.943-3.057-3.057-.943L4.39 9.39l.943-3.057.943 3.057 3.057.943-3.057.943zM4 31h28c1.872 0 3.431-1.291 3.867-3.028H.133C.569 29.709 2.128 31 4 31zm-4-6.972h36V26H0z"/><path fill="#FFF" d="M5.333 6.333l-.942 3.058-3.057.943 3.057.943.943 3.057.943-3.057 3.057-.943-3.058-.943-.943-3.058zm.727 4.727l-.726 2.355-.727-2.355-2.355-.726 2.355-.726.726-2.355.727 2.354 2.355.726-2.355.727z"/><path fill="#D21034" d="M5.333 7.252l-.726 2.355-2.355.726 2.355.727.726 2.355.727-2.355 2.355-.727-2.355-.726z"/><path fill="#F9D616" d="M0 22.055h36v1.972H0zM0 27c0 .337.054.659.133.972h35.734c.079-.313.133-.635.133-.972v-1H0v1z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fd.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fd.svg new file mode 100644 index 0000000000000000000000000000000000000000..03bc680c754579e084b7054c2b20abfafadb7a03 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1fd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCE00" d="M18 5h-2v11h20v-2H18zm-2 17v9h2v-9h18v-2H16zm-3-2H0v2h11v9h2v-9zm0-6V5h-2v9H0v2h13z"/><path fill="#D21034" d="M16 5h-3v11H0v4h13v11h3V20h20v-4H16z"/><path fill="#0053A5" d="M18 22v9h14c2.209 0 4-1.791 4-4v-5H18zM0 22v5c0 2.209 1.791 4 4 4h7v-9H0zM11 5H4C1.791 5 0 6.791 0 9v5h11V5zm21 0H18v9h18V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..b5848545bba9683b991498774b7218cbac712c07 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e6-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E00034" d="M0 13h36v10H0z"/><path fill="#0098C3" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><g fill="#FFF"><path d="M17.844 21.333c-1.841 0-3.333-1.492-3.333-3.333 0-1.841 1.492-3.333 3.333-3.333.982 0 1.865.425 2.475 1.101C19.601 14.701 18.382 14 17 14c-2.209 0-4 1.791-4 4s1.791 4 4 4c1.382 0 2.601-.701 3.32-1.768-.61.676-1.493 1.101-2.476 1.101z"/><path d="M23.667 17.998l-1.196-.424.544-1.146-1.146.545-.426-1.195-.424 1.196-.003-.002-1.144-.542.546 1.146-1.196.426 1.196.424-.544 1.146 1.141-.543.005-.002.426 1.195.424-1.196 1.147.544-.546-1.146z"/></g><path fill="#00AE65" d="M4 31h28c2.209 0 4-1.791 4-4v-4H0v4c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..bbcd3b5e6048d7eb7d4b784806d536201cb5e75e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#2D3189" d="M32 5H9.177l-.665.484.365 1.123-.956-.695-.956.695.365-1.123L6.665 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h19.725l.105-.324-.955-.695h1.181l.365-1.123.365 1.123h1.181l-.955.695.105.324H32c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#E1E8ED" d="M6.965 6.607l.956-.695.955.695-.364-1.123L9.177 5H6.665l.665.484zm19.002 23.374h-1.181l-.365-1.122-.365 1.122h-1.181l.955.695-.105.324h1.392l-.106-.324zM9.999 6.815l.364 1.123h1.182l-.956.695.365 1.123-.955-.695-.956.695.365-1.123-.955-.695h1.18zm2.069 3.15l.365 1.122h1.182l-.956.695.365 1.123-.956-.694-.955.694.365-1.123-.956-.695h1.181zm2.054 3.148l.365 1.123h1.181l-.956.695.365 1.123-.955-.695-.956.695.365-1.123-.955-.695h1.181zm2.061 3.15l.365 1.123h1.181l-.955.694.365 1.123-.956-.694-.955.694.365-1.123-.956-.694h1.181zm2.061 3.149l.365 1.123h1.182l-.956.694.365 1.124-.956-.695-.955.695.365-1.124-.955-.694h1.181zm2.062 3.149l.365 1.123h1.181l-.955.694.364 1.123-.955-.694-.955.694.364-1.123-.955-.694h1.181zm2.053 3.148l.365 1.124h1.182l-.956.694.365 1.123-.956-.694-.955.694.365-1.123-.956-.694h1.181z"/><path fill="#FBD116" d="M28 31V5H11z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e7.svg new file mode 100644 index 0000000000000000000000000000000000000000..7f9e8c9d1a6c0dc5c65bf4be7a8db92d37eaece9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00267F" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#00267F" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FFC726" d="M12 5h12v26H12z"/><path d="M22.83 13.516c-1.406 0-2.5 1.031-2.859 1.438.422-.094.516.234.453.438-.444 1.477-.819 3.215-.931 4.15h-.903v-5.186l1.09-.226-1.366-.273-.283-1.377-.283 1.377-1.367.273 1.1.228v5.184h-.947c-.112-.936-.487-2.674-.931-4.15-.062-.203.031-.531.453-.438-.359-.406-1.453-1.438-2.859-1.438.613.906 2.245 3.432 2.458 6.403v.622h1.826v2.414h1.109v-2.414h1.756v-.232c.085-3.14 1.844-5.848 2.484-6.793z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..6edc8443057338fb3322490d45f3a941f20236c6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006A4D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><circle fill="#F42A41" cx="16" cy="17.5" r="7"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..86704269a7980b817d700063508e20ab72613acd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#141414" d="M7 5a4 4 0 0 0-4 4v18a4 4 0 0 0 4 4h6V5H7z"/><path fill="#FDDA24" d="M13 5h10v26H13z"/><path fill="#EF3340" d="M29 5h-6v26h6a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..8bceec74b3ad33ad0359e8790772ed6580760809 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009E49" d="M19.602 18.942l.99 3.048L18 20.106l-2.593 1.884.99-3.048L15.101 18H0v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H20.899l-1.297.942z"/><path fill="#EF2B2D" d="M32 5H4C1.791 5 0 6.791 0 9v9h15.101l-1.296-.942h3.205L18 14.01l.99 3.048h3.205L20.899 18H36V9c0-2.209-1.791-4-4-4z"/><path fill="#FCD116" d="M15.407 21.99L18 20.106l2.593 1.884-.991-3.048L20.899 18l1.296-.942H18.99L18 14.01l-.99 3.048h-3.205l1.296.942 1.297.942z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..6e81fba54d5a16aac053b7692c4dab6efd2c9caa --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#D62612" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-5H0v5z"/><path fill="#00966E" d="M0 14h36v8H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..73de5829e84e1346b8daf4b16aa8ab679c02c72f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M15 6L8 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h4l7-1V6z"/><path fill="#CE1126" d="M32 5H8l6.081 2.6L8 10.2l6.081 2.6L8 15.4l6.081 2.6L8 20.6l6.081 2.6L8 25.8l6.081 2.6L8 31h24c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..e53644c54f531719dee63061ef6b5a54dadb4bf9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#CE1126" d="M13.685 13.068c1.15-1.028 2.662-1.658 4.325-1.658 1.646 0 3.145.617 4.291 1.626l10.833-7.854C32.772 5.075 32.397 5 32 5H4c-.411 0-.8.08-1.174.195l10.859 7.873z"/><path fill="#1EB53A" d="M24.038 15.483c.303.751.473 1.569.473 2.427 0 .928-.198 1.809-.548 2.608l11.544 8.369c.304-.564.493-1.2.493-1.887V9c0-.67-.181-1.292-.472-1.847l-11.49 8.33zm-11.999 4.994c-.339-.788-.528-1.655-.528-2.566 0-.842.165-1.644.457-2.383L.456 7.182C.174 7.73 0 8.342 0 9v18c0 .675.183 1.301.478 1.859l11.561-8.382z"/><path fill="#CE1126" d="M22.157 22.916c-1.125.933-2.57 1.495-4.146 1.495-1.593 0-3.051-.575-4.181-1.526L2.881 30.822c.357.104.728.178 1.119.178h28c.377 0 .734-.069 1.079-.166l-10.922-7.918z"/><path fill="#1EB53A" d="M19.077 15.266l.317-.548.216-.375h-1.066l-.317-.548-.216-.375-.217.375-.316.548h-1.067l.217.375.316.548-.316.549-.217.375h1.067l.316.548.217.375.216-.375.317-.548h1.066l-.216-.375z"/><path fill="#CE1126" d="M19.177 14.593H18.4l-.389-.673-.389.673h-.778l.389.673-.389.674h.778l.389.673.389-.673h.777l-.389-.674z"/><path fill="#1EB53A" d="M21.928 19.805l.317-.549.217-.375h-1.067l-.316-.548-.217-.375-.216.375-.317.548h-1.066l.216.375.317.549-.317.548-.216.375h1.066l.317.548.216.376.217-.376.316-.548h1.067l-.217-.375z"/><path fill="#CE1126" d="M20.862 18.458l-.389.673h-.777l.388.674-.388.673h.777l.389.673.389-.673h.778l-.389-.673.389-.674h-.778z"/><path fill="#1EB53A" d="M16.542 20.353l-.316-.548.316-.549.217-.375h-1.066l-.317-.548-.217-.375-.216.375-.317.548H13.56l.216.375.317.549-.317.548-.216.375h1.066l.317.548.216.376.217-.376.317-.548h1.066z"/><path fill="#CE1126" d="M16.326 19.131h-.778l-.389-.673-.388.673h-.778l.389.674-.389.673h.778l.388.673.389-.673h.778l-.389-.673z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ef.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ef.svg new file mode 100644 index 0000000000000000000000000000000000000000..133d7112416a9f63913305cbc3661c15ea538e5d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ef.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCD116" d="M32 5H14v13h22V9c0-2.209-1.791-4-4-4z"/><path fill="#E8112D" d="M14 31h18c2.209 0 4-1.791 4-4v-9H14v13z"/><path fill="#008751" d="M14 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h10V5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..9d4904dd4c9b661fac58224a8a248c76269553cc --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#CE1A24" d="M10.391 21.254s-.337 1.015-.253 2.029c.085 1.015 2.452.93 2.959.846.507-.085.846-.085.507.339-.337.421-.76 1.098-.676 1.859.084.759-1.015.253-1.352-.509-.338-.76-.677-.76-1.269-1.098-.592-.338-1.165-1.19-1.522-1.691-.423-.591-.677-1.014 1.606-1.775zm15.217 0s.339 1.015.254 2.029c-.083 1.015-2.452.93-2.959.846-.508-.085-.845-.085-.508.339.34.421.762 1.098.678 1.859-.085.759 1.014.253 1.352-.509.34-.76.677-.76 1.269-1.098.593-.338 1.164-1.19 1.522-1.691.422-.591.676-1.014-1.608-1.775z"/><path fill="#F6E4BE" d="M27.047 22.859c-.931.424-2.861.703-3.637.762-1.025.079-1.183.338-1.183.592 0 .255 1.099.423 1.69.338.592-.083 1.269.085.254.677-1.015.591-2.367 1.438-3.636 1.775-1.267.339-2.535.254-2.535.254s-1.268.085-2.537-.254c-1.268-.338-2.621-1.184-3.635-1.775-1.015-.592-.339-.76.253-.677.592.085 1.691-.083 1.691-.338 0-.254-.158-.513-1.184-.592-.774-.059-2.706-.338-3.635-.762-.392-.178-.507-.506-.507-.506s0 .17.085.676c.084.507.507.845.592 1.353.084.506.084.761.507.845.423.085 1.353.17 1.353.17s0 .759-.169 1.183c-.17.423.423 1.185 2.705 2.029 2.283.847 3.298.762 4.481.762 1.184 0 2.198.085 4.48-.762 2.284-.845 2.874-1.607 2.706-2.029-.169-.424-.169-1.183-.169-1.183s.93-.085 1.352-.17c.425-.084.425-.339.508-.845.085-.509.507-.847.592-1.353.084-.506.084-.676.084-.676s-.115.329-.506.506z"/><path fill="#BCAD96" d="M14.28 27.342c.938.313 4.833 1.13 7.185.085.762-.341 1.015.674.339.93-.531.198-2.621.506-3.551.506-.93 0-3.482-.295-4.227-.591-.423-.171-.253-1.101.254-.93z"/><path fill="#666" d="M12.589 10.517H23.41v1.521H12.589z"/><path fill="#CE1A24" d="M18 11.531h-5.411v6.425c0 3.214 2.029 4.482 3.043 5.242 1.015.761 3.72.761 4.734 0 1.015-.76 3.044-2.027 3.044-5.242v-6.425H18z"/><path fill="#1353B4" d="M12.723 19.31c.468 2.239 2.052 3.246 2.909 3.889 1.015.761 2.368 1.27 2.368 1.27s1.353-.509 2.366-1.27c.86-.642 2.442-1.649 2.911-3.889H12.723zm-.134-7.779H23.41v3.974H12.589z"/><path fill="#EACE23" d="M14.788 12.969s.084-.169 0-.423c-.076-.227-.423-.423-.423-.423s-.347.196-.422.423c-.085.253 0 .423 0 .423-.423-.169-.592.254-.592.507 0 .254.339.422.339.422s0-.338.168-.338c.169 0 .169.338.169.338-.338 0 0 .254 0 .254l-.253.422.338-.085c-.084.254.254.507.254.507s.339-.253.253-.507l.339.085-.253-.422s.338-.254 0-.254c0 0 0-.338.168-.338.169 0 .169.338.169.338s.338-.168.338-.422c-.001-.253-.17-.677-.592-.507zm7.271 0s.084-.169 0-.423c-.075-.227-.423-.423-.423-.423s-.347.196-.423.423c-.085.253 0 .423 0 .423-.423-.169-.592.254-.592.507 0 .254.338.422.338.422s0-.338.169-.338.169.338.169.338c-.338 0 0 .254 0 .254l-.253.422.337-.085c-.084.254.255.507.255.507s.338-.253.253-.507l.339.085-.254-.422s.338-.254 0-.254c0 0 0-.338.169-.338s.169.338.169.338.339-.168.339-.422c-.001-.253-.171-.677-.592-.507zm-3.636 0s.084-.169 0-.423c-.076-.227-.423-.423-.423-.423s-.347.196-.423.423c-.084.253 0 .423 0 .423-.423-.169-.592.254-.592.507 0 .254.338.422.338.422s0-.338.169-.338.169.338.169.338c-.338 0 0 .254 0 .254l-.253.422.338-.085c-.084.255.254.509.254.509s.338-.253.253-.507l.338.085-.253-.422s.338-.254 0-.254c0 0 0-.338.169-.338s.169.338.169.338.338-.168.338-.422c.001-.255-.168-.679-.591-.509z"/><path fill="#FFF" d="M18.93 17.45l.423-.593-1.184.339.338-1.1-.507.339-.507-.339.338 1.1-1.184-.339.423.593-.423.506 1.184-.422-.423 1.183.592-.338.592.338-.423-1.183 1.184.422z"/><path fill="#EACE23" d="M18.93 22.015s-.254 0-.254.254c0 .255.254.338.254.338s-.17.253-.423.253c-.254 0-.338-.253-.338-.253s.338-.083.338-.253c0-.17-.254-.254-.254-.254s0-.423-.253-.423-.253.423-.253.423-.254.084-.254.254c0 .17.338.253.338.253s-.085.253-.338.253-.422-.253-.422-.253.253-.083.253-.338c0-.254-.253-.254-.253-.254 0-.338-.338-.17-.338-.17l.253 1.776h2.029l.253-1.776s-.338-.168-.338.17zm-1.945-2.2s-.253 0-.253.256c0 .253.253.338.253.338s-.168.253-.422.253c-.253 0-.338-.253-.338-.253s.338-.085.338-.253c0-.171-.253-.256-.253-.256s0-.421-.254-.421c-.253 0-.253.421-.253.421s-.254.085-.254.256c0 .168.338.253.338.253s-.084.253-.338.253c-.253 0-.423-.253-.423-.253s.254-.085.254-.338c0-.256-.254-.256-.254-.256 0-.336-.337-.168-.337-.168l.253 1.776h2.03l.253-1.776c-.001 0-.34-.168-.34.168zm3.889 0s-.253 0-.253.256c0 .253.253.338.253.338s-.168.253-.423.253c-.253 0-.338-.253-.338-.253s.338-.085.338-.253c0-.171-.253-.256-.253-.256s0-.421-.254-.421c-.253 0-.253.421-.253.421s-.255.085-.255.256c0 .168.339.253.339.253s-.084.253-.339.253c-.253 0-.422-.253-.422-.253s.253-.085.253-.338c0-.256-.253-.256-.253-.256 0-.336-.338-.168-.338-.168l.254 1.776h2.029l.254-1.776s-.339-.168-.339.168zM24.51 7.474l-.17.507-.337-.085.084-.507-.845-.169-.093.536-.331-.092.001-.613-.846-.084-.071.528-.605-.106v.338h-.169v-.423h-.422v.339h-.255V7.22h-.422v.338l-.338-.084v-.762l-.846-.084v.507h-.423v-.507h-.846v.507h-.423v-.507l-.843.084v.761l-.339.084V7.22h-.422v.423h-.253v-.339h-.423v.423h-.168v-.338l-.606.106-.071-.528-.847.083v.613l-.331.092-.092-.535-.846.169.084.507-.338.085-.168-.507-.845.253.423 1.099.253-.084 1.268 2.79s1.438-.422 2.79-.592c1.353-.169 2.621-.169 2.621-.169s1.268 0 2.621.169c1.352.169 2.789.592 2.789.592l1.268-2.79.254.084.422-1.099-.844-.253z"/><path fill="#5E520D" d="M18 7.981c-.187 0-.338.151-.338.337v.846h.677v-.846c-.001-.186-.152-.337-.339-.337zm-5.122.526c-.181.047-.29.231-.242.413l.213.818.654-.17-.213-.818c-.046-.182-.231-.29-.412-.243zm10.243 0c.182.047.289.231.243.413l-.214.817-.654-.17.213-.818c.047-.181.231-.289.412-.242z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..5e7b7f6974449e774b7b87cea08b23d155b860bd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CF1B2B" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M22.583 12.585v9.067c0 .639.146 1.515 1.312 2.057.993.462 2.473.993 3.146 1.419.377.236.959.638.959.638s.582-.401.958-.638c.674-.426 2.049-.957 3.042-1.419 1.167-.542 1.312-1.418 1.312-2.057v-9.067H22.583z"/><path fill="#2E8F22" d="M23.108 21.453c.007.594.16 1.484 1.227 1.98.93.432 2.137.929 2.768 1.328.352.222.897.597.897.597s.545-.375.896-.597c.631-.399 1.842-.896 2.771-1.328 1.067-.496 1.221-1.387 1.228-1.98h-9.787z"/><path fill="#FFF" d="M23.108 13.106h9.787v8.439h-9.787z"/><path fill="#CF1B2B" d="M31.862 20.376c-.07-.39 0-.993-.106-1.171-.106-.177-1.099-.531-1.809-.461-.708.071-.213-.886.284-1.134.497-.249.958-.462 1.028-.745.071-.284-.178-.497-.603-.426-.426.071-.674.071-.923.319-.248.248-.283-.035-.39-.319-.105-.283.07-.39.107-.674.035-.283-.036-1.064-.249-1.383-.212-.319-.103-.531-.457-.709-.355-.178-.742-.319-.742-.319s-.39.142-.745.319c-.354.178-.248.39-.46.709-.213.319-.284 1.1-.249 1.383.036.284.212.391.107.674-.107.284-.142.567-.39.319-.249-.248-.497-.248-.923-.319-.425-.071-.674.142-.603.426.07.283.531.496 1.028.745.497.248.992 1.205.284 1.134-.71-.07-1.702.284-1.809.461-.106.178-.036.781-.106 1.171-.071.39-.248.709-.071.638.178-.07.993-.354 1.384-.638.39-.284.851 1.135.674 1.489-.179.354-.213.603-.497.461-.284-.142-.709.071-.851.355-.142.283.177.46.532.708.354.249.779-.248.957-.496.177-.249 1.737-1.028 1.737-1.028s1.558.779 1.734 1.028c.178.248.602.745.957.496.354-.248.673-.425.53-.708-.142-.284-.567-.497-.851-.355-.284.142-.319-.107-.498-.461-.176-.354.284-1.773.674-1.489.391.284 1.206.567 1.384.638.179.071.003-.248-.069-.638z"/><path fill="#FFE000" d="M30.866 18.39s.107.248.248.248.391-.318.178-.566c-.212-.249-.391-.355-.283-.567.105-.213-.178-.568-.178-.568-.142.212-.532.532-1.206.106-.674-.425-1.206-.497-1.312-.248h-.627c-.105-.248-.638-.177-1.312.248s-1.065.106-1.206-.106c0 0-.283.355-.178.568.107.212-.071.318-.283.567-.213.248.036.566.178.566s.248-.248.248-.248.46.39.426.922c-.036.531-.745 1.027-.745 1.027.213.248.213.604.426 1.241.212.639.957.461.957.461.036.391.71.781.957.781.249 0 .319.212.319.212s-.283.178-.142.32c.133.132.609-.047.668-.069.059.022.535.201.668.069.142-.143-.142-.32-.142-.32s.07-.212.319-.212c.247 0 .921-.391.957-.781 0 0 .745.178.957-.461.213-.638.213-.993.426-1.241 0 0-.709-.496-.745-1.027-.033-.532.427-.922.427-.922z"/><path fill="#64B4D1" d="M31.298 18.106c-.213-.248-.39-.355-.284-.567.107-.213-.142-.354-.142-.354-.142.213-.734.516-1.24.213-.532-.32-.674-.249-.816-.32 0 0 .087.247-.106.32-.283.106-.391-.143-.391-.143h-.637s-.107.249-.391.143c-.193-.073-.106-.32-.106-.32-.143.071-.284 0-.816.32-.506.303-1.099 0-1.24-.213 0 0-.249.142-.142.354.106.212-.071.319-.284.567-.213.248.106.035.248.035.142 0 .497.249.497.249s.39.284.354.958c-.028.532-.816 1.062-.816 1.062.212.25.425 1.136.425 1.136.213.462 4.816-1.666 4.787-2.198-.035-.674.354-.958.354-.958s.355-.249.497-.249c.142.001.462.213.249-.035z"/><path fill="#CCC" d="M30.198 19.348c-.005-.094-.001-.18.008-.258-.337.02-.667-.158-.788-.31-.142-.177-.318-.177-.638 0-.319.178-.319.673-.319.673v.072l1.95 1.275.562-.336c.014-.02.026-.037.041-.055 0 .001-.787-.529-.816-1.061z"/><path fill="#E4CB5E" d="M25.66 17.894l.248 2.624 1.134.851 1.171-.958-.248-.744-.142-.957-.426-.284-.355-.709-.46-.036-.248.177s-.213-.142-.213-.106c0 .036-.178.213-.178.213l-.283-.071z"/><path d="M27.645 18l.426-.106.603 1.064.602-.071.107.283-1.631.532v-.426l.071-.141z"/><path d="M26.511 18.354l.177 2.554.178-.107s-.248-2.092-.213-2.057c.035.036.532 1.809.532 1.809l.213.071-.603-2.199.957 1.667.177-.426-.992-1.347-.284-.354-.142.389z"/><path fill="#9F5A2B" d="M27.716 19.453l1.597-.354.709 1.063-.284.815s-1.206.603-1.24.639c-.036.035-1.171-.107-1.171-.107l.389-2.056z"/><path fill="#CCC" d="M29.56 21.724s.071-.213.284-.178c.212.035.142.283.142.283s.39.179.603-.283c.015-.021.026-.044.035-.07.128-.384.178-.815.39-1.065 0 0-.02-.012-.053-.037-.188.076-.337.18-.337.18s0-.318-.354-.39c-.354-.071-.709.461-.709.461-.142-.425-.71 0-.958.39-.247.391-.851.284-.851.284l-.108-.213s.037-.354-.247-.532c-.284-.177-.71.248-.71.248.107-.461-.39-.391-.495-.318-.107.07-.284-.178-.532-.248-.186-.053-.352.35-.438.689.051.178.094.37.154.552.009.026.021.05.035.07.213.462.603.283.603.283s-.07-.248.142-.283c.213-.035.284.178.284.178s.248-.071.319.142c.07.213-.248.284-.248.284-.035.07.177.39.915.555.141.1.219.294.219.294v.318h.71V23s.077-.194.219-.296c.738-.165.95-.484.915-.555 0 0-.318-.071-.248-.284.071-.213.319-.141.319-.141z"/><path fill="#FFF" d="M27.503 14.064l.356.177-.071.142-.354-.071.069-.248zm.958 0l-.354.177.07.142.354-.071-.07-.248z"/><path d="M28.745 14.524l.07-.248-.318.32-.142.177-.178-.177-.177.177-.177-.177-.178.177-.142-.177-.318-.32.07.248-.355.249.32-.142.177.071.177.177.249-.07.177.212.177-.212.249.07.177-.177.177-.071.32.142z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..3c20edb28463d4ad5015ee236d9d3a0437b322f7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F7E017" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#141414" d="M36 27L0 19v-5l36 8z"/><path fill="#EEE" d="M36 22L0 14V9l36 8z"/><g fill="#CF1B26"><path d="M21.596 14.935c.443.688.699 1.507.699 2.386 0 2.44-1.978 4.419-4.418 4.419-2.441 0-4.419-1.979-4.419-4.419 0-.879.257-1.698.699-2.386-.838.905-1.351 2.116-1.351 3.447 0 2.801 2.27 5.071 5.071 5.071 2.801 0 5.071-2.271 5.071-5.071 0-1.331-.513-2.542-1.352-3.447zm-11.893.571c.537.118.656.323.629.758 0 0 .273.053.463.325.191.272.367.543.693.652.327.109.585.325.585.978v2.42s-.06.245.076.57c.136.327.059.789-.947.789s-1.012-.435-.877-.761c.136-.326.293-.599.293-.599v-2.08s-.196-.285-.468-.476c-.272-.19-.846-.87-.927-1.523-.082-.651-.234-1.209.48-1.053zm16.257 0c-.537.118-.656.323-.629.758 0 0-.274.053-.464.325s-.268.543-.594.652c-.326.109-.485.325-.485.978v2.42s-.039.245-.176.57c-.136.327-.107.789.898.789 1.006 0 1.087-.435.951-.761s-.219-.599-.219-.599v-2.08s.097-.285.368-.476c.273-.19.796-.87.878-1.523.083-.651.185-1.209-.528-1.053z"/><path d="M23.435 24.738s.325-.652-.028-.788c-.354-.136-1.06 0-1.06 0s.589-.747.026-1.061c-.561-.313-.947.462-1.439.815-.491.354-.986.549-1.586.748-.598.199-1.378.285-1.378.285s-.875-.086-1.473-.285c-.599-.199-1.188-.395-1.68-.748s-.877-1.129-1.439-.815c-.562.313.028 1.061.028 1.061s-.707-.136-1.06 0c-.354.136-.026.788-.026.788-.788.109-.513.599-.513.599s.196-.253 1.012-.253 1.153.797 1.697.797.54-.517.54-.517c1.007.843 2.915.843 2.915.843s1.814 0 2.82-.843c0 0-.051.517.493.517s.857-.797 1.674-.797c.815 0 1 .253 1 .253s.267-.489-.523-.599zm-2.16-10.571c-.598-.163-1.238-.924-2.081-.924s-1.225.653-1.225.653-.467-.653-1.31-.653-1.569.761-2.168.924c-.598.164-1.169 0-1.169 0 .136.625.835.768.835.768.074.388.659.401.659.401.079.462.927.144.927.144s-.053.455.382.4c.435-.054 1.172-.816 1.172-.816s-.212.218-.184.415c.027.198.365.183.365.183-.299.299.241.653.241.653l.25-.19.165.19s.497-.353.197-.653c0 0 .316.015.344-.183.027-.198-.195-.415-.195-.415s.732.762 1.167.816c.436.054.38-.4.38-.4s.847.319.927-.144c0 0 .584-.014.657-.401 0 0 .699-.143.835-.768-.001 0-.572.164-1.171 0zm-4.254-2.447c0-.121.383-.218.857-.218.473 0 .857.097.857.218 0 .12-.384.217-.857.217-.474.001-.857-.097-.857-.217z"/><path d="M18.882 12.155c-.027-.191-.142-.218-.142-.218s-.449.116-.863.116c-.415 0-.857-.116-.857-.116s-.109.027-.136.218c-.027.19-.217.775-.217.775l.354-.388.299.388.299-.388.258.388.265-.388.303.388.3-.388.355.388s-.19-.584-.218-.775zm-.913-2.324v1.06l.729.313-.281-.435.572-.273zm-.31 3.099h.449v1.142h-.449zm.816 8.076s.294-.407.233-.714c-.061-.306-.346-.789-.427-1.098-.082-.309.198-.595.198-.595l-.217-.041s.292-.265.217-.551c-.075-.286-.217-.652-.258-.978-.041-.327.258-.714.258-.714l-.387.224-.211-.224-.205.224-.38-.224s.299.387.258.714c-.041.326-.184.693-.258.978-.075.286.218.551.218.551l-.218.041s.279.286.197.595c-.081.309-.367.792-.428 1.098-.061.307.231.714.231.714l-.584-.122c.319.652.692.733 1.169.733.477 0 .856-.081 1.175-.733l-.581.122z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..ad0a8c9a219594b150dfb1a7f1276c4e311ef7f3 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#007934" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFE000" d="M0 13h36v10H0z"/><path fill="#D52B1E" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M12.894 16.335c.041.062.381.55.381.55h.489l-.2-.275-.67-.275zm.733-.488c.041.061.381.55.381.55h.489l-.2-.275-.67-.275zm.682-.614c.019.071.185.643.185.643l.462.157-.1-.324-.547-.476z"/><path fill="#A05A2D" d="M13.953 21.498c-.04.021-.089.005-.109-.036-.021-.04-.004-.09.035-.109l2.467-1.26c.04-.021.089-.005.109.034.021.041.004.09-.035.11l-2.467 1.261zm.494.456c-.038.024-.088.013-.113-.024-.024-.036-.015-.088.023-.113l2.31-1.527c.038-.025.088-.016.113.022.025.038.015.087-.023.112l-2.31 1.53z"/><path fill="#A05A2D" d="M14.947 22.377c-.03.033-.082.037-.115.008-.034-.03-.037-.082-.007-.116l1.831-2.078c.03-.034.081-.036.115-.007.034.029.037.08.007.114l-1.831 2.079z"/><path fill="#A05A2D" d="M17.348 20.715l-.57 1.181-.102-.104-.222.307-.603-.328.749-1.464z"/><path fill="#D52B1E" d="M17.593 22.525L18 20.592l-.042-1.691-2.931-2.8-.204.642-.407-.326-.122.672s-.51-.366-.53-.305c-.02.061-.143 1.548-.184 2.383-.04.834-.074 2.076.835 2.24 1.588.285 2.769-.896 2.769-.896s.387.367.407.428-.143.773-.204 1.059c-.059.283.206.527.206.527z"/><path fill="#FFE000" d="M15.555 16.644l-.162.465-.265-.143s-.675 3.401.426 3.666c1.101.265 1.224-.184 1.224-.184l-.53-.712-.397.183s-.193-.526-.193-1.24c0-.637.102-1.265.102-1.265l.202.142.042-.468-.449-.444z"/><path fill="#007934" d="M16.676 17.659l-.672-.571-.042.468-.263-.183s-.146.489-.144 1.12c.002.631.083 1.243.083 1.243s.468.162.712 0c.245-.163.326-2.077.326-2.077z"/><path fill="#E8A30F" d="M16.454 19.573c-.529.227-1.611.635-1.326 1.142.286.508 1.12.305 1.65-.267.53-.57-.324-.875-.324-.875z"/><path fill="#FFF" d="M23.105 16.335c-.04.062-.381.55-.381.55h-.489l.199-.275.671-.275zm-.733-.488c-.04.061-.38.55-.38.55h-.489l.199-.275.67-.275zm-.681-.614l-.185.643-.463.157.101-.324.547-.476z"/><path fill="#A05A2D" d="M22.047 21.498c.04.021.09.005.109-.036.021-.04.005-.09-.035-.109l-2.466-1.26c-.041-.021-.089-.005-.11.034-.021.041-.005.09.036.11l2.466 1.261zm-.494.456c.038.024.089.013.113-.024.025-.036.015-.088-.023-.113l-2.309-1.527c-.037-.025-.088-.016-.112.022-.025.038-.015.087.022.112l2.309 1.53z"/><path fill="#A05A2D" d="M21.054 22.377c.029.033.081.037.114.008.034-.03.037-.082.008-.116l-1.831-2.078c-.028-.034-.08-.036-.114-.007-.034.029-.037.08-.008.114l1.831 2.079z"/><path fill="#A05A2D" d="M18.652 20.715l.57 1.181.102-.104.222.307.603-.328-.749-1.464z"/><path fill="#D52B1E" d="M18.407 22.525L18 20.592l.042-1.691 2.931-2.8.205.642.407-.326.122.672s.508-.366.528-.305c.021.061.144 1.548.184 2.383.041.834.075 2.076-.834 2.24-1.589.285-2.77-.896-2.77-.896s-.387.367-.407.428.143.773.204 1.059c.06.283-.205.527-.205.527z"/><path fill="#FFE000" d="M20.445 16.644l.161.465.265-.143s.676 3.401-.426 3.666c-1.101.265-1.224-.184-1.224-.184l.529-.712.398.183s.192-.526.192-1.24c0-.637-.102-1.265-.102-1.265l-.202.142-.042-.468.451-.444z"/><path fill="#007934" d="M19.324 17.659l.672-.571.042.468.263-.183s.146.489.144 1.12c-.002.631-.083 1.243-.083 1.243s-.469.162-.713 0c-.245-.163-.325-2.077-.325-2.077z"/><path fill="#E8A30F" d="M19.546 19.573c.529.227 1.61.635 1.325 1.142-.285.508-1.12.305-1.649-.267-.53-.57.324-.875.324-.875z"/><path fill="#D52B1E" d="M16.331 15.825c.171.202.163.489-.018.642-.18.153-.464.113-.635-.089-.17-.202-.163-.489.017-.642.18-.153.465-.113.636.089z"/><path fill="#E7E7E7" d="M19.75 15.825c-.17.202-.162.489.019.642.181.153.464.113.636-.089.171-.202.163-.489-.018-.642-.181-.153-.465-.113-.637.089z"/><path fill="#007934" d="M19.1 13.484c-.143.102.265.753.184 1.466-.083.713-1.284 1.283-1.284 1.283s-1.202-.57-1.283-1.283c-.082-.712.326-1.364.183-1.466-.143-.102-.896.55-.936 1.242-.041.692.66 1.735 1.12 1.935.46.2.917.305.917.305s.456-.106.917-.305c.461-.2 1.162-1.243 1.12-1.935-.042-.692-.796-1.344-.938-1.242z"/><path fill="#FFF" d="M18 16.213s.122-.428.917-.672c.794-.245 1.547-.428 1.833-.448.286-.021-1.13-.57-1.466-.611-.336-.04-.753.041-.815.286-.061.244-.163.163-.468.204-.306.04-.509-.245-.652-.448-.142-.204-.683-.102-.947-.081-.265.02-1.273.651-1.273.651s1.752.285 2.118.468c.366.184.02.835-.081 1.019-.103.182.605-.057.834-.368z"/><path d="M18 16.213s.122-.428.917-.672c.794-.245 1.547-.428 1.833-.448.286-.021-1.038-.428-1.375-.469-.336-.04-.6-.04-.661.204-.061.244-.407.102-.713.143-.306.04-.652-.061-.794-.265-.143-.204-.387-.122-.652-.102-.264.02-1.425.489-1.425.489s1.752.285 2.118.468c.366.184.02.835-.081 1.019-.104.183.604-.056.833-.367z"/><path fill="#00A6DE" d="M15.821 18.656c0-1.316.976-2.382 2.179-2.382 1.204 0 2.179 1.067 2.179 2.382 0 1.316-.975 2.383-2.179 2.383-1.203 0-2.179-1.066-2.179-2.383z"/><path fill="#E8A30F" d="M16.401 18.656c0-1.034.716-1.873 1.599-1.873s1.599.839 1.599 1.873c0 1.036-.716 1.874-1.599 1.874s-1.599-.838-1.599-1.874z"/><path fill="#D52B1E" d="M17.308 17.842c0-.382.31-.692.692-.692s.692.311.692.692c0 .383-.31.693-.692.693s-.692-.31-.692-.693z"/><path fill="#007934" d="M18 20.53c.849 0 1.544-.775 1.596-1.755-.521-.193-1.382-.933-1.596-.933-.224 0-.509.245-.875.57-.188.168-.48.303-.718.395.065.964.753 1.723 1.593 1.723z"/><path fill="#E8A30F" d="M18.204 15.133c0 .102-.21.184-.468.184-.259 0-.469-.082-.469-.184 0-.101.21-.183.469-.183.258 0 .468.083.468.183z"/><path fill="#FFF" d="M17.185 19.573h.489l.142-.407.184.223-.204.591h-.448z"/><path fill="#B37D0A" d="M18.427 19.919c0 .191-.095.347-.213.347S18 20.111 18 19.919c0-.191.096-.346.214-.346s.213.155.213.346zm.306.347c0 .024-.019.041-.041.041-.022 0-.041-.017-.041-.041v-1.059c0-.022.018-.041.041-.041.022 0 .041.019.041.041v1.059z"/><path fill="#32B266" d="M19.038 19.104c0 .18-.159.326-.356.326-.197 0-.356-.146-.356-.326 0-.18.16-.326.356-.326.197.001.356.146.356.326z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..bde4921702f92f342569831ee9a0135ac046fc59 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEEDED" d="M1.369 30.011L34.633 5.99C33.93 5.376 33.006 5 32 5H13.25L0 15.833V27c0 1.203.529 2.278 1.369 3.011z"/><path fill="#012A87" d="M34.633 5.99L1.369 30.011C2.072 30.625 2.994 31 4 31h28c2.209 0 4-1.791 4-4V9c0-.552-.112-1.078-.314-1.557-.239-.563-.599-1.057-1.053-1.453z"/><path fill="#F9D90F" d="M4 5C1.791 5 0 6.791 0 9v6.833L13.25 5H4z"/><path d="M16.513 15.894l1.192-.688-1.192-.688c-.312-2.515-2.31-4.513-4.825-4.825L11 8.5l-.688 1.192c-2.515.312-4.513 2.31-4.825 4.825l-1.192.688 1.192.688c.312 2.515 2.31 4.513 4.825 4.825L11 21.912l.688-1.192c2.515-.313 4.513-2.311 4.825-4.826zM11 20.048c-2.67 0-4.843-2.172-4.843-4.842 0-2.67 2.172-4.842 4.843-4.842s4.842 2.172 4.842 4.842c0 2.67-2.172 4.842-4.842 4.842z"/><path fill="#DC171D" d="M12.914 15.206l.957-1.658h-1.914L11 11.891l-.957 1.657H8.129l.957 1.658-.957 1.657h1.914L11 18.521l.957-1.658h1.914z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..956e39d0715d678df58f2e1cb9533833c455d46c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009B3A" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FEDF01" d="M32.728 18L18 29.124 3.272 18 18 6.875z"/><circle fill="#002776" cx="17.976" cy="17.924" r="6.458"/><path fill="#CBE9D4" d="M12.277 14.887c-.332.621-.558 1.303-.672 2.023 3.995-.29 9.417 1.891 11.744 4.595.402-.604.7-1.28.883-2.004-2.872-2.808-7.917-4.63-11.955-4.614z"/><path fill="#88C9F9" d="M12 18.233h1v1h-1zm1 2h1v1h-1z"/><path fill="#55ACEE" d="M15 18.233h1v1h-1zm2 1h1v1h-1zm4 2h1v1h-1zm-3 1h1v1h-1zm3-6h1v1h-1z"/><path fill="#3B88C3" d="M19 20.233h1v1h-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..a75f68bb60af5c7bf0d559bf1f349095b67f6ec4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00ABC9" d="M1.364 29.987C2.069 30.61 2.985 31 4 31h28c2.209 0 4-1.791 4-4v-4.5H11.442L1.364 29.987z"/><path fill="#FAE042" d="M17.5 18l-6.058 4.5H36v-9H11.442z"/><path fill="#00ABC9" d="M32 5H4c-1.015 0-1.931.39-2.636 1.013L11.442 13.5H36V9c0-2.209-1.791-4-4-4z"/><path fill="#141414" d="M17.5 18l-6.058-4.5L1.364 6.013C.534 6.746 0 7.806 0 9v18c0 1.194.534 2.254 1.364 2.987L11.442 22.5 17.5 18z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..e822f94f3a17049975335b6a348205d034c75497 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FF4E11" d="M1.193 29.846C1.915 30.558 2.905 31 4 31h28c2.209 0 4-1.791 4-4V9c0-.896-.305-1.714-.803-2.381L1.193 29.846z"/><path fill="#FFD521" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 1.114.458 2.121 1.193 2.846L35.197 6.619C34.468 5.642 33.313 5 32 5z"/><path fill="#FFF" d="M31.925 10.479c-.361.024-.554.289-.771.289h-.386s.312-.434.482-.554c.168-.121.794-.169.939-.289.144-.121.168-.289.168-.289-.313.217-1.036.096-1.348.168-.312.072-.579.41-.579.41s.361-.723.458-1.037c.096-.313.096-.843.482-1.132.385-.289.145-.651.145-.651s-.097.241-.361.458c-.265.217-.53.193-.506.603.025.409.048.409-.144.602s-.192.144-.506.675c-.313.53-.458-.024-1.133.217s-.988-.434-1.517-.361c-.53.072-1.783-.17-2.288-.338-.507-.169-.241-.386-1.471-.963-1.228-.579-2-.024-1.518-.049.238-.012.605.082.915.18-.386-.028-.698.133-.698.133s.675.192 1.229.674c.554.482 0 .434-.723 0s-1.493-.53-2.144-.458c-.65.072-.481.289-.12.265.361-.024 1.181.217 1.832.458.649.241-.049.29-.049.29-1.422-.844-2.048-.169-1.663-.314.387-.145.819.193 1.494.555s-.963.145-.963.145-.747-.313-1.471-.386c-.723-.072-1.276.626-1.036.963.241.337.698.144.698.144-.518-.15-.361-.53-.023-.626.337-.096 1.639.241 2 .386.361.144.506.699-.481.24-.988-.458-.627.073-.627.073-.964-.073.434.554-.169.386-.602-.169-1.301.072-1.879.072-.578 0-.795.627-.795.627s.337-.193.759-.338c.422-.144 1.602.145 1.602.145-.481.482-.458 1.373-.458 1.373-.505.12-.987 1.036-.987 1.036.192-.313.867-.41.867-.41s.12.265-.192.651c-.313.385-.217.867-.217.867s.144-.385.338-.578c.191-.193.674-.169.674-.169-.217.506.603.819.603.819-.241.433.218.916.144.892-.071-.024-.844.24-.844.24s1.062.024.506.169c-.554.144-1.565-.434-1.565-.434l-1.18-.53s.506.482-.072.41c-.579-.072-1.157.217-1.663-.12-.506-.338-1.35-.531-1.181-.217.168.314.41.626.41.626-.915-.193-.458.626-1.132.555-.675-.073-.121.578-.771.385-.651-.193-1.277.53-1.277.53.217-.121.915.072.915.072-.265.096-.144.601-.144.601-.627.167-.458 1.11-.458 1.11-.53 0-.626.36-.843.601-.216.241-.723.241-.723.241.354.275 1.051.087 1.3.008-.228.148-.192.811-.192.811-.434.072-.048.723-.144.65-.097-.072-.337.097-.578.289-.241.193-.554.241-.554.241.168.217.554.241.554.241s-.29.554-.651.675c-.361.119-1.373.36-1.638.385-.265.024-.843 0-1.373-.145-.53-.144-1.084 0-1.518-.049-.434-.048-.699.386-.699.386s.361-.12.674-.048c.313.072.41.361.747.217.337-.145 1.036.193 1.036.193s-.241.144-.578.265c-.337.12-.795.264-1.181.337-.385.072-.843.627-.53.361.313-.265.505-.048.939-.121.435-.072.844-.096.844-.096s-.289 0-.506.265c-.217.266-.819.507-1.157.507-.337 0-.891.169-1.205.578-.313.41-.699.482-.699.482s.241.265.603 0c.361-.266.434-.386.964-.482.53-.097 1.084-.289 1.084-.289-.289.241-.458.53-.939.602-.482.073-1.229.65-1.518.94-.289.289-.795.507-.795.507.481.289.723-.072 1.229-.361.506-.289.771-.097 1.374-.266.602-.169.53-.674.722-.698.193-.023.699 0 .844-.241.145-.24.048-.433.41-.433.361 0 .505-.169.505-.169-.145.312-.505.578-.505.578.434.12.771-.289 1.205-.555.434-.265.723-.265.723-.265s-.265.458-.554.506c-.29.048-.627.555-.627.555.193-.41 1.108-.338 1.446-.627.337-.289.795-.772 1.084-.94.289-.169.578-.529 1.084-.987.506-.458 1.397-.361 1.397-.434 0-.072-.024.674-.024.674l-.843.073.53.385c-.337-.145-.819.53-.819.53l.834-.097.178.483c.265-.556.458-.435.458-.435.289.337.313 1.108.313 1.108s-.385-.097-.819.409c-.434.507.361 1.47.361 1.47s-.145.217 0 .627c.144.409.891.843 1.638.602.747-.241.675-1.252.675-1.252s.265-.266.216-.796c-.048-.53-.289-.818-.289-.818s.458-.169.747.144c.289.312.361 1.035.361 1.035s.289-1.349-.144-1.685-1.494-.313-1.494-.313c-.024-.555-.506-.868-.627-1.229-.121-.361.072-1.253.072-1.253l.602.049s-.048.217.385.53c.434.312 1.132.096 1.132.096s.795.072 1.181-.626c.385-.698-.337-1.253-.337-1.253-.12-1.108-1.759-.481-1.759-.481.169-.747.892-.747.892-.747s-.843-.435-1.325-.266c-.482.169-.314 1.374-.699 1.326s-.434-1.23-.121-2.146c.313-.915 1.903-.963 3.421-.36 1.517.601 3.662.722 3.662.722-.071.289-.457.724-.457.724l-.675-.266.409.507c-.145.361-.53.626-.53.626.409.289.867-.289.867-.289l.169.699.41-.578s.842.602 1.541.866c.698.266 2.049.507 2.049.507s-.458.217.023.987c.482.771 1.59.987 1.59.987s.844.386 1.613-.289c.772-.675.145-1.903.145-1.903 0-1.42-1.517-.975-1.517-.975.312-.614 1.048-1.025 1.048-1.025-1.193-.698-1.698.676-2.59.965-.892.289-2.458-.555-2.529-.555-.073 0 .047-.145.071-.458.024-.312.747-.915 1.108-1.662.362-.747.266-1.976.266-1.976.481-.481 1.133-.121 1.133-.121-.024.506-.338.723-.338.723.361.024.53-.314.53-.314-.169.53.386 1.157.386 1.157l.168-.82.506.579-.312-1.06c.963 0 1.975-.699 1.975-.699s.482.699 1.446.699c.963 0 1.927-1.036 1.927-1.494 0-.458-.867-1.108-.867-1.108s.337-.771-.939-.771-1.662 1.555-1.662 1.555-.531-.229-1.254-.038c-.722.193-1.902-.409-2.625-.77-.724-.361-1.735-1.35-1.735-1.35 0-.337.188-.868.188-.868s1.04.073.728.193c-.314.121-1.132.362-.481.41.649.048 1.276-.217 1.083 0-.192.217-.915.723-.626.723s.675-.362.868-.41c.192-.048.529.072 1.012.072.128 0 .263-.074.392-.179.496.235 1.23.934 1.583 1.287.434.433.698-.145.892-.409.111-.153-.194-.44-.523-.699.055-.068.111-.135.161-.193.026-.03.069-.051.108-.074l.553.2c.003.418-.01.983-.01.983.266-.189.278-.569.283-.889.379.131.711.231.923.238.698.024 1.155-.217 1.806-.289.65-.072.698.531.698.531s.266-.193-.12-.579c-.385-.386-.892-.361-.892-.361 0-.555-.669-.53-.669-.53.56.313-.005.65-.005.65.072-.313-.627-.504-.627-.504s.458.215.17.479c-.18.165-.428.164-.737.117.036-.166.1-.419.205-.647.17-.361-.12-.722-.12-.722l.313-.579s1.036-.169 1.324-.313c.29-.145.578-.266 1.301-.241.724.024.893-.385.893-.385-.316.196-1.232-.068-1.593-.044zm-4.794 1.566c.241-.168.386-.024.386-.024l.19.434.243-.53.337.265-.191.337.723-.096-.072.241s-.257.231-.509.434c-.499-.155-1.079-.374-1.494-.598.079-.134.225-.35.387-.463zm.818 1.276c-.074.049-.125.114-.161.184-.183-.137-.355-.258-.44-.328-.081-.066-.189-.127-.307-.186.306.078.629.181.955.296l-.047.034zm.69-.099c.073-.013.129-.021.129-.021l.003.053c-.043-.01-.084-.019-.132-.032zm.445.099c.066-.273.288-.433.288-.433-.01.191.022.358.059.5l-.347-.067z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..3d104a61133b0f022cfac52c20a2afd6fec82bc7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EF2B2D" d="M10 5H4C1.791 5 0 6.791 0 9v6h10V5zm22 0H16v10h20V9c0-2.209-1.791-4-4-4zM16 31h16c2.209 0 4-1.791 4-4.5V21H16v10zM0 21v5.5C0 29.209 1.791 31 4 31h6V21H0z"/><path fill="#002868" d="M14.5 5h-2.944l-.025 11.5H0v3h11.525L11.5 31h3V19.5H36v-3H14.5z"/><path fill="#EDECEC" d="M14.5 31H16V21h20v-1.5H14.5zM16 5h-1.5v11.5H36V15H16zm-4.5 0H10v10H0v1.5h11.5zM0 19.5V21h10v10h1.5V19.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..5edeb5d5f71d19a136dc04c9137982c85e2f33ed --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#75AADB" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4zM0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-5H0v5z"/><path fill="#141414" d="M0 16h36v4H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..3fef573be84c916296f5542d4c1f19ec454cb154 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4AA657" d="M6 31h26c2.209 0 4-1.791 4-4v-4H6v8z"/><path fill="#C8313E" d="M32 5H6v18h30V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h2V5H4z"/><g fill="#C8313E"><path d="M.766 29.188l.625-1.109.641 1.141-.542.871c.171.139.351.263.544.372l.792-1.437-1.42-2.276-1.117 1.726c.183.46.451.872.781 1.23l-.304-.518zm5.215-.091l-1.497-2.222-1.502 2.171L4.268 31h.647l1.066-1.903zm-1.453-1.019l.641 1.141-.641 1.031-.625-1.062.625-1.11zM6 18.333v-.894l-.313.436zM2.825 7.026l-.894-1.434C1.153 6.065.557 6.791.246 7.662l1.285 1.713 1.294-2.349zm-2.059.162l.625-1.109.641 1.141-.641 1.03-.625-1.062zm3.851 2.343l1.364-2.435L4.569 5h-.171L2.983 7.046l1.634 2.485zm.551-2.312l-.64 1.031-.625-1.062.625-1.109.64 1.14z"/><path d="M4.953 15l.875-1.453.172.076V13l-1.406-2.188-1.688 2.344-1.5-2.406L0 12.923v.65L.859 15l.609-.891-.437-.609.328-.438.953 1.234-1.406 2.312L0 15.361v1.553l.058-.077.953 1.234L0 19.735v1.177l.906-1.248 1.406 2.312L1.522 23l-.163.211L1.201 23l-.17-.227.438-.609-.609-.891L0 22.701v.575l1.438 2.193L2.838 23l.053-.094.058.094 1.614 2.609L6 23.062v-.391l-.125.056L5 21.273l-.61.891.438.609-.17.227-.158.211L4.337 23l-.79-1.023 1.406-2.312L6 21.106v-1.142l-1.157-1.902.953-1.234L6 17.1v-1.997L4.906 16.61 3.5 14.297l.953-1.234.328.437-.438.609.61.891zm-.668 2.031v1.928L2.89 21.162 1.576 18.95v-1.908l1.314-2.213 1.395 2.202z"/><path d="M2.031 16.823l.598 1.091-.598 1.091.438.24.445-.811.445.811.438-.24-.598-1.091.598-1.091-.438-.24-.445.811-.445-.811zM.026 26.188l.625 1.062.641-1.031-.641-1.141zm1.516 0l.625 1.062.64-1.031-.64-1.141zm1.484 0l.625 1.062.641-1.031-.641-1.141zm1.592 0l.625 1.062.64-1.031-.64-1.141zM.026 10.125l.625 1.063.641-1.032-.641-1.14zm1.516 0l.625 1.063.64-1.032-.64-1.14zm1.484 0l.625 1.063.641-1.032-.641-1.14zm1.592 0l.625 1.063.64-1.032-.64-1.14z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f43e4a7e1c7ec058f38d9ca4f86d42daef540c9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e7-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1B26" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#003E87" d="M.555 7C.211 7.59 0 8.268 0 9v18c0 .732.211 1.409.555 2h34.891c.343-.591.554-1.268.554-2V9c0-.732-.211-1.41-.555-2H.555z"/><circle fill="#FFF" cx="18" cy="18" r="10"/><circle fill="#730900" cx="18" cy="18" r="9"/><circle fill="#FFF" cx="18" cy="18" r="8.743"/><ellipse fill="#007F00" cx="18" cy="9" rx=".51" ry=".657"/><ellipse fill="#007F00" cx="18" cy="27" rx=".51" ry=".657"/><path fill="#007F00" d="M15.179 26.562c.094-.351.39-.575.662-.503.273.073.417.416.323.767-.094.351-.39.575-.663.503-.272-.074-.416-.417-.322-.767zM20.16 9.939c.272.073.568-.15.662-.501.094-.351-.05-.693-.322-.767-.272-.072-.568.152-.662.502-.094.352.05.694.322.766zm-7.101 15.6c.181-.315.526-.455.77-.315.244.142.294.51.113.824-.181.315-.526.455-.769.315-.245-.141-.296-.509-.114-.824zm9.113-14.766c.244.141.588.001.77-.313.182-.314.131-.683-.113-.823-.244-.141-.588-.001-.77.313-.182.315-.131.683.113.823zm-10.896 13.23c.256-.257.625-.304.825-.104.199.199.152.568-.104.825-.257.257-.625.304-.825.104-.199-.199-.153-.568.104-.825zM23.9 12.1c.199.199.567.152.824-.103.257-.258.303-.626.104-.825-.199-.199-.567-.153-.824.104-.257.255-.303.624-.104.824zM9.951 22.058c.314-.181.683-.13.824.114.141.243 0 .588-.314.77-.314.182-.683.131-.824-.113-.141-.245-.001-.59.314-.771zm15.276-8.23c.141.243.508.295.822.113.315-.182.455-.526.315-.769-.142-.244-.51-.296-.824-.114-.315.181-.455.526-.313.77zM9.175 19.837c.351-.094.693.05.766.322.073.272-.152.568-.502.663-.351.094-.693-.051-.766-.323-.073-.272.151-.568.502-.662zM26.06 15.84c.072.273.414.417.766.323.351-.095.574-.391.502-.663-.073-.271-.416-.416-.766-.322-.351.093-.575.39-.502.662z"/><ellipse fill="#007F00" cx="9" cy="18" rx=".657" ry=".51"/><path fill="#007F00" d="M26.344 18c0 .282.293.51.656.51s.656-.228.656-.51-.293-.51-.656-.51-.656.228-.656.51zM9.438 15.179c.351.094.575.39.503.662-.073.273-.416.417-.767.323-.351-.094-.575-.39-.503-.663.074-.272.417-.416.767-.322zM26.06 20.16c-.073.272.15.568.501.662.351.094.693-.05.767-.322.072-.272-.152-.568-.502-.662-.351-.094-.693.05-.766.322zm-15.599-7.102c.314.181.455.526.314.77-.142.244-.51.295-.824.113-.314-.181-.455-.526-.314-.769.141-.245.509-.296.824-.114zm14.766 9.114c-.141.243-.001.588.313.77.314.182.683.13.823-.113.141-.244.001-.589-.313-.771-.315-.182-.683-.13-.823.114zm-13.23-10.897c.257.256.304.625.104.825-.199.199-.568.152-.825-.104-.257-.257-.304-.626-.104-.825.199-.199.568-.152.825.104zM23.9 23.9c-.199.199-.152.566.104.824.258.256.626.303.825.104s.153-.568-.104-.824c-.256-.258-.625-.303-.825-.104zM13.942 9.95c.181.314.13.683-.114.824-.243.141-.588 0-.769-.314-.182-.314-.131-.683.113-.824.244-.141.589 0 .77.314zm8.23 15.276c-.243.141-.295.509-.113.823.182.315.526.454.77.314.244-.141.296-.509.114-.823-.182-.315-.527-.455-.771-.314zM16.163 9.174c.094.351-.05.693-.322.766-.272.073-.568-.152-.663-.502-.094-.351.051-.693.323-.766.272-.073.568.152.662.502zM20.16 26.06c-.273.073-.417.415-.323.767.095.35.391.574.663.501.271-.073.416-.415.322-.766-.093-.351-.39-.576-.662-.502z"/><path fill="#B34B00" d="M14.96 12.198l.992 1.693h1.087l.487.391.3 1.036-1.076-.472 1.004.822-.242.824h.827v-1.463l1.35-.827-.223-.166-1.12.626-.13-.914-.202-.217.688-.849-.355-.144-.52.77-.073-.626.073-.773s-.346-.275-.314-.185c.032.09 0 .68 0 .68l-.65-.698-.301.12.653.579-.759.566-.921-.253.177-.939h-.189l-.163.885-.163-.754-.236.417m3.487-1.037h.217v.813h-.217zm1.138.163h.271v.433h-.271z"/><path fill="#FFF" d="M16.16 13.159c.033.082.179.479.179.479l1.045.108.443.455-.174-.522-.269-.604-1.224.084z"/><path fill="#289400" d="M14.981 11.308c.629-.378 1.039.253 1.039.253s.26-.795 1.037-.849c.776-.054.77.289.77.289s.172-.499 1.209-.295c1.038.204 1.006.548.832.692-.174.145-1.745.054-1.745.054s.162.307.18.433c.018.127.578-.234 1.462 0 0 0 .435-.758 1.103-.361.669.398 1.106 1.156.941 1.373-.164.217-1.357.072-1.492-.072 0 0-.242.398-.803.325-.561-.072-1.5-.668-1.5-.668l-.188-.29s-.436-.343-.964-.361c-.528-.017-.896 0-.896 0s-.356.416-.771.47c-.415.055-.848.036-.848.036s-.087-.595.634-1.029z"/><path fill="#289400" d="M15.711 12.464c1.039-.163 1.725 0 1.797.506.072.506-.775.416-.947.434-.173.018-1.167.361-1.491.343-.325-.018-.994-.343-.506-.812.488-.471 1.147-.471 1.147-.471zm3.979.921c1.022.238 1.504.795 1.268 1.03-.234.234-.837.199-1.385 0s-1.308-.054-1.478-.434c-.171-.379.435-.867 1.595-.596zm-.348 1.301c.776.127.804.812.678.939-.127.126-1.319-.036-1.589-.361-.272-.325.143-.704.911-.578zm-2.886-.344c.968-.366 1.383.055 1.371.434-.011.379-.823.361-1.14.506-.316.145-.894.325-1.092.108-.2-.217.096-.759.861-1.048z"/><path fill="#ADADAD" d="M15.792 24.336c-.27.266-.677.82.197.99.875.17.534-.69.35-.832-.185-.144-.547-.158-.547-.158z"/><path fill="#69F" d="M16.227 24.584c.018.053.126.307 0 .451-.127.145-.343.254-.542.234 0 0 .849.145 1.029.236.181.088.343-.182.253-.561-.09-.378-.74-.36-.74-.36z"/><path fill="#EEE" d="M21.753 22.832c-.47 0-1.102.379-1.102.379s-.289-.289-.759-.037c-.47.254-.74.326-.704.795 0 0-.256.131-.506.199-.397.109-.668.017-.668.017s-.271.092-.668-.017c-.25-.068-.505-.199-.505-.199.036-.469-.235-.541-.705-.795-.47-.252-.759.037-.759.037s-.632-.379-1.102-.379c-.47 0-.885.451-.867.578.018.127.235.559.361.775.126.217.235.344.578.344.343 0 1.065-.217 1.065-.217s.163.162 1.012.488c.849.324 1.589.307 1.589.307s.74.018 1.589-.307c.849-.326 1.012-.488 1.012-.488s.723.217 1.066.217c.343 0 .451-.127.578-.344.126-.217.344-.648.361-.775.019-.127-.396-.578-.866-.578z"/><path fill="#ADADAD" d="M15.458 23.27c.346.234 1.068.564 1.383.699 0 0 .112-.305-.167-.48-.279-.178-.684-.338-.881-.416-.199-.079-.335.197-.335.197zm.136 1.066c-.487-.438-.794-.601-1.156-.674-.361-.072-.784.061-.771.338.012.277.358.566.681.529.321-.035 1.246-.193 1.246-.193z"/><path fill="#69F" d="M15.594 23.373s.018-.342.253-.199c.235.146.163.406.163.406l-.416-.207zm-.325.85s-.614-.451-.885-.451c-.272 0-.542.018-.524.225.018.209.38.299.579.334.198.036.83-.108.83-.108z"/><path fill="#ADADAD" d="M20.236 24.336c.271.266.678.82-.196.99-.876.17-.534-.69-.351-.832.186-.144.547-.158.547-.158z"/><path fill="#69F" d="M19.803 24.584c-.018.053-.127.307 0 .451.126.145.343.254.541.234 0 0-.849.145-1.029.236-.181.088-.343-.182-.252-.561.089-.378.74-.36.74-.36z"/><path fill="#ADADAD" d="M20.571 23.27c-.348.234-1.068.564-1.383.699 0 0-.112-.305.167-.48.279-.178.685-.338.881-.416.199-.079.335.197.335.197zm-.136 1.066c.487-.438.794-.601 1.156-.674.36-.072.783.061.771.338-.013.277-.358.566-.681.529-.323-.035-1.246-.193-1.246-.193z"/><path fill="#69F" d="M20.435 23.373s-.018-.342-.252-.199c-.236.146-.163.406-.163.406l.415-.207zm.325.85s.614-.451.885-.451.542.018.524.225c-.018.209-.38.299-.578.334-.199.036-.831-.108-.831-.108z"/><path fill="#D3D3D3" d="M15.017 23.266c.422.164 1.102.902 0 .434-1.103-.471-.651-.688 0-.434zm1.462.867c.479.131 1.282.27 1.734.27.451 0 .74.471.18.416-.56-.055-1.716-.176-2.113-.34-.397-.167-.194-.456.199-.346zm2.854.052c.505-.269 1.463-.865 1.788-.939.325-.072.723-.035.687.127-.036.164-.235.252-.542.289-.308.037-1.301.867-1.933.957-.631.092 0-.434 0-.434z"/><path fill="#289400" d="M13.047 21.277c.996-.199 5.491-.324 6.773-.162 1.283.162 4.083.94 3.721 1.391-.36.451-1.914.416-2.799.271-.885-.145-1.229.633-2.728.65-1.5.018-2.258-.471-2.89-.705-.632-.234-1.535-.108-2.077.055s-2.33-1.029 0-1.5z"/><path d="M15.359 16.275v3.414c0 1.246.939 2.258 1.327 2.619.389.359 1.328.885 1.328.885s.939-.525 1.327-.885c.389-.361 1.327-1.373 1.327-2.619v-3.414h-5.309z"/><path fill="#9ED7FF" d="M15.63 16.492v3.201c0 1.119.843 2.137 1.192 2.461.349.324 1.192.795 1.192.795s.843-.471 1.191-.795c.349-.324 1.192-1.342 1.192-2.461v-3.201H15.63z"/><path fill="#006AC8" d="M16.456 21.748h3.118c.122-.154.25-.336.369-.541h-3.856c.118.205.247.387.369.541z"/><path fill="#5AC800" d="M16.456 21.748c.141.178.272.318.367.406.064.06.146.123.235.189h1.915c.09-.066.171-.129.234-.189.095-.088.226-.229.367-.406h-3.118z"/><path fill="#FFD801" d="M18.015 22.949s.561-.314.957-.605h-1.915c.396.291.958.605.958.605z"/><path fill="#FFF" d="M15.825 20.664l2.19-1.951v-2.221H15.63v3.201c0 .338.078.668.195.971z"/><path fill="#FFD83C" d="M20.203 20.664c.118-.303.195-.633.195-.971v-3.201h-2.384v2.221l2.189 1.951z"/><path fill="#B34B00" d="M17.703 18.327l-.011-.01c-.031-.032-.083-.032-.115 0l-.068.068-.473-.473c.056-.075.062-.167.011-.218l-.958-.941c-.058-.058-.168-.04-.246.039-.077.079-.093.188-.035.245l.958.942c.04.039.104.042.165.016l.483.483-.099.1c-.032.032-.032.083 0 .116l.011.01c.031.031.083.031.115 0l.261-.262c.033-.032.033-.084.001-.115z"/><path fill="#782121" d="M16.167 18.817c-.037.049-.107.059-.156.021-.049-.037-.058-.106-.021-.155l1.025-1.339c.037-.049.107-.058.155-.021.049.038.058.107.021.156l-1.024 1.338z"/><path fill="#D3D3D3" d="M16.836 17.16l.285-.45.6.38-.286.45z"/><path fill="#782121" d="M20.001 18.656c.041.045.112.049.157.007.045-.041.049-.111.007-.156l-1.137-1.246c-.042-.045-.112-.048-.157-.007s-.049.111-.007.157l1.137 1.245z"/><path fill="#FFF" d="M18.216 17.34l.515-.488.367.387-.515.488zm.214.8l1.345-1.292.338.352-1.346 1.291z"/><path fill="#B34B00" d="M16.687 20.598s.73.336 1.355.351.781-.088.781-.088l-.178.346h-1.523l-.435-.609z"/><path fill="#FFF" d="M16.927 20.551l.383.275h1.417l-.192-.937-1.225.058z"/><path fill="#892614" d="M14.221 13.742c.42-.203 1.219-.65 1.341-.718s.325.176.136.258c-.19.081-1.192.677-1.477.812-.284.135 0-.352 0-.352z"/><path fill="#FBD44D" d="M12.758 21.658c-.054.397-.289.795.163.92.451.127.536-.293.413-.67-.124-.377-.576-.25-.576-.25zm1.572-.021c-.072.166-.289.529.144.482.434-.047.705-.043.975 0 .272.045.434-.25.145-.238-.289.012-.506-.094-.615-.363-.108-.268-.649.119-.649.119zm-1.061-4.991l-.129-.7s-.365.373-.491.554c-.126.181-.377-.081-.522-.199-.145-.117-.307-.478-.343-.785-.036-.307-.398-.487-.271-.704.126-.217.235-.325.452-.325.216 0 .271.289.271.289s.418.053.253.253c-.406.493-.085.576-.085.576l.246-.305s-.091-.578 0-.686c.091-.109.633-.307.814-.326.181-.018.398-.18.316-.289-.081-.108-.262-.307-.262-.543 0-.234-.082-.74.447-.667.529.072.71.415.565.704-.145.289-.216.379-.163.542.054.163.07.361.423.379.353.018.421.131.475.438.054.307.059.465.041.718-.019.253.001.343.001.343s.324-.063.558-.027c.235.036.723.335.723.335h-1.174l-.09.38s-.127.145-.181.126c-.054-.019-.353-.488-.353-.488l-.134.488-1.387-.081z"/><path fill="#D3D3D3" d="M13.173 16.601c-.198.433-.379 1.372-.343 1.877.036.505.135 1.029-.005 1.498-.14.471-.338 1.807-.338 1.807l.506.344.56-.361.09-2.113.32-1.046.312.757-.127 2.348.921-.017s-.073-2.168-.091-2.51c-.018-.343-.146-1.391-.19-1.716-.044-.325-.134-.74-.134-.74l-1.481-.128z"/><path fill="#9B5F00" d="M13.21 16.51s.372.102.754.091c.399-.012.809-.137.817-.091.019.091 0 .398 0 .398s-.335-.073-.781 0c-.446.072-.627.054-.79 0-.163-.054 0-.398 0-.398z"/><path d="M14.09 12.5c.398 0 .571.307.553.632-.018.325-.116.416-.116.416s.065-.352-.143-.181v-.343s-.452.036-.605 0c-.154-.036-.244-.072-.244-.072l-.063.244s-.209-.244-.01-.479c.199-.234.534-.217.534-.217"/><path fill="#892614" d="M11.038 15.449c.184-.271.515-.474.515-.474s.054.067.244 0c.19-.068.176-.122.285-.163.108-.041.095-.163.095-.163s.637-.258.908-.38.583-.311.583-.311l.122.095s0 .203-.108.27c-.109.068-.921.475-.989.529-.068.054-.217.108-.217.108s-.067-.136-.135-.081c-.068.054-.109.203-.109.203s-.271.122-.434.231c-.163.108-.352.488-.528.569-.178.081-.301-.331-.232-.433z"/><path fill="#D3D3D3" d="M14.935 13.282c.099-.095.464-.351.553-.216.088.135.224.88.657.812 0 0-.257.23-.474.338-.217.108-.601.136-.601.136s-.005-.352 0-.555c.005-.204-.135-.515-.135-.515z"/><path fill="#B34B00" d="M19.139 12.32c.149-.068 1.619.718 1.866.826s.396.542.641.637c.243.095.04.257-.108.176-.149-.082-.475-.054-.76-.149-.284-.095-1.806-.906-1.847-1.027-.04-.122.208-.463.208-.463z"/><path fill="#892614" d="M23.226 21.658c.054.397.289.795-.163.92-.451.127-.535-.293-.411-.67.121-.377.574-.25.574-.25zm-1.572-.021c.072.166.288.529-.145.482-.434-.047-.704-.043-.976 0-.271.045-.433-.25-.144-.238.288.012.507-.094.614-.363.11-.268.651.119.651.119zm1.061-4.991l.129-.7s.29.291.417.472c.126.18.421.2.564.082.146-.117.34-.677.376-.983.035-.307.378-.253.251-.47-.126-.217-.261-.356-.478-.356s-.225.085-.225.085-.276.072-.168.307c.108.235-.032.55-.032.55l-.215-.184s-.068-.691-.159-.799c-.092-.109-.474-.343-.654-.362-.181-.018-.397-.18-.316-.289.082-.108.262-.307.262-.543 0-.234.083-.74-.446-.667-.529.072-.71.415-.564.704.143.289.121.397.067.56-.055.162.024.343-.329.361-.352.018-.471.204-.525.511-.054.307-.008.392.01.645.019.253-.002.343-.002.343s-.323-.063-.558-.027c-.235.036-.723.335-.723.335h1.174l.091.38s.126.145.181.126c.055-.019.352-.488.352-.488l.135.488 1.385-.081z"/><path fill="#D3D3D3" d="M22.81 16.601c.198.433.379 1.372.343 1.877-.036.505-.136 1.029.005 1.498.14.471.338 1.807.338 1.807l-.505.344-.56-.361-.09-2.113-.32-1.046-.312.757.127 2.348-.922-.017s.072-2.168.091-2.51c.019-.343.146-1.391.19-1.716.045-.325.135-.74.135-.74l1.48-.128z"/><path fill="#9B5F00" d="M22.773 16.51s-.371.102-.753.091c-.398-.012-.809-.137-.818-.091-.017.091 0 .398 0 .398s.336-.073.782 0c.446.072.627.054.789 0 .164-.054 0-.398 0-.398z"/><path d="M21.894 12.5c-.396 0-.571.307-.553.632.018.325.111.416.111.416s-.078-.352.139-.181v-.343s.456.036.609 0c.154-.036.247-.072.247-.072l.063.244s.208-.244.01-.479c-.199-.234-.533-.217-.533-.217"/><path fill="#B34B00" d="M22.205 13.959l1.484.797s-.197-.001-.193.17c.005.171-1.215-.574-1.215-.574l-.076-.393zm2.081 1.192l.461.149s.055-.149.189-.075c.136.075-.067.678-.162.668-.095-.011-.203-.16-.217-.281-.014-.122-.42-.285-.42-.285l.149-.176z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d9c386dbe868dd1ead9fc22419a30a7c267cf3b0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D52B1E" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h6V5H4zm28 0h-6v26h6c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M10 5h16v26H10z"/><path fill="#D52B1E" d="M18.615 22.113c1.198.139 2.272.264 3.469.401l-.305-1.002c-.049-.176.021-.368.159-.476l3.479-2.834-.72-.339c-.317-.113-.23-.292-.115-.722l.531-1.936-2.021.427c-.197.03-.328-.095-.358-.215l-.261-.911-1.598 1.794c-.227.288-.687.288-.544-.376l.683-3.634-.917.475c-.257.144-.514.168-.657-.089l-1.265-2.366v.059-.059l-1.265 2.366c-.144.257-.401.233-.658.089l-.916-.475.683 3.634c.144.664-.317.664-.544.376l-1.598-1.793-.26.911c-.03.12-.162.245-.359.215l-2.021-.427.531 1.936c.113.43.201.609-.116.722l-.72.339 3.479 2.834c.138.107.208.3.158.476l-.305 1.002 3.47-.401c.106 0 .176.059.175.181l-.214 3.704h.956l-.213-3.704c.002-.123.071-.182.177-.182z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..ce130d70b993bc88869f46d885b5338587cdb521 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="green" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path d="M30.529 19.661l.17.583h.587l-.464.358.171.567-.464-.357-.464.34.17-.55-.464-.358h.573zm-1.531-6.504l-.679.627.068-.921-.914-.139.762-.523-.46-.801.884.27.339-.859.339.859.884-.27-.46.801.761.522-.913.14.068.921zm-3.623 5.313l-.679.627.068-.922-.914-.139.762-.522-.46-.802.884.271.339-.859.339.859.884-.271-.46.802.761.522-.913.139.068.922zm7.11-.439l-.678.627.067-.922-.914-.139.763-.522-.46-.802.883.271.339-.859.339.859.884-.271-.46.802.762.522-.913.139.067.922zm-3.547 7.74l-.678.627.067-.921-.914-.139.763-.523-.46-.801.884.27.338-.859.339.859.884-.27-.46.801.762.522-.913.14.067.921zm-8.573-3.831c-2.175 0-3.94-1.766-3.94-3.941 0-2.177 1.765-3.94 3.94-3.94.828 0 1.594.258 2.228.695-.905-1.039-2.235-1.699-3.724-1.699-2.731 0-4.944 2.214-4.944 4.945 0 2.73 2.213 4.945 4.944 4.945 1.488 0 2.819-.66 3.727-1.7-.635.437-1.403.695-2.231.695zM11.973 12c0 2.809-2.276 5.086-5.085 5.086S1.801 14.809 1.801 12s2.277-5.086 5.086-5.086S11.973 9.191 11.973 12z" fill="#FFE000"/><path fill="#802000" d="M7.144 16H6.01s.372-.352.567-.67c.195-.319.973-2.012.885-3.557-.087-1.545.178-1.287.267-.365.089.921 0 2.812-.159 3.362-.16.549-.336.899-.106.97.229.071.3.26.3.26h-.62z"/><path fill="green" d="M5.177 8.919h.691l1.418 1.348-.479-.869.436-.271.131-1.075 1.187-.107-.159.603.62.319-.691 1.009 1.506-.141-.283.886h.815l.337 1.116-1.985-.159.992.744v1.134l-2.091-1.967-.177.833-.124.833-.458.137-.109-.633-.479.797h-.637l.62-2.248-3.19.6.851-1.027 1.683-.338-1.488-.779 2.197.39-2.268-1.135z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1b15c995f7de393e476b43fda77fb9a3007cc4d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#007FFF" d="M4 31h28c2.209 0 4-1.791 4-4V11.25L3.215 30.921c.254.05.516.079.785.079zM32 5H4C1.791 5 0 6.791 0 9v15.75L32.785 5.079C32.531 5.029 32.269 5 32 5zM9.63 16.02l-3.06-2.34-3.06 2.34 1.17-3.78L1.62 9.9H5.4l1.17-3.78L7.74 9.9h3.78l-3.06 2.34 1.17 3.78z"/><path fill="#F7D618" d="M7.74 9.9L6.57 6.12 5.4 9.9H1.62l3.06 2.34-1.17 3.78 3.06-2.34 3.06 2.34-1.17-3.78 3.06-2.34zM3.215 30.921L36 11.25V9.9L1.873 30.376c.406.256.856.448 1.342.545zm29.57-25.842L0 24.75v1.35L34.127 5.624c-.406-.256-.856-.448-1.342-.545z"/><path fill="#CE1021" d="M34.127 5.624L0 26.1v.9c0 1.425.751 2.668 1.873 3.376L36 9.9V9c0-1.425-.751-2.668-1.873-3.376z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..72166cbe0bfa35e739b8a996d2b1cb2bdf48ddd4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#003082" d="M32 5H4C1.791 5 0 6.791 0 9v2.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 11.5h36V18H0z"/><path fill="#289728" d="M0 18h36v6.5H0z"/><path fill="#FFCE00" d="M0 24.5V27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-2.5H0z"/><path fill="#D21034" d="M15 5h6v26h-6z"/><path fill="#FFCE00" d="M6.878 7.612l-.68-2.094-.681 2.094H3.316l1.781 1.294L4.417 11l1.781-1.294L7.979 11l-.681-2.094L9.08 7.612z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..3d466e3da26bcff4c5f5f6ad9af2e3ee1523d415 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009543" d="M4 5C1.791 5 0 6.791 0 9v18c0 1.104.448 2.104 1.172 2.828L26 5H4z"/><path fill="#FBDE4A" d="M32 5h-6L1.172 29.828C1.896 30.552 2.896 31 4 31h6L34.828 6.172C34.104 5.448 33.104 5 32 5z"/><path fill="#DC241F" d="M10 31h22c2.209 0 4-1.791 4-4V9c0-1.104-.448-2.104-1.172-2.828L10 31z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..741b52144d76ac6eac0f6ad093c66677bb82686c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D32D27" d="M31 27c0 2.209-1.791 4-4 4H9c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h18c2.209 0 4 1.791 4 4v18z"/><path fill="#FFF" d="M25 16.063h-5v-5h-4v5h-5V20h5v5.063h4V20h5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..bd2c3e06203171e286bd78fc0e5232019832d4d4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F77F00" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#009E60" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..04e034448c24c2cb59573aee24e6fa47b4b662ef --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M27.803 11.783l.812-.59h-1.004l-.31-.955-.31.955h-1.004l.812.59-.31.954.812-.589.812.589zm2.562.741l.982-.208-.917-.409.105-.998-.672.746-.916-.409.501.87-.672.745.982-.208.502.869zm2.05 1.762l.983.206-.674-.744.5-.87-.916.41-.673-.745.107.998-.916.411.982.206.107.998zm1.144 2.4l.816.585-.316-.953.809-.594-1.003.006-.316-.953-.305.956-1.003.005.815.586-.305.956zm.081 2.69l.503.868.103-.998.982-.211-.918-.406.103-.999-.67.747-.918-.406.504.868-.671.747zm-1.038 2.446l.105.998.502-.869.982.209-.672-.746.503-.869-.917.408-.672-.747.105.999-.917.407zm-1.938 1.88l-.306.956.809-.593.815.587-.314-.954.809-.593-1.003.004-.314-.953-.307.956-1.003.004zm-2.52.879l-.669.748.981-.212.505.867.101-.998.981-.213-.919-.405.102-.998-.669.748-.919-.405zm-3.906-12.057l-.982-.208.917-.409-.105-.998.671.746.917-.409-.502.87.672.745-.982-.208-.501.869zm-2.051 1.762l-.982.206.673-.744-.5-.87.916.41.673-.745-.107.998.916.411-.982.206-.107.998zm-1.144 2.4l-.815.585.315-.953-.809-.594 1.004.006.315-.953.305.956 1.004.005-.815.586.305.956zm-.08 2.69l-.503.868-.104-.998-.981-.211.918-.406-.104-.999.671.747.917-.406-.503.868.67.747zM22 21.822l-.104.998-.502-.869-.982.209.671-.746-.502-.869.917.408.671-.747-.104.999.917.407zm1.939 1.88l.306.956-.81-.593-.814.587.314-.954-.81-.593 1.004.004.314-.953.306.956 1.004.004zm2.52.879l.669.748-.981-.212-.505.867-.101-.998-.981-.213.918-.405-.101-.998.669.748.918-.405z" fill="#FFF"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..52b3a007d3f8aebe01b82927d3c1c9d58a72f59e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#1F429B" d="M13 5H4C1.791 5 0 6.791 0 9v9h13V5zm-4.663 9.292l-1.882-1.367-1.882 1.367.719-2.212-1.882-1.368h2.326L6.455 8.5l.719 2.212H9.5L7.618 12.08l.719 2.212z"/><path fill="#EEE" d="M32 5H13v13h23V9c0-2.209-1.791-4-4-4z"/><path fill="#D42D27" d="M0 18v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0z"/><path fill="#FFF" d="M7.174 10.712L6.455 8.5l-.719 2.212H3.41l1.882 1.368-.719 2.212 1.882-1.367 1.882 1.367-.719-2.212L9.5 10.712z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..7da7b66a7d46bd1d5ed2f2451d7ddabe45b830f4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CC212D" d="M12 5v26h12V5H12zm7.882 15.59L18 19.223l-1.882 1.367.719-2.212-1.882-1.367h2.326L18 14.798l.719 2.212h2.326l-1.882 1.367.719 2.213z"/><path fill="#288541" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FEE833" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4zM18.719 17.011L18 14.798l-.719 2.213h-2.326l1.882 1.367-.719 2.212L18 19.223l1.882 1.367-.719-2.212 1.882-1.367z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..c10116d0a2821663b17d8e44d8dcc39018eddf52 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DE2910" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFDE02" d="M11.136 8.977l.736.356.589-.566-.111.81.72.386-.804.144-.144.804-.386-.72-.81.111.566-.589zm4.665 2.941l-.356.735.566.59-.809-.112-.386.721-.144-.805-.805-.144.721-.386-.112-.809.59.566zm-.957 3.779l.268.772.817.017-.651.493.237.783-.671-.467-.671.467.236-.783-.651-.493.817-.017zm-3.708 3.28l.736.356.589-.566-.111.81.72.386-.804.144-.144.804-.386-.72-.81.111.566-.589zM7 10.951l.929 2.671 2.826.058-2.253 1.708.819 2.706L7 16.479l-2.321 1.615.819-2.706-2.253-1.708 2.826-.058z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..dc825d2463fdc2fd12ecf525e56cef1295040aca --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FBD116" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#22408C" d="M0 18h36v7H0z"/><path fill="#CE2028" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-2H0v2z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..4eafe7aa5b829db665fd04bc0c35c1254f13b444 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED2939" d="M36 27c0 2.209-1.791 4-4 4h-8V5h8c2.209 0 4 1.791 4 4v18z"/><path fill="#002495" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..acecc89523ebb37c0a81255340b389ddc3a9a87e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002B7F" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 9h36v18H0z"/><path fill="#CE1225" d="M0 13h36v10H0z"/><ellipse fill="#EEE" cx="8.5" cy="18" rx="3.5" ry="4"/><path fill="#F4CB58" d="M10.269 19.5c0 .828-.792 2.079-1.769 2.079S6.731 20.328 6.731 19.5c0-.829.792-1.5 1.769-1.5s1.769.671 1.769 1.5z"/><ellipse fill="#DCA841" cx="8.5" cy="19.5" rx="2.5" ry="1.5"/><ellipse fill="#89C5E4" cx="8.5" cy="16" rx="1.5" ry="1"/><ellipse fill="#088930" cx="8.5" cy="18.5" rx="1.5" ry="2.5"/><ellipse fill="#DCA841" cx="8.5" cy="16.5" rx="1.5" ry=".5"/><path fill="#89C5E4" d="M10 18c0 1.104-.671 2-1.5 2S7 19.104 7 18s.671-1.498 1.5-1.498S10 16.896 10 18z"/><ellipse fill="#DCA841" cx="8.5" cy="18.5" rx="1.5" ry=".5"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..13b637014bd27056fd3d1a6d95946ad9ff2a582b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002A8F" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M13.846 15H36v-5H6.923zM6.923 26H36v-5H13.846z"/><path fill="#CF142B" d="M13.846 15l-6.923-5-5.541-4.002C.542 6.731 0 7.797 0 9v18c0 1.203.542 2.269 1.382 3.002L6.923 26l6.923-5L18 18l-4.154-3z"/><path fill="#FFF" d="M7.495 18.602L9.5 17.149H7.022l-.769-2.362-.772 2.362H3l2.006 1.454-.771 2.36 2.015-1.459 2.015 1.459z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b2cc18dfdd92692d6718e7f9871338e04632c3a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#003893" d="M32 5H4C1.791 5 0 6.791 0 9v10h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 19h36v2H0zm0 5h36v2H0z"/><path fill="#CF2027" d="M0 21v3h36v-3H0z"/><path fill="#003893" d="M4 31h28c2.209 0 4-1.791 4-4v-1H0v1c0 2.209 1.791 4 4 4z"/><path fill="#F7D116" d="M14.347 15.903l.764-.555h-.944l-.292-.898-.292.898h-.944l.764.555-.292.899.764-.555.764.555zm6.182 4.492l.764-.555h-.944l-.292-.899-.292.899h-.945l.765.555-.292.898.764-.555.764.555zm-12.364 0l.765-.555h-.945l-.292-.899-.292.899h-.944l.764.555-.292.898.764-.555.764.555zm0 4.017l.765-.555h-.945l-.292-.898-.292.898h-.944l.764.555-.292.898.764-.555.764.555zm12.364 0l.764-.555h-.944l-.292-.898-.292.898h-.945l.765.555-.292.898.764-.555.764.555zm-6.362 3.936l-.292-.898-.292.898h-.944l.764.555-.292.899.764-.555.764.555-.292-.899.764-.555zm4.001-.686l.764-.555h-.945l-.291-.898-.292.898h-.945l.764.555-.292.898.765-.555.764.555zm0-10.504l.764-.555h-.945l-.291-.898-.292.898h-.945l.764.555-.292.898.765-.555.764.555zM9.582 27.662l-.764-.555h.945l.291-.898.292.898h.945l-.764.555.292.898-.765-.555-.764.555zm0-10.504l-.764-.555h.945l.291-.898.292.898h.945l-.764.555.292.898-.765-.555-.764.555z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..c53d09f79e1a1f6d0fdfa69b24325223ad8bc8d6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002B7F" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-2H0v2z"/><path fill="#F9E814" d="M0 21h36v4H0z"/><path fill="#002B7F" d="M32 5H4C1.791 5 0 6.791 0 9v12h36V9c0-2.209-1.791-4-4-4zM4 9.764l-1.176.854.449-1.382-1.175-.854h1.453L4 7l.449 1.382h1.453l-1.175.854.449 1.382L4 9.764zm5.567 5.393L8 14.019l-1.567 1.139.599-1.843-1.567-1.139h1.937L8 10.333l.599 1.843h1.937l-1.567 1.139.598 1.842z"/><path fill="#FFF" d="M8.599 12.176L8 10.333l-.599 1.843H5.464l1.567 1.139-.598 1.842L8 14.019l1.567 1.138-.598-1.842 1.567-1.139zM5.902 8.382H4.449L4 7l-.449 1.382H2.098l1.175.854-.449 1.382L4 9.764l1.176.854-.449-1.382z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fd.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fd.svg new file mode 100644 index 0000000000000000000000000000000000000000..6a322f57747d60920df35eb6bece1ca09b4d5028 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0021AD" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#1B8A42" d="M34.618 30.002C35.458 29.269 36 28.202 36 27V9c0-2.209-1.791-4-4-4H4c-1.006 0-1.915.384-2.618.998l33.236 24.004z"/><path d="M8.52 22.262l.169.584h.587l-.464.357.171.567-.463-.358-.464.342.17-.551-.464-.357h.572zm-1.532-6.504l-.678.627.067-.921-.914-.139.763-.523-.46-.801.883.27.339-.859.339.859.884-.27-.46.801.762.522-.913.14.067.921zM3.365 21.07l-.678.627.067-.921-.914-.139.763-.522-.46-.802.883.271.339-.859.339.859.884-.271-.46.802.762.522-.913.139.067.921zm7.111-.438l-.679.627.067-.921-.914-.14.763-.522-.46-.801.884.27.339-.859.338.859.884-.27-.46.801.762.521-.913.141.067.921zm-3.547 7.741L6.25 29l.067-.922-.914-.138.763-.524-.46-.801.884.27.339-.86.339.86.883-.27-.46.801.762.522-.913.14.067.922z" fill="#FFF"/><path fill="#FFC639" d="M14.437 18c0-1.968 1.595-3.563 3.563-3.563s3.563 1.595 3.563 3.563-1.595 3.563-3.563 3.563-3.563-1.595-3.563-3.563z"/><path fill="#1B8A42" d="M15.862 16.359s1.085 1.006 1.643 1.049c.91.07 1.777-.688 1.777-1.247l.855-.361v1.12l.815.559-1.527 1.399v1.679l-.914-.222-.066-1.166s-.041-.443-.6-.443c-.56 0-.998-.035-1.114-.338-.032-.083-1.513.21-1.513.21l.959-1.337-.315-.341v-.561z"/><path fill="#FFC639" d="M29.617 6.518c.232-.182 2.409 1.969 2.668 2.384.259.415.156 1.969.415 2.669s.491.856.751.7c.259-.156 1.167 0 1.296.337 0 0-.726.441-.777.752 0 0-2.306.803-3.628 1.477-1.321.674-.979.328-2.072.804-1.607.699-3.059.362-4.12.207-1.064-.155-.753-.389 0-.284.751.104 3.004-.13 3.601-.337.596-.207 1.763-1.14 2.255-1.373.492-.233 1.114-1.088.57-1.607-.546-.521-2.178-1.247-2.826-1.947-.648-.699-.647-.803.363-.647 1.011.156 1.898.689 2.383 1.173.52.519.981-.145.669-.975-.311-.83-.745-.743-1.031-1.495-.284-.751-.751-1.657-.517-1.838z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..19bead4dd0f37eb7b1441aab263f508052fab75d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><g fill-rule="evenodd" clip-rule="evenodd" fill="#5C913B"><path d="M12.974 22.148c.013.061-.008.072-.073.053-.355-.1-.67-.26-.891-.568-.073-.1-.12-.213-.148-.334-.013-.059-.002-.09.068-.072.411.101.739.324.97.682.045.07.072.15.074.239zm8.469.069c-.021-.111.008-.213.064-.303.23-.363.562-.584.977-.69.073-.018.075.021.063.074-.052.236-.184.422-.366.572-.215.177-.464.284-.738.347zm.95.23c-.007.039-.031.068-.059.092-.294.269-.632.418-1.038.379-.102-.01-.193-.053-.278-.113-.045-.031-.042-.053-.001-.088.148-.127.319-.207.505-.256.255-.066.514-.084.776-.041.033.004.065.01.095.027zm-9.954-.049c.276.004.584.061.858.244.05.033.133.07.128.119-.006.057-.09.084-.149.109-.168.074-.341.072-.515.031-.262-.062-.499-.174-.689-.369-.023-.023-.059-.051-.046-.084.01-.025.053-.023.083-.029.094-.019.189-.021.33-.021zm1.091-.384c0 .094-.012.184-.044.271-.019.051-.042.059-.087.025-.142-.105-.227-.25-.285-.412-.096-.267-.141-.541-.072-.822.024-.098.035-.1.104-.027.256.271.36.601.384.965zm7.35-.03c.028-.338.13-.666.383-.932.073-.078.087-.076.106.027.079.412.004.793-.25 1.131-.039.053-.099.131-.154.115-.066-.018-.062-.115-.074-.184-.01-.043-.007-.09-.011-.157zm-2.228.62c.032.551-.229.947-.604 1.303-.119-.432.093-1.097.604-1.303zm-2.282 1.314c-.362-.352-.628-.723-.614-1.236.002-.076.026-.078.085-.043.35.209.508.529.546.92.012.111.011.224-.017.359zm3.627-1.908c.067.193.059.387.02.582-.048.24-.143.457-.325.629-.09.084-.104.082-.151-.035-.059-.146-.053-.297-.016-.445.066-.266.2-.494.399-.682.014-.014.027-.025.042-.037l.031-.012zm-5.59-.008c.333.223.567.764.488 1.1-.015.066-.028.156-.085.174-.053.016-.105-.062-.145-.111-.28-.341-.351-.725-.258-1.163zm5.622 1.43c.326.02.607.137.824.391.07.082.065.09-.041.119-.271.074-.522.006-.766-.107-.135-.064-.258-.144-.366-.246-.045-.041-.044-.066.016-.09.107-.042.216-.069.333-.067zm-5.644.002c.106-.002.208.018.306.057.093.037.097.049.023.111-.208.182-.446.303-.718.353-.135.025-.269.023-.401-.016-.103-.029-.107-.035-.036-.119.163-.197.38-.307.625-.365.066-.015.134-.021.201-.021zm5.786.826c-.384.185-.944.174-1.219-.254-.038-.062-.028-.082.038-.098.456-.105.84.03 1.181.352zm-5.928.004c.209-.223.46-.342.752-.383.139-.02.276-.012.412.023.096.023.098.029.043.109-.189.277-.46.377-.782.357-.144-.007-.285-.034-.425-.106zm1.399-.922c-.004.088-.019.158-.045.228-.021.057-.045.062-.091.024-.167-.139-.278-.316-.358-.516-.082-.203-.147-.41-.11-.635.005-.027.005-.066.028-.074.032-.014.051.025.071.045.22.217.406.453.483.76.009.035.013.07.018.108l.004.06zm3.128.004c-.001-.146.043-.283.11-.414.102-.201.245-.373.407-.531.048-.045.069-.049.084.023.033.156.005.307-.037.455-.076.266-.195.508-.407.697-.078.068-.085.064-.122-.031-.025-.065-.034-.131-.035-.199zm.662 1.398c-.199.014-.401.021-.6-.035-.272-.078-.442-.269-.564-.514-.018-.035-.02-.057.031-.057.471.002.845.195 1.127.566.006.006.008.016.012.025 0 .003-.003.007-.006.015zm-4.471.008c.061-.125.141-.201.227-.272.259-.213.55-.344.893-.342.058 0 .087.004.051.072-.174.344-.445.533-.834.539-.107.005-.214.003-.337.003zm5.395-1.932c-.132-.195-.142-.402-.091-.615.053-.228.169-.426.323-.602.042-.049.063-.041.091.01.072.133.082.273.06.42-.046.301-.177.557-.383.787zm-6.583-1.255c.311.269.553.887.286 1.244-.348-.266-.511-.977-.286-1.244zm-.502 1.863c-.141-.004-.306-.02-.451-.113-.092-.059-.09-.067-.011-.135.18-.158.393-.178.616-.145.17.025.335.074.501.117.057.016.056.035.023.074-.075.084-.175.121-.279.152-.121.036-.246.05-.399.05zm7.841 0c-.179-.004-.345-.023-.501-.098l-.05-.025c-.05-.029-.12-.062-.117-.119.003-.051.083-.043.13-.055.217-.057.432-.123.66-.105.14.012.261.064.367.154.08.068.081.076-.011.135-.148.095-.316.109-.478.113z"/><path d="M18.027 24.555c-.25-.061-.502-.121-.752-.184-.049-.012-.095-.012-.144 0-.25.064-.502.123-.755.18.158-.125.338-.205.551-.27l-.815-.283c.1-.016.165.016.231.033.262.068.526.125.792.176.114.021.22-.016.328-.037.319-.062.635-.145.952-.225-.299.125-.608.223-.936.334.208.067.389.143.548.276z"/></g><path fill-rule="evenodd" clip-rule="evenodd" fill="#F4900C" d="M25.774 11.114l-.149.073c-.268.126-.521.299-.838.278-.03-.002-.065.014-.071.048-.021.1-.097.112-.176.113-.153.003-.267.067-.356.193-.099.138-.224.244-.398.281-.056.012-.108.044-.157.074-.145.088-.299.129-.467.112-.055-.006-.091.011-.124.056-.077.103-.162.202-.244.301-.045.053-.094.106-.161.119-.224.044-.402.181-.596.286-.362.196-.726.39-1.132.485-.168.039-.346.087-.51.043-.135-.036-.218.009-.309.075-.056.039-.11.08-.158.127-.189.184-.409.266-.673.232-.049-.007-.098-.006-.143.019-.22.12-.468.123-.706.169-.108.022-.219-.017-.322.008-.246.057-.487-.01-.726-.032-.177-.017-.351-.058-.53-.029-.109.018-.202-.009-.282-.081-.078-.07-.157-.075-.245-.024-.075.044-.155.047-.23.007-.088-.046-.174-.048-.267-.022-.113.031-.229.052-.345.014-.271-.087-.551-.151-.811-.271-.125-.058-.125-.054-.113.088.014.165.071.323.065.492-.008.231-.018.461-.036.692-.026.343-.204.574-.498.735-.111.061-.21.061-.322.007-.204-.1-.405-.206-.619-.286-.273-.102-.541-.127-.816-.008-.094.041-.175.129-.294.099-.007-.002-.02.013-.028.021-.096.1-.196.197-.233.337-.054.201-.142.373-.344.475-.111.056-.202.15-.317.204-.158.074-.351.086-.465-.018-.135-.124-.333-.198-.396-.397-.012-.037-.055-.065-.08-.009-.054.124-.106.252-.042.39.047.101.097.2.175.28.024.025.039.055.046.089.023.116.031.233.002.348-.017.068-.006.126.03.184.026.042.074.102.051.132-.092.118-.006.192.048.277.004.008.01.017.01.026-.004.138.095.187.199.233.062.028.125.059.147.131.059.192.085.393.153.585.023.065.038.11.1.145.141.078.291.143.378.297.041.072.135.094.223.084.034-.004.076-.018.094.014.042.068.109.068.17.062.143-.016.244.045.325.154.042.057.096.092.163.113.146.049.292.098.431.162.083.039.164.053.243-.01.021-.016.045-.018.07-.014.134.025.248-.014.349-.104.041-.037.091-.062.144-.037.089.041.173.021.261 0 .097-.025.199-.033.288.018.166.094.27.248.372.404.066.1.065.209.046.32-.007.039.007.045.042.047.191.014.383.031.579.049-.017-.065-.064-.107-.098-.156-.075-.113-.123-.236-.079-.367.076-.227.24-.391.449-.49.088-.043.183-.08.272-.123.25-.123.507-.108.766-.033.136.039.297-.012.382-.119.017-.022.041-.029.064-.031.07-.01.143-.021.211 0 .073.025.132.025.186-.043.024-.029.069-.037.11-.035.027 0 .051 0 .074-.025.063-.074.151-.102.243-.123.021-.004.043-.002.059-.021.135-.169.331-.215.529-.255.071-.015.12-.044.161-.104.145-.21.289-.263.536-.198.062.017.078-.005.093-.057.026-.094.068-.182.155-.232.049-.028.061-.062.061-.111.001-.142.003-.284.006-.425.007-.328.248-.499.498-.539.153-.024.308-.007.461-.004.106.003.2.031.287.088.079.053.151.115.231.168.078.054.158.049.242.003.072-.04.105-.092.083-.174-.013-.051.013-.066.06-.063.071.005.153.023.209-.016.13-.088.262-.044.393-.035.05.003.102.002.144.028.108.07.249.063.351.149.007.006.021.001.056.001-.053-.028-.048-.058-.04-.093.018-.082 0-.161-.048-.229-.079-.113-.221-.179-.243-.336-.005-.03-.056-.056-.087-.08-.061-.047-.124-.091-.186-.137-.037-.028-.075-.06-.085-.106-.037-.181-.162-.298-.286-.418-.242-.235-.345-.517-.288-.855.018-.11.029-.224.104-.31.066-.076.145-.137.138-.25-.001-.013.011-.031.021-.039.131-.108.259-.219.45-.18.082.017.167.017.248.003.109-.017.194-.073.225-.191.016-.062.028-.129.062-.183.177-.289.435-.501.713-.683.114-.075.253-.125.38-.186.081-.038.16-.083.249-.095.057-.008.092-.034.126-.077.158-.207.328-.401.597-.471.074-.019.109-.084.136-.153.033-.09.065-.188.148-.24.259-.163.482-.398.815-.416.072-.003.111-.044.129-.112l.07-.277c.003-.004.011-.01.01-.012-.011-.007-.02-.002-.028.003z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd3b47061b8f413a2a2731770e53f7a3ff7024c0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e8-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D7141A" d="M1.383 29.973C2.084 30.628 2.998 31 4 31h28c2.209 0 4-1.791 4-4.5V18H17.5L1.383 29.973z"/><path fill="#EEE" d="M32 5H4c-1.016 0-1.94.382-2.646 1.006L17.5 18H36V9c0-2.209-1.791-4-4-4z"/><path fill="#11457E" d="M1.383 29.973L17.5 18 1.354 6.006C.525 6.739 0 7.807 0 9v17.5c0 1.48.537 2.683 1.383 3.473z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..10a539990cad59e9120117c3c5929b1e57cf21cd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCD05" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#ED1F24" d="M0 14h36v9H0z"/><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..565a7aa4f1609260f321c78429548cd6986c16ab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path d="M34.363 28.125c-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.762 0-1.201.178-1.591.383.071.638.277 1.233.613 1.744.263-.077.575-.127.979-.127 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.088 0 .157-.01.236-.015.674-.581 1.157-1.372 1.326-2.283-.386.21-.821.391-1.565.391zM36 25.383v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.002 1.233-.186 1.635-.393zm0-4.257v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.063-3.636-1.063-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.191-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789 0 1.233-.185 1.635-.392zm0-4.257v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.002 1.233-.186 1.635-.393zm0-4.258v-1.944c-.402.227-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.001 1.233-.186 1.635-.393zm-.062-4.227c-.095-.611-.317-1.177-.656-1.663-.252.071-.545.119-.919.119-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1c-1.814 0-1.82-.994-3.625-.999C.877 6.342.314 7.169.101 8.133c.377-.193.808-.356 1.535-.356 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.751 0 1.187-.168 1.574-.362z" fill="#00247D"/><path fill="#C1694F" d="M27.248 28.677c0 .179-.143.323-.322.323-.179 0-.324-.145-.324-.323V12.815c0-.178.146-.323.324-.323.179 0 .322.145.322.323v15.862z"/><path fill="#DD2E44" d="M24.656 20.364s.139-.334.627-.334c.49 0 .607.255.901.372.294.118.666.177.666.177v2.447h-2.624s-.099-.92-.255-1.37c-.157-.449-.294-1.058.039-1.254.334-.194.646-.038.646-.038z"/><path fill="#FFCC4D" d="M26.84 19.728v.352s-.675-.059-1.263-.47c-.358-.25-1.116-.559-1.703-.058-.382.322-.353 1.146-.116 1.468.233.323.469 1.058-.031.559-.499-.5-.647-1.264-.499-1.763.147-.499.47-.998 1.233-.998.765 0 1.264.411 1.616.617.306.177.794.233.763.293z"/><path fill="#FFCC4D" d="M23.895 21.499l.41-.019-.117.626s.411-.312.431-.235c.018.08.078.646.078.646l-.53-.117.313.451-.41.194s-.157-.528-.196-.781c-.04-.255.021-.765.021-.765zm.86.334l.391-.039s-.338-.764.157-.745c.549.021.176.726.176.726h.412l.059.567-.391-.235v.334l.43.411-1.136.116.293-.489-.018-.351-.274.313-.099-.608z"/><path fill="#DD2E44" d="M29.205 20.364s-.138-.334-.627-.334-.606.255-.9.372c-.294.118-.666.177-.666.177v2.447h2.625s.097-.92.254-1.37c.157-.449.293-1.058-.039-1.254-.334-.194-.647-.038-.647-.038z"/><path fill="#FFCC4D" d="M27.021 19.728v.352s.676-.059 1.263-.47c.358-.25 1.116-.559 1.704-.058.382.322.351 1.146.116 1.468-.234.323-.468 1.058.03.559.499-.5.647-1.264.499-1.763-.146-.499-.47-.998-1.233-.998-.765 0-1.264.411-1.615.617-.305.177-.793.233-.764.293z"/><path fill="#FFCC4D" d="M29.969 21.499l-.411-.019.117.626s-.411-.312-.431-.235c-.019.08-.078.646-.078.646l.527-.117-.313.451.411.194s.157-.528.197-.781c.038-.255-.019-.765-.019-.765zm-.863.334l-.392-.039s.339-.764-.157-.745c-.547.021-.175.726-.175.726h-.411l-.061.567.393-.235v.334l-.431.411 1.137.116-.295-.489.021-.351.274.313.097-.608zm-1.495-3.095c0 .39-.308.704-.685.704-.379 0-.686-.315-.686-.704 0-.389.307-.705.686-.705.378.001.685.316.685.705zm-1.301-1.546h1.232v.49H26.31z"/><path fill="#FFCC4D" d="M26.633 16.859h.586v4.523h-.586z"/><path fill="#FFCC4D" d="M26.44 21.187h.919l-.255.646.588-.313v.86l-.569-.195.49.744h-1.272l.391-.744-.567.136v-.763l.529.254z"/><path fill="#FFCC4D" d="M26.928 22.635c1.215 0 1.978.1 2.84.411 0 0 .06.511-.059.765-.116.255-2.8-.177-2.8-.177l.019-.999z"/><path fill="#FFCC4D" d="M26.963 22.635c-1.214 0-1.978.1-2.838.411 0 0-.06.511.057.765.118.255 2.8-.177 2.8-.177l-.019-.999z"/><path fill="#EEE" d="M30.078 24.33c0 .384-1.412.693-3.152.693-1.74 0-3.153-.309-3.153-.693 0-.385 1.413-.696 3.153-.696s3.152.311 3.152.696z"/><path fill="#99AAB5" d="M29.043 24.583c0 .212-.948.384-2.117.384-1.17 0-2.119-.172-2.119-.384 0-.21.949-.382 2.119-.382 1.169 0 2.117.172 2.117.382z"/><path fill="#77B255" d="M25.655 6.873l.646.803s.451-.274.471-.215c.02.059-.039.666-.039.666l.313.078-.255.803s.393-.215.372-.137c-.019.078-.117.764-.117.764l.157.098-.02.764s.157.273.157.215c0-.058.156-.998.156-.998l.216.176.076-.489.177-.842.196.313.411-1.391.216.49.489-.568.333-.02.489-.137.099.293h.45s-.234.196-.215.254c.018.059.43.274.371.294-.059.02-1.058-.079-1.058-.079l-.566.568.352.118-.53.313.451.137-.411.313.353-.039-.568.431.568.118-.764.391.176.196-.763.451-.099.313.725-.568s.588-.392.881-.568c.294-.176.529-.509 1.02-.646s1.429.02 1.429.02l-.882.47.177.274-.567.176.078.332-.941.138.02.352-.803.138-.098.333-.548.196.255.215s-.471.157-.411.176c.059.02.685.078.685.078s-.314.274-.256.274c.06 0 .842.039.842.039l-.333.235.785.039-.354.274s.646.059.646.118c0 .058-.273.352-.273.352l.567.059s-.273.293-.216.314c.061.019.804.528.804.528l-.882-.117s-.215.293-.235.234c-.018-.058-.233-.411-.233-.411l-.216.235-.234-.47s-.274.156-.256.098c.02-.059-.313-.431-.313-.431l-.078.177-.215-.529-.195.274-.373-.51-.137.215-.51-.45s-.019.294 0 .353c.02.059.373.313.373.313s-.235.098-.235.156c0 .059.471.431.471.431l-.216.157.509.431s-.47.098-.412.137c.06.039.294.352.294.352l-.195.47-.391-.607-.216.059-.04-.509-.214-.02.116-.567-.234.039-.02-.47-.099-.47-.195-.314s-.137.235-.118.293c.02.059.178.431.178.431s-.216.117-.178.176c.04.059.255.489.255.489s-.47.098-.411.098c.06 0 .216.274.216.274l-.255.098-.117.294s-.293-.333-.274-.274c.02.059-.176.607-.176.607l-.293-.333.293-1.155-.354-.098-.254.529s-.215-.254-.235-.196c-.02.059-.235.451-.235.451s-.252-.431-.233-.372c.019.058-.295.686-.295.686s-.274-.549-.274-.47c0 .078-.195.764-.195.764s-.312-.529-.294-.431c.021.098-.215.549-.215.549l-.06-.49-.43.254.489-.705.823-.764.627-.469-.414-.058s.597-.207.665-.215c.178-.02-.272-.176-.272-.176l1.096-.333s-.489-.255-.548-.196c-.059.059-.647.176-.647.176l-.078-.45-.606.254s-.099-.412-.118-.353c-.019.059-.49.313-.49.313l-.233-.254-.275.431-.314-.235-.566.176.273-.411-.313-.176.646-.411.137-.274.882.059s-.236-.314-.196-.255c.04.059.9.196.9.196l.256-.039.861.313-.705-.568-.607-.118.392-.313-.921-.332.197-.313-1.216-.313.746-.196-.51-.862 1.057.627.47-.157.236.607.431.255.077.45.216-.098.195.528.256-.079.136.373.374.019-.1-.49.156-.235-.431-.353.374-.176-.55-.451.47-.059-.666-.646.53.02-.53-.607.432-.098-.081-.782z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ef.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ef.svg new file mode 100644 index 0000000000000000000000000000000000000000..42cbb243db0bbf5aca32cb335489bd6b0d3ba16c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ef.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#6AB2E7" d="M32 5H4c-1.016 0-1.94.382-2.646 1.006L17.5 18H36V9c0-2.209-1.791-4-4-4z"/><path fill="#12AD2B" d="M32 31H4c-1.016 0-1.94-.382-2.646-1.006L17.5 18H36v9c0 2.209-1.791 4-4 4z"/><path fill="#EEE" d="M1.383 29.973L17.5 18 1.354 6.006C.525 6.739 0 7.807 0 9v17.5c0 1.48.537 2.683 1.383 3.473z"/><path fill="#D7141A" d="M6.5 14.5l.826 2.543H10l-2.163 1.572.826 2.543L6.5 19.586l-2.163 1.572.826-2.543L3 17.043h2.674L6.5 14.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ab629ba1355de8ac4eaf1b8a9cabacd34cf1c56 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C60C30" d="M32 5H15v11h21V9c0-2.209-1.791-4-4-4zM15 31h17c2.209 0 4-1.791 4-4.5V20H15v11zM0 20v6.5C0 29.209 1.791 31 4 31h7V20H0zM11 5H4C1.791 5 0 6.791 0 9v7h11V5z"/><path fill="#EEE" d="M15 5h-4v11H0v4h11v11h4V20h21v-4H15z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..750424f7b3e9bb7ff5e1aadd19a78fd1fee5f56d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006B3F" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M36 15H21V5h-6v10H0v6h15v10h6V21h15z"/><path fill="#FCD116" d="M15 5h2v26h-2z"/><path fill="#FCD116" d="M0 15h36v2H0z"/><path fill="#141414" d="M17 5h2v26h-2z"/><path fill="#141414" d="M0 17h36v2H0z"/><circle fill="#DD2E44" cx="18" cy="18" r="6"/><path d="M18 12.64l-.169.524h-.555l.451.325-.173.524.446-.325.445.325-.171-.528.449-.32h-.552zm-3.08 1l.171.523-.448.326.555-.001.168.525.169-.525.552.001-.448-.326.175-.522-.447.324zm-1.904 2.621l.446.322-.171.527.449-.327.445.326-.172-.525.447-.323-.555-.001-.166-.525-.17.526zm0 3.239l.55-.002.171.527.171-.529.552.002-.447-.322.172-.525-.45.325-.442-.327.171.525zm1.904 2.619l.444-.324.448.326-.172-.529.448-.322-.552.001-.17-.525-.172.527-.55-.003.447.324zm3.08 1l.169-.523h.554l-.451-.326.173-.524-.445.326-.445-.326.17.527-.448.321h.552zm3.08-1l-.172-.523.448-.326-.555.001-.168-.525-.169.525-.552-.001.448.326-.175.523.448-.326zm1.903-2.621l-.446-.322.171-.527-.449.327-.444-.326.171.524-.446.324h.554l.166.525.171-.525zm-.001-3.238l-.549.001-.171-.527-.171.529-.552-.003.447.323-.171.525.449-.325.442.327-.171-.526zm-1.903-2.62l-.444.324-.448-.325.171.528-.447.322.552-.001.17.525.172-.528.549.005-.446-.324z" fill="#006000"/><path fill="#00693F" d="M19.594 20.818c-.018-.137-.061-.652-.069-1.062-.005-.276-.506-.646-.837-.643-.226-.462-.887-1.02-1.331-.576-.043.309.034.91.18 1.14l.678.154c.068-.043.145-.144.171-.23.019-.006.031-.024.049-.032.126.487.377 1.247.448 1.429.077.197.189.6.438.67.111.059.266.016.197-.498.076-.018.092-.215.076-.352z"/><path fill="#7D76B6" d="M18.86 15.76c.013.102.077.206.154.27-.051.038-.077.09-.09.128-.283.244-.939 1.941-.951 2.314-.045.199-.136.515-.213.65-.437-.392-.887-1.125-.812-1.455-.026-.004-.064-.008-.107-.021.009-.03.025-.18.03-.27-.026 0-.073 0-.112-.013.009-.056.026-.219.026-.292-.043-.013-.095-.056-.133-.099.029-.077.107-.227.146-.317-.064-.008-.111-.073-.133-.111.056-.034.129-.133.158-.193-.047-.039-.102-.094-.111-.12.06-.056.236-.248.313-.355-.048 0-.064-.004-.104-.013.064-.025.138-.12.224-.201.147.128.428.105.563.028.244.141.508.161.849.051.066.019.239.045.303.019z"/><path fill="#00693F" d="M19.838 20.428c.051-1.813-.258-3.472-.733-4.076-.476-.605-1.349-.47-1.594.051-.104.219-.118.741-.014.965.181.386.875 1.607 1.351 2.07.475.462.809.771.99.99z"/><path fill="#FFD420" d="M19.122 19.996c-.137.016-.3-.018-.429-.078-.129-.061-.24-.119-.377-.119-.138 0-.883-.053-1.003-.096-.12-.043-.455-.102-.592-.094-.137.008-.352.104-.438.104-.086 0-.128.068-.128.137 0 .068.017.197.119.266.181-.008.438-.025.472-.06.249.068.583.139.789.146.206.008.574.025.712.018.137-.01.162-.053.343.008.18.06.42.189.531.223.111.035.18-.076.205-.197.028-.121-.058-.268-.204-.258z"/><path fill="#FFF" d="M17.279 15.002c-.005 0-.011.006-.016.006-.039-.173-.219-.295-.32-.29-.314.083-.296.663-.013.862-.008-.104.028-.188.078-.261.023.07.077.136.218.153.149-.053.098-.381.053-.47z"/><path fill="#7D76B6" d="M17.146 15.662c.147.128.428.105.563.028.244.141.508.161.849.051.064.02.237.045.302.02.039-.039.077-.064.116-.09-.077-.064-.154-.18-.193-.295 0 0 .065-.078.09-.116-.063-.064-.192-.167-.257-.206.039-.038.077-.154.077-.154-.129-.038-.257-.128-.309-.18l.013-.077c-.21-.013-.201-.27-.655-.347-.309-.052-.772.077-.798.424.172.167.434.39.283.754-.039.052-.111.12-.154.142.026.028.043.032.073.046z"/><path fill="#FFF" d="M18.342 20.219c-.086-.01-.171-.104-.171-.18 0-.078.008-.233.154-.25-.048-.082-.116-.104-.182-.094-.062-.075-.161-.091-.256-.07.003-.004.005-.013.009-.016-.08-.065-.172-.051-.252-.011-.148-.087-.373.022-.408.294-.034.266.103.455.3.445v-.003c.089.044.216.004.249-.048l-.001-.019c.082.054.164.055.237.003.026.024.051.05.09.059.112.027.197-.067.231-.11z"/><path fill="#FFD420" d="M17.562 14.59c-.231 0-.225.347 0 .347s.231-.347 0-.347z"/><path d="M17.562 14.72c-.058 0-.056.086 0 .086.056.001.058-.086 0-.086z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..c627c34ee03eb697f2589bf013eefd0e012c9670 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002D62" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#DD2E44" d="M32 5H20v11h16V9c0-2.209-1.791-4-4-4z"/><path fill="#CE1225" d="M4 31h12V20H0v7c0 2.209 1.791 4 4 4z"/><path fill="#EEE" d="M36 15H21V5h-6v10H0v6h15v10h6V21h15z"/><path fill="#002D62" d="M18.022 15.945h-1.917l.335.323v1.655h1.582v-1.978zm0 3.936c.255-.278.429-.267 1.15-.267.385 0 .43-.262.43-.771v-.92h-1.58v1.958z"/><path fill="#CE1225" d="M18.022 19.881c-.255-.278-.429-.267-1.151-.267-.386 0-.431-.262-.431-.771v-.92h1.582v1.958zm0-3.936h1.915l-.335.323v1.655h-1.58v-1.978z"/><path fill="#FFF" d="M18.295 19.677v-3.732h-.547v3.735c.093.032.192.107.274.201.07-.085.186-.172.273-.204z"/><path fill="#FFF" d="M16.44 17.644h3.161v.547H16.44z"/><path fill="#002D62" d="M18.022 17.556l1.038-1.108v.335l.192-.161v1.851c0 .687-1.082.619-1.231.302-.149.317-1.232.385-1.232-.302v-1.851l.193.161v-.335l1.04 1.108z"/><path fill="#FFF" d="M18.022 18.743c-.498.267-.821.057-.821-.198v-.318c-.193 0-.411-.099-.411-.162v-.273c0 .081.324.155.411.155v-.958l.18.143v-.249l.274.28v.196l-.181-.153v.81c.187 0 .333.111.548.111.214 0 .36-.111.547-.111v-.81l-.18.153v-.196l.273-.28v.249l.181-.143v.958c.087 0 .41-.075.41-.155v.273c0 .063-.218.162-.41.162v.318c0 .255-.324.466-.821.198v-.279c.267.155.547.193.547.025v-.199c-.187 0-.333.112-.547.112-.215 0-.361-.112-.548-.112v.199c0 .168.281.13.548-.025v.279z"/><path fill="#CE1225" d="M18.389 17.164v.196l.18-.153v.81c-.187 0-.333.111-.547.111-.215 0-.361-.111-.548-.111v-.81l.181.153v-.196l.367.393.367-.393z"/><path fill="#CE1225" d="M16.79 18.066v.407c0 .687 1.083.619 1.232.302.148.317 1.231.385 1.231-.302v-.407c0 .061-.218.161-.41.161v.318c0 .254-.324.465-.821.198-.498.267-.821.057-.821-.198v-.318c-.193 0-.411-.099-.411-.161z"/><path fill="#002D62" d="M18.438 15.282c.019-.05.038-.122.056-.188-.142-.018-.313-.03-.472-.03-.16 0-.331.012-.473.03.018.066.037.138.056.188.012.038-.062.131-.329.115-.229-.013-.563.009-.854.059.049.075.067.09.062.148-.007.065-.16.126-.427.164-.267.037-.37.314-.462.711-.105-.044-.271-.086-.375-.101.06-.258.267-.844.526-.903-.063-.14-.048-.21.193-.323.261-.122.703-.196 1.19-.214-.031-.118 0-.165.153-.231.131-.057.339-.1.741-.1.4 0 .609.043.739.1.154.065.184.113.154.231.486.018.929.092 1.189.214.241.112.256.183.193.323.258.059.466.645.525.903-.101.015-.27.058-.373.101-.092-.397-.196-.674-.464-.711-.267-.038-.421-.099-.427-.164-.007-.058.013-.073.061-.148-.29-.05-.626-.072-.853-.059-.266.016-.34-.078-.329-.115z"/><g fill="#996B38"><path d="M18.022 17.65l1.273-1.09.028.033-1.301 1.113zm0-.122l1.075-1.167.031.031-1.106 1.2zm0-.16l.854-1.179.034.025-.888 1.228zm0 .282l-1.273-1.09-.028.033 1.301 1.113z"/><path d="M18.022 17.528l-1.075-1.167-.031.031 1.106 1.2zm0-.16l-.855-1.179-.035.025.89 1.228z"/></g><path d="M19.274 16.544l.183-.096-.122.167c-.01.009-.069-.063-.061-.071zm-.2-.195l.172-.117-.102.18c-.01.009-.078-.055-.07-.063zm-.221-.172l.157-.137-.082.191c-.008.012-.082-.044-.075-.054zm-2.084.367l-.184-.096.123.167c.01.009.069-.063.061-.071zm.199-.195l-.17-.117.103.18c.008.009.076-.055.067-.063zm.222-.172l-.156-.137.08.191c.009.012.083-.044.076-.054z" fill="#FFCE46"/><path fill="#FFF" d="M17.713 17.372c.05-.041.191-.109.274-.065.064-.074.216-.138.299-.095l.176.543c-.049.035-.148.017-.21.055-.017.01-.065.037-.073.057-.03-.013-.098-.006-.146.01-.044.013-.075.059-.127.066l-.193-.571"/><path d="M17.908 17.948l-.197-.575.001-.003c.054-.044.194-.107.277-.065.058-.07.215-.139.299-.095l.178.545c-.026.021-.063.026-.102.031-.039.004-.079.01-.109.028-.022.013-.065.037-.072.056-.032-.012-.103-.002-.147.011-.019.006-.035.018-.052.03-.023.016-.046.032-.076.037zm-.191-.575l.193.57c.025-.006.047-.022.069-.038.018-.013.034-.024.054-.031.045-.015.114-.024.148-.009.003-.019.046-.043.066-.055.035-.021.076-.026.116-.031.038-.004.074-.009.097-.026l-.178-.54c-.075-.039-.226.02-.293.096-.081-.042-.218.022-.272.064z"/><path fill="#549334" d="M19.707 20.28c.163-.001.379.043.447.068-.069-.056-.173-.108-.285-.149.149.024.187.049.287.074.069.02.08.027.083.127.001.067.001.154.042.014.038-.126.052-.144-.015-.186-.071-.049-.162-.095-.261-.135.192.05.348.112.441.173-.047-.072-.122-.16-.236-.229.112.026.262.087.367.144-.05-.067-.138-.179-.244-.229.17.036.351.092.449.147-.095-.125-.203-.235-.345-.278.189.023.368.08.449.129-.11-.105-.225-.216-.338-.254.155.021.299.061.383.099-.105-.105-.282-.194-.449-.22.117.002.267.013.394.039-.106-.068-.288-.114-.368-.108.193-.044.41-.038.647.04-.1-.062-.274-.133-.443-.171.094-.005.231-.027.319-.015-.095-.032-.329-.079-.434-.073.19-.056.379-.092.493-.113-.199-.013-.423 0-.622.032.22-.187.38-.187.523-.211.142-.025.249-.056.101-.071-.096-.009-.174-.017-.241-.018.155-.047.351-.146.416-.181.065-.034.224-.149.053-.072-.171.078-.416.09-.638.115-.095.011-.164.029-.229.064.12-.069.255-.142.396-.21.141-.068.11-.091.233.049.059.069.055 0-.022-.178-.062-.138-.115-.074-.25-.021-.05.02-.114.048-.188.088.078-.093.348-.405.392-.458.048-.053.119.009.211.068.088.06.058.003-.026-.094-.085-.096-.125-.111-.181-.064-.055.047-.325.218-.476.361.276-.261.596-.556.669-.639-.158.085-.3.18-.427.278.044-.062.124-.178.166-.227-.064.043-.152.089-.202.136.074-.132.152-.253.163-.274.017-.034.035-.042.061-.044l.14-.012c.08-.006.049-.023.014-.032-.222-.058-.213-.033-.263.015-.036.037-.085.094-.136.16.056-.173.224-.334.251-.383-.174.096-.266.171-.328.25.079-.128.328-.324.403-.402-.077.031-.239.112-.282.162.041-.073.08-.149.116-.227-.136.086-.234.201-.312.334.008-.032.021-.08.034-.12.044-.085.164-.202.226-.271.063-.068.077-.087.254.025-.026-.077-.061-.131-.091-.174-.051-.077-.075-.044-.145.014-.039.031-.075.075-.145.136.076-.196.165-.406.212-.542-.127.124-.226.294-.306.485.006-.137.081-.417.068-.56-.06.075-.124.203-.154.352-.004-.151-.006-.338-.043-.445.011.093-.085.306-.11.455-.06-.142-.126-.279-.164-.374.003.074.024.245.056.447-.05-.155-.231-.317-.237-.441-.005.18.125.485.139.572.002.028.013.07.023.118-.062-.1-.21-.28-.249-.398 0 .074.028.204.042.285-.078-.072-.133-.03-.265.219.043-.013.093-.068.13-.093s.072-.052.112.012c.05.082.185.27.258.51-.021-.069-.146-.231-.19-.302.01.034.032.146.047.211-.06-.163-.122-.279-.167-.345-.004.081.056.309.065.405-.035-.083-.074-.156-.105-.218.023.064.057.292.053.409-.051-.092-.103-.167-.142-.223.032.094.059.28.064.387-.018-.036-.033-.063-.045-.082-.062-.1-.103.081-.14.174-.038.093-.018.08.025.016.065-.099.057-.086.095.022.024.064.091.217.146.417-.054-.088-.129-.205-.169-.292-.041-.087-.044-.082 0 .091.028.113.099.323.07.547-.04-.142-.092-.312-.149-.465.008.097.02.281.02.359-.024-.045-.052-.082-.083-.11.041.131.051.358.051.5-.022-.09-.053-.175-.084-.229-.003.103.026.345.051.456-.021-.086-.054-.17-.09-.237.021.116.028.307-.006.431-.006-.064-.025-.122-.048-.189-.01.058-.024.227-.065.3.023-.107.025-.207.016-.268-.031.117-.072.225-.119.315.015-.055.036-.16.042-.264-.014.065-.058.118-.082.174.012-.092.015-.169.011-.205-.047.156-.114.268-.204.391.048-.126.061-.26.061-.341-.08.141-.087.201-.214.369.067-.14.055-.258.041-.324-.01.036-.054.14-.118.252-.013-.079.005-.278.03-.334-.055.037-.13.144-.13.224-.02-.081-.052-.153-.1-.205.043.278.027.52-.14.631-.372.244-.687.785-1.142.986.032.018.106.081.144.125.435-.192.728-.625 1.065-.867.16-.086.527.107.932.002.156-.04.46.05.596.106-.064-.087-.187-.157-.406-.2z"/><path fill="#549334" d="M16.575 19.999c.075-.013.28-.011.443.016-.108-.041-.039-.298-.17-.394.134.062.191.04.262.052l.025.007c-.006-.033.003-.108.031-.148.018.068.093.083.158.133.01.007.021.017.033.028.003-.081.12-.187.133-.24.025.072.091.123.115.225.062.262-.143.317-.068.504.372.244.703.731 1.157.933-.032.018-.106.081-.143.125-.603-.267-.992-1.04-1.544-1.078l-.042.017c-.137.066-.265.116-.386.09-.121-.023-.23.014-.33.06.153-.237.232-.305.326-.33-.079.031-.234.055-.348.007-.068.165-.228.212-.371.23-.143.02-.248.077-.293.156-.015-.072-.008-.198.01-.234-.062-.008-.137-.01-.227.005.085-.033.162-.274.37-.303-.039-.026-.073-.057-.102-.098.049.028.093-.003.183-.027.045-.013.117-.022.183-.02-.071-.049-.124-.139-.137-.204-.064.194-.276.246-.401.255-.15.01-.221.059-.249.1 0-.092.03-.167.064-.217-.062.006-.119.008-.151.021.027-.144.097-.229.171-.276-.091-.021-.217-.181-.224-.295.072.083.367-.003.511.158-.091-.078-.139-.176-.147-.287.033.044.104.045.174.085-.097-.352-.341-.273-.485-.385-.183-.144-.109-.393-.255-.511.064 0 .117.004.16.015-.031-.076-.03-.226-.027-.316.035.112.159.097.237.206.013-.031.02-.062.015-.091.056.067.108.125.141.187-.01-.118.038-.187.074-.219-.003.042.009.144.056.237s.065.199.03.37c-.032.162.034.287.117.406.009-.071-.001-.278-.023-.343s-.032-.174-.01-.296c.013.05.071.122.134.183.016.016.027.037.035.062.02-.044.033-.078.048-.115.02-.056-.239-.15-.225-.442-.174-.097-.331-.226-.374-.459.019.019.054.034.096.05-.096-.143-.121-.324-.087-.414.023.075.099.094.181.152.02-.155-.144-.267-.14-.416.006-.236.13-.239.173-.386.034.054.059.104.077.157.028-.099.148-.173.15-.248.062.09.108.191.074.293.081-.024.174-.007.226.03-.152.028-.143.211-.243.258-.1.047-.287.178-.24.376.062.068.12.177.153.364.03.029.057.065.076.107.025-.042.048-.092.066-.148-.009-.078-.112-.164-.14-.24-.038-.101.052-.255.016-.392.049.019.133.05.192.125.046-.108.135-.176.137-.357.037.071.068.149.088.226.055-.075.154-.161.27-.195-.072.124-.047.246-.05.349-.003.102-.006.274-.155.388-.149.116-.188.147-.22.438.063-.137.214-.243.22-.316.031.13.056.23.052.319.05-.059.14-.092.246-.097-.075.086-.131.425-.33.465-.198.041-.278.242-.332.324-.068.103-.085.182-.017.318-.003-.109.02-.227.054-.296.066-.132.208-.187.217-.28.019.098.029.176.025.241.1-.202.311-.144.37-.203-.041.053-.083.127-.103.237-.018.108-.102.21-.22.267-.092.044-.172.051-.22.146-.012.056.036.103.036.188.005-.031.014-.06.028-.08.057-.082.094-.144.094-.19.125.124.152.246.112.376-.04.132-.07.238.011.342.048.041.104.071.156.087.066-.066-.011-.146-.086-.224-.075-.077-.068-.26-.006-.335.062-.077.116-.156.112-.224.046.04.096.113.111.153.024-.06.059-.113.106-.142.01.109.081.159.081.277.032-.071.084-.133.156-.156-.016.06.039.151.047.208.006.045 0 .096-.022.152-.022.059-.061.119-.152.165-.029.014-.074.028-.119.049.106-.014.299.021.343.1-.079-.03-.25.033-.334.067z"/><g fill="#CE1225"><path d="M18.12 20.687c-.02-.018-.049-.026-.098-.026-.048 0-.077.009-.097.026-.196-.067-.323-.038-.323.023v.188c0 .032.072.072.337.008.02.012.041.022.083.022.043 0 .067-.01.087-.024v.001c.266.065.338.024.338-.008v-.188c0-.062-.128-.092-.327-.022z"/><path d="M18.427 20.679c.082.01.176.024.238.055-.009.041-.029.191-.029.225-.047-.031-.146-.064-.208-.07v-.21zm-.805 0c-.082.01-.175.024-.238.055.01.041.03.191.03.225.046-.031.146-.064.207-.07v-.21z"/><path d="M18.022 20.485c.567 0 1.023.034 1.386.112-.044.034-.083.079-.112.101-.033.028-.021.106.054.173.075.064.257.121.438.042l.104-.046c-.051.043-.093.1-.07.153.107.239.519-.075.765.226.066-.084.231-.259.299-.324-.14-.17-.335-.142-.496-.129.059-.097.065-.171-.064-.263-.052-.038-.233-.032-.399.043.03-.078.025-.206-.232-.319-.392-.176-1.057-.212-1.672-.212-.616 0-1.282.036-1.674.212-.257.113-.263.241-.231.319-.168-.075-.347-.081-.401-.043-.128.092-.121.166-.062.263-.162-.013-.357-.041-.497.129.068.066.234.24.298.324.246-.302.659.013.765-.226.024-.054-.018-.11-.068-.153l.103.046c.181.079.364.022.438-.042.075-.067.087-.145.054-.173-.03-.022-.067-.067-.113-.101.363-.077.819-.112 1.387-.112z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..c29a7e2998f852367e04ffb172795d82d216a917 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1e9-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006233" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h14V5H4z"/><path fill="#EEE" d="M32 5H18v26h14c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#D20F34" d="M20 24c-3.315 0-6-2.685-6-6 0-3.314 2.685-6 6-6 1.31 0 2.52.425 3.507 1.138-1.348-1.524-3.312-2.491-5.507-2.491-4.061 0-7.353 3.292-7.353 7.353 0 4.062 3.292 7.354 7.353 7.354 2.195 0 4.16-.967 5.507-2.492C22.521 23.575 21.312 24 20 24z"/><path fill="#D20F34" d="M25.302 18.23l-2.44.562-.22 2.493-1.288-2.146-2.44.561 1.644-1.888-1.287-2.147 2.303.98 1.644-1.889-.22 2.494z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1fd565cd1f16e7c0d079495648e9566a02241e5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C60A1D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFC400" d="M0 12h36v12H0z"/><path fill="#EA596E" d="M9 17v3c0 1.657 1.343 3 3 3s3-1.343 3-3v-3H9z"/><path fill="#F4A2B2" d="M12 16h3v3h-3z"/><path fill="#DD2E44" d="M9 16h3v3H9z"/><ellipse fill="#EA596E" cx="12" cy="14.5" rx="3" ry="1.5"/><ellipse fill="#FFAC33" cx="12" cy="13.75" rx="3" ry=".75"/><path fill="#99AAB5" d="M7 16h1v7H7zm9 0h1v7h-1z"/><path fill="#66757F" d="M6 22h3v1H6zm9 0h3v1h-3zm-8-7h1v1H7zm9 0h1v1h-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..c035be7a90f823d8b968721b135b4514e6fab297 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED1C23" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#034EA2" d="M0 17h36v7H0z"/><path fill="#FD0" d="M36 17V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v8h36z"/><path fill="#FD0" d="M23 19c0 1.104-.896 2-2 2h-6c-1.104 0-2-.896-2-2v-3c0-1.104.896-2 2-2h6c1.104 0 2 .896 2 2v3z"/><path fill="#034EA2" d="M22 18c0 1.104-.896 3-2 3h-4c-1.104 0-2-1.896-2-3v-1c0-1.104.896-2 2-2h4c1.104 0 2 .896 2 2v1z"/><path fill="#ED1C23" d="M21 18c0 1.104-.896 3-2 3h-2c-1.104 0-2-1.896-2-3v-1c0-1.104.896-2 2-2h2c1.104 0 2 .896 2 2v1z"/><path fill="#6DBE46" d="M19.973 14.135c-.133.488-.961.865-1.973.865s-1.84-.377-1.973-.865C14.822 14.307 15 14.628 15 15c0 .552.791 1 3 1s3-.448 3-1c0-.372.178-.693-1.027-.865z"/><path fill="#A6D388" d="M19 19c0 .553-.448 1-1 1s-1-.447-1-1v-3c0-.552.448-1 1-1s1 .448 1 1v3z"/><path fill="#662113" d="M21.5 12c.44 0 .858.052 1.246.137C22.123 11.061 20 10 18 12c-2-2-4.123-.939-4.746.137.388-.085.806-.137 1.246-.137 1.933 0 3.5.896 3.5 2 0-1.104 1.566-2 3.5-2z"/><ellipse fill="#8ED2E7" cx="18" cy="17.5" rx="2" ry="3.5"/><path fill="#6DBE46" d="M17.5 17c-.536 0-1.037.13-1.491.345-.001.052-.009.102-.009.155 0 1.933.896 3.5 2 3.5 1.003 0 1.825-1.295 1.97-2.979-.633-.63-1.506-1.021-2.47-1.021z"/><ellipse fill="#FFCC4D" cx="18" cy="22" rx="3" ry="1"/><path fill="#034EA2" d="M20 23c0 .828-.896 1-2 1s-2-.172-2-1 .896-2 2-2 2 1.172 2 2z"/><path fill="#ED1C23" d="M17 23c0-.828.448-2 1-2s1 1.172 1 2-.448 1-1 1-1-.172-1-1z"/><path fill="#CCD6DD" d="M17 11c0-.552.448 0 1 0s1-.552 1 0-.448 1-1 1-1-.448-1-1z"/><ellipse fill="#FFF" cx="18" cy="17.5" rx="1" ry=".5"/><ellipse fill="#C1694F" cx="13" cy="15.5" rx="1" ry=".5"/><ellipse fill="#C1694F" cx="14" cy="13.5" rx="1" ry=".5"/><ellipse fill="#C1694F" cx="23" cy="15.5" rx="1" ry=".5"/><ellipse fill="#C1694F" cx="22" cy="13.5" rx="1" ry=".5"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..47a55895cd186d590a62e5c0d33822284b8aa207 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M0 14h36v9H0z"/><path fill="#4891D9" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M32 31H4c-2.209 0-4-1.791-4-4v-4h36v4c0 2.209-1.791 4-4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..2034a3e5108cb7226d7e5490d7a72557ed99f2e7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#CE1225" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#BF9300" d="M14.75 21.562s.016.25.234.375c0 0-.062.188.172.297.234.109 1.078.281 2.547.281s2.297-.156 2.516-.266c.219-.109.234-.359.234-.359s.234-.125.219-.281c-.016-.156-.328-.328-.328-.328s-.078-.203-.297-.281c-.219-.078-.922.344-2.266.281-1.344-.062-2.109-.266-2.359-.25-.25.016-.359.266-.359.266s-.282.125-.313.265z"/><path fill="#EEE" d="M14.922 21.547c-.013.093.188.297.188.297s0 .234.203.297 1.031.219 2.375.203c1.344-.016 2.297-.094 2.406-.188.109-.094.203-.297.203-.297s.219-.156.203-.281-.328-.203-.328-.203-.088-.188-.192-.266-.776.312-2.214.312c-1.407 0-2.219-.344-2.359-.328-.141.016-.234.281-.234.281s-.235.064-.251.173z"/><path fill="#BF9300" d="M20.859 15.484s-.031-.734-.703-.641c-.672.094-.719.422-1.438.5l-.148.014c-.108-.285-.196-.697-.196-1.014 0-.469.141-.672-.344-.906-.484-.234-.578-.016-.578-.016s-.375-.188-.547-.047c-.172.141-.078.5 0 .391.078-.109.391.203.391.203.106.519-.195 1.081-.401 1.394-.071-.007-.128-.01-.208-.019-.719-.078-.766-.406-1.438-.5-.672-.094-.703.641-.703.641l-.266 5.672.547-.422.003-.067 1.138-1.011.19-.19-.471 1.377s-.719-.047-.516.531c0 0 .109-.328.297-.266s.734.203.734.203l.188.297.234-.219.734-.031s.234.062.219.266c.049-.113.055-.206.037-.283l.221-.015c-.022.08-.018.178.034.299-.016-.203.219-.266.219-.266l.734.031.235.219.188-.297s.546-.141.733-.203.297.266.297.266c.203-.578-.516-.531-.516-.531l-.449-1.313.126.126 1.138 1.011.003.067.547.422-.265-5.673zm-3.107 3.438c-1.127-.696-1.22-2.453-1.22-2.453s.697-.036 1.203-.391c.456.405 1.234.359 1.234.359s-.053 1.764-1.217 2.485zm2.576-3.656l-.953.906-.16.064c-.164.006-.962.008-1.465-.439-.625.438-1.484.469-1.484.469l-.133-.053-1.055-.947-.277.114c.012-.113.074-.367.418-.317.564.081.797.391 1.391.453l.168.017-.059.076c.092 0 .228-.027.328-.049l.113.011-.051.178c.08-.024.196-.093.291-.154l.26.025.059.082.198-.099.133-.013c.115.067.279.127.279.127l.031-.156c.141.094.375.094.375.094-.027-.022-.054-.078-.082-.126l.144-.015c.594-.062.826-.372 1.391-.453.344-.049.406.204.418.317l-.278-.112z"/><path fill="#EEE" d="M17.375 18.891l-.563 2.14-.937-.187.969-2.75zm.699 0l.562 2.14.938-.187-.969-2.75z"/><path fill="#BF9300" d="M16.766 16.641s.078.906.484 1.609v-1.812s-.266.156-.484.203zm1.953.031s-.078.906-.484 1.609v-1.812c-.001 0 .265.156.484.203z"/><path fill="#EEE" d="M16.953 13.578s.109-.109.422.109c.203.142.383.25.383.25s.128-.135.316-.104c.188.031.083.292.114.838.031.547.25.781.25.781l-.266-.156.016.172-.297-.141-.141.203-.141-.219-.228.139-.069-.186-.266.141s.391-.484.422-1.016c.009-.159-.031-.516-.031-.516s-.249-.311-.484-.295z"/><path fill="#BF9300" d="M15.547 21.656c-.179.107-.109.172 0 .219s.765.126 2.094.156c1.359.031 2.203-.125 2.312-.188.109-.062.125-.172-.062-.203-.188-.031-1.125.125-2.266.125-1.406.001-2-.156-2.078-.109z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b8dc5a64ab4dd8d1613f6a768476fecc9cc15eb --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#007A3D" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><path fill="#C4111B" d="M1.129 6.223C.433 6.943 0 7.92 0 9v18c0 1.08.433 2.057 1.129 2.777L12 18 1.129 6.223z"/><g fill="#C4111B"><path d="M17.894 18.033c0-1.692 1.213-3.101 2.817-3.405-.211-.04-.428-.062-.65-.062-1.915 0-3.467 1.552-3.467 3.467S18.146 21.5 20.06 21.5c.222 0 .439-.022.65-.062-1.603-.304-2.816-1.712-2.816-3.405z"/><path d="M19.13 20.132l1.478-1.057 1.467 1.073-.548-1.732L23 17.353l-1.817-.014-.556-1.73-.575 1.724-1.817-.006 1.462 1.079-.567 1.726z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..8e1e510fee7a2c95aaf25d1e74beefe64ddbe463 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E9A00" d="M32 5H4c-1.185 0-2.238.525-2.97 1.343V18H36V9c0-2.209-1.791-4-4-4z"/><path fill="#4289DE" d="M32 31H4c-1.185 0-2.238-.525-2.97-1.343V18H36v9c0 2.209-1.791 4-4 4z"/><path fill="#EB0438" d="M1.03 6.343C.397 7.051 0 7.976 0 9v18c0 1.024.397 1.949 1.03 2.657L36 18 1.03 6.343z"/><path fill="#FFC827" d="M11.688 24.312c-.457.188-2 .312-2.375 0s.75-1 .75-1-1.125.062-2.469-.406C6.25 22.438 5.625 21.594 5 21.594c.406-.406 1.781.281 1.781.281s-2.469-1.156-2.594-2.844c.781 1.094 1.656 1.344 1.656 1.344s-1.969-1.406-1.312-3.469c.157.532.563 1.094.563 1.094s-.75-2.312.094-3.625c.281.25.375 1.844.375 1.844s-.125-1.531.094-2.375c.218-.844.874-1.156.874-1.156L6.25 14.25s.562-.438.781-.812 1.25-1.75 2-1.844c.094.219-.594.875-.594.875s1.844-.938 2.688-.531c-.5.469-2.062.656-2.062.656s.812.375 1.188.094c-.094.281-.719.5-1.156.406-.439-.094-.845.281-.845.281s.629.265.906 0c-.188.594-1.125.469-1.438.469s-1.438.75-1.438 1.281c.5-.156.875-.781.875-.781s.345.906-.561 1.312-.844 1.188-.844 1.188.502-.184.562-.625c.531.25-.156.688-.312.938s-.188 1.375-.188 1.375.281-.969.344-1.094.532.874.344 1.312-.375 1.344-.094 1.844c.188-.125.063-1.094.063-1.094s.656.594.688 1.188c.188.156.188-.375.188-.375s.438.906.594 1.406 1.062.938 1.5.906c.438-.031.969.281.969.281s-.188-1.094-.188-1.562c0-.469.062-.969.062-.969s-1.875.906-1.938-.844c.469.531 1.062.344 1.062.344s-1.156-.219-1.094-1.25c.375.469.938.469.938.469s-.625-.402-.469-1.029c.719.123 1.125 1.217 1.125 1.217s.062-.902.031-1.217c-.031-.315-.062-.908-.062-.908s-1.156.5-1.344-1.031c.312.406.656.25.656.25s-.656-.5-.375-1.438c.219.625.719.875.719.875s-.219-.5-.219-.781c.438 0 .906.438.812 1.406.594-.594.5-1.406.375-1.656-.531.188-1-.5-1-.5s.656.25.781-.219c-.781.219-.969-.406-.969-.406s.688-.25 1.031 0c.25-.188.094-.594.094-.594s.969.344.312 1.188c.125.406.125 1.031.125 1.031s.312-.969 1.094-1.031c-.469.438-.281.844-.281.844s.564-.095.626-.439c.719.594-.688 1.312-.688 1.312s.406.156.75-.281c.438.719-.688.906-1.125.75-.438-.156-.688-.188-.781.094-.094.281-.219 1.562-.188 1.469.031-.094.252-.93.5-1.281-.031.469.125.906.125.906s1 .031.75-.906c.969-.062-.188 1.346-.188 1.346s.472.377 1.048 0c.202.873-.767.685-1.111.685s-1.188-.062-1.062.531c.127.594.439 1.719.439 1.719s.094-.688.375-1.188.656-.656.5.125c.406-.062.719-.75.719-.75s.469.844-.531 1.438c.219.219.701-.375.701-.375s.112.875-.638 1.125-1.031.094-1.094.562c-.062.469 0 .844 0 .844s.375.062.969-.312c.594-.375 1.062-.031 1.438-.438.375-.406.438-1.531 1.062-1.938.031.406 0 .812 0 .812s.469-.312.469-.781c0-.469.094-.719.25-.906.156-.188-.188-.621-.219-1.154-.031-.533.259-.783.259-.783s.178 1.188.585 1.594c.312-1-.25-1.469-.375-2.031s.219-.594-.375-1-.938-1-.719-1.656c.406.906.938.969.938.969s-.562-1.406-.875-1.312c-.312.094-1.094.469-1.656-.094.781.031.906-.125.906-.125s-.188-.594-.906-.375c-.719.219-1.625-.187-1.906-.562.531.156.688.062.688.062l-.531-.344s.438.094.75 0 .406-.312.812.031c.406.344 1 .688 1 .688s-1.031-.688-.969-1.531c1.281.375 1.625 1.531 1.938 1.719s.81.686.966 1.186c.156-.594-.469-1.625-.469-1.625s1.094.094 1.156 2.781c.281-.188 0-1.531 0-1.531s1 .5.75 1.906-.656 2.033-.656 2.033.611-.283.696-.971c.71.688.147 1.812-1.009 3.281 1.323-.625 1.323-1.656 1.323-1.656s.271 1.375-.885 2.188c-1.156.812-1.688.938-1.688.938s.781.062 1.156.156c-.188 1.062-3.844 1.219-4.531 1.312.845.5.811.886.533 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1fd565cd1f16e7c0d079495648e9566a02241e5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C60A1D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFC400" d="M0 12h36v12H0z"/><path fill="#EA596E" d="M9 17v3c0 1.657 1.343 3 3 3s3-1.343 3-3v-3H9z"/><path fill="#F4A2B2" d="M12 16h3v3h-3z"/><path fill="#DD2E44" d="M9 16h3v3H9z"/><ellipse fill="#EA596E" cx="12" cy="14.5" rx="3" ry="1.5"/><ellipse fill="#FFAC33" cx="12" cy="13.75" rx="3" ry=".75"/><path fill="#99AAB5" d="M7 16h1v7H7zm9 0h1v7h-1z"/><path fill="#66757F" d="M6 22h3v1H6zm9 0h3v1h-3zm-8-7h1v1H7zm9 0h1v1h-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..762cc1fb99b7b506ae30ee863789883971e28f10 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCDD0A" d="M0 13h36v10H0z"/><path fill="#088930" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#DA1219" d="M4 31h28c2.209 0 4-1.791 4-4v-4H0v4c0 2.209 1.791 4 4 4z"/><circle fill="#0F47AF" cx="18" cy="18" r="9"/><g fill="#FCDD0A"><path d="M13.25 24.469l1.719-5.531-2.731-1.985h1.156l3.778 2.893-.594.359-.922-.83-1.468 4.406z"/><path d="M22.609 24.469l-4.73-3.345-2.723 1.97.357-1.1 3.964-2.824.158.676-1.128.759 3.739 2.759z"/><path d="M25.382 15.64l-4.519 3.372 1.012 3.222-.935-.677-1.463-4.633.693.058.395 1.272 3.7-2.647z"/><path d="M17.872 10.07l1.86 5.487 3.344.05-.933.68-4.549-.038.271-.642.979-.06-1.327-4.37zm-7.669 5.477h5.906l1.063-3.254.358 1.098L16.012 18l-.526-.456.476-1.372-4.783.029zm7.526 6.765h.417v3.647h-.417zm7.847-2.087l-.128.396L22 19.466l.128-.396z"/><path d="M22.473 11.453l.337.245-2.177 3.021-.337-.244zm-9.359.245l.337-.245 2.174 3.021-.336.245zm-2.637 8.923l-.129-.396 3.454-1.155.129.397z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..045024a339ce2a7b03464f5d7dc8fdb0209f0cd6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ea-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#039" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M18.539 9.705l.849-.617h-1.049l-.325-.998-.324.998h-1.049l.849.617-.325.998.849-.617.849.617zm0 17.333l.849-.617h-1.049l-.325-.998-.324.998h-1.049l.849.617-.325.998.849-.617.849.617zm-8.666-8.667l.849-.617h-1.05l-.324-.998-.325.998H7.974l.849.617-.324.998.849-.617.849.617zm1.107-4.285l.849-.617h-1.05l-.324-.998-.324.998h-1.05l.849.617-.324.998.849-.617.849.617zm0 8.619l.849-.617h-1.05l-.324-.998-.324.998h-1.05l.849.617-.324.998.849-.617.849.617zm3.226-11.839l.849-.617h-1.05l-.324-.998-.324.998h-1.05l.849.617-.324.998.849-.617.849.617zm0 15.067l.849-.617h-1.05l-.324-.998-.324.998h-1.05l.849.617-.324.998.849-.616.849.616zm11.921-7.562l-.849-.617h1.05l.324-.998.325.998h1.049l-.849.617.324.998-.849-.617-.849.617zm-1.107-4.285l-.849-.617h1.05l.324-.998.324.998h1.05l-.849.617.324.998-.849-.617-.849.617zm0 8.619l-.849-.617h1.05l.324-.998.324.998h1.05l-.849.617.324.998-.849-.617-.849.617zm-3.226-11.839l-.849-.617h1.05l.324-.998.324.998h1.05l-.849.617.324.998-.849-.617-.849.617zm0 15.067l-.849-.617h1.05l.324-.998.324.998h1.05l-.849.617.324.998-.849-.616-.849.616z" fill="#FC0"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..e07328edd52747952679895be2458ef207b44017 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EDECEC" d="M32 5H18v10h18V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M11 5H4C1.791 5 0 6.791 0 9v6h11V5z"/><path fill="#EDECEC" d="M32 31H18V21h18v6c0 2.209-1.791 4-4 4zm-21 0H4c-2.209 0-4-1.791-4-4v-6h11v10z"/><path fill="#003580" d="M18 5h-7v10H0v6h11v10h7V21h18v-6H18z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ef.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ef.svg new file mode 100644 index 0000000000000000000000000000000000000000..190134b5d010ce94b0016efa8983e9565604a675 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1ef.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#68BFE5" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M27.646 11.625h-4.875v8.25c0 2.791 4.875 4.354 4.875 4.354s4.875-1.563 4.875-4.354v-8.25h-4.875z"/><path fill="#FFF" d="M27.646 24.019c-.555-.191-4.675-1.694-4.675-4.144v-8.05h9.35v8.05c0 2.449-4.12 3.952-4.675 4.144z"/><path fill="#D21034" d="M32.321 14.896v-3.071h-9.35v3.071h4.008v3.396h-4.008v1.312h4.008v4.158c.317.132.56.219.667.256.104-.036.338-.12.646-.247v-4.167h4.029v-1.312h-4.029v-3.396h4.029z"/><path fill="#FFF" d="M24.184 13.692c0 .275-.257.498-.572.498-.316 0-.572-.223-.572-.498s.256-.498.572-.498c.315 0 .572.223.572.498z"/><path fill="#FFD101" d="M23.719 13.297c-.326.057-.484-.141-.422-.328s.375-.359.672-.391c.297-.031.578.266.812.281.234.016.359-.114.406-.284s.375-.557.172-.654c.266 0 .266.281.266.281s.297-.297.516-.281c.125.219 0 .531 0 .531s.312-.125.531.016c-.422.062-.484.312-.484.312s.078.203-.031.312c-.109.109.859.312 1.391.156.531-.156 1.547-.516 2.203-.516.656 0 .797.25.953.031.156-.219-.188-.453-.75-.406s-1.516.698-1.891.263c-.094 0-.141.112-.141.112s-.234-.078-.469-.203c-.234-.125-.188.297-.062.359-.391-.016-.378-.268-.378-.268s-.482-.354-.169-.62c.023.485.453.344.688.25.234-.094.531-.016.672.109.141.125.547.234 1.062-.062.516-.297 1.906-.406 1.922.219s-.688.672-.688.672.078.375.516.297.719-.203.844.141.406.359.313.641c-.094.281-.406.412-.828.339-.422-.073-.469-.245-.125-.308.344-.062.406-.328.281-.391s-.359.188-.672.062-.719-.375-.719-.375.016.172-.266.266c-.281.094-.047.203.031.375s-.281.312-.656.39-.656.282-1.016-.156c-.359-.438.094-.562.281-.422s.375.391.531.266c.156-.125-.109-.203-.141-.438-.031-.234.016-.515.016-.515s-.5.78-1.562.936c-1.062.156-1.25.156-1.25.156l-.312-.219-.375.25-.016-.281s-.594.466-.906.538-1.166-.131-1.185-.366c-.019-.234.075-.344.356-.438.281-.094.328.062.469.188s.297.297.5.125.312-.234.312-.234l.062-.297-.297-.016.109-.343s-.219.046-.375-.095c-.156-.141-.172-.281-.312-.234-.139.048-.03.204-.389.267z"/><path fill="#964B36" d="M24.469 17.828c-.266.109-.672-.766-.438-1.016.235-.25.703.907.438 1.016zm.515-.109c-.249.022-.156-1.188 0-1.188.157 0 .344 1.157 0 1.188zm.438.191c-.311-.057.156-.785.281-.785s.078.851-.281.785zm4.937.199c-.609.017-.266-.107-.203-.272.062-.166.025-1.4.025-1.4h.35s-.109 1.063 0 1.282c.11.219.391.375-.172.39zm1.203 2.157c.145-.162-.219-.422-.469-.422s-.533.141-.743.734c-.21.594.235.422.349.094s.207-.516.379-.531c.172-.016.234.406.484.125zm-2.39 2.078c-.321-.024-.594.812-.594.812s1.438-.75.594-.812z"/><path fill="#00A651" d="M24.184 17.125c.078.25-.715-.04-.73.394-.328-.05.141-.691.438-.597-.062-.344-.506-.484-.55.078-.497-.438.136-.859.421-.672-.152-.531-.443-.522-.479-.203-.376-.312.003-.812.329-.578.326.234.35.484.35.484s.227-.809.805-.545c-.701.296-.838.826-.584 1.639z"/><path fill="#00A651" d="M25.004 16.777c-.207-.199-.332-.418-.332-.418s.221.594-.124.844c.015-.547-.36-.734-.157-.953.203-.219.547 0 .547 0s.081-.127-.271-.438c-.352-.31-.604-.297-.62-.562.353.21.893.211.957.797.074-.703.391-.719.537-.734s.49.062.615-.062c0 .25-.281.172-.469.25.25.172.266.727.266.727s-.359-.633-.516-.586c-.156.047-.26.516-.26.516s.571-.017.363.75c-.088-.422-.182-.469-.291-.469s-.245.338-.245.338z"/><path fill="#00A651" d="M25.541 17.307c.021-.292.162-.792.318-.831.052-.32.219-.773.562-.851.344-.078.422.281.344.484-.203-.297-.484-.375-.547.328.297-.078.469.156.391.469-.281-.328-.484-.367-.609-.129.328.129.334.41.167.645-.073-.406-.29-.375-.405 0-.116.374-.221-.115-.221-.115zm4.754-.53c-.357 0-.826.369-.857.942-.375-.563.084-1.188.565-1.407-.847.016-1.159.391-1.268.703-.109-.828.943-1.156 1.268-1.016-.206-.359-1.018-.329-1.425-.032 0-.687 1.215-.852 1.717-.231-.061-.503.143-.628.143-.628v.672s1.131-1.062 1.753.219c-1.003-.516-1.491.016-1.491.016s1.039-.25.896.953c-.33-.734-1.018-.656-1.018-.656s.797.36.484 1.25c-.312-.859-.767-.785-.767-.785z"/><path fill="#FFF202" d="M29.531 20.688c-.047-.469.547-.734.547-.734s1 .609 1.141.734c.141.125-.086.648-.52.785-.433.136-1.168-.785-1.168-.785z"/><path fill="#00A651" d="M29.256 22.355c-.235-.148-.385-.98 0-1.059-.146-.5.166-.75.275-.781.109-.031.514.152.819.443.306.291.571.361.595.475.024.113-.191.457-.56.488.115.345-.764.665-1.129.434z"/><path d="M24.047 20.407s.234-.095.375-.235.328-.141.484.117c.156.258.271.586.271.586s-.053-.469.432-.719.558-.312.558-.312l-.167.668s.578-.355.672-.559c.125.797-.469 1.367-.844 1.52.203.34.109.621.109.621l.688.562-.75.234-.334-.719s-.867.031-.993-.625.173-1.008 0-1.035c-.173-.027-.501-.104-.501-.104z"/><path fill="#FFF" d="M25.604 22.069l-.067.003c-.146 0-.791-.028-.89-.544-.066-.343-.01-.597.028-.765.028-.129.047-.214-.001-.284l-.024-.036-.086-.03c-.063-.01-.148-.027-.23-.045.056-.035.112-.078.159-.126.03-.029.076-.065.128-.065.065 0 .137.058.2.163.149.246.262.565.263.567l.194-.044c-.002-.017-.036-.405.378-.619.157-.081.271-.143.355-.189l-.167.67.209-.129c.07-.044.345-.216.535-.391-.021.639-.533 1.066-.798 1.174l-.107.044.06.101c.175.292.103.528.101.538l-.021.065.596.488-.489.153-.326-.699z"/><path fill="#00A651" d="M24.255 20.299c-.114-.267-.114-.267-.294-.346-.008.172 0 .281 0 .281s-.101-.328-.258-.281c-.094.375.242.454.242.454s-.148.048-.133.312c.266.108.234-.126.234-.126s-.055.24.137.378c.129-.205.072-.672.072-.672z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..0091bc78b0e4c41a5d43c2059793228265831cb9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#BA6747" d="M23.278 22.656c.276-.516.468-1.031.692-1.188.225-.156 1.484-.031 1.729.25.245.281.12 1.734-.364 2.547-.484.812-1.387 1.125-1.725 1.062s-.557-.672-.619-.891c-.062-.219.144-.297.619-.156s1.178-1.062 1.162-1.5c-.406-.297-.762-.062-.92.297-.157.361-.574-.421-.574-.421z"/><path fill="#D7A896" d="M22.648 23.703c.066.291.338.982.63 1.366-.142-.852.495-.585.448-.241.219.062-.059-.484-.115-.797-.057-.312-.01-.922-.525-.891-.516.032-.485.354-.438.563z"/><path fill="#BA6747" d="M32.612 22.656c-.276-.516-.468-1.031-.692-1.188-.225-.156-1.484-.031-1.73.25-.245.281-.12 1.734.364 2.547.484.812 1.387 1.125 1.725 1.062.338-.062.549-.672.611-.891.062-.219-.144-.297-.619-.156s-1.17-1.062-1.154-1.5c.406-.297.762-.062.92.297.158.361.575-.421.575-.421z"/><path fill="#E9CFC6" d="M32.909 23.453c.073-.312-.297-.797-.531-1.263-.954 1.792-3.47 2.025-4.433 2.028-.963-.003-3.478-.236-4.433-2.028-.234.466-.604.95-.531 1.263.073.312 2.337 1.938 4.948 1.951v.002l.016-.001.016.001v-.002c2.611-.013 4.875-1.639 4.948-1.951z"/><path fill="#D7A896" d="M33.242 23.703c-.066.291-.338.982-.63 1.366.142-.852-.495-.585-.448-.241-.219.062.059-.484.115-.797.057-.312.01-.922.525-.891.516.032.486.354.438.563z"/><path fill="#FFF" d="M27.958 10.646H23.27v6.5c0 5.708 4.688 6.958 4.688 6.958s4.688-1.25 4.688-6.958v-6.5h-4.688z"/><path fill="#0072C4" d="M27.957 23.703c-.517-.155-4.354-1.481-4.354-6.55V11.04h8.709v6.113c0 5.022-3.872 6.398-4.355 6.55z"/><path fill="#FFF" d="M26.094 16.688c.109-.438.188-1.047-.078-1.141-.266-.094-.736-.375-.892-.875-.155-.5-.077-1.656-.218-1.734-.141-.078-.562.109-.812-.203s-.094-.423.078-.532c.172-.109.656-.359.625-.453-.031-.094.031-.243.327-.344.548-.188.985.297 1.157.484.172.188.625.438.828.453.203.016 2.656.047 2.938.078.281.031 1 .219.938 1.078s-.184 1.688-.303 1.844c-.119.156-.197.203-.197.203s.125.688.109.812c-.016.125-.234.172-.25-.047-.016-.219-.094-.734-.094-.734l-.422-.077s.016.75-.125.969c-.141.219-.5.078-.406-.078.094-.156.141-.297.141-.484s-.047-.469-.141-.5c-.094-.031-.562.156-.906.156s-1.109-.219-1.25-.094c-.141.125-.328.766-.422 1.125-.094.359-.25.141-.234-.031s.078-.75-.016-.656c-.094.094-.062.531-.125.672-.063.14-.25.109-.25.109z"/><path fill="#015121" d="M24.984 15.906s.203 1.166.969 1.672 3.979.375 4.531-.016c.553-.391 1.062-1.344 1.062-1.344s-.453 0-.609-.172c-.453.25-.719.141-.812-.016-.359.359-.328.141-.375.031-.312.359-.766.141-.906.016-.312.203-.781.078-.875-.047-.359.312-.891.234-1 .094-.234.391-.578.25-.766.125-.266.25-.375-.031-.469-.203-.218.376-.578.11-.75-.14z"/><path fill="#FFF" d="M23.422 17.375s.484.062.859-.281c.375-.344 1.016-.516 1.484 0 .469.516 1 .5 1.406.078.406-.422 1.016-.622 1.594-.045.578.577 1.078.33 1.422 0 .344-.33 1.062-.545 1.531 0 .469.545.797.249.797.249l-.203 1.438s-.141.031-.578-.344c-.438-.375-1.047-.516-1.484-.047-.438.469-1.094.484-1.562.031-.469-.453-1.016-.406-1.422-.047-.406.359-1.109.531-1.672 0-.562-.531-1.047-.266-1.328.016-.281.281-.662.391-.662.391l-.182-1.439zm.481 2.565c.124-.042.257-.11.378-.222.375-.344 1.016-.516 1.484 0 .469.516 1 .5 1.406.078.406-.422 1.016-.622 1.594-.045.578.576 1.078.329 1.422 0 .344-.33 1.062-.546 1.531 0 .094.108.182.183.263.234.081.311-.359 1.018-.419.979-.415-.272-.93-.329-1.312.081-.438.469-1.094.484-1.562.031-.469-.453-1.016-.406-1.422-.047-.406.359-1.109.531-1.672 0-.486-.46-.915-.322-1.203-.095-.045.038-.746-.905-.488-.994zm1.221 2.049c.223.014.447.109.642.323.469.516 1 .5 1.406.078.406-.422 1.016-.622 1.594-.045.578.576 1.078.329 1.422 0 .125-.12.3-.226.494-.284-.644.924-2.479 1.861-2.724 1.86-.248 0-2.239-.874-2.834-1.932z"/><path d="M24.703 12.094c.078-.172.342-.125.421 0s-.499.172-.421 0z"/><path fill="#DD8B59" d="M23.846 19.719c-.095.115 1.201.682 1.201.682s.115.615.219.537.547.007.547.007.106 1.837 2.156 1.837c2.05 0 2.601-1.963 2.601-1.963s.74.009.827.054c.087.045-.178-.243-.068-.472.109-.229.375-.494.219-.557-.156-.062-1.812.391-1.812.391s.031 1.484-1.766 1.484-1.562-.969-1.562-.969-2.416-1.21-2.562-1.031z"/><path fill="#DD8B59" d="M26.484 21.322c0 .048-.038.086-.086.086-.048 0-.086-.038-.086-.086v-3.955c0-.047.038-.086.086-.086.048 0 .086.038.086.086v3.955zm1.485.483c0 .039-.031.07-.07.07-.039 0-.07-.031-.07-.07v-4.719c0-.039.031-.07.07-.07.039 0 .07.031.07.07v4.719zm1.547-.258c0 .043-.035.078-.078.078s-.078-.035-.078-.078v-4.188c0-.043.035-.078.078-.078s.078.035.078.078v4.188z"/><path fill="#FECF3D" d="M25.875 18s.141.281.609.156c.469-.125.484-.516.484-.516l-1.093.36zm2.578-.625l-1.062.266s.109.347.508.267c.398-.08.554-.533.554-.533zm.469.5s.25.297.594.188c.344-.109.562-.516.562-.516l-1.156.328zm-1.797.313l-1.34.368s-.129.24-.082.49.172.484.172.484.125-.312.438-.375.531.188.531.188-.12-.572.281-1.155zm.266 0s-.273.155-.266.625c.004.257.266.581.266.581s.141-.253.438-.347c.297-.094.625.172.625.172s-.123-.379-.078-.672c.045-.293.25-.638.25-.638l-1.235.279zm1.437.234s-.094.204-.094.438.188.671.188.671.094-.328.438-.406c.344-.078.531.156.531.156s-.115-.231-.065-.569c.05-.337.394-.625.394-.625l-1.392.335zm-1.937 1.031l-1.171.219s.14.375.585.328c.445-.047.586-.547.586-.547zm1.625-.059s-1.125.061-1.125.138c0 .076.109.359.484.297s.641-.435.641-.435zm1.453.059l-1.109.248s.156.283.555.205c.397-.078.554-.453.554-.453z"/><path fill="#FF0100" d="M26.312 17.367l-.828.274.828.088zm1.578-.267l-.828.274.828.088zm1.563.181l-.828.274.828.089z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..b49556b5672354572de36ee89cccbb14378f1054 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#75B2DD" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M18.3 7.6l-.584 1.797h-1.889l1.528 1.11-.583 1.796 1.528-1.11 1.528 1.11-.583-1.796 1.528-1.11h-1.889zm8.603 9.816v-1.889l-1.11 1.528-1.796-.583L25.107 18l-1.11 1.528 1.796-.583 1.11 1.528v-1.889L28.7 18zm-7.658 8.077l.583-1.796-1.528 1.11-1.528-1.11.583 1.796-1.528 1.11h1.889L18.3 28.4l.584-1.797h1.889zm-8.438-8.438l-1.11-1.528v1.889L7.9 18l1.797.584v1.889l1.11-1.528 1.796.583L11.493 18l1.11-1.528z" fill="#FFF"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..93a127285147b714d4ac67dceaae6fd42ba163b8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M9.444 5H4C1.791 5 0 6.791 0 9v5.5h9.444V5zM36 14.5V9c0-2.209-1.791-4-4-4H16.5v9.5H36z"/><path fill="#0065BD" d="M36 16v-1.5H16.5V5H15v11zM11 5H9.444v9.5H0V16h11z"/><path fill="#EEE" d="M0 21.5V27c0 2.209 1.791 4 4 4h5.444v-9.5H0zm16.5 0V31H32c2.209 0 4-1.791 4-4v-5.5H16.5z"/><path fill="#ED2939" d="M15 16V5h-4v11H0v4h11v11h4V20h21v-4z"/><path fill="#0065BD" d="M15 20v11h1.5v-9.5H36V20zm-4 0H0v1.5h9.444V31H11z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..4eafe7aa5b829db665fd04bc0c35c1254f13b444 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1eb-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED2939" d="M36 27c0 2.209-1.791 4-4 4h-8V5h8c2.209 0 4 1.791 4 4v18z"/><path fill="#002495" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..a8c6fa417dd5a8a07f37f9a3338ddcc1b13a6848 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009E60" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#3A75C4" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-5H0v5z"/><path fill="#FCD116" d="M0 14h36v8H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e7.svg new file mode 100644 index 0000000000000000000000000000000000000000..21b97e9fcb089eadb5e7f27fe8ff0978519d500d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M0 9.059V13h5.628zM4.664 31H13v-5.837zM23 25.164V31h8.335zM0 23v3.941L5.63 23zM31.337 5H23v5.837zM36 26.942V23h-5.631zM36 13V9.059L30.371 13zM13 5H4.664L13 10.837z"/><path fill="#CF1B2B" d="M25.14 23l9.712 6.801c.471-.479.808-1.082.99-1.749L28.627 23H25.14zM13 23h-2.141l-9.711 6.8c.521.53 1.189.909 1.938 1.085L13 23.943V23zm10-10h2.141l9.711-6.8c-.521-.53-1.188-.909-1.937-1.085L23 12.057V13zm-12.141 0L1.148 6.2C.677 6.68.34 7.282.157 7.949L7.372 13h3.487z"/><path fill="#EEE" d="M36 21H21v10h2v-5.836L31.335 31H32c1.117 0 2.126-.461 2.852-1.199L25.14 23h3.487l7.215 5.052c.093-.337.158-.686.158-1.052v-.058L30.369 23H36v-2zM0 21v2h5.63L0 26.941V27c0 1.091.439 2.078 1.148 2.8l9.711-6.8H13v.943l-9.914 6.941c.294.07.598.116.914.116h.664L13 25.163V31h2V21H0zM36 9c0-1.091-.439-2.078-1.148-2.8L25.141 13H23v-.943l9.915-6.942C32.62 5.046 32.316 5 32 5h-.663L23 10.837V5h-2v10h15v-2h-5.629L36 9.059V9zM13 5v5.837L4.664 5H4c-1.118 0-2.126.461-2.852 1.2l9.711 6.8H7.372L.157 7.949C.065 8.286 0 8.634 0 9v.059L5.628 13H0v2h15V5h-2z"/><path fill="#CF1B2B" d="M21 15V5h-6v10H0v6h15v10h6V21h15v-6z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..e4f37f95a7d53fa35622765fcab9b0211a4f28e7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#007A5E" d="M3.5 8.5h29v19h-29z"/><path fill="#FCD116" d="M3.5 8.5h29l-29 19h29l-29-19z"/><circle fill="#CE1126" cx="18" cy="18" r="3.5"/><path d="M18 14.798l.719 2.213h2.326l-1.882 1.367.719 2.212L18 19.223l-1.882 1.367.719-2.212-1.882-1.367h2.326zm0-9.616l.386 1.188h1.249l-1.01.734.386 1.188L18 7.558l-1.011.734.386-1.188-1.01-.734h1.249zm8.02 0l.386 1.188h1.249l-1.01.734.386 1.188-1.011-.734-1.01.734.386-1.188-1.011-.734h1.249zm-16.04 0l.386 1.188h1.249l-1.011.734.386 1.188-1.01-.734-1.011.734.386-1.188-1.01-.734h1.249zm8.02 22.5l.386 1.188h1.249l-1.01.734.386 1.188L18 30.058l-1.011.734.386-1.188-1.01-.734h1.249zm8.02 0l.386 1.188h1.249l-1.01.734.386 1.188-1.011-.734-1.01.734.386-1.188-1.011-.734h1.249zm-16.04 0l.386 1.188h1.249l-1.011.734.386 1.188-1.01-.734-1.011.734.386-1.188-1.01-.734h1.249z" fill="#FCD116"/><path fill="#CE1126" d="M6.118 19.067c.304.315.645.579.962.712.005-.349-.057-.748-.164-1.148-.268-.251-.572-.464-.868-.577-.043.318-.012.673.07 1.013z"/><path fill="#FCD116" d="M7.643 19.563c.803-2.916-2.06-2.738-2.803-3.67.512 1.068-1.329 3.617 1.739 4.214-.202-.276-.366-.649-.46-1.04-.082-.34-.113-.695-.07-1.013.297.113.6.326.868.577.313.293.578.637.726.932z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..8c2bd5a6353e51f2b78aa085662b760d501abba4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M32 5H20.5v10.5H36V9c0-2.209-1.791-4-4-4z"/><path fill="#E8112D" d="M20.5 5h-5v10.5H0v5h15.5V31h5V20.5H36v-5H20.5z"/><path fill="#E8112D" d="M28.915 9.585c.031-.623.104-1.244.221-1.86-.588.073-1.183.073-1.77 0 .117.615.19 1.237.221 1.86-.623-.031-1.244-.104-1.86-.221.073.588.073 1.183 0 1.77.615-.117 1.237-.19 1.86-.221-.031.623-.104 1.244-.221 1.86.588-.073 1.183-.073 1.77 0-.117-.615-.19-1.237-.221-1.86.623.031 1.244.104 1.86.221-.073-.588-.073-1.183 0-1.77-.616.118-1.237.191-1.86.221z"/><path fill="#EEE" d="M15.5 5H4C1.791 5 0 6.791 0 9v6.5h15.5V5z"/><path fill="#E8112D" d="M8.415 9.585c.031-.623.104-1.244.221-1.86-.588.073-1.183.073-1.77 0 .117.615.19 1.237.221 1.86-.623-.031-1.244-.104-1.86-.221.073.588.073 1.183 0 1.77.615-.117 1.237-.19 1.86-.221-.031.623-.104 1.244-.221 1.86.588-.073 1.183-.073 1.77 0-.117-.615-.19-1.237-.221-1.86.623.031 1.244.104 1.86.221-.073-.588-.073-1.183 0-1.77-.616.118-1.237.191-1.86.221z"/><path fill="#EEE" d="M36 27v-6.5H20.5V31H32c2.209 0 4-1.791 4-4z"/><path fill="#E8112D" d="M28.915 26.415c.031.623.104 1.244.221 1.86-.588-.073-1.183-.073-1.77 0 .117-.615.19-1.237.221-1.86-.623.031-1.244.104-1.86.221.073-.588.073-1.183 0-1.77.615.117 1.237.19 1.86.221-.031-.623-.104-1.244-.221-1.86.588.073 1.183.073 1.77 0-.117.615-.19 1.237-.221 1.86.623-.031 1.244-.104 1.86-.221-.073.588-.073 1.183 0 1.77-.616-.118-1.237-.191-1.86-.221z"/><path fill="#EEE" d="M15.5 20.5H0V27c0 2.209 1.791 4 4 4h11.5V20.5z"/><path fill="#E8112D" d="M8.415 26.415c.031.623.104 1.244.221 1.86-.588-.073-1.183-.073-1.77 0 .117-.615.19-1.237.221-1.86-.623.031-1.244.104-1.86.221.073-.588.073-1.183 0-1.77.615.117 1.237.19 1.86.221-.031-.623-.104-1.244-.221-1.86.588.073 1.183.073 1.77 0-.117.615-.19 1.237-.221 1.86.623-.031 1.244-.104 1.86-.221-.073.588-.073 1.183 0 1.77-.616-.118-1.237-.191-1.86-.221z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..2f10cee3c827174186fcbbcc4bb534c5f0452cd6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#078930" d="M32 5H4c-1.006 0-1.915.384-2.618.998L16.228 16.72h.828L18 13.814l.944 2.906H22l-2.472 1.796.249.767 14.841 10.718C35.458 29.269 36 28.203 36 27V9c0-2.209-1.791-4-4-4z"/><path fill="#FCDD09" d="M20.472 21.422L18 19.626l-2.472 1.796.944-2.906L14 16.72h2.228L1.382 5.998C.542 6.731 0 7.797 0 9v18c0 2.209 1.791 4 4 4h28c1.006 0 1.915-.384 2.618-.998L19.777 19.284l.695 2.138z"/><path fill="#DA121A" d="M16.472 18.516l-.944 2.906L18 19.626l2.472 1.796-.695-2.138-.249-.768L22 16.72h-3.056L18 13.814l-.944 2.906H14z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..84f604394718d8a1f9df541e38d18e241fb06f15 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#E8112D" d="M21 31h-6V21H0v-6h15V5h6v10h15v6H21z"/><path fill="#F9DD16" d="M27.5 17H19V9.5l1-1h-4l1 1V17H8.5l-1-1v4l1-1H17v7.5l-1 1h4l-1-1V19h8.5l1 1v-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..33302188d6e79a25429ade141d236656997b706f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CC212D" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FBD116" d="M15.423 22h5.185l-2.592-1.884zm3.587-4.941h3.215l-2.601 1.889.991 3.052H36v-8H18.016zm-2.602 1.889l-2.601-1.889h3.215L18.016 14H0v8h15.416z"/><path fill="#288541" d="M20.617 22.006L20.608 22h-5.186l-.009.006.003-.006H0v5c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-5H20.615l.002.006z"/><path d="M13.807 17.059l2.601 1.889L15.416 22l-.002.006.009-.006 2.593-1.884L20.608 22l.009.006-.002-.006-.991-3.052 2.601-1.889H19.01L18.016 14l-.994 3.059z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..432a7272b4e93e8826cd4b9913e083a36e1a1395 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DA1C0B" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-5h36v5z"/><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v14h36V9c0-2.209-1.791-4-4-4z"/><path fill="#DA1C0B" d="M14.451 10.363v.779h-.778v-.779h-1.557v.779h-.779v-.779h-.778v1.557h.778v3.892h3.114V11.92h.779v-1.557z"/><path fill="#DA1C0B" d="M15.241 14.255v.779h-.779v-.779h-.778v.779h-1.557v-.779h-.779v.779h-.778v-.779h-.778v1.557-.001.001h.778v4.254l-.778.416v.779h6.227v-.779l-.778-.416v-4.254h.778v-1.557z"/><path d="M12.116 13.477h1.557v1.557h-1.557z"/><path d="M13.673 13.477c0 .43-.348.778-.778.778-.43 0-.778-.348-.778-.778 0-.43.348-.778.778-.778.43-.001.778.348.778.778zm0 4.903c0-.621-.157-1.125-.778-1.125s-.778.504-.778 1.125v1.325h1.557V18.38h-.001z"/><path fill="#DA1C0B" d="M24.91 10.363v.779h-.778v-.779h-1.557v.779h-.778v-.779h-.779v1.557h.779v3.892h3.113V11.92h.78v-1.557z"/><path fill="#DA1C0B" d="M25.69 14.255v.779h-.78v-.779h-.778v.779h-1.557v-.779h-.778v.779h-.779v-.779h-.778v1.557-.001.001h.778v4.254l-.778.416v.779h6.227v-.779l-.777-.416v-4.254h.777v-1.557z"/><path d="M22.575 13.477h1.557v1.557h-1.557z"/><path d="M24.132 13.477c0 .43-.349.778-.778.778-.43 0-.778-.348-.778-.778 0-.43.349-.778.778-.778.429-.001.778.348.778.778zm0 4.903c0-.621-.157-1.125-.778-1.125s-.778.504-.778 1.125v1.325h1.557V18.38h-.001z"/><path fill="#DA1C0B" d="M20 8v1h-1V8h-2v1h-1V8h-1v2h1v5h4v-5h1V8z"/><path fill="#DA1C0B" d="M21 13v1h-1v-1h-1v1h-2v-1h-1v1h-1v-1h-1v9h8v-9z"/><path d="M17 12h2v2h-2z"/><circle cx="18" cy="12" r="1"/><path d="M19.444 18.298c0-.798-.646-1.445-1.444-1.445s-1.444.647-1.444 1.445v2.167h2.889v-2.167h-.001z"/><path fill="#FFF100" d="M18.162 23.349v.133l1.079 1.078-1.079 1.078v4.717h-.348v-.527h-1.191v-.707h.348v.361h.843v-1.049h-.843v.355h-.348v-.702h1.191v-2.45l-1.08-1.076 1.08-1.074v-.137z"/><path fill="#DA1C0B" d="M17.24 24.557l.748-.748.748.749-.749.748z"/><path fill="#FFF100" d="M18.147 21.32h-.294c-.243 0-.44.3-.44.669v1.338c0 .369.197.669.44.669h.294c.243 0 .44-.3.44-.669v-1.338c0-.369-.197-.669-.44-.669zm.11 2.029c0 .209-.111.377-.247.377s-.248-.168-.248-.377V22c0-.207.111-.375.248-.375s.247.168.247.375v1.349z"/><path fill="#FFF100" d="M19.326 20.265c-.107-.06-.25-.058-.318.003L18 21.177l-1.008-.909c-.068-.061-.211-.062-.318-.003-.108.059-.14.156-.072.218l1.232 1.108c.038.034.1.045.166.041.066.004.127-.007.166-.041l1.232-1.108c.069-.062.037-.16-.072-.218z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..8a2ba3e4fe488a805235d53f4d94bbbb2754784b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D00C33" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0v9z"/><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><circle fill="#EEE" cx="13.5" cy="18" r="8"/><path fill="#D00C33" d="M13.5 10c-4.418 0-8 3.582-8 8h16c0-4.418-3.582-8-8-8z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..383cf9d3c274867a73545c04198c486975969fe8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CC162B" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#3C762C" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#EEE" d="M0 21h36v2H0zm0-8h36v2H0z"/><path fill="#0D218A" d="M0 15h36v6H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..16f4a9027c0a0714c7bc0bea32b2f81f3b527bc8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FCD116" d="M12 5h12v26H12z"/><path fill="#009460" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..ca9e4c6a646112143a46b872e770752c3bc197f8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002488" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#141414" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V14H0v13z"/><path fill="green" d="M29 28.479s-8.396-4.417-12.458-5.75-5.146-.292-5.375.208c.438-1.188.896-1.479.896-1.479s-1.604.416-1.583 1.416c-.333-.896.791-2 2.271-2.021-1.333-.188-3.646.021-4.062 1.333.021-1.354 2.375-1.729 3.333-1.688-2.396-.75-4.396-.729-4.542.271-.167-.438.292-.797.292-.797s-.938-.079-1.396.338c-.021-.375 1.521-.749 2.271-.666-1.312-.521-2.333-.606-2.583-.012-.085-.694 2.353-.882 3.478-.632-2.625-.958-3.604-1.333-4.583-.312 0-.708.854-.979 1.458-.917-.521-.542-.916-.896-1.458-.917.312-.125.979.125.979.125s-.75-.792-1.271-1.042c.917.146 2.625 1.917 2.75 2.062s.854.312.854.312-2.375-1.938-2.458-2.562c.979.479 2.896 2.583 2.896 2.583s.479.271.5.062c.021-.208-2.875-2.104-2.833-3.188.583.812 1.417 1.729 1.417 1.729s-.604-.792-.542-1.521c.583 1.042 1.458 2.312 2.25 2.75-1.302-1.278-1.438-2.021-1.333-2.292.708 1.292 1.854 2.583 2.042 2.667s.292.062.292.062-.812-.854-.938-1.396c.562.396.958 1.312 1.083 1.354s.271-.042.271-.042-1.208-1.25-1.208-1.854c.583.458 1.354 1.729 1.458 1.917s.583.521.646.375-1.729-1.771-1.208-2.042c.833.688 1.312 1.688 1.396 1.708s.458.167.396.042-1.175-1.531-.896-2.312c.061.829.917 2.417 2.396 2.771s5.875 3.312 8.812 4.188 8.229 2.042 8.229 2.042l-.167.25s-7.771-2.042-7.771-1.979.229.271.229.271 7.459 1.958 7.438 2.021-.168.356-.168.356l-7.562-2.354h-.229s7.542 2.542 7.542 2.604-.146.333-.146.333l-7.792-2.938.25.292s7.438 2.832 7.417 2.916-.209.292-.209.292l-7.083-2.896-.417-.104 7.375 3.188-.229.271-6.854-3.041h-.229l6.938 3.438-.272.207z"/><path fill="#FCDD09" d="M25.351 24.345s-.259-.883-1.971-.919l.004-.004c.933-.933 1.781-.845 2.245-.663 0 0-.433-.78-2.056-.491.716-1.012 1.531-1.094 2.008-1.01 0 0-.598-.724-2.215-.043.01-.023.024-.043.033-.068.471-1.232 1.281-1.498 1.779-1.521 0 0-.711-.544-2.073.381.245-1.205.952-1.611 1.421-1.727 0 0-.837-.415-2.029.851 0-.017.003-.032.002-.048-.065-1.316.567-1.888 1.014-2.109 0 0-.896-.22-1.781 1.247l-.001-.005c-.343-1.272.155-1.965.545-2.276 0 0-.914-.024-1.471 1.576-.579-1.158-.241-1.931.074-2.312 0 0-.895.17-1.109 1.844-.799-1.012-.628-1.836-.399-2.273 0 0-.842.351-.706 2.035-.995-.827-.997-1.669-.862-2.145 0 0-.752.517-.271 2.138-1.144-.601-1.323-1.427-1.29-1.921 0 0-.634.664.184 2.161-1.266-.345-1.616-1.123-1.687-1.616 0 0-.479.774.613 2.054-1.274-.093-1.768-.769-1.936-1.232 0 0-.318.87 1.054 1.913-.008.001-.015 0-.023.002-1.3.205-1.938-.363-2.205-.785 0 0-.117.882 1.351 1.6-1.154.374-1.853-.033-2.183-.382 0 0 .053.938 1.76 1.343-.022.013-.044.021-.066.035-1.106.714-1.919.452-2.333.175 0 0 .259.883 1.97.919l-.005.004c-.93.931-1.78.847-2.244.663 0 0 .433.781 2.055.491-.714 1.01-1.53 1.096-2.007 1.01 0 0 .598.724 2.214.042-.01.024-.024.044-.033.068-.469 1.229-1.28 1.5-1.778 1.521 0 0 .71.544 2.071-.38-.243 1.203-.95 1.612-1.419 1.726 0 0 .836.415 2.028-.851 0 .016-.003.031-.002.048.067 1.314-.565 1.889-1.013 2.109 0 0 .896.22 1.781-1.247l.001.005c.344 1.271-.154 1.965-.544 2.275 0 0 .914.024 1.47-1.575.579 1.156.242 1.93-.074 2.312 0 0 .895-.171 1.109-1.844.8 1.011.629 1.835.399 2.272 0 0 .842-.351.707-2.035.995.826.997 1.669.862 2.144 0 0 .752-.517.271-2.137 1.147.603 1.321 1.429 1.29 1.92 0 0 .633-.663-.183-2.159 1.268.346 1.613 1.124 1.687 1.614 0 0 .478-.772-.611-2.052 1.275.093 1.765.77 1.935 1.23 0 0 .318-.869-1.054-1.913l.021-.001c1.303-.206 1.938.364 2.205.784 0 0 .117-.881-1.351-1.601 1.155-.374 1.852.035 2.183.382 0 0-.053-.937-1.759-1.344.022-.013.044-.021.065-.034 1.107-.711 1.917-.447 2.333-.171zM6.249 11.417s.043-1.479-.916-2.271c-.958-.792-1.562.062-1.521.542.042.479.455 1.104 1.217 1.333-.467-.917.167-.934.387-.812.311.172.479.625.479 1.208h.354zm.439-5.146c-1.042.542-1 2.146-.667 2.958.333.813.417 2.188.417 2.188h.5s.083-1.375.417-2.188c.333-.812.374-2.417-.667-2.958zm.438 5.146s-.043-1.479.916-2.271c.958-.792 1.562.062 1.52.542-.042.479-.455 1.104-1.217 1.333.467-.917-.167-.934-.387-.812-.311.172-.479.625-.479 1.208h-.353zm-.438.187l-.877.073.877.073.876-.073zm1.14 1.084c-.547-.297-.702-.75-.702-.75h-.877s-.155.453-.702.75c.484.078.984-.172.984-.172s-.282.688.156 1.359c.438-.672.156-1.359.156-1.359s.501.25.985.172zm9.734-1.271s.043-1.479-.916-2.271c-.958-.792-1.563.062-1.521.542.042.479.455 1.104 1.217 1.333-.467-.917.167-.934.387-.812.311.172.479.625.479 1.208h.354zM18 6.271c-1.042.542-1 2.146-.667 2.958.333.813.417 2.188.417 2.188h.5s.083-1.375.417-2.188c.333-.812.375-2.417-.667-2.958zm.438 5.146s-.043-1.479.916-2.271c.958-.792 1.562.062 1.521.542-.042.479-.455 1.104-1.218 1.333.468-.917-.167-.934-.387-.812-.311.172-.479.625-.479 1.208h-.353zm-.438.187l-.877.073.877.073.877-.073zm1.141 1.084c-.547-.297-.702-.75-.702-.75h-.877s-.155.453-.702.75c.484.078.984-.172.984-.172s-.282.687.156 1.359c.438-.672.156-1.359.156-1.359s.5.25.985.172zm9.811-1.271s.043-1.479-.915-2.271c-.959-.792-1.563.062-1.521.542.042.479.455 1.104 1.217 1.333-.467-.917.168-.934.388-.812.311.172.479.625.479 1.208h.352zm.439-5.146c-1.042.542-1 2.146-.666 2.958.333.813.416 2.188.416 2.188h.5s.083-1.375.416-2.188c.334-.812.376-2.417-.666-2.958zm.438 5.146s-.043-1.479.916-2.271c.958-.792 1.562.062 1.52.542-.042.479-.455 1.104-1.218 1.333.468-.917-.167-.934-.387-.812-.311.172-.479.625-.479 1.208h-.352zm-.438.187l-.877.073.877.073.877-.073zm1.14 1.084c-.547-.297-.702-.75-.702-.75h-.876s-.155.453-.702.75c.484.078.984-.172.984-.172s-.282.688.156 1.359c.438-.672.156-1.359.156-1.359s.5.25.984.172z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d4e7119f85dbe2e6818ff90df08e234af4d7f120 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E32118" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#3E9A00" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#0173CE" d="M7.333 13L1.91 5.604C.768 6.308 0 7.56 0 9v18c0 1.44.768 2.692 1.91 3.396L7.333 23 11 18l-3.667-5z"/><path d="M18.443 15h-2.396v4.75c0 .969.547 1.125.828 1.125h.922c.578 0 .646.479.646.479s.068-.479.646-.479h.922c.281 0 .828-.156.828-1.125V15h-2.396z"/><path fill="#FFF" d="M18.443 20.93c-.133-.141-.339-.255-.646-.255h-.922c-.188 0-.628-.09-.628-.925V15.2h4.392v4.55c0 .835-.439.925-.628.925h-.921c-.308 0-.514.114-.647.255z"/><path d="M14.922 18.703s.249.438.562.734c.578.547-.352.984-.352.984s-.289-.188-.383-.406c-.093-.218.235-.874.173-1.312z"/><path fill="#FFF" d="M15.148 20.185c-.085-.069-.179-.164-.215-.248-.015-.056.04-.273.077-.418.021-.078.041-.16.06-.243.082.104.176.213.276.308.143.135.129.22.125.248-.02.131-.189.27-.323.353z"/><path d="M15.202 19.73s.001.776.767 1.081c.943.376 1.594.22 1.672.251.078.031 0 .797 0 .797s-1.043.172-1.967-.266c-.924-.438-.877-.782-.829-.876.048-.094.11-.161.155-.405.042-.227.202-.582.202-.582z"/><path fill="#FFF" d="M17.134 21.692c-.357 0-.887-.048-1.374-.279-.668-.316-.75-.56-.735-.608.066-.115.122-.212.164-.414.128.229.343.462.706.607.452.181.913.271 1.37.271.082 0 .153-.002.211-.005.001.105-.007.262-.019.416-.082.007-.192.012-.323.012z"/><path d="M21.965 18.703s-.249.438-.562.734c-.578.547.352.984.352.984s.289-.188.383-.406c.092-.218-.236-.874-.173-1.312z"/><path fill="#FFF" d="M21.738 20.185c.085-.069.179-.164.215-.248.015-.056-.04-.273-.077-.418-.021-.078-.041-.16-.06-.243-.082.104-.176.213-.276.308-.143.135-.129.22-.125.248.02.131.189.27.323.353z"/><path d="M21.685 19.73s-.001.776-.767 1.081c-.943.376-1.594.22-1.672.251-.078.031 0 .797 0 .797s1.043.172 1.967-.266.877-.782.829-.876c-.049-.094-.11-.161-.155-.405-.042-.227-.202-.582-.202-.582z"/><path fill="#FFF" d="M19.753 21.692c.358 0 .887-.048 1.374-.279.668-.316.75-.56.735-.608-.066-.115-.122-.212-.164-.414-.128.229-.343.462-.706.607-.452.181-.913.271-1.37.271-.082 0-.153-.002-.211-.005-.001.105.007.262.02.416.081.007.191.012.322.012z"/><path d="M19.715 21.354s-.012.338-1.271.338c-1.26 0-1.271-.338-1.271-.338s-.047.538 0 .755.375.344 1.271.344c.896 0 1.225-.127 1.271-.344.047-.216 0-.755 0-.755z"/><path fill="#FFF" d="M18.443 22.253c-1.007 0-1.072-.167-1.076-.185-.015-.067-.018-.19-.016-.319.219.083.56.145 1.092.145.531 0 .873-.061 1.092-.145.002.13-.001.252-.016.319-.003.018-.069.185-1.076.185z"/><path fill="#FFD701" d="M17.854 13.476l.169.293h.339l-.17.293.17.294h-.339l-.169.293-.169-.293h-.339l.169-.294-.169-.293h.339zm-1.339.155l.23.248.33-.076-.099.324.231.248-.33.076-.099.324-.231-.248-.33.076.098-.324-.23-.248.33-.076zm-1.259.431l.273.201.31-.138-.037.338.274.199-.309.137-.036.337-.274-.2-.309.137.035-.336-.274-.2.31-.137zm3.862-.586l-.169.293h-.339l.17.293-.17.294h.339l.169.293.17-.293h.339l-.169-.294.169-.293h-.339zm1.34.155l-.23.248-.331-.076.1.324-.231.248.33.076.098.324.232-.248.33.076-.099-.324.231-.248-.33-.076zm1.259.431l-.274.201-.309-.138.037.338-.275.199.31.137.036.337.274-.2.309.137-.035-.336.273-.2-.309-.137z"/><path fill="#A36629" d="M18.443 20.625c-.6 0-.693-.219-.49-.688.203-.469.312-1.104.312-1.873 0-.768-.273-.94-.59-1.237-.316-.297.162-.188.384 0s.303.359.303.359v-.719l.248.078v.547s.36-.312.602-.344c.241-.031.382.156.069.25-.312.094-.671.255-.671 1.065 0 .81.124 1.654.28 1.951.157.298.153.611-.447.611z"/><path fill="#009A3B" d="M17.75 17.547c-.318.167-.543-.203-.543-.203s-.289.203-.561.062c-.271-.141-.229-.266 0-.391s.505-.156.505-.156.071-.344.194-.578c.123-.234.33-.328.33-.328s.252-.547.687-.578c.435-.031.435.422.435.422s.27 0 .322.156c.24-.25.662-.219.756-.109.094.109 0 .344 0 .344s.371-.109.451.016c.08.125 0 .286 0 .286s.299.058.158.386-.578.234-.578.234-.178.188-.37.172c-.192-.016-.255-.282-.255-.282s-.298.078-.484-.188c-.187.281-.531.125-.578.016-.047.36-.141.547-.469.719z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..74d842d61db77c03127bb27d4fb5e90487deb50b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0D5EB0" d="M4 31h28c.702 0 1.361-.182 1.935-.5H2.065c.574.318 1.233.5 1.935.5z"/><path fill="#EEE" d="M8.5 19.5H0V22h36v-2.5H14zM0 27c0 .17.014.336.035.5h35.931c.02-.164.034-.33.034-.5v-2H0v2zm14-13h22v2.5H14zm0-5.5V11h22V9c0-.17-.014-.336-.035-.5H14z"/><path fill="#0D5EB0" d="M14 11h22v3H14zM0 22h36v3H0zm2.065 8.5h31.87c1.092-.605 1.869-1.707 2.031-3H.035c.161 1.293.938 2.395 2.03 3zM0 14h5.5v5.5H0zm14 2.5V14H8.5v5.5H36v-3zm19.935-11C33.361 5.182 32.702 5 32 5H4c-.702 0-1.361.182-1.935.5C.973 6.105.196 7.207.034 8.5.014 8.664 0 8.83 0 9v2h5.5V5.5h3V11H14V8.5h21.965c-.161-1.293-.938-2.395-2.03-3z"/><path fill="#EEE" d="M8.5 11V5h-3v6H0v3h5.5v5.5h3V14H14v-3z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..d8b1e5febeb8a2c8f92c97bf96de37d65d088f45 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#CDAD57" d="M26.656 10c-.135-.104-.344-.234-.641-.406-.297-.172-.359-.531-.219-.797.141-.266.475-.359.393-.109-.081.25-.169.557 0 .583.169.026.122-.333.278-.317.156.016-.156.578 0 .594.156.016.109-.5.281-.438s.141.516 0 .547.018.234.119.343c.102.109-.07.108-.211 0zm.799 0c.135-.104.344-.234.641-.406.297-.172.359-.531.219-.797-.141-.266-.475-.359-.394-.109s.169.557 0 .583-.122-.333-.278-.317c-.156.016.156.578 0 .594-.156.016-.109-.5-.281-.438-.172.062-.141.516 0 .547.141.031-.016.234-.117.344-.102.108.07.107.21-.001z"/><path fill="#923F00" d="M26.917 10.875c.091-.348-.021-.687-.292-.583s-.521-.062-.479-.146.355-.333.771-.333.957.229.916.333-.5.198-.5.198.063.406.834.406 1.416.188 1.271 1.125-.188 1.062-.312 1.021-.146-.354-.083-.625-.104-.646-.188-.375-.251.792-.459.833.083-.792.062-.979-.5-.146-.521.146.037.771-.138.896c-.175.125-.195-.292-.175-.583s-.187-.75-.208-.354-.042.896-.229.958 0-.479-.062-.812-.312-.73-.208-1.126z"/><path fill="#FFF" d="M27.516 15.609c-.266.25-1.266.812-1.656-.109.938.375 1.491-.438 1.491-.438l.165.547zm-1.375-2.218C25.726 12.109 24.797 12 24.797 12s-.047.406.156.695c-.67-.062-1.328-.367-1.328-.367-.188.531.938 1.094 1.625 1.062-.328.328-.016.61.297.665-.156-.383.344-.639.453-.339s.141-.325.141-.325z"/><path fill="#1500FF" d="M26.312 15.597c-.843.091-1.442-1.203-1.439-1.587.503.147.909.491.909.491s.133-1.142.238-1.422c.418.313.527 1.188.387 1.594.459.022.547.406.406.688-.219-.314-.451-.017-.501.236z"/><path fill="#FFF" d="M28.745 15.609c.266.25 1.266.812 1.656-.109-.938.375-1.491-.438-1.491-.438l-.165.547zm1.375-2.218C30.535 12.109 31.464 12 31.464 12s.047.406-.156.695c.67-.062 1.328-.367 1.328-.367.188.531-.938 1.094-1.625 1.062.328.328.016.61-.297.665.156-.383-.344-.639-.453-.339-.11.3-.141-.325-.141-.325z"/><path fill="#1500FF" d="M29.949 15.597c.843.091 1.442-1.203 1.44-1.587-.503.147-.909.491-.909.491s-.133-1.142-.238-1.422c-.418.313-.527 1.188-.387 1.594-.459.022-.547.406-.406.688.218-.314.449-.017.5.236z"/><path fill="#656263" d="M28.203 17.406c-1.297 0-1.75-.594-1.625-1s.562-.188.703-.297c.141-.109.141-.828-.188-1.156-.328-.328-.531-.672-.391-.844-.188-.312.107-.453.194-.812.087-.359.18-.694.316-.734.137-.04.208.297.255.234.047-.062.1-.344.331-.359.231-.016.2.234.278.297.078.062.141-.29.359-.297.219-.008.281.297.375.313.094.016.125-.225.312-.188s.125.516.25.719c.125.203.391.594.234.828.219.156-.016.438-.281.641-.266.203-.578.703-.391 1.266.172.375.828-.016.984.219.16.233.098 1.17-1.715 1.17z"/><path fill="#FFF" d="M26.559 13.891c0-.375 1.004-.5 1.566-.5s1.594.13 1.594.5-.785 0-1.58 0-1.58.359-1.58 0z"/><path fill="#1500FF" d="M27.588 13.423c-.176.02-.353.051-.511.093-.052.169-.022.353.069.493.151-.025.321-.055.503-.08-.105-.124-.147-.306-.061-.506zm.49-.031v.502c.021-.001.04-.003.061-.003.192 0 .383.022.563.05.056-.062.095-.133.095-.218 0-.119-.073-.219-.17-.304-.182-.02-.534-.027-.549-.027zm.97.606c.392.07.671.112.671-.108 0-.194-.285-.321-.636-.398.058.072.104.149.104.231.001.116-.065.204-.139.275z"/><path fill="#ADB0B2" d="M26.662 14.286c.041-.176 1.477.808 1.477.808s1.519-1.061 1.534-.917c.015.144-1.534 1.182-1.534 1.182s-1.518-.897-1.477-1.073z"/><path fill="#6A4C2D" d="M26.688 18.438c-.688.656-3.438 3.031-3.594 3.531-.156.5.172.625.656.297-.172.391.047.547.156.562.109.016.562-.141.75-.547.203.328.719.375.812.312.094-.062.141-.172.141-.172s.09.471.264.407c.174-.063.328-.313.439-.298.11.016-.007.234.247.219.254-.016.357-.125.493-.266.136-.141.354.062.464.031.109-.031.219-.703.391-1.188.171-.482-1.219-2.888-1.219-2.888z"/><path fill="#FFF" d="M29.188 20.875c.459.104.969-.021 1.214.125s.432.271.786.292 1.021-.291 1.167 0 .333.708.521.771.896.291.188.333-2.291 0-2.291 0l.188.25-1.386.084s-.813-.709-.776-1.209.389-.646.389-.646z"/><path fill="#00713D" d="M27.516 20.875c-.565.342-.302.771-.302.771s.091.584.137.521c.046-.062.299-.271.299-.271s-.044.466-.037.447c.007-.019.309.001.309.001s.11.409.157.491c.047.082.308-.189.308-.189s.25.16.359.205c.109.045.151-.288.151-.288s.296.378.486.272c.19-.105.43-.418.43-.418l-.354-.312s.062-.082 0-.239c-.062-.157-.291-.22-.291-.22s.229-.166.062-.271-.783-1.063-1.714-.5z"/><path fill="#FFF" d="M30.065 16.984l-.287-.002L28.267 18l-1.512-1.018-.25.001-.13.001v2.219c0 .193.034.497.146.833.088.265.226.548.441.82.105.133.232.26.375.382.198.168.443.317.729.446.069.031.127.069.202.097.078-.029.138-.068.209-.101.285-.13.53-.279.728-.447.149-.127.281-.26.388-.398.215-.278.334-.572.431-.833.118-.317.136-.613.136-.8v-2.219l-.095.001z"/><path fill="#1E5AA6" d="M30.161 17.921l-.408-.53.313-.407-.287-.002L28.267 18l-1.512-1.018-.25.001.313.407-.443.576v.036l.429.557-.429.557v.036l.413.537-.267.347c.088.265.226.548.441.82l.387-.503.335.434-.347.45c.198.168.443.317.729.446l.207-.269.204.265c.285-.13.53-.279.728-.447l-.343-.445.347-.451.384.499c.215-.278.346-.566.431-.833l-.242-.314.378-.491v-.127l-.394-.511.394-.511.001-.127zm-.582.638l-.37.481-.37-.481.37-.481.37.481zm-.724 1.129l.354-.461.354.461-.354.461-.354-.461zm-1.149-1.129l-.357.464-.357-.464.357-.464.357.464zm-.699 1.129l.342-.444.342.444-.342.444-.342-.444zm.909 1.1l.356-.463.356.463-.356.463-.356-.463z"/><path fill="#016C00" d="M28.268 17.25c-.403-.246-1.011-.269-1.513-.268l1.506 4.234c0 .018.012.018.012 0l1.506-4.234c-.502-.001-1.11.022-1.511.268z"/><path fill="#8B9497" d="M23.922 17.641c.036-1 .203-1.5.188-1.891s.328-.391.594-.469c.266-.078.391.141.609.156.219.016.344.047.281.312s-.266.608-.312.703c-.047.094.266.688.516 1.188s.609 1.141.344 2.141c-.266 1-.422 1.359-.531 1.438-.109.078-.025-.656-.122-1s-.222-.422-.222-.422-.422.398-.578.902c-.156.504-.031.871.266 1.078.297.207.969.332 1.078.395.109.062-.219.203-.672.172-.453-.031-1.525-.412-1.927-.839-.401-.427-.949-1.125-.636-1.896.172-.422.5-.562.609-.703.109-.14.504-.966.515-1.265z"/><path fill="#FFF" d="M31.531 15.601c.341-.047 1.188 2.133 1.281 3.071.094.938.078 2.625-.484 2.688-.562.062-1.068-.156-1.245-1.094-.177-.938-.042-1.656 0-2.266s-.052-2.329.448-2.399z"/><path d="M31.389 15.601c.024-.4.408-.539.861-.46.453.078.422.781.406 1.109-.016.328.711.25.715 2.016.004 1.766-.496 2.766-.356 3.016.141.25.781.578.422.641s-.812-.312-1.125-.422.027-.547.154-1.078.064-1.111-.201-1.04c-.266.071.109 1.36-.328 1.317-.438-.043-.672-1.009-.625-1.893.047-.884.219-.947.469-1.228.25-.281.094-.406-.172-.703s-.172-.531.109-.688c.282-.157-.363-.048-.329-.587z"/><path fill="#FFF" d="M30.994 17.109c-.375.031-.76.141-.76.297s-.016.672 0 .734.531-.265.76-.25v-.781z"/><path fill="#F66B01" d="M31.531 15.601c.092-.483-.781-.023-.828.102-.047.125.735.39.828-.102z"/><path fill="#F8F001" d="M31.797 15.359c.047-.14 1.094-.312 1.266-.297s.162-.022.115.057c-.017.028-.515.096-.521.145-.014.087.439.032.516.095.051.042-.504.037-.41.106.125.093.598.305.459.253-.242-.09-1.502-.131-1.425-.359z"/><path fill="#F66B01" d="M31.63 21.233c-.233.043-.958-.011-.708.136.25.146.328.162.328.162s-.449.164-.256.246c.193.082.637.031.931.025.294-.006.51-.171.388-.303s-.334-.329-.683-.266z"/><path fill="#C11600" d="M25.054 25.078c.562.109 1.297.344 1.297.344l-.094 1.016s-.234-.344-1.469-.562c-.141-.407.266-.798.266-.798zm.187-1.703s.016.328-.422.703-.937.344-.906-.078c.422-.109.312-.946.663-1.054-.038.351.103.585.665.429zm6.473 1.703c-.562.109-1.297.344-1.297.344l.094 1.016s.234-.344 1.469-.562c.14-.407-.266-.798-.266-.798z"/><path fill="#FFBC00" d="M31.464 24.188c.359-.391.609-.375.797-.75s-.094-.672-.578-.583c-.484.089-.984.864-.984.864s-.921-.547-2.314-.547c-1.394 0-2.315.547-2.315.547s-.5-.775-.984-.864c-.484-.089-.766.208-.578.583s.438.359.797.75c-.578.391-1.047 1.172-1.047 1.172l.531.516s.297-.5.922-1.016c.547.625.547 1.578.547 1.578s.164-.672.418-.891c-.012-.609-.184-1.062-.184-1.062s.816-.5 1.893-.5c1.076 0 1.893.5 1.893.5s-.172.453-.184 1.062c.254.219.418.891.418.891s0-.953.547-1.578c.625.516.922 1.016.922 1.016l.531-.516c-.001-.001-.47-.782-1.048-1.172z"/><path fill="#C11600" d="M31.526 23.375s-.016.328.422.703.938.344.906-.078c-.422-.109-.312-.946-.663-1.054.038.351-.102.585-.665.429z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..fea623c97d8fb0a164c336028510a1dde7d1c0ab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4997D0" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4zM4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#437E24" d="M22.658 18.736c.113-.242.097-.396-.034-.259-.115.12-.283.162-.492.31l.017-.059c.183-.346.579-.179.813-.731.041-.102.25-.211-.035-.194-.204.012-.461.133-.647.393.142-.386.484-.189.624-1.119.025-.171.045-.52-.068-.234-.046.114-.156.228-.272.364.038-.192.025-.359-.015-.486.072-.111.137-.225.155-.357.031-.227-.023-.428-.109-.189-.03.086-.087.142-.147.2-.022-.08-.043-.108-.105 0-.065.112-.1.255-.12.414l-.002.01c-.015-.084-.035-.167-.054-.249.046-.312.527-.303.36-1.311-.039-.244-.057-.315-.143-.012-.08.281-.328.304-.34.866l-.021-.065c-.055-.539.314-.99.035-1.452-.148-.246-.227-.268-.211-.068.019.233-.121.48-.095.819l-.01-.022c-.059-.417.091-.543-.078-.814-.088-.138-.219-.32-.185-.092.007.046.011.1.016.156-.054-.236-.258-.381-.516-.464-.244-.079-.17.037-.08.131.128.137.095.305.254.512-.172-.083-.321-.091-.42-.215-.195-.241-.094.067-.047.206.095.272.254.418.438.511-.018.02-.01.09.042.236.064.18.143.314.228.422-.064-.04-.122-.084-.165-.148-.205-.303-.285-.337-.246.024.035.313.168.48.329.59.002.063.025.151.089.243.114.165.234.234.345.276.055.128.085.247.114.37-.007-.005-.012-.014-.02-.019-.307-.217-.23-.092-.205.097.115.891.537.585.451 1.16-.012.053-.024.104-.038.155.015-.331-.138-.518-.264-.664-.174-.201-.234-.143-.148.229.02.087.04.195.057.309l-.004-.012c-.174-.351-.225-.25-.209.017.02.257-.197.359-.057.852.042.144.063.421-.077.633l-.024.032c.308-.569-.064-.739-.03-.911.041-.195-.01-.229-.119.012-.125.278-.099.474-.061.64-.023.013-.04.02-.07.04-.099.067-.179.132-.246.194.009-.054.024-.106.029-.16.025-.255-.045-.38-.154-.104-.137.339-.383.332-.539.841-.123.411-.214.494-.405.575l-.028.012c.289-.224.448-.525.491-.875.045-.388-.051-.332-.182-.098-.125.225-.363.192-.514.683-.047.152-.158.385-.45.491.395-.281.568-.745.522-1.023-.021-.138-.086-.223-.148.005-.074.28-.279.212-.445.743-.085.27-.159.325-.513.485l.052-.01c-.207.084-.387.171-.537.26-.141-.085-.316-.168-.517-.249l.029.005c-.35-.159-.424-.213-.508-.48-.162-.525-.367-.457-.44-.733-.06-.227-.124-.143-.146-.007-.046.274.125.731.511 1.009-.285-.106-.394-.334-.441-.483-.148-.485-.383-.452-.507-.674-.129-.232-.225-.287-.179.096.041.345.198.643.483.864l-.06-.025c-.165-.078-.251-.173-.367-.554-.152-.504-.396-.496-.532-.83-.11-.272-.177-.15-.151.102.005.054.019.106.029.159-.066-.062-.145-.126-.243-.192-.03-.02-.047-.027-.07-.04.037-.164.063-.359-.061-.634-.108-.236-.158-.203-.119-.012.035.173-.335.34-.024.908l-.023-.03c-.146-.211-.123-.489-.083-.635.139-.486-.074-.587-.056-.841.018-.265-.034-.364-.205-.017l-.005.014c.017-.114.037-.221.057-.307.085-.368.023-.425-.146-.226-.125.145-.277.33-.262.657-.014-.051-.026-.103-.038-.156-.084-.566.332-.266.447-1.146.024-.187.101-.311-.204-.096-.008.005-.013.014-.02.019.029-.122.059-.24.115-.367.11-.042.228-.11.341-.273.063-.092.086-.178.087-.241.158-.109.289-.275.323-.584.04-.355-.039-.322-.241-.023-.043.063-.1.107-.163.146.083-.107.162-.238.225-.416.05-.144.058-.214.04-.234.183-.093.341-.237.433-.506.047-.138.146-.441-.046-.204-.099.123-.245.131-.415.213.158-.204.125-.371.251-.507.088-.094.163-.208-.078-.13-.257.082-.458.226-.512.459.005-.055.009-.109.016-.154.034-.226-.097-.045-.181.09-.168.268-.022.393-.077.803l-.011.025c.026-.336-.113-.58-.095-.811.016-.197-.061-.175-.207.068-.275.455.087.9.036 1.431l-.02.063c-.015-.551-.26-.573-.337-.851-.086-.3-.102-.229-.142.012-.164.996.312.987.356 1.296-.019.082-.038.164-.053.247l-.003-.014c-.007-.054-.022-.099-.034-.147l-.004-.011c-.022-.087-.042-.177-.081-.246-.061-.107-.081-.079-.103 0-.059-.057-.115-.112-.145-.198-.084-.237-.139-.038-.108.187.018.13.082.243.153.353-.039.126-.052.292-.014.482-.115-.135-.223-.248-.268-.361-.113-.282-.093.062-.068.232.138.922.477.724.617 1.108-.184-.259-.437-.379-.64-.391-.282-.017-.076.092-.034.192.231.547.621.382.802.723l.017.059c-.207-.147-.371-.189-.485-.308-.13-.135-.145.018-.033.257-.122.014-.252.024-.334-.003-.102-.034-.102.119.181.238.129.054.333.138.529.234.145.109.29.183.415.297-.389-.28-.682-.145-.9-.272-.271-.157-.124.089-.049.164.764.765.884.187 1.307.593-.066-.03-.137-.053-.217-.063-.339-.039-.46-.089-.283.125.211.256.384.38.536.448-.1-.001-.197.004-.286.022-.218.046-.143.086.004.13.18.054.294.18.494.262h-.002c-.328.102-.384.14-.135.263.425.213.722.219.958.18-.114.036-.217.086-.305.151-.18.133-.131.183.023.158.291-.047.472.04.712.04-.146.107-.268.228-.487.293-.147.044-.195.126.045.148.917.078 1.15-.496 1.588-.49.224.069.434.151.633.284-.06.046-.124.093-.159.136.011.103.247.052.271.109.03-.032.062-.055.093-.083.031.028.062.051.093.083.023-.057.219-.039.23-.141-.027-.034-.08-.069-.122-.104.204-.137.417-.22.646-.291.443-.006.679.575 1.606.496.242-.022.195-.105.047-.15-.222-.065-.346-.188-.494-.296.243.001.427-.087.721-.04.156.024.205-.026.022-.161-.088-.066-.193-.116-.308-.153.239.039.54.034.97-.182.252-.124.195-.163-.135-.266h-.002c.202-.083.317-.21.498-.265.15-.045.225-.085.004-.131-.089-.019-.188-.024-.289-.023.154-.069.33-.195.545-.454.176-.217.055-.165-.287-.126-.083.01-.156.033-.224.065.431-.415.55.174 1.326-.602.074-.073.223-.324-.051-.164-.221.129-.52-.011-.919.283.129-.121.281-.196.431-.31.197-.097.402-.181.533-.236.287-.121.287-.274.182-.24-.081.031-.211.021-.335.007zm-6.94 2.353l.105.066c-.113-.051-.244-.1-.385-.143.079.003.171.021.29.088l-.01-.011zm1.23.324l-.053-.016.037.006.016.01zm-2.118-1.441c.009.014.011.022.021.038.086.134.1.272.183.435-.039-.035-.078-.07-.116-.107-.106-.128-.113-.242-.088-.366zm-.165-4.493c-.112.149-.297.172-.469.314.099-.172.228-.333.39-.376.063-.017.124-.039.184-.063-.029.031-.063.07-.105.125zm-.17 4.54l.016.018-.012-.007-.004-.011zm1.136 1.362c.172-.035.315-.08.455-.072l.059.03c-.186-.009-.36.002-.514.042zm5.937-6.252s-.001 0 0 0c-.001 0 0 0 0 0zm-.253.275c-.043-.056-.077-.096-.108-.127.06.025.122.046.186.064.164.044.295.207.394.38-.173-.143-.359-.167-.472-.317zm-.779 5.594c-.142.043-.274.092-.388.143l.098-.062-.005.006c.122-.066.215-.084.295-.087zm.59-1.013l.022-.039c.025.125.019.24-.088.369-.039.038-.079.075-.12.11.085-.165.099-.304.186-.44zm-2.104 1.409l.042-.007-.061.019c.006-.003.013-.007.019-.012zm.798-.066l.062-.031c.146-.007.294.042.476.077-.16-.043-.343-.054-.538-.046zm1.65-1.314l.015-.018-.003.01c-.005.002-.008.006-.012.008z"/><path fill="#B1B6BA" d="M16.595 18.422s-.763.686-.857.779c-.093.093-.187.499-.187.499l.249.155 1.107-1.137-.312-.296z"/><path fill="#6C301E" d="M15.536 19.685l.234.186s-.203.202-.234.405-.577.825-.686.981c-.109.157-.25.124-.312 0-.061-.124-.201-.218-.217-.311-.017-.093.343-.421.514-.607.17-.188.357-.265.451-.373.094-.111.25-.281.25-.281zm1.107-1.092l-.473.529.126.126.455-.515z"/><path fill="#B1B6BA" d="M14.46 13.981l1.512 1.573.374-.187-.117-.169-.257.06z"/><path fill="#FAB81B" d="M16.346 20.524l.187.313.17-.157s.138.25 0 .296c-.139.048-.242 0-.242 0l-.474.387s-.187-.113-.343 0c0 0 .032-.229.126-.229.093 0 .434-.452.434-.452s-.181-.051-.144-.157c.037-.108.286-.001.286-.001z"/><path fill="#B1B6BA" d="M16.346 20.65s2.773-2.758 3.927-2.862c0 0-.873.531-1.418.967-.546.437-2.321 2.083-2.321 2.083l-.188-.188z"/><path fill="#B1B6BA" d="M19.493 18.422s.764.686.855.779c.094.093.188.499.188.499l-.248.155-1.107-1.137.312-.296z"/><path fill="#6C301E" d="M20.552 19.685l-.234.186s.203.202.234.405.578.825.686.981c.109.157.25.124.312 0s.201-.218.217-.311c.018-.093-.344-.421-.514-.607-.17-.188-.357-.265-.451-.373-.094-.111-.25-.281-.25-.281zm-1.108-1.092l.473.529-.125.126-.455-.515z"/><path fill="#B1B6BA" d="M18.785 16.264l-.176.498 1.505-1.504-.231-.042z"/><path fill="#B1B6BA" d="M21.626 13.981l-1.512 1.573-.373-.187.373-.109z"/><path fill="#FAB81B" d="M19.741 20.524l-.185.313-.17-.157s-.139.25 0 .296c.137.048.242 0 .242 0l.473.387s.188-.113.342 0c0 0-.031-.229-.125-.229s-.434-.452-.434-.452.18-.051.143-.157c-.036-.108-.286-.001-.286-.001z"/><path fill="#B1B6BA" d="M19.741 20.65s-2.773-2.758-3.926-2.862c0 0 .874.531 1.418.967.546.437 2.322 2.083 2.322 2.083l.186-.188z"/><path fill="#F9F0AA" d="M16.367 15.164c.453-.026 1.76.016 2.244 0 .482-.015.373.234.404.375.031.14-.263.296-.263.296s.31.187.716 1.278c.404 1.091.31 1.588-.234 1.621-.544.031-1.947.125-2.416.125-.467 0-.545-.171-.545-.421 0-.249.374-.624.748-.411 0 0 0-.166-.218-.789s-.686-1.293-.732-1.589c-.048-.298.062-.471.296-.485z"/><path fill="#437E24" d="M17.738 14.089c-.187-.172.073-.359.263-.343.188.016.282.124.08.343 0 0 .546.296.981.701.436.405 1.332 1.498 1.418 2.68.109 1.527-.732 2.321-1.045 2.866-.311.546-1.011 1.917-1.011 1.917s-.016-.701.904-1.979c0 0-.716 1.278-1.823 1.512 0 0 1.385-.976 1.774-1.756.389-.778.957-1.949.865-2.759-.094-.811-.24-1.499-1.315-2.03 0 0-.681-.038-.981-.28-.484-.389-.11-.872-.11-.872z"/><path fill="#E2CF81" d="M18.751 15.835c0 .047.202.3.175.3h-2.381c-.026 0-.16-.165-.16-.212l-.182-.213c.142.055.315 0 .341 0h2.38c.028 0-.173.077-.173.125zm-1.729 2.758c0 .047-.1.201-.073.201h2.381c.025 0 .245-.165.245-.212l.096-.212c-.142.055-.315 0-.341 0h-2.381c-.026 0 .073.175.073.223z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..2098ecca223084307298390744a2415d6fa08d8a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#00297B" d="M35 27c0 1.657-1.343 3-3 3H4c-1.657 0-3-1.343-3-3V9c0-1.657 1.343-3 3-3h28c1.657 0 3 1.343 3 3v18z"/><path fill="#DD2E44" d="M17.519 26.625c2.672-2.22 5.629-4.795 5.629-8.434 0-3.64-2.957-6.215-5.629-8.435-2.673 2.22-5.63 4.794-5.63 8.435 0 3.639 2.957 6.214 5.63 8.434z"/><path fill="#017BDD" d="M12.727 19.626c.615 2.561 2.794 4.497 4.792 6.202 1.999-1.705 4.178-3.642 4.792-6.202h-9.584z"/><path fill="#66AFEB" d="M22.31 19.626c.111-.457.172-.936.172-1.435 0-3.296-2.607-5.628-4.963-7.638-2.356 2.01-4.962 4.341-4.962 7.638 0 .499.06.978.17 1.435h9.583z"/><path fill="#9C8431" d="M22.463 18.664c-.025.331-.076.651-.152.962h-5.758c.071-.192.17-.488.256-.711 1.62.223 4.171.163 5.654-.251z"/><path fill="#FFF100" d="M14.938 23.423c-.441-.479-.848-.983-1.196-1.515.906.041 2.676.229 3.379.84.171.148.171.222-.042.192-.427-.058-1.567.181-2.141.483z"/><path fill="#FFF100" d="M21.789 21.05c-.932 1.88-2.66 3.404-4.27 4.778-.501-.428-1.013-.869-1.509-1.331.684-1.083 2.59-.417 2.59-1.379 0-.503-.483-.943-1.166-.992-.213-.014-.265-.023-.1-.147.782-.591 1.579.044 2.914-.562.973-.441 1.418-.408 1.541-.367z"/><path fill="#029270" d="M18.542 14.45c-.018-.023-.039-.084-.046-.099.042.037.228.085.295.096-.028-.018-.078-.092-.096-.107.053.022.252.092.295.07-.035-.036-.136-.141-.178-.17.074.026.252.126.298.126-.01-.04-.025-.103-.049-.156.062.045.18.097.24.119-.006-.048-.021-.126-.041-.17.062.044.178.133.254.163-.02-.03-.014-.126-.049-.17.049.037.199.156.264.178-.037-.044-.043-.133-.072-.17.043.037.186.104.25.148-.016-.03-.043-.097-.072-.141.043.044.234.155.291.2-.014-.044-.043-.141-.062-.178.084.03.305.163.377.192-.256-.512-1.406-.684-2.063-.476.104-.051.16-.153.357-.201-.049-.015-.172-.078-.185-.1.063.015.298-.03.348-.037-.043-.037-.121-.096-.156-.133.093.007.313-.015.377-.037-.037-.015-.115-.044-.158-.066.064.007.214.022.277.007-.041-.037-.113-.126-.17-.163.092.022.277.022.398.007-.057-.037-.135-.074-.186-.103.059.007.299-.059.363-.074-.035-.037-.129-.059-.186-.081.1-.007.264-.104.312-.148-.792.012-1.45.396-1.793.962.011-.184-.05-.408-.059-.539l-.099.125c.03-.102.029-.373.013-.455-.018.053-.067.133-.089.174.007-.098-.019-.368-.049-.475-.022.056-.078.132-.101.174.018-.123-.061-.439-.099-.56.001.058-.052.201-.069.237-.003-.11-.092-.464-.133-.54.018.059-.014.215-.016.27-.027-.078-.134-.282-.171-.341.014.042.001.122.001.165-.062-.089-.226-.255-.3-.308.064.098.12.252.154.318-.019-.01-.068-.031-.092-.036.056.068.162.253.201.32-.035-.012-.108-.018-.144-.018.074.058.22.223.27.291-.032-.014-.13-.008-.157.004.064.034.213.17.258.232-.035-.023-.119-.045-.153-.042.075.079.184.217.233.271-.043-.026-.182-.065-.231-.06.058.057.231.242.276.303-.044-.016-.146-.001-.182-.001.065.06.234.253.275.303-.041-.023-.153-.042-.193-.045.075.084.182.252.229.322-.039-.003-.123-.014-.156-.028-.371-.613-1.04-.991-1.506-1.026.064.029.285.17.355.244-.05 0-.121-.015-.164-.015.078.067.242.163.306.192-.021 0-.114 0-.142.019.064.064.234.111.345.192-.042 0-.114.007-.156.007.096.037.263.156.32.241-.028-.004-.107-.011-.146-.015.092.052.221.144.277.204-.035-.011-.117-.011-.149-.011.057.044.231.122.284.188-.029-.003-.128-.011-.156-.011.06.048.229.178.321.278-1.084-.524-2.403-.287-3.101.677.086-.029.384-.207.483-.237-.043.052-.029.119-.057.17.085-.052.22-.163.32-.23-.021.037-.036.118-.071.185.071-.044.291-.192.398-.281-.014.067-.042.126-.064.17.114-.067.327-.215.399-.267-.035.066-.064.141-.1.185.1-.037.327-.185.462-.259-.021.052-.035.126-.071.17.107-.059.277-.111.392-.104-.022.037-.057.104-.1.133.107-.037.259-.064.43-.042-.733.242-1.466 1.032-1.446 1.552.067-.119.203-.277.288-.355-.018.056-.007.145-.003.196.035-.111.11-.244.177-.363-.01.067.011.152.025.196.035-.107.164-.325.22-.415-.018.063.004.182.018.244.054-.111.164-.281.253-.381-.021.067-.018.181-.014.222.056-.1.198-.278.284-.37-.025.078-.025.196-.029.252.068-.107.26-.307.37-.403-.032.07-.043.185-.053.233.082-.089.32-.237.409-.263-.143.1-.292.355-.377.477l.138-.026c-.078.052-.23.24-.267.307.043-.026.121-.052.161-.067-.061.063-.196.267-.235.359.046-.026.128-.044.167-.059-.081.074-.206.34-.249.447.032-.041.149-.107.182-.122-.06.078-.199.377-.213.455.022-.052.132-.141.164-.178-.025.07-.068.277-.075.341.014-.038.067-.085.092-.115-.007.1.011.315.032.396.011-.107.06-.248.075-.314.007.019.028.063.042.082 0-.082.033-.274.043-.344.018.029.064.078.089.1-.018-.085-.025-.288-.021-.366.014.029.085.085.11.092-.025-.063-.049-.248-.046-.318.01.037.057.103.082.122-.007-.1-.003-.262-.007-.329.014.044.088.155.125.181-.008-.074-.022-.307-.018-.377.022.037.1.088.124.111-.01-.081-.018-.318-.018-.377.014.041.082.122.107.148-.004-.104.018-.285.025-.362.024.026.078.085.092.115.014-.155.107-.318.227-.466.128.133.239.429.26.455.014-.033.032-.104.046-.119.003.074.035.267.042.318.015-.037.057-.115.071-.126 0 .089.01.237.021.304.014-.037.049-.096.071-.111-.018.074-.01.274 0 .348.014-.03.061-.093.085-.115-.022.067.05.304.057.407.007-.037.058-.096.078-.133 0 .081.028.318.035.436.015-.048.064-.119.09-.148-.018.107.035.311.074.403.007-.052.028-.137.05-.17.035.071.131.271.135.381.043-.107.036-.326-.014-.462.032.026.063.044.085.052-.024-.096-.1-.281-.139-.314.036.018.089.044.11.063-.024-.111-.107-.296-.152-.374.042.011.103.022.142.044-.039-.081-.175-.27-.235-.321.036.011.126.04.157.052-.039-.067-.221-.226-.331-.296.058-.007.156-.007.203-.007-.067-.085-.228-.2-.327-.252.032.004.117.022.159.033-.027-.081-.184-.237-.259-.303.065.034.271.137.334.204.015-.052.004-.174-.018-.226.063.04.217.184.245.24.015-.052.015-.141.011-.174.163.115.267.251.31.326.007-.052.01-.174-.004-.237.05.044.167.181.193.24.002-.048.01-.126-.004-.167.035.044.131.237.145.277.012-.041.037-.17.025-.207.039.056.17.251.189.318.014-.059.039-.152.035-.185.043.063.121.288.127.351.018-.03.053-.182.047-.237.035.067.139.337.16.393.014-.041.035-.163.031-.196.025.041.143.333.146.381.017-.044.027-.155.023-.192.016.067.104.245.217.37.101-.957-.921-1.564-1.736-1.688z"/><path fill="#7B4800" d="M16.894 20.684c-.396 0-.576.073-1 .103-.006-1.64.003-2.212-.045-2.212-.047 0-.04.573-.045 2.215-.089.005-.167.011-.281.011-.74 0-.875-.118-1.373-.118-.016.177.188.353.753.426l-.023.145c-.078-.003-.164-.016-.208-.031-.032.167.363.207.85.207s.881-.04.849-.207c-.044.016-.13.028-.208.031l-.023-.144c.566-.073.77-.25.754-.426zm-.853.583c-.174.024-.394.024-.519.024s-.345 0-.52-.024l.019-.145c.147.014.308.024.5.024s.352-.01.499-.024l.021.145z"/><g fill="#7B4800"><path d="M17.661 14.707c.063 1.825-.718 6.224 2.046 7.589.264.119.068.617-.381.386-2.631-1.491-1.789-6.031-1.836-7.986l.171.011z"/><circle cx="17.449" cy="14.775" r=".198"/><circle cx="17.682" cy="14.705" r=".198"/><circle cx="17.782" cy="14.517" r=".198"/><circle cx="17.436" cy="14.454" r=".198"/></g><path fill="#FFF" d="M14.825 18.694c.17.621-.015 1.441-.32 2.012.654-.066 1.706-.133 2.062 0-.313-.828-1.031-1.842-1.742-2.012z"/><path d="M14.845 17.567c-.048-.135-.137-.218-.257-.218-.18 0-.296.184-.296.458s.119.465.3.462c.152-.001.253-.109.264-.288h-.233v-.215h.432v.699h-.138c0-.047-.007-.111-.02-.154-.066.116-.175.182-.308.189-.277.018-.511-.288-.511-.695s.198-.676.511-.676c.247 0 .45.185.45.438h-.194zm1.611.709c.165 0 .208-.124.208-.24v-.906h.23v.903c0 .222-.101.47-.439.47-.337 0-.439-.248-.439-.47v-.903h.231v.906c.002.117.046.24.209.24zm2.089-.283l-.146.001.151-.558.15.558-.155-.001v.229h.22l.074.279h.225l-.381-1.373h-.266l-.381 1.373h.225l.075-.279h.209v-.229zm1.781.508l-.213-1.046v1.046h-.222v-1.373h.345l.205 1.053.205-1.053h.346v1.373h-.222v-1.046l-.213 1.046z" fill="#DD2E44"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..6e01b9e21686920b2e401aba2c676d8570bf132b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCD116" d="M32 5H15v13h21V9c0-2.209-1.791-4-4-4z"/><path fill="#009E49" d="M15 31h17c2.209 0 4-1.791 4-4v-9H15v13z"/><path fill="#CE1126" d="M15 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h11V5zm-5 17l-2.547-1.851L4.906 22l.973-2.994-2.547-1.851H6.48l.973-2.994.973 2.994h3.148l-2.547 1.851L10 22z"/><path d="M8.426 17.155l-.973-2.994-.973 2.994H3.332l2.547 1.851L4.906 22l2.547-1.851L10 22l-.973-2.994 2.547-1.851z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..1edc6ef4731b4a800865a38d39e8464bf1deebab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ec-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009E49" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M1.808 5.654c-.154.101-.302.213-.44.334v24.024c.139.121.286.233.441.335L36 18 1.808 5.654c.001-.001 0-.001 0 0z"/><path fill="#FCD116" d="M3.168 28.712L32.5 18 3.168 7.288z"/><path fill="#141414" d="M18 18L3.168 7.288l-1.8-1.3c-.31.271-.577.589-.791.942l.018 22.126c.214.354.463.684.773.955l1.8-1.3L18 18z"/><path fill="#CE1126" d="M.577 6.93l-.001.002C.21 7.536 0 8.243 0 9v18c0 .757.229 1.453.594 2.057L16 18 .577 6.93z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..ef5ca3bcef02b87879e8242cd601183a1b44b9d4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DE2910" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><g fill="#FFF"><path d="M19.626 9.201c-.604-.314-1.289-.481-2.035-.31-.906.208-2.011 1.148-2.312 2.24-.142.515-.261.97-.254 1.391.005.29.004.774.039 1.252.024.339.193 1.071.461 1.717l.017-.006c.147.491.633 1.253 1.109 1.878.546.717.973 1.04 1.059 1.039-.052-.032-.105-.066-.162-.137-.312-.391-.624-1.104-.688-1.587-.124-.943.036-1.625.297-2.444.065-.205.2-.264.289-.211.007.004.011.013.018.019.055.051.089.144.04.314-.125.438-.431 1.54-.268 2.322.15.721.364 1.151.617 1.455-.101-.202-.215-.592-.223-.994-.004-.224-.023-.446.089-.647.188-.337.462-.518.779-.689.219-.118.425-.279.614-.4.86-.548 1.149-1.632 1.125-2.07l-.021-.327c.018-.119-.036-.446-.179-.774-.107-.246-.276-.488-.412-.673-.069-.095-.108-.204-.146-.271-.147-.255-.147-.544-.145-.727.001-.216.029-.241.091-.344.049-.082.102-.193.268-.282.122-.064.397-.045.559.038.138.069.164.063.235.102.064.035.231.123.221.088-.039-.132-.523-.672-1.082-.962zm-3.738 9.867c-.941-.129-1.558-.463-2.28-.931-.179-.116-.202-.261-.13-.333l.006-.003c.059-.052.166-.066.332.034.391.236 1.373.821 2.17.871.649.04 1.087-.031 1.43-.161-.232.024-.564.016-.89-.068-.217-.057-.436-.099-.6-.26-.273-.271-.374-.584-.454-.936-.055-.243-.154-.484-.22-.699-.295-.976-1.261-1.547-1.69-1.642l-.32-.067c-.11-.05-.44-.084-.794-.037-.266.036-.544.135-.759.216-.111.042-.225.049-.3.068-.286.073-.564-.005-.739-.056-.208-.06-.225-.094-.307-.182-.066-.069-.159-.148-.2-.333-.029-.134.064-.394.187-.528.104-.112.105-.14.161-.199.051-.053.181-.189.144-.188-.136 0-.786.32-1.215.78-.466.498-.812 1.112-.848 1.876-.043.929.564 2.247 1.534 2.832.456.274.863.513 1.271.619.281.073.746.205 1.216.301.333.067 1.083.104 1.777.02v-.019c.513-.009 1.377-.272 2.106-.56.921-.366 1.371-.736 1.303-.77l-.012.01c-.009.01-.026.013-.044.016-.039.029-.065.06-.125.086-.457.196-1.228.31-1.71.243zm2.516 1.171c-.061-.864-.228-1.358-.306-1.439.006.026.018.038.022.068.061.496-.047 1.267-.247 1.712-.389.867-.883 1.364-1.535 1.927-.108.092-.214.119-.288.099-.049-.013-.084-.046-.094-.094-.015-.072.024-.176.15-.291.336-.309 1.175-1.085 1.447-1.838.21-.583.269-1.009.25-1.365-.041.229-.151.568-.343.872-.119.189-.225.385-.429.492-.341.179-.67.18-1.029.148-.247-.02-.508.002-.733-.002-1.02-.014-1.856.734-2.076 1.114l-.161.285c-.081.089-.213.393-.274.745-.047.265-.037.56-.025.789.006.118-.022.229-.026.307-.018.294-.176.536-.278.688-.12.179-.157.185-.265.237-.085.041-.19.106-.379.09-.136-.013-.356-.18-.446-.338-.076-.133-.102-.142-.141-.214-.035-.064-.125-.23-.136-.194-.041.13.067.847.375 1.394.334.596.815 1.11 1.533 1.376.871.322 2.311.143 3.162-.606.401-.352.751-.669.976-1.024.155-.245.421-.648.655-1.067.165-.296.425-1.002.556-1.688l-.017-.005c.145-.491.157-1.394.102-2.178z"/><path d="M24.492 23.068c-.181-.503-.346-.943-.596-1.283-.171-.234-.449-.629-.754-1.001-.215-.262-.775-.762-1.367-1.136l-.009.014c-.405-.315-1.241-.657-1.99-.893-.783-.246-1.311-.285-1.453-.252.061-.005.128-.006.218.021.48.141 1.144.549 1.473.908.641.703.898 1.354 1.155 2.176.065.207-.014.334-.12.337-.003 0-.003.005-.006.005-.005 0-.006-.006-.009-.008-.075-.007-.159-.064-.218-.236-.149-.431-.528-1.509-1.109-2.059-.535-.505-.957-.735-1.339-.841-.071-.019-.108-.05-.146-.079-.005.004-.01.003-.015.009l.143.085c.199.107.518.359.756.683.131.182.275.352.3.581.041.382-.078.688-.237 1.013-.11.223-.186.473-.271.681-.387.943.002 1.995.275 2.339l.206.255c.054.108.288.343.593.528.229.141.508.239.727.314.111.037.204.103.275.136.267.123.434.36.538.511.123.177.115.214.124.334.007.094.028.215-.056.384-.062.122-.298.266-.477.293-.152.021-.17.042-.251.052-.072.009-.261.032-.23.056.105.086.812.248 1.434.162.677-.092 1.332-.352 1.842-.921.618-.697.977-2.103.594-3.168z"/><path d="M27.01 15.069c-.496-.786-1.747-1.519-2.878-1.444-.53.036-1.001.074-1.395.219-.273.1-.73.258-1.17.449-.312.135-.946.537-1.468 1.002l.011.013c-.416.302-.976 1.012-1.408 1.667-.455.689-.63 1.171-.635 1.313.014-.057.027-.115.073-.189.266-.424.838-.952 1.274-1.171.85-.425 1.546-.498 2.406-.522.217-.006.317.103.293.205-.004.016-.014.031-.025.046-.041.057-.116.107-.271.115-.454.026-1.595.099-2.281.509-.632.379-.968.723-1.173 1.061-.038.064-.078.093-.117.121.002.005 0 .009.004.015l.122-.115c.157-.161.488-.398.864-.538.21-.078.414-.169.642-.13.379.065.641.265.907.508.185.167.404.309.579.447.802.631 1.921.547 2.327.38l.302-.129c.117-.021.407-.182.671-.424.197-.182.369-.421.499-.611.067-.098.156-.168.208-.227.192-.223.465-.318.638-.377.204-.069.237-.051.355-.026.093.019.215.031.354.159.101.093.174.36.148.54-.021.152-.004.175-.018.255-.012.072-.039.259-.009.237.111-.078.462-.713.551-1.335.096-.675.028-1.376-.38-2.023z"/></g><path d="M17.79 12.618l-.366.552-.627-.147-.017-.004.411.519-.334.55-.009.016.621-.231.433.502-.029-.663.594-.25.017-.007-.639-.177zm-4.579 4.06l-.002-.018-.342.567-.652-.125.433.502-.31.564-.009.016.611-.257.44.469.013.014-.056-.66.583-.274.017-.008-.645-.151zm10.348-.192l-.643-.163-.07-.659-.353.56-.631-.133-.017-.004.423.51-.323.558-.008.016.615-.246.431.479.013.013-.042-.661.588-.262zm-7.84 5.584l-.002-.017-.34.568-.632-.117-.018-.004.435.499-.306.567-.009.016.609-.261.443.467.013.014-.06-.659.582-.279.016-.008-.646-.146zm5.777-.507l-.001-.018-.373.549-.625-.156-.018-.004.405.524-.341.547-.009.015.623-.224.413.493.012.015-.018-.662.596-.243.018-.006-.636-.186z" fill="#DE2910"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..989da76df59d5d1f7767b43222f4146775f5f773 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M9 26.023l-1.222 1.129.121-1.66-1.645-.251 1.373-.94-.829-1.443 1.591.488L9 21.797l.612 1.549 1.591-.488-.83 1.443 1.374.94-1.645.251.121 1.66zM27.95 9.562l-.799.738.079-1.086-1.077-.164.899-.615-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.615-1.076.164.079 1.086zm-4 6l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zm9-2l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zm-5 14l-.799.739.079-1.086-1.077-.164.899-.616-.542-.944 1.04.319.4-1.013.401 1.013 1.041-.319-.543.944.898.616-1.076.164.079 1.086zM31 16l.294.596.657.095-.475.463.112.655L31 17.5l-.588.309.112-.655-.475-.463.657-.095z" fill="#FFF"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..298ec95afb28018cd59cf4b95b4101ffbb3b4984 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#0156A3" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4zM0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-5H0v5z"/><path fill="#2657A7" d="M18.265 17.76l-.249-.766-.249.766h-.806l.652.473-.249.767.652-.474.652.474-.249-.767.652-.473zm5.332 2.48l-.249.766.652-.473.652.473-.249-.766.652-.473h-.806L24 19l-.249.767h-.806zm.652-4.48L24 14.994l-.249.766h-.806l.652.473-.249.767.652-.474.652.474-.249-.767.652-.473zm-12.707 4.48l-.249.766.652-.473.652.473-.249-.766.652-.473h-.806L11.945 19l-.249.767h-.806zm.652-4.48l-.249-.766-.249.766h-.806l.652.473-.249.767.652-.474.652.474-.249-.767.652-.473z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..7b8740c958bcb36e76c6faff0fbb5c5a9fdf5b1c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 12.9h36v10.2H0z"/><path fill="#171796" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-4h36v4z"/><path fill="#D52B1E" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#D52B1E" d="M11.409 7.436V18.97c0 3.64 2.951 6.591 6.591 6.591s6.591-2.951 6.591-6.591V7.436H11.409z"/><path d="M14.25 18h2.5v2.5h-2.5zm2.5 2.5h2.5V23h-2.5zm0-5h2.5V18h-2.5zm2.5 2.5h2.5v2.5h-2.5zm0-5h2.5v2.5h-2.5zm2.5 2.5h2.341V18H21.75zm-7.5-2.5h2.5v2.5h-2.5zm7.5 10h.805c.626-.707 1.089-1.559 1.334-2.5H21.75V23zm-2.5 0v1.931c.929-.195 1.778-.605 2.5-1.171V23h-2.5zm-5 0v-2.5h-2.139c.245.941.707 1.793 1.334 2.5h.805zm-2.341-7.5h2.341V18h-2.341zM14.25 23v.76c.722.566 1.571.976 2.5 1.171V23h-2.5z" fill="#FFF"/><path fill="#171796" d="M24.757 8.141l-1.998.791-1.328-1.682-1.829 1.126L18 6.949l-1.603 1.428-1.826-1.128-1.331 1.684-1.995-.793-1.122 2.08 1.331 2.862.176-.082c.78-.363 1.603-.662 2.443-.888l.04-.011c.854-.227 1.702-.378 2.523-.451l.064-.006c.705-.06 1.896-.06 2.601 0l.058.005c.824.074 1.678.226 2.536.453l.033.009c.836.225 1.658.524 2.441.889l.175.082 1.331-2.861-1.118-2.08z"/><path fill="#0193DD" d="M16.638 8.681l.221 2.563c.33-.026.729-.051 1.141-.051.412 0 .811.025 1.141.051l.221-2.563L18 7.468l-1.362 1.213zm7.941-.053l-1.698.673-.668 2.489c.731.206 1.45.468 2.144.779l1.086-2.336-.864-1.605zm-13.157-.002l-.866 1.606 1.087 2.336c.69-.31 1.409-.572 2.144-.779l-.67-2.49-1.695-.673z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..8ccca4282079a227b0d12b9780d04255d672c1bb --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D21C33" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#00209F" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M12 13.041h11.906V23H12z"/><path fill="#006A16" d="M23.906 21.622c-1.499-.761-3.529-1.237-5.901-1.237-2.37 0-4.506.476-6.005 1.237V23h11.906v-1.378z"/><path fill="#00209F" d="M15.523 16.72l1.165 1.311-.146.822-.252-.143-.227.858h-.059l-.107.453-1.979-.167.048-1.412.477.137.058-1.318.693.471.035-.798z"/><path fill="#D21C33" d="M18.005 19.282v2.002l-1.5-.441-.382-.56-.262-.191.143-.506.226-.876h.346l.085-.739zm-4.313-.906c.179-.214.513-.071.524 0 .012.072-.131.059-.262.179-.131.119-.095.488-.322.441-.226-.048.06-.62.06-.62zm.809-1.115c.231-.156.513.074.504.146-.009.072-.143.021-.301.099-.159.078-.227.443-.432.334-.204-.109.229-.579.229-.579zm.954-.682c.249-.125.499.14.481.21-.018.07-.193-.054-.36.003-.168.057-.234.466-.423.331-.189-.134.302-.544.302-.544z"/><path fill="#F1B517" d="M14.945 16.023l.773.471-.085.226 2.087 2.311v.179l-2.169-2.431-.283-.047zm-1.11.697s.775.298.775.334c0 .036.142.274.142.274l2.824 2.288-.083.108-2.801-2.288-.405-.179-.452-.537zm-.822 1.174s.894.125.906.161c.012.036.072.239.072.239l3.276 1.787-.143.084-3.193-1.765-.369-.024-.549-.482z"/><path fill="#F1B517" d="M13.788 19.592l3.367.411-.319.384-.499.05.373.501-.18.203-.501-.548s-.155.798-.834.798-.895-.679-.895-.906c0-.227.06-.345.06-.345h-.644l.072-.548z"/><path fill="#00209F" d="M20.445 16.648l-1.217 1.443.05.833.313-.214.226.858h.06l.107.453 1.978-.167-.048-1.412-.476.137-.059-1.318-.692.471-.037-.798z"/><path fill="#D21C33" d="M18.005 19.282v2.002l1.436-.441.349-.56.246-.191-.151-.506-.235-.876-.266.198-.092-.817zm4.183-.906c-.18-.214-.514-.071-.525 0-.012.072.132.059.263.179.131.119.096.488.322.441.226-.048-.06-.62-.06-.62zm-.809-1.115c-.231-.156-.512.074-.504.146.009.072.143.021.302.099s.226.443.432.334c.203-.109-.23-.579-.23-.579zm-.953-.682c-.25-.125-.498.14-.481.21.018.07.192-.054.359.003.168.057.235.466.424.331.189-.134-.302-.544-.302-.544z"/><path fill="#F1B517" d="M20.935 16.023l-.772.471.149.226-2.02 2.311v.179l2.103-2.431.251-.047zm1.11.697s-.774.298-.774.334c0 .036-.143.274-.143.274l-2.824 2.288.084.108 2.8-2.288.404-.179.453-.537zm.822 1.174s-.894.125-.905.161c-.013.036-.071.239-.071.239l-3.277 1.787.143.084 3.193-1.764.37-.024.547-.483z"/><path fill="#F1B517" d="M22.093 19.592l-3.366.411.319.384.498.05-.373.501.181.203.501-.548s.155.798.834.798c.68 0 .894-.679.894-.905 0-.227-.059-.345-.059-.345h.643l-.072-.549z"/><path fill="#FFF" d="M22.86 22.142s-.59.021-1.209-.113c-.619-.135-.726-.377-.995-.323-.269.054-.893.285-1.404.351-.512.064-1.247.086-1.247.086s-.676-.021-1.188-.086c-.512-.066-1.077-.297-1.347-.351-.269-.054-.377.189-.997.323-.619.135-1.212.113-1.212.113l.162.286-.162.14c1.401.026 2.048-.426 2.048-.426.7.464 2.696.477 2.696.477s2.056-.013 2.756-.477c0 0 .676.452 2.076.426l-.148-.14.171-.286z"/><path fill="#F1B517" d="M18.292 17.894c0 1.49-.13 2.699-.292 2.699-.161 0-.292-1.209-.292-2.699 0-1.491.131-2.699.292-2.699.162 0 .292 1.208.292 2.699z"/><path fill="#D21C33" d="M17.434 20.426h1.144v1.145h-1.144z"/><path fill="#FFF" d="M18.649 20.354c0 .132-.274.238-.614.238-.339 0-.614-.107-.614-.238s.275-.238.614-.238c.34 0 .614.107.614.238z"/><path fill="#D21C33" d="M18.649 21.498c0 .132-.274.238-.614.238-.339 0-.614-.106-.614-.238s.275-.238.614-.238c.34 0 .614.106.614.238z"/><path fill="#006A16" d="M20.514 14.694c-.229-.274-.818-.262-1.218-.274-.399-.012-.601.131-.422-.059s.455-.142.746-.155c.292-.012.343-.047.164-.142-.179-.095-.493-.213-.91-.106-.409.105-.667.36-.885.404-.218-.043-.491-.299-.9-.404-.417-.107-.74.01-.918.106-.179.095-.131.13.161.142.292.012.565-.036.744.155.179.191-.024.047-.423.059-.399.012-.989 0-1.218.274-.229.274.199.095.426.059.226-.036.56-.047.56-.047s-.56.166-.715.381c-.155.214.047.405.334.238.286-.167.727-.393.965-.417 0 0-.62.258-.894.481-.274.223.013.199.221.199s.422-.083.601-.215c.179-.131-.118.262-.167.513-.047.25.322.191.388 0 .065-.191.279-.572.279-.572s-.094.548-.082.918c.012.37.134.393.229.226s.425.099.425.099.3-.266.395-.099c.096.167.186.143.198-.226.012-.369-.083-.918-.083-.918s.214.381.28.572c.065.191.435.25.387 0-.047-.25-.345-.644-.166-.513.179.131.393.215.601.215.209 0 .495.024.222-.199-.274-.223-.894-.481-.894-.481.239.024.679.25.965.417.286.167.488-.024.333-.238-.155-.215-.715-.381-.715-.381s.334.012.561.047c.226.037.654.215.425-.059z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..206baa15bfc22184a707bf334ae7f51a8ae75bfc --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ed-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#CD2A3E" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#436F4D" d="M4 31h28c2.209 0 4-1.791 4-4v-5H0v5c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..46b094979919e6144f72e34434bf23d20a45ae09 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FC0" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#0868A9" d="M12 5h12v26H12z"/><path fill="#C09B5A" d="M21.021 16.3c-.278-.29-.614 0-.762-.088-.146-.088-.336-.154-.321.154s.249.45.381.553c.132.103.059.408.059.408s-.22-.25-.308-.411c-.088-.161-.161-.308-.322-.308s-.322.219-.22.307c.103.088.469.176.469.41 0 .234.146.469.146.469l-.044.161s-.146-.073-.19-.161c-.044-.088.044-.366-.161-.366-.205 0-.264.454-.132.527.132.073.513.498.513.498s.16.307.409.454c.249.146.572.469.572.469s-.425.308-.454.498c-.029.189.146.263.131.425-.015.16-.204.078-.365.166-.162.088.003.312.003.312h.44l.217-.405v-.294l.464-.103s-.042.176.046.278c.088.104.426.249.426.498s-.131.257-.278.271c-.146.016-.219.186-.219.186h.572s.16-.375.249-.55c.087-.177.028-.298-.074-.343-.103-.044-.204-.273-.175-.463 0 0 .204.164.439.12.234-.044.439-.241.454-.489.015-.25 0-.495-.234-.582s-.189.164-.103.236c.088.073.088.396-.029.47-.117.074-.307.162-.366-.043-.059-.205-.186-.526-.436-.614-.249-.088-.589-.645-.574-1.04.012-.394.114-1.259-.223-1.61zm-6.061 0c.278-.29.615 0 .761-.088.146-.088.337-.154.322.154-.015.308-.249.45-.38.553-.132.103-.059.408-.059.408s.22-.25.308-.411c.088-.161.161-.308.322-.308s.322.219.22.307c-.103.088-.469.176-.469.41 0 .234-.146.469-.146.469l.044.161s.146-.073.19-.161c.044-.088-.044-.366.161-.366.205 0 .264.454.132.527-.132.073-.513.498-.513.498s-.161.307-.41.454c-.249.146-.571.469-.571.469s.425.308.454.498c.029.189-.146.263-.132.425.015.16.205.078.366.166.161.088.118.307.118.307h-.441l-.336-.399v-.294l-.456-.103s.038.176-.05.278c-.088.104-.428.249-.428.498s.13.257.277.271c.146.016.218.186.218.186h-.571s-.162-.375-.249-.55c-.088-.177-.03-.298.073-.343.102-.044.205-.273.176-.463 0 0-.205.164-.439.12-.234-.044-.439-.241-.454-.489-.015-.25 0-.495.234-.582.234-.087.191.164.103.236-.088.073-.088.396.029.47.117.074.308.162.366-.043.059-.205.186-.526.436-.614.249-.088.589-.645.575-1.04-.016-.395-.118-1.26.219-1.611z"/><path fill="#8C8D8F" d="M21.226 17.245c-.213.036-.555.009-.805-.007-.088-.005-.122.249-.059.264.196.045.713.076.875-.018.061-.036.084-.255-.011-.239z"/><path d="M20.176 16.169s-.086.131-.239.154c0 0-.017-.124.072-.172.09-.048.167.018.167.018zm.354.219c-.128-.026-.227.051-.103.095.126.044.183-.079.103-.095zm.55.3s-.015.468-.27.461c-.257-.007-.154-.402 0-.571 0 0-.185.47-.016.483.169.015.286-.373.286-.373z"/><path fill="#8C8D8F" d="M14.754 17.245c.213.036.555.009.806-.007.088-.005.122.249.058.264-.196.045-.712.076-.875-.018-.061-.036-.084-.255.011-.239z"/><path d="M15.805 16.169s.085.131.239.154c0 0 .017-.124-.072-.172-.09-.048-.167.018-.167.018zm-.355.219c.129-.026.227.051.103.095-.125.044-.183-.079-.103-.095zm-.549.3s.015.468.271.461c.256-.007.154-.402 0-.571 0 0 .184.47.015.483-.17.015-.286-.373-.286-.373z"/><path fill="#EBD11B" d="M18.757 15.138s-.296-.285-.616-.212l-.069-.046.006-.313h-.146l.007.313-.069.046c-.319-.072-.616.212-.616.212-.475-.19-.933.123-.933.484s.274.524.332.587c.059.064.374.847.374.847h1.955s.316-.783.375-.847c.059-.063.332-.227.332-.587.001-.361-.457-.675-.932-.484z"/><path fill="#BE1827" d="M17.815 15.451v.234l-.163.182s-.158.014-.231-.04c-.072-.055-.136-.186-.136-.186s.167-.113.265-.141c.098-.027.265-.049.265-.049zm-.588.267s-.027.19-.168.24c-.14.05-.28.027-.28.027s.036-.099.153-.181c.118-.081.295-.086.295-.086z"/><path fill="#0868A9" d="M17.507 15.247c.146-.035.308 0 .308 0s-.003.207-.194.237c-.19.03-.267-.056-.267-.056s.04-.154.153-.181zm-.903.394c-.052-.25.292-.342.464-.151 0 0 .034.259-.168.338-.203.08-.275-.088-.296-.187zm.467-.349c.043-.096.237-.008.179.095-.06.105-.254.069-.179-.095z"/><path fill="#0868A9" d="M17.112 15.537c.091-.095.227.094.115.144-.113.051-.185-.072-.115-.144z"/><path fill="#BE1827" d="M18.167 15.451v.234l.177.182s.166.014.238-.04c.072-.055.139-.186.139-.186s-.18-.113-.277-.141c-.097-.027-.277-.049-.277-.049zm.617.267s.027.19.167.24c.141.05.281.027.281.027s-.036-.099-.154-.181c-.117-.081-.294-.086-.294-.086z"/><path fill="#0868A9" d="M18.503 15.247c-.145-.035-.307 0-.307 0s.003.207.194.237c.19.03.268-.056.268-.056s-.041-.154-.155-.181zm.903.394c.052-.25-.292-.342-.464-.151 0 0-.034.259.169.338.202.08.275-.088.295-.187zm-.466-.349c-.044-.096-.237-.008-.179.095.059.105.255.069.179-.095z"/><path fill="#0868A9" d="M18.898 15.537c-.09-.095-.226.094-.114.144.112.051.184-.072.114-.144z"/><path fill="#BE1827" d="M17.028 16.916c0-.186.431-.337.963-.337s.963.151.963.337c0 .186-.431.337-.963.337-.533-.001-.963-.152-.963-.337z"/><path fill="#020202" d="M17.999 16.854h-1.874v3.063c0 1.207 1.875 1.207 1.875 1.207s1.854 0 1.854-1.207v-3.063h-1.855z"/><path fill="#4C86C7" d="M17.998 17.057h-1.661v2.861c0 .995 1.661.98 1.661.98s1.661.015 1.661-.98v-2.861h-1.661z"/><path fill="#A5A7A9" d="M20.364 14.738c.242-.088.44-.42.44-.42s-.39.049-.635 0-.427-.225-.427-.225c.177-.312-.113-.501-.669-.567-.43-.05-1.076-.068-1.076-.068s-.657.018-1.088.068c-.555.065-.851.254-.675.567 0 0-.185.176-.43.225-.245.049-.635 0-.635 0s.196.332.439.42c0 0-.069.225-.372.273 0 0 .635.107 1.093-.087.459-.195.713-.361.781-.43.069-.068-.181-.224.004-.244.186-.019.882-.039.882-.039s.685.02.871.039c.186.02-.077.176-.008.244.068.068.322.234.781.43.459.195 1.093.087 1.093.087-.3-.048-.369-.273-.369-.273z"/><path d="M18.557 20.547h-1.132l.566-.567zm-.82-1.874h-1.133l.567-.567zm0-.879h-1.133l.567-.566zm0 1.815h-1.133l.567-.565zm1.581-.936h-1.132l.566-.567zm0-.879h-1.132l.566-.566zm0 1.815h-1.132l.566-.565z" fill="#FFF"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..de31273f8c2795621ba94c351f68222613508df5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DC1F26" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-9h36v9z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..3c502571eecfbd8d7bd9831da4a812432f512db0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#169B62" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#FF883E" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..5cf3241556c5f59d0b40fe9a0d73e0c5d5071eb7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EDECEC" d="M20.666 19l-.467.809h.934zM18 21.618l.467-.809h-.934z"/><path fill="#EEE" d="M0 25h36V11H0v14zM.294 7.5h35.413C35.113 6.035 33.678 5 32 5H4C2.322 5 .887 6.035.294 7.5z"/><path fill="#EDECEC" d="M21.133 16.191h-.934l.467.809zm-5.332 0h-.934l.467.809zm3.243 3.618L20.089 18l-1.045-1.809h-2.088L15.911 18l1.045 1.809zM15.334 19l-.467.809h.934zM18 14.382l-.467.809h.934z"/><path fill="#0038B8" d="M.294 7.5C.106 7.964 0 8.469 0 9v2h36V9c0-.531-.106-1.036-.294-1.5H.294z"/><path fill="#EEE" d="M.294 28.5h35.413C35.113 29.965 33.678 31 32 31H4C2.322 31 .887 29.965.294 28.5z"/><path fill="#0038B8" d="M.294 28.5C.106 28.036 0 27.531 0 27v-2h36v2c0 .531-.106 1.036-.294 1.5H.294zm16.084-7.691L18 23.618l1.622-2.809h3.243L21.244 18l1.622-2.809h-3.243L18 12.382l-1.622 2.809h-3.243L14.756 18l-1.622 2.809h3.244zm1.622.809l-.467-.809h.934l-.467.809zm3.133-5.427l-.467.809-.467-.808h.934zM20.666 19l.467.808h-.934l.467-.808zM18 14.382l.467.809h-.934l.467-.809zm-1.044 1.809h2.089L20.089 18l-1.044 1.809h-2.089L15.911 18l1.045-1.809zm-1.155 0l-.467.809-.467-.808h.934zM15.334 19l.467.808h-.934l.467-.808z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..7fc9d465a88c222a46190994f3a9dff9e2b8d10b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CF1B2B" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><circle fill="#F8DC15" cx="17.635" cy="16.575" r="1.383"/><circle fill="#F8DC15" cx="17.635" cy="17.316" r="1.383"/><path fill="#FFF" d="M9.858 12.11c.407-.204 1.33 1.544 2.059 1.501.729-.043 2.616-1.439 3.646-1.535 0 0 0-.439.858-.439s.986.43 1.072.987c0 0 .685 1.072.986 1.887.301.815.301 1.373.301 1.373s-.644.643-1.03.686c-.386.043-1.458-.343-1.458-.343s-.214-1.626-.3-2.121l-.3-.324s-.428.472-1.201.601c-.773.129-1.973.085-2.402.171-.429.086-.386.644-.772.601-.386-.043-.085-.901-.772-1.373-.687-.471-1.202-1.415-.687-1.672zm7.563 14.08c-.38-.252.672-1.926.271-2.535-.402-.609-2.555-1.545-3.153-2.389 0 0-.379.219-.808-.525-.429-.742-.121-1.068.318-1.422 0 0 .585-1.129 1.142-1.797.555-.668 1.038-.947 1.038-.947s.879.236 1.109.548c.23.312.432 1.436.432 1.436s-1.301.997-1.687 1.32l-.131.422s.623.135 1.12.74c.499.604 1.061 1.666 1.35 1.994.289.328.75.012.907.369.156.353-.738.523-.803 1.353-.065.831-.625 1.749-1.105 1.433zm8.365-13.525c-.027.455-2.003.38-2.33 1.032-.327.653-.062 2.985-.492 3.925 0 0 .379.218-.051.961-.429.743-.865.639-1.39.436 0 0-1.271.058-2.128-.09-.856-.146-1.338-.425-1.338-.425s-.235-.879-.081-1.235c.156-.355 1.027-1.092 1.027-1.092s1.516.628 1.987.801l.432-.097s-.196-.608.08-1.341c.273-.734.912-1.751 1.052-2.166.14-.415-.363-.656-.134-.97.229-.313.822.377 1.573.018.753-.358 1.828-.33 1.793.243z"/><path fill="#F8DC15" d="M11.628 14.892l.376.327.481-.124-.195.458.266.419-.495-.044-.318.383-.111-.485-.462-.183.428-.255zm7.318 8.374l.095-.491-.348-.355.494-.059.23-.441.209.453.491.082-.364.34.071.49-.433-.242zm3.546-10.46l-.471.163-.133.479-.299-.398-.497.021.287-.406-.174-.467.475.145.39-.308.007.498z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..55f97e6fbbf003af3007115637f446bc4855f96a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#138808" d="M0 27a4 4 0 0 0 4 4h28a4 4 0 0 0 4-4v-5H0v5z"/><path fill="#F93" d="M36 14V9a4 4 0 0 0-4-4H4a4 4 0 0 0-4 4v5h36z"/><path fill="#F7F7F7" d="M0 13.667h36v8.667H0z"/><circle fill="navy" cx="18" cy="18" r="4"/><circle fill="#F7F7F7" cx="18" cy="18" r="3.375"/><path d="m18.1 16.75-.1.65-.1-.65.1-1.95zm-.928-1.841.408 1.909.265.602-.072-.653zm-.772.32.888 1.738.412.513-.238-.613zm-.663.508 1.308 1.45.531.389-.389-.531zm-.508.663 1.638 1.062.613.238-.513-.412zm-.32.772 1.858.601.653.072-.602-.265zM14.8 18l1.95.1.65-.1-.65-.1zm.109.828 1.909-.408.602-.265-.653.072zm.32.772 1.738-.888.513-.412-.613.238zm.508.663 1.45-1.308.389-.531-.531.389zm.663.508 1.062-1.638.238-.613-.412.513zm.772.32.601-1.858.072-.653-.265.602zM18 21.2l.1-1.95-.1-.65-.1.65zm.828-.109-.408-1.909-.265-.602.072.653zm.772-.32-.888-1.738-.412-.513.238.613zm.663-.508-1.308-1.45-.531-.389.389.531zm.508-.663-1.638-1.062-.613-.238.513.412zm.32-.772-1.858-.601-.653-.072.602.265zM21.2 18l-1.95-.1-.65.1.65.1zm-.109-.828-1.909.408-.602.265.653-.072zm-.32-.772-1.738.888-.513.412.613-.238zm-.508-.663-1.45 1.308-.389.531.531-.389zm-.663-.508-1.062 1.638-.238.613.412-.513zm-.772-.32-.601 1.858-.072.653.265-.602z" fill="#6666B3"/><g fill="navy"><circle cx="17.56" cy="14.659" r=".2"/><circle cx="16.71" cy="14.887" r=".2"/><circle cx="15.948" cy="15.326" r=".2"/><circle cx="15.326" cy="15.948" r=".2"/><circle cx="14.887" cy="16.71" r=".2"/><circle cx="14.659" cy="17.56" r=".2"/><circle cx="14.659" cy="18.44" r=".2"/><circle cx="14.887" cy="19.29" r=".2"/><circle cx="15.326" cy="20.052" r=".2"/><circle cx="15.948" cy="20.674" r=".2"/><circle cx="16.71" cy="21.113" r=".2"/><circle cx="17.56" cy="21.341" r=".2"/><circle cx="18.44" cy="21.341" r=".2"/><circle cx="19.29" cy="21.113" r=".2"/><circle cx="20.052" cy="20.674" r=".2"/><circle cx="20.674" cy="20.052" r=".2"/><circle cx="21.113" cy="19.29" r=".2"/><circle cx="21.341" cy="18.44" r=".2"/><circle cx="21.341" cy="17.56" r=".2"/><circle cx="21.113" cy="16.71" r=".2"/><circle cx="20.674" cy="15.948" r=".2"/><circle cx="20.052" cy="15.326" r=".2"/><circle cx="19.29" cy="14.887" r=".2"/><circle cx="18.44" cy="14.659" r=".2"/><circle cx="18" cy="18" r=".9"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..565a7aa4f1609260f321c78429548cd6986c16ab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path d="M34.363 28.125c-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.762 0-1.201.178-1.591.383.071.638.277 1.233.613 1.744.263-.077.575-.127.979-.127 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.088 0 .157-.01.236-.015.674-.581 1.157-1.372 1.326-2.283-.386.21-.821.391-1.565.391zM36 25.383v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.002 1.233-.186 1.635-.393zm0-4.257v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.063-3.636-1.063-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.191-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789 0 1.233-.185 1.635-.392zm0-4.257v-1.944c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.002 1.233-.186 1.635-.393zm0-4.258v-1.944c-.402.227-.846.43-1.637.43-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789-.001 1.233-.186 1.635-.393zm-.062-4.227c-.095-.611-.317-1.177-.656-1.663-.252.071-.545.119-.919.119-1.817 0-1.817-1.062-3.636-1.062-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1c-1.814 0-1.82-.994-3.625-.999C.877 6.342.314 7.169.101 8.133c.377-.193.808-.356 1.535-.356 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.751 0 1.187-.168 1.574-.362z" fill="#00247D"/><path fill="#C1694F" d="M27.248 28.677c0 .179-.143.323-.322.323-.179 0-.324-.145-.324-.323V12.815c0-.178.146-.323.324-.323.179 0 .322.145.322.323v15.862z"/><path fill="#DD2E44" d="M24.656 20.364s.139-.334.627-.334c.49 0 .607.255.901.372.294.118.666.177.666.177v2.447h-2.624s-.099-.92-.255-1.37c-.157-.449-.294-1.058.039-1.254.334-.194.646-.038.646-.038z"/><path fill="#FFCC4D" d="M26.84 19.728v.352s-.675-.059-1.263-.47c-.358-.25-1.116-.559-1.703-.058-.382.322-.353 1.146-.116 1.468.233.323.469 1.058-.031.559-.499-.5-.647-1.264-.499-1.763.147-.499.47-.998 1.233-.998.765 0 1.264.411 1.616.617.306.177.794.233.763.293z"/><path fill="#FFCC4D" d="M23.895 21.499l.41-.019-.117.626s.411-.312.431-.235c.018.08.078.646.078.646l-.53-.117.313.451-.41.194s-.157-.528-.196-.781c-.04-.255.021-.765.021-.765zm.86.334l.391-.039s-.338-.764.157-.745c.549.021.176.726.176.726h.412l.059.567-.391-.235v.334l.43.411-1.136.116.293-.489-.018-.351-.274.313-.099-.608z"/><path fill="#DD2E44" d="M29.205 20.364s-.138-.334-.627-.334-.606.255-.9.372c-.294.118-.666.177-.666.177v2.447h2.625s.097-.92.254-1.37c.157-.449.293-1.058-.039-1.254-.334-.194-.647-.038-.647-.038z"/><path fill="#FFCC4D" d="M27.021 19.728v.352s.676-.059 1.263-.47c.358-.25 1.116-.559 1.704-.058.382.322.351 1.146.116 1.468-.234.323-.468 1.058.03.559.499-.5.647-1.264.499-1.763-.146-.499-.47-.998-1.233-.998-.765 0-1.264.411-1.615.617-.305.177-.793.233-.764.293z"/><path fill="#FFCC4D" d="M29.969 21.499l-.411-.019.117.626s-.411-.312-.431-.235c-.019.08-.078.646-.078.646l.527-.117-.313.451.411.194s.157-.528.197-.781c.038-.255-.019-.765-.019-.765zm-.863.334l-.392-.039s.339-.764-.157-.745c-.547.021-.175.726-.175.726h-.411l-.061.567.393-.235v.334l-.431.411 1.137.116-.295-.489.021-.351.274.313.097-.608zm-1.495-3.095c0 .39-.308.704-.685.704-.379 0-.686-.315-.686-.704 0-.389.307-.705.686-.705.378.001.685.316.685.705zm-1.301-1.546h1.232v.49H26.31z"/><path fill="#FFCC4D" d="M26.633 16.859h.586v4.523h-.586z"/><path fill="#FFCC4D" d="M26.44 21.187h.919l-.255.646.588-.313v.86l-.569-.195.49.744h-1.272l.391-.744-.567.136v-.763l.529.254z"/><path fill="#FFCC4D" d="M26.928 22.635c1.215 0 1.978.1 2.84.411 0 0 .06.511-.059.765-.116.255-2.8-.177-2.8-.177l.019-.999z"/><path fill="#FFCC4D" d="M26.963 22.635c-1.214 0-1.978.1-2.838.411 0 0-.06.511.057.765.118.255 2.8-.177 2.8-.177l-.019-.999z"/><path fill="#EEE" d="M30.078 24.33c0 .384-1.412.693-3.152.693-1.74 0-3.153-.309-3.153-.693 0-.385 1.413-.696 3.153-.696s3.152.311 3.152.696z"/><path fill="#99AAB5" d="M29.043 24.583c0 .212-.948.384-2.117.384-1.17 0-2.119-.172-2.119-.384 0-.21.949-.382 2.119-.382 1.169 0 2.117.172 2.117.382z"/><path fill="#77B255" d="M25.655 6.873l.646.803s.451-.274.471-.215c.02.059-.039.666-.039.666l.313.078-.255.803s.393-.215.372-.137c-.019.078-.117.764-.117.764l.157.098-.02.764s.157.273.157.215c0-.058.156-.998.156-.998l.216.176.076-.489.177-.842.196.313.411-1.391.216.49.489-.568.333-.02.489-.137.099.293h.45s-.234.196-.215.254c.018.059.43.274.371.294-.059.02-1.058-.079-1.058-.079l-.566.568.352.118-.53.313.451.137-.411.313.353-.039-.568.431.568.118-.764.391.176.196-.763.451-.099.313.725-.568s.588-.392.881-.568c.294-.176.529-.509 1.02-.646s1.429.02 1.429.02l-.882.47.177.274-.567.176.078.332-.941.138.02.352-.803.138-.098.333-.548.196.255.215s-.471.157-.411.176c.059.02.685.078.685.078s-.314.274-.256.274c.06 0 .842.039.842.039l-.333.235.785.039-.354.274s.646.059.646.118c0 .058-.273.352-.273.352l.567.059s-.273.293-.216.314c.061.019.804.528.804.528l-.882-.117s-.215.293-.235.234c-.018-.058-.233-.411-.233-.411l-.216.235-.234-.47s-.274.156-.256.098c.02-.059-.313-.431-.313-.431l-.078.177-.215-.529-.195.274-.373-.51-.137.215-.51-.45s-.019.294 0 .353c.02.059.373.313.373.313s-.235.098-.235.156c0 .059.471.431.471.431l-.216.157.509.431s-.47.098-.412.137c.06.039.294.352.294.352l-.195.47-.391-.607-.216.059-.04-.509-.214-.02.116-.567-.234.039-.02-.47-.099-.47-.195-.314s-.137.235-.118.293c.02.059.178.431.178.431s-.216.117-.178.176c.04.059.255.489.255.489s-.47.098-.411.098c.06 0 .216.274.216.274l-.255.098-.117.294s-.293-.333-.274-.274c.02.059-.176.607-.176.607l-.293-.333.293-1.155-.354-.098-.254.529s-.215-.254-.235-.196c-.02.059-.235.451-.235.451s-.252-.431-.233-.372c.019.058-.295.686-.295.686s-.274-.549-.274-.47c0 .078-.195.764-.195.764s-.312-.529-.294-.431c.021.098-.215.549-.215.549l-.06-.49-.43.254.489-.705.823-.764.627-.469-.414-.058s.597-.207.665-.215c.178-.02-.272-.176-.272-.176l1.096-.333s-.489-.255-.548-.196c-.059.059-.647.176-.647.176l-.078-.45-.606.254s-.099-.412-.118-.353c-.019.059-.49.313-.49.313l-.233-.254-.275.431-.314-.235-.566.176.273-.411-.313-.176.646-.411.137-.274.882.059s-.236-.314-.196-.255c.04.059.9.196.9.196l.256-.039.861.313-.705-.568-.607-.118.392-.313-.921-.332.197-.313-1.216-.313.746-.196-.51-.862 1.057.627.47-.157.236.607.431.255.077.45.216-.098.195.528.256-.079.136.373.374.019-.1-.49.156-.235-.431-.353.374-.176-.55-.451.47-.059-.666-.646.53.02-.53-.607.432-.098-.081-.782z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..06cfe319271c0bef87976fe158b0c33b503d9763 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#DD2E44" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><g fill="#007A3C"><path d="M11.227 18.06v1.229h5.651v-.737c0-.328-.369-.308-.369-.062v.552h-4.423v-.86l3.102-3.102.471.501-2.815 2.846h2.928s.133-.86.931-.86l.912.635v2.314h-8.23s-.205 1.085-1.454.941c0 0 .86-.573.86-1.249 0-.675-.552-1.208-.552-1.208l.778-.491s.082.42.164.542c.083.122.389.235.389.235h1.044l-.014-.546-.151-.065.778-.615zm8.302 1.002l-.166.227h-.487c.002-1.151.006-3.418-.001-3.441-.01-.031.215-.194.215-.194l-.982-.542v5.406h1.843l-.422-1.456zm5.458-3.09v3.317h-.491V16.34l-.615.615v2.335h-.491v-1.966l-.613.615v.006l-.134.127.134.052v.457c-.586-.301-1.229.155-1.229.71v1.228h4.053V15.36l-.614.612zm-2.564 3.317h-.036c-.246 0-.215-.328.123-.328.188 0 .248.101.267.191v.137h-.354zm1.315-4.208c0 .152-.051.277-.113.277-.062 0-.112-.124-.112-.277 0-.153.051-.276.112-.276.063 0 .113.123.113.276zm-1.034.747s.184.175.523.123c.338-.051.45-.358.45-.358s.194.317.409.266c.216-.051.41-.389.41-.389s.01.542-.308.593c-.317.051-.45-.174-.45-.174s-.164.246-.471.266c-.307.022-.563-.327-.563-.327zm4.944 3.205l-.265.256h-.43v-3.491l.255-.113-.992-.573v5.406h1.852z"/><path d="M10.716 21.132c0 .146-.119.266-.267.266-.146 0-.266-.119-.266-.266 0-.147.12-.267.266-.267.148 0 .267.119.267.267z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..e8ae7b17764bccbcf4a76707dcfd9419ace2696d --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DA0001" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#239F40" d="M36 13V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v4h36z"/><path fill="#E96667" d="M0 23h36v1H0z"/><g fill="#BE1931"><path d="M19.465 14.969c.957.49 3.038 2.953.798 5.731 1.391-.308 3.162-4.408-.798-5.731zm-2.937 0c-3.959 1.323-2.189 5.423-.798 5.731-2.24-2.778-.159-5.241.798-5.731zm1.453-.143c.04.197 1.101.436.974-.573-.168.408-.654.396-.968.207-.432.241-.835.182-.988-.227-.148.754.587.975.982.593z"/><path d="M20.538 17.904c-.015-1.248-.677-2.352-1.329-2.799.43.527 1.752 3.436-.785 5.351l.047-5.097-.475-.418-.475.398.08 5.146-.018-.015c-2.563-1.914-1.233-4.837-.802-5.365-.652.447-1.315 1.551-1.329 2.799-.013 1.071.477 2.243 1.834 3.205-.558.149-1.162.208-1.678.201.464.253 1.34.192 2.007.131l.001.068.398.437.4-.455v-.052c.672.062 1.567.129 2.039-.128-.532.008-1.159-.053-1.732-.213 1.344-.961 1.83-2.127 1.817-3.194z"/></g><path fill="#7BC58C" d="M0 12h36v1H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..c8e918c34ea7d8b59e734a0905149196b3a07f38 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#003897" d="M10 5H4C1.791 5 0 6.791 0 9v6h10V5zm22 0H16v10h20V9c0-2.209-1.791-4-4-4zM10 31H4c-2.209 0-4-1.791-4-4v-6h10v10zm22 0H16V21h20v6c0 2.209-1.791 4-4 4z"/><path fill="#D72828" d="M14.5 5h-2.944l-.025 11.5H0v3h11.525L11.5 31h3V19.5H36v-3H14.5z"/><path fill="#EEE" d="M14.5 31H16V21h20v-1.5H14.5zM16 5h-1.5v11.5H36V15H16zm-4.5 0H10v10H0v1.5h11.5zM0 19.5V21h10v10h1.5V19.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c380176682282c459cfc59b6e627ab203060bd4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ee-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE2B37" d="M36 27c0 2.209-1.791 4-4 4h-8V5h8c2.209 0 4 1.791 4 4v18z"/><path fill="#009246" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..a17c379d1825fcc782f04da1d7f57648801db0e2 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#D52048" d="M3.186 5.084c-1.168.242-2.134 1.002-2.687 2.02L15.286 18 .499 28.896c.553 1.019 1.519 1.778 2.687 2.021L18 20l14.814 10.916c1.168-.242 2.135-1.002 2.688-2.021L20.714 18 35.502 7.104c-.553-1.018-1.52-1.778-2.688-2.02L18 16 3.186 5.084z"/><path fill="#FFCC4D" d="M20.531 7c-.168.065-.254.365-.254.365s-.15-.339-.605-.118c0 0 .248.248.195.456-.053.209-.197.301-.443.267-.287-.039-.34-.371-.34-.371s.178-.033.197-.183c.012-.091-.033-.222-.189-.234-.119-.01-.235.065-.235.208 0 .105.131.195.131.195s-.104.224-.34.235c-.299.013-.432-.156-.436-.443-.007-.411.521-.417.521-.417s-.046-.202-.228-.306c-.182-.104-.352.039-.352.039s.13-.293.091-.496c-.034-.173-.164-.346-.211-.403v-.019l-.008.01-.008-.01v.021c-.047.057-.178.229-.211.403-.039.202.091.496.091.496s-.169-.144-.352-.039c-.183.104-.229.306-.229.306s.528.006.521.417c-.004.287-.137.456-.437.443-.235-.011-.339-.235-.339-.235s.13-.09.13-.195c0-.144-.116-.218-.234-.208-.156.013-.201.143-.189.234.02.15.196.183.196.183s-.052.333-.339.371c-.247.034-.391-.058-.443-.267-.052-.208.195-.456.195-.456-.456-.222-.605.118-.605.118s-.085-.302-.253-.367c-.17-.065-.339-.039-.339-.039s.313.496.521.977c.209.482.287.978.287.978s.356-.25.938-.391c.45-.109 1.024-.117 1.1-.118.075.001.649.008 1.098.118.584.142.94.391.94.391s.078-.496.287-.978c.209-.481.521-.977.521-.977s-.171-.026-.341.039z"/><path fill="#DD2E44" d="M20.062 8.916s-.477-.313-.977-.424c-.467-.103-.99-.104-1.061-.104s-.594.001-1.06.104c-.502.111-.977.424-.977.424s-.409 1.52-.169 2.626c.473 2.186 2.021 3.086 2.199 3.184v.01l.008-.004.008.004v-.01c.178-.097 1.727-.998 2.199-3.184.241-1.106-.17-2.626-.17-2.626z"/><path fill="#231F20" d="M18.018 14.737l-.004-.012c-.174-.094-1.726-.998-2.199-3.183-.237-1.094.166-2.612.169-2.627.006-.005.483-.316.979-.426.439-.097.923-.104 1.061-.104s.622.007 1.062.104c.494.11.972.421.977.424l.001.001c.005.015.408 1.533.17 2.627-.472 2.185-2.024 3.089-2.2 3.185l.001.008c-.003.002-.007 0-.012-.002l-.005.005zm.006-.008l.011.005-.004-.008c.177-.098 1.727-1.001 2.2-3.184.234-1.082-.158-2.58-.17-2.624-.022-.014-.49-.315-.976-.423-.439-.097-.922-.104-1.06-.104s-.621.007-1.06.104c-.496.109-.972.42-.977.423-.003.014-.405 1.531-.168 2.624.472 2.183 2.022 3.086 2.197 3.182l.001.008.006-.003z"/><path fill="#FFCC4D" d="M19.406 8.922s-.092.124-.411.124c-.319 0-.177-.042-.43-.042-.255 0-.365.065-.365.143 0 .078.091.127.431.127.338 0 .463-.085.736-.085.273 0 .377.098.377.222s-.176.352-.457.28c0 0 .197.097.406.084.207-.012.383-.051.397-.005.014.045.098.286.086.417-.02.202-.275.273-.379.261-.104-.013-.24.085-.279.13l.025-.137-.105.039.059-.169h-.129s.064-.131.168-.131c.105 0 .34.026.354-.045.012-.071-.066-.169-.215-.163-.15.006-.438.091-.613.045 0 0-.058.084-.006.15.051.065.129.144.09.189-.039.045-.137.045-.227.039-.092-.006-.405.019-.515.059-.111.039-.215.098-.215.098l.052-.15s-.104-.033-.156.013c0 0 .02-.097.104-.117l-.098-.026s.04-.117.183-.104c.143.013.208.045.254-.007.046-.052-.111-.156-.111-.156s-.117.046-.377.085c-.261.04-.43.026-.43.026s-.033.274-.45.319c-.417.045-.625-.15-.723-.189-.098-.039-.235-.006-.235-.006l.065-.124-.157.033s-.01-.15.098-.156l-.143-.039s.104-.124.247-.091c.144.032.217.154.352.221.222.111.737.033.353-.045-.09-.018-.153-.104-.153-.104s-.245.052-.434-.241c-.129-.201-.189-.365-.424-.319 0 0 .111-.143.235-.098 0 0-.072-.091-.182-.085 0 0 .052-.13.208-.084 0 0-.085-.078-.163-.072 0 0 .045-.137.254-.02.207.114.082.213.122.284.026.045.083.125.222.248.235.208.345.261.273.049-.078-.052-.124-.186-.143-.251-.02-.065-.13-.221-.098-.261.033-.039.13.033.13.033s.124-.053.293-.053c.169 0 .234.078.234.078s.117-.091.137-.045c.019.045-.065.118-.104.196-.039.078.006.169.006.169s.114.149.349.156c.234.006.583-.033.707-.059.123-.026.338-.069.482-.042.144.026.548.016.535-.088-.014-.104-.111-.137-.312-.111-.203.026-.378.091-.75.065-.372-.026-.409-.215-.385-.307.033-.124.242-.199.437-.199.196 0 .441.082.583.082.145.002.33-.038.33-.038z"/><path fill="#DD2E44" d="M16.995 9.492s.078.037.124.033c.046-.004.127-.045.127-.045s-.026.049-.026.094-.01.092-.088.094c-.117.003-.101-.072-.107-.104-.007-.032-.03-.072-.03-.072z"/><path fill="#11429A" d="M17.19 9.913c0 .032-.026.059-.059.059h-.013c-.032 0-.058-.027-.058-.059v-.254c0-.032.026-.059.058-.059h.013c.033 0 .059.026.059.059v.254zm-1.029-.034c-.061.029-.098.073-.098.073l.143.039c-.108.006-.098.156-.098.156l.155-.033-.102-.235zm3.314.317c-.068.035-.107.115-.107.115h.129l-.059.169.105-.039-.025.137c.018-.023.062-.058.113-.086l-.156-.296zm-1.193.307l-.107-.322c-.065.029-.085.089-.085.089l.098.026c-.085.019-.104.117-.104.117.052-.045.156-.013.156-.013l-.052.15c0 .001.038-.021.094-.047zm-2.18-1.47c.045-.004.094.021.125.043l.018-.106c-.114-.022-.143.063-.143.063zm.162 1.083l-.064.123s.051-.012.112-.013l-.048-.11zm-.063-.878l.023-.141c-.125-.015-.168.092-.168.092.063-.003.113.024.145.049zm-.197.134c.072-.014.127-.008.173.012l.02-.118c-.106-.006-.193.106-.193.106z"/><path fill="#FFCC4D" d="M19.219 10.719s-.08.111-.368.111c-.287 0-.158-.038-.387-.038-.228 0-.327.058-.327.129 0 .07.082.114.386.114.303 0 .416-.076.66-.076.246 0 .34.088.34.199 0 .112-.158.316-.408.252 0 0 .174.088.361.076.188-.011.346-.046.357-.005s.086.257.076.375c-.018.182-.246.246-.34.234-.094-.011-.217.076-.252.117l.023-.123-.094.035.053-.152h-.117s.059-.117.152-.117c.094 0 .305.023.316-.041.012-.065-.059-.152-.193-.146-.135.005-.393.081-.55.041 0 0-.052.076-.005.135.046.058.116.128.081.169-.035.041-.123.041-.204.035-.082-.005-.363.018-.462.053-.1.035-.193.087-.193.087l.046-.135s-.094-.029-.141.012c0 0 .018-.088.094-.106l-.088-.023s.035-.105.164-.093c.129.011.188.041.229-.006.04-.047-.1-.141-.1-.141s-.105.041-.34.076c-.234.036-.386.023-.386.023s-.029.246-.404.287c-.375.04-.562-.135-.65-.17-.087-.035-.21-.005-.21-.005l.058-.112-.14.03s-.008-.135.087-.141l-.128-.035s.094-.111.222-.082c.129.029.195.139.316.199.198.1.661.029.316-.041-.081-.017-.138-.093-.138-.093s-.219.046-.389-.217c-.116-.18-.17-.328-.38-.287 0 0 .1-.128.21-.088 0 0-.064-.082-.164-.076 0 0 .047-.117.187-.076 0 0-.076-.07-.146-.064 0 0 .041-.123.228-.019.188.106.075.194.111.258.024.041.075.112.199.223.211.188.311.234.246.043-.07-.046-.111-.167-.128-.225-.018-.059-.117-.199-.088-.234.029-.035.117.03.117.03s.111-.047.263-.047c.152 0 .21.071.21.071s.106-.082.123-.042c.018.042-.058.105-.093.176-.035.07.006.152.006.152s.102.135.313.141c.21.005.523-.03.634-.053.111-.023.305-.061.433-.038.13.023.492.015.48-.08-.012-.093-.1-.122-.281-.099-.181.023-.338.082-.672.058-.333-.023-.367-.192-.345-.275.029-.111.216-.178.392-.178.175 0 .395.073.524.073.132 0 .298-.035.298-.035z"/><path fill="#DD2E44" d="M17.042 11.234s.07.032.111.03c.041-.004.114-.042.114-.042s-.023.044-.023.085-.009.083-.08.085c-.106.003-.09-.065-.096-.093-.005-.031-.026-.065-.026-.065z"/><path fill="#11429A" d="M17.218 11.611c0 .03-.023.053-.053.053h-.011c-.029 0-.053-.023-.053-.053v-.228c0-.03.024-.053.053-.053h.011c.029 0 .053.023.053.053v.228zm-.965-.033c-.054.025-.088.066-.088.066l.129.035c-.097.005-.088.141-.088.141l.139-.029-.092-.213zm2.976.283c-.061.032-.098.103-.098.103h.117l-.051.152.094-.035-.023.123c.016-.02.055-.052.102-.078l-.141-.265zm-1.071.277l-.096-.289c-.059.026-.077.081-.077.081l.087.023c-.076.018-.093.106-.093.106.047-.042.14-.012.14-.012l-.047.135c.001-.001.036-.02.086-.044zm-1.957-1.32c.042-.004.084.018.113.038l.016-.096c-.104-.018-.129.058-.129.058zm.145.973l-.058.11s.045-.011.101-.011l-.043-.099zm-.056-.789l.021-.127c-.112-.013-.15.083-.15.083.055-.003.1.022.129.044zm-.177.12c.064-.012.114-.008.155.011l.018-.106c-.096-.005-.173.095-.173.095z"/><path fill="#FFCC4D" d="M18.864 12.462s-.062.082-.274.082c-.213 0-.117-.028-.287-.028-.169 0-.243.044-.243.095 0 .053.06.085.287.085.226 0 .309-.057.491-.057s.252.066.252.148c0 .083-.118.235-.304.187 0 0 .131.065.269.057.139-.009.258-.035.266-.004.008.031.065.191.057.278-.014.135-.184.183-.252.174-.07-.009-.161.057-.187.087l.017-.092-.069.026.04-.113h-.088s.044-.087.112-.087c.07 0 .228.018.236-.03.008-.048-.043-.114-.144-.108-.099.004-.29.06-.408.03 0 0-.039.057-.004.1.035.044.087.096.061.127-.026.029-.091.029-.153.025-.06-.004-.269.013-.343.039-.074.026-.143.065-.143.065l.035-.101s-.07-.021-.104.009c0 0 .013-.064.07-.078l-.065-.018s.025-.078.121-.07c.096.009.139.031.17-.004.03-.035-.074-.105-.074-.105s-.079.031-.252.057c-.174.026-.287.018-.287.018s-.022.183-.3.213c-.278.031-.417-.1-.483-.125-.065-.026-.156-.004-.156-.004l.044-.083-.104.022s-.006-.101.065-.104l-.096-.026s.069-.083.165-.061.145.103.235.148c.148.073.492.021.235-.031-.06-.012-.102-.07-.102-.07s-.163.035-.29-.161c-.086-.134-.125-.243-.282-.213 0 0 .074-.095.157-.065 0 0-.048-.061-.122-.057 0 0 .035-.086.139-.057 0 0-.057-.052-.109-.048 0 0 .031-.09.17-.012s.055.144.083.192c.018.031.055.083.148.165.156.139.23.174.182.033-.052-.035-.082-.125-.095-.167-.013-.044-.087-.148-.065-.175.022-.026.087.022.087.022s.083-.035.196-.035.157.052.157.052.078-.061.091-.03c.013.03-.044.079-.07.131-.026.052.004.113.004.113s.077.1.233.104c.157.004.389-.022.472-.039.083-.018.227-.045.322-.029.096.018.366.011.357-.059-.009-.069-.074-.091-.209-.074-.134.019-.252.061-.5.044-.247-.018-.272-.143-.256-.205.022-.082.161-.133.291-.133s.294.055.389.055c.09.001.214-.025.214-.025z"/><path fill="#DD2E44" d="M17.255 12.843s.052.023.083.021c.03-.002.084-.031.084-.031s-.017.033-.017.064c0 .03-.007.061-.059.062-.078.003-.067-.047-.072-.07-.003-.021-.019-.046-.019-.046z"/><path fill="#11429A" d="M17.385 13.123c0 .021-.017.039-.039.039h-.008c-.022 0-.039-.018-.039-.039v-.169c0-.022.017-.04.039-.04h.008c.022 0 .039.017.039.04v.169zm-.686-.023c-.041.019-.065.049-.065.049l.096.026c-.071.003-.065.104-.065.104l.103-.022-.069-.157zm2.21.211c-.044.024-.071.077-.071.077h.088l-.04.113.069-.026-.017.092c.012-.016.042-.039.076-.058l-.105-.198zm-.795.206l-.071-.215c-.043.02-.057.06-.057.06l.065.018c-.057.013-.07.078-.07.078.035-.029.104-.009.104-.009l-.035.101c.001-.001.027-.016.064-.033zm-1.455-.982c.031-.003.063.015.084.029l.012-.07c-.077-.015-.096.041-.096.041zm.109.724l-.043.081s.034-.008.075-.009l-.032-.072zm-.042-.587l.015-.094c-.083-.01-.112.062-.112.062.041-.002.075.016.097.032zm-.132.09c.047-.009.084-.005.115.008l.013-.079c-.07-.003-.128.071-.128.071z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd82d4fad87f53dd777c079d5ae2166a2ac14d1a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009B3A" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#141414" d="M35.762 28.361c.154-.425.238-.883.238-1.361V9c0-.477-.084-.935-.237-1.359l-.001-.002L21.416 18l14.346 10.361zM14.584 18L.238 7.639v.001C.084 8.065 0 8.523 0 9v18c0 .478.084.936.238 1.361L14.584 18z"/><path fill="#FFD202" d="M32.535 5.035L18 15.533 3.465 5.035h-.001C1.969 5.235.736 6.261.237 7.638L14.584 18 .238 28.361l.001.003c.499 1.375 1.731 2.4 3.223 2.6h.004L18 20.467l14.534 10.497c1.494-.2 2.728-1.224 3.227-2.601l.001-.003L21.416 18 35.762 7.639c-.498-1.378-1.732-2.404-3.227-2.604z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..40710a56a8b57757e12a6b198f880979802233d5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#007A3D" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><path fill="#CE1126" d="M1.351 6.004H1.35C.522 6.737 0 7.808 0 9v18c0 1.193.522 2.264 1.351 2.997L17.5 18 1.351 6.004z"/><path fill="#FFF" d="M6.627 19.338l1.056.976-.105-1.435L9 18.662l-1.187-.812.717-1.247-1.375.421-.528-1.338-.528 1.338-1.375-.421.716 1.247-1.186.812 1.421.217-.104 1.435z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..3a724e9fd2404bc5216c43eddb70887acc4772af --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ef-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><circle fill="#ED1B2F" cx="18" cy="18" r="7"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..5bee37fd7fd3a3f0ea384f90fa594755ae3fb222 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#060" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#BB1600" d="M0 13h36v10H0z"/><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 13h36v1H0zm0 9h36v1H0z"/><path fill="#141414" d="M23.054 9.404c-.066-.039-.186.089-.794.764-.216.24-.486.539-.785.86-.608.653-1.244 1.461-.783 1.935l-7.265 12.211c-.011.018-.019.047.003.087.046.083.199.175.294.177h.003c.046 0 .068-.021.079-.039l7.268-12.215c.626.148 1.024-.784 1.305-1.616.14-.417.274-.796.381-1.1.302-.856.356-1.027.294-1.064z"/><path fill="#FFF" d="M22.305 10.208c-.216.24-.486.539-.786.861-.886.952-1.124 1.528-.769 1.868l.018.016-7.29 12.252c-.004.008.001.021.005.027.035.063.169.144.242.145h.002c.01 0 .023-.001.028-.01l7.279-12.234.012-.02.022.006c.458.13.846-.355 1.254-1.572.14-.417.274-.796.381-1.101.168-.475.314-.889.314-.984-.082.046-.375.372-.712.746z"/><path fill="#141414" d="M15.308 12.963c.461-.474-.174-1.282-.783-1.935-.299-.322-.569-.62-.785-.86-.608-.674-.728-.803-.794-.764-.062.038-.008.208.293 1.063.107.304.241.683.381 1.1.28.833.678 1.764 1.305 1.616l7.268 12.215c.011.018.033.039.079.039h.003c.095-.002.248-.094.294-.177.021-.04.014-.069.003-.087l-7.264-12.21z"/><path fill="#FFF" d="M15.25 12.937c.355-.34.118-.916-.769-1.868-.3-.322-.569-.621-.786-.861-.337-.374-.631-.7-.714-.745 0 .095.146.509.314.984.107.305.242.684.381 1.101.409 1.217.796 1.702 1.254 1.572l.022-.006.012.02 7.279 12.234c.005.009.019.01.028.01h.002c.073-.001.207-.081.242-.145.004-.007.009-.02.005-.027l-7.29-12.252.02-.017z"/><path fill="#141414" d="M18.018 10.458L18 10.444l-.018.014c-2.492 1.87-3.704 4.331-3.704 7.523s1.211 5.653 3.704 7.524l.018.013.018-.013c2.492-1.87 3.704-4.331 3.704-7.524s-1.212-5.655-3.704-7.523z"/><path fill="#BB1600" d="M20.879 14.059c-.603-1.363-1.551-2.54-2.88-3.54-1.326.999-2.273 2.174-2.877 3.533.525 1.181.782 2.468.782 3.937 0 1.467-.256 2.751-.779 3.928.604 1.356 1.55 2.529 2.873 3.527 1.326-.999 2.273-2.174 2.876-3.534-.521-1.178-.776-2.461-.776-3.921.002-1.462.258-2.747.781-3.93z"/><path d="M18 18.927c.306 0 .555-.424.555-.946s-.249-.947-.555-.947c-.306 0-.554.424-.554.947-.001.522.248.946.554.946zm-.231-2.497c-.502-.739-.746-1.677-.746-2.821 0-1.145.244-2.083.746-2.823v5.644zm.462 0c.501-.739.744-1.677.744-2.821 0-1.145-.243-2.083-.744-2.823v5.644zm-.462 3.1c-.502.738-.746 1.677-.746 2.821 0 1.146.244 2.082.746 2.822V19.53zm.462 0c.501.738.744 1.677.744 2.821 0 1.146-.243 2.082-.744 2.822V19.53z" fill="#FFF"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..2616d9e0575b4c2f87f875af24cefa367aad9ca6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E8112D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFCC4D" d="M18.473 11.986c.014-1.045.94-1.764.979-3.156.663.834-.433 2.397-.044 3.304.178-1.029 1.203-1.595 1.461-2.963.525.928-.803 2.3-.561 3.256.336-.99 1.438-1.387 1.906-2.699.373.999-1.152 2.146-1.062 3.128.486-.924 1.637-1.144 2.305-2.367.213 1.045-1.475 1.939-1.539 2.924.625-.837 1.797-.875 2.647-1.978.047 1.066-1.76 1.684-1.977 2.647.748-.729 1.91-.583 2.922-1.54-.119 1.06-2 1.389-2.367 2.306.854-.603 1.98-.277 3.129-1.063-.283 1.028-2.193 1.059-2.697 1.907.936-.462 1.996.036 3.256-.561-.441.97-2.334.702-2.965 1.461.998-.31 1.969.349 3.305-.044-.59.89-2.414.328-3.156.979 1.033-.15 1.889.651 3.269.473-.719.787-2.435-.053-3.269.473 1.045.014 1.764.941 3.154.978-.834.666-2.396-.434-3.303-.043 1.031.178 1.596 1.203 2.965 1.461-.928.525-2.301-.803-3.258-.561.99.336 1.389 1.438 2.699 1.906-.998.375-2.144-1.152-3.129-1.062.926.486 1.147 1.637 2.367 2.305-1.045.213-1.938-1.475-2.924-1.539.838.625.875 1.797 1.979 2.647-1.065.047-1.686-1.76-2.647-1.977.729.748.582 1.91 1.539 2.922-1.061-.119-1.389-2-2.305-2.367.602.854.275 1.98 1.062 3.129-1.029-.283-1.059-2.193-1.906-2.697.463.936-.037 1.996.561 3.256-.971-.441-.703-2.334-1.461-2.965.309.998-.348 1.969.044 3.305-.89-.59-.328-2.414-.979-3.156.15 1.033-.651 1.889-.473 3.269-.787-.719.053-2.435-.473-3.269-.014 1.045-.94 1.764-.979 3.154-.665-.832.433-2.396.043-3.303-.177 1.031-1.203 1.596-1.46 2.965-.525-.928.803-2.301.56-3.256-.336.988-1.438 1.387-1.906 2.697-.374-.998 1.153-2.144 1.063-3.129-.487.926-1.638 1.147-2.305 2.367-.213-1.045 1.475-1.938 1.539-2.922-.625.836-1.796.873-2.646 1.977-.048-1.065 1.76-1.686 1.977-2.647-.748.729-1.911.582-2.923 1.539.12-1.061 2.002-1.389 2.367-2.305-.853.602-1.979.275-3.128 1.062.284-1.029 2.194-1.059 2.698-1.906-.937.463-1.997-.035-3.256.561.442-.971 2.333-.703 2.964-1.461-.998.309-1.967-.348-3.304.043.588-.888 2.414-.328 3.155-.978-1.034.15-1.888-.652-3.269-.473.72-.786 2.435.053 3.269-.473-1.044-.014-1.763-.94-3.155-.979.834-.665 2.397.433 3.304.043-1.03-.177-1.595-1.203-2.963-1.46.928-.526 2.3.803 3.256.56-.99-.336-1.387-1.438-2.699-1.906.999-.374 2.146 1.153 3.128 1.063-.925-.487-1.144-1.638-2.367-2.305 1.045-.213 1.939 1.475 2.924 1.539-.837-.625-.875-1.796-1.978-2.646 1.065-.047 1.684 1.76 2.647 1.977-.729-.748-.583-1.911-1.54-2.923 1.059.12 1.389 2.002 2.306 2.367-.604-.853-.277-1.978-1.063-3.128 1.028.284 1.059 2.194 1.907 2.698-.462-.937.036-1.997-.561-3.255.97.441.702 2.332 1.461 2.963-.31-.998.349-1.967-.044-3.304.89.588.328 2.414.979 3.155-.151-1.034.651-1.888.473-3.269.786.719-.054 2.435.472 3.269z"/><path fill="#E8112D" d="M18.001 22.906c2.709 0 4.905-2.197 4.905-4.906 0-2.71-2.195-4.905-4.905-4.905-2.709 0-4.905 2.196-4.905 4.905s2.196 4.906 4.905 4.906z"/><g fill="#FFCC4D"><path d="M18 13.451c1.252 0 2.377.536 3.16 1.393-1.229.124-2.271.414-3.16.855-.889-.441-1.932-.731-3.159-.855.783-.857 1.908-1.393 3.159-1.393zm-.323 2.422c-.099.055-.195.112-.29.171-.797-.423-1.752-.696-2.887-.777.052-.073.106-.145.163-.214 1.179.105 2.174.387 3.014.82zm.649 0c.099.055.195.112.289.171.798-.423 1.752-.696 2.887-.777-.051-.073-.106-.145-.162-.214-1.18.105-2.174.387-3.014.82zm-3.969-.386c-.045.073-.088.148-.129.225 1.056.024 1.942.268 2.67.67.076-.058.154-.113.232-.167-.76-.415-1.679-.674-2.773-.728zm-.13 4.258c-.368-.633-.504-1.232-.504-2.016 0-.64.138-1.244.388-1.787 1.022-.007 1.877.216 2.575.604-1.033.847-1.872 1.839-2.459 3.199zm2.03 1.888c-.192-.074-.401-.283-.579-.383.101-1.607.853-2.929 1.901-4.041.078.076.153.152.225.233-.974 1.139-1.6 2.617-1.547 4.191zm5.389-6.146c.045.073.088.148.129.225-1.057.024-1.943.268-2.67.67-.076-.058-.154-.113-.233-.167.761-.415 1.679-.674 2.774-.728z"/><path d="M21.775 19.746c.367-.633.504-1.233.504-2.017 0-.64-.139-1.244-.389-1.787-1.021-.007-1.877.216-2.575.604 1.035.847 1.875 1.84 2.46 3.2zm-3.774-1.938c.767 1.234.914 2.584.872 4.109-.333.082-.513.09-.872.09s-.539-.008-.872-.09c-.042-1.447.105-2.828.872-4.109zm1.739 3.825c.191-.074.406-.221.584-.32-.101-1.607-.854-2.992-1.902-4.103-.077.076-.152.152-.224.233.976 1.138 1.595 2.616 1.542 4.19zm-2.416-4.652c-.091-.075-.194-.154-.293-.222-1.085.962-1.891 2.08-2.343 3.595.167.191.164.332.362.49.28-1.593 1.187-2.812 2.274-3.863zm1.355 0c.091-.075.194-.154.293-.222 1.085.962 1.888 2.1 2.341 3.616-.168.191-.192.312-.392.47-.279-1.594-1.155-2.813-2.242-3.864zm-.678-.927c.054.032.239.148.286.179-.073.045-.24.158-.286.189-.045-.032-.213-.145-.286-.189.047-.031.232-.148.286-.179zm-.541.357c-.073.055-.184.14-.226.176.105.069.246.176.291.211.055-.047.163-.143.224-.187-.074-.055-.232-.169-.289-.2zm1.082 0c.073.055.184.14.226.176-.105.069-.246.176-.291.211-.054-.047-.163-.143-.224-.187.075-.055.233-.169.289-.2zm-.541.399c.047.04.186.163.223.2-.066.058-.168.155-.223.216-.054-.061-.156-.158-.222-.216.036-.037.176-.159.222-.2z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..54f6e90471894e1ef8f24118a1e42aa363fbf6e1 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#032EA1" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#E01E24" d="M0 10.572h36v14.855H0z"/><path fill="#FFF" d="M27.021 22.897v-.902h-.542v-.901h-.496v-.586h-.226v-.451h-.438l-.238-.341v-1.599l.271-.271v-1.488l-.226.203v-.474h-.181v.226h-.359v-.723l-.429.384.136-.485-.249-1.116h-.136s-.111-.474-.337-.474c0 0 .09-.292-.091-.292s-.136.225-.136.225-.315.136-.315.473l-.18-.022-.271 1.307.191.384-.44-.384v.993H19.94v-.902l-.136.135v.316h-.315v-.316l.226-.203v-.428l-.182.191-.271-.372v-.316l-.157.157-.046-.27.226-.36-.034-.293-.258.315v-.27l.113-.248-.519-1.309-.124-.362-.191-.022v-.181s-.136-.315-.316-.315-.315.315-.315.315v.181l-.191.022-.125.362-.518 1.309.113.248v.27l-.259-.315-.035.293.226.36-.044.27-.158-.157v.316l-.27.372-.181-.191v.428l.226.203v.316h-.315v-.316l-.136-.135v.902H13.58v-.993l-.44.384.191-.384-.271-1.307-.181.022c0-.337-.315-.473-.315-.473s.045-.225-.136-.225c-.18 0-.09.292-.09.292-.226 0-.338.474-.338.474h-.135l-.248 1.116.135.485-.428-.384v.722h-.361v-.226h-.181v.474l-.225-.203v1.488l.27.271v1.599l-.239.341h-.348v.451h-.314v.586h-.452v.901h-.495v.902h-.497l-.045.991h19.035l.045-.991h-.496z"/><path fill="#DB7F86" d="M11.596 17.869v1.735h-.813l-.194.378h1.007v3.907h.342v-6.02zm13.731 2.113l-.178-.378h-.736v-1.735h-.338v6.02h.338v-3.907zm-8.222-2.113v1.735h-3.692v-1.745h-.33v6.02h.33v-3.897h3.692v3.907h.353v-6.02zm5.406 0v1.735h-3.599v-1.735h-.349v6.02h.349v-3.907h3.599v3.907h.427v-6.02z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..233cce8d7469ddfb68db7d1080bc1415a2f6907c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#CE1126" d="M32 5H4C1.791 5 0 6.791 0 9v9h35.926L36 9c0-2.209-1.791-4-4-4z"/><path fill="#FFAC33" d="M20.878 17.737c.277-.377.663-.375 1.124-.135-.064-.611-.793-.997-1.122-1.049.134-.45.565-.675 1.078-.608-.266-.553-1.146-.571-1.475-.504-.025-.471.306-.832.808-.948-.434-.427-1.267-.137-1.555.038-.18-.433.007-.887.442-1.171-.552-.251-1.239.311-1.449.576-.317-.344-.292-.836.021-1.253-.604-.045-1.059.725-1.167 1.046-.414-.212-.557-.681-.406-1.182-.58.169-.749 1.049-.741 1.388-.459-.055-.753-.447-.78-.971-.488.361-.351 1.246-.229 1.562-.451.109-.859-.159-1.06-.641-.337.509.09 1.293.311 1.547-.388.258-.86.15-1.212-.235-.146.596.52 1.185.814 1.347-.277.377-.444.654-.904.417.063.611.575.715.905.766l6.597.01z"/><path fill="#FFF100" d="M19.922 17.142l2.266-.823-2.404.012 1.85-1.563-2.257.848 1.213-2.112-1.836 1.581.429-2.406-1.193 2.123-.407-2.409-.407 2.409-1.192-2.123.429 2.406-1.835-1.581 1.212 2.112-2.257-.848 1.851 1.563-2.407-.012 2.268.823z"/><path fill="#FFF100" d="M17.583 19.521c1.292 0 2.339-1.064 2.339-2.377 0-1.313-1.047-2.377-2.339-2.377s-2.339 1.063-2.339 2.377c0 1.312 1.047 2.377 2.339 2.377z"/><path fill="#F15A29" d="M17.583 19.551c-1.307 0-2.369-1.08-2.369-2.407s1.062-2.406 2.369-2.406c1.306 0 2.369 1.079 2.369 2.406s-1.063 2.407-2.369 2.407zm0-4.754c-1.273 0-2.31 1.053-2.31 2.347s1.036 2.347 2.31 2.347c1.273 0 2.309-1.053 2.309-2.347s-1.036-2.347-2.309-2.347z"/><path fill="#FFAC33" d="M17.438 9.504c-.188-.253-.421-.522-.702-.649-.281-.126-.783-.205-1.325-.063-.607.158-1.331.403-1.901.237-.109-.031-.187.08.031.206.218.127.772.159 1.324.087.39-.05.905-.032 1.107.047.242.095.678.42.865.752l.601-.617zm1.231 1.378c.169-.067.553-.099.708-.073.204.034.486-.067.579-.109.168-.075-.011-.203-.663-.166-.429.023-.595.212-.624.348z"/><path fill="#FCD116" d="M21.094 8.491c-1.349-.063-1.692.214-2.346.269-.598.05-.974.232-1.278.586-.273.317-.544.605-.694.705-.018.012-.029.025-.044.038-.222-.016-.445-.105-.572-.228-.211-.205-.494-.229-.701-.02-.039.04-.086.104-.215.104-.222 0-.576.004-.581.376.117-.147.199-.171.577-.171.058 0 .129.028.187.127.086.146.276.261.468.265.19.004.271.133.397.269.367.396 1.185.657 1.949.364.395-.151.765-.666 1.435-.649.639.016.973-.19.421-.333-.554-.142-.976-.087-1.349-.015-.132.025-.265.006-.404-.026.054-.014.094-.045.107-.097.097.036.245-.023.277-.127.096.04.24-.016.277-.11.128.047.26.012.318-.103.085.051.233-.004.257-.123.086.056.219.048.25-.079.109.075.241.016.234-.111.05.024.154 0 .163-.079.202.008.459 0 .459-.15.172.008.413-.07.408-.256.12-.008.273-.102.309-.234.034-.111-.091-.182-.309-.192z"/><path fill="#EEE" d="M15 18h5v2h-5z"/><path fill="#00247D" d="M35.926 27.733c-.384.211-.818.313-1.562.313-1.817 0-1.817-.984-3.636-.984-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.762 0-1.201.178-1.591.383C.269 29.441 1.943 31 4 31h28c1.958 0 3.581-1.408 3.926-3.267zm.074-2.35v-1.944c-.402.228-.846.374-1.637.374-1.817 0-1.817-1.007-3.636-1.007-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 2.378 0 2.323.991 3.638.991.789 0 1.233-.207 1.635-.414zm0-4.257v-1.944c-.402.228-.846.365-1.637.365-1.817 0-1.817-.999-3.636-.999-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.191-1.636.404v2c.402-.214.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.969 3.638.969.789.001 1.233-.184 1.635-.391z"/><path fill="#EEE" d="M36 19.125v-1.979c-.402.228-.846.43-1.637.43-1.817 0-1.817-1.063-3.636-1.063-1.818 0-1.818 1-3.693 1-1.762 0-1.762-1-3.608-1-1.789 0-1.789 1-3.607 1-1.818 0-1.818-1-3.637-1-1.818 0-1.818 1-3.636 1s-1.818-1-3.636-1-1.818 1-3.636 1-1.818-1-3.637-1c-.791 0-1.234.19-1.636.404v2c.402-.213.846-.404 1.636-.404 1.818 0 1.818 1 3.637 1 1.818 0 1.818-1 3.636-1s1.818 1 3.636 1 1.818-1 3.636-1 1.818 1 3.637 1c1.818 0 1.818-1 3.629-1 1.825 0 1.825 1 3.64 1 1.822 0 1.822-1 3.639-1 1.82 0 1.82.987 3.638.987.789 0 1.233-.168 1.635-.375z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..91c12b8003cc5dd50697a1f7adce155a3d3de03c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3A75C4" d="M0 18v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0z"/><path fill="#FFC61E" d="M36 18V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v9h36z"/><path fill="#CE1126" d="M0 18h36v6.5H0z"/><path fill="#EEE" d="M0 11.5h36V18H0z"/><path fill="#3D8E33" d="M1.351 6.004H1.35C.522 6.737 0 7.808 0 9v18c0 1.193.522 2.264 1.351 2.997L17.5 18 1.351 6.004z"/><g fill="#FFF"><path d="M3.926 18c0-2.627 1.837-4.822 4.295-5.38-.395-.09-.805-.142-1.227-.142-3.05 0-5.522 2.472-5.522 5.522s2.472 5.522 5.522 5.522c.422 0 .832-.052 1.227-.142-2.458-.558-4.295-2.753-4.295-5.38z"/><path d="M7.62 14.875l.601-.437.601.437-.23-.706.601-.437H8.45l-.229-.707-.23.707h-.743l.601.437zm0 2.635l.601-.437.601.437-.23-.707.601-.436H8.45l-.229-.707-.23.707h-.743l.601.436zm0 2.635l.601-.437.601.437-.23-.707.601-.437H8.45l-.229-.706-.23.706h-.743l.601.437zm.601 2.198l.601.436-.23-.706.601-.437H8.45l-.229-.706-.23.706h-.743l.601.437-.229.706z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..461e0f263b2fd6c12a528a8953446637d9716501 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009E49" d="M4 5C1.791 5 0 6.791 0 9v15.323L26.496 5H4z"/><path fill="#CE1126" d="M32 31c2.209 0 4-1.791 4-4V11.186L8.767 31H32z"/><path fill="#FCD116" d="M26.496 5L0 24.323v1.874L29.066 5zM8.767 31L36 11.186V9.312L6.197 31z"/><path fill="#141414" d="M32 5h-2.934L0 26.197V27c0 2.209 1.791 4 4 4h2.197L36 9.312V9c0-2.209-1.791-4-4-4z"/><path d="M27.152 9.729l-2.074 1.513-2.079-1.505.798 2.439-2.074 1.513 2.567-.005.797 2.44.789-2.443 2.567-.004-2.08-1.505zM13.185 19.915l-2.074 1.513-2.079-1.505.798 2.439-2.074 1.513 2.567-.005.797 2.44.789-2.443 2.567-.004-2.08-1.505z" fill="#FFF"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..d530523c77911208d682ed1891ce1e103ed984a1 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#024FA2" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 9h36v1H0zm0 17h36v1H0z"/><path fill="#ED1C27" d="M0 10h36v16H0z"/><path fill="#FFF" d="M13.278 23.778c3.191 0 5.778-2.587 5.778-5.778s-2.587-5.778-5.778-5.778S7.5 14.809 7.5 18s2.587 5.778 5.778 5.778zm-1.257-7.508l1.257-3.868 1.257 3.868h4.067l-3.29 2.39 1.257 3.868-3.29-2.39-3.29 2.39 1.257-3.868-3.29-2.39h4.065z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..7b5ee2334f40bd0d9cb25fe9f8625505a95e655f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#C60C30" d="M21.441 13.085c-2.714-1.9-6.455-1.24-8.356 1.474-.95 1.356-.621 3.227.737 4.179 1.357.949 3.228.618 4.178-.738s2.822-1.687 4.178-.736c1.358.95 1.688 2.821.737 4.178 1.901-2.714 1.241-6.455-1.474-8.357z"/><path fill="#003478" d="M22.178 17.264c-1.356-.951-3.228-.62-4.178.736s-2.821 1.687-4.178.737c-1.358-.951-1.687-2.822-.737-4.179-1.901 2.716-1.241 6.456 1.473 8.356 2.715 1.901 6.455 1.242 8.356-1.474.951-1.355.621-3.226-.736-4.176z"/><path d="M24.334 25.572l1.928-2.298.766.643-1.928 2.298zm2.57-3.063l1.928-2.297.766.643-1.928 2.297zm-1.038 4.351l1.928-2.297.766.643-1.928 2.297zm2.572-3.066l1.93-2.297.766.644-1.93 2.296zm-1.041 4.352l1.93-2.297.765.643-1.929 2.297zm2.571-3.065l1.927-2.3.767.643-1.927 2.3zm.004-14.162l.766-.643 1.93 2.299-.767.643zM27.4 7.853l.766-.643 1.928 2.299-.767.642zm-1.533 1.288l.766-.643 4.5 5.362-.766.643zm-1.532 1.284l.767-.643 1.927 2.298-.766.642zm2.57 3.065l.766-.643 1.93 2.297-.765.643zM6.4 20.854l.766-.643 4.499 5.363-.767.643zM4.87 22.14l.765-.642 1.929 2.298-.767.643zm2.567 3.066l.766-.643 1.93 2.297-.766.643zm-4.101-1.781l.766-.643 4.5 5.362-.767.643zm-.001-10.852l4.498-5.362.767.642-4.5 5.363zm1.532 1.287l4.5-5.363.766.643-4.5 5.362zM6.4 15.145l4.5-5.363.766.643-4.5 5.363z" fill="#292F33"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..db949b28730db69bb401be8d461b908f506b2e55 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#007A3D" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#CE1126" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><path fill="#141414" d="M1.205 6.138C.462 6.865 0 7.879 0 9v18c0 1.122.462 2.135 1.205 2.862L9 22.5v-9L1.205 6.138z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..57323f8967ea4ac761d8606d5677dc87ad5a8b12 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#F9D050" d="M33.74 22.72c-.279.04-.396.44-.516.68 0 0-.279.24-.72.2 0 0 .202-.32.401-.641.2-.319.081-.72-.199-.759-.279-.041-.319-.201-.68-.52-.36-.32-1-.36-1.12-.08-.12.279-.681.48-.6.88.079.4.279.92.479 1.24 0 0-.946.6-1.707.88-.76.28-1.311.32-1.311.32s-.799-.04-1.559-.32c-.761-.28-1.484-.88-1.484-.88.199-.32.399-.84.481-1.24.079-.399-.481-.601-.601-.88-.12-.28-.76-.24-1.12.08-.36.319-.399.479-.681.52-.279.039-.4.439-.2.759s.398.641.398.641c-.44.04-.721-.2-.721-.2-.12-.24-.244-.64-.524-.68-.28-.04-.286.239-.246.521.04.279.225.8.344 1.119.12.32.331.36.772.44.44.08 1.102-.279 1.102-.279C25.29 26.04 27.536 26 27.536 26s2.465.04 4.025-1.479c0 0 .772.359 1.213.279.44-.08.707-.12.826-.44.12-.319.334-.84.374-1.119.042-.282.047-.561-.234-.521z"/><path fill="#DB1C1C" d="M33.588 24.319s.319-.959.399-1.28c.08-.319-.24-.44-.479-.24-.24.201-.601 1.361-.601 1.361s.12-.24.36-.201c.241.041.321.36.321.36zm-1.921-1.479s.44-.521.48-.841c.04-.319-.4-.72-.721-.68-.319.04-.56.28-.479.56.08.28.359.841.359.841s0-.08.161-.08c.16 0 .2.2.2.2zm-9.741 1.479s-.32-.959-.401-1.28c-.079-.319.24-.44.48-.24.24.201.601 1.361.601 1.361s-.12-.24-.36-.201c-.241.041-.32.36-.32.36zm1.92-1.479s-.44-.521-.48-.841c-.04-.319.4-.72.72-.68.32.04.561.28.48.56-.08.28-.36.841-.36.841s0-.08-.159-.08c-.161 0-.201.2-.201.2z"/><path fill="#CF1B2B" d="M27.767 15.838h-3.231v2.928h7v-2.928z"/><path fill="#FFF" d="M30.271 23.358c.56-.681 1.265-1.919 1.265-3.64v-1.486c-.214-.004-.445-.024-.503-.007-.369.106-.431.493-.879.493-.519 0-.661-.52-1.181-.52-.521 0-.691.52-1.211.52-.439 0-.805-.52-1.205-.52s-.843.52-1.203.52c-.318 0-.528-.405-.819-.5l.002 1.5c0 1.196.243 2.146.527 2.864.165.417.623 1.042.706 1.107 0 0 .945.205 1.494 1.169 0 0 .098.071.514.071.416 0 .507-.092.507-.092.547-.999 1.486-.871 1.986-1.479z"/><path fill="#0B50A0" d="M25.231 20.879c.479 0 1.079-.439 1.399-.439.32 0 .6.439 1.04.439.44 0 1-.439 1.28-.439s.72.439 1.159.439c.44 0 .6-.439.999-.439.08 0 .316.031.38.059.041-.261.061-.698.047-1.106-.167-.004-.284-.01-.364-.01-.047 0-.106-.009-.173.014-.34.119-.411.483-.846.483-.519 0-.661-.52-1.181-.52-.521 0-.691.52-1.211.52-.439 0-.805-.52-1.205-.52s-.843.52-1.203.52c-.247 0-.427-.245-.631-.398-.093-.07-.186-.093-.186-.093-.024.554.03 1.103.03 1.103.198.115.289.387.666.387zm3.764 2.361c-.515 0-.679.505-1.185.516-.506-.011-.671-.516-1.185-.516-.348 0-.625.296-.856.45.267.169.655.276 1.163.653.362.269.878.297.878.297s.516-.029.878-.297c.509-.377.897-.484 1.163-.653-.23-.154-.508-.45-.856-.45zm2.311-2.121c-.56 0-.518.52-1.037.52-.521 0-.641-.52-1.16-.52-.521 0-.681.52-1.2.52-.441 0-.801-.52-1.201-.52-.399 0-.84.52-1.199.52-.274 0-.572-.302-.857-.447 0 0 .139.835.405 1.374.091.04.214.073.331.073.48 0 1.079-.439 1.4-.439.32 0 .6.439 1.04.439.44 0 1-.439 1.28-.439s.72.439 1.159.439c.285 0 .48-.192.672-.322.184-.338.323-.728.434-1.195-.019-.002-.045-.003-.067-.003z"/><path fill="#059334" d="M25.841 19.834l.355-1.207.365 1.204 1.258-.036-1.032.72.422 1.185-1.003-.76-.997.769.412-1.189-1.038-.711zm3.681 0l.354-1.207.366 1.204 1.258-.036-1.033.72.423 1.185-1.004-.76-.996.769.412-1.189-1.039-.711z"/><path fill="#059334" d="M27.682 21.994l.354-1.208.366 1.205 1.258-.035-1.033.719.423 1.185-1.003-.758-.998.767.413-1.188-1.039-.712z"/><path fill="#F9D050" d="M25.184 16.098c.25-.205.48.12.521.32.04.2.28.48.52.48 0 0 .16-.48.28-.72.12-.24.44-.32.641-.24.2.08.56.04.52.4-.04.36-.16.52-.16.52s.72.04 1.04 0c.32-.04.681-.24.921-.12.239.12.6.16.72.08s.2-.32-.08-.28c-.28.041-.52.041-.76.081-.24.039-1.28.08-1.28-.24s.399-.36.479-.32c.081.04.681-.4.801-.2s.12.44-.24.44-.881-.08-.881.04.161.2.401.2c.239 0 .64-.16.919-.16.28 0 .681-.32.92-.12.24.2.44.48.24.6-.199.12-.92.16-1.16.12 0 0 .28.16.521.2.24.041.72.12.681.36-.041.24.079.56-.24.52-.32-.04-.28-.2-.2-.32.08-.12-.12-.24-.48-.2-.359.04-.8-.16-.8-.16s-.12.32.04.4c0 0-.48.2-.76.24-.28.04-.56.16-.56 0s.2-.4.36-.32c.16.08.439-.041.521-.041.079 0-.281-.24-.081-.32.2-.08-.159-.12-.359 0-.2.12-1.4.44-1.801.6-.399.16-.76.12-.92.2-.16.08-.479-.12-.32-.32.16-.2.24-.32.36-.2s.32.08.6 0c.28-.08-.159-.16-.239-.24-.08-.08-.4-.56-.4-.68-.005-.12-.725-.24-.285-.6zm1.483-3.019c-.24-.36-.96-.84-.96-.84l.68.2s-.32-.44-.68-.52c.079 0 .72.08.919.24 0 0-.56-.64-.84-.76 0 0 .681.2.921.44l-.28-.6s.52.24.68.56c0 0-.16-.64-.48-.96 0 0 .48.281.642.52l.118-.571.353.318.241-.444.282.459.485-.503s-.12.39-.16.751c0 0 .2-.325.64-.485 0 0-.56.858-.64 1.178 0 0 .8-.792 1.32-.992 0 0-.721.845-.92 1.165 0 0 .6-.518 1.159-.678 0 0-.72.761-.84.921 0 0 .4-.16.92-.12 0 0-1.199.68-1.479.92-.281.24-2.081-.199-2.081-.199z"/><path fill="#FFF" d="M26.098 14.844c-.432.079-.55.315-.511.551.039.236.315.432.589.314.275-.118.402-.176.512-.196.267-.049.629-.157.629-.157s.433.078.669 0c0 0 .432.196.786.039 0 0 .865.393 1.258.236.393-.157.072-.684-.118-.747-.354-.118-1.219-.236-1.888-.275-.668-.04-1.926.235-1.926.235z"/><path fill="#073163" d="M29.947 14.879c-.147-.049-.383-.099-.655-.143 0 0 .055.222.095.462.027.161.036.339.123.439.205.065.413.058.558 0 .399-.158.073-.694-.121-.758zm-2.343-.273c.123.144.199.521.371.757.062.038.458.214.795.044.037-.067-.28-.771-.28-.771-.159-.016-.733-.041-.886-.03zm-.86.896c.061.037.543-.105.543-.138-.006-.063-.06-.15-.139-.326-.065-.142-.15-.258-.241-.353-.395.06-.733.13-.817.148.168.286.353.489.654.669z"/><path fill="#059334" d="M24.787 13.239s.12-.441.64-.441.28.32.88.36c.601.04 2.721.32 3.04.48.32.16.721.12.92.08.2-.041.041.2-.159.32s-.601.04-.601.04.441.4.561.68c.12.28 0 .4-.2.28s-.44.12-.481-.04c-.04-.16-.439-.72-.439-.72s-1.16-.16-1.48.12c-.319.28-.712.384-1.36.32-.399-.04-.64-.24-.559-.48.08-.24.279-.32.279-.32s-.04-.48-.199-.36c-.16.12-.521.04-.561-.04-.041-.079-.281-.279-.281-.279z"/><path fill="#059334" d="M26.066 13.079c.172-.103 1-.48 1.641-.44.64.04 1.04.2 1.479.44.441.24.4.44.641.52.24.08.12.2 0 .32s-.521.8-1.801.76c-1.28-.04-1.4-.4-1.6-.56-.2-.16-.32-.56-.32-.68s-.239-.241-.04-.36z"/><path fill="#00493D" d="M28.467 14.279c.434-.119 1.022-.276 1.308-.702-.184-.091-.184-.278-.588-.498-.439-.24-.84-.4-1.479-.44-.452-.029-.999.151-1.341.296-.019.283-.019.624-.019.624s.36.2.64.44c.279.24 1.038.4 1.479.28z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..d2101ab54573dfef012356cc41c83cfb8a5000ac --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f0-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00AFCA" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><g fill="#FFCC4D"><circle cx="19.035" cy="16.513" r="2.865"/><path d="M19.037 13.432c.17-.002.232-.109.232-.236 0-.17-.232-1.496-.232-1.496s-.236 1.326-.236 1.496c0 .127.064.236.236.236zm0 6.178c-.172.001-.236.108-.236.235 0 .171.236 1.479.236 1.479s.232-1.309.232-1.479c.001-.126-.062-.235-.232-.235zm-.801-.121c-.165-.042-.252.045-.285.168-.044.164-.163 1.506-.163 1.506s.571-1.221.615-1.385c.034-.123-.001-.245-.167-.289zm1.6-5.968c.166.044.256-.044.289-.166.044-.165.154-1.49.154-1.49s-.562 1.203-.607 1.369c-.033.122-.001.243.164.287zm-2.343 5.658c-.149-.083-.256-.022-.319.089-.085.147-.547 1.412-.547 1.412s.867-1.031.952-1.178c.064-.111.063-.237-.086-.323zm3.089-5.351c.149.086.259.024.322-.086.086-.148.535-1.398.535-1.398s-.856 1.017-.942 1.164c-.062.11-.062.235.085.32zm-3.727 4.862c-.122-.119-.241-.088-.331.002-.12.121-.894 1.223-.894 1.223s1.105-.772 1.225-.891c.09-.09.122-.214 0-.334zm4.369-4.37c.122.121.243.09.333 0 .121-.12.879-1.213.879-1.213s-1.089.762-1.209.883c-.09.09-.123.21-.003.33zm-4.857 3.731c-.087-.146-.21-.146-.321-.083-.148.085-1.18.949-1.18.949s1.267-.458 1.414-.543c.111-.064.173-.174.087-.323zm5.35-3.089c.087.149.213.15.322.087.148-.086 1.163-.944 1.163-.944s-1.249.453-1.397.538c-.11.064-.172.171-.088.319zm-5.657 2.346c-.046-.164-.166-.196-.289-.164-.164.044-1.385.612-1.385.612s1.342-.115 1.506-.159c.123-.034.212-.123.168-.289zm5.966-1.6c.046.166.166.2.289.167.165-.044 1.368-.61 1.368-.61s-1.324.114-1.49.158c-.122.032-.211.121-.167.285zm-6.071.803c-.002-.17-.109-.232-.236-.232-.17 0-1.496.232-1.496.232s1.326.236 1.496.236c.127 0 .236-.064.236-.236zm6.178 0c.001.172.108.236.235.236.171 0 1.479-.236 1.479-.236s-1.309-.232-1.479-.232c-.127-.001-.235.062-.235.232zm-6.073-.797c.042-.165-.045-.252-.168-.285-.164-.044-1.506-.163-1.506-.163s1.221.571 1.385.615c.123.033.245-.001.289-.167zm5.967 1.599c-.044.166.044.256.166.289.165.044 1.49.154 1.49.154s-1.203-.563-1.369-.607c-.122-.032-.243-.001-.287.164zm-5.659-2.342c.083-.148.022-.256-.089-.319-.147-.085-1.412-.547-1.412-.547s1.031.867 1.178.952c.111.064.237.062.323-.086zm5.351 3.089c-.086.149-.024.259.086.322.147.086 1.398.535 1.398.535s-1.017-.855-1.164-.941c-.11-.063-.235-.063-.32.084zm-4.862-3.727c.119-.122.088-.241-.002-.331-.121-.12-1.223-.894-1.223-.894s.772 1.105.891 1.225c.09.09.213.122.334 0zm4.37 4.369c-.121.122-.09.244 0 .333.12.121 1.213.879 1.213.879s-.762-1.089-.883-1.21c-.09-.09-.21-.123-.33-.002zm-3.73-4.858c.145-.087.146-.21.083-.321-.085-.147-.949-1.18-.949-1.18s.458 1.267.543 1.414c.063.111.174.173.323.087zm3.089 5.351c-.148.086-.15.211-.087.321.086.148.944 1.163.944 1.163s-.453-1.25-.538-1.398c-.064-.109-.172-.172-.319-.086zm-2.347-5.658c.164-.046.196-.166.164-.289-.044-.164-.612-1.385-.612-1.385s.115 1.342.159 1.506c.033.123.123.212.289.168zm1.6 5.967c-.166.046-.2.166-.167.289.044.165.61 1.368.61 1.368s-.114-1.325-.158-1.489c-.032-.123-.121-.212-.285-.168z"/></g><g fill="#FFCC4D"><path d="M21.846 23.645l-.037.016-.041.006-.031.006-.057-.012-.025-.01-.023-.011-.027-.017-.045-.032-.041-.033-.023-.016-.029-.012-.02-.005h-.029l-.113.235-.023.033-.022.027-.023.017-.02.017-.029.011h-.027l-.025-.011-.035-.017-.01-.017-.012-.017-.012-.022-.012-.026-.016-.083-.033.027-.031.039-.062.094-.037.049-.039.038-.021.023-.027.017-.027.012-.033.01h-.016l-.029.006-.027-.006-.021-.01-.064-.077-.072-.077-.049.077-.057.065-.027.027-.025.027-.027.022-.051.028-.027.006h-.027l-.023-.006-.022-.012-.016-.017-.021-.026c-.014-.041-.029-.081-.045-.121l-.006-.028-.01-.021-.012-.011h-.012l-.148.242-.021.021-.039.017-.086.021h-.051l-.039-.011-.012-.006-.016-.017-.004-.01v-.022l.02-.242-.016.006-.043.021c-.039.041-.078.083-.115.126l-.049.061-.061.051-.057.043-.032.018-.066.01-.027-.006-.012-.004-.011-.012-.006-.017V24.1l.006-.07.017-.111-.011-.065-.023-.038-.033.049-.054.071c-.045.049-.091.097-.138.144-.026.017-.052.036-.077.055l-.06.021-.012-.006h-.017l-.012-.01-.004-.006-.012-.017-.004-.017v-.021l-.006-.028.006-.208c-.1.068-.201.134-.303.197l-.038.017-.043.022c-.041.01-.081.02-.121.032h-.04l-.037-.005-.034-.012.017-.044.033-.077.021-.032.024-.033.021-.033.056-.055.061-.043.07-.045.072-.033.083-.027.082-.021.187-.033.093-.012c.276-.016.553-.018.829-.016l.303-.017.094-.011.174-.033.084-.023.078-.032.072-.033c.038-.03.077-.06.117-.088l.053-.062-.057-.109.045-.006.043-.01.045-.022.037-.028.016-.01.018-.017.012-.022.012-.016.004-.022v-.038l-.012-.022.094-.017.1-.011.105-.006h.109c.153.006.305.015.457.027.23.028.461.05.692.072l.207.011v.076l-.004.034-.012.032-.01.033-.012.027-.016.022c-.019.022-.04.044-.061.065l-.049.032-.053.022-.053.012-.061.011-.117-.011-.061-.017-.053-.028-.057-.027-.043-.039-.043-.043v.094c-.008.061-.018.121-.027.182l-.021.057-.012.023-.016.016-.012.017-.014.01m-4.418-.517l.125.055c.025-.021.051-.041.077-.06l.049-.026.044-.028.165-.066.142-.066.072-.027.122-.065.049-.034c.124-.081.249-.161.374-.24l.109-.077.083-.066c.082-.074.162-.149.242-.225l.033-.022.038-.022c.046-.023.091-.045.138-.066l.093-.032c.186-.051.375-.091.565-.121.194-.023.388-.049.582-.071l.258-.044c.064-.018.128-.034.193-.049l.066-.083.106-.115.072-.071.08-.067.094-.071.109-.072.166-.098c.119-.06.237-.12.355-.182.21-.098.417-.202.623-.308l.098-.066.027-.083.039-.081.049-.083.127-.17c.058-.062.114-.124.17-.188.068-.066.138-.13.209-.192l.106-.087.053-.039.057-.038c.04-.023.08-.045.121-.066l.061-.028.059-.021.129-.034.064-.004.061-.006.064.006.061.01-.004.066-.016.065-.049.138-.041.071-.049.072-.06.076-.072.077.057-.006.049-.011.039-.012.037-.016.072-.022.103-.011.006.039v.038l-.006.038-.01.033-.016.033-.023.033-.021.026-.027.028c-.076.073-.152.144-.231.214l.065.006c.048.015.096.03.145.043l.053.012-.064.05c-.051.034-.102.067-.154.099l-.176.099-.088.055-.088.061-.082.066.037.005.051.022.022.006.021.011.018.005.016-.005-.109.061c-.068.032-.136.065-.203.099l-.084.05-.016.017-.01.017-.012.016.004.022.012.017.021.016.02.018-.008.021-.012.018-.021.016-.02.017-.053.026-.064.028-.125.044-.078.039.109.109-.039.038-.037.028-.033.017-.039.016-.076.011h-.108l.012.05.016.049.023.111c-.068.053-.138.104-.209.153l-.127.082-.141.082-.084.039-.082.038c-.093.036-.186.069-.281.099l-.213.045-.117.017c.127.004.254.006.381.005l.312-.033.137-.027.121-.033c.08-.027.158-.057.236-.088l.152-.07.15-.083.141-.089.15-.087-.09-.044-.086-.027-.041-.019c-.031-.015-.062-.03-.094-.043l-.051-.028.043-.032.053-.022.057-.021c.066-.016.133-.031.199-.045.086-.009.172-.02.258-.032l.109-.011.084-.021.022-.012.016-.017-.004-.006-.012-.011-.016-.006-.021-.01-.061-.012-.078-.011-.076-.006-.076-.011-.068-.017-.041-.017.537-.12.094-.028c.041-.015.081-.032.121-.049l.053-.034.023-.021-.006-.005-.01-.012-.051-.011-.07-.006h-.084c-.057-.004-.113-.008-.17-.01l-.07-.012-.045-.011.078-.032c.116-.036.234-.069.352-.1.067-.023.135-.046.203-.066l.104-.044.049-.027.045-.027.016-.017.017-.022.016-.016.006-.017-.006-.017-.016-.012-.017-.004h-.152l-.072.004h-.098l-.029-.004-.019-.012-.024-.011c.2-.132.402-.263.605-.391l.158-.11c.043-.035.084-.072.125-.109l.049-.055.045-.055.033-.06.027-.06.016-.067v-.071h-.037l-.039.006-.086.032c-.076.048-.154.094-.232.138l-.043.028-.051.021-.049.017-.045.011-.043.006H24.5l-.043-.017.133-.099c.107-.091.213-.183.318-.275.116-.111.229-.224.34-.341l.158-.176c.047-.062.095-.122.144-.182.039-.056.078-.113.115-.17l.012-.021.004-.017-.004-.023-.006-.016-.006-.018-.016-.011-.017-.017-.016-.006-.021-.01-.024-.006h-.043l-.021.006-.029.004-.016.018-.023.017c-.112.112-.223.226-.332.341l-.133.126c-.087.076-.175.151-.264.226-.042.028-.084.056-.127.082l-.121.061.037-.033c.04-.038.079-.076.117-.115.141-.162.276-.33.406-.5l.254-.357.068-.12.068-.11.055-.1.043-.094.027-.076.006-.027v-.044l-.006-.017-.02-.033-.012-.011-.018-.005-.031-.018-.041-.011h-.075l-.021.006-.016.005-.023.012-.016.016-.045.039c-.049.059-.097.12-.143.182-.11.172-.226.34-.346.505l-.139.165-.07.072-.076.066.098-.183.154-.323.1-.236.043-.121.076-.248c.019-.08.036-.16.051-.241.007-.075.013-.15.018-.226l-.008-.055-.004-.049-.006-.051-.016-.064-.012-.018-.027-.027-.037-.016-.041-.012h-.037l-.035.006-.01.006-.016.004-.006.012c-.099.312-.174.63-.26.945-.032.088-.064.176-.098.264l-.082.159-.051.071.033-.158c.016-.092.03-.183.043-.275l.023-.226.006-.094c-.003-.048-.007-.095-.012-.143l-.01-.055-.016-.044-.023-.033-.012-.011-.033-.011-.016-.006h-.018l-.016.006-.045.011-.043.022c-.034.17-.075.339-.121.506-.065.211-.143.418-.23.62-.059.124-.122.247-.188.368l-.121.209-.131.197c-.088.123-.179.244-.273.362-.092.104-.186.206-.281.308-.099.097-.2.193-.303.287-.106.088-.213.173-.322.257-.133.096-.269.188-.408.275l-.242.142-.385.177-.396.142-.328.1-.34.076-.17.028-.348.044-.176.011-.017.006-.017.005-.033.018-.037.026c-.043.037-.085.076-.127.115l-.088.089-.319.356-.121.121-.142.109-.056.038-.055.034-.12.055c-.186.076-.375.145-.562.22l-.049.027-.044.023-.032.021-.061.061-.017.027-.012.027-.004.039v.028"/><path d="M19.441 23.375l.092.012.045.017.01.005v.006h-.01l-.012.005-.088.017h-.07l-.23-.017-.583-.011c-.154.002-.308.006-.462.011-.136.01-.271.021-.407.033l-.105.017-.093.021c-.022.008-.043.016-.065.022l-.028.012-.022.017.01-.056.024-.056-.077.022-.066.033-.026.017-.023.022-.017.026-.004.028-.016-.038-.012-.034c-.003-.024-.007-.048-.012-.071.006-.029.012-.058.016-.087l.018-.028.01-.022.023-.026.044-.044.06-.039.068-.038c.035.021.074.037.114.049.035.005.076-.001.117-.011.061.054.219.043.241-.055.009-.032.008-.073 0-.11l.066-.005.077-.012.17-.044.089-.017.082-.021.077-.011.065-.006-.027.023-.143.109-.054.038.07.018.061.011-.13.148-.034.044.043.017.044.012.05.011h.099l.098-.022.039-.023.045.023.044.017c.028.008.057.016.086.022.068.007.136.015.205.021h.414m-.501-1.672l-.049.099-.056.127c-.029.052-.056.105-.081.158l-.028.028-.065-.055-.072-.05-.077-.039-.081-.032-.177-.045-.087-.016c-.095-.011-.19-.02-.286-.027-.127-.002-.253-.008-.379-.018l-.176-.021-.099-.017-.093-.021-.098-.034-.083-.043-.061-.04-.126-.093c-.184-.173-.366-.348-.555-.517l-.109-.076-.05-.022-.052-.016-.093-.021c-.054-.019-.109-.038-.164-.055-.051-.025-.103-.048-.155-.071-.091-.056-.178-.117-.263-.182l-.055-.051-.109-.109-.105-.115c-.173-.211-.336-.429-.505-.643-.081-.086-.163-.17-.247-.253l-.071-.065-.072-.06-.158-.115-.016.005-.018.017-.017.022c-.01.025-.018.051-.026.077l-.006.022-.04-.018-.033-.017-.04-.017-.033-.011h-.071l-.039.011-.038.017c.03.038.059.076.087.115l.049.077.089.17.032.083.012.044.012.033.005.038v.032h-.296l.043.066c.033.045.068.089.103.132l.182.182.061.049.056.039c-.048.005-.095.009-.143.012l-.144.016.049.045c.043.03.085.061.127.093l.071.049.072.044.071.039.066.022.061.016.049.011.016.006.012.012.004.005v.021l-.016.045-.004.032-.007.022v.016l.007.028.004.022.012.01.016.012.021.011.028.006.056.022.027.01.022.017.005.006v.011l-.005.006-.044.032-.022.022-.022.027v.023l-.005.022.011.059.192.066.044.01.044.018.033.017.028.017-.182.143.049.044.061.033.077.038c.055.02.11.038.166.056l.082.016.072.017h.065l-.061.044-.077.049-.082.045-.061.044.055.038c.167.086.338.166.512.237.304.124.615.232.928.329.07.017.139.035.208.055l.088.017-.177-.017c-.11-.014-.219-.031-.329-.05l-.154-.033-.303-.087-.142-.05c-.38-.148-.751-.318-1.132-.462l.028-.016.077-.028.049-.011c.067-.02.132-.042.198-.066-.131-.02-.261-.043-.391-.07-.067-.022-.135-.042-.203-.061l-.039-.017-.033-.017-.027-.018-.018-.016v-.005l.006-.006.017-.006.016-.011.044-.017.192-.056.111-.038c-.159-.03-.319-.057-.479-.082l-.077-.018-.061-.021-.022-.012-.021-.017-.018-.01-.011-.018.017-.011.049-.011c.051-.008.103-.017.154-.027l.088-.011c.05-.014.099-.029.148-.045l.023-.016.022-.018-.087-.033-.056-.01-.055-.012-.252-.033-.066-.016-.061-.012-.121-.043-.056-.028-.045-.032-.044-.039-.033-.049.012-.006.021-.006h.028l.044.006.209.011.122.012h.153l.043-.006.034-.011.022-.012c-.103-.042-.206-.086-.308-.132-.067-.034-.135-.067-.204-.099l-.208-.109-.099-.061c-.061-.043-.121-.087-.181-.132l-.077-.066-.034-.038-.034-.033-.021-.033-.023-.039-.022-.032-.012-.038-.009-.071h.037l.044.005.044.018.044.016.087.055.099.055.044.028.049.026.049.022.044.017.049.012.044.005h.05l.043-.017-.13-.1c-.108-.089-.214-.181-.319-.273-.174-.166-.341-.338-.501-.518l-.07-.093-.072-.088c-.039-.056-.078-.113-.116-.171l-.01-.022v-.038l.005-.017.005-.016.017-.011.016-.017.018-.012.021-.006.022-.004h.044l.027.004.024.006.021.017c.119.118.236.237.351.358.127.122.259.24.396.352l.126.081.065.034.061.021-.043-.027-.115-.115c-.141-.162-.275-.33-.407-.5-.058-.08-.115-.16-.171-.242-.05-.08-.101-.158-.154-.236-.042-.069-.082-.138-.121-.209-.022-.057-.046-.114-.07-.17l-.007-.027v-.045l.007-.016.021-.033.012-.012.017-.01.071-.023h.077l.022.005.016.006.022.012.061.055.143.182c.112.172.23.34.352.505l.13.165.072.071.077.066c-.087-.166-.172-.334-.252-.504-.034-.078-.067-.157-.099-.236l-.044-.121c-.023-.083-.049-.166-.077-.248l-.027-.121-.02-.123-.012-.115-.005-.109.005-.055.007-.05.005-.05.011-.049.011-.018.006-.016.016-.018.011-.01.038-.017.039-.01h.038l.033.006.016.004.012.006.006.012.006.016c.094.307.171.619.252.93.032.087.065.173.1.258l.038.082.044.077.049.077-.032-.16c-.013-.092-.027-.183-.044-.273-.011-.106-.02-.213-.027-.319l.011-.143.011-.056.017-.043.022-.033.011-.012.016-.011.016-.005h.05l.045.016.043.022.077.346c.028.105.059.21.093.313.056.157.117.313.182.467l.077.159.11.21.12.208.133.198.142.197.133.165c.092.104.185.207.28.308.099.097.2.192.303.285l.159.133c.146.114.296.222.451.324.121.072.244.142.368.209l.378.182c.192.076.386.146.582.208.192.051.387.095.583.132.263.042.533.067.804.078"/></g><g fill="#FFCC4D"><path d="M3.457 28.522s-.237.197-.317.098c-.129-.16.397-.959.397-1.241 0-.461-.309-.589-.689-.654-.256-.044-.671.019-.671.019.078.105.129.138.261.144-.147.078-.296.243-.296.501 0 .396.164.56.164 1.009 0 .249-.204.565-.204.565.36-.036.54-.369.438-.637.058-.008.109.004.154.047.026-.073-.015-.16-.071-.233.045-.023.078-.009.149.005-.007-.076-.053-.156-.164-.232.324.083.523-.142.523-.378 0-.18-.125-.308-.248-.308-.04 0-.098.017-.131.041-.023-.048-.011-.114.012-.163-.089.023-.146.076-.105.188-.069.005-.124.029-.161.074.038.047.095.075.161.072-.05.104.006.163.087.209 0 0-.052-.209.081-.209.06 0 .114.021.114.108 0 .075-.067.181-.221.175-.155-.007-.28-.107-.28-.352 0-.229.183-.342.424-.349.218-.007.382.111.382.336 0 .298-.432.98-.432 1.246 0 .2.179.311.355.311.228 0 .42-.226.42-.226l-.132-.166zm-.05-5.402c0-.498.448-.755.8-.755.474 0 .727.284.727.654 0 .212-.039.344-.136.545l-1.087 2.257c-.038.079-.051.169-.051.3 0 .202.197.368.403.373.187.005.392-.175.392-.38 0-.249-.128-.359-.261-.359-.163 0-.228.066-.228.181 0 .081.039.115.094.115.14 0 .101-.188.101-.188.069.016.125.086.094.176.051.011.098.037.135.079-.037.037-.081.065-.135.074.033.108-.011.161-.105.184.019-.043.019-.08.013-.116-.149.042-.377-.024-.377-.282 0-.256.177-.471.51-.418-.08-.036-.119-.113-.127-.201.06.025.127.028.127.028-.039-.068-.093-.127-.091-.263.062.029.119.08.198.047-.124-.243.028-.577.416-.658-.142.165-.211.345-.211.524 0 .58.162.676.162 1.078 0 .168-.087.351-.258.474v-.007c.112.03.185.087.227.162-.259.073-.636.072-.837-.007-.233-.026-.395-.205-.443-.295-.048-.092-.141-.418 0-.714.154-.321.88-1.86 1.106-2.345.048-.102.077-.212.077-.33 0-.295-.271-.399-.425-.399-.185 0-.373.142-.373.316 0 .112.061.178.147.178.209 0 .196-.177.154-.289.129.06.205.162.184.272.074.01.144.045.208.117-.051.066-.113.114-.208.115.042.17-.072.242-.184.281.035-.124.058-.269-.154-.269-.155 0-.277-.027-.348-.128-.005.135-.018.665-.018.665-.008.2.267.194.442.135-.067.23-.202.355-.517.323.077.032.158.104.158.241 0 .188-.152.395-.251.457l-.05-1.948z"/><path d="M3.506 23.12c0-.498-.448-.755-.8-.755-.474 0-.727.284-.727.654 0 .212.039.344.136.545l1.087 2.257c.038.079.05.169.05.3 0 .202-.197.368-.402.373-.188.005-.392-.175-.392-.38 0-.249.128-.359.261-.359.163 0 .228.066.228.181 0 .081-.039.115-.094.115-.14 0-.101-.188-.101-.188-.069.016-.126.086-.094.176-.051.011-.098.037-.135.079.037.037.081.065.135.074-.032.108.012.161.106.183-.019-.043-.019-.08-.013-.116.149.042.377-.024.377-.282 0-.256-.177-.471-.509-.418.079-.036.119-.113.126-.201-.06.025-.126.028-.126.028.038-.068.092-.127.09-.263-.062.029-.118.08-.198.047.124-.243-.028-.577-.416-.658.142.165.211.345.211.524 0 .58-.161.676-.161 1.078 0 .168.087.351.258.474v-.007c-.113.03-.186.087-.227.162.259.073.635.072.837-.007.233-.026.395-.205.443-.295.048-.092.141-.418 0-.714-.154-.321-.88-1.86-1.106-2.345-.048-.102-.077-.212-.077-.33 0-.295.271-.399.425-.399.185 0 .373.142.373.316 0 .112-.061.178-.147.178-.209 0-.196-.177-.155-.289-.129.06-.205.162-.184.272-.073.01-.143.045-.208.117.051.066.113.114.208.115-.042.17.072.242.184.281-.035-.124-.058-.269.155-.269.155 0 .277-.027.348-.128l.018.665c.008.2-.268.194-.443.135.066.229.202.354.516.322-.077.032-.158.104-.158.241 0 .188.151.395.251.457l.05-1.946zm-.049 5.402s.237.197.317.098c.129-.16-.397-.959-.397-1.241 0-.461.309-.589.689-.654.256-.044.672.019.672.019-.079.105-.129.138-.261.144.146.078.296.243.296.501 0 .396-.164.56-.164 1.009 0 .249.204.565.204.565-.36-.036-.54-.369-.438-.637-.057-.008-.108.004-.154.047-.026-.073.016-.16.071-.233-.045-.023-.078-.009-.149.005.007-.076.052-.156.164-.232-.324.083-.523-.142-.523-.378 0-.18.125-.308.248-.308.04 0 .098.017.131.041.023-.048.011-.114-.013-.163.09.023.146.076.106.188.069.005.123.029.161.074-.038.047-.095.075-.161.072.05.104-.006.163-.087.209 0 0 .052-.209-.081-.209-.06 0-.114.021-.114.108 0 .075.067.181.221.175.154-.007.279-.107.279-.352 0-.229-.183-.342-.424-.349-.218-.007-.382.111-.382.336 0 .298.432.98.432 1.246 0 .2-.179.311-.355.311-.228 0-.42-.226-.42-.226l.132-.166zm-.05-14.145c0-.5.448-.756.8-.756.474 0 .727.284.727.655 0 .211-.039.343-.136.544l-1.087 2.258c-.038.079-.051.168-.051.299 0 .203.197.368.403.374.187.004.392-.176.392-.38 0-.248-.128-.359-.261-.359-.163 0-.228.067-.228.182 0 .079.039.114.094.114.14 0 .101-.188.101-.188.069.015.125.086.094.174.051.011.098.038.135.08-.037.037-.081.065-.135.075.033.108-.011.16-.105.183.019-.042.019-.08.013-.116-.149.042-.377-.024-.377-.282 0-.255.177-.47.51-.417-.08-.038-.119-.115-.127-.201.06.024.127.026.127.026-.039-.068-.093-.127-.091-.262.062.028.119.08.198.047-.124-.244.028-.579.416-.658-.142.166-.211.346-.211.524 0 .579.162.676.162 1.079 0 .168-.087.35-.258.474v-.007c.11.03.182.085.225.161-.259.074-.636.072-.837-.007-.233-.027-.395-.205-.443-.295-.048-.091-.141-.418 0-.712.154-.322.88-1.861 1.106-2.346.047-.103.077-.212.077-.33 0-.296-.271-.4-.425-.4-.185 0-.373.141-.373.315 0 .112.061.179.147.179.209 0 .196-.178.154-.289.129.058.205.162.184.272.074.01.144.044.208.118-.051.064-.113.112-.208.114.042.171-.072.243-.184.282.035-.124.058-.268-.154-.268-.155 0-.277-.027-.348-.127-.005.134-.018.665-.018.665-.008.199.267.194.442.134-.065.23-.2.354-.515.322.077.032.158.104.158.242 0 .187-.152.395-.251.456l-.05-1.948z"/><path d="M3.506 14.377c0-.5-.448-.756-.8-.756-.474 0-.727.284-.727.655 0 .211.039.343.136.544l1.087 2.258c.038.079.05.168.05.299 0 .203-.197.368-.402.374-.188.004-.392-.176-.392-.38 0-.248.128-.359.261-.359.163 0 .228.067.228.182 0 .079-.039.114-.094.114-.14 0-.101-.188-.101-.188-.069.015-.126.086-.094.174-.051.011-.098.038-.135.08.037.037.081.065.135.075-.032.108.011.16.105.183-.019-.042-.019-.08-.013-.116.149.042.377-.024.377-.282 0-.255-.177-.47-.509-.417.079-.038.119-.115.126-.201-.06.024-.126.026-.126.026.038-.068.092-.127.09-.262-.062.028-.118.08-.198.047.124-.244-.028-.579-.416-.658.142.166.211.346.211.524 0 .579-.161.676-.161 1.079 0 .168.087.35.258.474v-.007c-.111.03-.184.085-.225.161.259.074.635.072.837-.007.233-.027.395-.205.443-.295.048-.091.141-.418 0-.712-.154-.322-.88-1.861-1.106-2.346-.048-.103-.077-.211-.077-.329 0-.296.271-.4.425-.4.185 0 .373.141.373.315 0 .112-.061.179-.147.179-.209 0-.196-.178-.155-.289-.129.058-.205.162-.184.272-.073.01-.143.044-.208.118.051.064.113.112.208.114-.042.171.072.243.184.282-.035-.124-.058-.268.155-.268.155 0 .277-.027.348-.127l.017.663c.008.199-.268.194-.443.134.066.23.202.354.516.323-.077.032-.158.104-.158.242 0 .187.151.395.251.456l.05-1.948z"/><path d="M3.506 12.879c0 .499-.448.756-.8.756-.474 0-.727-.284-.727-.656 0-.21.039-.342.136-.544l1.087-2.258c.038-.079.05-.168.05-.299 0-.202-.197-.368-.402-.373-.188-.004-.392.175-.392.38 0 .249.128.359.261.359.163 0 .228-.067.228-.182 0-.08-.039-.114-.094-.114-.14 0-.101.188-.101.188-.069-.015-.126-.086-.094-.175-.05-.009-.097-.036-.135-.079.037-.036.081-.064.135-.074-.032-.108.012-.16.106-.183-.019.042-.019.08-.013.116.149-.042.377.026.377.282 0 .255-.177.47-.509.417.079.038.119.115.126.201-.06-.023-.126-.026-.126-.026.038.068.092.127.09.262-.062-.028-.118-.08-.198-.047.124.244-.028.579-.416.659.142-.167.211-.346.211-.525 0-.578-.161-.676-.161-1.078 0-.168.087-.35.258-.474v.007c-.112-.031-.185-.087-.226-.163.259-.073.635-.072.837.008.233.027.395.205.443.296.048.09.141.417 0 .712-.154.322-.88 1.861-1.106 2.345-.048.102-.077.211-.077.329 0 .297.271.4.425.4.185 0 .373-.141.373-.316 0-.111-.061-.179-.147-.179-.209 0-.196.177-.155.289-.129-.058-.205-.162-.184-.272-.073-.01-.143-.045-.208-.118.051-.064.113-.113.208-.114-.042-.17.072-.243.184-.283-.035.125-.058.27.155.27.155 0 .277.026.348.127l.018-.666c.008-.199-.268-.193-.443-.134.066-.23.202-.354.516-.323-.077-.032-.158-.104-.158-.242 0-.187.151-.395.251-.456l.049 1.95zm0 8.744c0 .499-.448.755-.8.755-.474 0-.727-.283-.727-.654 0-.211.039-.344.136-.544l1.087-2.258c.038-.079.05-.168.05-.299 0-.203-.197-.368-.402-.373-.188-.005-.392.175-.392.379 0 .248.128.359.261.359.163 0 .228-.067.228-.182 0-.079-.039-.113-.094-.113-.14 0-.101.188-.101.188-.069-.016-.126-.086-.094-.175-.051-.01-.098-.037-.135-.08.037-.036.081-.065.135-.074-.032-.109.011-.161.105-.184-.019.042-.019.08-.013.116.149-.042.377.025.377.282 0 .255-.177.469-.509.417.079.039.119.115.126.202-.06-.023-.126-.027-.126-.027.038.068.092.128.09.262-.062-.028-.118-.08-.198-.047.124.243-.028.58-.416.658.142-.165.211-.346.211-.524 0-.577-.161-.676-.161-1.078 0-.169.087-.351.258-.474v.006c-.111-.029-.184-.084-.225-.161.259-.073.635-.072.837.008.233.027.395.205.443.295.048.091.141.417 0 .712-.154.322-.88 1.861-1.106 2.346-.048.102-.077.21-.077.329 0 .296.271.399.425.399.185 0 .373-.141.373-.316 0-.109-.061-.177-.147-.177-.209 0-.196.177-.155.288-.129-.058-.205-.163-.184-.272-.073-.01-.143-.043-.208-.117.051-.063.113-.111.208-.115-.042-.17.072-.241.184-.281-.035.125-.058.269.155.269.155 0 .277.026.348.128l.018-.666c.008-.198-.268-.193-.443-.134.066-.229.202-.353.516-.322-.077-.032-.158-.104-.158-.242 0-.187.151-.394.251-.456l.049 1.947z"/><path d="M3.407 21.623c0 .499.448.755.8.755.474 0 .727-.283.727-.654 0-.211-.039-.344-.136-.544l-1.087-2.258c-.038-.079-.051-.168-.051-.299 0-.203.197-.368.403-.373.187-.005.392.175.392.379 0 .248-.128.359-.261.359-.163 0-.228-.067-.228-.182 0-.079.039-.113.094-.113.14 0 .101.188.101.188.069-.016.125-.086.094-.175.051-.01.098-.037.135-.08-.037-.036-.081-.065-.135-.074.033-.109-.011-.161-.105-.184.019.042.019.08.013.116-.149-.042-.377.025-.377.282 0 .255.177.469.51.417-.08.039-.119.115-.127.202.06-.023.127-.027.127-.027-.039.068-.093.128-.091.262.062-.028.119-.08.198-.047-.124.243.028.58.416.658-.142-.165-.211-.346-.211-.524 0-.577.162-.676.162-1.078 0-.169-.087-.351-.258-.474v.006c.112-.03.185-.085.227-.162-.259-.073-.636-.072-.837.008-.233.027-.395.205-.443.295-.048.091-.141.417 0 .712.154.322.88 1.861 1.106 2.346.048.102.077.21.077.329 0 .296-.271.399-.425.399-.185 0-.373-.141-.373-.316 0-.109.061-.177.147-.177.209 0 .196.177.154.288.129-.058.205-.163.184-.272.074-.01.144-.043.208-.117-.051-.063-.113-.111-.208-.115.042-.17-.072-.241-.184-.281.035.125.058.269-.154.269-.155 0-.277.026-.348.128-.005-.134-.018-.666-.018-.666-.008-.198.267-.193.442-.134-.067-.229-.202-.353-.517-.322.077-.032.158-.104.158-.242 0-.187-.152-.394-.251-.456l-.05 1.948zm.05-14.144s.237-.199.317-.1c.129.161-.397.96-.397 1.242 0 .462.309.587.689.653.256.045.672-.018.672-.018-.08-.105-.13-.136-.262-.144.146-.076.296-.241.296-.499 0-.398-.164-.562-.164-1.01 0-.249.204-.566.204-.566-.36.037-.54.37-.438.637-.057.009-.108-.005-.153-.047-.026.074.016.16.071.234-.045.024-.078.009-.149-.006.007.077.052.157.164.233-.325-.084-.524.142-.524.379 0 .179.125.306.248.306.04 0 .098-.016.131-.041.023.049.011.115-.013.164.09-.023.146-.077.106-.188.069-.007.123-.03.161-.074-.039-.048-.096-.075-.162-.073.05-.104-.006-.162-.087-.208 0 0 .052.208-.081.208-.06 0-.114-.02-.114-.107 0-.076.067-.182.221-.175.154.006.279.106.279.353 0 .227-.183.339-.424.347-.217.006-.381-.112-.381-.336 0-.299.432-.979.432-1.246 0-.2-.179-.312-.355-.312-.228 0-.42.226-.42.226l.133.168z"/><path d="M3.457 7.479s-.237-.199-.317-.1c-.13.162.397.961.397 1.243 0 .462-.309.587-.689.653-.256.044-.671-.019-.671-.019.078-.105.129-.136.261-.144-.147-.076-.297-.241-.297-.499 0-.398.164-.562.164-1.01 0-.249-.204-.566-.204-.566.36.037.54.37.438.637.058.008.109-.005.154-.047.026.074-.015.16-.071.234.044.024.077.009.149-.006-.007.077-.053.157-.164.233.324-.084.523.142.523.379 0 .179-.125.306-.248.306-.04 0-.098-.016-.131-.041-.022.05-.01.115.013.164-.089-.023-.145-.077-.105-.187-.069-.007-.124-.03-.161-.074.038-.048.095-.076.161-.074-.05-.104.006-.162.087-.208 0 0-.052.208.081.208.06 0 .114-.02.114-.107 0-.076-.067-.182-.221-.175-.155.006-.28.106-.28.352 0 .227.183.339.424.347.218.006.382-.111.382-.336 0-.299-.432-.979-.432-1.246 0-.2.179-.312.355-.312.228 0 .42.226.42.226l-.132.169zm-.05 5.4c0 .499.448.756.8.756.474 0 .727-.284.727-.656 0-.21-.039-.342-.136-.544l-1.087-2.258c-.037-.077-.05-.167-.05-.298 0-.202.197-.368.403-.373.187-.004.392.175.392.38 0 .249-.128.359-.261.359-.163 0-.228-.067-.228-.182 0-.08.039-.114.094-.114.14 0 .101.188.101.188.069-.015.125-.086.094-.175.049-.01.097-.037.134-.08-.037-.036-.081-.064-.136-.074.033-.108-.011-.16-.105-.183.019.042.019.08.013.116-.149-.042-.377.025-.377.282 0 .255.177.47.51.417-.08.038-.119.115-.127.201.06-.023.127-.026.127-.026-.039.068-.093.127-.091.262.062-.028.119-.08.198-.047-.124.244.028.579.416.659-.142-.167-.211-.346-.211-.525 0-.578.162-.676.162-1.078 0-.168-.087-.35-.258-.474v.007c.112-.031.185-.087.227-.163-.26-.072-.637-.071-.839.009-.232.026-.395.204-.442.295-.048.09-.141.417 0 .712.154.322.88 1.861 1.106 2.345.047.103.077.212.077.329 0 .297-.271.4-.425.4-.185 0-.373-.141-.373-.316 0-.111.061-.179.147-.179.209 0 .196.177.154.289.129-.058.205-.162.184-.272.074-.01.144-.045.208-.118-.051-.064-.113-.113-.208-.114.042-.17-.072-.243-.184-.283.035.125.058.27-.154.27-.155 0-.277.026-.348.127-.005-.134-.018-.666-.018-.666-.008-.199.267-.193.442-.134-.065-.228-.2-.352-.515-.321.077-.032.158-.104.158-.242 0-.187-.152-.395-.251-.456l-.05 1.948z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ea005dbe4a41f189547af36453be62e29179ced --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-3H0v3zM32 5H4C1.791 5 0 6.791 0 9v3h36V9c0-2.209-1.791-4-4-4z"/><path fill="#002868" d="M0 24h36V12H0v12zm18-11c2.761 0 5 2.239 5 5s-2.239 5-5 5-5-2.239-5-5 2.239-5 5-5z"/><circle fill="#FFF" cx="18" cy="18" r="5"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e7.svg new file mode 100644 index 0000000000000000000000000000000000000000..4271b73a4cb49be82c5aaf916eede8f890b72da5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED1C23" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="green" d="M16.993 13.204c-.183.203-.615.486-.713.679-.098.194-.413.392-.581.464-.169.072-.021.188.163.073.185-.115.338-.11.446-.214.108-.104.264-.005.112.066-.151.072-.209.192-.275.278-.066.087-.099.13-.252.133-.153.003-.289.04-.396.196-.108.155-.24.337-.297.423-.058.086-.014.154.129.048.142-.106.302-.194.373-.076.071.117.068.173-.122.249-.405.162-.522.258-.595.421-.073.164-.03.214-.283.295-.254.082-.664.381-.932.582-.268.202-.115.212.09.202.314-.016.718-.229.924-.139.062.118.134.269.23.378-.331.466-.386.646-.726.654-.341.008-.554.353-.712.526-.158.174-.295.338-.459.41-.144.063-.176.115-.064.171.112.058.211-.08.314-.032.103.049.171.031.33-.075s.327-.246.581-.277c.122.142.184.218.322.291-.24.328-.6.583-.913.692-.313.108-.361.228-.585.514-.223.286-.213.379-.442.384-.23.006-.22.057-.099.147.121.091.214.047.393.086.18.038.41.076.643-.176.233-.253.804-.693 1.288-.65.23.021.393.068.118.329s-.672.461-.942.514c-.525.106-.751.315-.904.309-.154-.006-.296.1-.063.239.233.14.31.173.571.056.261-.116.69-.313.86-.358.169-.047.295-.118.415-.086.12.031.213-.006.347-.093.134-.088.33-.1.496-.257.194-.183.4-.026.529.081.13.108.386.536.155.831-.232.294-.489.606-.571.761-.082.155-.128.165-.225.2-.312.118-.631.312-.723.391-.092.078-.057.103.071.126.128.023.145-.003.261-.099.117-.096.259-.243.548-.234.153.005.279-.082.412-.222.134-.139.42-.264.565-.234.145.031.187-.003.271-.066.083-.061.151-.088.281.02.13.108.24.088.375.009.135-.08.28-.049.316.036.035.084.054.16.175.243.121.082.552.337.69.411.137.073.228-.065.124-.156-.104-.091-.157-.167-.141-.244.016-.077.095-.108.329-.076.367.052.892.313 1.082.427.191.116.363.214.516.21.154-.003.203-.039.065-.164-.14-.124-.309-.111-.372-.238-.107-.219-.292-.061-.389-.281-.069-.157-.165-.176-.284-.165-.119.011-.278-.096-.388-.264-.388-.587-.493-1.112-.366-1.507.128-.394.499-.513.716-.347.217.166.473.27.584.259.111-.011.205-.012.349.069.147.082.396.136.699.01.303-.126.41-.027.603-.021.163.004.358.034.49.142.129.108.327.18.625.225.298.045.501-.037.26-.176-.243-.139-.447-.22-.536-.346-.087-.126-.216-.148-.343-.146-.127.003-.334-.086-.507-.26-.174-.176-.312-.207-.447-.187-.136.02-.289-.019-.385-.136.131-.156.272-.448.396-.536.154-.012.281.028.385.119.105.091.249.071.352.069.102-.002.247.045.334.103.087.058.223.055.349.001.125-.053.098-.121-.056-.211-.156-.09-.243-.148-.296-.233-.051-.083-.096-.125-.283-.121-.187.004-.276-.087-.423-.246-.332-.358-.552-.379-.766-.35-.212.03-.423.069-.599-.182.218-.107.396.139.679-.074.151-.114.251-.142.441-.078.189.064.41.042.467-.002.06-.044.136-.114.229-.124.091-.011.08-.134-.056-.118-.263.031-.309-.13-.563-.081-.254.048-.347.008-.512-.108-.165-.116-.303-.215-.786-.136.022-.154.009-.315.247-.363.18.107.349.086.494.083.145-.003.639-.006.783.017.147.022.178-.047-.038-.161-.214-.114-.521-.159-.632-.165-.111-.006-.165-.081-.236-.225-.071-.143-.285-.257-.601-.259-.256-.002-.444-.118-.574-.234-.131-.116-.251-.208-.405-.23-.154-.022-.293-.13-.227-.259.065-.129.319-.185.501-.071.18.116.292.121.4.059.109-.062.178-.089.341-.033.162.056.325.052.073-.138-.363-.273-.719-.163-.841-.313-.122-.151-.223-.089-.307-.053-.085.036-.237-.048-.055-.144.135-.071.27-.108.391-.051.12.057.265.037.356-.008.094-.045.185-.131-.097-.185-.282-.054-.711-.223-.877-.373-.164-.149-.343-.179-.487-.151-.144.029-.263.048-.513-.108s-.577-.311-.805-.629c-.224-.308-.245-.111-.387.044z"/><path d="M16.152 15.017c-.165-.02-.299.057-.213.17.085.113.129.042.236-.011.107-.054.207-.133-.023-.159zm.455.36c-.151.073-.297.16-.344.314-.048.154-.042.29.101.253.216-.056.23-.311.388-.34-.052-.076-.067-.178-.145-.227zm.265-.134c.014.063.035.165.087.215.139-.067.493-.202.627-.231.011-.096-.016-.159-.043-.21-.191.018-.47.087-.671.226zm1.191.601c.002.094.042.331.061.425.086.041.197.072.283.096.057-.112.071-.274.069-.376-.156-.099-.295-.206-.413-.145zm-.303.135c.01.076.013.187.023.255-.111.002-.288.066-.398.102-.11.037-.242-.165-.048-.245.194-.081.321-.101.423-.112zm-2.723.766c.201-.107.306-.04.491-.096.087.083.191.183.261.283-.107.181-.433.061-.542.14-.086-.092-.148-.184-.21-.327zm.821-.206c.053.11.107.202.15.252.153.014.211-.072.277-.176.066-.104.063-.231-.107-.219-.17.013-.263.049-.32.143zM14.531 18.5c.045.109.173.149.209.234.142-.088.211-.081.331-.058.12.022.441-.087.624-.278.183-.191.064-.171-.148-.141-.212.03-.373.068-.518.037-.146-.031-.366.033-.498.206zm1.878-.892c-.101.062-.151.105-.072.197.079.092.12.049.213-.005.093-.053.134-.13.081-.198-.054-.065-.122-.055-.222.006zm.498-.157c-.102.002-.094.066-.08.116.014.051.027.082.11.081.083-.002.095-.021.068-.104-.027-.082-.034-.095-.098-.093zm.308.088c.003.116-.017.109.098.126s.154.01.157-.099c.004-.108.009-.147-.125-.151-.132-.003-.131.041-.13.124zm.475.092c-.033.092-.08.168.062.222.141.055.147.016.189-.106.042-.122.047-.18-.062-.21-.109-.029-.147-.022-.189.094zm.505.034c-.005.051-.047.192-.065.238.058.024.135.054.194.091.058.037.139-.067.111-.162-.028-.095-.133-.246-.24-.167zm.598-1.526c-.018.064-.077.276-.101.334.167.041.295.064.41.055.115-.009.299-.044.389-.028.089.017.138-.073-.011-.185-.149-.111-.239-.128-.335-.127-.095.003-.258-.114-.352-.049zm.636.79c-.114-.018-.177.074-.098.136.078.062.179.034.19-.023.012-.057.017-.096-.092-.113zm.256-.031c.007.057.022.159.023.204.085.081.173-.004.264.077.091.081.158-.003.176-.087.018-.083.029-.128-.047-.126-.167.003-.278-.141-.416-.068zm-1.811-1.964c.02.044.073.145.075.196.077.049.258.102.307.012.049-.091.067-.129-.017-.172-.085-.042-.267-.198-.365-.036zm.686.158c-.055.062-.011.096.067.139.078.043.134-.028.126-.086-.008-.058-.112-.145-.193-.053zm-2.52 4.345c.058.052.105.126.09.21-.015.086.037.119.097.144.06.023.217.171.247.011.031-.163-.103-.415-.197-.43-.093-.016-.136-.015-.18-.065-.044-.05-.17.03-.057.13zm5.245-.675c-.04.145-.196.462-.296.525-.153-.073-.436-.136-.463-.22.056-.154.111-.283.154-.377.175-.038.456-.053.605.072zm-.959-.218c-.004.111-.069.359-.1.445-.178.021-.605-.063-.749-.009.006-.119.002-.273.035-.351.272-.005.523-.181.814-.085z" fill="#EEE"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..12b2237e33b10140f1744c1c3dd2ff14a58d6fab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#6CF" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M9.333 28.747l2.346-2.909L18 10.2l6.321 15.638 2.346 2.909L18 7.34z"/><path d="M24.321 25.838L18 10.2l-6.321 15.638L18 18z"/><path fill="#FCD116" d="M18 18l-6.321 7.838-2.346 2.909h17.334l-2.346-2.909z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..9e474bc1f44fbae14d5f4be91cb9ae2ed86c67b1 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1B26" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#002B7F" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#B28914" d="M12.516 11.415c0-.744-.585-1.334-1.428-1.334-.892 0-1.873.3-2.623.468h-.568c-.75-.167-1.73-.468-2.623-.468-.843 0-1.428.59-1.428 1.334 0 .889.328 1.545.726 2.317h7.217c.399-.772.727-1.428.727-2.317z"/><path fill="#FFD83D" d="M7.826 10.408l-.023.328c-.626-.095-1.513-.445-2.341-.445-.764 0-1.357.306-1.357 1.077 0 .76.322 1.451.75 2.153l-.445.211c-.397-.772-.725-1.429-.725-2.317 0-.744.584-1.475 1.591-1.475.891 0 1.801.301 2.55.468zm.711 0l.023.328c.626-.095 1.513-.445 2.341-.445.765 0 1.357.306 1.357 1.077 0 .76-.322 1.451-.75 2.153l.445.211c.397-.772.725-1.429.725-2.317 0-.744-.584-1.475-1.591-1.475-.891 0-1.801.301-2.55.468zm-.356-3.382l-.262.492.262.49.263-.49zm0 1.242l-.262.49.262.492.263-.492zm-.935-.13l.414.262.412-.262-.412-.263zm1.045 0l.412.262.414-.262-.414-.263z"/><path fill="#FFD83D" d="M8.181 7.945c.11 0 .199.088.199.198 0 .11-.089.199-.199.199-.109 0-.199-.088-.199-.199 0-.109.09-.198.199-.198zm0 .936c.294 0 .533.238.533.533 0 .293-.238.531-.533.531-.294 0-.532-.238-.532-.531 0-.294.238-.533.532-.533zm0 3.319c-.658 0-1.141.311-1.17 1.1-.161-.283-.841-1.173-1.476-1.054-.376.071-.71.594-.653 1.194-.313-.898-1.228-1.046-1.896-.515.593.488.857 1.927 1.356 2.552h7.68c.499-.625.764-2.064 1.357-2.552-.668-.531-1.583-.383-1.895.515.055-.6-.279-1.124-.657-1.194-.634-.119-1.313.771-1.474 1.054-.03-.79-.514-1.1-1.172-1.1z"/><path d="M11.718 15.253c-.591-.164-1.95-.246-3.537-.247-1.057 0-2.015.037-2.71.11-.348.036-.629.082-.827.137-.194.058-.319.111-.329.224.009.112.132.175.326.249.591.211 1.951.386 3.539.386 1.058 0 2.017-.078 2.712-.192.348-.057.63-.123.827-.194.195-.073.317-.137.326-.249-.008-.114-.133-.167-.327-.224z"/><path fill="#FFD83D" d="M7.715 10.383s.585.084.931 0c0 0 .135 1.197.252 1.641 0 0-.412-.117-.702-.117s-.733.117-.733.117.083-.539.146-.898.106-.743.106-.743zm-4.403 1.635c-.189-.804-.198-1.625.817-2.324s2.708-.109 3.176.007.478.627-.096.484-2.183-.591-2.959.102-.626 1.204-.507 1.614c.344 1.181-.284.744-.431.117zm9.739.046c.189-.804.198-1.625-.817-2.324s-2.708-.109-3.176.008-.478.627.096.484 2.183-.591 2.959.102.621 1.202.507 1.614c-.261.945.283.743.431.116z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..a2fe8143e0001fc65d438d3dd89df5ea32ccf890 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFB700" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#8D2129" d="M32 6H10v24h22c1.654 0 3-1.346 3-3V9c0-1.654-1.346-3-3-3z"/><path fill="#005641" d="M4 6C2.346 6 1 7.346 1 9v18c0 1.654 1.346 3 3 3h1V6H4z"/><path fill="#FF5B00" d="M5 6h4v24H5z"/><path d="M13.199 10.062s-.067-.959-.035-1.762c.021-.532-.277-1.175-.84-1.082s-1.188-.021-1.188-.021.125.364 0 .708-.125 1.062.719 1.156c.844.095 1.188.532 1.344 1.001zm18.684 0s.067-.959.035-1.762c-.021-.532.277-1.175.84-1.082s1.188-.021 1.188-.021-.125.364 0 .708.125 1.062-.719 1.156c-.844.095-1.188.532-1.344 1.001zM13.199 25.938s-.067.96-.035 1.763c.021.532-.277 1.175-.84 1.081-.562-.094-1.188.021-1.188.021s.125-.365 0-.709-.125-1.062.719-1.156c.844-.094 1.188-.532 1.344-1zm18.684 0s.067.96.035 1.763c-.021.532.277 1.175.84 1.081.562-.094 1.188.021 1.188.021s-.125-.365 0-.709.125-1.062-.719-1.156c-.844-.094-1.188-.532-1.344-1zM18.406 13.375s.594-.031 1.188-.188c.594-.156.406-.718.406-.718s.531-.281.844 0c.312.281.688.25.5-.125.562-.281.812.344.812.344s.281-.177.344-.417c.5-.052.594.448.906.385s.531-.389.531-.389.062.889-.469 1.108c.438.562.312 1.656.312 1.938l-.312-.188s.188.875.281 1c.094.125-.312 0-.312 0s.219.594.375.688c.156.094 3.094-.188 3.938-.188.844 0 2-.125 2-.875s-.969-.688-2.062-.531c-1.094.156-1.812.125-2.25-.156-.438-.281-.937-.354-.896.354-.667-.312-.188-.979-.188-.979s-.761-.833-.276-1.667c.484-.833 2.359-1.084 3.672-.354s1.833 1.333 2.375 1.438c-.021-.396.646-.687.729.042s-.834.583-1.229.354-1.104-.917-1.104-.917-.021.417.25.688c-.75-.083-.916-.646-.916-.646s-.043.603-.73.624c.5-.583.333-1.062-.354-1.312.396.604.021 1.125-.562 1.208.396-.562.063-1.208-.666-1.333.104.458-.25.583-.25.583s-.166-.417-.5-.188-.418.73.019 1.042c.271-.542.812-.5 1-.271-.562.062-.541.584-.333.854.208-.354.417-.458.625-.083s.833.354 1.958.188 2.161-.044 2.333.958c.146.854-.708 1.271-.708 1.271s1.104.833.396 2.646-.416 2.562-.146 2.75.688.208.125.708-.417.855-.188 1.146.167.583-.5.208c-.292.292-.583.208-.75-.042-.167.229-.479.292-.688.042-.208.167-.479.167-.333-.188s.854-.5 1.062-.562.188-.438.125-.854-.417-.854-1.167-1.25c-.333.25-.292.541-.167.688s.521.188.542.312-.208.396-.458.584-.208.521-.125.688.187.577-.084.768c-.271.19-.541-.247-.541-.247s-.168.521-.646.021c-.271.334-.541.209-.666.021-.271.271-.688.25-.479-.125s.458-.376.75-.396.687-.082.646-.666-.156-1.177-.562-1.542c-.625-.562-.521-1.229-.521-1.229s-1.042-.104-1.854.459-1.438.562-1.438.562-.459.5-.5.812.146.417.396.5.438.062.062.396-.688.312-.688.312-.019.353.022.561-.084.569-.292.607c-.208.038-.521-.232-.521-.232s-.396.417-.708-.021c-.354.333-.667.209-.792 0-.208.333-.542.188-.333-.188s.5-.418 1-.396.916-.375.729-.896-.354-1.229-.354-1.229-.396-.042-.979-.375c-.729.875-.979.563-1.188.396s-.708-.625-.708-.625-.271-.021-.229.229c-.292-.021-.188-.479-.188-.708s-.083-.5-.25-.5-.417.042-.417.042 0 .082.25.166.229.251-.021.271-.417.082-.229.229.208.229.062.375-.125.541.125.688c.167-.396.479-.166.417.104s-.521.229-.521.229l.312.354-.476.104s-.024.292-.211.354-.229-.438-.229-.438l-.438-.021.292-.354s-.417-.146-.438-.396.312-.125.375 0c.333-.146.229-.479.104-.604s-.042-.229.083-.375.104-.229-.083-.188-.5-.334-.188-.334.375-.021.333-.25c-.375-.041-.146-.333-.146-.333s-.292-.209-.083-.354c-.188-.166-.229-.438-.021-.479-.125-.104.042-.292.042-.292s-.601-.102-.601-.56.521-.375.521-.375-.062-1.458.083-3.5 1-2.75 1.521-2.958c-.542 1.146-.479 3.083-.479 4.271s-.021 2.125-.021 2.125.583.041.541.437-.312.479-.312.479L18 19.833s-.062-1.389.396-1.944c.458-.555 1.166-1.076 1.375-1.243s-.129-.609-.291-.125c-.236-.029-.438-.417-.438-.417s.021.146-.125.25c-.146.104-.104-.354-.188-.312s-.312.167-.604.25c.021-.167.146-.375.146-.375s-.375.041-.709.083c0-.292.187-.771.354-.812-.417-.208-.312-.604-.125-.542s1.062.583 2.042.646c-.312-.354-.562-.812-.562-.812l-.104.354-.375-.354-.042.354s-.917-.667-1.083-1.208.021-.939.333-.896c.604.082.406.645.406.645z" fill="#FFB700"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd4a1e47b3ebb9c90f5193c2d046b1e974c85b96 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path d="M35.692 28.538H.308C.911 29.983 2.336 31 4 31h28c1.664 0 3.089-1.017 3.692-2.462zM0 23.811h36v2.561H0zM11.5 9.629H36v2.561H11.5zm24.192-2.167C35.089 6.017 33.664 5 32 5H11.5v2.462h24.192zM11.5 14.356H36v2.561H11.5zM0 19.083h36v2.561H0z" fill="#BF0A30"/><path d="M11.5 12.189H36v2.167H11.5zM0 16.917v2.166h36v-2.166H12zm11.5-9.455v2.167H36V9c0-.545-.111-1.064-.308-1.538H11.5zM0 21.644h36v2.167H0zM0 27c0 .545.111 1.064.308 1.538h35.383c.198-.474.309-.993.309-1.538v-.629H0V27z" fill="#EEE"/><path fill="#002868" d="M4 5C1.791 5 0 6.791 0 9v7.917h12V5H4z"/><path fill="#FFF" d="M6.794 10.245L6 7.802l-.794 2.443H2.638l2.078 1.51-.794 2.443L6 12.688l2.078 1.51-.794-2.443 2.078-1.51z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..ec06e4fcc56708439fe2228acf1868c2fa10f1eb --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009543" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#00209F" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><g fill-rule="evenodd" clip-rule="evenodd"><path fill="#292F33" d="M21.199 19.859c-.015-.047-.426.141-.426.141l-1.846-2.362c.226-.405.49-1.073.49-1.904 0-1.241-.658-1.567-1.077-1.654v-.055c0-.172-.139-.311-.311-.311h-.059c-.172 0-.311.139-.311.311v.056c-.419.087-1.076.413-1.076 1.654 0 .848.275 1.528.504 1.93L15.328 20s-.359-.188-.375-.141c-.016.047-.75 1.219-.75 1.219s1.562 1.02 3.797 1.02c2 0 3.873-1.02 3.873-1.02s-.658-1.172-.674-1.219zm-2.105-4.078c0 .554-.221 1.157-.424 1.529l-.352-.45c.004-.02.022-.033.022-.054v-.728h.488l-.488-.488v-1.121c.494.174.754.719.754 1.312zm-2.188 0c0-.594.26-1.138.753-1.312v1.121l-.488.488h.488v.728c0 .025.021.041.026.064l-.345.458c-.204-.37-.434-.982-.434-1.547z"/><path fill="#53646D" d="M20.797 20.344s-1.422.526-2.797.526-2.797-.526-2.797-.526l-.344.649s1.453.649 3.141.649 3.141-.649 3.141-.649l-.344-.649z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..5fcfd8bf192d9e1b798d76d18a40c4d11a1a9539 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006A44" d="M0 14h36v8H0z"/><path fill="#FDB913" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#C1272D" d="M4 31h28c2.209 0 4-1.791 4-4v-5H0v5c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..e66c904e782207fadee12e2c7fa6a147c4beb443 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#ED2939" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#00A1DE" d="M4 31h28c2.209 0 4-1.791 4-4v-5H0v5c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..f5f39223b38748cda911d9df2e89a59997cde12c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#9E3039" d="M32 5H4C1.791 5 0 6.791 0 9v6h36V9c0-2.209-1.791-4-4-4zm0 26H4c-2.209 0-4-1.791-4-4v-6h36v6c0 2.209-1.791 4-4 4z"/><path fill="#EEE" d="M0 15h36v6H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..c6c12ed669110b2de676e8a7c9f74806bbe8e038 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f1-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M0 24h36V12H0v12zm21.25-8.298l1.032 1.42 1.67-.542L22.92 18l1.032 1.42-1.67-.542-1.032 1.42v-1.756L19.58 18l1.67-.543v-1.755zM18 14.75c.902 0 1.718.368 2.307.961-.464-.335-1.033-.535-1.649-.535-1.56 0-2.824 1.264-2.824 2.824s1.264 2.824 2.824 2.824c.617 0 1.185-.2 1.649-.535-.589.593-1.405.961-2.307.961-1.795 0-3.25-1.455-3.25-3.25s1.455-3.25 3.25-3.25z"/><path fill="#E70013" d="M32 5H4C1.791 5 0 6.791 0 9v3h36V9c0-2.209-1.791-4-4-4z"/><path fill="#239E46" d="M32 31H4c-2.209 0-4-1.791-4-4v-3h36v3c0 2.209-1.791 4-4 4z"/><path fill="#FFF" d="M18 21.25c.902 0 1.718-.368 2.307-.961-.464.335-1.033.535-1.649.535-1.56 0-2.824-1.264-2.824-2.824s1.264-2.824 2.824-2.824c.617 0 1.185.2 1.649.535-.589-.593-1.405-.961-2.307-.961-1.795 0-3.25 1.455-3.25 3.25s1.455 3.25 3.25 3.25z"/><path fill="#FFF" d="M21.25 18.542v1.756l1.032-1.42 1.67.542L22.92 18l1.032-1.42-1.67.542-1.032-1.42v1.755L19.58 18z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d6d689a31bd09bc3bcd41fd6427fc7751c124ba7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1272D" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#006233" d="M15.047 22.165l1.128-3.471-2.953-2.145h3.649L18 13.074l1.129 3.474h3.649l-2.953 2.145 1.128 3.471L18 20.019l-2.953 2.146zm3.583-2.603l.916.665-.35-1.077-.566.412zm-1.826-.412l-.35 1.077.916-.665-.566-.412zm.241-.74l.955.694.955-.694-.365-1.122h-1.182l-.363 1.122zM15.5 17.288l.915.665.216-.665H15.5zm3.869 0l.216.665.915-.665h-1.131zm-1.019-.74L18 15.47l-.35 1.079h.7z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..8604a1c4517efa6ec11c8706b1a3a8c8bba020fe --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 18v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0z"/><path fill="#CE1126" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..eb2d4a2062dbaca1f4262eda4903b5ba298f0d44 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#265FB5" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FFCC4D" d="M12 5h12v26H12z"/><path fill="#DD2E44" d="M16 15h4v3h-4z"/><path fill="#269" d="M16 18v2l2 1 2-1v-2z"/><path fill="#A0724A" d="M16 11v1h1v2h2v-3zm3 10l-1 .625L17 21l-1 3 2 1 2-1zm-4-8l-1-1-1 1v10l2-2v-7h1zm7-1l-1 1-1 1h1v7l2 2V13z"/><path fill="#FFCC4D" d="M16.234 17.594h.531V18h-.531zm3 0h.531V18h-.531z"/><path fill="#77B255" d="M15.637 22.743c-.106.062-.263-.01-.35-.159l-2.232-3.866c-.086-.15-.07-.321.037-.383l.136-.078c.106-.062.263.01.349.159l2.232 3.867c.087.149.07.32-.036.382l-.136.078z"/><path fill="#FFCC4D" d="M22.817 18.393c.107.061.125.23.039.377l-2.191 3.798c-.086.147-.24.216-.348.155l-.135-.078c-.106-.062-.124-.23-.039-.378l2.192-3.798c.085-.146.24-.217.347-.154l.135.078z"/><path fill="#DD2E44" d="M16 21l-1 1v1l1-1zm4 0v1l1 1v-1z"/><path fill="#FFCC4D" d="M18 17l-1-1v2.958L18 20l1-1.042V16z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..47c5b2e526240990cc6391c762e8ec4c03ac8a14 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#DD2E44" d="M35 27c0 1.657-1.343 3-3 3H4c-1.657 0-3-1.343-3-3V9c0-1.657 1.343-3 3-3h28c1.657 0 3 1.343 3 3v18z"/><path fill="#FFCC4D" d="M22.885 17.401c.604-2.41-1.354-4.542-1.354-4.542l-.513 2.501-1.055 1.39.438.779-.437.242-1.037-1.437.384-.869 1.336-.689-1.479-.489-.896 1.043L18 16.483l-.342-1.153-.968-1.043-1.388.316 1.163.776.465.955-.953 1.483-.521-.289.438-.779-1.054-1.39-.513-2.501S12.37 14.99 12.973 17.4c.604 2.41 3.201 2.747 3.201 2.747l-1.652 1.117-.967.078-.165 1.062.876.407.77-.844 1.918-.703-1.094 1.594L18 24l2.069-1.141L19 21.351v-.062l1.84.681.761.844.872-.407-.168-1.062-.969-.078-1.652-1.117c0-.002 2.597-.34 3.201-2.749z"/><path fill="#5C913B" d="M18 19.5v1.297s-.181-.271-.75-.438c-.75-.219-.875-.859-.875-.859H18zm.002 0v1.297s.181-.271.75-.438c.75-.219.875-.859.875-.859h-1.625z"/><path fill="#269" d="M16.734 16.797s.734.297 1.266.031v2.547h-1.625s-.062-.547.156-1.266c.137-.449-.125-.812-.125-.812l.328-.5zm2.534 0s-.734.297-1.266.031v2.547h1.625s.062-.547-.156-1.266c-.137-.449.125-.812.125-.812l-.328-.5zm3.81 4.375c0 .44-.356.797-.797.797-.441 0-.797-.356-.797-.797 0-.441.356-.797.797-.797.441 0 .797.356.797.797z"/><path fill="#FFCC4D" d="M19.031 14.023c0 .22-.437.398-.977.398s-.977-.178-.977-.398c0-.22.437-.398.977-.398s.977.178.977.398z"/><path fill="#FFCC4D" d="M18.031 12.25c-.846 0-1.531.395-1.531.883s.685.883 1.531.883c.846 0 1.531-.395 1.531-.883s-.685-.883-1.531-.883zm-1.078 1.253c-.188-.082-.188-.3-.156-.457.031-.156.297-.312.297-.312s-.181.379-.028.541c.153.163.075.31-.113.228zm.646-.013c-.068-.021-.076-.096-.119-.223s-.09-.22-.059-.377c.031-.156.421-.287.421-.287s-.109.318-.078.474c.031.156.156.322.156.322s-.253.112-.321.091zm.967-.223c-.043.127-.051.202-.119.223-.068.021-.322-.089-.322-.089s.125-.166.156-.322-.078-.474-.078-.474.39.13.421.287c.032.155-.015.249-.058.375zm.528.236c-.188.082-.266-.066-.113-.228.153-.162-.028-.541-.028-.541s.266.156.297.312c.031.157.031.376-.156.457zm3.981 7.755c-.027.109-.139.174-.247.147l-1.104-.287c-.108-.028-.173-.141-.146-.248.028-.109.139-.174.247-.146l1.104.287c.109.028.176.137.146.247z"/><path fill="#FFCC4D" d="M22.495 21.131c-.024.096-.121.154-.219.129-.097-.025-.153-.122-.128-.22l.247-1.131c.024-.095.121-.153.219-.128.097.025.153.123.128.219l-.247 1.131zm-7.66 2.744c-.06.023-.166-.102-.235-.278l-1.945-4.941c-.07-.177-.078-.34-.018-.364l.099-.039c.061-.023.314.043.384.219l1.945 4.941c.07.177-.071.398-.131.423l-.099.039zm2.349-5.627h1.631v1.127h-1.631z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..4eafe7aa5b829db665fd04bc0c35c1254f13b444 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED2939" d="M36 27c0 2.209-1.791 4-4 4h-8V5h8c2.209 0 4 1.791 4 4v18z"/><path fill="#002495" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..becf2f46180aceedb52a596f04e4e9654d7105c9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FC3D32" d="M32 5H13v13h23V9c0-2.209-1.791-4-4-4z"/><path fill="#007E3A" d="M13 31h19c2.209 0 4-1.791 4-4v-9H13v13z"/><path fill="#EEE" d="M13 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h9V5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..6774f9b34f7f77880fdfea51a1fb28aa20d02265 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#003893" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#F4900C" d="M34.593 5.977L.835 29.42c.025.033.053.064.08.098L36 11V9c0-1.214-.553-2.289-1.407-3.023z"/><path fill="#EEE" d="M1.012 29.635L36 17v-6L.915 29.518c.032.039.063.079.097.117z"/><path fill="#FFF" d="M9 6.917l.306 5.156 1.022-2.158-.442 2.347 1.639-1.737-1.146 2.096 2.096-1.146-1.737 1.639 2.347-.442-2.158 1.023 5.156.305-5.156.306 2.158 1.022-2.347-.442 1.737 1.639-2.096-1.146 1.146 2.096-1.639-1.736.442 2.346-1.022-2.158L9 21.082l-.306-5.155-1.022 2.158.442-2.346-1.639 1.736 1.146-2.096-2.096 1.146 1.737-1.639-2.347.442 2.158-1.022L1.917 14l5.156-.305-2.158-1.023 2.347.442-1.737-1.639 2.096 1.146-1.146-2.096 1.639 1.737-.442-2.347 1.022 2.158z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..371b2358f6aeffe6e6aa9858f6fd0691cc509563 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D20000" d="M34.618 5.998L32 6l-1.5-1H20l-2 1-2-1H5.5L4 6l-2.618-.002C.542 6.731 0 7.797 0 9v6.5L1 18l-1 2.5V27c0 1.203.542 2.269 1.382 3.002L4 30l1.5 1H16l2-1 2 1h10.5l1.5-1 2.618.002C35.458 29.269 36 28.203 36 27v-6.5L35 18l1-2.5V9c0-1.203-.542-2.269-1.382-3.002z"/><path fill="#FFE600" d="M36 20.5v-5l-13.681 1.9c-.101-.724-.369-1.391-.779-1.957l13.091-9.455C33.928 5.373 33.008 5 32 5h-1.5l-9.663 9.691c-.659-.566-1.482-.932-2.392-1.026L20 5h-4l1.555 8.665c-.911.094-1.733.46-2.392 1.026L5.5 5H4c-1.008 0-1.928.373-2.632.988l13.092 9.455c-.41.566-.678 1.233-.779 1.957L0 15.5v5l13.681-1.9c.101.724.369 1.391.779 1.957L1.368 30.012l.001.001C2.072 30.628 2.993 31 4 31h1.5l9.663-9.691c.659.566 1.482.932 2.392 1.026L16 31h4l-1.555-8.665c.911-.094 1.733-.46 2.392-1.026L30.5 31H32c1.008 0 1.929-.373 2.632-.988L21.54 20.557c.41-.566.678-1.233.779-1.957L36 20.5z"/><path fill="#D20000" d="M18 13.62c-2.415 0-4.38 1.965-4.38 4.38s1.965 4.38 4.38 4.38 4.38-1.965 4.38-4.38-1.965-4.38-4.38-4.38zm0 7.737c-1.851 0-3.357-1.506-3.357-3.357s1.506-3.357 3.357-3.357 3.357 1.506 3.357 3.357-1.506 3.357-3.357 3.357z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..3a522a0fd4330e6ed3a25b759a60145b18ae0983 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#14B53A" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FCD116" d="M12 5h12v26H12z"/><path fill="#CE1126" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..69db533a9f82f2968132f051f8181b1387cd4e02 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA2839" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#34B232" d="M0 13h36v10H0z"/><path fill="#FECB01" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M18 8.76L20.353 16h7.613l-6.159 4.333 2.352 7.169L18 22.992l-6.159 4.458 2.353-7.107L8.035 16h7.613z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..b9635cf7bbb1ca3d82a79c5a8b4f28b979df9615 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C4272F" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#005197" d="M12 5h12v26H12z"/><g fill="#F9CF01"><path d="M1.286 16.429h1.571V29H1.286zm2.395 2.357H8.32v.786H3.681zm5.462-2.357h1.571V29H9.143zm-5.462 9.427H8.32v.786H3.681zm.087-9.427h4.464L6 17.989zm-.087 11.198h4.638L6 29.249zm3.89-15.913c0 .869-.704 1.571-1.571 1.571s-1.571-.703-1.571-1.571c0-.869.704-1.571 1.571-1.571s1.571.703 1.571 1.571zm-.785-2.946c0 .759-.352.982-.786.982s-.786-.223-.786-.982C5.214 8.008 5.754 7 6 7s.786 1.008.786 1.768z"/><path d="M6 14.404c-1.303 0-2.438-.593-3.084-1.477.271 1.462 1.546 2.567 3.084 2.567s2.813-1.105 3.084-2.566c-.646.883-1.781 1.476-3.084 1.476zm2.569 8.31c0-1.095-.687-2.022-1.649-2.39.299.257.58.447.58 1.062 0 .973-.578 1.496-1.5 1.496v.009c-.642.024-1.158.547-1.158 1.193 0 .645.516 1.167 1.158 1.191v.008c.01 0 .018-.003.028-.003.005 0 .009.003.014.003.015 0 .027-.008.042-.008 1.379-.045 2.485-1.169 2.485-2.561zm-2.94 1.37c0-.229.183-.413.413-.413.229 0 .413.184.413.413 0 .228-.183.414-.413.414-.23 0-.413-.186-.413-.414z"/><path d="M6 20.152v-.006l-.021.002-.01-.002c-.011 0-.02.006-.031.006-1.389.034-2.507 1.162-2.507 2.562 0 1.096.687 2.023 1.649 2.391-.299-.257-.557-.448-.557-.999 0-.98.524-1.522 1.43-1.522l.002-.018c.005 0 .009.003.014.003.668 0 1.211-.546 1.211-1.212 0-.659-.527-1.188-1.18-1.205zm-.031 1.62c-.231 0-.417-.188-.417-.417 0-.229.185-.419.417-.419s.417.189.417.419c-.001.229-.186.417-.417.417z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..790900e40eca249973770b0ca05ff6ec021bfae5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00785E" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><g fill-rule="evenodd" clip-rule="evenodd"><path fill="#FBD116" d="M17.976 8.567c.181.347.279.775.407 1.174h1.272c-.328.256-.678.489-1.008.743.094.41.248.759.36 1.15-.068.027-.164-.064-.24-.119-.22-.163-.513-.383-.742-.552-.373.186-.713.533-1.031.695.101-.402.257-.749.36-1.151-.307-.277-.657-.51-1.007-.743.367-.056.839-.008 1.246-.023.143-.375.278-.76.383-1.174zm-5.441 3.404c.246-.147.466-.317.695-.479-.104-.247-.149-.554-.264-.791.221.075.458.341.695.479.247-.144.469-.314.695-.479-.019.229-.18.523-.239.791.184.214.439.358.67.527-.241.058-.589.014-.838 0-.124.243-.21.525-.288.815-.126-.233-.192-.527-.264-.815h-.647c-.017-.07-.196.021-.215-.048zm10.714.048h-.623c-.103.257-.168.551-.264.815-.109-.259-.193-.543-.289-.815-.27.024-.561.029-.862.024.208-.192.464-.335.671-.527-.066-.293-.178-.541-.264-.815.243.149.465.319.695.479.271-.138.46-.356.719-.503-.104.246-.148.554-.264.79.202.198.454.346.695.504-.018.069-.196-.022-.214.048zM11.266 13.48c.117.226.118.568.191.839.301.019.569.069.862.096-.241.142-.48.286-.742.407.016.304.095.545.144.815-.07.016-.21-.121-.312-.216-.112-.104-.213-.236-.311-.311-.27.122-.498.284-.767.407.12-.248.219-.516.359-.743-.169-.239-.4-.414-.623-.599.251-.043.571.051.839.072.138-.237.254-.496.36-.767zm13.804.767c.288-.031.559-.081.863-.096-.204.206-.435.381-.625.6.129.24.229.507.361.743-.229-.052-.505-.263-.744-.383-.232.15-.441.453-.646.551.042-.277.122-.517.144-.814-.236-.148-.476-.292-.743-.408.243-.077.558-.081.839-.119.105-.237.107-.58.192-.839.133.241.248.501.359.765z"/><path fill="#FFF" d="M21.427 23.211c-1.558-.08-2.548-.728-3.451-1.463-.844.776-1.874 1.368-3.402 1.463h-4.506c.005.019 0 .047.023.047.104.16.209.318.336.455 1.401.096 3.067.049 4.481.025 1.357-.082 2.26-.617 3.092-1.223.829.608 1.735 1.14 3.091 1.223 1.441.023 3.107.07 4.482-.025.121-.145.232-.295.336-.455.007.003.019-.004.025 0-.176-.107-.718-.047-1.008-.047h-3.499zm3.594 1.149c.042.007.084-.093 0-.071-4.689.031-9.494-.064-14.092.048.024 0 .028.019.048.023.062.07.145.189.24.216.189.052.532 0 .838 0h12.774c.051-.087.143-.129.192-.216zm-.862.839c.024.001.028-.018.048-.024.002-.029.03-.032.023-.071-3.994.078-8.175-.106-12.15 0-.068.002-.271-.068-.288.071.024 0 .029.02.048.024.147.109.29.223.432.335 3.764.041 7.693.041 11.456 0 .142-.112.286-.225.431-.335zm-1.101.79c.063-.046.056-.033 0-.047-.332-.078-.844 0-1.271 0h-8.34c-.155 0-.605-.032-.503.047.281.175.572.339.887.48 2.724.039 5.616.039 8.339 0 .314-.141.606-.304.888-.48zm-1.582.793h.047c-.001-.041-.009-.044-.047-.049-.526-.077-1.158 0-1.75 0-1.762 0-3.616-.039-5.249.049h.049c.861.318 1.788.575 2.924.622.096.056.295.009.431.024h.24c.136-.016.335.031.431-.024 1.13-.051 2.062-.3 2.924-.622z"/><path fill="#FFF" d="M15.915 16.644c.046 1.144.355 2.025.839 2.732-.385-.855-.726-1.797-.623-3.02.133-1.597.953-2.864 1.894-3.618.887.799 1.696 2.014 1.845 3.595.123 1.316-.277 2.358-.743 3.211.521-.669.916-1.671.959-2.9.04-.041.04-.247 0-.288-.031-.839-.218-1.525-.503-2.109.151-.303.396-.515.478-.886.38.602.625 1.34.695 2.253v.743c-.067 1.131-.45 1.947-.91 2.684-.021.003-.074.079-.024.072.049-.087.142-.129.192-.216 1.035-.881 2.253-1.581 4.098-1.653h.432c.045.072-.116.163-.192.264-.082.108-.141.252-.216.336-2.006.039-3.316.774-4.361 1.772.789-.543 1.871-1.156 3.14-1.269 1.213-.108 2.265.079 3.163.455-.255.688-.616 1.269-1.078 1.75-.114.095-.218.198-.312.311-.826.748-1.83 1.316-3.307 1.414h-.575c0 .023.029.018.048.023.1.062.272.048.431.049.113.039.392.039.504 0 1.606-.062 2.612-.727 3.522-1.486.126.09.692.066.576.192-.13.109-.249.229-.359.359-.848.742-1.877 1.302-3.38 1.39h-.504c-1.517-.088-2.552-.658-3.402-1.414-.081-.086-.142-.192-.264-.239-.058.094-.157.146-.215.239-.851.756-1.887 1.325-3.403 1.414h-.503c-1.517-.091-2.558-.654-3.403-1.414-.103-.122-.214-.233-.336-.335.013-.034-.094-.06-.024-.072.21-.022.408-.056.576-.12.937.74 1.925 1.43 3.547 1.486.111.039.391.039.503 0 .158-.001.333.013.431-.049h.048c-.144-.055-.391-.008-.574-.023-1.479-.096-2.481-.667-3.308-1.414-.094-.113-.198-.217-.312-.311-.46-.482-.827-1.059-1.078-1.75.893-.377 1.936-.556 3.139-.455 1.26.107 2.345.702 3.116 1.246.046.058.112.096.168.145-.009-.08-.072-.104-.12-.145-1.071-.956-2.345-1.713-4.339-1.748-.155-.179-.345-.454-.455-.599h.455c1.814.08 3.045.742 4.051 1.629.098.102.175.225.311.287.018-.104-.047.019-.048-.047-.025-.055-.055-.106-.096-.144-.435-.723-.799-1.518-.863-2.612v-.743c.061-.916.331-1.619.672-2.253.126.328.316.595.503.863-.24.526-.42 1.113-.479 1.821-.055.034-.009.168-.024.24v.071c-.043.039-.043.245-.003.286zm.839 2.732c.019.085.061.146.12.191-.019-.085-.062-.145-.12-.191z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..f0a5fb45dc575b816182b7f5437e08ac5c9b3928 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#265FB5" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFF" d="M25.935 18.32c-.017-.324-.222-.581-.222-.581s.308-.29.29-.718c-.018-.427-.428-.734-.428-.734s.138-.154.154-.479c.017-.325-.257-.444-.257-.444s.103-.274-.051-.445c-.154-.171-.394-.154-.394-.154s.223-.222.068-.53c-.153-.307-.427-.376-.427-.376s.068-.376-.205-.649c-.273-.274-.752-.24-.752-.24s.084-.563-.153-.803c-.24-.239-.769-.085-.769-.085.085-.206-.069-.582-.325-.752-.257-.17-.974-.103-.974-.103.051-.188-.154-.427-.462-.53-.308-.103-.615.051-.615.051s-.29-.342-.547-.359c-.256-.017-.444.103-.444.103s-.138-.308-.445-.308-.922.411-.922.411-.701-.325-1.042-.308c-.342.017-.53.239-.53.239s-.358-.206-.769-.017c-.41.188-.444.461-.444.461s-.257-.137-.667-.051c-.41.085-.461.513-.461.513s-.325-.137-.649.085c-.325.222-.239.444-.239.444s-.24-.188-.633.017c-.393.205-.393.564-.393.564s-.256-.068-.564.342c-.308.41-.256.581-.256.581s-.325.017-.513.496 0 .718 0 .718-.273.12-.479.53c-.205.411-.068.821-.068.821s-.376.171-.342.667c.034.496.359.615.359.615s-.29.154-.325.547c-.034.394.223.547.223.547s-.256.154-.273.479c-.017.323.547.513.547.513s-.205.119-.205.428c0 .307.41.442.41.442s-.171.155-.068.549c.102.392.461.392.461.392-.102.291.24.394.24.394s-.154.102.119.429c.273.322.547.203.547.203-.12.359.222.479.222.479.035.633.735.479.735.479.12.581.564.444.564.444s-.188.256.103.564c.291.309.752.204.752.204.256.411.82.563 1.453.462.632-.102 1.316-.137 1.641-.222.325-.085 2.479.017 2.479.017s.819.188 1.264-.051c.444-.24.41-.462.41-.462s.239.153.701-.067c.461-.224.376-.703.376-.703s.427 0 .667-.221c.239-.221.154-.359.154-.359s.375-.188.511-.358c.138-.172.018-.343.018-.343s.17.085.478-.188c.309-.274.273-.719.273-.719s.223.034.411-.273c.188-.309.067-.581.067-.581s.257-.19.411-.581c.153-.393.017-.805.017-.805s.204-.306.187-.631zm-2.188.65c.017.051-.137.018-.341.309-.206.289-.068.683-.068.683s-.239.188-.394.36c-.153.17-.153.495-.153.495s-.205.017-.496.255c-.29.239-.29.666-.29.666s-.205-.051-.513.207c-.308.256-.308.598-.308.598s-.223-.172-.685.051c-.462.223-.871.599-.871.599s-3.469-.034-3.726-.411c-.256-.374-.94-.203-.94-.203s.068-.225-.273-.445c-.342-.222-.667-.119-.667-.119s.188-.102.102-.275c-.085-.17-.324-.152-.324-.152s.136-.051.051-.359c-.085-.307-.581-.273-.581-.273s.222-.136.068-.427c-.154-.292-.513-.239-.513-.239s.069-.257 0-.512c-.068-.258-.341-.309-.341-.309s.222-.034.17-.343c-.051-.308-.393-.461-.393-.461s.069-.204.069-.547c0-.341-.206-.427-.206-.427s.256-.12.291-.41c.034-.29-.154-.598-.154-.598s.171-.137.24-.359c.068-.223-.035-.342-.035-.342s.223-.137.308-.377c.086-.239.051-.495.051-.495s.188-.052.359-.256c.171-.205.086-.393.086-.393s.393.017.581-.188c.188-.206.206-.462.206-.462s.239.034.547-.188c.308-.222.273-.427.273-.427s.29.085.529-.068c.24-.154.359-.427.359-.427s.085.12.444 0 .496-.239.496-.239.137.205.479.136c.342-.068.615-.29.615-.29s.052.239.428.171c.375-.069.529-.189.529-.189s-.034.256.24.325c.273.068.53-.035.53-.035s.033.189.222.223.324-.102.324-.102.034.273.326.427c.29.154.768.068.768.068s-.017.137.188.239c.206.103.41.137.41.137s-.068.29.258.393c.323.103.512.103.512.103s.034.24.153.479c.12.239.428.342.428.342s-.104.154-.051.427c.051.274.443.393.443.393s-.101.189-.034.445c.068.256.257.444.257.444s-.12.256-.137.479c-.017.222.257.82.257.82s-.273.154-.257.462c.017.303.137.56.154.611z"/><path fill="#FFB636" d="M17.925 24.223c-3.637 0-6.6-2.749-6.723-6.358-.003.078-.005.156-.005.233 0 3.716 3.013 6.729 6.728 6.729 3.717 0 6.729-3.013 6.729-6.729 0-.078-.002-.156-.005-.233-.123 3.609-3.087 6.358-6.724 6.358z"/><path fill="#B58FE5" d="M19.867 10.8s-.216-.33-.66-.273c-.445.057-1.025-.171-1.379-.353-.353-.183-.899.091-.899.535 0 .444.285.661.694.661.41 0 .969-.183 1.356-.444.321-.218.888-.126.888-.126z"/><path fill="#6B26B5" d="M17.623 11.374c-.444 0-.698-.242-.698-.665 0-.199.108-.378.297-.493.195-.118.434-.136.608-.045.175.09.743.361 1.23.361.05 0 .099-.003.146-.009.035-.004.069-.007.101-.007.375 0 .562.279.563.282l.006.008-.01-.001c-.004 0-.569-.089-.885.125-.387.261-.945.444-1.358.444zm-.042-1.253c-.119 0-.245.034-.355.102-.186.113-.293.29-.293.486 0 .417.252.657.69.657.411 0 .968-.183 1.353-.444.295-.201.806-.137.882-.127-.036-.049-.25-.315-.65-.264-.048.006-.098.009-.147.009-.49 0-1.059-.272-1.234-.363-.074-.037-.158-.056-.246-.056z"/><path fill="#B58FE5" d="M24.243 13.615c.604 0 .614.535.627.752.011.217.103.672.25.854.149.182.32.615.343.797.022.183 0 .365-.16.125-.16-.239-.536-.718-.899-.923-.365-.205-.809-.502-.809-.958-.001-.454.375-.647.648-.647z"/><path fill="#6B26B5" d="M25.422 16.263c-.03 0-.07-.038-.122-.116-.166-.248-.542-.721-.898-.922-.402-.225-.812-.516-.812-.961 0-.475.4-.652.653-.652.589 0 .617.515.63.734l.001.021c.01.196.096.662.249.852.146.179.32.609.344.799.007.052.022.222-.033.243l-.012.002zm-1.179-2.644c-.25 0-.646.175-.646.645 0 .441.408.73.808.954.357.201.734.675.9.924.061.09.097.113.117.113l.009-.002c.033-.012.044-.102.027-.234-.023-.189-.196-.617-.342-.795-.155-.191-.241-.66-.251-.857l-.001-.021c-.012-.236-.04-.727-.621-.727z"/><path fill="#B58FE5" d="M25.246 17.466c.421 0 .593.319.593.672 0 .354-.206.65-.297 1.002-.091.354-.057.855-.126 1.026-.068.172-.159.263-.159.263s-.101-.147-.125-.388c-.023-.239 0-.615-.17-.913-.172-.295-.411-.67-.411-1.013 0-.342.422-.649.695-.649z"/><path fill="#6B26B5" d="M25.256 20.435l-.002-.004c-.001-.001-.103-.15-.126-.39-.005-.051-.008-.108-.011-.17-.012-.227-.025-.508-.159-.741l-.044-.075c-.163-.278-.367-.625-.367-.94 0-.348.436-.653.699-.653.44 0 .597.349.597.676 0 .222-.079.417-.163.625-.049.121-.1.246-.134.378-.047.185-.061.407-.072.604-.011.183-.021.34-.054.423-.068.17-.159.263-.16.264l-.004.003zm-.01-2.965c-.261 0-.691.302-.691.645 0 .313.203.658.366.936l.045.075c.134.235.147.518.159.744.003.062.006.119.011.171.021.214.105.355.122.381.017-.019.095-.107.154-.258.033-.081.043-.237.054-.419.012-.198.024-.422.072-.606.034-.132.085-.257.134-.379.084-.207.163-.402.163-.622 0-.157-.043-.668-.589-.668z"/><path fill="#B58FE5" d="M10.342 15.609s.171.182.262.399c.091.216.137.592.331.832.194.239.604.934.604 1.23 0 .296-.217.592-.604.592s-.823-.33-.842-.694c-.035-.627.331-.545.285-.991-.035-.331-.012-.376-.023-.547-.016-.224-.013-.821-.013-.821z"/><path fill="#6B26B5" d="M10.935 18.666c-.408 0-.828-.346-.846-.698-.019-.336.078-.471.164-.589.076-.105.142-.195.121-.401-.022-.209-.021-.304-.02-.389 0-.049.001-.096-.003-.158-.015-.221-.012-.815-.012-.821v-.01l.007.007c.002.002.173.186.263.4.03.071.055.16.082.254.056.195.118.416.248.576.185.228.605.931.605 1.233-.001.289-.214.596-.609.596zm-.589-3.047c0 .081-.002.605.012.81.004.063.004.11.003.159-.001.084-.002.18.02.388.021.209-.048.305-.122.407-.085.117-.181.25-.163.584.019.348.434.69.838.69.39 0 .601-.303.601-.588 0-.3-.419-1-.604-1.228-.131-.161-.194-.383-.25-.579-.027-.094-.052-.183-.082-.253-.078-.189-.22-.353-.253-.39z"/><path fill="#B58FE5" d="M14.262 11.393s-.398.352-.603.9c-.206.547-.422 1.401-1.048 1.401-.524 0-.662-.444-.662-.718 0-.273.354-.57.707-.684.353-.114.575-.28.752-.502.273-.342.809-.41.809-.41"/><path fill="#6B26B5" d="M12.61 13.698c-.647 0-.666-.648-.666-.722 0-.283.368-.578.709-.688.326-.105.558-.259.751-.5.271-.339.806-.411.811-.411l.001.008c-.005.001-.537.072-.806.408-.194.242-.427.397-.754.503-.339.109-.704.4-.704.68 0 .073.019.714.658.714.547 0 .781-.659.968-1.188.026-.073.051-.144.076-.21.203-.542.601-.898.605-.901l.005.006c-.004.003-.4.358-.602.898-.025.066-.05.137-.076.21-.188.532-.422 1.193-.976 1.193z"/><path fill="#8C8A8C" d="M16.826 13.023c.877 0 1.527.022 1.982.022.457 0 .912.148.912.57 0 .421-.227.57-.227.57s.091.318-.057.661c-.149.341-.411.524-.878.524s-1.298.011-1.527.011c-.227 0-.442-.055-.592-.57-.445-1.526-.081-1.788.387-1.788zm.262 2.369h1.72c.194 0 .366 0 .387.547.024.547.981 8.159 1.037 8.728.057.57-.422.638-.422.638s-.136.263-.763.444c-.627.182-.855.114-1.071.057-.216-.057-.456-.125-.763 0-.308.125-.582.092-.844-.045-.262-.136-.285-.343-.285-.343s-.171-.046-.376-.204c-.205-.158-.194-.547-.137-.81.057-.261.923-7.656.991-8.181.07-.523.15-.831.526-.831z"/><path fill="#FFF" d="M17.955 13.303l1.025 3.209 3.402.008-2.767 1.978 1.076 3.227-2.736-2.021-2.737 2.021 1.076-3.227-2.767-1.978 3.402-.008z"/><g fill="#FFB636"><path d="M12.109 17.283s-.202-.647-.661-.558c-.354.068-.251.251-.137.353.114.102.114.171.216.102.103-.068.262-.057.342.023.08.08.24.08.24.08zm-1.436-1.812s.068.069.148.206c.08.136.388.205.513.159.125-.045.16.331.046.433-.114.102-.245.153-.467-.046-.32-.284-.24-.752-.24-.752zm1.071.058c.171-.058.33.091.308.319-.023.228-.262.684-.262.684s-.046-.091-.08-.205c-.034-.114.125-.17.023-.354-.103-.182.011-.444.011-.444zm-.49-1.641s.239.228.375.274c.137.045.411-.069.49.113.08.183.103.57-.216.467-.319-.103-.444-.296-.524-.467-.079-.171-.125-.387-.125-.387zm1.698-.513c.137-.148.478-.16.501.125.023.285-.216.809-.216.809s-.069-.183-.08-.262c-.011-.08-.08-.331-.228-.387-.148-.057.023-.285.023-.285zm.615-.707c.194-.137.41-.023.468.148.056.171-.069.798-.171.934l-.068-.228c-.022-.08.011-.387-.251-.456-.263-.066.022-.398.022-.398zm1.082-1.754s-.638.581-.262 1.026c.376.444.433 0 .387-.137-.045-.137-.011-.148-.091-.274-.08-.125-.08-.262-.034-.364.046-.103 0-.251 0-.251z"/><path d="M14.205 12.35c-.023.171.034.251.137.33.102.08.045.398.045.398s.205-.045.25-.421c.046-.376-.102-.569-.205-.569s-.227.262-.227.262zm.866-.547c-.103.126-.125.421.045.547.171.126.102.513.102.513s.25-.148.273-.501c.022-.354-.194-.604-.194-.604l-.226.045zm.809-1.242s-.559.491-.274.9c.285.41.559-.091.456-.193-.102-.103-.273-.194-.205-.376.069-.183.023-.331.023-.331z"/><path d="M15.926 11.621c.182-.057.296.069.33.262.034.193-.251.763-.251.763s-.125-.114-.069-.285c.058-.17-.056-.285-.159-.387-.102-.103-.033-.296.149-.353zm1.31-.353c-.213.05-.33.25-.148.399.182.148.171.227.125.341-.045.114.011.251.011.251s.239-.125.307-.479c.07-.353-.101-.558-.295-.512zm2.802-.685s-.204.456.034.752c.24.296.468.068.456-.103-.011-.171-.171-.205-.273-.273-.102-.068-.159-.068-.137-.17.025-.103-.08-.206-.08-.206zm.013.946c-.104.046-.149.376-.092.479.058.103-.079.229-.114.354l-.034.125s.285-.091.468-.365c.183-.273.193-.502.079-.581-.114-.08-.307-.012-.307-.012zm.979-.752s-.502.421-.456.821c.046.399.422.307.49.114.067-.194-.058-.353-.079-.468-.023-.114.021-.182.056-.273.034-.091 0-.194-.011-.194z"/><path d="M20.894 11.894c-.104.125-.046.376-.046.524 0 .148-.17.296-.159.434 0 0 .513-.125.581-.661.068-.537-.376-.297-.376-.297zm.752-.262c.215-.171.593-.148.878-.045 0 0-.081.182-.239.171-.16-.012-.081.319-.479.376-.4.056-.331-.365-.16-.502zm.25.866c-.201.08-.308.354-.114.456.193.103.17.16.159.308-.012.149.081.262.081.262s.146-.216.181-.559c.035-.342-.079-.558-.307-.467zm.662.262c.022-.217.308-.422.58-.422.273 0 .445.102.445.102s-.012.103-.217.114c-.205.012-.217.41-.559.434-.341.023-.249-.228-.249-.228zm2.038 3.931s.126-.126.32-.136c.192-.012.375.182.49.33.112.148.17.353.17.353s-.159 0-.217-.091c-.057-.091-.502-.022-.718-.182 0 0-.091.103-.204.171-.115.068-.319.011-.399.16-.079.148-.216.25-.216.25s-.046-.456.158-.684c.206-.228.297-.251.434-.228.137.023.182.057.182.057z"/></g><path fill="#207900" d="M12.747 13.592s.205.137.102.558c-.102.421-.228.945-.148 1.299 0 0-.285-.342-.251-.684.035-.342.285-.581.205-.843-.079-.262.092-.33.092-.33z"/><path fill="#103800" d="M12.733 15.514l-.045-.055c-.012-.014-.289-.351-.255-.696.015-.151.073-.284.124-.402.067-.157.126-.292.083-.435-.083-.273.099-.35.101-.351l.008-.003.007.005c.009.006.214.148.11.576-.096.396-.228.938-.148 1.291l.015.07zm.012-1.902c-.032.018-.137.093-.073.305.047.155-.016.302-.083.458-.052.121-.106.246-.121.392-.024.249.127.502.204.613-.052-.359.07-.861.161-1.234.086-.357-.054-.504-.088-.534z"/><path fill="#207900" d="M12.234 14.401c.068.319.148.866.114 1.151-.034.285-.319.512-.319.512s.171-.364.125-.797c-.039-.374.08-.866.08-.866z"/><path fill="#103800" d="M11.982 16.123l.031-.066c.002-.003.168-.365.124-.788-.04-.373.079-.867.08-.872l.018-.073.016.073c.065.303.149.862.115 1.156-.035.289-.314.514-.326.523l-.058.047zm.251-1.64c-.031.154-.092.503-.062.781.034.322-.052.609-.099.737.083-.081.235-.253.259-.452.032-.266-.036-.754-.098-1.066z"/><path fill="#DE200F" d="M11.14 16.907s-.151.226-.148.388c.002.162.159.262.25.262.376 0 .319-.433.194-.616 0 0 .126-.102.17-.308.046-.205-.136-.364-.136-.364s.216 0 .285-.228c.068-.228-.046-.456-.046-.456s.205-.034.296-.274c.091-.239-.011-.421-.011-.421s.183-.011.308-.217c.125-.205.068-.398.068-.398s.137.023.296-.183c.16-.205.114-.399.114-.399s.16-.011.308-.148c.148-.137.16-.387.16-.387s.148.011.319-.137c.171-.149.16-.296.16-.296s.183.057.387-.08c.205-.137.205-.354.205-.354s.137.08.387-.056c.251-.137.239-.32.239-.32s.148.103.398-.034c.251-.137.262-.262.262-.262s.114.091.342.011c.228-.08.308-.262.308-.262s.08.171.353.103c.274-.068.354-.285.354-.285s.114.194.331.194c.216 0 .399-.16.399-.16s.091.137.308.137c.216 0 .376-.137.376-.137s.068.092.341.114c.274.023.377-.057.377-.057s.101.171.273.216c.17.046.387-.034.387-.034s.057.171.263.251c.204.08.41 0 .41 0s-.012.193.228.273c.239.08.41 0 .41 0s.067.206.284.308c.217.103.377.08.377.08s.012.171.192.296c.183.125.377.114.377.114s0 .206.171.342c.171.137.354.171.354.171s-.08.194.046.342c.125.148.363.25.363.25s-.034.194.069.354c.103.16.308.239.308.239s.012.137.067.308c.058.171.331.273.331.273s-.103.183-.057.354.273.318.273.318-.08.092-.058.274c.023.182.217.376.217.376s-.045.102-.058.376c-.011.273.16.376.16.376s-.113.125-.125.33c-.011.206.171.399.342.387.172-.011.25-.125.229-.33-.023-.205-.195-.411-.195-.411s.149-.159.139-.353c-.014-.194-.263-.433-.263-.433s.102-.057.091-.318c-.012-.262-.239-.353-.239-.353s.079-.068.022-.342c-.057-.273-.262-.341-.262-.341s.057-.148-.034-.377c-.091-.227-.331-.285-.331-.285s0-.183-.079-.387c-.08-.206-.319-.194-.319-.194s.034-.274-.137-.433c-.171-.159-.376-.171-.376-.171s.067-.182-.137-.376c-.205-.194-.388-.114-.388-.114s0-.262-.229-.421c-.227-.16-.364-.091-.364-.091s-.011-.16-.228-.273c-.217-.114-.409-.08-.409-.08s-.012-.193-.251-.285c-.24-.09-.434-.023-.434-.023s0-.17-.262-.262c-.263-.091-.423-.022-.423-.022s-.067-.125-.273-.205c-.205-.08-.444.046-.444.046s-.16-.171-.388-.194c-.228-.023-.364.091-.364.091s-.069-.114-.331-.137c-.262-.022-.376.125-.376.125s-.045-.08-.285-.102c-.239-.023-.432.228-.432.228s-.206-.16-.422-.126-.342.216-.342.216-.125-.091-.365-.034c-.24.058-.341.239-.341.239s-.103-.057-.331.034c-.228.091-.285.331-.285.331s-.148-.103-.421.056c-.273.16-.262.296-.262.296s-.114-.045-.342.08c-.228.125-.194.387-.194.387s-.182-.08-.41.091c-.228.171-.16.376-.16.376s-.273-.012-.399.183c-.125.193-.103.41-.103.41s-.239.023-.353.205c-.114.182-.046.399-.046.399s-.216 0-.33.216c-.114.217-.045.41-.045.41s-.216.057-.297.296c-.079.239.012.399.012.399s-.251.068-.307.296c-.057.228.045.421.045.421s-.148.091-.193.319c-.043.231.105.379.105.379z"/><path fill="#FFE301" d="M11.14 17.17s.117.096.251 0c0 0 .091.325-.148.285-.208-.036-.103-.285-.103-.285zm.068-.621s.051.048.128.054c.077.006.142-.023.142-.023s.006.086-.028.166c-.034.08-.088.168-.19.134-.103-.034-.094-.168-.083-.225.012-.058.031-.106.031-.106zm.18-.738s.068.057.134.063c.065.005.145-.012.145-.012s-.008.094-.049.177c-.04.082-.114.136-.196.117-.083-.02-.083-.131-.08-.197.003-.065.046-.148.046-.148zm.26-.692s.045.059.105.077c.06.017.151.02.151.02s-.023.108-.06.163c-.037.054-.117.125-.194.091s-.085-.128-.068-.21c.017-.085.066-.141.066-.141zm.338-.664s.042.069.114.088c.071.019.148.019.148.019s-.031.083-.077.149c-.046.066-.129.103-.214.071-.069-.025-.074-.134-.051-.199.023-.066.08-.128.08-.128zm.408-.632s.031.069.085.105c.068.045.148.051.148.051s-.094.12-.137.154c-.042.035-.168.094-.231-.011-.048-.081 0-.165.031-.205.032-.04.104-.094.104-.094zm.441-.601s.022.083.082.119c.06.038.146.051.146.051s-.093.231-.26.206c-.168-.026-.125-.18-.091-.24.035-.06.123-.136.123-.136zm.524-.502s.04.087.077.117c.049.04.129.071.129.071s-.102.142-.22.163c-.114.02-.191-.06-.185-.148.007-.114.199-.203.199-.203zm.578-.473s.021.086.066.125c.046.04.133.085.133.085s-.108.151-.236.151-.168-.054-.168-.125c0-.071.049-.14.086-.165.036-.026.119-.071.119-.071zm.63-.412s.008.096.054.157c.032.041.123.082.123.082s-.106.13-.236.13c-.131 0-.171-.065-.171-.143 0-.077.06-.136.103-.167.041-.031.127-.059.127-.059zm.664-.329s-.005.103.026.151.117.105.117.105-.105.074-.191.086c-.084.011-.159-.003-.184-.1-.025-.097.043-.162.083-.188.038-.025.149-.054.149-.054zm.672-.298s-.003.094.043.176c.03.054.085.106.085.106s-.082.077-.225.068c-.139-.008-.164-.122-.142-.2.034-.122.239-.15.239-.15zm.746-.183s-.031.117-.003.185c.029.068.085.111.085.111s-.102.057-.217.057c-.113 0-.194-.079-.17-.194.034-.164.305-.159.305-.159zm.726-.065s-.022.083-.02.131c.005.103.062.157.062.157s-.099.052-.216.023c-.117-.029-.157-.065-.154-.163.003-.096.1-.14.168-.153.069-.015.16.005.16.005zm.436.125c-.005-.06.088-.156.276-.154-.003.005-.014.105.003.157.017.051-.279-.003-.279-.003zm.724-.017c.048-.105.265-.111.342-.068 0 0-.061.122-.031.188.028.065-.311-.12-.311-.12zm1.082.071s-.08.057-.091.122c-.012.065.022.163.022.163s-.113-.009-.197-.041c-.082-.031-.137-.116-.116-.21.017-.077.105-.103.186-.106.079-.002.196.072.196.072zm.693.242s-.046.017-.073.102c-.029.086-.007.168-.007.168-.086-.017-.15-.04-.223-.1-.068-.058-.076-.123-.042-.197.034-.073.119-.071.194-.06.073.013.151.087.151.087zm.327.225c.045-.08.231-.042.285 0 .054.043.068.08.068.08s-.062.014-.092.08c-.028.066-.008.16-.008.16s-.085-.024-.16-.072c-.074-.048-.156-.133-.093-.248zm.649.356c.048-.102.18-.083.245-.04.065.043.107.105.107.105s-.067.02-.099.08c-.031.06-.034.165-.034.165s-.1-.031-.168-.094c-.067-.062-.085-.141-.051-.216zm.621.368c.06-.074.149-.057.214-.006.065.051.107.149.107.149s-.067.017-.104.062c-.037.045-.037.136-.037.136s-.085-.025-.154-.105c-.068-.079-.071-.18-.026-.236zm.546.473c.067-.076.17-.042.221.008.051.052.103.174.103.174s-.094.006-.128.045c-.034.04-.057.137-.057.137s-.058-.034-.115-.12c-.057-.085-.077-.181-.024-.244zm.527.518c.075-.071.198-.003.231.04.048.062.062.154.062.154s-.065.011-.106.04c-.039.029-.079.123-.079.123s-.066-.034-.109-.111c-.041-.078-.066-.18.001-.246zm.556.621c.157-.006.24.188.24.188s-.159-.003-.215.125c-.054.128-.067-.173-.067-.211 0-.036.042-.102.042-.102zm.262.587c.094-.075.192-.02.229.04.037.06.071.186.071.186s-.097.008-.156.042c-.06.034-.108.106-.108.106s-.049-.062-.086-.171c-.037-.109.008-.17.05-.203zm.334.649c.093-.056.171.023.211.069.04.045.066.168.066.168s-.104.002-.149.031c-.045.028-.104.119-.104.119s-.055-.094-.078-.171c-.023-.076-.012-.176.054-.216zm.268.653c.1-.042.178.054.191.126.011.071.019.177.019.177s-.048-.023-.134 0c-.089.024-.125.065-.125.065s-.046-.08-.058-.168c-.01-.09.008-.158.107-.2zm.16.732c.139-.035.185.077.188.17.002.097-.003.143-.003.143s-.062-.02-.135 0c-.071.02-.113.08-.113.08s-.04-.092-.055-.18c-.013-.088.012-.187.118-.213zm.05.709c.101-.026.198.074.203.154.006.079.003.17.003.17s-.068-.025-.131-.014c-.062.012-.142.078-.142.078s-.026-.083-.037-.163c-.011-.079-.005-.197.104-.225z"/><path fill="#FFB636" d="M22.876 13.569c.265-.076.273.205.331.33.056.125-.069.513-.195.649 0 0-.079-.045-.056-.182.021-.137-.263-.421-.274-.547-.012-.125.114-.227.194-.25z"/><path fill="#207900" d="M19.07 12.327s.319-.09.319-.592-.718-.82-1.094-.627l.125.274s-.012-.023.205-.023.463.164.514.399c.068.318-.069.569-.069.569z"/><path fill="#103800" d="M19.036 12.354l.02-.036c.001-.002.133-.25.067-.558-.052-.238-.298-.385-.497-.385-.165 0-.19.014-.192.015.003-.002.006-.009.003-.017l-.031.015-.004-.009-.129-.279.015-.007c.201-.105.508-.069.762.085.227.139.357.342.357.557 0 .509-.329.608-.332.609l-.039.01zm-.41-1.013c.212 0 .476.158.53.413.053.25-.016.456-.052.54.083-.042.268-.177.268-.56 0-.203-.124-.395-.34-.527-.234-.143-.524-.178-.714-.092l.11.241c.024-.008.077-.015.198-.015z"/><path fill="#207900" d="M17.623 11.21s.251-.228.559-.228c.308 0 .524.354.524.593s-.08.775-.604.775c0 0 .296-.205.296-.604 0-.398-.24-.581-.388-.581-.148 0-.387.045-.387.045z"/><path fill="#103800" d="M18.102 12.367h-.055l.045-.031c.003-.002.289-.205.289-.59 0-.398-.241-.563-.371-.563-.145 0-.382.044-.384.045l-.06.012.044-.041c.011-.009.26-.232.57-.232.326 0 .542.367.542.61.001.131-.029.79-.62.79zm-.091-1.219c.17 0 .405.208.405.598 0 .313-.181.512-.264.585.51-.036.537-.633.537-.756 0-.232-.213-.576-.507-.576-.217 0-.407.118-.495.183.082-.014.222-.034.324-.034z"/><path fill="#207900" d="M23.617 13.729s-.104.41.034.729c.137.319.397 1.196-.126 1.526 0 0 .068-.41.058-.74-.012-.33-.217-.684-.229-.98-.01-.296.263-.535.263-.535z"/><path fill="#103800" d="M23.502 16.019l.007-.038c0-.004.067-.412.058-.737-.007-.168-.063-.344-.119-.514-.054-.165-.104-.321-.109-.467-.012-.3.257-.539.268-.548l.042-.036-.014.053c-.001.004-.101.408.033.718.184.428.362 1.236-.133 1.548l-.033.021zm.087-2.238c-.074.079-.226.267-.218.482.006.141.056.294.109.457.056.172.113.351.119.523.009.269-.035.594-.052.705.547-.394.107-1.438.088-1.483-.109-.255-.07-.56-.046-.684z"/><path fill="#207900" d="M24.118 14.833s-.026.35-.012.627c.024.433.718 1.003.502 1.641 0 0-.104-.376-.239-.638-.138-.262-.422-.775-.41-1.048.011-.274.159-.582.159-.582z"/><path fill="#103800" d="M24.606 17.16l-.015-.054c-.001-.003-.104-.377-.238-.635l-.033-.063c-.146-.275-.39-.737-.378-.994.011-.274.154-.575.16-.588l.039-.082-.007.09c0 .003-.025.352-.012.625.009.162.117.349.232.547.189.328.404.7.27 1.1l-.018.054zm-.511-2.23c-.044.111-.111.307-.119.485-.01.248.231.704.375.977l.033.063c.104.201.19.47.225.585.095-.366-.105-.711-.283-1.017-.116-.202-.227-.393-.235-.562-.012-.186-.003-.406.004-.531z"/><path fill="#207900" d="M24.778 18.035s.388.501.365.89c-.023.388-.273.818-.16 1.15 0 0-.251-.309-.159-.844.092-.535-.046-1.196-.046-1.196z"/><path fill="#103800" d="M25.03 20.159l-.061-.073c-.01-.013-.255-.32-.162-.857.09-.526-.045-1.183-.046-1.19l-.016-.073.046.059c.016.021.392.511.368.901-.009.153-.053.314-.096.471-.067.245-.132.477-.064.673l.031.089zm-.221-2.052c.033.189.105.701.032 1.127-.062.361.036.619.103.745-.025-.182.03-.382.088-.593.043-.153.087-.312.096-.463.016-.298-.219-.672-.319-.816z"/><path fill="#207900" d="M24.722 17.979s.269.466.262.764c-.011.488-.307 1.012-.41 1.332-.103.319-.147.889-.147.889s-.114-.354-.091-.662c.022-.307.319-.967.376-1.469.055-.502.01-.854.01-.854z"/><path fill="#103800" d="M24.437 21.051l-.027-.082c-.001-.003-.114-.36-.091-.668.01-.144.077-.356.155-.603.089-.28.19-.598.221-.867.055-.493.011-.846.011-.85l-.011-.084.042.073c.012.02.272.474.264.773-.007.353-.162.723-.287 1.021-.049.116-.094.226-.123.315-.102.314-.146.88-.147.885l-.007.087zm.309-2.99c.01.134.021.418-.019.774-.03.272-.132.592-.221.873-.078.245-.145.456-.155.595-.016.21.034.444.065.567.018-.175.062-.56.14-.8.03-.092.076-.202.125-.318.123-.296.277-.663.284-1.009.007-.221-.145-.54-.219-.682z"/><path fill="#207900" d="M10.935 18.126s0 .558.023.787c.023.227.513.981.581 1.354.068.377-.217.776-.217.776s.034-.434 0-.661c-.034-.228-.558-1.024-.547-1.435.012-.41.16-.821.16-.821z"/><path fill="#103800" d="M11.3 21.104l.005-.062c0-.005.034-.435 0-.657-.012-.084-.095-.251-.191-.445-.162-.327-.363-.733-.356-.994.011-.409.159-.822.16-.826l.033-.092v.098c0 .005 0 .56.023.785.01.103.124.326.244.562.141.276.3.589.336.791.068.38-.208.772-.219.789l-.035.051zm-.382-2.87c-.044.146-.118.432-.125.714-.007.251.192.654.352.977.097.197.181.366.195.455.026.176.013.468.004.599.073-.122.229-.424.179-.708-.036-.197-.194-.508-.333-.781-.127-.25-.237-.466-.248-.575-.018-.166-.023-.507-.024-.681z"/><path fill="#207900" d="M11.003 20.701s.171-.148.16-.386c-.012-.24-.137-.595-.251-.89-.114-.298-.159-.753-.103-.912.058-.16.125-.388.125-.388s-.307.342-.341.662c-.035.318.039.812.216 1.139.229.423.194.775.194.775z"/><path fill="#103800" d="M10.982 20.742l.004-.043c0-.003.031-.353-.192-.765-.185-.343-.25-.848-.218-1.148.035-.321.333-.657.346-.671l.051-.057-.021.073c-.001.002-.069.23-.126.389-.052.147-.015.591.103.9.111.288.24.649.252.895.012.244-.158.394-.166.399l-.033.028zm-.089-2.538c-.089.114-.258.358-.283.586-.032.296.032.792.214 1.129.181.334.199.629.198.738.047-.054.132-.176.124-.341-.012-.24-.14-.599-.25-.885-.11-.289-.163-.755-.103-.923.036-.098.075-.223.1-.304z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..f7053092c3a85f48522d9994e64a96887c75cc5a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#21428E" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M16 5h4v26h-4z"/><path fill="#EEE" d="M0 16h36v4H0z"/><path fill="#FFF" d="M11.438 13.25c-.375-.667-3.688-.938-4.896-.333 1.084-.938 4.333-.25 4.438-1.792.082-1.228-2.23-1.125-3.126-1.354-.895-.229-.104-.479.584-.771s1.438-.562 1.271-1.555c-.167-.993-1.855-.924-2.626-.966-.771-.041-1.75.25-1.521.729-.604.25-1.312.208-1.729 0-.005.167.26.229.26.229l-.447.105c.521.25 1.604.125 2.062-.104.083.104.375.167 1.5.104s1.25-.271 1.521-.021c.455.419-.5.583-1.708 1.021-1.208.438-.688 1.5-.042 1.833.646.333 1.292.304 2.375.48 1.084.176.312.395-.312.437-.23.016-2.063.083-3.042.604-1.144.608-.917 1.375-1.021 1.5-.104.125-1.104.083-1.875-.146.271.75 1.563.75 2.021.771S6 15.125 8.771 15.083s3.041-1.166 2.667-1.833zM6.766 6.969c-.125.125-.235.078-.11-.078s.235-.047.11.078zm-.111 6.654c.27-.311 4.001-.453 3.798.058-.261.656-4.125.318-3.798-.058zm25.616-.373c-.375-.667-3.688-.938-4.896-.333 1.084-.938 4.333-.25 4.438-1.792.083-1.228-2.229-1.125-3.125-1.354-.896-.229-.105-.479.583-.771s1.438-.562 1.271-1.555c-.166-.993-1.854-.924-2.625-.965-.771-.041-1.75.25-1.521.729-.604.25-1.312.208-1.729 0-.005.167.261.229.261.229l-.448.104c.521.25 1.604.125 2.062-.104.084.104.375.167 1.5.104s1.25-.271 1.521-.021c.455.419-.5.583-1.709 1.021-1.208.438-.688 1.5-.041 1.833s1.291.304 2.375.48.312.395-.312.437c-.229.016-2.062.083-3.042.604-1.143.608-.917 1.375-1.021 1.5s-1.104.083-1.875-.146c.271.75 1.562.75 2.02.771s.875 1.104 3.646 1.062c2.771-.041 3.042-1.166 2.667-1.833zm-4.672-6.281c-.125.125-.234.078-.109-.078s.234-.047.109.078zm-.111 6.654c.269-.311 4.001-.453 3.798.058-.261.656-4.125.318-3.798-.058zm-16.05 14.169c-.375-.667-3.688-.938-4.896-.333 1.084-.938 4.333-.25 4.438-1.792.083-1.227-2.229-1.125-3.125-1.354-.896-.229-.104-.479.583-.771s1.438-.562 1.271-1.556c-.167-.992-1.854-.924-2.625-.965-.771-.041-1.75.25-1.521.729-.604.25-1.312.209-1.729 0-.005.167.26.229.26.229l-.448.104c.521.25 1.604.125 2.062-.104.083.104.375.167 1.5.104s1.25-.271 1.521-.021c.455.42-.5.584-1.708 1.021-1.208.438-.688 1.5-.042 1.833.646.333 1.292.304 2.375.479 1.084.176.312.396-.312.438-.23.017-2.063.084-3.042.605-1.144.609-.917 1.375-1.021 1.5-.104.125-1.104.084-1.875-.146.271.75 1.562.75 2.021.771.458.021.875 1.104 3.646 1.062 2.771-.041 3.041-1.166 2.667-1.833zm-4.672-6.281c-.125.125-.234.078-.109-.078.124-.157.234-.047.109.078zm-.111 6.653c.27-.311 4.001-.453 3.798.059-.261.656-4.125.318-3.798-.059zm25.616-.372c-.375-.667-3.688-.938-4.896-.333 1.084-.938 4.333-.25 4.438-1.792.083-1.227-2.229-1.125-3.125-1.354-.896-.229-.104-.479.583-.771s1.438-.562 1.271-1.556c-.166-.992-1.854-.924-2.625-.965-.771-.041-1.75.25-1.521.729-.604.25-1.312.209-1.729 0-.005.167.261.229.261.229l-.448.104c.521.25 1.604.125 2.062-.104.084.104.375.167 1.5.104s1.25-.271 1.521-.021c.455.42-.5.584-1.709 1.021-1.208.438-.688 1.5-.041 1.833s1.291.304 2.375.479.312.396-.312.438c-.229.016-2.062.083-3.042.604-1.143.609-.917 1.375-1.021 1.5s-1.104.084-1.875-.146c.271.75 1.562.75 2.021.771.458.021.875 1.104 3.646 1.062 2.77-.04 3.041-1.165 2.666-1.832zm-4.672-6.281c-.125.125-.234.078-.109-.078.124-.157.234-.047.109.078zm-.111 6.653c.269-.311 4.001-.453 3.798.059-.261.656-4.125.318-3.798-.059z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..8335c8b5cb476584b2198cce31dbc0e44874eb9a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE2540" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#0F6433" d="M0 9v18h36V9z"/><path fill="#FFC514" d="M14.936 12.664l1.894 1.375-.722 2.221-.002.005.007-.005L18 14.889l1.887 1.371.006.005-.001-.005-.722-2.221 1.894-1.375h-2.341L18 10.437l-.723 2.227z"/><path fill="#FFC514" d="M26.1 13.641c-.019 4.458-3.638 8.067-8.1 8.067s-8.081-3.609-8.1-8.067c-.186.694-.294 1.42-.294 2.173 0 4.636 3.758 8.395 8.395 8.395s8.395-3.758 8.395-8.395c-.001-.753-.11-1.479-.296-2.173z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..04a1cc1e5c3bd0809decae83b51bed0e422843a3 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#55ACEE" d="M32.962 12.498h-9.936v7.52l4.968 2 4.968-2z"/><path fill="#9F1D22" d="M23.026 20.018c.006.082.004.17.013.25.142 1.225.65 2.131 1.477 2.869 1.431 1.278 3.478 1.559 3.478 1.863 0-.305 2.047-.585 3.477-1.863.827-.738 1.337-1.645 1.477-2.869.009-.08.008-.168.013-.25h-9.935z"/><path d="M28.342 14.753h1.893v-.628h-1.893v-.843h-.663v.843h-1.927v.628h1.927v7.954h.663z"/><path fill="#77B253" d="M28.342 15.689c.114-.099.175-.158.244-.148.071.011.166.006.236-.016.07-.022.421-.065.564-.017.048.006.113.032.213.117.102.084.248.231.198.637-.05.406-.033.58-.054.807-.037.4-.128.732-.287.705.217.378.237.704.378.964.141.259.23.791.174 1.365-.055.574-.206 1.863.249 2.73-.076.054-.26 0-.423-.174-.161-.174-.233-.167-.368-.065-.41.312-.796.693-1.365.312-.13-.086-.17-.189-.076-.454.239-.661.354-1.566.316-1.992v-4.771z"/><path fill="#FAAA34" d="M26.022 20.594c.347.357 1.43 1.503 1.569 1.633.141.13.207.12.262-.01.392-.943.293-2.145-.678-3.327-.157.581-.562.958-1.196 1.094-.323.069-.379.277-.32.357.088-.156.282-.162.375.017.074.147-.024.331-.186.38-.162.048-.401.043-.498-.126-.098-.167-.178-.558.271-.751.45-.196.933-.396 1.023-.798.093-.4.217-.595.488-.622 1.5 1.381 1.69 2.926 1.066 4.306-.151.335-.39.423-.553.218-.162-.207-1.297-1.549-1.882-2.21.135-.009.224-.084.259-.161z"/><path fill="#F6DDCD" d="M28.733 15.282c.03.093.046.212-.003.319-.05.109-.06.239.022.396.131-.184.314-.147.422-.255.109-.108.131-.211.213-.233-.082-.07-.207-.146-.18-.352.027-.206.314-.374.054-.688-.167-.203-.411-.146-.517-.068-.05.037-.092.089-.109.125-.015.035.005.115-.035.163-.026.033-.059.065-.097.092-.024.017-.04.043-.014.073.01.012.029.015.05.022-.011.025-.025.049-.039.067-.013.016-.008.032.009.045-.021.065.019.073-.009.121-.022.042-.055.092.032.141.025.014.141.04.201.032zm-1.054 1.079c-.15.038-.393-.027-.58-.005-.08.009-.145-.033-.135-.113.011-.082.022-.207.006-.321-.024-.177.06-.422.179-.693.12-.271.18-.422.18-.549 0-.085.007-.179.083-.228.057-.036.067-.071.088-.1.045-.068.089-.084.093-.044.005.025-.004.047-.025.08.049-.04.13-.088.151-.102.018-.013.113-.081.118-.017.039-.019.066-.018.073.002.011.023.004.032-.014.048.026-.006.059.042.005.084.027-.01.056.037.006.081-.052.045-.112.076-.132.112-.018.035-.147.133-.198.155-.05.022-.053.051-.053.127 0 .834-.101.767-.101.967 0 .054-.011.103.043.086.056-.016.134-.041.214-.041v.471zm.034 1.798c.245-.124.524-.168.671-.207.146-.037.38-.151.493-.211.113-.059.205-.14.27-.162.065-.021.139-.066.179-.147.212-.411.325-.742.325-1.028 0-.19-.05-.4-.233-.25-.172.143-.36.418-.411.618-.077.304-.14.368-.157.429-.016.059-.077.059-.152.075-.318.071-.395.12-.633.298-.239.179-.498.336-.673.433-.173.097-.204.108-.243.187-.038.079-.072.138-.105.174-.033.035-.043.076-.035.119.006.035-.01.197-.014.252-.002.054.011.068.033.07.021.002.051-.008.062-.073-.012.066.079.043.084-.005-.003.07.092.029.098-.036 0 .045.071.014.077-.008.017-.055.031-.114.052-.157.031-.063.066-.145.128-.19.07-.051.037-.108.184-.181zm1.754 4.437c.018.059.046.127.058.166.012.041-.009.054-.02.078-.057.117-.117.307-.126.41-.007.06-.047.118-.066.151-.021.038-.014.07.035.107.023.017.098-.006.105-.043.028.026.077.015.098-.026.024.026.065.008.092-.032.025.017.061-.015.074-.038.037.02.078-.004.079-.078 0-.014.01-.041.021-.057.009-.018.014-.053.013-.083-.001-.03.018-.089.044-.132.025-.041.07-.115.05-.186-.016-.066-.046-.061-.069-.155-.06-.063-.141-.149-.225-.153-.085-.005-.134.05-.163.071zm-1.54.464c.075.076.245.079.366-.049-.044-.019-.14-.062-.183-.098-.059.061-.128.129-.183.147z"/><path fill="#955C0F" d="M28.693 14.449c.029-.193.165-.188.252-.168.035.008.121.016.202-.006.16-.043.282.014.267.168.043.032.088.108.08.173-.007.065.006.092.064.101.06.008.188.081.104.184.082.049.144.173.101.257-.043.083-.175.097-.227.021-.061.027-.157.032-.218-.03-.041.048-.145.043-.164 0-.018-.044-.049-.066-.088-.079-.043-.014-.047-.133.019-.146-.01-.035-.006-.076.011-.094.015-.02.003-.055-.036-.084-.037-.03-.07-.144-.033-.206-.063.022-.208-.04-.238-.084-.027-.042-.068-.045-.096-.007z"/><path d="M29.638 15.237c-.043 0-.081-.018-.104-.048-.063.027-.154.028-.215-.028-.022.022-.057.031-.088.031l-.02-.001c-.031-.004-.055-.018-.063-.038-.016-.038-.042-.062-.083-.074-.027-.009-.038-.048-.037-.08.002-.032.016-.068.05-.079-.009-.037-.003-.075.014-.094.011-.014.003-.045-.035-.073-.037-.03-.068-.135-.042-.201l-.018.001c-.074 0-.186-.052-.213-.091-.013-.02-.028-.031-.044-.031h-.001c-.015 0-.028.008-.039.023l-.014-.005c.012-.073.039-.125.082-.155.045-.031.103-.037.18-.02.034.007.12.015.198-.006.095-.025.177-.016.227.026.038.032.056.083.05.146.045.035.088.112.08.177-.007.064.006.085.058.092.041.005.11.039.132.092.009.022.012.056-.019.097.082.053.141.176.097.263-.022.042-.068.071-.121.075l-.012.001zm-.099-.067l.003.005c.022.031.063.05.105.046.047-.003.089-.028.108-.066.041-.081-.02-.201-.098-.248l-.008-.004.006-.007c.025-.031.032-.061.021-.089-.019-.046-.082-.078-.12-.083-.068-.009-.077-.047-.071-.109.008-.06-.033-.134-.077-.166l-.003-.002v-.004c.007-.06-.009-.107-.044-.137-.045-.038-.124-.046-.213-.023-.081.022-.17.014-.206.006-.074-.017-.127-.011-.167.017-.035.024-.059.064-.071.121.01-.007.021-.011.032-.011h.002c.021 0 .041.014.056.038.024.035.134.085.201.085.011 0 .021-.001.029-.004l.019-.006-.01.018c-.035.057-.005.167.031.196.02.015.033.032.04.049.007.018.006.034-.003.045-.015.017-.019.054-.01.088l.003.008-.008.001c-.031.006-.044.039-.045.067-.002.032.009.06.025.065.046.014.076.042.093.083.007.014.025.025.052.028.031.005.076-.002.1-.03l.006-.006.005.006c.057.057.146.055.21.028l.007-.005zm-.805.12l-.002-.015c.051-.007.085-.025.115-.042s.059-.032.097-.032h.009v.015c-.039-.002-.065.012-.098.03-.032.018-.067.037-.121.044zm-.149 2.018l-.01-.011c.171-.157.108-.495.062-.742l-.003-.015c-.037-.213 0-.397.111-.547l.012.009c-.108.146-.145.327-.107.535l.002.015c.047.251.111.594-.067.756zm.268.575c-.06 0-.119-.012-.168-.037l.006-.014c.11.055.27.045.362-.021.096-.07.272-.072.406-.043l-.004.015c-.123-.026-.301-.026-.395.041-.054.039-.13.059-.207.059z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..553810216b9a4732454d46c6cc9820fb8b044f03 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CF142B" d="M32 5H18v26h14c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h14V5H4z"/><path fill="#CF142B" d="M1.654 9.656h8.691v2.688H1.654z"/><path fill="#CF142B" d="M4.656 6.654h2.688v8.691H4.656z"/><g fill="#CF142B"><circle cx="4.71" cy="12.271" r=".921"/><circle cx="7.355" cy="12.271" r=".921"/><circle cx="4.71" cy="9.824" r=".921"/><circle cx="7.355" cy="9.824" r=".921"/></g><g fill="#99AAB5"><circle cx="4.708" cy="12.271" r=".708"/><circle cx="7.355" cy="12.271" r=".708"/><circle cx="4.708" cy="9.824" r=".708"/><circle cx="7.355" cy="9.824" r=".708"/></g><circle fill="#CCD6DD" cx="6.032" cy="11.032" r="1.817"/><path fill="#CCD6DD" d="M5 7h2v8H5z"/><path fill="#CCD6DD" d="M2 10h8v2H2z"/><circle fill="#B2C0C9" cx="6.032" cy="11.083" r="1.204"/><path fill="#99AAB5" d="M6.647 11.023c.015-.017.032-.032.048-.047l.009-.007c.042.021.083.047.123.072.08.049.334-.066.219-.137-.099-.061-.198-.132-.32-.111-.091.016-.169.063-.238.122-.008-.062-.015-.123-.029-.184.019-.02.03-.042.025-.069-.011-.058.021-.122.041-.175.01-.026-.004-.044-.025-.055.009-.012.016-.024.024-.037.035.012.071.023.108.031.063.013.146-.013.195-.052.046-.036.031-.073-.022-.083-.094-.019-.181-.067-.269-.105-.058-.025-.143.001-.194.029-.033.018-.084.066-.031.092-.006.006-.013.22-.016.227-.044.095-.118-.534-.169.466h-.018c-.017 0-.141-.345-.134-.414.074-.015.026-.264.026-.315v-.029c0-.015.113-.025.105-.033.03-.019.117-.045.09-.067-.042-.035-.1-.011-.146.007-.014-.007-.014-.012-.028-.014-.01-.002-.013 0-.023 0 .054-.022.1-.058.086-.099-.008-.025-.014-.045 0-.07.067-.116-.21-.09-.257-.009-.029.051-.035.097-.017.153.012.038.061.051.113.046-.028.015-.053.037-.068.065l-.003.009c-.042 0-.09.013-.119.025-.161.069-.331.119-.482.209-.025.015-.094.063-.031.083.038.012.087.006.131-.007.002.007.002.013.006.019.039.051.096.098.154.126.061.03.142.013.196-.023.036-.023.075-.081.03-.112.017-.025.043-.043.068-.061.003.064.011.127.027.184.004.016.013.028.023.038-.033.006-.065.019-.09.034-.033.02-.072.065-.042.096-.07.013-.139.031-.205.062-.025.011-.08.043-.085.078l-.096.012c-.051.008-.135.032-.153.09-.024.001-.052.006-.072.011-.059.008-.17.034-.175.086-.008.092.038.167.078.245-.037.036-.063.078-.074.132-.024.119.256.077.277-.029.003-.016.005-.032.019-.042.035-.025.07-.074.039-.108.012-.01.02-.018.016-.025-.035-.068-.072-.134-.077-.21.015.006.031.009.047.01.019.102.097.192.171.26.018.016.051.018.087.013-.015.012-.028.025-.034.042-.034.085-.048.173-.059.263-.004.037.024.073.06.082.116.027.209.082.303.154.097.074.339-.062.213-.159-.088-.067-.183-.123-.288-.159.007-.051.016-.102.035-.15.007-.018.009-.034.007-.047.023-.009.045-.019.065-.031.178-.108.396-.131.587-.218-.008.028.009.055.049.064.082.019.231.018.258.112.027.095-.005.209.056.293.056.078.323-.016.256-.109-.023-.032-.019-.095-.021-.133-.003-.059-.006-.121-.034-.175-.057-.108-.242-.116-.346-.141-.036-.008-.076-.055-.114-.043.003-.007-.003-.071-.021-.071h-.006c.001 0 .001.048.002.047.061-.004.12.023.159-.024z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c249812644f608636080f9da3ffcff0ffe166d9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA2839" d="M32 5H4C1.791 5 0 6.791 0 9v2.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#1A206D" d="M0 11.5h36V18H0z"/><path fill="#FFD500" d="M0 18h36v6.5H0z"/><path fill="#00A551" d="M0 24.5V27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-2.5H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..b57be9c6fba9d5c059e2b98b0c9de722ff501373 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D21034" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#007E3A" d="M6 11h24v14H6z"/><path fill="#FFF" d="M19.64 22.344c.279 0 .551-.027.814-.077-2.009-.381-3.529-2.146-3.529-4.266s1.52-3.885 3.529-4.266c-.264-.05-.536-.077-.814-.077-2.399 0-4.344 1.945-4.344 4.344 0 2.397 1.945 4.342 4.344 4.342z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b8ddf52c7d61239646b2bc0c2333f7b46795010 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#DD2E44" d="M0 13h36v10H0z"/><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path d="M23.191 12C22.153 10.208 20.22 9 18 9c-2.22 0-4.153 1.208-5.191 3h10.382zm-5.493-6h.603L18 8.163zm-1.514.18l.594-.102.068 2.183zm-1.463.433l.569-.201.435 2.14zm-1.368.673l.527-.293.79 2.036zm-1.235.895l.47-.378 1.122 1.873zm-1.067 1.09l.401-.452 1.421 1.658zm-.866 1.255l.317-.513 1.681 1.393zM10.898 12l-1.13-.65-.226.559.364.091zm15.355 0l.218-.054-.221-.557-1.074.611zm-.731-1.951l.312.512-2.001.872zm-.943-1.198l.394.451-1.826 1.198zm-1.132-1.023l.464.38-1.596 1.487zm-1.288-.816l.521.296-1.323 1.735zm-1.408-.588l.564.204-1.011 1.934zm-1.487-.341l.59.106-.67 2.077z" fill="#DD2E44"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fd.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fd.svg new file mode 100644 index 0000000000000000000000000000000000000000..93d54c46f03f8cee4b61302a201edbf31d79dba4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006847" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h7V5H4z"/><path fill="#CE1126" d="M32 5h-7v26h7c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M11 5h14v26H11z"/><path fill="#A6D388" d="M23 18c0 2.762-2.238 5-5 5-2.761 0-5-2.238-5-5h-1c0 3.313 2.686 6 6 6s6-2.687 6-6h-1z"/><path d="M13.543 20.269c-.092-.18-.278-.28-.468-.271-.069.002-.14.02-.205.053-.247.125-.344.427-.219.673.09.177.189.35.296.516v.001l.004.006v.001l.008.011v.001l.003.006.001.002.004.005v.001l.003.005v.002l.003.005.001.002.003.005.001.002.003.004.002.003.002.003.001.003.003.005.001.001.002.003.003.006.001.002.003.005.001.002.007.01v.001l.005.007v.001c.052.077.105.151.161.226.102.138.262.206.421.2.096-.004.193-.036.276-.099.222-.164.268-.478.103-.699-.158-.226-.305-.464-.43-.71zm-.497-1.582c-.021-.156-.036-.315-.043-.477-.005-.12-.005-.238-.003-.356.008-.275-.209-.506-.485-.514l-.036.001c-.26.011-.471.221-.478.485-.002.104-.003.207-.001.311v.09l.001.005v.028l.001.003-.001.002v.003l.001.002v.029l.001.003v.011l.001.019.001.009v.011c.009.16.025.319.046.477.036.257.261.44.515.43.016-.001.032-.002.047-.005.281-.04.471-.293.433-.567zm5.294 4.3l-.006.001-.124.008c-.237.009-.477.003-.71-.021-.024-.003-.047-.003-.071-.002-.245.01-.451.2-.476.45-.027.274.173.519.447.547l.125.011.004.001.002-.001.003.001h.002l.006.001h.006l.003.001h.001l.006-.001.003.001h.005l.006.001.005.001h.013l.006.001h.013c.152.01.305.015.459.012h.039l.007-.001.006.001h.015l.005-.001h.019l.006-.001h.001l.005.001.001-.001.006.001h.001l.005-.001h.008l.006-.001h.006l.001.001.006-.001h.007l.005-.001h.02l.005-.001h.004l.004-.001.004.001h.005l.004-.001h.005c.042-.001.085-.005.127-.007.269-.022.471-.255.453-.526-.007-.272-.242-.483-.514-.473zm-2.439-.448c-.251-.116-.495-.255-.724-.411-.092-.064-.199-.091-.303-.087-.152.006-.3.08-.393.217-.155.227-.098.539.13.694l.001.001.006.003.006.006.006.004.006.005c.266.181.548.34.842.476.074.035.153.049.23.046.182-.008.352-.113.433-.289.119-.251.01-.549-.24-.665zm5.03-.398c-.085.004-.171.03-.248.08-.233.148-.481.279-.734.387-.255.106-.375.399-.267.655.084.197.279.312.48.305.059-.002.116-.016.173-.038l.134-.06h.002l.006-.004.002-.001.004-.002h.004l.004-.002.002-.002.006-.001.002-.002.003-.002.005-.002.003-.001.005-.002.002-.001.005-.002.002-.001c.003-.002.003-.003.005-.003l.002-.001.006-.003h.002l.006-.003.006-.003.002-.001.005-.003.002-.001.006-.003.001-.001.007-.001.007-.004.002-.001.004-.003h.002l.006-.004.008-.002.006-.004h.001l.007-.004.001-.001.014-.006.007-.003.014-.008.008-.003.006-.003h.001l.014-.008v-.001l.006-.002h.001l.022-.012.007-.002.014-.008.007-.004h.001c.001-.001.003-.002.007-.002.002-.003.004-.004.006-.005l.008-.004.006-.003v-.001l.014-.006h.001l.007-.004.001-.001.005-.003h.001l.007-.004.006-.003h.002l.006-.004v-.001l.007-.003.001-.001.006-.003v-.001l.006-.002.002-.001.004-.003.003-.001.005-.003.002-.001.005-.003.002-.001.006-.002c-.001-.001 0-.001.001-.001l.006-.003.002-.001.004-.003.002-.001.006-.003.002-.001c0-.002.002-.002.004-.003l.003-.001.004-.002.003-.002.004-.002.003-.002.003-.002.003-.003.005-.001.004-.001.002-.002.004-.002.004-.003.002-.001.004-.002.004-.003.003-.002c.002.001.003 0 .005-.001l.002-.002.004-.002.003-.002.003-.002.004-.002.004-.003.002-.001c.002-.001.006-.001.008-.003-.002-.001-.002-.001 0-.001l.004-.002.007-.005.002-.001.007-.003v-.001l.012-.006.008-.005c.006-.004.012-.008.02-.011h.001c.063-.038.128-.077.19-.117.232-.15.301-.457.152-.69-.115-.149-.285-.232-.457-.225zm2.571-4.618l-.024.001c-.266.011-.478.229-.479.498 0 .277-.025.557-.072.829-.047.271.137.531.408.577.036.006.071.009.106.008.23-.01.432-.179.473-.417v-.005l.001-.002.001-.002-.001-.002.001-.002v-.002l.001-.002v-.003l.001-.002v-.009c.002-.001.002-.003.002-.004v-.006c.021-.129.039-.259.052-.391l-.001-.001.001-.003v-.001l.001-.004v-.011l.002-.003v-.001l-.001-.003v-.002l.001-.003v-.004l.002-.001-.002-.003v-.004c.002-.001.002-.002.002-.003v-.019l.002-.003v-.001c.013-.163.021-.328.021-.495 0-.273-.222-.498-.498-.499zm-.443 2.696c-.084-.046-.175-.066-.263-.062-.169.007-.329.1-.417.258-.134.242-.289.476-.463.692-.172.217-.135.531.08.702.1.079.217.113.333.108.14-.006.276-.07.37-.188.116-.146.227-.299.33-.455.002-.007.007-.014.011-.02l.001-.001.004-.006v-.001l.004-.007c.002-.002.004-.004.004-.006l.001.001.004-.006v-.001c.002-.002.003-.005.003-.007l.002-.001.004-.006v-.001c.002-.001.002-.003.003-.005l.001-.001.004-.006.001-.002.002-.005.003-.002.002-.005h.002l.002-.006.001-.002.004-.004.001-.002c.001-.002.001-.004.003-.005l.001-.003.004-.003c0-.001 0-.002.002-.003v-.004l.003-.002.003-.005.001-.002.003-.006.002-.002.002-.004.002-.003c0-.001 0-.002.002-.003 0-.001 0-.002.002-.003l.003-.005.001-.003.002-.003.002-.003c.002-.001.002-.002.002-.003.002-.001.002-.002.002-.004l.002-.003.003-.004.003-.004v-.003l.002-.003.003-.004.003-.003v-.003l.004-.005v-.003c.002-.001.003-.002.003-.004l.002-.002.002-.003.003-.005.002-.003v-.002l.004-.005c0-.001 0-.002.002-.003l.001-.003.003-.004.002-.004.002-.003c.001-.001 0-.003.002-.004 0-.001 0-.002.002-.002l.002-.005.002-.002.002-.006.002-.001.002-.004.002-.002.002-.005.002-.002.002-.006c.002-.001 0-.002 0-.002l.004-.005.001-.002.004-.005v-.001l.003-.006.002-.002.002-.006v-.001l.005-.005.003-.006v-.001l.004-.007.002-.001.025-.047c.129-.234.043-.538-.199-.672z" fill="#5C913B"/><ellipse fill="#55ACEE" cx="18" cy="21" rx="3" ry="1"/><ellipse fill="#FFCC4D" cx="18.5" cy="21" rx="1.5" ry="1"/><path fill="#5C913B" d="M19.117 21.274c-.081 0-.163-.02-.239-.061-.243-.132-.333-.436-.201-.678.16-.294.328-.561.502-.795-.139.006-.283.009-.43.009-.276 0-.528-.225-.528-.501s.195-.5.472-.5l.082.001c.296 0 .6-.018.872-.043.158-.017.309.047.41.156.014-.011.028-.022.043-.031.1-.066.193-.119.28-.161.059-.046.131-.079.211-.094l.036-.007c.188-.061.32-.069.373-.069.159 0 .308.075.402.203.094.128.122.292.075.444-.082.266-.265.326-.586.39-.06.023-.142.063-.238.128-.188.123-.432.104-.599-.034.137.177.143.431-.002.614-.17.217-.337.475-.496.768-.09.167-.262.261-.439.261zm-1.42-1.589c-.021 0-.044-.001-.066-.004-.374-.05-.729-.124-1.056-.221-.265-.079-.416-.357-.337-.622l.006-.02-.012.023c-.135.241-.44.328-.681.192-.34-.19-.645-.419-.907-.681-.195-.195-.195-.512 0-.707.195-.195.512-.195.707 0 .197.197.428.37.688.515.214.12.306.374.229.597.105-.213.354-.326.59-.256.276.082.579.145.9.188.274.036.467.287.431.561-.029.252-.245.435-.492.435zm-2.452-2.339c-.426 0-.977-.165-1.311-.559-.512-.604-.813-1.379-.767-1.973.012-.159-.143-.287-.295-.327-.087-.023-.24-.037-.312.118-.059.126-.207.179-.332.122-.125-.058-.18-.207-.122-.332.156-.339.506-.49.892-.392.358.093.701.415.667.85-.036.462.226 1.109.65 1.61.223.264.611.371.875.381.215.011.324-.038.347-.059-.056-.133-.797-.523-1.113-.689-.269-.141-.349-.335-.369-.472-.067-.455.4-.916.852-1.36.159-.157.31-.305.392-.414.093-.123.078-.205.06-.256-.069-.187-.368-.372-.728-.452-.333-.074-.558-.235-.668-.479-.145-.321-.068-.741.234-1.285.067-.122.22-.164.34-.097.121.067.164.219.097.34-.285.512-.257.744-.215.837.042.092.149.157.32.195.423.094.932.345 1.088.767.089.241.044.501-.128.73-.104.139-.268.3-.441.471-.258.254-.739.727-.708.931.006.042.061.079.107.102.751.394 1.25.679 1.352 1.028.036.123.021.247-.042.359-.097.169-.299.273-.585.299-.043.004-.09.006-.137.006z"/><ellipse fill="#FFCC4D" cx="19.5" cy="18" rx=".5" ry="1"/><path fill="#FFCC4D" d="M17.292 17.188c0 .288-.345.521-.771.521-.425 0-.771-.233-.771-.521s.345-.521.771-.521c.425 0 .771.233.771.521zm-1.187-4.627c.05.212-.227.46-.619.553-.392.093-.75-.004-.801-.216-.05-.213.227-.461.618-.554.393-.092.752.004.802.217z"/><path fill="#C1694F" d="M22.533 17.955c.09.07.243-.729.22-.978 0-.017-.029-.546.083-.924.069-.128.073-1.083-.033-1.334.084-.007.185-.034.197-.136-.388.143-.479-.817-.852-1.369-.362-.553-.811-.875-1.28-1.211.035-.094.091-.182.162-.27-.575.288-1.471-.755-2.795-.677-.297.029-.438.047-.514.229-.247.02-.498.076-.498.401 0 .078.071.22.229.221.216.063.392.014.539.316l.039.312s-.193-.247-.299-.286l.065-.133c-.1-.058-.277-.011-.277-.011s-.385-.18-.694-.132l-.06-.25c-.054.154-.175.146-.192.291-.034-.104-.079-.233-.111-.337-.109.148-.077.308-.116.462-.042.036-.128.037-.15-.062-.011-.122-.026-.133-.026-.278-.078.137-.172.204-.203.439l-.083-.26c.003.307-.261.49-.511.707-.071.13.011.131.017.198l.132.066.237-.017c.039.049.007.053.11.084.276.077.62-.254.89.267-.124.104-.249.347-.209.393.05 0-.1.07.102.006-.21.204-.352.473-.352.489-.024.058.084-.008.062.097l.05-.006c-.479.518-.016 1.075-.067 1.374.08.129.09-.003.19-.016.084.368.326.591.474.882l-.312.003c.007.138.132.269.231.39l-.209.066c-.149.076-.247.157-.352.274-.069.168.333.208.527.238l-.007.203c.303.029.653-.061.653-.078l.076-.059.171.094c.057 0 .146-.228.105-.403.11.131.214.342.324.474l.103-.014c.094.149.223.297.317.446l.105.04c.061-.021.113-.028.146-.148l.048.084.166-.114.116-.023.087.142c.051-.019.101-.13.104-.248.052.103.066.095.104.122l.077-.162.415.388.314.018c.112.076.419.124.471.001.252.108.549-.014.534-.134.232.092.589.03.589.015.043-.005.153-.113.049-.194-.767-.534-1.904-1.418-2.343-1.631 0-.158-.119-.727-.247-.883l.104-.174c.299.279.407.252.566.296.17.135.229.34.399.527l.152.028c-.105-.267-.236-.526-.554-.873.164.082.436.301.618.46.12.201.155.361.265.613.08.051.162.238.151.083-.019-.291-.224-.752-.224-.785.326.258.322.66.421.905.083.124.125.29.161.251l-.096-.756-.056-.277c.241.139.327.669.44 1.305 0 .101.041.212.035.277.052.064.111.241.11.136 0 0 0-1.034-.071-1.271-.018-.127.03-.333.03-.333.088.429.182.894.271 1.322v.315l.132.133c.025-.26.055-.518.081-.776l-.099-.925v-.264c-.002-.093.085-.076.14.03.013.227.013.404.022.63.039.258.066.447.085.776.011.266.023.904.079.893z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..0480330cd0331175fcbccb1984c5d9e1408bead5 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M.555 29h34.891c.343-.591.554-1.268.554-2H0c0 .732.211 1.409.555 2zM0 23h36v2H0zm0-4h36v2H0zm0-4h36v2H0zm0-4h36v2H0zm.555-4C.211 7.59 0 8.268 0 9h36c0-.732-.211-1.41-.555-2H.555z"/><path fill="#010066" d="M18 5H4C1.791 5 0 6.791 0 9v10h18V5z"/><path fill="#FFCC4D" d="M9.534 17.233C6.644 17.233 4.3 14.89 4.3 12c0-2.89 2.343-5.233 5.233-5.233.715 0 1.397.146 2.018.405C10.556 6.438 9.331 6 8 6c-3.313 0-6 2.687-6 6 0 3.314 2.687 6 6 6 1.331 0 2.556-.438 3.551-1.172-.621.26-1.302.405-2.017.405z"/><path fill="#FFCC4D" d="M12.922 8.829l.334 1.62 1.003-1.315-.402 1.604 1.475-.749-1.059 1.271 1.654-.035-1.505.686 1.505.686-1.654-.035 1.059 1.271-1.475-.749.402 1.605-1.003-1.316-.334 1.621-.334-1.621-1.003 1.316.402-1.605-1.475.749 1.058-1.271-1.653.035 1.505-.686-1.505-.686 1.653.035-1.058-1.271 1.475.749-.402-1.604 1.003 1.315z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..cfa95772e36d0a6354a2afe65eea9d5fbcee16cd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f2-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCE100" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#141414" d="M0 13h36v10H0z"/><path fill="#007168" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 13h36v1H0zm0 9h36v1H0z"/><path fill="#DD2E44" d="M1.313 29.945l15.719-11.881L1.33 6.041C.519 6.773 0 7.822 0 9v18c0 1.171.512 2.214 1.313 2.945z"/><path fill="#FCE100" d="M9.478 23.062l-3.271-2.395-3.267 2.395 1.267-3.851L.92 16.845l4.054.015 1.234-3.858 1.239 3.86 4.05-.018-3.288 2.371 1.269 3.847z"/><path fill="#141414" d="M3.369 20.702h2.356c.19.213.613.3 1.016-.002.738-.404 2.167.002 2.167.002l.281-.299-.686-2.25-.246-.264s-.528-.317-1.53-.211c-1.002.106-1.354-.036-1.354-.036s-.879.106-1.125.229c-.027.022-.282.281-.282.281l-.597 2.55z"/><path fill="#FFF" d="M3.369 20.376h2.356c.19.213.613.3 1.016-.002.738-.404 2.167.002 2.167.002l.281-.299-.686-2.25-.246-.264s-.528-.317-1.53-.211c-1.002.105-1.354-.036-1.354-.036s-.879.106-1.125.229c-.027.022-.282.281-.282.281l-.597 2.55z"/><path fill="#141414" d="M2.213 17.012l1.263-1.851.773.124.446-.46 1.541 1.888 1.236-.878.757-.632.454.279 1.607-1.036-1.453 1.362-1.205.856-.959.432 3.242 3.822-.424.301-3.091-3.75-1.002.805 1.317.421-.042.631-1.85-.51.083 1.309-.427.185-.378-.755-1.635 1.917-.589-1.01 1.851-1.557.042-.547 1.01-.925.294-.042.842-.337-1.263-1.346-1.686 2.352-.722-.87"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d2a79fd2cd0664d951bb7c9fe91b11be611b244b --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009543" d="M1.067 29.701C1.798 30.495 2.836 31 4 31h28c2.209 0 4-1.791 4-4V9c0-1.018-.393-1.937-1.019-2.643L1.067 29.701z"/><path fill="#003580" d="M34.933 6.299C34.202 5.505 33.164 5 32 5H4C1.791 5 0 6.791 0 9v18c0 1.018.393 1.937 1.019 2.643L34.933 6.299z"/><path fill="#EEE" d="M36 9c0-2.209-1.791-4-4-4h-.664L0 26.942V27c0 2.209 1.791 4 4 4h.664L36 9.059V9z"/><path fill="#D20F34" d="M32.984 5.136L.175 28.108c.399 1.377 1.506 2.447 2.912 2.777L35.843 7.949c-.378-1.382-1.468-2.459-2.859-2.813z"/><path fill="#FFCE00" d="M8 8l.809 1.981L10.5 8.67l-.29 2.12 2.12-.29-1.311 1.691L13 13l-1.981.809L12.33 15.5l-2.12-.29.29 2.12-1.691-1.311L8 18l-.809-1.981L5.5 17.33l.29-2.12-2.12.29 1.311-1.691L3 13l1.981-.809L3.67 10.5l2.12.29-.29-2.12 1.691 1.311z"/><circle fill="#003580" cx="8" cy="13" r="3.175"/><circle fill="#FFCE00" cx="8" cy="13" r="2.467"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..e5dff93453839fed4fc13bc38d4cca26423c1776 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009543" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#ED4135" d="M0 13h36v10H0z"/><path fill="#0035AD" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><ellipse transform="rotate(-76.714 13.001 18.001)" fill="#141414" cx="13" cy="18" rx="9.402" ry="9.402"/><circle fill="#FAE600" cx="13" cy="18" r="9"/><g fill="#141414"><path d="M12.87 9.008h.322v17.984h-.322z"/><path d="M14.25 14.719c0 .673-.546 1.219-1.219 1.219s-1.219-.545-1.219-1.219c0-.673.546-1.219 1.219-1.219s1.219.545 1.219 1.219zm-.219 7.547c0 .786-.448 1.422-1 1.422s-1-.636-1-1.422c0-.786.448-1.422 1-1.422s1 .635 1 1.422zm.219-3.985c0 .406-.546.734-1.219.734s-1.219-.328-1.219-.734c0-.406.546-.734 1.219-.734s1.219.328 1.219.734zM11.688 13s-.125-.875.125-1.25.906-.719 1.438-.844C13.781 10.781 14.5 10 14.5 10s-.094 1.156-.969 1.875c-.875.719-1.843 1.125-1.843 1.125zm-.766 1.776s.484.312.609.781c.125.469.469.969 1.469.969v.562s-.844.062-1.312-.125c-.469-.188-.594-1.062-.594-1.375s-.172-.812-.172-.812zm4.187 0s-.484.312-.609.781c-.125.469-.469.969-1.469.969v.562s.844.062 1.312-.125c.469-.188.594-1.062.594-1.375s.172-.812.172-.812z"/><path d="M14.938 21.188c0-.312-.141-1.188-.609-1.375-.47-.188-1.329-.26-1.329-.26s-.844.072-1.312.26c-.469.188-.594 1.062-.594 1.375S10.922 23 10.922 23s.656-1.098.781-1.566c.125-.469.641-1.053 1.297-1.053.672 0 1.203.562 1.328 1.031.125.469.774 1.588.774 1.588s-.164-1.5-.164-1.812zM13 24v3s-.875.094-2.125-.234-1.484-.453-1.484-.453 1.272-1.273 1.828-1.75C11.875 24 13 24 13 24zm0 0v3s.875.094 2.125-.234 1.484-.453 1.484-.453-1.273-1.273-1.828-1.75C14.125 24 13 24 13 24z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..53f25f5012f7904fc6c2b99b07fb0924bd4b1e17 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#E05206" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><circle fill="#E05206" cx="18" cy="18" r="4"/><path fill="#0DB02B" d="M32 31H4c-2.209 0-4-1.791-4-4v-4h36v4c0 2.209-1.791 4-4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..990687f09e6470e6af1cb015bd5b5b47cf16dd9a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#007934" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4zm28 0h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#007934" d="M20.016 21.657c.525-.04 1.344.185 1.946.131.601-.056.506-.097.308-.253-.199-.157-.369-.041-.471.06-.104.103-.28.096-.199-.007.082-.103.007-.149-.191-.137-.198.015-.342.083-.471.117-.13.034-.273-.056-.172-.102.104-.049.089-.089.007-.096-.082-.007-.088-.061.137-.097.226-.033.382.028.513.075.13.049.28.008.377-.06.095-.068.15-.144.265-.137.117.007.186-.055.035-.158-.149-.102-.368-.108-.499-.046-.13.061-.191.02-.24-.042-.046-.062-.232-.056-.415.027-.184.083-.31.188-.417.041-.055-.075-.431.014-.662.082-.233.068-.275 0-.084-.089.254-.117.409-.035.786-.178.254-.096.614.061 1.21-.28.143-.082.28-.164-.115-.178-.199-.007-.294.014-.362.103-.068.09-.15.068-.144 0 .007-.068-.179-.115-.335-.014-.157.104-.273.191-.349.212-.075.021-.092.003-.075-.055s-.038-.051-.105-.007c-.068.045-.185.102-.26.097-.075-.007-.157-.069.055-.179.212-.108.412-.244.734-.219.424.035.518-.141.724-.134.205.008.313-.149.038-.153-.276-.003-.358.059-.42.104-.061.043-.186.075-.165-.018.022-.093-.027-.093-.125-.048-.101.044-.343.075-.459.04-.115-.033-.226-.095.052-.108.276-.014.469-.146.704-.086.212.055.323-.054.401-.044.08.01.176-.059.035-.171-.14-.112-.492-.119-.615-.1-.122.021-.186 0-.163-.047.022-.048-.011-.068-.117-.064-.105.003-.4.071-.525.126-.164.071-.287-.039-.153-.126.088-.059.323-.13.453-.113.131.017.188.032.15-.059-.017-.04-.023-.092.117-.058.14.034.424.041.58-.048.157-.089.042-.191-.212-.185-.252.007-.799.081-1.018.225-.219.144-.25-.01-.16-.058.089-.047.102-.082.054-.112-.047-.03-.045-.058.087-.106.252-.092.519-.065.832-.208.235-.107.479-.233.554-.416.075-.185-.041-.123-.179-.068-.135.054-.218.095-.218.191s-.115.096-.108-.021c.006-.116-.062-.17-.247-.095-.184.075-.649.246-.812.226-.164-.02-.232-.124-.062-.13.172-.007.403-.075.54-.123.137-.047.219-.123.115-.178-.102-.055-.026-.123.09-.123.115 0 .252-.103.402-.082.15.021.32-.029.123-.144-.081-.047-.156-.109-.055-.164.103-.055.042-.205-.115-.225-.158-.021-.302.013-.384.041-.081.027-.15.02-.17-.048-.021-.069-.287-.062-.397-.034-.108.027-.32.014-.163-.062.157-.075.492-.123.655-.123.164 0 .336-.041.424-.075.089-.034.11-.212-.088-.212-.199 0-.457.014-.411-.061.049-.076-.123-.123-.313-.082-.191.04-.452.082-.3-.021.15-.103.457-.212.601-.206.144.007.245-.02.15-.136-.096-.116-.034-.157.062-.171.095-.014.116-.13-.021-.157-.137-.027-.488-.107-.655-.013-.233.129-.41.123-.335.047.074-.075.022-.073-.098-.041-.271.075-.86.246-1.023.233-.083-.007-.178.01-.176-.09.001-.091.066-.098.305-.136.479-.075 1.004-.225 1.23-.198.225.028.322-.006.26-.102-.062-.096-.24-.021-.163-.144.075-.123-.061-.11-.165-.116-.102-.007-.209-.048-.268-.102-.083-.08-.365-.034-.508.021-.144.055-.46.128-.583.12-.15-.01-.159-.01-.166-.12-.003-.056.016-.079.084-.106.156-.062.793-.086.991-.048.389.075.405-.069.323-.14-.105-.092-.443-.051-.656-.014-.212.038-.437.079-.495.027-.058-.051.007-.098.154-.126.178-.034.595-.011.66-.041.065-.031.13-.127-.015-.165-.143-.038-.481 0-.638.055-.158.055-.332.038-.37-.017-.038-.055-.023-.191.24-.17.262.021.745.014.83 0 .087-.014.097-.075.052-.133-.044-.058-.099-.12-.049-.164.052-.044.032-.082.005-.119-.028-.038 0-.068.027-.093.026-.024.063-.082-.035-.064-.167.031-.427-.055-.559-.003-.134.051-.436.086-.534.072-.044-.007-.068-.096.014-.106.143-.018.427-.059.533-.113.105-.055.215-.095.349-.092.132.003.219-.047.089-.109-.131-.061-.342-.044-.466.014-.122.058-.344.171-.464.154-.119-.017-.131-.087-.085-.236.024-.079.181-.085.291-.065.109.021.431-.061.553-.034.123.027.233-.021.097-.123-.137-.103-.26-.068-.397-.014-.136.055-.437.13-.518.055-.082-.075-.102-.267.051-.198.167.075.584-.061.696-.003.113.058.171-.051.061-.102-.108-.051-.43-.003-.538.021-.185.042-.26.055-.26-.051 0-.072.211-.061.27-.045.151.041.373-.146.509-.112s.113-.042.042-.096c-.072-.054-.343-.027-.438.034-.095.062-.26.1-.321.096-.061-.004-.088-.021-.088-.13s.059-.141.14-.181c.133-.065.155-.164.054-.14-.157.038-.211.089-.211-.123 0-.096.013-.182.139-.208.127-.028.151-.113.11-.133-.042-.021-.093.03-.155.055-.061.024-.103.048-.109-.123-.003-.099.055-.13.112-.133.059-.003.117-.045.144-.082.028-.038 0-.089-.088-.051-.089.038-.173.048-.174-.051-.003-.222-.031-.731-.038-.851-.007-.12-.092-.15-.092-.014 0 .137-.008.629-.027.861-.007.082-.055.089-.124.048-.068-.041-.266-.014-.129.048.136.061.225.082.232.191.007.109-.054.123-.171.068-.116-.055-.266-.034-.054.096.212.129.225.137.218.273-.006.137-.076.124-.211.062-.165-.076-.3-.014-.109.075s.321.205.314.328c-.012.121-.102.182-.245.005-.144-.178-.375-.267-.546-.246-.171.021-.082.102.116.178.199.075.519.225.595.308.075.082.034.15-.144.075s-.575-.226-.704-.178c-.13.048-.184.123.035.13.218.007.598.069.758.13.199.075.226.232.034.177-.191-.054-.724-.164-.881-.068-.157.096-.205.192.062.15.267-.041.602-.042.752.021.082.034.15.041.144.157-.007.116-.096.116-.259.048-.165-.068-.657-.198-.807-.075-.15.123-.116.144.096.109.212-.034.534-.003.69.027.318.062.294.117.089.117s-.813.027-.956-.028c-.144-.054-.355-.089-.438-.054-.082.034-.014.068.054.068.069 0 .124.055.075.102-.047.047-.075.136.117.102.191-.034.465-.034.608.021.143.055.361.117.539.136.191.021.198.027.191.171-.005.106-.225.041-.437-.096s-.622-.211-.813-.082c-.191.13-.082.157.096.123s.67.055.854.116c.184.062.297.021.287.191-.007.102-.11.049-.267-.014-.478-.191-1.054-.208-1.243-.185-.134.017-.154.03-.11.068.033.027.008.079-.072.099-.082.02-.188.055-.238.096-.052.041-.048.082.099.068.147-.013.294.011.208.068-.085.058-.193.136-.023.151.437.038 1.072.311 1.291.434.219.123.277.133.273.246-.003.113-.122.095-.25.027-.399-.211-.796-.163-1.001-.307-.205-.144-.505-.301-.696-.178-.191.123-.157.198.013.178.171-.02.355.007.287.096s-.115.146.164.185c.39.055 1.025.3 1.237.389.212.089.294.15.116.178-.178.027-.185-.099-.465-.109-.177-.007-.403-.103-.526-.198-.122-.095-.205-.144-.409-.123-.206.021-.499.055-.608.117-.109.061-.151.15.027.157.178.007.26.116.124.164-.137.048-.28.075-.328.13-.048.055.02.103.205.103s.472.061.725.185c.252.123.983.492 1.182.505.198.014.219.041.212.144-.007.103-.076.082-.239.034-.164-.048-.629-.191-.779-.321-.15-.13-.304-.253-.44-.259-.137-.007-.099.038-.052.089.048.051.044.177-.047.092-.147-.137-.253-.283-.447-.287-.195-.003-.379 0-.478.055-.1.055-.087.134.099.16.219.031.455.099.564.164.109.065.061.13-.041.123-.103-.007-.079.051.034.119s.181.16.095.182c-.123.03-.338-.216-.437-.202-.068.01-.014.058.044.096.059.038.06.163-.034.092-.129-.1-.304-.229-.502-.157-.198.072-.293.157-.126.229.167.072.288.138.208.239-.039.048-.074.12.163.137.147.01.311.068.383.147.072.078-.021.11-.109.072-.089-.038-.287-.058-.383.031-.096.088.001.15.195.173.546.065 1.127.243 1.448.271.321.026.588.104.724.157.181.071.086.273-.047.205-.188-.097-.318-.153-.39-.168-.072-.013-.072.014-.059.079.014.064-.068.098-.146.023-.079-.075-.318-.218-.465-.242-.146-.025-.126.003-.102.05.024.048.014.13-.082.035-.096-.096-.396-.233-.574-.222-.116.007-.091.044-.068.092.024.048-.037.15-.109.052-.072-.1-.225-.238-.406-.13-.075.044-.15.106-.26.127-.11.02-.086.083.064.115.393.085.546-.024.807.079.198.079.372.102.447.109.075.007.13.052.045.078-.086.028-.079.092.013.175.093.082.019.209-.062.112-.147-.178-.362-.115-.44-.201-.079-.086-.113-.075-.113-.007 0 .068-.039.086-.113.027-.263-.204-.591-.164-.731-.068s-.109.128.144.168c.714.112 1.602.263 2.367.583.415.174.39.212.37.264-.021.051-.101.063-.267-.048-.188-.127-.689-.202-.912-.339-.222-.136-.287-.064-.226.022.062.085.039.174-.088.061-.127-.113-.39-.257-.539-.26-.15-.003-.038.061.038.112.075.051.092.208-.038.126-.13-.081-.517-.297-.817-.222-.3.075-.256.12-.102.219.154.099.298.171.626.161.328-.011.642.051.789.147.146.096.01.119-.089.061-.099-.058-.365-.102-.475-.088-.109.013-.059.064-.014.116.044.051-.007.212-.096.112-.089-.099-.331-.215-.478-.249-.321-.075-.464.073-.324.123.085.03.129.075.078.144-.052.068-.079.146.095.119.407-.062 1.156-.049 1.568.082.355.113.277.188.184.182-.092-.007-.191-.056-.144.033.048.089.044.169-.075.086-.246-.171-.587-.235-.745-.229-.085.003-.047.049-.01.097.037.047-.017.13-.109.058-.092-.071-.263-.174-.375-.178-.113-.003-.109.034-.059.085.051.052.04.141-.065.065-.157-.112-.406-.232-.587-.219-.181.014-.1.102.065.171.31.13.638.211.871.233.232.02.437.085.533.091.095.007.136.06.006.075-.177.021-.464-.107-.608-.04-.075.034.019.084.031.108.024.049.014.174-.078.099-.28-.229-.455-.197-.554-.27-.099-.071-.201-.03-.137.051.066.083-.072.059-.177-.006-.106-.065-.284-.108-.396-.075-.113.035-.164.075.068.198.232.123.42.215.657.26.235.044.266.183.136.167-.129-.017-.152.058-.064.123.041.03.068.116.061.168-.007.051-.086.041-.188-.072-.246-.273-.789-.294-1.059-.215-.27.078-.157.208.038.392.195.185.376.379.881.317.505-.061 1.4-.252 1.811-.143.41.108.364.295.239.315-.225.033-.219-.186-.45-.199-.233-.013-.308.103-.383.185-.075.082-.131.154-.369.041-.301-.144-.533.061-.663.034.123.068.328.226.274.287-.055.062-.144-.062-.328-.13-.184-.068-.458-.082-.663.041-.205.123.007.246.232.301.226.055.718.055 1.121-.055.403-.109.902-.187 1.086-.191.137-.004.199.071.106.157.14.041.305.001.393-.055.226-.144.195 0 .146.089.148.01.404-.174.506-.106.03.618-.011 1.868-.011 2.299 0 .075.055.062.431.062.455 0 .479.034.464-.186-.013-.213-.144-1.488-.102-1.953.042-.465.171-.431.335-.396.164.034.554.157.746.15-.123-.13-.137-.219-.021-.191.116.027.267-.021.368-.109-.088-.007-.149-.123.009-.15.156-.027.21.055.483.144s1.302.292 1.887-.082c.171-.109.034-.157-.178-.157s-.32.048-.424.089c-.103.041-.195.071-.174-.01.021-.082-.163-.113-.328-.038-.164.075-.304.109-.263.021.04-.089-.024-.109-.243-.096-.19.012-.758-.051-.734-.142.014-.056.122-.082.311-.041.447.095 1.444.123 1.747.103.49-.034.347-.186.16-.239-.188-.056-.4-.015-.447.044-.049.059-.211.096-.172.003.055-.13-.216-.16-.454-.03-.163.089-.195.044-.137-.027.059-.072-.038-.121-.222-.105-.264.02-.742.026-.926-.052-.209-.091-.16-.119.189-.147zm-1.628-7.115c-.061.017-.126.044-.126-.027 0-.075.075-.044.126-.038.052.007.122.032 0 .065zm-.003-.321c.052.017.164.031.236.014.072-.017.158.037.044.068-.202.055-.409.099-.413-.027-.002-.078.082-.072.133-.055zm-.584-.061c-.111-.047-.075-.099-.021-.119.055-.02.17-.014.164.106-.003.071-.095.033-.143.013zm-1.855 7.69c-.058-.086.018-.031.137.003.071.02.141.068.137.126-.007.099-.216-.044-.274-.129zm1.377-1.381c.116.075.478.068.478.219 0 .068-.075.027-.165.027-.088 0-.279-.076-.403-.184-.122-.11-.027-.137.09-.062zm.457 1.475c-.016.138-.245.041-.417-.054-.171-.097.014-.137.089-.117.075.021.145.023.239 0 .089-.019.11 0 .089.171zm-.109-.395c-.123 0-.39-.102-.622-.199-.232-.095-.021-.15.116-.095.137.055.369.068.513.068.164 0 .177.226-.007.226zm-.198-3.143c-.198-.027-.376-.177-.916-.3-.225-.051-.171-.082-.014-.082s.615.206 1.1.281c.108.017.239.04.232.191-.005.149-.209-.063-.402-.09zm.201-.56c-.122-.092-.536-.222-.69-.253-.153-.03-.239-.082-.092-.103.147-.021.348.024.529.117.1.051.271.126.342.126.072 0 .126-.01.126.14.001.161-.091.065-.215-.027zm-.706-3.007c.198.076.597.045.854.205.11.068-.041.082-.198.02-.157-.061-.342-.027-.663-.137-.263-.088-.151-.147.007-.088zm.519 1.155c-.235-.085-.331-.157-.314-.194.017-.038.237.018.389.068.271.089.326.096.318.215-.007.096-.157-.003-.393-.089zm-.56.284c.239 0 .532.137.734.233.14.066.219.092.215.181-.003.075-.088.04-.157-.007-.068-.047-.55-.191-.782-.287-.233-.096-.249-.12-.01-.12zm.977.772c-.007.061-.062.02-.116.02-.099 0-.349-.188-.684-.242-.165-.027-.362-.168-.543-.226-.181-.058-.04-.14.059-.083.063.037.15.059.331.092.181.034.574.182.701.267.058.041.267.029.252.172zm.031-1.636c-.007.109-.059.12-.127.058-.068-.061-.225-.106-.39-.154-.163-.048-.099-.15.028-.089s.298.092.444.072c.075-.011.048.051.045.113zm.303.351c.006-.157.021-.163.119-.143.112.023.455.01.592-.003.137-.014.249.038.017.082-.232.045-.407.093-.506.134-.098.04-.229.087-.222-.07zm1.354 3.208c-.097.102-.604.195-.909.335-.253.116-.301.082-.301-.075 0-.172.177-.068.267-.13.088-.062.628-.117.793-.205.162-.088.245-.028.15.075zm-.417.834c-.164.021-.314.108-.575.197-.259.09-.22-.051-.116-.115.109-.068.465-.15.663-.165.198-.013.191.062.028.083zm-.104-1.046c-.054.055-.197.109-.396.156-.198.048-.294.042-.294-.075 0-.115.062-.082.205-.068.144.015.417.021.485-.013zm-.471-.611c-.075.048-.238.072-.235 0 .003-.072 0-.065.041-.068.201-.017.375-.131.482-.14.163-.014.255-.027.16.044-.095.072-.373.116-.448.164zm-.14-1.555c.072.002.301-.04.408-.081.105-.041.112-.011.046.031-.065.041-.281.113-.375.144-.14.044-.208.061-.212-.028-.004-.079.014-.069.133-.066zm.018.619c.147.007.427 0 .519-.055.094-.055.215-.051.267-.045.052.007.032.041-.059.096-.088.055-.398.058-.501.123-.103.064-.252.079-.318.082-.065.003-.075 0-.075-.075-.001-.116.02-.133.167-.126zm-.158.515c.003-.079.011-.099.083-.099.191 0 .512-.15.639-.153.127-.003.191.068.038.089-.155.02-.482.103-.551.146-.069.045-.213.096-.209.017zm.26.657c.19.027.212.095-.041.137-.123.02-.167.027-.177-.083-.008-.067.026-.082.218-.054zm-.089 1.202c.096.005.302-.038.374-.059.128-.038.115.014.033.059-.082.044-.287.13-.441.112-.154-.016-.103-.119.034-.112zm.315 2.391c-.089-.027-.15-.034-.24-.013-.088.02-.15-.056-.15-.15.089.067.308-.042.505.067.083.047-.027.123-.115.096zm.088-.539c-.101 0-.253.109-.389.081-.137-.026-.123-.156.014-.122.109.026.191-.021.342-.056.15-.033.135.097.033.097zm-.403-.514c.068 0 .137 0 .219-.026.083-.027.075.026.014.061-.062.033-.15.096-.239.068-.09-.027-.069-.103.006-.103zm.055-.587c-.267.117-.183-.058-.055-.116.075-.034.437-.157.649-.239.212-.082.37-.082.527-.102.156-.021.156.007.046.137-.108.129-.232.089-.408.082-.179-.007-.493.122-.759.238zm.942.212c-.17.007-.172-.053-.075-.082.068-.02.191-.041.24-.007.047.034.007.082-.165.089z"/><path fill="#EEE" d="M17.879 15.779c0 .168-.136.304-.304.304h-.632c-.168 0-.304-.136-.304-.304 0-.168.136-.304.304-.304h.632c.168 0 .304.136.304.304zm1.534 4.249c0 .243-.197.441-.44.441h-.042c-.243 0-.441-.197-.441-.441 0-.243.197-.44.441-.44h.042c.243 0 .44.197.44.44zm-.607 1.79c0 .088-.072.16-.161.16-.089 0-.161-.072-.161-.16v-.628c0-.088.072-.16.161-.16.089 0 .161.072.161.16v.628zm-1.026-.172c0 .165-.133.298-.297.298h-.136c-.164 0-.297-.133-.297-.298 0-.164.133-.297.297-.297h.136c.164.001.297.133.297.297zm.11-4.335c0 .24-.136.436-.304.436-.167 0-.304-.195-.304-.436v-.478c0-.24.136-.436.304-.436.168 0 .304.195.304.436v.478zm.717-1.471c0 .1-.081.182-.182.182-.1 0-.182-.082-.182-.182v-.278c0-.101.081-.182.182-.182.101 0 .182.082.182.182v.278zm2.589 6.148c0 .185-.129.335-.289.335h-.601c-.16 0-.29-.149-.29-.335 0-.185.13-.334.29-.334h.601c.16 0 .289.15.289.334zm-4.632.53c0 .159-.129.288-.288.288h-.709c-.159 0-.288-.129-.288-.288 0-.159.129-.288.288-.288h.709c.159-.001.288.128.288.288z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c6e31ca0685c6ecbccf1ecf491df8a3947128a7 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009A49" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#009A49" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..990868aa7fd7fe216eb5b818e02ea6ad7063ab59 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#265FB5" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#A9BF4C" d="M22.557 18c0 2.517-2.04 4.557-4.557 4.557s-4.557-2.04-4.557-4.557 2.041-4.557 4.557-4.557 4.557 2.04 4.557 4.557z"/><circle fill="#EEE" cx="18" cy="18" r="4"/><path fill="#265FB5" d="M14.758 20.155l3.228-5.591 3.228 5.591z"/><path fill="#55ACEE" d="M15.116 19.938l2.87-4.969 2.869 4.969z"/><path fill="#BBDDF5" d="M15.116 19.938l.693-1.199 4.322-.054.724 1.253z"/><path fill="#5C913B" d="M15.672 19.156l1.078-.875.469.531.406-.438.344.344.328-.359.391.359.359-.375.328.375.312-.344.516.641.094.188s-.547.109-1.297.047-1.188.109-1.781.188c-.594.078-1.656-.078-1.656-.078l.109-.204z"/><path fill="#E2F09F" d="M16.734 18.469l.719.781-.359.031-.406-.593zm.86.062l.578.516-.266.047-.281-.391zm.734-.031l.5.469-.125.078-.406-.438zm.656 0l-.203.188.094.109zm.625.016l-.234.296.078.141.172-.328z"/><path fill="#BBDDF5" d="M18.031 16.43l.067.929.531-.763-.399.83.83-.399-.763.532.93.066-.93.066.763.532-.83-.399.399.83-.531-.763-.067.929-.066-.929-.531.763.398-.83-.83.399.764-.532-.93-.066.93-.066-.764-.532.83.399-.398-.83.531.763z"/><path fill="#DD2E44" d="M18 17.203l-.188.188s.047.281.031.328c-.015.047.157.281.157.281l.234-.281-.062-.375-.172-.141z"/><path fill="#269" d="M18.094 16.875c.766 0 1.203.375 1.203.375l-.281-.5s-.453-.344-.984-.344c-.531 0-1.125.422-1.125.422l-.266.531s.687-.484 1.453-.484z"/><path fill="#FFCC4D" d="M18.094 16.875c.766 0 1.203.375 1.203.375l-.203-.359s-.547-.328-1.078-.328-1.188.422-1.188.422l-.188.375c.001-.001.688-.485 1.454-.485z"/><path fill="#DD2E44" d="M18.094 16.875c.766 0 1.203.375 1.203.375l-.141-.234s-.422-.297-1.141-.266c-.531 0-1.266.391-1.266.391l-.109.219c.001-.001.688-.485 1.454-.485z"/><path fill="#EEE" d="M17.587 21.747h.996v.955h-.996zm-.159-7.405h-.716l-.358-.875.716-.08zm1.632.398l-.477-.159.239-1.155.915.08zm-4.299 4.897l-1.393.318-.04-.955 1.393-.199zm.359.995l-1.155.478-.279-.756 1.075-.359zm7.683-.875l-1.274-.359v-.676l1.433-.2zm-.637 1.313l-1.194-.557.397-.717 1.315.398z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..65e8be9abd0325c16c5daa914a5c1344fea02571 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#AE1F28" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#20478B" d="M4 31h28c2.209 0 4-1.791 4-4v-5H0v5c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f5260a686057e02198d1f06cf06a0aaeff21b36 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EF2B2D" d="M10 5H4C1.791 5 0 6.791 0 9v6h10V5zm22 0H16v10h20V9c0-2.209-1.791-4-4-4zM10 31H4c-2.209 0-4-1.791-4-4v-6h10v10zm22 0H16V21h20v6c0 2.209-1.791 4-4 4z"/><path fill="#002868" d="M14.5 5h-2.944l-.025 11.5H0v3h11.525L11.5 31h3V19.5H36v-3H14.5z"/><path fill="#EEE" d="M14.5 31H16V21h20v-1.5H14.5zM16 5h-1.5v11.5H36V15H16zm-4.5 0H10v10H0v1.5h11.5zM0 19.5V21h10v10h1.5V19.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f5.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..5e5faaf26f419c0f920b067fe7911707eb1fc6ff --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#22408B" d="M27.796 19L8 5v26h19.796L15.918 19z"/><path fill="#DD2F45" d="M25 18L9 7.196V30h16L13.574 18z"/><path fill="#FFF" d="M14.291 24.041l.586-.816-1 .098.1-1-.817.586-.414-.916-.414.916-.817-.586.099 1-1-.098.586.816-.916.414.916.414-.586.816 1-.098-.099 1 .817-.586.414.916.414-.916.817.586-.1-1 1 .098-.586-.816.916-.414zm-1.546-7.147l.001.002.001-.002.018.002c1.468 0 2.66-1.13 2.784-2.567-.348.648-.912 1.16-1.595 1.442l-.175-.244.611-.276-.611-.276.391-.545-.668.066.067-.668-.546.391-.276-.612-.276.612-.546-.391.067.668-.668-.066.391.545-.611.276.611.276-.167.233c-.67-.284-1.222-.792-1.566-1.431.121 1.429 1.303 2.554 2.763 2.565z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..72485e70799d6941c4b2ddd0caa2df6b8f6d8a24 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002B7F" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFC61E" d="M0 17h36v2H0z"/><path fill="#FFF" d="M9.979 19.479l.492 1.965 1.409-1.456-.556 1.949 1.949-.557-1.457 1.409 1.966.492-1.966.492 1.457 1.41-1.949-.557.556 1.949-1.409-1.457-.492 1.966-.492-1.966-1.409 1.457.556-1.949-1.948.557 1.456-1.41-1.966-.492 1.966-.492-1.456-1.409 1.948.557-.556-1.949 1.409 1.456z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..dd50901afff6c547df90ef292a3a5acacc7c07a3 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFE150" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/><circle fill="#004A77" cx="9.5" cy="11.5" r="2.5"/><path fill="#FFE150" d="M9.5 8.966l.599 1.6 1.824.038-1.454 1.225.529 1.746L9.5 12.533l-1.498 1.042.529-1.746-1.454-1.225 1.824-.038zm-5.676 1.519l.246.707.748.016-.596.452.216.716-.614-.427-.614.427.217-.716-.597-.452.749-.016zm11.352 0l.246.707.748.016-.596.452.216.716-.614-.427-.614.427.216-.716-.596-.452.748-.016zM9.5 5.821l.246.707.748.016-.596.452.216.716-.614-.427-.614.427.217-.716-.597-.452.748-.016zm0 9.467l.246.707.748.015-.596.452.216.717-.614-.428-.614.428.217-.717-.597-.452.748-.015z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..956a9d21589bdf3d9bf8d08467b83d699a5f7228 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f3-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEEDED" d="M29.194 9.5h-1.263l-.194-.58-.237-.706-.237.706-.194.58h-1.263l.535.443.472.39-.199.587-.267.782.656-.504.497-.383.497.383.656.504-.267-.782-.199-.587.472-.39z"/><path fill="#CF1B2B" d="M27.5 9l-.251.75H26.5l.605.501-.255.749.65-.5.65.5-.255-.749.605-.501h-.749z"/><path fill="#EEEDED" d="M29.194 25.75h-1.263l-.194-.58-.237-.706-.237.706-.194.58h-1.263l.535.443.472.39-.199.587-.267.782.656-.504.497-.383.497.383.656.504-.267-.782-.199-.587.472-.39z"/><path fill="#CF1B2B" d="M27.5 25.25l-.251.75H26.5l.605.501-.255.749.65-.5.65.5-.255-.749L28.5 26h-.749z"/><path fill="#EEEDED" d="M33.194 13.5h-1.263l-.194-.58-.237-.706-.237.706-.194.58h-1.263l.535.443.472.39-.199.587-.267.782.656-.504.497-.383.497.383.656.504-.267-.782-.199-.587.472-.39z"/><path fill="#CF1B2B" d="M31.5 13l-.251.75H30.5l.605.501-.255.749.65-.5.65.5-.255-.749.605-.501h-.749z"/><path fill="#EEEDED" d="M25.194 15.5h-1.263l-.194-.58-.237-.706-.237.706-.194.58h-1.263l.535.443.472.39-.199.587-.267.782.656-.504.497-.383.497.383.656.504-.267-.782-.199-.587.472-.39z"/><path fill="#CF1B2B" d="M23.5 15l-.251.75H22.5l.605.501-.255.749.65-.5.65.5-.255-.749.605-.501h-.749z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f4-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f4-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..29af825894be2bdb99ade3ca2285fcae5ee2c0ab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f4-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="green" d="M8 31h24c2.209 0 4-1.791 4-4v-4H8v8z"/><path fill="#EEE" d="M32 5H8v8h28V9c0-2.209-1.791-4-4-4z"/><path fill="#DB161B" d="M36 13H9V5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h5v-8h27V13z"/><g fill="#EEE"><path d="M3.625 8.453c.313.567.313.789.222.839-.09.05-.238-.09-.55-.657-.313-.567-.672-1.345-.582-1.395.091-.051.597.647.91 1.213zm1.891-.349c-.313.567-.493 1.067-.402 1.117.09.05.417-.369.73-.935.312-.567.493-1.067.402-1.117-.091-.05-.418.369-.73.935zm-.563.912l-.297-1.422-.028-.006c.103-.049.184-.126.184-.237 0-.16-.147-.289-.328-.289s-.328.13-.328.29c0 .108.075.193.175.243l-.284 1.436.906-.015z"/><path d="M6.703 11.766c-.271-.226-1.349-1.159-1.861-1.716.046-.16.073-.332.062-.516h.017v.008h.891v.172h1.094v-.531H5.812v.172h-.89v.008h-.031v-.269h-.813v.269H3.75v.016h-.641v-.22H2.078v.578h1.031v-.218h.641v.016h.276l-.036.374s-1.039.046-1.318.091c-.688.109-.469.312.094.5.259.086.517.12.761.133-.397.424-1.207 1.053-1.402 1.164-.219.125-.219.281.203.188.409-.091 1.355-.926 1.684-1.348l.285-.012c.15-.006.269-.1.369-.224.427.505 1.264 1.254 1.6 1.458.359.219.527.214.654.193.127-.021.064-.052-.217-.286z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..4fc55f5b083292145524cccf5cce01419077be81 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M18 18V5H4C1.791 5 0 6.791 0 9v9h18zm0 0v13h14c2.209 0 4-1.791 4-4v-9H18z"/><path fill="#005293" d="M18 18v13H4c-2.209 0-4-1.791-4-4v-9h18z"/><path fill="#D21034" d="M18 18V5h14c2.209 0 4 1.791 4 4v9H18z"/><path fill="#005293" d="M9.674 10.573L9 8.5l-.674 2.073H6.147l1.763 1.281-.673 2.073L9 12.646l1.763 1.281-.673-2.073 1.763-1.281z"/><path fill="#D21034" d="M25.91 24.854l-.673 2.073L27 25.646l1.763 1.281-.673-2.073 1.763-1.281h-2.179L27 21.5l-.674 2.073h-2.179z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc93b299aa4197e332f977ff142ca0391d2001c4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D91023" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#EEE" d="M12 5h12v26H12z"/><path fill="#D91023" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..333c6d0abda9a7a5deb60e53d37609f568f267b4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 12h36v12H0z"/><path d="M14.962 19.766c-.13-.35-.166-.656-.166-.656s-.078-.109-.318 0-.494.312-.854.391c-.167.036-.311-.049-.42-.147.04.143.101.275.153.413h1.605zm3.571 0c-.099-.202-.221-.359-.533-.359-.302 0-.437.177-.536.359h1.069zm4.11 0c.059-.152.124-.302.167-.461-.331.337-.84.208-.997.008-.172-.219-.562-.252-.562-.252s-.047.315-.15.69c-.001.005-.005.011-.007.016h1.549zm-.356.75c.079-.135.161-.268.228-.411-.097-.049-.215-.094-.358-.097-.344-.008-.377.238-.859.242-.229.002-.35-.056-.416-.13-.116.142-.272.279-.444.396h1.849zm-5.374 0h2.067c-.042-.042-.083-.086-.118-.134l.003.012s-.428-.409-.866-.409c-.562 0-.95.409-.95.409l.013-.024c-.043.049-.094.099-.149.146zm-1.439 0c-.141-.117-.259-.257-.348-.41-.148.102-.315.188-.485.176-.422-.031-.69-.48-.938-.359-.085.042-.165.083-.242.119.074.165.164.32.254.475l1.759-.001zm-1.094.89h7.242c.119-.129.233-.262.339-.402-.168-.144-.422-.316-.711-.316-.484 0-.691.438-1.119.438-.428 0-.475-.391-1.006-.391s-.766.453-1.18.453c-.414 0-.711-.453-1.101-.453-.391 0-.688.453-1.109.453s-.656-.5-1.031-.5c-.236 0-.515.15-.699.265.116.158.242.309.375.453zm6.356.735c.115-.078.236-.147.345-.234-.251-.12-.667-.297-.95-.297-.428 0-.537.234-1.006.234s-.676-.266-1.143-.266c-.467 0-.625.344-1.069.344-.444 0-.632-.375-1.179-.375-.321 0-.698.134-.957.245.149.13.315.237.479.349h5.48zm-1.595.265c-.531 0-.781.453-1.141.453s-.674-.469-1.087-.469c-.248 0-.538.138-.74.25.565.228 1.178.36 1.827.36.652 0 1.265-.139 1.831-.369-.182-.112-.427-.225-.69-.225z" fill="#083E9D"/><path d="M14.777 16.677l-1.399-.574c-.147.355-.239.735-.3 1.126l1.699.122v-.674zm1.02.419v.328l.949.068v-.007l-.949-.389zm5.303.252l1.821-.131c-.065-.409-.163-.807-.321-1.177l-1.5.616v.692zm-.969-.294l-.853.35.003.074.85-.061v-.363zm1.562-2.399l-.593.518v.845l1.146-.6c-.163-.271-.341-.53-.553-.763zm-1.562 1.363l-.875.763.007.199.868-.455v-.507zm-3.4.903l-.934-.815v.57l.941.497-.007-.252zm-1.954-1.704l-.543-.473c-.216.249-.398.523-.561.81l1.104.583v-.92zm5.354-.013c0-.152.206-.24.427-.261l.69-.715c-.246-.208-.508-.396-.79-.557l-1.229 2.127c.003.172.009.341.014.51l.889-.922-.001-.182zm-4.334-.188v.46l.921 1.002-.014-.497-1.294-2.238c-.256.156-.495.335-.72.529l.537.584c.273-.035.57.008.57.16zm3.424-.146l.691-1.468c-.265-.112-.536-.211-.822-.275l-.277 1.123s.583.021.458.042c-.033.005-.047.239-.05.578zm-2.594-1.655c-.211.061-.407.152-.605.238l.652 1.462-.047-1.7zm-1.85 4.672l-1.761-.047c-.006.053-.016.105-.016.16 0 .198.032.388.058.578h1.719v-.691zm6.323.691h1.842c.026-.19.058-.38.058-.578 0-.055-.01-.107-.016-.16l-1.884.069v.669z" fill="#FF9D11"/><path d="M15.047 15.297v3.578c0 .484.266 1.641 1.031 1.641 1.047 0 1.386-1.297 1.386-1.297s-.755.664-1.291.453c-.536-.211-.573-.531-.573-1.234v-3.052c.001-.277-.553-.339-.553-.089zm5.855 0v3.578c0 .484-.266 1.641-1.031 1.641-1.047 0-1.386-1.297-1.386-1.297s.755.664 1.29.453c.536-.211.573-.531.573-1.234v-3.052c.001-.277.554-.339.554-.089zm-2.09 1.997l-1.797-.551v-2.868c0-.844.646-1.26 1.797-.859-1 .094-1.318.936 0 1.562v2.716z" fill="#CE1126"/><path d="M20 18.711c0 .073-.06.133-.133.133h-3.859c-.073 0-.133-.06-.133-.133 0-.073.06-.133.133-.133h3.859c.073 0 .133.06.133.133zm-2.984.702h-.893l.383-.507h.893zm1.853 0h.893l-.383-.507h-.894zm-2.211-1.116l-.223-.243.222-.242c.04-.043.025-.102-.034-.131-.058-.029-.139-.017-.179.027l-.101.109v-.149c0-.035-.028-.063-.063-.063s-.063.028-.063.063v.149l-.1-.109c-.04-.044-.121-.056-.179-.027-.059.029-.074.088-.034.131l.222.242-.223.243c-.04.043-.024.102.034.132.059.028.138.016.179-.028l.164-.179.164.179c.041.044.121.056.179.028.059-.03.074-.089.035-.132zm.828 0l-.223-.243.222-.242c.04-.043.025-.102-.034-.131-.058-.029-.139-.017-.179.027l-.101.109v-.149c0-.035-.028-.063-.063-.063s-.063.028-.063.063v.149l-.1-.109c-.04-.044-.121-.056-.179-.027-.059.029-.074.088-.034.131l.222.242-.223.243c-.04.043-.024.102.034.132.059.028.138.016.179-.028l.164-.179.164.179c.041.044.121.056.179.028.059-.03.075-.089.035-.132zm.829 0l-.223-.243.222-.242c.04-.043.025-.102-.034-.131-.058-.029-.139-.017-.179.027l-.101.11v-.149c0-.035-.028-.063-.063-.063s-.063.028-.063.063v.149l-.1-.109c-.04-.044-.121-.056-.179-.027-.059.029-.074.088-.034.131l.222.242-.223.243c-.04.043-.024.102.034.132.059.028.138.016.179-.028l.164-.179.164.179c.041.044.121.056.179.028.059-.031.075-.09.035-.133zm.831 0l-.223-.243.222-.242c.04-.043.025-.102-.034-.131-.058-.029-.139-.017-.179.027l-.101.109v-.149c0-.035-.028-.063-.063-.063s-.063.028-.063.063v.149l-.1-.109c-.04-.044-.121-.056-.179-.027-.059.029-.074.088-.034.131l.222.242-.223.243c-.04.043-.024.102.034.132.059.028.138.016.179-.028l.164-.179.164.179c.041.044.121.056.179.028.059-.03.075-.089.035-.132zm.828 0l-.223-.243.222-.242c.04-.043.025-.102-.034-.131-.058-.029-.139-.017-.179.027l-.101.109v-.149c0-.035-.028-.063-.063-.063s-.063.028-.063.063v.149l-.1-.109c-.04-.044-.121-.056-.179-.027-.059.029-.074.088-.034.131l.222.242-.223.243c-.04.043-.024.102.034.132.059.028.138.016.179-.028l.164-.179.164.179c.041.044.121.056.179.028.059-.03.075-.089.035-.132z" fill="#630810"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..2d20ed8e796e20c5a45cf471c4798ed0f3f42c6e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#CE1126" d="M34.618 30.002C35.458 29.269 36 28.202 36 27V9c0-2.209-1.791-4-4-4H4c-1.006 0-1.915.384-2.618.998l33.236 24.004z"/><path d="M7.721 13.536l.383 1.316h1.324l-1.045.804.383 1.279-1.045-.805-1.045.768.383-1.242-1.045-.804h1.289zm-4.014 5.133l.383 1.314h1.324l-1.045.804.383 1.279-1.045-.803-1.045.767.383-1.243L2 19.983h1.289zm4.014 6.933l.383 1.315h1.324l-1.045.804L8.766 29l-1.045-.804-1.045.767.383-1.242-1.045-.804h1.289zm1.792-2.794l.192.657h.662l-.523.403.192.639-.523-.403-.522.384.191-.62-.522-.403h.644zm2.203-4.504l.383 1.315h1.324l-1.045.804.383 1.279-1.045-.804-1.045.767.383-1.242-1.045-.804h1.289z" fill="#FFF"/><path fill="#FCD116" d="M22.723 12.734c-.309.399-1.039-.401-1.914-.419-.875-.019-1.496.838-1.75 1.13-.256.292-1.077 1.823-1.059 1.988.02.164.512-.457.693-.566.017.219-.201.475-.146.547.055.074.639-.438.84-.455.055.146-.109.291-.055.51.072.074.4-.364.619-.455.037.164-.201.474-.072.674.09.019.639-.619.82-.692.182-.073-.092.602 0 .657.164-.109.674-.693.838-.766.164-.073-.018.747.055.747.201-.145.711-.838.766-.947.055-.109-.055 1.057.512 1.677.566.62 1.422 1.331 1.514 1.331.109-.2-.037-.62.055-.602.256.273.729.675.838.675s-.072-.438.074-.438c.291.273 1.129 1.35 2.771 1.842-.109-.311-.348-.584-.365-.729.109.018.492.2.564.183.074-.019-.801-1.095-.748-1.24.201-.019.293.109.365.018-.09-.146-.857-1.003-.857-1.203 0-.201.238.036.311 0 .074-.037-.291-.802-.219-.894.072-.09.875.492 1.076.492.201 0 .055-.711.147-.747.09-.036.766.383.91.383.146 0 .129-.31.184-.274.055.036 1.641 1.623 1.094 3.482-.547 1.331-1.641 2.042-3.246 1.459.092.146.949.856 1.879.602.93-.255 2.061-.984 1.934-2.808-.129-1.824-.73-2.079-.82-2.352-.094-.273.145.073.344.145.203.074-.035-.383-.09-.583-.055-.2.602.419.766.474.164.055-.383-1.495-.547-1.604-.164-.109.164.037.273.073.109.036-1.004-1.696-1.24-1.696s.201-.091.328-.091-1.275-1.13-1.514-1.13c-.236 0 .512-.292.584-.311.127.019-1.623-.93-3.191.019-.09-.073.738-.648.766-.894.01-.063-.273-.2-.291-.273-.018-.073.438-.292.455-.456-.109-.146-.309-.091-.418-.127-.027-.137.383-.475.346-.621-.027-.082-.328-.109-.4-.055-.074.055.192-.383.145-.51-.035-.055-.182-.018-.328.018-.09-.018.475-.802.365-.912-.109-.109-1.641.802-2.205 1.823-.566 1.021-.129 1.842-.201 2.188-.072.346-.164.693-.4.693-.238 0-.785-.365-.967-.547-.184-.183-.219-.31-.475-.383-.256-.073-.84.146-1.059.164-.219.019-1.074-.164-1.129-.109-.055.055.838.383 1.039.493.199.109.219.254.363.346.143.09 1.512.491 1.073 1.056zm5.343 2.571c.438.438 3.391 2.407 3.391 4.814s-2.152 2.334-2.772 2.261c.693.584 3.318.475 3.318-2.261 0-2.407-3.391-4.814-3.828-5.033-.437-.219-.548-.219-.109.219z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..e9f011d36046015e6801b9149d82198fd3287dd2 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#0038A8" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M1.313 29.945l17.718-11.881L1.33 6.041C.519 6.773 0 7.822 0 9v18c0 1.171.512 2.214 1.313 2.945z"/><path fill="#FCD116" d="M16.07 16.52l.043 1.153 1.115.294-1.083.396.065 1.152-.712-.908-1.075.417.643-.957-.73-.893 1.11.316zM1.603 7.982l.866.763.98-.607-.458 1.059.88.745-1.148-.108-.437 1.066-.251-1.125-1.151-.086.993-.586zm.431 17.213l.574 1 1.124-.257-.774.854.594.989-1.052-.472-.757.871.123-1.148-1.061-.45 1.128-.238zM10 18c0 1.657-1.343 3-3 3s-3-1.344-3-3c0-1.657 1.343-3 3-3s3 1.343 3 3z"/><path d="M7.595 12.597l-.157 2.648-.244-.036.085-3.074L7 11.953l-.279.182.085 3.074-.244.036-.157-2.648-.353.218.329 2.697h1.238l.329-2.697zm-1.19 10.806l.157-2.648.244.036-.086 3.074.28.182.279-.182-.085-3.074.244-.036.157 2.648.353-.218-.329-2.698H6.381l-.329 2.698zm-3.647-2.004l1.985-1.759.146.196-2.233 2.113.068.327.327.069 2.113-2.235.197.147L3.6 22.242l.404.094 1.675-2.139-.438-.438-.438-.438-2.139 1.675zm8.484-6.799l-1.985 1.761-.146-.197 2.233-2.113-.068-.327-.327-.069-2.113 2.234-.197-.146 1.761-1.985-.404-.094-1.675 2.139.438.438.438.438 2.139-1.675zm-9.645 2.805l2.649.157-.037.244-3.074-.086-.182.28.182.279 3.074-.085.037.244-2.649.157.218.353 2.697-.329V17.38l-2.697-.328zm10.806 1.19l-2.649-.157.037-.244 3.074.085.182-.279-.182-.28-3.074.086-.037-.244 2.649-.157-.218-.353-2.698.328v1.239l2.698.329zM3.6 13.758l1.761 1.985-.197.146-2.113-2.234-.327.069-.068.327 2.233 2.113-.146.197L2.758 14.6l-.094.404 2.139 1.675.438-.438.438-.438-1.675-2.139zm6.8 8.484l-1.761-1.985.197-.147 2.113 2.235.327-.069.068-.327-2.233-2.113.146-.196 1.985 1.759.094-.403-2.139-1.675-.438.438-.438.438 1.675 2.139z" fill="#FCD116"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..a718df6c23547929a1df280922aca133e2d1febf --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#004600" d="M32 5H9v26h23c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4zm-9.5 20.472c-4.142 0-7.5-3.358-7.5-7.5 0-3.72 2.711-6.799 6.263-7.39-2.22 1.034-3.763 3.279-3.763 5.89 0 3.59 2.91 6.5 6.5 6.5 2.611 0 4.856-1.543 5.89-3.763-.591 3.553-3.67 6.263-7.39 6.263zm5.11-10.424l-1.213 2.022-.208-2.349-2.298-.528 2.17-.924-.207-2.349 1.548 1.779 2.17-.924-1.212 2.023 1.548 1.779-2.298-.529z"/><path fill="#EEE" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h5V5H4z"/><path fill="#FFF" d="M29.572 11.775l-2.17.924-1.548-1.779.207 2.349-2.17.924 2.298.528.208 2.349 1.213-2.022 2.298.529-1.548-1.779z"/><path fill="#FFF" d="M24 22.972c-3.59 0-6.5-2.91-6.5-6.5 0-2.611 1.543-4.856 3.763-5.89-3.552.592-6.263 3.671-6.263 7.39 0 4.142 3.358 7.5 7.5 7.5 3.72 0 6.799-2.711 7.39-6.263-1.034 2.221-3.279 3.763-5.89 3.763z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..8169875a70804c882871078f320982373de59cf0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#DC143C" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0v9z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..dc55c02f1fb155b299dde88661fb72bd97b39e15 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0092C8" d="M32 5H9.75v26H32c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCC4D" d="M33.75 13.719c-1.188-.406-2.531-.469-2.531-.469l-.875 1.719s2.594.055 2.594.215c0 .11-.59 1.088-.959 1.689-.189-.059-.421-.091-.697-.091-1.125 0-1.562.25-2.031.938-.469.688 0 .969 0 .969s-.58 1.287-2.752 2.002l.713-2.463c.813-.136 1.508.274 1.508.274s-.531-1.562.125-3.906c.655-2.346 3.092-4.096 3.092-4.096l-2.726.806.694-2.399s.344-.75 0-.969c-.224-.142-.34.162-.396.395-.239-.068-.657-.129-1.104.074-.688.312-2.281-.139-2.281-.139s.625.701 1.094.826c-.5.25-1.469.156-1.469.156s1.188.688 1.984.438c.529-.166 1.114-.18 1.451-.171l-.583 1.97-2.478.733s-1.125.906-1.5 3.562c-.375 2.656.969 4.625.969 4.625s-.141-1.283.934-1.918l-.706 2.39c-.299.07-.615.132-.964.177-.008-.019-1.295-2.907-1.077-5.337.219-2.438 2.344-4.928 2.344-4.928l-2.781 1.011.978-3.396s.615-.406.084-.656c-.529-.25-.427.55-.427.55-.246-.048-.596-.063-.968.106-.688.312-2.281-.139-2.281-.139s.625.701 1.094.826c-.5.25-1.469.156-1.469.156s1.188.688 1.984.438c.514-.161.976-.185 1.241-.182l-.83 2.512-2.53.919s-.438.625-1.344 2.438c-.906 1.812.375 4.406.375 4.406s.378-.574 1.178-.738l-.485 1.47C17.935 19.59 17.5 18 17.5 18s.344-.062.344-.437c0-.361-.154-.546-1.195-.56l.252-.9c.455.268.787.679.787.679s-.438-1.625.469-3.25c.906-1.625 3.031-3.031 3.125-3.031.05 0-1.553.456-3.055.88l.627-2.236s.459-.675-.041-.831-.419.706-.419.706c-.235-.03-.536-.02-.853.124-.688.312-2.281-.139-2.281-.139s.625.701 1.094.826c-.5.25-1.469.156-1.469.156s1.187.688 1.984.438c.461-.144.889-.177 1.171-.18l-.374 1.293-1.979.557s-.406.625-.875 2.125.344 2.719.344 2.719.25-1.062 1.031-1.062c.074 0 .147.015.219.029l-.32 1.111c-.748.054-.867.259-.867.578 0 .375.406.406.406.406s-.094.656.156 1.469c.25.812-.312.656-1.25.188-.062-.03-.123-.047-.184-.069l.006-.006L12 18.531s-.5-.719-.75-.219.562.615.562.615l1.348.68c-.263.137-.394.357-.254.58.312.5 1 0 2.406 1.375.474.463 1.51 1.576 3.024 2.539.271.173 13.274-.395 13.182-.629-.227-.576-.719-1.611-1.394-1.878 1.5-1.344 1.594-2.906 1.594-2.906s.406 0 .75-.688c.172-.345.156-.649-.044-.868.478-.928 1.653-3.205 1.95-3.725.376-.657.001-.969-.624.312zm-10.5 7.437c-.995 0-1.816-.134-2.504-.341l.512-1.774c.101.017.195.023.305.053 1.589.436 3.285 1.953 3.295 1.962-.485.063-1.017.1-1.608.1z"/><path d="M34.688 23.031c-.781-.562-1.5-.375-1.656.17s-.875.299-1.656-.264-1.312-.469-1.469.156-1.031.562-1.844-.031c-.812-.594-1.625-.156-1.938.29-.312.446-.562.491-1.566-.134s-1.715-.25-1.996.281c-.281.531-.688.406-1.531-.17-.844-.576-1.625-.361-2.031 0-.406.361-.969.482-1.719 0-.75-.482-1.344-.455-1.719-.068s-.812.957-2 .036-1.812-.142-2.406.265c-.595.407-1.157-.624-1.157-.624v.656s.562 1.031 1.156.625c.594-.406 1.219-1.186 2.406-.265s1.625.351 2-.036.969-.414 1.719.068c.75.482 1.312.361 1.719 0 .406-.361 1.188-.576 2.031 0 .844.576 1.25.701 1.531.17.281-.531.992-.906 1.996-.281s1.254.58 1.566.134c.312-.446 1.125-.884 1.938-.29.812.594 1.688.656 1.844.031s.688-.719 1.469-.156 1.5.809 1.656.264.875-.732 1.656-.17S36 24 36 24v-.656s-.531.25-1.312-.313z"/><path fill="#BBDDF5" d="M34.688 23.688c-.781-.562-1.5-.375-1.656.17s-.875.299-1.656-.264-1.312-.469-1.469.156-1.031.562-1.844-.031c-.812-.594-1.625-.156-1.938.29-.312.446-.562.491-1.566-.134s-1.715-.25-1.996.281c-.281.531-.688.406-1.531-.17-.844-.576-1.625-.361-2.031 0-.406.361-.969.482-1.719 0-.75-.482-1.344-.455-1.719-.068s-.812.957-2 .036-1.812-.142-2.406.265c-.595.406-1.157-.625-1.157-.625v.625s.562 1.031 1.156.625c.594-.406 1.219-1.186 2.406-.265s1.625.351 2-.036.969-.414 1.719.068c.75.482 1.312.361 1.719 0 .406-.361 1.188-.576 2.031 0 .844.576 1.25.701 1.531.17.281-.531.992-.906 1.996-.281s1.254.58 1.566.134c.312-.446 1.125-.884 1.938-.29.812.594 1.688.656 1.844.031s.688-.719 1.469-.156 1.5.809 1.656.264.875-.732 1.656-.17 1.313.312 1.313.312V24s-.531.25-1.312-.312zm-22.532 2.281c.53-.601 1.344-.531 1.969 0s.906.129 1.5-.217 1.437-.367 1.625.128-.781-.179-1.375.346c-.594.524-1.556.68-2.25 0s-1.938.274-1.469-.257zm6.969.12c.571.194 1.344.255 2.031-.183s1.188-.233 1.938.368 1.312.399 2 0 1.25-.899 2.219-.462c.969.438 1.438.482 1.812.335.375-.148 0 .509-.938.352-.938-.156-1.594-.75-2.438-.188-.844.562-1.938 1.088-2.812.341-.875-.747-1.344-.644-1.875-.32-.531.323-1.125.354-1.438.198-.312-.155-.959-.597-.499-.441zm12.031 0c.362.219.75.276 1.125 0s.75-.052 1.219.211c.469.263.562.558 0 .379-.562-.179-.781-.577-1.219-.331-.438.246-.906.316-1.125 0-.219-.317-.271-.423 0-.259zm-16.094 1.474c.514-.272 1.344-.656 1.937 0 .594.656.875.312 1.344 0 .469-.312.875-.688 1.594-.219.719.469 1.062.34 1.344.185.281-.154.531-.06 0 .252s-1.062.281-1.469-.031c-.406-.312-.75-.469-1.281.062-.531.531-1.219.69-1.719.189-.5-.501-.656-.542-1.156-.287-.5.255-1.108.121-.594-.151zm9.563.151c.629-.332 1.469-.901 2.156-.245.688.656 1.094.348 1.656-.029.562-.377 1.094-.922 1.906-.274.812.647 1.344.585 1.75.397.406-.188.219.172-.281.289-.5.117-1.188.117-1.656-.289-.469-.406-.906-.385-1.406.151-.5.536-1.75.686-2.219.205-.469-.481-1.062-.2-1.5-.013s-1.034.14-.406-.192zM11.5 28.21c.373-.344.875-.21 1.5.415s.906.5 1.469.188 1.312-.375 1.625-.031c.312.344.188.453-.188.289-.375-.164-.735-.258-1.243.18-.507.438-1.414.531-1.851 0-.438-.531-.688-.844-1.031-.719-.344.124-.781.138-.281-.322zm8.656.609c.364-.391 1.094-.712 1.812 0 .719.712.844.618 1.406.243s1.219-.805 1.906-.168c.688.637.969.512 1.562.168.594-.344 1.125-.648 1.781-.168.656.48 1.156.605 1.719.262.562-.344.686-.191.156.25-.438.363-1.231.5-1.781-.031-.689-.665-1.125-.469-1.688-.062-.562.406-1.438.5-1.938-.031s-.844-.375-1.312 0c-.469.375-1.275.758-1.844-.031-.569-.789-1.125-.438-1.406-.281-.279.155-.904.419-.373-.151z"/><path fill="#CA0000" d="M0 22v5c0 2.209 1.791 4 4 4h6v-9H0z"/><path fill="#FFCC4D" d="M8.141 24.641c-.406.156-.781.109-1.281-.462-.101-.115-.212-.191-.326-.249.241.057.549.172.81.195.516.047 1.031-.328 1.031-.328s-.234-.188-.859-.359c-.511-.141-1.368-.036-1.666.368-.242.014-.474.063-.662.086-.326.039-.703-.109-.703-.109s-.062-.766-.938-.766c-.766 0-.781.703-.781.703s-.391.188-.391-.363-.438-.52-.82-.52-.477-.023-.477.477.281.406.453.562c0 0 .172.875 1.203.75.046.085.062.297.062.297s-.187.052-.484-.016c-.443-.101-.766-.156-.766.453s.641.438 1.547.438.953-.562.953-.562.422-.125.922-.094c-.125.109-.054.374.062.5.243.262.688.156 1.031.156s.5-.266.422-.625c.328.234 1.234-.203 1.125 0-.109.203.156.703.844.422.689-.283.095-1.111-.311-.954z"/><ellipse cx="3.367" cy="24.25" rx=".289" ry=".297"/><path d="M3.367 23.695c0 .073-.1.133-.223.133s-.223-.059-.223-.133c0-.073.1-.133.223-.133.124.001.223.06.223.133z"/><ellipse cx="3.656" cy="23.695" rx=".223" ry=".133"/><path fill="#FFCC4D" d="M8.141 28.156c-.406.156-.781.109-1.281-.462-.101-.115-.212-.191-.326-.249.241.058.549.172.81.195.516.047 1.031-.328 1.031-.328s-.234-.188-.859-.359c-.511-.141-1.367-.035-1.666.368-.242.014-.474.063-.662.086-.326.039-.703-.109-.703-.109s-.062-.766-.938-.766c-.766 0-.781.703-.781.703s-.391.188-.391-.363c0-.551-.438-.52-.82-.52s-.477-.023-.477.477.281.406.453.562c0 0 .172.875 1.203.75.046.085.062.297.062.297s-.187.052-.484-.016c-.443-.101-.766-.156-.766.453s.641.438 1.547.438.953-.562.953-.562.422-.125.922-.094c-.125.109-.054.374.062.5.243.262.688.156 1.031.156s.5-.266.422-.625c.328.234 1.234-.203 1.125 0-.109.203.156.703.844.422.689-.282.095-1.11-.311-.954z"/><path d="M3.656 27.766c0 .164-.129.297-.289.297-.16 0-.289-.133-.289-.297 0-.164.129-.297.289-.297.16 0 .289.133.289.297zm-.289-.555c0 .073-.1.133-.223.133s-.223-.06-.223-.133c0-.073.1-.133.223-.133.124 0 .223.06.223.133zm.512 0c0 .073-.1.133-.223.133s-.223-.06-.223-.133c0-.073.1-.133.223-.133s.223.06.223.133z"/><path fill="#EEE" d="M0 14h10v8H0z"/><path d="M2.079 17.319l-.278-.421c-.011-.347-.063-.617-.129-.617s-.118.269-.129.617l-.278.421c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257s.075-.103.099-.257h.191c.129.001.18-.077.118-.173zm-.274-1.469c0 .237-.06.214-.133.214-.073 0-.133.023-.133-.214 0-.236.06-.428.133-.428.074 0 .133.192.133.428zm.194.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.192.133-.428.133zm-.653 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm3.877.989l-.278-.421c-.011-.347-.063-.617-.129-.617s-.118.269-.129.617l-.277.421c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257s.075-.103.099-.257h.191c.128.001.179-.077.117-.173zm-.274-1.469c0 .237-.06.214-.133.214-.073 0-.133.023-.133-.214 0-.236.06-.428.133-.428.074 0 .133.192.133.428zm.194.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.192.133-.428.133zm-.653 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm3.951.989l-.278-.421c-.011-.347-.063-.617-.129-.617s-.118.269-.129.617l-.278.421c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257.04 0 .075-.103.099-.257h.191c.13.001.181-.077.118-.173zm-.273-1.469c0 .237-.06.214-.133.214-.073 0-.133.023-.133-.214 0-.236.06-.428.133-.428.073 0 .133.192.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133.001.074-.191.133-.428.133zm-.652 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm-1.724-1.632c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257s.075-.103.099-.257h.191c.127 0 .178-.078.116-.173l-.277-.421c-.003-.102-.011-.193-.021-.277h-.216c-.01.084-.017.175-.02.277l-.278.421zm-3.141 0c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257s.075-.103.099-.257h.191c.127 0 .178-.078.116-.173l-.278-.421c-.002-.102-.01-.193-.019-.277h-.217c-.01.084-.017.175-.02.277l-.278.421zm-2.492 3.73c0 .237-.06.214-.133.214s-.133.023-.133-.214c0-.236.06-.428.133-.428s.133.192.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133.001.074-.191.133-.428.133zm-.326-3.779c.04 0 .075-.103.099-.257H.51c.127 0 .178-.078.116-.173l-.278-.421C.345 14.175.337 14.084.327 14H.111c-.01.084-.017.175-.02.277L0 14.415v.457h.12c.025.154.059.257.099.257zm0 5.199c.04 0 .075-.103.099-.258H.51c.127 0 .178-.078.116-.173l-.278-.421c-.01-.348-.063-.617-.129-.617s-.118.269-.129.617l-.09.138v.456h.12c.024.155.059.258.099.258zm-.112-1.553c0-.059.009-.107-.107-.124v.249c.115-.018.107-.066.107-.125zm3.565 1.123l-.278-.421c-.01-.348-.063-.617-.129-.617s-.118.269-.129.617l-.276.421c-.062.095-.011.173.116.173h.191c.024.155.059.258.099.258s.075-.103.099-.258h.191c.128-.001.179-.079.116-.173zm-.273-1.47c0 .237-.06.214-.133.214-.073 0-.133.023-.133-.214 0-.236.06-.428.133-.428.073 0 .133.192.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.191.133-.428.133zm-.652 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm3.889.99l-.278-.421c-.01-.348-.063-.617-.129-.617s-.118.269-.129.617l-.278.421c-.062.095-.011.173.116.173h.191c.024.155.059.258.099.258s.075-.103.099-.258h.191c.129-.001.18-.079.118-.173zm-.274-1.47c0 .237-.06.214-.133.214-.073 0-.133.023-.133-.214.001-.236.06-.428.133-.428.074 0 .133.192.133.428zm.194.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.192.133-.428.133zm-.653 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm3.699-.48c0 .237-.06.214-.133.214s-.132.024-.132-.214c0-.236.059-.428.133-.428s.132.192.132.428zm-.591-3.73c-.062.095-.011.173.116.173h.191c.024.155.059.257.099.257s.075-.103.099-.257H9.9c.049 0 .075-.02.1-.039v-.158l-.262-.397c-.003-.102-.01-.193-.02-.277h-.216c-.01.084-.017.175-.02.277l-.278.421zm.459 4.161c-.066 0-.118.269-.129.617l-.278.421c-.062.095-.011.173.116.173h.191c.024.155.059.258.099.258s.075-.103.099-.258h.191c.023 0 .029-.014.047-.018v-.259l-.209-.316c-.009-.348-.062-.618-.127-.618zm.112-.084c0 .073-.023.133.214.133l.011-.001v-.264l-.011-.001c-.238.001-.214.06-.214.133zm-.439.133c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zM7.934 22h.238c-.019-.271-.064-.469-.119-.469-.055 0-.1.198-.119.469zm.252-.9c0 .238-.06.215-.133.215s-.133.023-.133-.215c0-.236.06-.428.133-.428s.133.191.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133.001.074-.191.133-.428.133zm-.652 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm-2.744-.48c0 .238-.06.215-.133.215-.073 0-.133.023-.133-.215 0-.236.06-.428.133-.428.073 0 .133.191.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.191.133-.428.133zm-.652 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133 0 .074.192.133.428.133zm.207.42h.238c-.019-.271-.064-.469-.119-.469s-.1.198-.119.469zm-3.215 0h.238c-.019-.271-.064-.469-.119-.469s-.1.198-.119.469zm.252-.9c0 .238-.06.215-.133.215-.073 0-.133.023-.133-.215 0-.236.06-.428.133-.428.073 0 .133.191.133.428zm.193.48c-.237 0-.214-.06-.214-.133 0-.073-.023-.133.214-.133.236 0 .428.059.428.133 0 .074-.192.133-.428.133zm-.652 0c.237 0 .214-.06.214-.133 0-.073.023-.133-.214-.133-.236 0-.428.059-.428.133-.001.074.191.133.428.133z" fill="#292F33"/><path fill="#DC241F" d="M0 14V9c0-2.209 1.791-4 4-4l1 1 1-1h4v9H6l-1-1-1 1H0z"/><path fill="#009543" d="M10 6.49V5h-.567L6 8.09l-1 .89-1-.89-2.476-2.229-.002-.001-.001.001c-.39.308-.722.689-.975 1.12l.003.003L2.766 8.98l1.23 1.01L2.766 11 0 13.49V14h1.655L4 11.89 5 11l1 .89L8.345 14H10v-.51L7.234 11 5.997 9.99l1.237-1.01L10 6.49z"/><path fill="#EEE" d="M6 8.979V5H4v3.979H.001L0 9v2h4v3h2v-3h4V8.979H6z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..234f53f413ed797c567ff497ce4f4ba36354f064 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#DD2E44" d="M30.464 20.153c0 .49-.561.888-1.253.888-.691 0-1.252-.397-1.252-.888s.561-.889 1.252-.889c.692.001 1.253.398 1.253.889z"/><path fill="#009A67" d="M24.744 18.771c0 .421 1.267.916 2.286-.326 1.02-1.242.723.448.305.71-.418.262-.865.894-1.767.797-.901-.098-1.131-.454-1.339-.974-.208-.52.515-.207.515-.207z"/><path fill="#FFF100" d="M24.926 16.122c.104.256-.018.547-.274.652l-.926.378c-.256.105-.548-.018-.652-.273-.104-.256.018-.547.274-.652l.926-.379c.255-.105.547.018.652.274zm7.972 2.816c-.15.232-.419.324-.6.207l-1.31-.85c-.181-.117-.206-.399-.056-.631.15-.232.419-.325.601-.208l1.31.85c.18.118.206.4.055.632z"/><path fill="#FFF100" d="M33.068 18.63c.074.266-.081.542-.347.616-.267.074-.542-.081-.616-.347l-.537-1.927c-.074-.266.081-.542.347-.616.267-.074.542.081.616.347l.537 1.927z"/><path fill="#FFF100" d="M33.479 18.852c0 .277-.224.5-.5.5s-.5-.223-.5-.5c0-.276.224-.5.5-.5s.5.224.5.5z"/><path fill="#009A67" d="M25 18.625c0 .207-.224.375-.5.375s-.5-.167-.5-.375v-2.25c0-.208.224-.375.5-.375s.5.167.5.375v2.25z"/><path fill="#009A67" d="M25.719 17.587c.166.221.167.499.003.622l-1.185.889c-.163.123-.431.043-.597-.178-.166-.222-.167-.5-.003-.623l1.185-.889c.163-.122.431-.043.597.179z"/><path fill="#009A67" d="M24.535 18.615c0 .272-.239.493-.535.493s-.536-.221-.536-.493.24-.493.536-.493.535.221.535.493zm9.311-1.614c-.109.258-.657.271-1.225.029-.566-.242-.937-.646-.826-.904.109-.258.657-.271 1.225-.029.566.241.936.646.826.904z"/><path fill="#D4D5D6" d="M27.805 17.255c-.58.376-1.357 1.076-1.357 1.076l.433.055s.529.554.621 1.079c.092.524-.118.169-.162.575-.044.406.184.68.184.68s.628-.212 1.04-.528c.412-.316.688-.79.923-.547.235.243.207.355.207.355H30s-.506-.494-.498-.777c.008-.283-.443-1.689-.443-1.689l-1.254-.279zm-.681-1.261s.475-.361.425-.316c-.05.045.537.25.894.104.356-.146 1.052-.849 1.223-.745.171.103-.863.709-.431.805s.568-.268.835-.4.685-.148.281.119c-.403.267-.959 1.422-.959 1.422l-1.63-.128-.427-.313-.211-.548z"/><path fill="#009A67" d="M29.905 17.203c0 .23-.602.417-1.344.417-.741 0-1.343-.187-1.343-.417 0-.23.601-.417 1.343-.417.743-.001 1.344.186 1.344.417zm-4.439 4.943c-.069.22-.57.255-1.12.081-.549-.174-.938-.491-.869-.71.07-.22.571-.256 1.121-.082.548.174.937.493.868.711zm7.605 1.623c-.03.17-.526.225-1.108.122-.582-.101-1.03-.322-1-.491.029-.169.525-.224 1.107-.121.582.101 1.031.322 1.001.49z"/><path fill="#009A67" d="M32.082 23.851c-.157.757-.423 1.34-.592 1.305-.169-.035-.179-.676-.021-1.432.157-.756.422-1.34.591-1.305.169.035.179.677.022 1.432zm-2.513-6.514c.274.715 1.049 2.129 1.788 2.139.739.01.837-.31.837-.31s.027.562-.645.666c-.672.104-1.054-.228-.931-.113.123.114.395.374 1.021.538.626.164 1.696.357 1.664.956-.032.599-.45.831-.408.567.042-.264-.429-.744-1.256-.93-.827-.186-1.763-.637-2.172-1.977-.409-1.341-.076-.123-.076-.123s-.81.247-.805-.157.628-.192.5-.706-.432-.865-.13-.756c.303.11.613.206.613.206zm-2.038 1.83c-.406.624-1.585 1.502-1.965 1.914-.38.412-.655 1.191-.736 1.708-.081.517.074 1.313.362.419s.798-1.241 1.313-1.818c.516-.577.866-.959 1.055-1.344.189-.385-.029-.879-.029-.879z"/><path fill="#FFF100" d="M29.955 19.589c.127.419.114.793-.029.836-.143.043-.361-.261-.487-.68-.127-.419-.113-.794.03-.837.142-.043.36.262.486.681zm-3.539-.006c0 .127-.308.229-.688.229-.38 0-.688-.103-.688-.229 0-.127.308-.229.688-.229.38 0 .688.102.688.229zm-1.101 4.145c.149.772.127 1.425-.048 1.458-.174.033-.436-.564-.583-1.337-.149-.772-.127-1.426.048-1.459.174-.034.436.565.583 1.338z"/><path fill="#FFF100" d="M25.821 23.585c0 .156-.442.281-.986.281-.545 0-.987-.125-.987-.281 0-.155.442-.281.987-.281.544 0 .986.126.986.281zm.225 2.193c.188.382.24.744.111.807-.127.063-.384-.196-.574-.578-.188-.382-.239-.745-.111-.807.128-.064.384.196.574.578zm5.431.244c-.277.396-.65.614-.834.486-.185-.129-.108-.555.169-.951.277-.397.65-.615.835-.486.183.128.107.554-.17.951zm2.279-4.598c.124.203-.253.66-.844 1.021-.59.361-1.169.488-1.293.285-.125-.204.252-.661.842-1.022.591-.361 1.17-.488 1.295-.284zm-10.113-.21c.281-.662 1.153-1.016 1.73-1.168.576-.152.705-.325 1.171-.692.466-.367.354-.615.581-.449.227.166.417.243.198.553-.219.31-.983.966-1.479 1.157-.495.191-1.469.601-1.531.712-.063.111-.764.108-.67-.113z"/><path fill="#4D8FCC" d="M25.88 20.192h4.775v3.632c0 1.547-2.388 3.154-2.388 3.154s-2.388-1.577-2.388-3.229l.001-3.557z"/><path fill="#009A67" d="M30.354 24.818l-2.059-4.078-2.218 3.83c.558 1.316 2.189 2.408 2.189 2.408s1.454-.988 2.088-2.16z"/><path fill="#FFF100" d="M26.072 24.312l.157.386 2.067-3.741 2.005 3.71.163-.412-2.125-4.063zm4.47-3.736c.333.549.942.386 1.204 1.312.262.927.123 1.931-.151 1.137s-.354-1.24-1.131-1.445c-.776-.205.078-1.004.078-1.004zm-4.976 4.797l-.194 1.158L26.416 26zm5.535.184l-.984.457 1.079.648z"/><path fill="#FFF100" d="M29.251 23.813c0 .103-.084.187-.186.187h-1.456c-.103 0-.187-.084-.187-.187s.084-.186.187-.186h1.456c.102 0 .186.084.186.186z"/><path fill="#FFF100" d="M28.428 25.738c0 .144-.038.262-.084.262h-.154c-.046 0-.084-.117-.084-.262v-2.477c0-.144.038-.262.084-.262h.154c.046 0 .084.117.084.262v2.477z"/><path fill="#FFF100" d="M27.049 24.83l.584.61-.102.125.659.435.901-.434-.192-.121.653-.492-.094.832-.239-.069-.943.796-.991-.841-.189.02z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..f4c2ace3679e733bf2841f615e1ce8382ee113bc --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA0B19" d="M32 5H4c-1.008 0-1.926.375-2.629.99L6.923 10H36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M13.846 15H36v-5H6.923z"/><path fill="#EA0B19" d="M18 18l-4.154 3H36v-6H13.846z"/><path fill="#EEE" d="M6.923 26H36v-5H13.846z"/><path fill="#EA0B19" d="M1.371 30.01c.703.615 1.621.99 2.629.99h28c2.209 0 4-1.791 4-4v-1H6.923l-5.552 4.01z"/><path fill="#0F55EC" d="M13.846 21L18 18l-4.154-3-6.923-5-5.552-4.01C.532 6.724 0 7.799 0 9v18c0 1.201.532 2.276 1.371 3.01L6.923 26l6.923-5z"/><path fill="#FFF" d="M8.187 18.838l2.313-1.675H7.641l-.888-2.726-.89 2.726H3l2.315 1.677-.89 2.723 2.325-1.684 2.325 1.684z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..6ce8ec769d8627f7a907b2779371cdc5c3222718 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#007229" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><path fill="#D21034" d="M1.351 6.004H1.35C.522 6.737 0 7.808 0 9v18c0 1.193.522 2.264 1.351 2.997L17.5 18 1.351 6.004z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..c1d4a84ff2deb07b29580948008227485bddb570 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#060" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#D52B1E" d="M32 5H15v26h17c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCC4D" d="M15 10c-4.419 0-8 3.581-8 8 0 4.418 3.581 8 8 8 4.418 0 8-3.582 8-8 0-4.419-3.582-8-8-8zm-6.113 4.594l1.602 1.602-2.46 1.23c.083-1.022.383-1.981.858-2.832zm-.858 3.979l4.4 2.207-2.706 1.804.014.021c-.96-1.097-1.583-2.492-1.708-4.032zM14 24.92c-.937-.134-1.813-.453-2.592-.92H14v.92zM14 23h-3.099L14 20.934V23zm0-3.268l-.607.405L9.118 18l2.116-1.058L14 19.707v.025zm0-1.439l-3.543-3.543 3.543.59v2.953zm0-3.992l-4.432-.713c1.084-1.333 2.65-2.253 4.432-2.508v3.221zm7.113.293c.475.851.775 1.81.858 2.833l-2.46-1.23 1.602-1.603zM16 11.08c1.782.256 3.348 1.175 4.432 2.508L16 14.301V11.08zm0 4.26l3.543-.591L16 18.293V15.34zm0 4.367l2.765-2.765L20.882 18l-4.274 2.137-.608-.405v-.025zm0 5.213V24h2.592c-.779.467-1.655.786-2.592.92zM16 23v-2.066L19.099 23H16zm4.264-.395l.014-.021-2.706-1.804 4.4-2.207c-.126 1.54-.749 2.935-1.708 4.032z"/><path fill="#D52B1E" d="M11 13v7c0 2.209 1.791 4 4 4s4-1.791 4-4v-7h-8z"/><path fill="#FFF" d="M12 14v6c0 1.656 1.343 3 3 3s3-1.344 3-3v-6h-6z"/><path fill="#829ACD" d="M13 17h4v2h-4z"/><path fill="#829ACD" d="M14 16h2v4h-2z"/><path fill="#039" d="M12 17h1v2h-1zm2 0h2v2h-2zm3 0h1v2h-1zm-3 3h2v2h-2zm0-6h2v2h-2z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..043f7a518ca1e54ac560d440eb6fae068b1aeaea --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4AADD6" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><circle fill="#FFDE00" cx="14.8" cy="18" r="8"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..c8e83dc3f6bbb63a136280eff3ecc0698975feb9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f5-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0038A8" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#D52B1E" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path d="M22 18c0 2.209-1.791 4-4 4s-4-1.791-4-4 1.791-4 4-4 4 1.791 4 4z"/><path fill="#EEE" d="M21.75 18c0 2.071-1.68 3.75-3.75 3.75s-3.75-1.68-3.75-3.75 1.679-3.75 3.75-3.75 3.75 1.679 3.75 3.75z"/><path d="M21.25 18c0 1.795-1.455 3.25-3.25 3.25s-3.25-1.455-3.25-3.25 1.455-3.25 3.25-3.25 3.25 1.455 3.25 3.25z"/><path fill="#EEE" d="M21.126 18c0 1.726-1.4 3.126-3.126 3.126s-3.124-1.4-3.124-3.126 1.399-3.124 3.124-3.124c1.726 0 3.126 1.399 3.126 3.124z"/><path fill="#99AAB5" d="M21.132 17.98c0-1.73-1.402-3.132-3.132-3.132s-3.132 1.402-3.132 3.132c0 .573.154 1.111.423 1.573l2.712-1.491 2.707 1.491c.268-.463.422-1 .422-1.573z"/><path d="M20.5 18c0 1.381-1.119 2.5-2.5 2.5s-2.5-1.119-2.5-2.5 1.12-2.5 2.5-2.5 2.5 1.119 2.5 2.5z"/><circle fill="#EEE" cx="18" cy="18" r="2.4"/><path fill="#FFAC33" d="M18 17.182l.184.565h.594l-.481.35.183.565-.48-.349-.48.349.183-.565-.481-.35h.594z"/><path fill="#007127" d="M18.497 16.517s.3-.07.476-.088c.176-.018.334.388.545.458.214.072.212.282.3.529.088.247.035.299.035.581s.158.423.123.634c-.035.211-.211.264-.316.405-.105.142-.018.317-.124.423-.105.105-.458.088-.581.194-.123.105-.352.264-.511.176-.158-.088-.493-.123-.493-.123s.088-.317.335-.423c.247-.105.352-.088.581-.158.229-.071.211-.177.37-.317.158-.141.176-.335.264-.476.089-.141.106-.247.071-.441-.036-.194-.107-.405-.177-.582-.07-.176-.229-.387-.335-.511-.105-.123-.563-.281-.563-.281z"/><path fill="#007127" d="M17.405 16.622s.175-.383 0-.405c-.705-.088-.846.546-1.057.616-.213.072-.247.423-.334.669-.088.247-.053.299-.053.582 0 .282.005.334.041.546.035.211.083.37.188.511.106.141.146.211.252.316.105.105.312.212.435.317.123.105.498.141.657.053.158-.088.435-.123.435-.123s-.118-.212-.364-.317c-.247-.105-.264-.193-.493-.264-.229-.071-.211-.177-.37-.317-.158-.141-.176-.335-.264-.476-.088-.141-.041-.176-.005-.37.035-.194.105-.352.176-.528.07-.176.247-.405.352-.528.105-.123.404-.282.404-.282z"/><path fill="#007127" d="M17.423 19.863l.229.158.299-.211.282.194.37-.141-.37.265-.264-.212-.282.194-.282-.159z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f6-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f6-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..f3e91d043d5380f28714acf87dd5d60d67e9bef9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f6-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8D1B3D" d="M32 5H11v26h21c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M11 28.111l5.295-1.444L11 25.222l5.295-1.444L11 22.333l5.295-1.444L11 19.444 16.295 18 11 16.556l5.295-1.444L11 13.667l5.295-1.444L11 10.778l5.295-1.445L11 7.889l5.295-1.444L11 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h7l5.295-1.444L11 28.111z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab1399fc14c0d279e3db26152dfd8171e295cc7c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#36F" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="red" d="M18 18L1.368 30.012l.001.001C2.072 30.628 2.993 31 4 31h28c1.008 0 1.929-.373 2.632-.988L18 18z"/><path fill="#FF0" d="M18 18.019l18 1.487v-2.975zM0 16.531v2.975l18-1.487zm2.405-11.2C1.531 5.711.82 6.394.404 7.247L18 18 2.406 5.33l-.001.001zm33.191 1.916c-.417-.853-1.129-1.536-2.003-1.917L18 18 35.596 7.247zM19.5 5h-3L18 18z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..33ac6edf7aa000af10e6310832186172fff31b6c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002B7F" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FCD116" d="M12 5h12v26H12z"/><path fill="#CE1126" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..5c6c69e45949fb9cf7fea7d5eedb087e88357009 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0C4076" d="M0 13h36v10H0z"/><path fill="#EEE" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#C6363C" d="M36 9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v4h36V9zM7 13v9.5c0 3.037 2.462 5.5 5.5 5.5s5.5-2.463 5.5-5.5V13H7z"/><path fill="#EDB92E" d="M12.5 7.062c-3.938 0-5.172 1.672-4.844 2.297.328.625 1.312 2.234 1.312 2.234s-.312.125 0 .75 1.531.203 3.531.203 3.219.422 3.531-.203 0-.75 0-.75.984-1.609 1.313-2.234c.329-.625-.905-2.297-4.843-2.297zm-3.438 2.969c-.283.088 0 .953-.1.579-.082-.309-.4-.438-.4-.266s-.125 0-.094-.312c.031-.313-.062-.5-.25-.766-.187-.266-.187-.5.048-.657.234-.156.75-.281.75-.281s.203.891.312 1.094c.109.203.312.336.312.336s-.094.148 0 .226c.094.078.203.266.203.266s-.343-.281-.405-.219c-.062.062.078.141.062.25-.016.11-.188-.328-.438-.25zm3.188.016c-.078.078-.141-.063-.297-.172-.156-.109-.25-.046-.219.079s-.188.109-.188.297-.203.109-.203.109.25-.656-.172-.641c-.239.009-.156.5 0 .672-.069-.105-.266-.109-.43-.234s.023-.329-.102-.282c-.125.047-.203.25-.328.297s-.062-.142 0-.297c.062-.156-.072-.234-.072-.234s.01-.109.104-.172c.094-.062.125-.172 0-.297s-.577-.828-.437-1.063c.141-.234.609-.5 1.922-.469.234 1.078-.125 1.609-.125 1.609s.266.172.344.266c-.188.079-.047.157.078.266.125.11.203.188.125.266zm2.438-.172c.062.156.125.344 0 .297s-.203-.25-.328-.297c-.125-.047.062.157-.102.282-.164.125-.36.129-.43.234.156-.172.239-.663 0-.672-.422-.016-.172.641-.172.641s-.203.078-.203-.109-.219-.172-.188-.297-.062-.188-.219-.079c-.156.109-.219.25-.297.172-.078-.078 0-.156.125-.266.126-.109.267-.187.079-.265.078-.094.344-.266.344-.266s-.359-.531-.125-1.609c1.312-.031 1.781.234 1.922.469.141.234-.312.938-.438 1.062s-.094.234 0 .297c.094.062.104.172.104.172s-.135.078-.072.234zm2.093-.609c-.188.266-.281.453-.25.766.031.312-.094.484-.094.312s-.318-.042-.4.266c-.1.374.183-.49-.1-.579-.25-.078-.578.672-.5.594s.188-.531.125-.594c-.062-.063-.406.219-.406.219s.109-.188.203-.266c.094-.078 0-.226 0-.226s.203-.133.312-.336c.109-.203.312-1.094.312-1.094s.516.125.75.281.236.391.048.657z"/><path fill="#FFAC33" d="M12.609 7.242c0 .099-.081.18-.18.18-.099 0-.18-.081-.18-.18V5.664c0-.099.081-.18.18-.18.099 0 .18.081.18.18v1.578z"/><path fill="#EDB92E" d="M12.969 6.086c0 .091-.073.164-.164.164h-.781c-.091 0-.164-.073-.164-.164 0-.091.073-.164.164-.164h.781c.091 0 .164.073.164.164z"/><path fill="#0C4076" d="M13.016 7.062c0 .332-.269.602-.602.602-.332 0-.602-.27-.602-.602s.269-.602.602-.602c.332.001.602.27.602.602zm-3.412 5.214c0 .147-.169.266-.378.266s-.378-.119-.378-.266c0-.146.169-.265.378-.265s.378.118.378.265z"/><path fill="#C6363C" d="M11.125 12.185c0 .147-.169.266-.378.266s-.378-.119-.378-.266c0-.146.169-.265.378-.265.208 0 .378.119.378.265zm3.375 0c0 .147-.169.266-.378.266s-.378-.119-.378-.266c0-.146.169-.265.378-.265.208 0 .378.119.378.265z"/><path fill="#0C4076" d="M16.062 12.276c0 .147-.169.266-.378.266s-.378-.119-.378-.266c0-.146.169-.265.378-.265s.378.118.378.265zm-3.254-.11c0 .147-.169.266-.378.266s-.378-.119-.378-.266c0-.147.169-.265.378-.265s.378.118.378.265z"/><path fill="#EDB92E" d="M10.286 22.562c-.342.776-.378 1.158-.783 1.131-.406-.027-.692-.096-.692.068 0 .163.645.095.645.095s-.609.26-.489.559c.119.3.645-.381.645-.381s.107.027.31-.137c.203-.163.74-.953.74-.953l-.376-.382zm4.412 0c.342.776.378 1.158.783 1.131.406-.027.692-.096.692.068 0 .163-.644.095-.644.095s.609.26.489.559c-.119.3-.645-.381-.645-.381s-.107.027-.31-.137c-.203-.163-.74-.953-.74-.953l.375-.382z"/><path fill="#FFF" d="M17.114 15.688c-.176-1.208-1.313-.833-1.796 0-.483.833-.9 1.333-1.347.75-.447-.583-.742-1.208-.096-2l.646-.792c-.092-.479-.479-.375-1.033-.146-.554.229-.904.125-.849.375.056.25.258.271.258.271s-.349.34-.441 1.513c-.092-1.173-.441-1.513-.441-1.513s.203-.021.258-.271c.055-.25-.295-.146-.849-.375s-.941-.333-1.033.146l.646.792c.646.792.351 1.417-.096 2-.446.583-.864.146-1.347-.688-.483-.833-1.621-1.208-1.796 0-.176 1.208.028 3.312.028 3.312s-.111 1.146.111 2.125c.221.979.351 1.854 0 2.604.387-.104.627-.604.627-.604s-.129.604.111.542c.24-.062.295-.521.479-.688.185-.166.333-.541.333-.541s.388-.146 0 .5c.314.021.517-.188.517-.188l.11.584.185-.312.092.562.332-.542.218.25s.041-1.062.336-.854c.295.208.313.896.111 1.312-.203.416 0 .584 0 .584s-.295.438-.446.688c-.151.25.078.541.078.541s-.572.854-.413 1.188c.154.32 1.107.524 1.804.539l.006.003.039-.001.039.001.006-.003c.697-.015 1.65-.219 1.804-.539.16-.333-.413-1.188-.413-1.188s.228-.291.078-.541c-.151-.25-.447-.688-.447-.688s.203-.168 0-.584c-.202-.416-.184-1.104.111-1.312.295-.208.335.854.335.854l.218-.25.332.542.092-.562.185.312.11-.584s.203.208.517.188c-.388-.646 0-.5 0-.5s.148.375.332.542.24.625.48.688c.24.062.111-.542.111-.542s.24.5.627.604c-.35-.75-.221-1.626 0-2.604.222-.979.111-2.125.111-2.125s.206-2.167.03-3.375z"/><path fill="#EDB92E" d="M11.891 14.312c-.44-.422-1.538-.969-1.902-.891-.364.079-.656.329-.385.72.271.391.385.375.385.375s.433-.391.621-.172c.188.219.031.297-.312.328-.344.031-.693-.203-.693-.203s.113.406.59.453c.321.312.726.078.93.078s1.156-.312.766-.688zm1.131 0c.44-.422 1.538-.969 1.902-.891.364.078.656.328.385.719-.271.391-.385.375-.385.375s-.433-.391-.621-.172c-.188.219-.031.297.312.328.344.031.693-.203.693-.203s-.113.406-.59.453c-.321.313-.726.079-.93.079s-1.157-.312-.766-.688zM9.969 25.199c.137-.316.041-.361-.069-.471-.111-.109-.166-.262-.166-.262s-.055.152-.166.262c-.111.109-.207.154-.07.471-.333-.197-.388.164-.235.383.043-.197.305-.152.305.088s-.217.131-.191.229c.027.099.225.306.356.306.131 0 .33-.207.356-.306.027-.099-.19.011-.19-.229 0-.24.261-.285.305-.088.154-.219.099-.58-.235-.383zm5.438 0c.137-.316.041-.361-.07-.471-.111-.109-.166-.262-.166-.262s-.055.152-.166.262c-.111.109-.207.154-.07.471-.333-.197-.388.164-.235.383.043-.197.305-.152.305.088s-.217.131-.19.229c.026.099.225.306.356.306.131 0 .33-.207.356-.306.027-.099-.19.011-.19-.229 0-.24.261-.285.305-.088.153-.219.099-.58-.235-.383z"/><path fill="#C6363C" d="M10.244 16.875v3.859c0 1.233 1 2.234 2.234 2.234s2.234-1.001 2.234-2.234v-3.859h-4.468z"/><path fill="#EEE" d="M14.712 19.172H12.96v-2.297h-.962v2.297h-1.753v.963h1.753v2.779c.155.034.315.055.481.055.166 0 .326-.021.482-.055v-2.779h1.753v-.963z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..46f74d591ccc0b5b3a8f107497cfa23420fcbb1e --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE2028" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-4h36v4z"/><path fill="#22408C" d="M0 13h36v10H0z"/><path fill="#EEE" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..6175c02fd1dd9dd3ac1bc3b3daf571aeffdc1e86 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f7-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#20603D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FAD201" d="M0 19h36v7H0z"/><path fill="#00A1DE" d="M32 5H4C1.791 5 0 6.791 0 9v12h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FAD201" d="M26 5l.522 4.034 1.548-3.762-.539 4.032L30 6.072l-1.565 3.755 3.221-2.484-2.483 3.222L32.929 9l-3.234 2.469 4.033-.54-3.762 1.548L34 13l-4.034.523 3.762 1.547-4.033-.539L32.929 17l-3.756-1.565 2.483 3.222-3.221-2.484L30 19.929l-2.469-3.234.539 4.033-1.548-3.762L26 21l-.522-4.034-1.549 3.762.54-4.033L22 19.929l1.565-3.756-3.221 2.484 2.482-3.222L19.071 17l3.233-2.469-4.032.539 3.761-1.547L18 13l4.033-.523-3.761-1.548 4.032.54L19.071 9l3.755 1.565-2.482-3.222 3.221 2.484L22 6.072l2.469 3.232-.54-4.032 1.549 3.762z"/><circle fill="#00A1DE" cx="26" cy="13" r="4"/><circle fill="#FAD201" cx="26" cy="13" r="3"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..d0d95800c6fae8eb5c55e6bead90184753c2da9f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006C35" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><g fill="#FFF"><path d="M8.919 14.05c.632.06.283-1.069.512-1.274.043-.101.123-.102.129.026v.958c-.006.312.199.403.358.468.166-.013.276-.007.341.154l.078 1.658s.384.11.402-.933c.019-.612-.122-1.124-.039-1.243.003-.117.152-.124.256-.067.165.116.239.26.495.203.391-.107.625-.297.631-.597-.023-.285-.055-.57-.178-.855.017-.052-.075-.186-.058-.238.07.11.177.101.201 0-.066-.219-.169-.429-.337-.52-.138-.122-.34-.097-.414.157-.034.292.106.64.318.923.045.111.109.295.081.461-.113.064-.227.038-.321-.062 0 0-.311-.233-.311-.285.083-.528.019-.588-.027-.734-.032-.202-.128-.267-.206-.405-.078-.082-.183-.082-.233 0-.138.238-.074.75.026.979.071.21.181.343.129.343-.043.119-.131.091-.195-.046-.092-.284-.11-.707-.11-.898-.028-.236-.058-.741-.213-.869-.095-.129-.236-.067-.285.052-.01.234-.012.469.015.686.106.379.14.713.192 1.102.014.521-.301.226-.287-.032.073-.335.054-.863-.011-.997-.051-.133-.112-.167-.236-.145-.098-.008-.352.27-.424.73 0 0-.061.237-.087.448-.035.238-.191.406-.301-.033-.095-.319-.153-1.106-.312-.922-.046.615-.101 1.697.421 1.807z"/><path d="M9.87 14.499c-.52.01-1.281.683-1.302 1.056.548-.264 1.087-.518 1.645-.79-.09-.135-.005-.256-.343-.266z"/><path d="M12.737 16.516c.241-.803-.039-1.395.092-1.392.277.299.665.04.75-.064.037-.052.128-.086.192-.018.217.156.599.082.678-.192.046-.268.083-.546.092-.833-.177.055-.309.092-.321.165l-.037.238c-.015.077-.168.08-.174-.018-.067-.305-.345-.345-.513.128-.113.092-.317.11-.339-.027.027-.317-.101-.36-.357-.211-.082-.629-.165-1.23-.247-1.859.107-.003.205.076.302-.046-.107-.333-.333-1.013-.458-1.062-.061-.074-.113-.028-.192-.009-.134.043-.259.159-.22.384.159.965.263 1.7.421 2.665.024.113-.07.262-.192.247-.207-.14-.259-.424-.613-.412-.257.003-.55.281-.586.55-.043.213-.058.445 0 .632.18.216.397.195.586.146.155-.064.284-.22.338-.183.037.045.009.558-.732.952-.449.201-.806.247-.998-.119-.119-.229.009-1.099-.284-.897-.867 2.235 2.03 2.545 2.354.092.031-.101.153-.202.174-.037-.067 2.222-2.241 2.375-2.61 1.676-.092-.165-.119-.531-.128-.751-.055-.437-.284-.269-.32.164-.037.241-.027.309-.027.54.115 1.755 2.915 1.001 3.369-.449zm-1.08-1.518c-.018.034-.097.02-.155.02-.066-.003-.097-.014-.137-.067-.018-.06.038-.117.063-.162.031-.053.198-.108.257.04.026.067.003.136-.028.169z"/><path d="M13.602 13.009c.174-.064.999-1.007.999-1.007-.043-.037-.081-.064-.124-.101-.046-.04-.041-.08 0-.119.204-.119.139-.38.032-.499-.177-.08-.331-.054-.444.004-.143.137-.177.357-.064.495.11.052.22.163.147.224-.337.36-1.261.981-1.154 1.003.023.03.59.029.608 0zm.611-1.481c.053-.013.121.034.153.104.032.07.015.137-.037.15h-.002c-.052.013-.12-.034-.152-.104-.031-.071-.014-.137.038-.15zm-5.351 5.73c-.136.277-.193.087-.205-.068-.021-.294.007-.565.039-.779.034-.22 0-.153-.07-.064-.309.492-.336 1.228-.165 1.447.09.104.239.15.35.116.194-.084.279-.478.233-.621-.066-.101-.117-.117-.182-.031zm10.181-5.208c.356.478.694.965 1.025 1.461.065.43.112.85.14 1.267.055.804.071 1.674.021 2.521.15.006.393-.244.477-.609.055-.505-.02-1.404-.025-1.702-.005-.159-.015-.354-.027-.56.394.644.778 1.318 1.153 2.067.137-.064.107-.83.027-.938-.3-.643-.713-1.279-.845-1.523-.049-.09-.216-.346-.415-.639-.031-.336-.062-.608-.084-.698-.062-.428.177.047.144-.202-.077-.428-.315-.717-.593-1.109-.09-.127-.087-.153-.226.031-.058.131-.069.244-.066.351-.036-.053-.076-.108-.139-.185-.241-.207-.255-.219-.455-.388-.101-.072-.347-.202-.391.014-.022.191-.01.294.022.454.026.107.181.285.257.387zm.74-.024c.019.083.039.166.052.251l.015.081c-.059-.08-.108-.146-.131-.172-.164-.194-.028-.152.064-.16z"/><path d="M21.919 16.693c-.348.363-.85.81-1.396 1.017-.059.066.146.349.41.349.443-.052.833-.301 1.194-.956.097-.152.267-.479.271-.733.033-1.486-.074-2.643-.297-3.717-.015-.104-.006-.227.012-.259.028-.034.126 0 .178-.084.075-.078-.201-.718-.359-.964-.056-.11-.075-.184-.168.013-.098.16-.163.439-.155.699.211 1.463.276 2.744.414 4.207.011.141-.01.347-.104.428zm5.83-3.71c-.015-.104-.061-.346-.043-.377.028-.074.173.008.225-.077.076-.077-.374-.655-.531-.901-.057-.11-.076-.184-.169.013-.098.16-.132.447-.093.699.235 1.589.41 2.783.446 4.192-.021.134-.025.206-.088.374-.139.178-.292.4-.437.508-.144.107-.451.21-.552.289-.317.185-.318.396-.06.403.442-.052.966-.088 1.327-.634.097-.152.212-.565.217-.819.033-1.486-.019-2.596-.242-3.67zm-3.351 1.237c.004-.204.023-.474.034-.643.005-.063.02-.134.08-.15.061-.016.169.062.17-.004-.012-.129-.038-.321-.111-.412-.1-.148-.365-.112-.412.12.001.086.04.132.033.21-.012.044-.058.074-.167.022.018-.016-.071-.139-.071-.139-.085-.052-.199.003-.272.05-.041.074-.07.201-.024.33.12.227.539.612.74.616z"/><path d="M24.257 12.481c.293.359.592.723.893 1.093.065.826.082 1.502.146 2.328-.009.35-.117.655-.22.699 0 0-.155.09-.259-.009-.076-.031-.379-.505-.379-.505-.155-.142-.257-.102-.367 0-.304.293-.441.843-.647 1.221-.054.085-.204.157-.371-.006-.423-.579-.175-1.402-.227-1.19-.377.425-.211 1.128-.126 1.28.124.248.225.408.467.531.22.162.392.06.486-.053.222-.231.225-.816.329-.934.072-.213.257-.177.346-.082.087.124.189.204.315.273.207.183.454.216.697.049.166-.093.275-.214.372-.453.108-.288.049-1.612.027-2.406.155.2.306.409.459.618.067.663.105 1.323.083 1.997-.016.135.47-.4.466-.654-.002-.205 0-.391 0-.566.234.352.462.715.676 1.099.134-.07.09-.825.005-.929-.247-.414-.576-.845-.803-1.153-.015-.039-.023-.083-.041-.12-.091-.211-.034-.381-.077-.605-.042-.225-.031-.561-.096-.828-.018-.104-.072-.438-.056-.469.026-.075.126.002.175-.084.073-.08-.253-.925-.419-1.167-.06-.108-.168-.071-.302.105-.123.116-.077.38-.03.631.117.608.215 1.191.299 1.768-.161-.215-.356-.469-.545-.713l-.008-.044c0-.011-.027-.524-.051-.646-.004-.049-.016-.064.036-.058.055.046.062.049.097.065.056.01.105-.085.072-.172l-.517-.952c-.041-.041-.095-.085-.16.011-.063.055-.13.155-.128.283.016.225.055.455.07.681l.022.122c-.023-.027-.051-.061-.063-.073-.439-.462.202-.075-.084-.432-.242-.266-.312-.349-.52-.509-.104-.067-.167-.195-.201.023-.013.191-.027.414-.015.575 0 .092.093.26.174.36zm-8.901 1.079c.252.104.413-.376.517-.902.07-.148.124-.164.16-.088-.009.7.05.855.23 1.068.401.31.733.039.76.013l.312-.312c.069-.073.162-.078.26-.013.096.086.083.236.287.34.172.069.54.016.625-.132.115-.196.143-.264.195-.338.082-.109.222-.06.222-.026-.013.061-.095.122-.039.231.098.073.12.026.178.01.204-.098.356-.54.356-.54.009-.165-.083-.151-.143-.117-.078.047-.083.063-.161.111-.1.015-.293.081-.388-.067-.098-.178-.1-.426-.174-.605 0-.013-.13-.283-.009-.3.061.011.19.045.211-.063.063-.106-.137-.408-.273-.561-.119-.13-.284-.146-.443-.013-.112.103-.096.217-.118.326-.028.124-.022.278.105.443.111.219.314.502.247.898 0 0-.118.188-.325.164-.086-.019-.226-.056-.3-.606-.056-.417.014-1-.163-1.273-.064-.165-.11-.324-.266-.042-.042.111-.222.279-.091.626.107.219.15.576.102.974-.074.113-.09.151-.187.264-.136.146-.283.109-.396.054-.106-.071-.188-.108-.236-.334.009-.36.029-.95-.037-1.075-.097-.194-.257-.124-.326-.065-.329.301-.491.808-.59 1.211-.091.294-.188.21-.256.091-.166-.156-.177-1.373-.378-1.172-.323.914.182 1.918.532 1.82z"/><path d="M20.137 15.524l-.096-.055-1.881-.009c-.097-.037-.068-.069 0-.095.449-.061 1.248-.191 1.301-.958-.009-.399-.172-.661-.662-.733-.359.028-.616.377-.575.76-.017.104.034.306-.071.329-.691.063-1.444.495-1.469.805-.042.029-.136-.055-.124-.187-.026-.535-.202-1.14-.475-1.606-.218-.218-.15-.146-.296-.043-.094.108-.111.182-.106.397 0 .008.176.499.325.843.099.353.192.756.125 1.137-.232.504-.699.956-1.149 1.201-.232.075-.431.048-.48-.004-.143-.096-.136-.273-.125-.276.379-.265.813-.478 1.153-1.191.1-.272.13-.437.031-.858-.039-.158-.089-.286-.197-.398.061-.04.236.093.263.014-.04-.202-.177-.472-.331-.61-.135-.123-.282-.137-.406-.024-.14.078-.17.356-.103.6.074.184.275.215.419.584 0 .008.052.276-.022.381-.059.184-.824.785-.866.812-.021.026-.012-.013-.015-.113-.005-.122.049-.41.034-.412-.249.161-.332.654-.377.8-.63.435-1.343.759-1.755 1.201-.215.335 1.478-.385 1.675-.472.044.032.039.183.157.318.176.238.548.385.913.294.61-.221.963-.637 1.321-1.098.051-.075.131-.132.205-.075.246.551.957.941 1.874.982.213-.259.11-.384.024-.438 0-.008-.453-.18-.522-.352-.042-.156.06-.293.264-.397.589-.071 1.168-.15 1.729-.33.006-.188.115-.47.19-.592.072-.124.111-.087.1-.132zm-1.547-1.172c.028-.047.121-.045.208.006.087.05.136.13.107.177-.028.048-.122.045-.209-.006-.087-.05-.134-.129-.106-.177zm-.757 1.9c-.202.069-.396.123-.396.415.075.406-.103.267-.208.211-.124-.089-.473-.304-.523-.768-.008-.111.079-.204.218-.204.209.057.518.061.786.089.219.014.328.186.123.257zm-6.967-4.505c.216.104.624.06.606-.29 0-.031-.008-.135-.011-.163-.044-.103-.164-.078-.192.029-.009.035.015.091-.016.109-.018.018-.087.007-.084-.089 0-.031-.023-.064-.036-.083-.014-.009-.022-.012-.047-.012-.03.001-.03.009-.046.035-.007.025-.017.051-.017.08-.004.034-.017.046-.042.052-.028 0-.022.003-.044-.012-.014-.015-.031-.021-.031-.046 0-.026-.006-.068-.014-.086-.012-.016-.031-.023-.053-.029-.118 0-.126.135-.119.187-.011.009-.015.251.146.318z"/><path d="M17.512 14.027c0-.031-.023-.063-.036-.083-.014-.009-.022-.012-.047-.012-.03.001-.029.009-.046.035-.007.026-.017.051-.017.08-.003.035-.017.047-.042.052-.028 0-.022.003-.045-.011-.014-.015-.031-.021-.031-.046 0-.026-.006-.069-.014-.086-.012-.016-.031-.023-.053-.028-.118 0-.126.135-.12.186-.009.01-.014.251.147.319.217.103.732.043.606-.29 0-.031-.008-.135-.011-.164-.044-.103-.165-.077-.192.029-.008.035.016.091-.016.109-.016.018-.086.007-.083-.09zm3.397-.707c.216.104.623.06.605-.289 0-.031-.008-.135-.011-.164-.044-.103-.164-.077-.191.029-.009.035.015.091-.017.109-.018.018-.087.008-.084-.089 0-.031-.023-.064-.036-.083-.014-.009-.022-.012-.048-.012-.03.002-.029.009-.046.035-.007.026-.017.051-.017.08-.004.035-.017.047-.042.052-.028 0-.022.003-.045-.011-.014-.015-.03-.021-.03-.046 0-.026-.006-.069-.014-.087-.013-.016-.031-.023-.054-.028-.118 0-.126.135-.119.186-.007.01-.012.251.149.318zm.146-1.352c.077.216-.059.422.022.452.073.034.177-.223.215-.46.045-.192-.092-.585-.286-.666-.118-.028-.286.042-.232.2-.027.076.238.334.281.474zm1.995 5.064c.151.001.325-.345.399-.688.041-.472-.028-.759-.04-1.037-.013-.277-.313-2.392-.375-2.602-.073-.397.293-.053.253-.284-.127-.291-.442-.714-.542-.967-.06-.108-.034-.204-.168-.028-.123.405-.166.735-.119.987.318 1.66.644 3.04.592 4.619zm3.756-4.34c.035.108-.053.457.02.489.067.036.161-.241.196-.498.019-.141-.084-.633-.261-.721-.108-.03-.261.045-.211.217-.025.083.217.361.256.513zm-13.119 3.656c.065.027.154-.177.188-.366.019-.104-.081-.465-.25-.53-.104-.022-.246.006-.202.16-.005.083.23.183.244.376.034.08-.05.337.02.36zm-4.556-4.615c.033.083-.033.348.036.373.063.028.152-.184.185-.379.019-.108.004-.474-.246-.549-.103-.023-.246.034-.199.165-.024.062.187.274.224.39zm4.902 1.173c-.191.104-.266.412-.146.591.111.159.287.1.311.1.188.023.299-.352.299-.352s.006-.105-.217.094c-.094.018-.106-.017-.129-.071-.02-.097-.016-.195.029-.292.032-.093-.04-.134-.147-.07zm1.442-1.153c.071-.052.095-.086.118-.174.029-.146-.155.069-.178-.094-.041-.151.077-.213.189-.359.004-.101.002-.172-.135-.09-.096.065-.288.263-.294.491-.006.129-.03.128.055.21.061.089.122.08.245.016zm1.299.078c.124-.336.124-.478.133-.621-.038-.217-.185-.21-.282.031-.042.091-.091.57-.083.57-.033.143.149.204.232.02zm8.17 2.383s-1.003.713-1.027.738c-.1.088-.05.4 0 .364.071.028 1.08-.657 1.06-.737.047.002.07-.401-.033-.365zm-.123 1.934c.067.036.244-.183.237-.456.02-.141-.051-.658-.227-.746-.108-.03-.252.062-.202.233-.025.082.124.369.163.521.035.109-.044.416.029.448zm-5.68 1.496c0 .009.085.082.185.024.21-.081.342-.159.636-.224.077-.001.072-.208-.05-.215-.159.008-.307.016-.466.142-.098.022-.114-.037-.136-.091-.024-.133.055-.225.038-.324.006.006-.091-.083-.19-.033-.005 0-.221.146-.29.248-.043.033-.038.061-.025.116.033.076.092.053.158.017.088-.012.13.046.123.151-.042.133.017.182.017.189zm6.551.166c-.033.057-.055.143.047.17.188.053.621-.229.621-.234.07-.053.047-.152.041-.152-.041-.047-.133-.02-.195-.027-.029 0-.127-.015-.08-.101.038-.053.052-.086.078-.151.029-.065.004-.108-.102-.143-.107-.02-.15-.01-.269 0-.064.014-.086.042-.098.12.005.118.076.112.15.159.043.055.071.105-.003.194-.07.065-.119.101-.19.165zM25.5 23H24v-.5c0-.276-.224-.5-.5-.5s-.5.224-.5.5v.5H11s0 1 3 1h9v.5c0 .276.224.5.5.5s.5-.224.5-.5V24h1v.5c0 .276.224.5.5.5s.5-.224.5-.5v-1c0-.276-.224-.5-.5-.5z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e7.svg new file mode 100644 index 0000000000000000000000000000000000000000..a55ff606a5693e2746a50bca8991d2e49ab0208f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0051BA" d="M33.552 5.312C33.075 5.111 32.55 5 32 5H4C1.791 5 0 6.791 0 9v18c0 .806.239 1.556.649 2.184L33.552 5.312z"/><path fill="#215B33" d="M2.448 30.687l.006.003c.476.2.998.31 1.546.31h28c2.209 0 4-1.791 4-4V9c0-.806-.238-1.556-.649-2.184L2.448 30.687z"/><path fill="#FCD116" d="M.651 29.189c.434.662 1.059 1.188 1.797 1.499L35.351 6.816l-.001-.002c-.434-.663-1.059-1.19-1.798-1.501L.649 29.184l.002.005z"/><g fill="#FFF"><path d="M7.069 12.021l.01.007-.484 1.49 1.292-.939 1.293.939-.484-1.49.009-.007-.009-.029 1.258-.915H8.387l-.5-1.537-.499 1.537H5.82l1.259.915z"/><path d="M8.705 12.021l1.299-.944h-.05l-1.258.915zm-1.636 0l.01-.029-1.259-.915h-.049zm-.474 1.497l-.016.048 1.308-.951 1.308.951-.015-.048-1.293-.939zM2.676 8.255l.01.007-.485 1.491 1.293-.939 1.293.939-.485-1.491.01-.007-.01-.029 1.259-.914H3.994l-.5-1.538-.5 1.538H1.427l1.259.914z"/><path d="M2.201 9.753l-.015.047 1.308-.95 1.308.95-.015-.047-1.293-.939zm.475-1.498l.01-.029-1.259-.914h-.049zm1.636 0l1.299-.943h-.05l-1.259.914zm7.151 7.531l.009.007-.484 1.491 1.293-.94 1.292.94-.484-1.491.01-.007-.01-.029 1.258-.914H12.78l-.499-1.538-.5 1.538h-1.567l1.258.914z"/><path d="M13.099 15.786l1.298-.943h-.05l-1.258.914zm-1.636 0l.009-.029-1.258-.914h-.05zm-.475 1.498l-.015.047 1.308-.95 1.308.95-.016-.047-1.292-.94zm-8.312-1.498l.01.007-.485 1.491 1.293-.94 1.293.94-.485-1.491.01-.007-.01-.029 1.259-.914H3.994l-.5-1.538-.5 1.538H1.427l1.259.914z"/><path d="M4.312 15.786l1.299-.943h-.05l-1.259.914zm-2.111 1.498l-.015.047 1.308-.95 1.308.95-.015-.047-1.293-.94zm.475-1.498l.01-.029-1.259-.914h-.049zm8.787-7.531l.009.007-.484 1.491 1.293-.939 1.292.939-.484-1.491.01-.007-.01-.029 1.258-.914H12.78l-.499-1.538-.5 1.538h-1.567l1.258.914z"/><path d="M11.463 8.255l.009-.029-1.258-.914h-.05zm1.636 0l1.298-.943h-.05l-1.258.914zm-2.111 1.498l-.015.047 1.308-.95 1.308.95-.016-.047-1.292-.939z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..40e42eaa34d1f74c9224ea4261c55b460c34c266 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D62828" d="M32 5h-7.833L1.129 29.785l.001.001c.152.157.317.301.493.431l.001.001L36 13.667V9c0-2.209-1.791-4-4-4z"/><path fill="#FCD856" d="M.763 29.35c.112.154.235.299.367.435L24.167 5H12L.763 29.35c-.001-.001-.001-.001 0 0z"/><path fill="#003F87" d="M12 5H4C1.791 5 0 6.791 0 9v18c0 .878.283 1.689.762 2.349L12 5z"/><path fill="#EEE" d="M2.063 30.501l.004.002L36 22.333v-8.667L1.624 30.218c.14.103.287.198.439.283z"/><path fill="#007A3D" d="M4 31h28c2.209 0 4-1.791 4-4v-4.667L2.067 30.502C2.64 30.819 3.299 31 4 31z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..ddb60bae3daa3c0bc31b22d8c1d07e9898ad3067 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D21034" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#141414" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><path fill="#007229" d="M1.351 6.004H1.35C.522 6.737 0 7.808 0 9v18c0 1.193.522 2.264 1.351 2.997L17.5 18 1.351 6.004z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..a039dc2ded5876027e3e428b82bdd6a23ed119de --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006AA7" d="M15.5 31H32c2.209 0 4-1.791 4-4.5v-6H15.5V31zM32 5H15.5v10.5H36V9c0-2.209-1.791-4-4-4zM10.5 5H4C1.792 5 .002 6.789 0 8.997V15.5h10.5V5zM0 20.5v6.004C.002 29.211 1.792 31 4 31h6.5V20.5H0z"/><path fill="#FECC00" d="M15.5 5h-5v10.5H0v5h10.5V31h5V20.5H36v-5H15.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..199e54e18f0d44b912a91e05be18721aad29191c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#ED2939" d="M36 18V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v9h36z"/><path fill="#FFF" d="M6 11.5c0-2.585 1.624-4.748 3.81-5.336C9.389 6.061 8.952 6 8.5 6 5.462 6 3 8.462 3 11.5S5.462 17 8.5 17c.452 0 .889-.06 1.31-.164C7.624 16.248 6 14.085 6 11.5z"/><path d="M12 7l.225.691h.726l-.588.427.225.691L12 8.382l-.588.427.225-.691-.588-.427h.726zm-2 7l.225.691h.726l-.588.427.225.691-.588-.427-.588.427.225-.691-.588-.427h.726zm4 0l.225.691h.726l-.588.427.225.691-.588-.427-.588.427.225-.691-.588-.427h.726zm-5-4l.225.691h.726l-.588.427.225.691L9 11.382l-.588.427.225-.691-.588-.427h.726zm6 0l.225.691h.726l-.588.427.225.691-.588-.427-.588.427.225-.691-.588-.427h.726z" fill="#EEE"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..57d004da3b5faed8eccb4a487b2540d09f7ea10f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M27.47 23.513c-4.601-1.797-4.426-5.971-4.239-10.389l.011-.25.206-.141c.379-.26 2.206-.765 4.204-.765 1.999 0 3.825.505 4.204.765l.206.142.011.249c.187 4.418.363 8.592-4.239 10.389l-.182.071-.182-.071z"/><path fill="#FF0" d="M31.572 13.146c-.274-.188-1.982-.677-3.921-.677-1.939 0-3.647.489-3.921.677-.189 4.479-.279 8.261 3.921 9.901 4.202-1.641 4.111-5.422 3.921-9.901z"/><path fill="#8FC5FF" d="M23.668 16c.047 3.191.713 5.77 3.983 7.047 3.271-1.277 3.938-3.855 3.983-7.047h-7.966z"/><path fill="#366CC9" d="M27.651 23.047c1.724-.673 2.72-1.711 3.287-3.006h-6.574c.568 1.295 1.564 2.333 3.287 3.006z"/><path fill="#00D860" d="M27.614 20.793c-.098 0-.177.079-.177.177s.079.177.177.177h2.672c.087-.115.17-.233.246-.353h-2.918zm-.322.906c0 .098.079.177.177.177h2.143c.128-.114.247-.232.359-.353h-2.503c-.097 0-.176.079-.176.176zm-.459.73c0 .098.079.177.177.177h1.566c.199-.112.387-.229.562-.354H27.01c-.098 0-.177.079-.177.177z"/><path fill="#5D3100" d="M24.562 17.886c.168-.449.541-1.084.688-1.104.146-.021 1.746 3.113 1.621 3.26s-1.912.24-2.267.178-.042-2.334-.042-2.334z"/><path fill="#CF6200" d="M26.438 20.562c-.125-.396-2.104-4.084-2.229-4.084-.088 0-.319.34-.493.644.112 1.519.44 2.864 1.232 3.948.667-.056 1.578-.227 1.49-.508z"/><path d="M27.099 16.271h.131v3.792h-.131zm1.333-.105h.131v3.897h-.131zm1.229.105h.131v3.792h-.131z" fill="#FF0"/><path d="M25.312 19.098c.198.055 1.039.521 1.559.677.625.188 1.546.163 1.796.163s.728-.729.937-.729h1.251c.188 0 .124 1.25-.354 1.25h-3.375c-.313 0-1.375-.979-1.583-1.083s-.407-.327-.231-.278z"/><path d="M27.651 16.677c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.088.198.198zm1.325-.198c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109-.001.198.088.198.198zm1.361.396c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm0 1.094c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.088.198.198zm0 .725c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm-1.361-1.486c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm0 .761c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.088.198.198zm0 .725c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm-1.325-1.288c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm0 .761c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109 0 .198.089.198.198zm0 .726c0 .109-.089.198-.198.198h-.692c-.109 0-.198-.089-.198-.198 0-.109.089-.198.198-.198h.692c.109-.001.198.088.198.198z" fill="#EEE"/><path fill="#AC5F1A" d="M25.867 13.241c.023-.165.446-.032.612-.178.166-.146.617-.498.984-.042.205.255.153.43.382.639.229.209 1.446.736 1.842.611-.021.25-.375.375-.375.375s.335.249.377.541c.042.292-.502-.453-1.273-.249-.308.082-.651.403-1.276.249s-.642-1.093-.658-1.487c-.005-.143-.63-.349-.615-.459z"/><path fill="#EEE" d="M26.18 13.156c.03-.134.364.004.51-.104.144-.106.537-.363.805.033.148.221.095.36.268.546.171.185 1.126.697 1.457.623-.033.201-.331.279-.331.279s.255.226.27.467c.015.239-.377-.404-1.018-.29-.256.046-.558.284-1.055.115-.499-.167-.449-.933-.436-1.255.003-.116-.491-.327-.47-.414z"/><path d="M27.375 15.66c0 .041-.033.074-.074.074-.041 0-.075-.033-.075-.074v-.47c0-.041.034-.074.075-.074.041 0 .074.033.074.074v.47zm.554 0c0 .041-.033.074-.074.074-.041 0-.075-.033-.075-.074v-.47c0-.041.034-.074.075-.074.041 0 .074.033.074.074v.47zm-.659-2.394c0 .078-.063.141-.141.141-.078 0-.141-.062-.141-.141 0-.078.062-.141.141-.141.077 0 .141.063.141.141z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..e25c04c83b018fc491bfb5c7cef7987716d643dd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED1C23" d="M36 27v-4H0v4c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4z"/><path fill="#EEE" d="M36 23H0V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v14z"/><path fill="#005DA4" d="M0 13h36v10H0z"/><path fill="#ED1C23" d="M11.125 7.917c-2.25 0-3.833.833-3.833.833s.146 2 .333 5.083 3.5 4.167 3.5 4.167 3.312-1.083 3.5-4.167.333-5.083.333-5.083-1.583-.833-3.833-.833z"/><path fill="#004A77" d="M14.592 8.586c-.588-.242-1.849-.67-3.467-.67s-2.879.428-3.467.67c.011.21.137 2.503.299 5.164.17 2.791 3.167 3.771 3.167 3.771s2.998-.98 3.167-3.771c.164-2.66.29-4.954.301-5.164z"/><path fill="#FFF" d="M12.104 15.92c-.354 0-.521.211-1.042.211s-.604-.211-.958-.211c-.268 0-.434.12-.639.179.812.61 1.66.86 1.66.86.711-.118 1.27-.466 1.693-.859-.269-.059-.445-.18-.714-.18zm-1.958-1.383c.333 0 .625.26.979.26s.604-.26.979-.26c.321 0 .743.419 1.36.179.278-.469.411-.841.411-.841l-1.25-1.792-.625.759-.875-1.675-.833 1.675-.604-.799s-.542.643-1.438 1.851c.107.286.251.534.407.766.709.35 1.187-.123 1.489-.123zm2.958.755c-.458 0-.646-.26-1-.26s-.521.26-1.042.26-.604-.26-.958-.26-.53.26-.854.26c-.117 0-.248-.036-.373-.085.127.168.252.341.39.484.386-.035.673-.273.879-.273.333 0 .625.278.979.278s.604-.278.979-.278c.231 0 .516.235.887.271.109-.142.205-.283.293-.423-.058.009-.113.026-.18.026z"/><path fill="#FD0" d="M10.318 8.807l.217.233-.309-.072-.094.304-.092-.304-.311.072.218-.233-.218-.233.311.072.092-.304.094.304.309-.072zm2.094 0l.217.233-.31-.072-.093.304-.093-.304-.31.072.217-.233-.217-.233.31.072.093-.304.093.304.31-.072zm-1.084 1.396l.216.233-.309-.072-.093.303-.093-.303-.31.072.217-.233-.217-.233.31.072.093-.304.093.304.309-.072z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ef.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ef.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f5260a686057e02198d1f06cf06a0aaeff21b36 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ef.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EF2B2D" d="M10 5H4C1.791 5 0 6.791 0 9v6h10V5zm22 0H16v10h20V9c0-2.209-1.791-4-4-4zM10 31H4c-2.209 0-4-1.791-4-4v-6h10v10zm22 0H16V21h20v6c0 2.209-1.791 4-4 4z"/><path fill="#002868" d="M14.5 5h-2.944l-.025 11.5H0v3h11.525L11.5 31h3V19.5H36v-3H14.5z"/><path fill="#EEE" d="M14.5 31H16V21h20v-1.5H14.5zM16 5h-1.5v11.5H36V15H16zm-4.5 0H10v10H0v1.5h11.5zM0 19.5V21h10v10h1.5V19.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..c4f7cafdfb4752a02fde1d0a633b47750c9f39d8 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EE2024" d="M36 27v-4H0v4c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4z"/><path fill="#EEE" d="M36 23H0V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v14z"/><path fill="#0A4EA2" d="M0 13h36v10H0z"/><path fill="#FFF" d="M11.837 25.09c-1.129-.646-3.638-2.278-4.555-4.488-.925-2.227-.719-5.423-.481-9.124l.06-.936h11.963l.061.936c.238 3.7.444 6.895-.481 9.123-.918 2.211-3.426 3.844-4.556 4.489l-1.004.572-1.007-.572z"/><path fill="#EE2024" d="M17.886 11.542H7.798c-.238 3.707-.422 6.68.407 8.676 1.021 2.46 4.516 4.22 4.631 4.276v.006l.005-.003.005.003v-.006c.115-.057 3.61-1.816 4.632-4.276.83-1.996.647-4.97.408-8.676z"/><path fill="#FFF" d="M15.865 16.109s-1.401.133-2.632.165c-.009-.269-.014-.506-.014-.681 0-.188.007-.394.017-.605.973.06 1.645.246 1.645.246.247 0 .447-.2.447-.447v-.606c0-.247-.2-.447-.447-.447 0 0-.739.126-1.568.179.071-.782.156-1.435.156-1.435 0-.247-.2-.447-.447-.447h-.605c-.247 0-.447.2-.447.447 0 0 .092.666.17 1.443-.852-.047-1.583-.187-1.583-.187-.247 0-.447.2-.447.447v.606c0 .247.2.447.447.447 0 0 .639-.206 1.67-.255.014.23.024.453.024.646 0 .161-.006.388-.016.649-1.242-.033-2.693-.164-2.693-.164-.247 0-.447.2-.447.447v.606c0 .247.2.447.447.447 0 0 1.319-.108 2.635-.128-.083 1.531-.207 3.322-.207 3.322 0 .247.2.447.447.447h.605c.247 0 .447-.2.447-.447 0 0-.111-1.773-.185-3.317 1.272.03 2.581.123 2.581.123.247 0 .447-.2.447-.447v-.606c0-.247-.2-.448-.447-.448z"/><path fill="#0A4EA2" d="M17.079 20.965c-.508-1.086-1.905-1.393-2.568-.066-.438-1.594-1.681-1.594-1.681-1.594s-1.244 0-1.681 1.594c-.658-1.316-2.04-1.024-2.558.041 1.314 2.074 4.143 3.504 4.247 3.555v.005l.005-.003.005.003v-.006c.103-.051 2.91-1.469 4.231-3.529z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..b08dd1d73665dd5295f9d959e2a5ea7c0d6029e4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#1EB53A" d="M32 5H4C1.791 5 0 6.791 0 9v5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#0072C6" d="M4 31h28c2.209 0 4-1.791 4-4v-5H0v5c0 2.209 1.791 4 4 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..b53d00dbc53084dfd36ea5166c6d68769021a91a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5EB6E4" d="M0 18v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-9H0z"/><path fill="#EEE" d="M32 5.041H4c-2.209 0-4 1.791-4 4V18h36V9.041c0-2.209-1.791-4-4-4z"/><path fill="#F4900C" d="M18 14.26c-2.433 0-2.656-.984 0-.984 2.656-.001 2.433.984 0 .984z"/><path fill="#FFAC33" d="M19.875 13.979c-.609 0-1.094.375-1.531.609-.125-.156-.344-.141-.344-.141s-.219-.016-.344.141c-.438-.234-.922-.609-1.531-.609s-2.047.594-2.047 3.609c0 3.969 3.922 5.234 3.922 5.234s3.922-1.266 3.922-5.234c0-3.016-1.438-3.609-2.047-3.609zm-4.687-1.329c.391.078.904.797.904 1.117.361-.398 1.908-.43 1.908-.43s1.547.031 1.908.43c0-.32.514-1.039.904-1.117-.078-.156-.297-.109-.297-.109s.484-.828.297-1.219c-.188-.391-.922-.375-1.516-.438-.594-.062-.703-.328-.703-.328l.156-.188s-.297-.062-.234-.266c.062-.203-.188-.188-.188-.188s.188-.188.109-.359c-.078-.172-.25-.219-.25-.219s-.109-.25 0-.328c.109-.078.359.219.359-.078s-.281-.047-.359-.156c-.077-.108.142-.389-.186-.389s-.109.281-.188.391c-.078.109-.359-.141-.359.156s.25 0 .359.078c.109.078 0 .328 0 .328s-.172.047-.25.219c-.078.172.109.359.109.359s-.25-.016-.188.188c.062.203-.234.266-.234.266l.156.188s-.109.266-.703.328-1.328.047-1.516.438c-.188.391.297 1.219.297 1.219s-.217-.049-.295.107zm4.124-1.421c.531.094 1.391.281.375.953.016-.234-.109-.422-.109-.422s-.25.031-.453.219c-.087-.31-.234-.406-.234-.406s-.297.093-.391.327c-.037-.101-.088-.186-.144-.257.088-.153.144-.361.144-.591 0-.049-.012-.092-.017-.139.258.158.572.27.829.316zm-2.624 0c.255-.045.567-.156.823-.312-.005.046-.016.087-.016.135 0 .232.056.442.146.596-.054.07-.104.154-.14.253-.094-.234-.391-.328-.391-.328s-.148.097-.234.406c-.203-.188-.453-.219-.453-.219s-.125.188-.109.422c-1.017-.672-.158-.86.374-.953z"/><path fill="#A0CFEB" d="M20.887 17.979c0-2.328-.672-2.594-.672-2.594s-.324.391-.787.234c-.463-.156-1.119-.672-1.119-.672s-.115.146-.326.154c-.211-.007-.327-.154-.327-.154s-.656.516-1.118.672c-.462.156-.788-.234-.788-.234s-.672.266-.672 2.594c0 2.202 2.608 4.276 2.891 4.494v.021l.014-.011.014.011v-.021c.282-.218 2.89-2.292 2.89-4.494z"/><path fill="#CCD6DD" d="M17.312 20.197c.156-.453.25-.75.25-1.016V18.04s-.25-.125-.25-.266v-.422l.25-.094v.281l.25-.094v-.25H18v.266l.219.047v-.234l.281.078v.391s-.219.234-.219.297v1.141c0 .109.328 1.016.328 1.016h-1.297zm.649-3.218s-.07-.297-.242-.547c-.172-.25-.115-.718.264-.719.705-.001.236.633.236.633s-.156-.32-.219-.227c-.062.094.164.453.062.656s-.101.204-.101.204zm-1.578.281s-.07-.297-.242-.547c-.172-.25-.115-.718.264-.719.705-.001.236.633.236.633s-.156-.32-.219-.226c-.062.094.164.453.062.656l-.101.203zm3.131 0s-.07-.297-.242-.547-.115-.718.264-.719c.705-.001.236.633.236.633s-.156-.32-.219-.226c-.062.094.164.453.062.656l-.101.203zm-3.662 2.865c.084-.268.132-.473.132-.662v-1.141s-.25-.125-.25-.266v-.422l.25-.094v.281l.25-.094v-.25h.188v.266l.219.047v-.234l.281.078v.391s-.219.234-.219.297v1.141c0 .11.328 1.016.328 1.016s-1.213-.247-1.179-.354zm3.013.354c.156-.453.25-.75.25-1.016v-1.141s-.25-.125-.25-.266v-.422l.25-.094v.281l.25-.094v-.25h.188v.266l.219.047v-.234l.281.078v.391s-.219.234-.219.297v1.141c0 .068.131.457.228.733.055.16-1.197.283-1.197.283z"/><path fill="#99AAB5" d="M16.383 17.479h-.148v.25l-.25.094v-.281l-.25.094v.422c0 .141.25.266.25.266v1.141c0 .189-.048.395-.132.662-.016.051.248.133.531.205v-2.853zm1.568-.282h-.149v.25l-.25.094v-.281l-.25.094v.422c0 .141.25.266.25.266v1.141c0 .189-.048.395-.132.662-.016.051.249.133.531.205v-2.853zm1.601.328l-.196-.047v.25l-.25.094v-.281l-.25.094v.422c0 .141.25.266.25.266v1.141c0 .189-.049.395-.133.662-.016.051.248.133.579.252v-2.853z"/><path fill="#8BB273" d="M18.984 20.033s-.328-.422-.984-.422c-.656 0-.938.438-.938.438s-.579-.228-1.251.093c.794 1.249 1.973 2.189 2.157 2.331v.021l.014-.011.014.011v-.021c.185-.142 1.371-1.09 2.165-2.345-.716-.304-1.177-.095-1.177-.095z"/><path fill="#658D5C" d="M18.855 24.541c-.442-.723-.839-1.547-1.917-2.047s-1.25-.641-1.562-1.156-.922-.859-.922-.859.016-.484-.188-.797c-.203-.312-.188-.703-.188-.703s-.25.133-.188-.355-.25-.816-.25-.816.391-.516.062-1.18c.375-.648.203-1.383.203-1.383s.328-.609 0-1.266c-1.047.438-1.109 1.828-1.109 1.828l-.594-.859s-.5.328-.375.938c.125.609.094.742.094.742l-.562-.476s-.406.672.156 1.203.656.688.656.688-.281-.156-.281.094.062.359.062.359l-.736-.609s-.217.828.298 1.297c.516.469.828.641.828.641s-.984-.281-.969-.211c.016.07.203.586.703.867.5.281.875.391.875.391l-1.016.184s.25.723.844.723 1.156-.188 1.156-.188-.422.344-.547.609c-.125.266-.484.297-.484.297s.328.344.938.234c.609-.109.688-.938 1.438-.672.75.266 2.094.75 2.531 1.422s.594.828.688 1.062c.095.232.485.209.356-.002z"/><path fill="#658D5C" d="M17.027 24.541c.441-.723.839-1.547 1.917-2.047 1.078-.5 1.25-.641 1.562-1.156s.922-.859.922-.859-.016-.484.188-.797.188-.703.188-.703.25.133.188-.355.25-.816.25-.816-.391-.516-.062-1.18c-.375-.648-.203-1.383-.203-1.383s-.328-.609 0-1.266c1.047.438 1.109 1.828 1.109 1.828l.594-.859s.5.328.375.938c-.125.609-.094.742-.094.742l.562-.476s.406.672-.156 1.203-.656.688-.656.688.281-.156.281.094-.062.359-.062.359l.735-.609s.218.828-.298 1.297-.828.641-.828.641.984-.281.969-.211c-.016.07-.203.586-.703.867-.5.281-.875.391-.875.391l1.016.184s-.25.723-.844.723-1.156-.188-1.156-.188.422.344.547.609c.125.266.484.297.484.297s-.328.344-.938.234-.688-.938-1.438-.672c-.75.266-2.094.75-2.531 1.422s-.594.828-.688 1.062c-.094.232-.484.209-.355-.002z"/><path fill="#E1E8ED" d="M15.625 23.144c-.734.085-.922.569-1.953.116-.047.234.328.594.328.594s-.562.016-.828-.078c.141.578.797.797 1.344.75.547-.047.891-.453 1.524-.312.633.141 1.088.335.962-.797-.424-.454-1.377-.273-1.377-.273zm4.75 0c.734.085.922.569 1.953.116.047.234-.328.594-.328.594s.562.016.828-.078c-.141.578-.797.797-1.344.75s-.891-.453-1.524-.312c-.633.141-1.088.335-.962-.797.424-.454 1.377-.273 1.377-.273z"/><path fill="#F5F8FA" d="M20.422 22.416c-.422-.187-1.344.281-2.422.281s-2-.469-2.422-.281c-.422.188-.344.25-.312.406.031.156.078.578.109.812.031.234.281.391.578.188.297-.203.672-.297 1.188-.141.516.156.834.146.834.146s.369.01.885-.146.891-.062 1.188.141c.297.203.547.047.578-.188.031-.234.078-.656.109-.812.031-.156.109-.218-.313-.406z"/><path fill="#99AAB5" d="M19.838 22.822c0 .096-.191.48-1.952.48s-1.892-.385-1.892-.48c0-.096.288.212 2.048.212s1.796-.307 1.796-.212z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2334722b2f16e14f88bb5877bbcdac9b50e4757 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00853F" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FDEF42" d="M12 5h12v26H12z"/><path fill="#E31B23" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#00853F" d="M18.869 16.674L18 14l-.869 2.674H14.32l2.274 1.652L15.726 21 18 19.348 20.274 21l-.868-2.674 2.274-1.652z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..293dd348f1872a7beb500d87d4275087d4b845b4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4189DD" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M19.405 16.066L18 11.741l-1.405 4.325h-4.548l3.679 2.673-1.405 4.325L18 20.391l3.679 2.673-1.405-4.325 3.679-2.673z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..c483fb95ea51de945256d2ebf1273209c3db8b68 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#377E3F" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-1H0v1z"/><path fill="#EEE" d="M0 23h36v3H0z"/><path fill="#377E3F" d="M32 5H4C1.791 5 0 6.791 0 9v1h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 10h36v3H0z"/><path fill="#B40A2D" d="M0 23h36V13H0v10zm16.833-6.11L18 13.297l1.167 3.593h3.778l-3.057 2.221 1.167 3.593L18 20.483l-3.056 2.221 1.167-3.593-3.057-2.221h3.779z"/><path fill="#ECC81D" d="M14.944 22.703L18 20.483l3.056 2.22-1.167-3.593 3.056-2.22h-3.778L18 13.297l-1.167 3.593h-3.778l3.056 2.22z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..0aa63d752af738f41136fc8edcb9fbbf7055aea2 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M32 5H4C1.791 5 0 6.791 0 9v3h36V9c0-2.209-1.791-4-4-4z"/><path fill="#078930" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-3H0v3z"/><path fill="#DA121A" d="M0 12h36v12H0z"/><path d="M0 12h36v2H0zm0 10h36v2H0z" fill="#EEE"/><path fill="#0F47AF" d="M1.351 6.004H1.35C.522 6.737 0 7.808 0 9.267v18c0 .926.522 1.997 1.351 2.729L17.5 18 1.351 6.004z"/><path fill="#FCDD09" d="M8.249 17.917l1.777-2.446-2.875.934-1.776-2.445v3.023l-2.875.934 2.875.934v3.022l1.776-2.445 2.875.934z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..f2bb52a3cf55fad0486950176322aa2400ceda68 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#12AD2B" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCE00" d="M8.173 13.5H36v9H8.173z"/><path fill="#D21034" d="M1.149 6.195C.438 6.917 0 7.907 0 9v18c0 1.093.438 2.083 1.148 2.805L12.5 18 1.149 6.195z"/><path d="M18.004 20.36l1.625-1.181 1.624 1.181-.62-1.91 1.624-1.181h-2.008l-.62-1.909-.621 1.909H17l1.625 1.181zm9.5 0l1.625-1.181 1.624 1.181-.62-1.91 1.624-1.181h-2.008l-.62-1.909-.621 1.909H26.5l1.625 1.181z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..873310c0968d63466fabc9ab055b4b2ea4dfefcd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0F47AF" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#1F601A" d="M17.462 21.297c.246-.764-.609-.906-.609-.906s.062.438-.453.453c.172.344.016.625-.203.641.359.327 1.109.296 1.265-.188zm-1.27-.463c.473-.578-.221-.992-.221-.992s-.095.4-.547.239c.033.355-.199.547-.394.486.201.408.862.635 1.162.267zm-.895-.795c.564-.302.152-.857.152-.857s-.207.284-.511.01c-.091.291-.336.366-.471.255.025.388.472.783.83.592zm-.346-1.009c.594-.121.371-.736.371-.736s-.265.202-.467-.129c-.162.239-.405.241-.497.104-.082.358.216.838.593.761zm-.14-.865c.545-.004.455-.586.455-.586s-.269.133-.39-.195c-.185.183-.399.142-.456.005-.134.302.045.778.391.776zm.129-.825c.425.146.492-.396.492-.396s-.241.044-.257-.28c-.187.112-.344.017-.356-.121-.177.232-.15.704.121.797zm.327-.683c.212.124.45-.288.45-.288s-.184-.066-.137-.369c-.164.074-.276.029-.26-.1-.179.187-.253.641-.053.757zm3.116 4.64c-.246-.764.609-.906.609-.906s-.062.438.453.453c-.172.344-.016.625.203.641-.359.327-1.109.296-1.265-.188zm1.269-.463c-.473-.578.221-.992.221-.992s.096.4.547.239c-.032.355.199.547.395.486-.202.408-.862.635-1.163.267zm.896-.795c-.563-.302-.151-.857-.151-.857s.207.284.51.01c.092.291.337.366.471.255-.025.388-.472.783-.83.592zm.346-1.009c-.594-.121-.37-.736-.37-.736s.265.202.467-.129c.162.239.404.241.496.104.081.358-.216.838-.593.761zm.139-.865c-.545-.004-.455-.586-.455-.586s.27.133.39-.195c.184.183.399.142.456.005.135.302-.045.778-.391.776zm-.129-.825c-.425.146-.492-.396-.492-.396s.242.044.258-.28c.188.112.344.017.356-.121.177.232.15.704-.122.797zm-.326-.683c-.213.124-.45-.288-.45-.288s.185-.066.138-.369c.163.074.275.029.26-.1.177.187.251.641.052.757z"/><circle fill="#06209F" cx="17.906" cy="21.301" r=".4"/><path fill="#06209F" d="M17.821 17.774l-1.859-1.993s-.312 2.297.594 2.906c.906.61 1.265-.913 1.265-.913z"/><path fill="#FFF" d="M16.854 16.739l-.414-.444s-.213 1.783.693 2.393c-.437-.891-.279-1.949-.279-1.949z"/><path fill="#06209F" d="M17.821 18.602l-2.549-1.445s-.125 1.484.322 2.203c.446.719 2.085.766 2.312.062.228-.703-.085-.82-.085-.82z"/><path fill="#FFF" d="M16.194 17.679l-.477-.271s-.284 2.983 1.977 2.298c-1.498-.07-1.5-2.027-1.5-2.027z"/><path fill="#06209F" d="M17.989 17.774l1.859-1.993s.312 2.297-.594 2.906c-.905.61-1.265-.913-1.265-.913z"/><path fill="#FFF" d="M18.956 16.739l.414-.444s.213 1.783-.693 2.393c.437-.891.279-1.949.279-1.949z"/><path fill="#06209F" d="M17.989 18.602l2.549-1.445s.125 1.484-.321 2.203c-.446.719-2.085.766-2.312.062-.228-.703.084-.82.084-.82z"/><path fill="#FFF" d="M19.616 17.679l.479-.271s.283 2.983-1.979 2.298c1.498-.07 1.5-2.027 1.5-2.027z"/><path fill="#FFCC01" d="M17.821 15.297l-2.474 4.265h4.949z"/><path fill="#FFF" d="M15.694 19.362l2.127-3.667 2.127 3.667z"/><path fill="#017E93" d="M16.303 18.312l-.609 1.05h4.254l-.609-1.05z"/><path fill="#FFCC01" d="M16.103 18.831s.688-.972.953-.972c.266 0 .391.305.391.305s.104-.164.247-.164c.143 0 .212.165.212.165s.103-.161.165-.131c.062.029.267.279.267.279s.061-.108.202-.148c.141-.04.234.148.234.148s.138-.296.17-.148c.033.148.543.667.543.667h-3.384z"/><circle fill="#E60000" cx="17.883" cy="17.236" r=".189"/><path d="M14.002 16.24c-.255.504-.413 1.059-.459 1.651l.498.013c.044-.52.185-1.007.411-1.45l-.45-.214zm4.754-1.858c.633.133 1.199.429 1.68.826l.345-.361c-.547-.457-1.192-.799-1.915-.951l-.11.486zm2.437 1.629c.434.633.69 1.398.69 2.224 0 .15-.027.293-.044.439l.49.09c.022-.176.054-.348.054-.529 0-.928-.286-1.787-.773-2.499l-.417.275zm-4.97 5.748c-1.184-.58-2.022-1.731-2.171-3.098l-.494.056c.169 1.546 1.119 2.845 2.459 3.498l.206-.456zm-1.336-5.975c.722-.899 1.817-1.487 3.06-1.487.026 0 .05.007.076.008l.031-.497c-.036-.001-.07-.011-.107-.011-1.413 0-2.656.672-3.469 1.701l.409.286zm6.8 3.621c-.33 1.055-1.081 1.916-2.068 2.382l.203.456c1.113-.523 1.962-1.491 2.337-2.679l-.472-.159z" fill="#FFCC01"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fd.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fd.svg new file mode 100644 index 0000000000000000000000000000000000000000..20472431e5ae9d9a821da77178d881296e004b37 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#032A87" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#DC181E" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M1.313 29.945l15.718-11.881L1.33 6.041C.519 6.773 0 7.822 0 9v18c0 1.171.512 2.214 1.313 2.945z"/><path fill="#FADA10" d="M8.625 14.739c0 .915-.962 1.657-2.148 1.657-1.187 0-2.148-.742-2.148-1.657s.962-1.656 2.148-1.656c1.186 0 2.148.742 2.148 1.656z"/><path fill="#BD725F" d="M3.854 14.042c.46-.46 2.119-.438 2.622-.146-.56-.754.212-.396.816-.396.604-.001.771.186.375.228-.396.043-.729-.02-.625.105.104.125.709.019 1.25-.105.542-.124 1.166.334 1.208.418s-.958-.125-1.312 0-.917.104-.875.229-.589.208-.836.146-1.269-.042-1.102-.146.375-.229.458-.271c.084-.042-1.25-.083-1.979-.062z"/><path fill="#DC181E" d="M10.156 14.562s-.939.477-1.891.25c-1.047-.25-1.812-.139-1.812.141 0-.28-.766-.391-1.812-.141-.951.227-1.891-.25-1.891-.25s.694 1.109.281 3.328c-.422 2.266-.297 3.297 1.49 3.364 1.511.057 1.932.511 1.932.511s.421-.454 1.932-.511c1.787-.067 1.912-1.099 1.49-3.364-.413-2.218.281-3.328.281-3.328z"/><path fill="#63B0E2" d="M9.469 18.578c-.531-1.828.031-3.328.031-3.328s-.828.25-1.75-.016-1.297.188-1.297.188-.375-.453-1.297-.188c-.922.266-1.75.016-1.75.016s.562 1.5.031 3.328c-.531 1.828.766 2.094 1.641 2.078.875-.016 1.375.484 1.375.484s.5-.5 1.375-.484c.875.016 2.172-.25 1.641-2.078z"/><path fill="#FFF" d="M8.547 19.891v-.907h.203v-.359h-.219v-.969h.203l-1.672-1.109v-.453h.25l-.859-.578-.859.578h.25v.453l-1.672 1.109h.203v.969h-.219v.359h.203v.907h-.25v.453h4.688v-.453zm.164-3.774c0 .358-.073.492-.164.492-.091 0-.164-.134-.164-.492s.164-.648.164-.648.164.29.164.648z"/><path fill="#FFF" d="M9.18 16.656H7.914c0-.172.283-.312.633-.312.349 0 .633.14.633.312z"/><path fill="#018830" d="M4.875 16.188s-.234.422-.281.672c-.047.25-.188-.156-.188-.156s-.25.25-.312.344c-.062.094-.078-.719 0-.828.078-.109-.188-.078-.281-.125-.094-.047.203-.344.203-.344s-.406-.188-.266-.234c.141-.047.656-.016.828.125.172.141.578-.094.734-.125.156-.031 0 .156-.125.266-.125.109-.062.391-.062.531s-.25-.126-.25-.126z"/><path fill="#B6B6B6" d="M5.578 18.203h1.844v.531H5.578zm-.89-.437h.562v.734h-.562zm0 1.234h.562v.734h-.562zm3.015-1.234h.562v.734h-.562zm0 1.234h.562v.734h-.562zm-1.656-2.781h.844v.391h-.844z"/><path fill="#FADA10" d="M11.5 18.766l-.156-.891-.828.266.25 1.203.188.047s.016.969-.719 1.719-2.031.75-2.031.75-.672.484-1.75.484c-1.078 0-1.75-.484-1.75-.484s-1.297 0-2.031-.75c-.734-.75-.719-1.719-.719-1.719l.188-.047.25-1.203-.828-.266-.156.891-.297.031s.016 1.75.625 2.672c.609.922 1.969 1.203 1.969 1.203s.016.109.047.219c.891.516 2.703.547 2.703.547s1.812-.031 2.703-.547c.031-.109.047-.219.047-.219s1.359-.281 1.969-1.203c.609-.922.625-2.672.625-2.672l-.299-.031z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..5e32d2cd27f1642ea25d5d67bc8aa3d326d22254 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#CE1126" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#141414" d="M32 31H4c-2.209 0-4-1.791-4-4v-4h36v4c0 2.209-1.791 4-4 4z"/><path d="M9.177 18.332l-.633 1.947 1.656-1.203 1.656 1.203-.633-1.947 1.656-1.202h-2.047l-.632-1.947-.632 1.947H7.521zm15.6 0l-.633 1.947 1.656-1.203 1.656 1.203-.633-1.947 1.656-1.202h-2.047l-.632-1.947-.632 1.947h-2.047z" fill="#007A3D"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..cb7f84a839c902747544b78312ce768e2f86d86a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f8-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E5EB9" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFD900" d="M0 10h36v16H0z"/><path fill="#B10D0D" d="M0 11h36v14H0z"/><path fill="#FFF" d="M27.513 16.779l1.562.594 1.531-.594-1.531-.5z"/><path fill="#FFD900" d="M28.531 16.8c0 .155-.126.281-.281.281H5.781c-.155 0-.281-.126-.281-.281 0-.155.126-.281.281-.281H28.25c.155 0 .281.126.281.281z"/><path fill="#FFF" d="M28.513 15.779l1.562.594 1.531-.594-1.531-.5z"/><path fill="#FFD900" d="M29.531 15.8c0 .155-.126.281-.281.281H6.781c-.155 0-.281-.126-.281-.281 0-.155.126-.281.281-.281H29.25c.155 0 .281.125.281.281zm4.196 2.192c0 .233-.188.422-.422.422H3.148c-.233 0-.422-.189-.422-.422 0-.233.189-.422.422-.422h30.156c.234 0 .423.189.423.422z"/><path fill="#FFF" d="M27.229 18.031s-4.058 5.49-9.062 5.49-9.063-5.49-9.063-5.49 4.058-5.49 9.063-5.49 9.062 5.49 9.062 5.49z"/><path d="M18.979 22.354c-.438-.208-1.188-.458-1.167-.646s.583-.25 1.104-.312c.521-.062.5-.312.354-.438s-.75-.292-1.104-.5-.021-.396.297-.646.328-.541.328-.75.25-.646.667-.917.021-.312-.312-.479-.313-.729-.25-1.146.042-.646-.104-.667-.229-.146-.312-.261c-.083-.115 0-.323-.312-.364s-.292-.146-.375-.333-.354-.479-.479-.833c-.105-.298.149-.863.828-1.519-4.993.019-9.036 5.488-9.036 5.488s4.058 5.49 9.063 5.49c.641 0 1.266-.092 1.868-.249-.143-.587-.705-.75-1.058-.918z"/><path fill="#FFF" d="M12.479 16.042h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.855-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438z"/><path d="M19.229 16.042h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.855-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.853-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.855-2.458h.438v1.479h-.438zm0 2.458h.438v1.479h-.438zm.854-2.458h.438v1.479H23.5zm0 2.458h.438v1.479H23.5z"/><path fill="#3D5DA7" d="M15.156 13.594c-.4.265-1.219 1.078-1.266 1.672.172-.156.375-.188.375-.188s-.234.328-.203.734c.141-.156.281-.219.281-.219s.083.375.391.766c.156-.094.203-.25.203-.25s.094.328.422.578c.12-.031.12-.172.12-.172s.193.406.99.578c-.141-.266.312-.635.141-1.052.14.083.281.286.281.286s.14-.203-.141-.578c.172.156.266.292.266.292s.108-.651-.266-1.058c.235.094.438.203.438.203s-.039-.787-.625-1.141c-.751-.451-1.407-.123-1.407-.451zm-11 4.312s.359.328-.141.375c-.5.047-.906.641-.891 1.234l.266-.125s-.078.406.047.672c.109-.266.266-.25.266-.25s.031.391.094.688c.125-.156.109-.328.109-.328s.188.062.281.328.141.469.359.594c.094-.047.141-.172.141-.172s.188.156.484.281c-.062-.422.344-.375.516-.672.062.078.078.234.078.234s.125-.234.125-.469.141-.422.141-.422.016.109 0 .281c.141-.078.172-.969.109-1.25.094.078.172.25.172.25s.109-.453 0-.742-.422-.524-.812-.383c-.391.141-.969-.234-.969-.234s.094.234-.031.312-.016-.124-.344-.202zm27.391-.156s-.312.109-.812.578-.656 1.266-.656 1.266.281-.234.391-.266c-.266.609.25.891.172 1.375.203-.031.391-.391.391-.391s.375.672.906 1.047c.125-.359.484-.656.484-.656l.078.203.219-.547.156.266s.141-.307 0-.646c.021.061.234.224.234.224v-.75s.125.234.219.297c0-.328-.188-.562-.109-.703l.109.193s.094-.521-.453-.928c-.547-.406-1.057-.375-1.169-.32-.113.055-.16-.242-.16-.242z"/><path fill="#A70000" d="M14.859 14.578c.29-.088.188.844-.156 1.219.188-.641-.203-1.109.156-1.219zm.68-.266c.069-.24.569.391 1.21.422-.561.094-1.296-.125-1.21-.422zm-.195.969c.17-.079.219.859 0 1.125.031-.468-.235-1.015 0-1.125zm.625-.234c-.217.059.421.578.781.547-.338-.064-.438-.641-.781-.547zm-.125.995c-.226 0 0 .599.406.739-.141-.219-.042-.739-.406-.739zm-11.61 2.567c.206 0-.062.703-.5.984.235-.343.204-.984.5-.984zm.672-.109c-.167.128.297.699.828.74-.343-.24-.625-.895-.828-.74zm-.5.906c.124-.021.148.653-.203.828.188-.437.016-.796.203-.828zm.594 0c.207-.127.31.402.609.573-.5-.12-.812-.448-.609-.573zm-.257.5c.207-.091.319.659 0 .875.116-.484-.18-.797 0-.875zm26.413-.666c.216-.006-.172.635-.5.807.313-.469.266-.801.5-.807zm.782-.334c-.161.111.297.422.516.422-.271-.084-.313-.562-.516-.422zm-.563 1.073c.165-.126.234.286 0 .583.143-.302-.219-.416 0-.583zm.672-.424c-.171.069.156.555.406.586-.273-.168-.156-.688-.406-.586zm-.235.492c.142-.107.432.594.091.953.162-.521-.359-.75-.091-.953z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..547fa056f805562a4f170a54c66383d32d62c39f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#C0E6E9" d="M26.641 13.104c-.141-.401-1.062-.745-1.469-.589.469-.875 1.246-1.141 1.639-1.547.393-.406.408-.766.408-.766s.359.609.719 1.172.846.875.846.875-1.268.382-2.143.855z"/><path fill="#AE7521" d="M26.826 13.019c0 .047-.038.085-.085.085-.047 0-.085-.038-.085-.085v-2.466c0-.047.038-.085.085-.085.047 0 .085.038.085.085v2.466z"/><path fill="#C7E9EB" d="M27.412 13.5c-.673 0-1.74-.031-1.834-.219-.094-.188-.125-.672-.125-.672s.797.391 1.875.391c1.078 0 1.766-.391 1.766-.391s.008.659-.311.781c-.223.087-.605.11-1.371.11z"/><path fill="#9FC2FF" d="M22.609 16.312c-.125.312-.141.719.094.891.234.172.609-.172.609-.172s-.671-.062-.703-.719z"/><path fill="#00A3D6" d="M24.141 16.844c-.297-.266-.918-.062-.918-.062s.074-.36.262-.469c-.516-.047-.789.094-.965.531-.207-.234.09-.812.09-.812s.672-.406 1.312 0c.531-.734.615-2-.028-1.891.169-.422 1.378-.157 1.148.57-.229.727-.604 1.008-.604 1.008s.627-.592 1.056-.327c.429.265.616 1.505-.321 1.096-.938-.409-1.109-.153-1.125 0-.017.153.093.356.093.356z"/><path fill="#9FC2FF" d="M26.312 16.625c-.4 1.177-1.188 1.177-1.188 1.177s.047-.406.203-.588c-.672.255-1.609-.151-1.406-1.182.156.656.812.875 1.422.578.61-.298 1.03-.163.969.015z"/><path fill="#00A3D6" d="M21.922 14.891c-.114-.186.158-.516.524-.391-.243.266-.132.531 0 .719s-.399-.125-.524-.328z"/><path fill="#9FC2FF" d="M24.406 14.078c-.297-.094-.513.062-.513.062s-.159-.359-.644-.219-.781-.033-.781-.033.156.506.891.512c-.453.583-1.219.693-1.438.49.125.281.562.625.719.641.156.016.979-.47 1.156-1.031.031-.099.125.015 0 .21-.125.196-.234.415-.156.758.113-.19.359-.203.484-.5s.016-.609.281-.703c.267-.093.001-.187.001-.187z"/><path fill="#8DA8C3" d="M28.208 18.479c-.485 0-.521-.833-.521-.833s-.146.068-.562.419c-.417.351-1.042.419-1.042.419s-.479-.526.084-1.151c-.021-.625-.729-1.271-.729-1.271l-.583-.125s1.395-1.354 2.416-1.438 1.083.375 1 1.312.209 1.521.209 1.521.874 1.147-.272 1.147z"/><path fill="#CC1530" d="M25.641 15.532c-.109.125-.105.171.205.156.311-.016.473.003.473.003s-.646.338-1.053.152c.062-.202.375-.311.375-.311zm2.266 2.015s.421-.266.577.188c.156.453-.02.5-.229.516-.208.015-.348-.704-.348-.704z"/><path fill="#9FC2FF" d="M29.359 16.234c-.138.305-.141.969.547 1.219.125-.5.032-.797-.547-1.219zm1.485.328c.156-.156.047-.766-.422-.531-.469.234-.68.172-.801.094.082-.141.41-.25.41-.25s-.6.047-.745-.453c.354.094.526 0 .526 0s-.195-.141-.191-.25c.27-.094.645.203.645.203s-.133-.219-.16-.734c-.027-.516.395-.695.707-.449-.297.356.047 1.043.188 1.637.578-.422 1.281-.328 1.312.328.031.656-.172.5-.172.5s.25-.625-.656-.531c.391.188.203.362.203.362s-.422-.113-.844.074z"/><path fill="#00A3D6" d="M28.799 14.875c-.408-.046-.252.455-.846.657.141.062.423 0 .423 0s-.28.515 0 1.046c.249-.203.327-.547.327-.547s0 .599.312.885c.274-.353.141-.792.141-.792s.191.536.799.792c.607.255 1.014-.307 1.061-.604.047-.297-.094-.386-.094-.386s-.512.48-.967.199c.201-.188.115-.291-.334-.325s-.559-.659-.605-.737c-.047-.079-.217-.188-.217-.188zm1.355-.54c.174-.46.768-.535.986-.396.406-.22.834.217 1.175.077-.143.328-.565.489-.784.385.266.38.972.635 1.234.405.263-.229.084.297-.45.472s-.909-.472-.909-.472.109.402 0 .571c-.406-.143-.617-.568-.605-.877s-.242-.534-.647-.165z"/><path fill="#9FC2FF" d="M32.315 15.278c.419-.091.732-.436.747-.568.016-.132-.213-.534-.747-.309.466.177.378.749 0 .877z"/><path fill="#00A3D6" d="M32.222 15.842c.325.439.231.908.169 1.001-.062.094-.546.262-.734-.062.405-.031.788-.386.565-.939z"/><path fill="#D9A323" d="M27.428 14.922c-.714 0-1.786.356-1.786.356s-.037-.424-.267-.778-.333-.854-.333-.854.583.104.646.458-.021.667-.021.667l.708-.188s-.188-.305-.354-.083-.354-.604-.104-.729.909-.271.909-.271.05.604.091.75-.334.151-.334.151l.062.099h.625s-.208-.234-.208-.604c0-.405.438-.792.438-.792s.391.523.391.833-.233.563-.233.563l.55.104s.208-.417 0-.312-.209-.125-.125-.396.021-.521.021-.521l.854.396s.062.091 0 .42c-.062.33-.438.299-.438.299v.197l.562.146s-.167-.388 0-.642.729-.42.729-.42-.459.827-.729 1.507c-.345-.164-.94-.356-1.654-.356z"/><path fill="#FFF" d="M27.437 18h-2.663v3.219c0 2.747 1.848 3.181 2.644 3.401v.005l.01-.003.009.003v-.005c.796-.221 2.644-.654 2.644-3.401V18h-2.644z"/><path fill="#179AF9" d="M27.418 18h-2.644v3.141h5.306V18h-2.662z"/><path fill="#179AF9" d="M27.428 22.984s-.193-.984-1.053-1.844h2s-.77.782-.947 1.844z"/><path fill="#FFF" d="M27.428 19.297s-.193.984-1.053 1.844h2s-.77-.782-.947-1.844zm-.24 0c-.059.173-.406.5-.656.578s-.637.375-.686.516c-.049-.157.123-.391.123-.391s-.281.031-.312.391c-.031.359-.614.375-.614.375s.114-.5.411-.797c.297-.297.48-.125.662-.234.182-.109-.068-.359.135-.641.203-.281.75-.203.938-.422.062.172-.469.484-.547.516-.078.031-.109.219-.016.203.093-.016.421-.063.562-.094zm.479 0c.059.173.406.5.656.578s.637.375.686.516c.049-.157-.123-.391-.123-.391s.281.031.312.391c.031.359.614.375.614.375s-.114-.5-.411-.797c-.297-.297-.48-.125-.662-.234-.182-.109.068-.359-.135-.641-.203-.281-.75-.203-.938-.422-.062.172.469.484.547.516.078.031.109.219.016.203-.093-.016-.421-.063-.562-.094z"/><path fill="#179AF9" d="M27.188 22.969c-.059-.173-.406-.5-.656-.578-.25-.078-.637-.375-.686-.516-.049.156.123.391.123.391s-.281-.031-.312-.391c-.031-.359-.614-.375-.614-.375s.114.5.411.797c.297.297.48.125.662.234.182.109-.068.359.135.641.203.281.75.203.938.422.062-.172-.469-.484-.547-.516-.078-.031-.109-.219-.016-.203.093.016.421.063.562.094zm.479 0c.059-.173.406-.5.656-.578.25-.078.637-.375.686-.516.049.156-.123.391-.123.391s.281-.031.312-.391c.031-.359.614-.375.614-.375s-.114.5-.411.797c-.297.297-.48.125-.662.234-.182.109.068.359-.135.641-.203.281-.75.203-.938.422-.062-.172.469-.484.547-.516.078-.031.109-.219.016-.203-.093.016-.421.063-.562.094z"/><path d="M25.656 16.031c.453.188.844-.062 1.25-.391.406-.328.846-.156.971-.109s-.143.043-.604.311c-.461.267-.68.351-.695.645-.016.294-.141.128-.203 0-.062-.128-.078.216 0 .56.078.344-.057.755-.057.755s-.117-1.078-.662-1.771z"/><path fill="#D8AB6D" d="M21.234 18.594s.078-.234.391-.406.094-.312-.109-.297c-.203.016-.359.031-.578.594-.219.562-1.047 3 .297 4.312-.391-.188-.75-.953-.75-.953s.047.516.312 1.031c-.797-1.25-.703-2.578-.578-3.578s.422-1.641.875-1.672c.375-.562 1.062-.271 1.578.177s.766.87.766.87.068-.828.456-.75c.388.078.95.359 1.028.562s-.484.047-.594-.078c-.109-.125-.322-.266-.434-.141-.112.125-.191.688-.191.688s.277-.516.443-.469.922.719.896.953-.229-.125-.433-.281c-.203-.156-.363-.438-.463-.391-.1.047-.459.875-.49.953-.031.078.084.062.237-.149.153-.211.325-.445.419-.445.094 0 .742.891.73 1.094-.012.203-.108.391-.188.438-.08.047.036-.233-.151-.562s-.359-.673-.438-.626c-.078.047-.438.609-.5.75-.062.141.406-.328.578-.25.172.078.424.967.431 1.25.007.283-.163.469-.25.547-.087.078-.054-.281 0-.453s-.071-.391-.118-.656c-.047-.266-.094-.516-.141-.438-.047.078-.766.703-.828.75-.062.047.225 0 .456-.125s.356-.109.388.125c.031.234.078.969-.281 1.172-.359.203.031-.25.078-.469.047-.219.016-.688-.078-.641-.094.047-.75.531-.953.609-.203.078-.094.609.109.906.203.297.646.594.737.328.091-.266.436-.547.631-.406.194.141.101.406.101.406s.256 0 .229.281c-.026.281-.386.562-1.261.438s-1.969-.469-1.906-2c-.328-1.344-.078-1.922-.031-2.297.047-.375.188-.927.141-.971-.047-.043-.406.067-.563.27zm12.436 0s-.078-.234-.391-.406-.094-.312.109-.297c.203.016.359.031.578.594.219.562 1.047 3-.297 4.312.391-.188.75-.953.75-.953s-.047.516-.312 1.031c.797-1.25.703-2.578.578-3.578s-.422-1.641-.875-1.672c-.375-.562-1.062-.271-1.578.177s-.766.87-.766.87-.068-.828-.456-.75c-.388.078-.95.359-1.028.562-.078.203.484.047.594-.078.109-.125.322-.266.434-.141.112.125.191.688.191.688s-.277-.516-.443-.469c-.166.047-.922.719-.895.953.026.234.229-.125.433-.281.203-.156.363-.438.463-.391.1.047.459.875.49.953.031.078-.084.062-.237-.149-.153-.211-.325-.445-.419-.445-.094 0-.742.891-.731 1.094.012.203.108.391.189.438.08.047-.036-.233.151-.562s.359-.673.438-.626c.078.047.438.609.5.75.062.141-.406-.328-.578-.25-.172.078-.424.967-.431 1.25-.007.283.163.469.25.547.087.078.054-.281 0-.453s.071-.391.118-.656c.047-.266.094-.516.141-.438.047.078.766.703.828.75.062.047-.225 0-.456-.125s-.356-.109-.388.125c-.031.234-.078.969.281 1.172.359.203-.031-.25-.078-.469-.047-.219-.016-.688.078-.641.094.047.75.531.953.609.203.078.094.609-.109.906-.203.297-.646.594-.737.328-.091-.266-.437-.547-.631-.406-.194.141-.101.406-.101.406s-.256 0-.229.281c.026.281.386.562 1.261.438.875-.125 1.969-.469 1.906-2 .328-1.344.078-1.922.031-2.297-.047-.375-.188-.927-.141-.971.046-.043.406.067.562.27z"/><path fill="#CC1530" d="M23.797 24.797c.128-.448 1.219-.859 1.562-.797.344.062.969.312.609.625-.359.312-1.125.578-1.641.688-.515.109-.624-.188-.53-.516zm7.282 0c-.128-.448-1.219-.859-1.562-.797-.344.062-.969.312-.609.625.359.312 1.125.578 1.641.688.514.109.624-.188.53-.516z"/><path fill="#FBFAE7" d="M31.402 24.203s-.484-.527-.953-.209c-.469.318-1.824 1.443-3.021 1.443-1.197 0-2.553-1.125-3.021-1.443-.469-.318-.953.209-.953.209s.234.109.188.344c-.047.234 0 .641.253.725-.294-.729.731-.365 1.149.064.418.43 1.52.945 2.385.945.865 0 1.967-.516 2.385-.945.418-.43 1.443-.793 1.149-.064.253-.084.3-.49.253-.725-.048-.235.186-.344.186-.344z"/><path fill="#FBFAE7" d="M25.266 23.997c.55-.116 1.266.487 1.391.628s-.062.578-.281.406c-.219-.172-.362-.205-.627-.249-.265-.044-.609-.395-.232-.532-.161.188 0 .44.25.282.249-.157.045-.428-.501-.535zm4.421 0c-.55-.116-1.266.487-1.391.628s.062.578.281.406c.219-.172.362-.205.627-.249.265-.044.609-.395.232-.532.161.188 0 .44-.25.282-.249-.157-.046-.428.501-.535z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..3c61bc79e73b160e6c3445ed08ce30214a10aadb --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M23 12v3.726c0 5.18 2.887 7.072 5.156 8.305 2.27-1.233 4.802-3.125 4.802-8.305V12H23z"/><path fill="#FEC400" d="M28.156 23.43c-2.202-1.231-4.739-3.008-4.739-7.704v-3.059h9.196v3.059c0 4.696-2.255 6.473-4.457 7.704z"/><path fill="#00A728" d="M29.953 20.984c-.062-.547-.516-2.266-1.047-2.781-.531-.516-.75-.117-.75-.117s-.219-.398-.75.117c-.531.516-.984 2.234-1.047 2.781s.062.672.344.672c.125.266.609.312.609.312s.547.359.844 0c.297.359.844 0 .844 0s.484-.047.609-.312c.282 0 .407-.125.344-.672z"/><path fill="#F0082D" d="M28.953 17.576c0 .476.126.861-.781.861s-.781-.386-.781-.861c0-.476.35-.862.781-.862.432 0 .781.386.781.862z"/><path fill="#FF9F3E" d="M26.484 16.953c-.25.422-.641.125-.812-.375s-.859-.641-1.109-.781-.312-.375 0-.547.125-.391.344-.453c-.281-.062-.533.094-.556 0-.022-.094.196-.354.556-.396-.297-.37-.125-1.151 0-1.167s.381.219.511.453.505.188.474.516c.078.078.344.031.594.438.248.406-.002 2.312-.002 2.312z"/><path fill="#FF927F" d="M26.596 16.891c-.354.027-.486-.281-.549-.734-.062-.453-.703-.284-.406-.962.297-.678.408-.267.438-.793s.202-.963.358-.963c.156 0 .359.484.438.688s.379.156.51.859-.025 1.219-.197 1.375c-.172.156-.25.179-.281.355-.032.175-.079.157-.311.175z"/><path fill="#FE9DE0" d="M26.596 13.906c.107.078.111.188 0 .375-.111.188.072.375.082.688.01.312-.152.422-.118.578.034.156.284.453.253.812-.031.359-.105.469-.217.531-.111.062-.064-.188-.041-.422.023-.234-.133-.5-.211-.734-.078-.234.105-.406.154-.641.049-.234-.076-.448-.092-.693-.015-.244.19-.494.19-.494z"/><path fill="#BA5B1F" d="M30.219 14.5c.047-.344.031-.875-.078-1.062-.109-.188-.281-.297-.172-.328.109-.031.625.516.344 1.625-.282 1.109-.094-.235-.094-.235z"/><path fill="#BA5B1F" d="M30.164 14.404c-.211-.123-.484-.436-.457-.607.027-.172.23-.484.262-.422.031.062-.094.256 0 .511s.14.269.267.439c.126.171-.072.079-.072.079zm-.115.237c-.126-.152-1.517-1.047-1.377-1.109s1.338.688 1.528 1.109c.191.421-.151 0-.151 0z"/><path fill="#BA5B1F" d="M29.969 14.906c-.509-.505-1.766-.594-1.703-.672s1.674.07 1.899.535c.226.465-.196.137-.196.137z"/><path fill="#BA5B1F" d="M29.934 15.173c-.574-.298-1.578-.361-1.67-.345-.092.016.969-.298 1.727.171.759.47-.057.174-.057.174zm.035.421c-.594-.266-1.469-.188-1.625-.094-.156.094.453-.354.875-.31.422.044.83.132.946.213.116.081.011.283-.196.191z"/><path fill="#BA5B1F" d="M30.315 14.401c-.072-.384-.073-.708-.588-.669-.515.039-.608 1.002-.479 2.346.128 1.344-.028 1.784-.052 1.861-.023.077.287-.267.265-.861-.022-.594-.153-1.899-.111-2.379.042-.48.275-.84.585-.746.31.095.24.336.231.629-.01.293.149-.181.149-.181z"/><path fill="#BA5B1F" d="M30.656 16.9s.156-.088.359-1.15c.203-1.062-.234-1.516-.625-1.516s-.828.453-.625 1.516c.203 1.062.359 1.15.359 1.15s-.479.455-.411.676c.067.221.677.226.677.226s.609-.005.677-.226c.068-.221-.411-.676-.411-.676z"/><path fill="#BA5B1F" d="M30.567 14.5c-.047-.344-.031-.875.078-1.062s.281-.297.172-.328c-.109-.031-.625.516-.344 1.625.282 1.109.094-.235.094-.235z"/><path fill="#BA5B1F" d="M30.622 14.404c.211-.123.484-.436.457-.607s-.23-.484-.262-.422c-.031.062.094.256 0 .511s-.14.269-.267.439c-.126.171.072.079.072.079zm.115.237c.126-.152 1.518-1.047 1.377-1.109-.141-.062-1.338.688-1.528 1.109-.19.421.151 0 .151 0z"/><path fill="#BA5B1F" d="M30.817 14.906c.509-.505 1.766-.594 1.703-.672s-1.674.07-1.899.535c-.225.465.196.137.196.137z"/><path fill="#BA5B1F" d="M30.853 15.173c.574-.298 1.578-.361 1.67-.345.092.016-.969-.298-1.728.171-.759.47.058.174.058.174zm-.036.421c.594-.266 1.469-.188 1.625-.094.156.094-.453-.354-.875-.31-.422.044-.83.132-.946.213-.116.081-.011.283.196.191z"/><path fill="#BA5B1F" d="M30.472 14.401c.072-.384.073-.708.588-.669.515.039.607 1.002.479 2.346s.028 1.784.052 1.861c.024.077-.287-.267-.265-.861.022-.594.153-1.899.111-2.379-.042-.48-.275-.84-.585-.746-.31.095-.24.336-.231.629.009.293-.149-.181-.149-.181z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..d106ba84d55a9f12c499281ba92828338ad68ed1 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002664" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FECB00" d="M12 5h12v26H12z"/><path fill="#C60C30" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..cf4bfacfcd9dd25a4b10c1f2d38c3ebe9bef2440 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#002395" d="M32 5H18v12H0v10c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 16h19v2H0z"/><path fill="#002395" d="M6 17H0V9c0-2.209 1.791-4 4-4h2v12z"/><path fill="#EEE" d="M6 5h6v12H6zm11 0h2v13h-2z"/><path fill="#ED2939" d="M12 5h6v12h-6z"/><g fill="#FFF"><path d="M29.964 20.094l-1.701 2.631v-4.763h2.268l.838-.962h-7.76l.838.962h2.269v4.763l-1.701-2.631-2.475 3.867h1.236l1.239-2.035 2.474 4.356 2.475-4.356 1.238 2.035h1.237z"/><path d="M27 19.005h3.132l-.688.941H27zm-3.224 4.018h2.476v.617h-2.476zm4.952 0h2.475v.617h-2.475zm-1.239 4.183l.299 1.027h1.034l-.816.661.299 1.014-.816-.62-.815.604.299-1-.817-.659h1.007zM22.152 18l.299 1.026h1.034l-.815.632.298 1-.816-.627-.815.6.299-.973-.816-.632h1.006zm10.673 0l.3 1.026h1.033l-.815.632.299 1-.817-.627-.814.6.298-.973-.816-.632H32.5zm-8.265 7.15l.298 1.027h1.035l-.816.641.298 1.005-.815-.625-.816.601.3-.982-.816-.64h1.005zm5.858 0l.3 1.027h1.033l-.816.641.299 1.005-.816-.625-.814.601.297-.982-.815-.64h1.007z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..4a05a3037e30e171ac29963952598bfd21476ed4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#006A4E" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-1.2H0V27zm15.526-6.5H15.5l20.5.1v-5.2H15.526zM32 5H15.526v5.2H36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCE00" d="M15.526 15.333v.067H36v-5.2H15.526zM.026 20.5L0 25.8h36v-5.2l-20.5-.1z"/><path fill="#D21034" d="M4 5C1.879 5 .161 6.656.026 8.743V20.5h15.5V5H4z"/><path fill="#FFF" d="M12.339 11.413H8.885l-.013-.04L7.776 8l-.022.068-1.087 3.345H3.078l2.858 2.077.045.033-1.067 3.285-.042.129 2.904-2.11 2.903 2.11-1.109-3.414 2.904-2.11z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ed.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..0bd4165c00de9a1f7c16965ece8e6c0e8cbdd342 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A7122D" d="M0 26.518V27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-.482H0z"/><path fill="#EEE" d="M0 22.181h36v4.485H0z"/><path fill="#292648" d="M0 13.513h36v8.821H0z"/><path fill="#EEE" d="M0 9.181h36v4.485H0z"/><path fill="#A7122D" d="M0 9.333V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v.333H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ef.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ef.svg new file mode 100644 index 0000000000000000000000000000000000000000..6045f4657623f66d8b46efc0a6d40db13f612155 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ef.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C00" d="M32 5H4C1.791 5 0 6.791 0 9v4.5h36V9c0-2.209-1.791-4-4-4z"/><path fill="#060" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4.5H0V27z"/><path fill="#EEE" d="M0 13.5h36v9H0z"/><g fill="#FFAC33"><path d="M16.13 21.455c-.408.116-.646-.272-.646-.272l.323-.145.156-.5.323.465h.364c.001-.001-.082.327-.52.452zm5.146.437c-.625-.188-2.082-.438-3.188-.438-1.104 0-2.562.25-3.188.438s-.479.791 0 .603 1.646-.375 3.188-.375c1.542 0 2.709.188 3.188.375.48.188.625-.415 0-.603zm-2.937-1.125l-.25-.417-.25.417-.438.188s.312.353.688.353.688-.353.688-.353l-.438-.188zm1.709.688c.408.116.646-.272.646-.272l-.323-.145-.156-.5-.322.465h-.365c-.002-.001.082.327.52.452z"/><path d="M22.443 20.2c-.104-.267-.362.448-1.062.338-.792-.125-.958-.917-.958-.917s-.625.626-1.271.334c-.646-.292-.812-.708-.812-1.167 0-.459-.059-.796 0-.979.094-.292.438-.501.792-.167.292-.416-.208-1.291-1.042-1.291-.833 0-1.333.875-1.042 1.291.354-.333.698-.125.792.167.059.183 0 .52 0 .979 0 .459-.167.875-.812 1.167s-1.271-.334-1.271-.334-.167.792-.958.917c-.7.11-.958-.605-1.062-.338-.104.267.458 1.067 1.25.808.792-.26.896-.928.896-.928s.407.749 1.354.458c.714-.22.854-.896.854-.896s.141.676.854.896c.948.291 1.354-.458 1.354-.458s.104.668.896.928c.79.259 1.353-.542 1.248-.808zm-5.042-3.1c.207-.44.688-.375.688-.375s.48-.065.688.375c-.354.041-.688.312-.688.312s-.334-.27-.688-.312zm-4.062.994l.197.61h.641l-.518.377.198.608-.518-.377-.518.377.197-.608-.518-.377h.641zm.625-2.229l.197.61h.641l-.518.377.198.608-.518-.377-.518.377.197-.608-.518-.377h.641zm1.676-1.792l.198.61h.641l-.518.377.197.608-.518-.377-.518.377.198-.608-.518-.377h.641zm2.449-.604l.197.609h.641l-.518.377.198.608-.518-.377-.518.377.197-.608-.518-.377h.641zm4.572 4.625l-.197.61h-.641l.518.377-.198.608.518-.377.518.377-.198-.608.519-.377h-.641zm-.625-2.229l-.197.61h-.641l.518.377-.198.608.518-.377.518.377-.198-.608.519-.377h-.641zm-1.676-1.792l-.198.61h-.641l.519.377-.198.608.518-.377.518.377-.198-.608.518-.377h-.641z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..bfa93625b2369aef573e70982dedc844126a9030 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#FFF" d="M3.354 11.146l.342 1.102 1.154-.008-.943.665L4.271 14l-.924-.69-.928.684.371-1.092-.938-.671 1.153.015zM8.101 18l.44 1.417 1.483-.01-1.212.857.469 1.407-1.189-.887-1.195.879.477-1.404-1.207-.864 1.484.019zm.186-11.481l.342 1.101 1.153-.008-.942.666.364 1.095-.924-.69-.928.684.37-1.093-.938-.671 1.154.015zm4.777 4.401l.242.78.816-.006-.667.471.258.775-.654-.488-.658.484.263-.773-.664-.475.816.01z"/><path fill="#FED100" d="M32 29H5s-.266-.172-.266-.5S5 28 5 28h27l1.484.5L32 29zM5 27s5-2 11-8S26 9 28 8c-1.753 1.753-3.771 14 1.229 18 0 0 2.771.521 2.771 1H5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f1.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f1.svg new file mode 100644 index 0000000000000000000000000000000000000000..6030072a3add8e4011b0c87478152d2d6943ed1f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DC241F" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFC726" d="M16 18L1.296 29.947c.079.072.16.141.244.207L23.667 18 1.54 5.846c-.084.066-.166.135-.244.207L16 18z"/><path fill="#141414" d="M1.296 6.053l-.002.001C.499 6.785 0 7.834 0 9v18c0 1.166.499 2.216 1.296 2.947L16 18 1.296 6.053z"/><path fill="#FFF" d="M4.761 19.01l.492 3.269 1.523-2.934 3.262.542-2.32-2.355 1.523-2.934-2.957 1.478-2.32-2.355.493 3.269L1.5 18.468z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..a57c35ccf433c1b58c8f055b686aa237d2a460ba --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#29AE66" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#CA3745" d="M4 5h7v26H4z"/><path fill="#FAAE29" d="M4 8.312l.805.805-.219.219.32.32.211-.211.664.664-.656.657-.273-.274-.29.289.243.242-.805.711v-.375l.441-.418-.238-.191.608-.607.351.304.328-.328-.351-.351-.246.246-.641-.641.24-.24L4 8.688zm0 4.626l.805.804-.219.219.32.32.211-.211.664.664-.656.657-.273-.274-.29.289.243.242-.805.711v-.375l.441-.418-.238-.191.608-.607.351.304.328-.328-.351-.351-.246.246-.641-.641.24-.24L4 13.312zm0 4.718l.805.805-.219.219.32.32.211-.211.664.664-.656.656-.273-.273-.29.289.243.242-.805.711v-.375l.441-.418-.238-.191.608-.608.351.305.328-.328-.351-.352-.246.246-.641-.64.24-.24L4 18.031zm0 4.656l.805.805-.219.219.32.32.211-.211.664.664-.656.657-.273-.274-.29.289.243.242-.805.711v-.375l.441-.418-.238-.191.608-.607.351.304.328-.328-.351-.351-.246.246-.641-.641.24-.24L4 22.688zm7-14l-.805.805.219.219-.32.32-.211-.211-.664.664.656.657.273-.274.29.289-.243.242.805.711v-.375l-.441-.418.238-.191-.608-.607-.351.304-.328-.328.351-.351.246.246.641-.641-.24-.24.492-.445zM4.562 5.688l.29-.29.273.274.656-.656L5.766 5h-.301l.025.025-.328.329-.351-.305-.608.607.238.192L4 6.266v.375l.805-.711zm6.235-.032l-.608-.607-.351.305-.328-.329L9.535 5h-.301l-.015.016.656.656.273-.274.29.29-.243.242.805.711v-.375l-.441-.418zM11 12.938l-.805.804.219.219-.32.32-.211-.211-.664.664.656.657.273-.274.29.289-.243.242.805.711v-.375l-.441-.418.238-.191-.608-.607-.351.304-.328-.328.351-.351.246.246.641-.641-.24-.24.492-.446zm0 4.718l-.805.805.219.219-.32.32-.211-.211-.664.664.656.656.273-.273.29.289-.243.242.805.711v-.375l-.441-.418.238-.191-.608-.608-.351.305-.328-.328.351-.352.246.246.641-.64-.24-.24.492-.446zm0 4.656l-.805.805.219.219-.32.32-.211-.211-.664.664.656.657.273-.274.29.289-.243.242.805.711v-.375l-.441-.418.238-.191-.608-.607-.351.304-.328-.328.351-.351.246.246.641-.641-.24-.24.492-.445z"/><path fill="#29AE66" d="M10.021 6.938v-.396l-.583-.354H9l-.708-.368H6.708L6 6.188h-.438l-.583.354v.396l-.541.333v.917l.541.333v.396l.583.354H6l.708.368h1.584L9 9.271h.438l.583-.354v-.396l.541-.333v-.917z"/><path fill="#FAAE29" d="M4.928 7.728v-.391l.462-.285v-.337l.498-.303h.374l.604-.313h.676v1.629z"/><path fill="#FFF" d="M4.887 7.729v.392l.462.284v.338l.498.302h.373l.605.313H7.5V7.729zm5.226 0v-.391l-.462-.284v-.338l-.498-.302H8.78l-.605-.313H7.5v1.628z"/><path fill="#FAAE29" d="M10.113 7.729v.392l-.462.284v.338l-.498.302H8.78l-.605.313H7.5V7.729zm-5.185 3.833h.676v.729h-.676zm.676-.104h.676v.729h-.676zm.677-.26h.676v.729h-.676zm3.135.364h.676v.729h-.676zm-.677-.104h.676v.729h-.676zm-.677-.26h.676v.729h-.676z"/><path fill="#FAAE29" d="M6.958 10.833h1.105v.901H6.958zm-2.03 1.651h.676v.729h-.676zm.676.104h.676v.729h-.676zm.677.261h.676v.729h-.676zm3.135-.365h.676v.729h-.676zm-.677.104h.676v.729h-.676zm-.677.261h.676v.729h-.676z"/><path fill="#FAAE29" d="M6.958 13.042h1.105v.901H6.958z"/><path fill="#FFF" d="M8.549 24.608H6.491l-1.456.932v1.316l1.456.931h2.058l1.456-.931V25.54z"/><path fill="#29AE66" d="M8.383 15.646H6.657l-1.221.86v1.217l1.221.86h1.727l1.221-.86v-1.217l-1.222-.86zm.736 1.936l-.937.66H6.858l-.937-.66v-.934l.937-.66h1.324l.937.66v.934zm-.526 6.96H6.447l-1.517.971v1.371l1.517.97h2.145l1.517-.97v-1.371l-1.516-.971zm1.059 2.221l-1.25.799H6.637l-1.25-.799v-1.13l1.25-.799h1.766l1.25.799v1.13zm.102-5.325v-.443h-.442v-.493H5.719v.493h-.494v.443h-.433v.646h.433v.479h.494v.521h3.594v-.521h.441v-.479h.517v-.646h-.517zm-.677 1.374H5.959v-2.084h3.118v2.084z"/><path fill="#29AE66" d="M7.5 20.25l-1.896 1.125v.729l1.896 1.23 1.916-1.188v-.771z"/><path fill="#CA3745" d="M6.651 25.766l.849-.491.848.491v.979l-.848.489-.849-.489z"/><path fill="#FAAE29" d="M8.348 30.084l-.244.166s-.208-.396-.771-.438-.875.188-1.354.219c-.479.031-1.955-1.086-1.188-2.797.688.495.331 1.099.645 1.391.314.292.645.49.772.834.128.344.726.059 1.125.125.625.104 1.015.5 1.015.5z"/><path fill="#FAAE29" d="M6.651 30.084l.244.166s.208-.396.771-.438.876.188 1.355.219 1.955-1.086 1.187-2.797c-.687.495-.331 1.099-.645 1.391-.314.292-.645.49-.772.834-.128.344-.726.059-1.125.125-.625.104-1.015.5-1.015.5z"/><path fill="#FFF" d="M18.18 8.289c.65.564 1.07 1.387 1.07 2.316 0 1.7-1.378 3.078-3.078 3.078-.585 0-1.125-.172-1.591-.455.571.622 1.384 1.018 2.294 1.018 1.726 0 3.125-1.399 3.125-3.125 0-1.26-.748-2.337-1.82-2.832zm-2.334-.422l-.246.483.383.384-.535-.085-.247.483-.084-.535-.536-.085.483-.246-.085-.537.384.384z"/><path fill="#FFF" d="M17.377 8.795l-.246.483.384.384-.536-.085-.247.483-.084-.536-.536-.085.483-.246-.084-.536.383.384zm-1.531.665l-.246.483.383.384-.535-.085-.247.483-.084-.536-.536-.085.483-.246-.085-.536.384.384zm-1.594.809l-.246.483.384.384-.536-.085-.247.484-.084-.536-.536-.085.483-.246-.084-.536.383.384zm1.594.902l-.246.483.383.384-.535-.085-.247.483-.084-.536-.536-.085.483-.246-.085-.536.384.384z"/><path fill="#CA3745" d="M7.062 20.771h.915v.615h-.915zm0 1.401h.915v.615h-.915z"/><path fill="#FAAE29" d="M5.604 21.484h1.253v.615H5.604zm2.584 0h1.228v.615H8.188z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..c13e73024870d34b6c4bee650a2f6b5cdc857259 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E70013" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><circle fill="#FFF" cx="18" cy="18" r="6.5"/><path fill="#E70013" d="M15.4 18c0-2.154 1.746-3.9 3.9-3.9 1.019 0 1.946.391 2.641 1.031-.887-1.216-2.321-2.006-3.941-2.006-2.692 0-4.875 2.183-4.875 4.875s2.183 4.875 4.875 4.875c1.62 0 3.055-.79 3.941-2.006-.695.64-1.622 1.031-2.641 1.031-2.154 0-3.9-1.746-3.9-3.9z"/><path fill="#E70013" d="M19.645 16.937l-1.249-1.719v2.125L16.375 18l2.021.657v2.125l1.249-1.719 2.021.656L20.417 18l1.249-1.719z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f4.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..20a9555ba8096a15ee188ec7c269c78d129194fe --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C10000" d="M32 5H15v13H0v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEEDED" d="M15 5H4C1.791 5 0 6.791 0 9v9h15V5zm-3 8H9v3H6v-3H3v-3h3V7h3v3h3v3z"/><path fill="#C10000" d="M9 7H6v3H3v3h3v3h3v-3h3v-3H9z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f7.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..861da57e372ee2f6c924346cc2833bf96ef1e67c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E30917" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#EEE" d="M16 24c-3.314 0-6-2.685-6-6 0-3.314 2.686-6 6-6 1.31 0 2.52.425 3.507 1.138-1.348-1.524-3.312-2.491-5.507-2.491-4.061 0-7.353 3.292-7.353 7.353 0 4.062 3.292 7.354 7.353 7.354 2.195 0 4.16-.967 5.507-2.492C18.521 23.575 17.312 24 16 24zm3.913-5.77l2.44.562.22 2.493 1.288-2.146 2.44.561-1.644-1.888 1.287-2.147-2.303.98-1.644-1.889.22 2.494z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..578c8eb4066905cac5ae56dbad1b5577d381585c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M1.148 6.196C.438 6.918 0 7.908 0 9v18c0 2.209 1.791 4 4 4h20.99L1.149 6.195l-.001.001zM32 5H11.01l23.841 24.805C35.562 29.083 36 28.093 36 27V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M2.23 5.412c-.404.2-.769.465-1.081.783L24.99 31h1.835L2.23 5.412zM11.01 5H9.175l24.594 25.588c.404-.2.77-.465 1.082-.783L11.01 5z"/><path fill="#141414" d="M4 5c-.635 0-1.236.148-1.769.412L26.825 31H32c.635 0 1.235-.148 1.768-.411l.002-.001L9.175 5H4z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..6558df605c3e4c16b48e280c440c149879509e15 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5B97B1" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path d="M13.598 27.772l-.487-1.499-.487 1.499h-1.577l1.276.927-.487 1.5 1.275-.927 1.276.927-.487-1.5 1.275-.927zm6.485-1.166l.487-1.499-1.276.926-1.275-.926.487 1.499-1.276.927h1.577l.487 1.5.487-1.5h1.577zm.487-6.785l-1.276.926-1.275-.926.487 1.499-1.276.927h1.577l.487 1.5.487-1.5h1.577l-1.275-.927zm4.473 5.449l.487-1.499-1.276.926-1.275-.926.487 1.499-1.276.927h1.577l.487 1.499.488-1.499h1.576zm-1.276-10.574l.487 1.499.488-1.499h1.576l-1.275-.927.487-1.5-1.276.927-1.275-.927.487 1.5-1.276.927zm4.546 6.535l-.487-1.499-.488 1.499h-1.576l1.275.927-.487 1.5 1.276-.927 1.275.927-.487-1.5 1.276-.927zm.043-8.104l.487 1.5.488-1.5h1.576l-1.275-.926.487-1.5-1.276.927-1.275-.927.487 1.5-1.276.926zm4.567 5.136l-.487-1.499-.487 1.499h-1.577l1.276.927-.488 1.5 1.276-.927 1.276.927-.488-1.5 1.276-.927zm-1.275-9.216l-.488 1.5 1.276-.927 1.276.927-.488-1.5L34.5 8.12h-1.577l-.487-1.499-.487 1.499h-1.577z" fill="#FFCE00"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 8.969V5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..4cd304e16a970353e01c24b95ed53e71e8094b5f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FE0000" d="M32 5H17v13H0v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#000095" d="M17 5H4C1.791 5 0 6.791 0 9v9h17V5zm-6.063 4.61l2.035-.548-1.491 1.487c-.121-.348-.307-.665-.544-.939zm.251 1.89c0 1.346-1.091 2.438-2.438 2.438S6.312 12.846 6.312 11.5 7.404 9.062 8.75 9.062s2.438 1.092 2.438 2.438zm0-4.222l-.548 2.035c-.273-.237-.591-.423-.939-.544l1.487-1.491zM8.75 6.625l.542 2.034c-.175-.033-.357-.052-.542-.052s-.367.019-.542.052l.542-2.034zm-.951 2.144c-.348.121-.665.307-.939.544l-.548-2.035 1.487 1.491zm-1.236.841c-.237.273-.423.591-.544.939L4.528 9.062l2.035.548zm-.654 1.348c-.034.176-.052.357-.052.542 0 .185.018.367.052.542L3.875 11.5l2.034-.542zm.11 1.492c.121.348.308.666.544.939l-2.035.548 1.491-1.487zm.293 3.272l.548-2.035c.273.236.591.423.939.544l-1.487 1.491zm2.438.653l-.542-2.034c.176.034.357.052.542.052s.367-.018.542-.052l-.542 2.034zm.951-2.144c.348-.121.666-.308.939-.544l.548 2.035-1.487-1.491zm1.236-.841c.237-.273.423-.591.544-.939l1.491 1.487-2.035-.548zm.654-1.348c.034-.176.052-.357.052-.542 0-.185-.018-.367-.052-.542l2.034.542-2.034.542z"/><path fill="#FFF" d="M9.292 8.659L8.75 6.625l-.542 2.034c.175-.033.357-.052.542-.052s.367.019.542.052zM5.857 11.5c0-.185.018-.367.052-.542l-2.034.542 2.034.542c-.033-.175-.052-.357-.052-.542zm2.351 2.841l.542 2.034.542-2.034c-.176.034-.357.052-.542.052s-.367-.019-.542-.052zm3.435-2.841c0 .185-.018.367-.052.542l2.034-.542-2.034-.542c.033.175.052.357.052.542zm-.455-4.222L9.701 8.769c.348.122.666.308.939.544l.548-2.035zm-.251 6.112l2.035.548-1.491-1.487c-.121.348-.307.665-.544.939zm-4.625 2.332l1.487-1.491c-.348-.121-.666-.308-.939-.544l-.548 2.035zm.251-6.112l-2.035-.548 1.491 1.487c.121-.348.307-.665.544-.939zm3.138 4.621l1.487 1.491-.548-2.035c-.274.237-.591.423-.939.544zM6.019 12.45l-1.491 1.487 2.035-.548c-.237-.273-.423-.59-.544-.939zm1.78-3.681L6.312 7.278l.548 2.035c.274-.237.591-.423.939-.544zm5.173.293l-2.035.548c.237.273.423.591.544.939l1.491-1.487z"/><circle fill="#FFF" cx="8.75" cy="11.5" r="2.438"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..a9ddb8ed062e1f17a6b9d7bc9f88d1480e758508 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1f9-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#1EB53A" d="M4 5C1.791 5 0 6.791 0 9v15.627L26.456 5H4z"/><path fill="#00A3DD" d="M32 31c2.209 0 4-1.791 4-4V11.33L9.479 31H32z"/><path fill="#141414" d="M32 5h-2.532L0 26.638V27c0 2.209 1.791 4 4 4h2.467L36 9.318V9c0-2.209-1.791-4-4-4z"/><path fill="#FBD035" d="M26.456 5L0 24.627v2.011L29.468 5zM9.479 31L36 11.33V9.318L6.467 31z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..989b5c28f2926348a9c68fbe9878df179efc0458 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#005BBB" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFD500" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-9h36v9z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..6602ca9ca95d86f139bd91562e34620cd40f6ba0 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D90001" d="M36 27v-1H0v1c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4z"/><path fill="#FCDC02" d="M0 22h36v4H0z"/><path fill="#141414" d="M0 18h36v4H0z"/><path fill="#D90001" d="M0 14h36v4H0z"/><path fill="#FCDC02" d="M0 10h36v4H0z"/><path fill="#141414" d="M0 9v1h36V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9z"/><circle fill="#FFF" cx="18" cy="18" r="4"/><path fill="#D90000" d="M17.344 15.031l-.267-.703s.579-.203 1.142 0c.429.155.469.703.469.703l-.671.203-.673-.203z"/><path fill="#FCDC02" d="M17.594 14.922v-.684s.111-.043.423 0 .453.262.453.262l-.438.532-.438-.11z"/><path fill="#141414" d="M17.745 16.896c-.083-.146 0-1 .239-1.062.239-.062.698-.812 0-1.062s-.844.479-.844.479-.69.203-.604.375c.083.167.667-.062.792.083s-.062.354-.562.938-.167 1.375.062 1.579.5.359.708.546.448.292.448.292v.604s-.698.062-1.031.021-.562.188-.646.458.125.417.125.209.083-.084.102.083c.019.167.168.104.168-.104s.083-.125.104-.021.167-.042.188-.167.208-.188.375-.229.614.041.614.041v1.104s-.927.062-1.01.188.562.104.562.104-.188.354-.104.375.667-.354.896-.396.583.104.625 0-.562-.25-.625-.354-.188-1.062-.188-1.062.271-.022.605-.001c.333.021.25-.271.042-.562s-.021-.375.333-.312c.354.063.625 0 .625-.563s-1.916-1.438-1.999-1.584zm.729 2.708h-.229l.083-.417c0 .001.292.417.146.417z"/><path fill="#D90000" d="M17.474 15.812c.029-.249-.375-.229-.396 0s.355.355.396 0z"/><path fill="#9CA69C" d="M17.75 17.047c.115-.041 1.406.547 1.75.703.344.156.303.75.245 1.109s-.261.469-.261.469-.225-.58-.938-.859c-.957-.375-1.234-1.266-.796-1.422z"/><path fill="#D90000" d="M19.203 17.734c.421.11 1.312.312 1.391 1.219.078.906-.849 1.438-.849 1.438l.155-.281-.275.094.12-.204-.433.094s.725-.578.472-1.094c.019.43-.269.547-.269.547s.248-.596-.828-1.25l.281-.072-.28-.225.594.225-.282-.35.562.219-.359-.36z"/><path fill="#9CA69C" d="M17.594 15.336c0 .056-.045.102-.102.102-.056 0-.102-.045-.102-.102 0-.056.045-.102.102-.102.056 0 .102.046.102.102z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..d51f600ab11eff5c782a04a3ed3dbd8704857d3f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#B22334" d="M35.445 7C34.752 5.809 33.477 5 32 5H18v2h17.445zM0 25h36v2H0zm18-8h18v2H18zm0-4h18v2H18zM0 21h36v2H0zm4 10h28c1.477 0 2.752-.809 3.445-2H.555c.693 1.191 1.968 2 3.445 2zM18 9h18v2H18z"/><path fill="#EEE" d="M.068 27.679c.017.093.036.186.059.277.026.101.058.198.092.296.089.259.197.509.333.743L.555 29h34.89l.002-.004c.135-.233.243-.483.332-.741.034-.099.067-.198.093-.301.023-.09.042-.182.059-.275.041-.22.069-.446.069-.679H0c0 .233.028.458.068.679zM0 23h36v2H0zm0-4v2h36v-2H18zm18-4h18v2H18zm0-4h18v2H18zM0 9c0-.233.03-.457.068-.679C.028 8.542 0 8.767 0 9zm.555-2l-.003.005L.555 7zM.128 8.044c.025-.102.06-.199.092-.297-.034.098-.066.196-.092.297zM18 9h18c0-.233-.028-.459-.069-.68-.017-.092-.035-.184-.059-.274-.027-.103-.059-.203-.094-.302-.089-.258-.197-.507-.332-.74.001-.001 0-.003-.001-.004H18v2z"/><path fill="#3C3B6E" d="M18 5H4C1.791 5 0 6.791 0 9v10h18V5z"/><path fill="#FFF" d="M2.001 7.726l.618.449-.236.725L3 8.452l.618.448-.236-.725L4 7.726h-.764L3 7l-.235.726zm2 2l.618.449-.236.725.617-.448.618.448-.236-.725L6 9.726h-.764L5 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 9l-.235.726zm-8 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L5 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 13l-.235.726zm-6-6l.618.449-.236.725L7 8.452l.618.448-.236-.725L8 7.726h-.764L7 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 7l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 11l-.235.726zM6.383 12.9L7 12.452l.618.448-.236-.725.618-.449h-.764L7 11l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 11l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 11l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 15l-.235.726zM6.383 16.9L7 16.452l.618.448-.236-.725.618-.449h-.764L7 15l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 15l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 15l-.235.726z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..a035a767cddde820bc2281a8334c46a94e6e1ce3 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4B92DB" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><g fill="#FFF"><path d="M10.554 15.53c.149-.305.393-.596.68-.813.64-.483 1.34-1.108 1.35-1.93-.212.591-.856.836-1.285 1.24-.227.214-.4.471-.502.738l-.015-.012c.053-.237.154-.451.222-.68.187-.626.153-1.375.763-1.793-.314.08-.577.283-.812.544-.492.545-.449 1.35-.384 2.068.02.222.008.411-.017.638zm3.217 7.731c-.71-.573-.817-1.432-1.134-2.186-.197-.468-.517-.889-.859-1.298.376.751.214 1.72.701 2.428.153.222.366.434.562.612l-.009.009c-.178-.083-.339-.207-.501-.342-.853-.709-2.136-.8-2.647-1.956.138.849.812 1.601 1.54 2.077.692.453 1.578.402 2.347.656z"/><path d="M10.569 20.879c.481.379 1.055.675 1.493 1.008-.086-.218-.227-.419-.284-.65-.258-1.04-.114-2.243-.56-3.205.083.547-.134 1.03-.184 1.55-.041.428.034.843.2 1.203.049.106.138.202.163.311-.16-.144-.274-.329-.384-.508-.517-.837-1.602-1.382-1.676-2.4-.037.453.003.934.154 1.336.21.559.613.989 1.078 1.355zm.73-7.131c.341-.32.737-.557 1.026-.939.347-.459.649-.97 1.101-1.366-.616.24-1.276.485-1.676 1.117-.233.369-.267.806-.451 1.188zm4.304 9.971c.129-.032.286-.022.406-.065-.498-.101-.979-.252-1.365-.605-.554-.507-1.045-1.047-1.638-1.441.464.625.596 1.532 1.444 1.852.15.057.322.066.452.148-.163.025-.306-.025-.458-.058-1.093-.233-2.428.067-3.247-.865.311.609.951 1.09 1.565 1.293.953.313 1.946-.037 2.841-.259z"/><path d="M10.724 19.841l.046.037c-.049-.336-.074-.698.021-1.019.145-.513.326-1.012.422-1.544.074-.413.159-.877.111-1.278-.055.216-.112.429-.231.613-.45.697-.913 1.515-.597 2.4-.007.01-.018.022-.029.015-.127-.292-.155-.625-.237-.939-.218-.831-.858-1.526-.67-2.487-.099.209-.139.444-.191.671-.111.588 0 1.211.16 1.751.198.677.86 1.161 1.195 1.78z"/><path d="M11.557 15.366c.149-.302.242-.643.283-.976-.055.142-.142.273-.259.385-.497.471-1.083.936-1.196 1.603-.016.095-.024.193-.052.286-.022.009-.022-.015-.031-.021l.062-.828c.06-.807-.365-1.705.102-2.416-.016-.003-.025.009-.037.016-.425.542-.708 1.135-.708 1.862 0 .898.517 1.525.581 2.369.133-.88.872-1.505 1.255-2.28zm14.215 2.761c-.082.313-.11.646-.237.939-.012.006-.022-.006-.029-.015.315-.885-.147-1.703-.597-2.4-.118-.183-.175-.397-.231-.613-.049.401.037.864.111 1.278.095.532.277 1.031.422 1.544.095.321.07.683.021 1.019l.046-.037c.335-.619.997-1.103 1.197-1.778.16-.54.27-1.164.16-1.751-.052-.227-.092-.463-.191-.671.186.959-.454 1.653-.672 2.485zm-2.302 4.357c-.162.135-.323.259-.501.342l-.009-.009c.197-.178.41-.39.562-.612.488-.708.325-1.677.701-2.428-.342.409-.662.83-.859 1.298-.317.754-.424 1.613-1.134 2.186.768-.253 1.655-.203 2.346-.656.727-.476 1.401-1.228 1.54-2.077-.51 1.156-1.793 1.246-2.646 1.956z"/><path d="M21.099 23.607c.13-.082.302-.092.452-.148.848-.32.98-1.227 1.444-1.852-.593.394-1.084.934-1.638 1.441-.386.353-.866.504-1.365.605.12.044.276.034.406.065.895.222 1.888.573 2.841.258.615-.203 1.255-.683 1.565-1.293-.819.932-2.154.632-3.247.865-.152.034-.295.084-.458.059zm3.505-2.511c.025-.108.114-.205.163-.311.166-.359.241-.775.2-1.203-.05-.52-.267-1.003-.184-1.55-.446.962-.302 2.165-.56 3.205-.057.23-.197.432-.284.65.438-.333 1.012-.629 1.493-1.008.465-.366.868-.796 1.078-1.355.151-.403.19-.883.153-1.336-.074 1.019-1.158 1.563-1.676 2.4-.109.179-.223.364-.383.508zm1.033-5.28l.062.828c-.009.006-.009.031-.031.021-.028-.092-.036-.19-.052-.286-.113-.667-.699-1.132-1.196-1.603-.118-.112-.204-.243-.259-.385.041.333.134.673.283.976.383.775 1.122 1.4 1.254 2.28.064-.844.581-1.471.581-2.369 0-.727-.283-1.32-.708-1.862-.012-.006-.021-.018-.037-.016.469.711.043 1.609.103 2.416z"/><path d="M24.998 14.074c.068.229.168.443.222.68l-.015.012c-.101-.267-.275-.524-.502-.738-.428-.404-1.073-.649-1.285-1.24.01.822.71 1.446 1.35 1.93.287.217.531.508.68.813-.025-.227-.036-.416-.016-.638.066-.718.108-1.523-.384-2.068-.235-.261-.499-.464-.812-.544.608.418.575 1.167.762 1.793zM21.225 24.34c-.736-.305-1.485-.711-2.324-.711-.305 0-.607.052-.901.14-.294-.089-.595-.14-.901-.14-.839 0-1.588.406-2.324.711-.666.276-1.549.222-2.139-.185.292.366.682.592 1.086.745.749.299 1.624.07 2.262-.338.459-.294.853-.71 1.4-.71.098 0 .197.015.295.036-.769.307-1.469.845-2.015 1.366.1.115.23.222.352.32.608-.628 1.297-1.304 1.983-1.585.687.281 1.376.957 1.983 1.585.122-.099.252-.206.352-.32-.545-.521-1.246-1.058-2.015-1.366.099-.021.197-.036.295-.036.547 0 .941.416 1.4.71.638.408 1.512.637 2.262.338.403-.153.794-.378 1.086-.745-.587.407-1.471.461-2.137.185z"/><path d="M24.702 13.748c-.184-.382-.218-.819-.452-1.189-.4-.632-1.06-.877-1.676-1.117.452.397.754.907 1.101 1.366.29.383.686.62 1.027.94zm-12.136.565l-.069-.037c-.403.817-.631 1.735-.631 2.706 0 .594.085 1.174.247 1.729l.145-.036c-.152-.52-.235-1.063-.242-1.618h1.106c.007.463.078.916.209 1.348l.143-.036c-.128-.42-.198-.861-.205-1.312h1.002c.003.148.021.293.04.438-.072.008-.141.031-.141.031l-.031.101c-.068.013-.111.126-.111.126-.056.019-.099.088-.08.107.018.019-.031.025-.031.025v.138l-.031.044.006.151c.037 0 .031.069.031.069-.062.006-.05.088-.05.088l-.13.044-.025.038-.161-.006-.039.04c-.013-.04-.032-.078-.044-.119l-.143.036c.004.015.011.029.016.043h-.185l-.012-.031-.062-.013-.006-.069-.093.006-.019.038-.099.006c.006.063-.099.157-.111.132-.013-.025-.081-.094-.05-.107.031-.013.111-.025.111-.025v-.044l-.229-.006-.025.038-.093.006v.101l-.043.013c-.031.019.006.088.006.088.043.044-.006.113-.006.113-.037.038.031.107.031.107.05.012-.031.05-.031.05.012.063.049.082.049.082-.037.063.025.094.025.094l.006.107.043.025v.069l.025.044h.099l-.006-.157c-.087-.101.074-.126.081-.088.006.038.074.057.074.057.012.094.118.151.148.057.031-.094.056-.038.074.006.019.044.136.151.136.151h.093l.012.088c.105-.006.136.006.179.151.043.144.161.182.161.182l.087-.006c0-.075.087.013.087.05 0 .038.167.182.167.182l.167.038.048.039c.099.124.199.246.311.361l-.782.782c-.692-.709-1.187-1.56-1.458-2.487l-.145.036c.285.976.811 1.87 1.55 2.609.5.5 1.072.903 1.692 1.2l.073-.13c-.587-.28-1.129-.656-1.608-1.123l.782-.782c.406.394.87.709 1.371.938l.073-.129c-.49-.222-.943-.529-1.339-.913l.138-.138c.009.015.021.021.024.046.012.094.056.075.056.075l.353-.006.124-.107.316-.006c.161-.006.062-.226.031-.226-.021-.017-.021-.054-.016-.093.253.195.519.368.809.492l.073-.129c-.386-.162-.741-.396-1.055-.688l-.037-.034.779-.779c.251.237.544.416.861.529l.074-.131c-.306-.106-.588-.276-.83-.503l.709-.71c.216.193.485.303.773.327l-.001.008s-.023.057.005.066c.028.009.018.014.032.028l-.014.033c-.023-.031-.037.024-.023.038.014.014-.032.005-.032.024s-.014.028 0 .038c.014.009-.005.014-.023.028-.019.014.079.019.079.019s-.018-.038.005-.038l.01.002v.048c-.011-.002-.013.002-.026-.001v.044l-.05.006.043.05.032.004v.103l-.001.006c0 .082-.204.025-.223.006l-.006.113-.037.006.006.075-.006.107.068-.013v.044l.167.006.032-.034v.116l-.001.006-.111.013-.046.024-.004-.001-.017-.035h-.049l-.015.02c-.15-.021-.303-.033-.445-.082l-.074.131c.091.033.185.054.28.076-.015.013-.041.028-.037.037.012.031-.049.063-.049.063l-.056.019-.037.057-.074.025-.012.132-.037.025v.057l-.043.012v.031l-.062.006.037.094.05.025c.087.012.049.119.049.119l.049.006.025.069.049.1c.019.075.074.057.099.05.025-.006.049.075.049.075l.247.006s-.012.025.031.038c.024.007.12.013.205.015v.111c-.458-.009-.901-.104-1.312-.276l-.073.129c.433.184.901.286 1.385.295v1.002c-.659-.01-1.296-.155-1.879-.42l-.073.129c.606.277 1.268.428 1.953.438v1.106c-.879-.011-1.726-.21-2.498-.577l-.073.13c.815.39 1.714.597 2.645.597.976 0 1.917-.228 2.764-.657l-.07-.136c-.79.4-1.679.631-2.62.643v-1.106c.448-.007.883-.081 1.302-.204l.12.037.031.101.05-.006.037-.031.148-.006.074-.069.08-.012.648-.551c.294-.183.578-.386.832-.633l.78.78c-.435.425-.936.783-1.483 1.06l.07.136c.574-.29 1.105-.672 1.573-1.14.492-.492.889-1.054 1.185-1.662l-.001-.001-.086-.047.086.047c.4-.824.612-1.733.612-2.676 0-.802-.154-1.579-.445-2.3-.304-.753-.76-1.445-1.351-2.037-.594-.594-1.289-1.05-2.046-1.355v.001c-.718-.291-1.493-.443-2.291-.443-.986 0-1.918.235-2.744.651l.067.129c.8-.401 1.684-.619 2.603-.63v1.106c-.749.011-1.457.193-2.089.506l.067.129c.622-.308 1.309-.477 2.022-.487v1.002c-.557.011-1.084.145-1.556.375l.068.129c.459-.223.964-.346 1.489-.357v1.106c-.348.01-.677.093-.975.232l.068.13c.282-.131.589-.205.907-.214v1.003c-.117.007-.225.042-.332.077h-.046l-.006-.069.031-.019-.05-.019-.037.05-.012.057-.062.013v.031h-.043v.055c-.088.049-.178.094-.253.16l-.71-.71c.183-.172.39-.312.613-.415l-.068-.13c-.239.112-.458.262-.648.441l-.783-.783c.275-.264.584-.478.918-.64l-.068-.129c-.352.172-.674.397-.953.666l-.709-.709c.358-.347.762-.631 1.197-.846l-.067-.129c-.456.226-.872.521-1.233.872l-.784-.784c.449-.439.956-.797 1.503-1.071l-.067-.129c-1.194.6-2.167 1.578-2.759 2.777l.067.038zm2.287 2.743l.004.035-.093.101.012.1-.056.019-.012.044-.025.132.062.006c.031-.013.025.082 0 .094-.025.013-.093.038-.056.063s-.099.019-.099-.019-.074-.069-.093-.056c-.01.007-.023-.009-.033-.027-.026-.162-.043-.326-.046-.492h.435zm-.407 3.037h.015c.031-.107.179.006.192.044.005.014.026.029.045.044l-.095.095c-.056-.059-.104-.123-.157-.183zm.969-.631c-.054-.056-.09-.124-.14-.183.011-.031.027-.059.027-.059.08-.05-.019-.132-.019-.132.012-.076-.043-.163-.043-.163-.111-.075-.08-.22-.08-.22v-.1c-.093-.088.037-.101.037-.101.043-.075-.031-.132-.031-.132l-.006-.082-.099-.013-.012-.295-.223-.32c-.043-.013-.012-.088-.012-.088.056-.031-.012-.107-.012-.107l-.006-.138.13-.013.031-.05h.062l-.006-.163c.015-.039.04-.048.062-.048h.008c.018.003.035.01.035.01l.087.006.009-.016h.295l.025.161-.08.069c-.068.038-.068.126.006.144.049.006.031.126-.043.044-.111 0 .062.101.012.075.111.057.087-.05.087-.05l.057-.045c.024.123.056.244.098.362.114.318.292.612.53.864l-.786.783zm-.218-2.566c-.074-.044-.037-.207-.037-.207.118-.176.254-.075.254-.075l.087-.006c.03.02.045.045.053.071-.006.045-.014.089-.017.135-.012.026-.024.045-.024.045-.007.01-.006.031-.008.049h-.24l.001-.005-.069-.007zm1.374.252l.025-.038.01-.054h.07c.002.037.019.069.024.105l-.005.024-.043.013-.012-.025-.018.069h-.111l-.006-.075.066-.019zm-.269 1.428c-.219-.233-.385-.503-.491-.796-.047-.13-.08-.265-.103-.403.052.02.108.102.108.117 0 .019.247.006.247.006.068.044.093.157.093.157.068-.088.21-.006.105.044.099.063.099.119.099.119.081-.025.081.038.081.057 0 .019.025-.094.025-.094-.093-.069.124-.094.062.031l-.038.056.062.05.006.144c.136-.013.099-.182.099-.182l.062-.012c0-.057.043-.025.043-.025-.034-.17.046-.227.082-.244.049.092.096.186.167.265l-.709.71zm.636-1.099c.008-.038.01-.072.01-.072-.056-.025-.025-.113.037-.038.062.075-.037-.151-.037-.151l-.049-.044-.042-.004c-.01-.063-.037-.122-.037-.187 0-.03.015-.056.017-.085.012-.003.025-.001.025-.001l.037.031.056.044.006.038-.037.019-.006.05.019.069h.049c.019-.101.149-.101.186-.038l.037-.088c-.087-.044-.002-.113.023-.082s.082-.082.082-.082.043.057 0-.019c-.043-.075.031-.113.031-.113-.012-.075.08-.063.08-.063l.006-.1-.087-.006c-.018.088-.093.013-.056-.006s.074-.057.074-.057v-.063l.037-.013.006-.063h.093l.08-.038.019-.031.087-.006.124-.113-.012-.05c-.074 0 0-.057 0-.057l.012-.094h-.068l-.01-.112c.085-.02.168-.05.258-.05l.012.151-.068-.023h-.043l-.018-.038-.037-.006v.138l.037.031.031.031.062.006.012.075.155.006.019.031.093.006.179.182-.012.057-.031.019c.012.044-.08.019-.08.019v.038l.043.006.043.025.062-.107c.068-.044.099.019.105.057.006.038-.031.031-.031.031v.088l.037.013c.062.075-.025.119-.025.119l-.019.063c-.019.057-.087.044-.087.044l-.025.038-.074.019.147.019c.014-.05.051-.063.07-.038.019.025.019.069.019.069l.037.006-.006.069.037.013v.201l.043.05c.074-.031.074.019.037.044-.037.025-.012.138-.012.138l-.031.031v.05l-.038.027v.069c-.062-.031-.136-.019-.155 0-.056-.038-.173-.025-.173.006.037.05-.043.063-.043.063l-.043.05c.031.063-.031.069-.031.069v.119l-.074.069.004.093c-.04.004-.074.023-.115.023-.289 0-.556-.114-.771-.303.001-.001.003 0 .004-.002.031-.05.08-.057.08-.057l.019-.044.167.006c.012-.069.093-.044.093-.013s.062.006.062.006l.043-.069h.068l.006-.075.031-.019v-.113c.099-.031.087-.126.087-.126l.025-.031-.012-.044c-.05-.019-.025-.063.006-.05.031.013-.043-.057-.043-.057-.037.031-.068-.038-.068-.038h-.093v-.088l-.012-.082-.093-.044-.068.063-.012.088v.056l-.062.013-.012.169-.049.019.006.063-.068.019-.068.019-.012.082-.049.031-.025.075-.029.171c-.092-.089-.161-.196-.214-.309zm3.289-3.281c.014.014.027.022.029.023.029.024.06.046.089.071v.038c.045-.011.109.045.117.088l-.764.764c-.22-.207-.472-.37-.743-.484-.276-.115-.574-.18-.881-.189v-1.106c.448.009.882.1 1.285.265.313.129.6.316.868.53zm.688-.025c.088.05.159.16.148.182-.012.025.074.019.074.019.012-.113.118-.075.124-.038.006.038.025.119.025.119l.031.056.043.044.068-.006.019.038.08.013s.068.075.074.094c.006.019.099.013.124.019.025.006.062.025.068.057.006.031.043.082.043.082s.074.019.08.044c.006.025.037.082.037.082l.062.05.006.057.068.006.019.075.111-.006.062-.044c.016-.009.026-.019.04-.028.023.052.057.098.077.15.209.526.323 1.09.332 1.672h-1.002c-.003-.17-.028-.336-.054-.501.01-.035.018-.069.006-.081-.018-.019.019-.107.019-.107s.025-.05 0-.101c-.025-.05.006-.107.025-.132l-.049-.025-.049-.006-.051.009-.031-.106.008-.016.031.006v-.038l-.057-.016c-.005-.015-.008-.031-.014-.047l-.01-.157-.043-.031.012-.05-.049-.019.025-.082-.043-.088h-.083c-.027-.053-.051-.108-.081-.16 0-.009.003-.02.034-.029.033-.009.045-.011.049-.01l-.006-.065-.056-.038-.019-.075s-.068.013-.062.05c.001.007-.014.008-.019.013-.039-.063-.09-.118-.133-.179.003-.01.004-.02.009-.029.025-.044.012-.069-.031-.082-.043-.013-.043-.013-.056-.063-.012-.05-.062-.063-.062-.063l-.019-.075-.058.036c-.023-.027-.041-.057-.065-.083l.025-.079c-.026-.005-.033-.022-.04-.038l.184-.18zm-.2.496l-.005.007c0 .058.023.055.049.049l.052.067c.004.026.017.045.041.053.1.133.191.269.27.413-.007.008-.01.015-.01.015l-.099.013v.1l-.05.019.006.063.068-.006s0 .075.019.044.173.006.161.082c-.005.031.155.113.136.213.017.003.016.014.026.022.03.087.054.176.077.266l-.004.008.009.01c.022.085.045.169.06.256-.006.063-.02.123-.051.142-.074.044.006.019.006.019l-.012.138c.019.063.049.031.068 0 .006-.01.013-.015.019-.021.009.091.027.179.029.271h-.748l.013-.017.031-.088.105-.031.012-.082-.056-.006s.062-.113.093-.113.235 0 .254-.013c.019-.013.056-.113.056-.132s.05-.025.068-.031c.019-.006.062-.056.074-.082.012-.025-.031-.182-.056-.157-.025.025-.08.038-.08.038l-.019.069-.031.025s.006.019 0 .063-.062.069-.062.069l-.025.031s-.149.008-.167 0c-.056-.025-.018-.1.019-.094.037.006-.006-.107-.006-.107l.05-.006s.006-.113.025-.113c.019 0-.006-.038-.031-.056-.025-.019-.056-.082-.081-.075-.025.006-.124 0-.124 0l-.019.038-.068.013s.006.049-.006.063c-.037.044-.179.138-.118-.019l.018-.038v-.057l-.111-.006s-.056-.019-.056-.044-.006-.056-.006-.056l-.13-.144-.155-.019-.012-.031-.093-.013c-.012-.006-.02.001-.032-.003-.041-.066-.095-.123-.143-.186l-.011-.044c-.005-.022-.07-.105-.107-.11-.017-.019-.028-.041-.046-.059l.768-.768c.021.021.028.034.06.057.005.003.008 0 .013.002.029.026.05.059.075.089zm.56 3.763c-.169.381-.402.727-.687 1.024-.012-.127-.039-.266-.039-.266l-.05-.025.012-.151h-.068l-.111.145-.012.04-.063-.063.032-.033-.006-.075.043-.038v-.063l.037-.013.006-.138.031-.006v-.301l-.093-.088c-.006.031-.105.031-.105.031s-.025.044-.043.044.025.057.012.094c-.012.038-.062.038-.062.038l-.093.025-.025.031h-.099l-.01-.066.016-.02.093-.026.062-.031.031-.063c.006-.063.08-.056.08-.056s.142-.119.148-.176c.006-.057.056-.214.142-.214h.161c.062-.025.043-.107.043-.107l.08-.013.012.044s.111.013.124-.006c.012-.019.037-.063.068-.044.031.019.13-.044.13-.044.006-.044.161-.025.161-.025l.019-.056s-.105-.144-.124-.144c-.019 0-.118-.088-.13-.057-.099-.025-.093-.163-.093-.163l-.037-.088c0-.05-.093-.157-.111-.144-.039-.029-.046-.059-.044-.086h.865c-.007.487-.116.951-.303 1.373zm-2.799-.171l.031.013-.056.044-.049.057-.062-.019-.074-.006-.025-.044-.043-.006-.006.088-.031.038-.074.076c.078 0 .026.042-.012.06v-.251c.076-.004.144-.033.217-.049l.03.026h.056l.005-.047c.031-.009.064-.01.094-.021-.006.017-.001.041-.001.041zm1.113-2.762c.008.001.018.006.026.006.037 0 .118-.013.118-.013l.053.012c.03.036.058.074.085.111l-.064-.01-.049-.006-.093-.006c-.093.063-.111.138-.111.138-.045.085-.14-.013-.126-.07l.161-.162zm-.203 3.522l.161.082c.019.025.099.019.099.019l.025.031s.05-.006.081.031c.031.038.192.006.192.006l.043.038.068.025.115.004.07.07c-.112.052-.337.035-.352.02-.019-.019-.148-.075-.148-.075s-.099-.082-.118-.056-.105-.031-.105-.013-.08-.044-.08-.044l-.124-.044.093-.019-.02-.075zm.019-.737c.003-.007.009-.013-.001-.023-.007-.008-.02-.007-.03-.008l-.051-.051c-.003-.039.005-.092.001-.111-.006-.025.105-.063.087-.006-.019.057 0 .082 0 .082.08-.075.148.006.142.025-.006.019.043.038.074.019s.068.057.056.094c-.012.038-.124.031-.13-.006-.006-.038-.025-.025-.037-.006-.011.017-.057.026-.088.014l-.023-.023zm.532-2.378c-.062 0-.074-.05-.074-.05s-.049-.019-.049.006-.019.075 0 .1c.018.025-.025.063-.043.044-.018-.019-.068-.075-.056-.094.012-.019-.087-.138.012-.157.099-.019-.006-.075.031-.088l.049-.025h.049l.022-.018c.028.039.062.074.088.114-.003.014-.02.019-.017.036.019.095.049.132-.012.132zm-1.472 2.161c-.035.015-.076.014-.113.026v-.12l.062-.069c.066-.023.055.116.051.163zm-.39 2.358c.032-.035.153-.039.21.003.068.05.161.019.161.019l.052.063c-.141.02-.277.053-.423.056v-.141zm.826-5.589c.253.106.488.258.693.451l-.043.043c-.017-.021-.084-.034-.084-.057 0-.025-.062-.057-.056-.019.006.038-.043.057-.056.044-.012-.013-.049.038-.049.038 0 .019-.012.044.025.05.037.006.105-.025.111.013.002.013.005.023.008.033l-.243.243c-.035.002-.068.001-.068.001-.019.057-.105-.006-.08-.044.025-.038.025-.063.025-.063l-.031-.006-.037.069c-.087 0-.111.05-.093.082.019.031-.025-.006-.037.038-.012.044.006.044.043.063.037.019-.019.019.006.05.018.023.048.02.054.029l-.024.024c-.045.022-.105.016-.105.016-.002.017-.023.018-.039.024-.061-.049-.128-.087-.196-.123l-.006-.008h-.007c-.031-.017-.058-.043-.09-.057.019-.013.045-.021.059-.062.025-.069.037-.182.037-.182s-.099-.006-.105.025c-.006.031-.068.05-.068.05s-.05.019-.031.044c.019.025-.037.038-.037.038s.005.029-.004.048c-.098-.029-.195-.062-.299-.068v-1.003c.288.006.567.067.827.176zm-.765 4.066l.142-.031c.012-.063.074.013.074.013.062-.006.074.038.074.038l.081.013c.068.019.027.026.031.05.006.038.037.025.037.025l.012-.082.037.006-.037-.044-.068-.031-.074-.031c-.049-.069.012-.057.062-.05h.08s.093.125.093.157c0 .031.043.038.043.038l.056-.006.019.044h.056l.019.038h.111l.006-.057-.105-.019-.006-.063-.074-.019c-.025-.107.018-.138.049-.088l.037.006-.012-.094.043-.013-.012-.132-.037-.012v-.046l.155.006c-.012-.082.006-.119.006-.119h.043l.006.031.189.018.009.001c.074.044.037.101.012.113-.025.013-.068.013-.068.013l-.012.025-.161.012-.012.063c-.08-.013-.111.075-.093.119.019.044 0 .082 0 .082l.068.031.087-.025c.012-.063.068-.076.118-.113.045-.034.106.048.1.102-.1.07-.19.153-.3.207-.164.08-.341.135-.524.175h-.001l-.068-.019-.006-.094c-.012-.063-.13-.063-.124-.019.006.044-.221.019-.222.019v-.173l.061-.065zm-.062 1.812c.172-.003.336-.04.503-.066l.022.049.105.031.074.019.025.107.056.006.019.069c.068.05-.019.157-.019.157v.138l.05.025-.006.05.081.081.093.006.151.161c-.369.1-.754.159-1.153.166v-.999zm2.469.245v-.047c.111-.082.118-.226.012-.239-.08-.01-.043-.094.031-.107l.043-.019v-.057l.142-.132v-.101l-.309-.258c-.068-.025-.068-.112-.04-.193.053-.046.111-.085.163-.134l.435.435c-.017.033-.032.065-.025.086l.056.025.006.107c.042.043.134.04.209.027l.026.026c-.227.223-.482.41-.749.581zm.853-.684l-.027-.027-.009-.159-.031-.031-.006-.157c.025-.082-.118-.201-.13-.176-.012.025-.093.006-.093.031s-.049.151-.025.195v.004l-.386-.386c.303-.315.544-.675.718-1.064.201-.45.312-.94.322-1.447h1.001c-.01.688-.169 1.34-.444 1.927-.224.478-.526.914-.89 1.29zm1.992-.689c-.283.584-.658 1.115-1.106 1.575l-.78-.78c.382-.394.69-.841.917-1.324.291-.619.449-1.297.459-2h1.106c-.011.905-.224 1.763-.596 2.529zm.164-4.844c.275.681.424 1.413.433 2.168h-1.106c-.009-.602-.127-1.186-.344-1.73-.029-.072-.074-.135-.106-.206.007-.034.021-.101.076-.084.062.019.019-.138.019-.138s-.087-.063-.081-.094c.006-.031-.087-.094-.08-.119.006-.025-.08-.075-.074-.1.006-.025-.043-.094-.043-.094l-.093-.088-.012-.057-.074-.006-.148-.182.006-.05-.043-.006v-.069l-.043-.025-.068-.006-.139-.154-.012-.069h-.068l.01-.107.723-.723c.552.567.979 1.225 1.267 1.939zm-5.478-2.636v-1.106c.753.009 1.484.158 2.164.431v-.001c.715.288 1.374.715 1.942 1.269l-.659.659c-.024.006-.05.013-.068.005-.043-.019.018-.063.018-.063v-.05l-.037-.038s-.105.013-.111-.006c-.006-.019-.025-.101-.025-.101l-.006-.107-.043-.019-.006-.038-.068.006v-.075l-.037-.013-.038-.017-.006-.075-.136-.006-.043-.063-.049-.075-.155-.013-.037-.038-.062-.013-.043-.019-.019.031-.118.006-.006.038c-.045.023-.184.016-.262.018-.111-.055-.215-.126-.33-.172l-.054.138c.101.041.193.104.291.152-.005.008-.008.022-.016.022-.031 0-.019.082-.019.082s.081 0 .105.006c.025.006.025.069.025.069.093-.006.13.119.118.151-.012.031.037.031.037.031s0 .1-.012.126c-.012.025.081.044.105.082.025.038-.012.163-.031.17-.019.006.049.025.043.057-.006.031.019 0 .025.05l.019.157.087.006c.012-.082.172-.085.198-.075.105.038.186.201.186.239s-.068.044-.068.044l.003.041-.221.221c-.02-.012-.042-.024-.054-.017-.031.019-.019-.132-.019-.132s.056-.038.081-.019-.21-.314-.26-.283c-.049.031-.161-.031-.155-.088.006-.056-.223-.245-.223-.245s-.074-.05-.087-.012c-.012.038-.037.063 0 .082.037.019.031-.031.074.013s.124.1.093.138c-.031.038-.068.05-.068.05l.043.05h.068l.012.107s.074.038.093.082c.015.036.01.056 0 .078-.138-.105-.279-.201-.429-.285.003-.016.011-.032.008-.044-.012-.044.05-.063.08-.013l.062-.006.012-.057-.086-.071h-.068s-.006.05-.049.031c-.043-.019-.019-.013-.056-.019-.037-.006-.025.082-.019.107l-.002.007c-.098-.051-.191-.112-.293-.153-.42-.172-.873-.267-1.339-.276v-.557c.035-.001.058-.01.062-.026.006-.025.012-.031.049-.038.037-.006-.006-.082-.043-.075-.032.005-.056-.014-.068-.037v-.268c.594.009 1.17.128 1.705.345l.054-.138c-.552-.224-1.146-.346-1.759-.355zm-1.166 3.89l-.059-.002c-.025.057-.087-.006-.087-.006-.012-.038-.099 0-.099 0 0 .069-.118-.031-.118-.031l-.217-.157c-.124-.113-.309.031-.315.063.003.044-.032.048-.068.042.097-.184.21-.359.356-.514l.607.605zm-.71-.709c-.162.172-.292.372-.4.585-.029-.001-.061 0-.069.022-.018.05-.099.038-.099.038l-.012.025-.062.013-.012.038-.074.013.186-.006c.05-.006-.019.107-.049.1l-.087.006-.031.031h-.08l-.039.05-.117-.006s-.068.057-.062.075c.006.019-.012.075-.031.075s-.056.057-.043.075c.012.019-.037.082-.037.082l-.012.063-.037.013v.17l-.074.05v.075l-.034.037h-.503c.01-.498.122-.978.324-1.419.165-.36.391-.694.673-.987l.781.782zm-.886-.886c-.286.297-.523.642-.698 1.021-.211.454-.333.958-.343 1.488h-1.002c.01-.692.169-1.359.46-1.966.219-.456.511-.879.873-1.252l.71.709zm-1.596-1.597l.784.784c-.365.376-.669.809-.899 1.286-.298.618-.469 1.308-.479 2.036h-1.106c.011-.903.222-1.774.61-2.563.275-.561.641-1.082 1.09-1.543z"/><path d="M13.106 19.923l.068.063.025-.044-.044-.094-.043-.032-.031-.088-.093-.043.044.113.024.056zm4.702-3.956zm-2.549 1.714c.006.069.056-.044.056-.044v-.427l-.111-.013.006.044h.031c.049.088.006.301.006.301s-.074.006-.087-.031c-.012-.038-.043.082-.019.101.025.019.112 0 .118.069z"/><path d="M15.203 17.719v.151l.099.132.037-.088.013-.057-.044-.019.007-.094.037-.006.006-.044-.093.063zm1.955-.276l.013-.063.037-.019.006-.063.025-.044.037-.044.013-.05.061-.037.075-.013.031-.038.012-.075.005-.056.026-.038.074-.032v-.119h-.037l-.006-.044-.068-.006-.013.031h-.03l-.007.05h.037l.007.038-.025.025-.012.032-.05.012-.111.107-.007.05-.03.044-.037.094-.131.006-.024.114.018.094zm.489.408l-.056.006.006.088.037.031.068.019s.093-.025.099-.1l-.142-.006-.012-.038zm.489-.358c.013.055.012-.088.037-.082.025.006.006-.088.006-.088l-.111.081c.056.008.062.064.068.089zm.439-.126c-.093-.063-.087-.144-.111-.201-.011-.024-.037-.044-.056.006v.082s.087.138.117.157c.032.019.082-.022.05-.044zm2.785.189c-.025-.075-.175-.011-.148.025.037.05.099.025.124.031.024.007.049.019.024-.056zm.198-2.091c0 .019.013.113.013.113s.043.019.049.044c.006.025 0 .075.019.082.018.006.056.031.043.056-.012.025-.012.075-.012.075l.025.057.049.031s.019-.151-.012-.157c-.031-.006-.018-.094-.018-.094s.031-.119-.019-.119-.012-.063-.043-.082c-.031-.019-.012-.107-.025-.132-.012-.025-.012-.057-.043-.075-.031-.019.006.069-.012.082-.019.013-.031.038-.05.057-.02.018.036.043.036.062zm-.266-.591c.018.025.056.044.056.069 0 .025-.012.044.025.05.037.006.062-.006.074.025.012.031.012.082.006.107-.006.025.006.063.037.063s.037.006.037.025c0 .019.037-.069.037-.069-.031-.025-.056-.082-.056-.082s-.031-.088-.031-.1c0-.013-.043-.025-.062-.031-.019-.006-.05-.063-.05-.063l-.073.006zm-.068-.138c.025 0 .043.013.068.025.025.013.043.031.062.057l.062-.019s.006-.063-.019-.044c-.025.019-.043-.044-.068-.038-.025.006-.037-.025-.062-.056s-.019-.038-.05-.057c-.031-.019-.05-.019-.05.006s.031.038.019.069c-.012.032.013.057.038.057zm-.706.434s.019.031.037.05c.019.019.062.057.019.082s.006.019.006.019-.006.132-.062.113c-.056-.019-.074.069-.074.094s.22.035.186 0c-.019-.019.025-.063.025-.063s.149.013.18.013.056-.006.037-.038c-.019-.031-.074-.025-.074-.025s-.074.019-.142-.019.012-.05.025-.05.068-.044.043-.075c-.025-.031 0-.088 0-.063 0 .025.068.038.081.019.012-.019 0-.075-.031-.094-.031-.019.056-.031.031-.063-.027-.032-.039-.07-.039-.07s-.037.05-.111.025c0 0-.012.119-.049.144h-.088zm.805-.048v.004s.004-.003 0-.004zm-2.234.374c0 .019.043.038.068.038s.093-.05.093-.05.031-.088.006-.082c-.025.006-.074.044-.08.006-.006-.038-.08-.019-.08-.019l-.099.013-.006.044.068.006c-.001 0 .03.026.03.044zm.532-2.091c-.031 0-.087-.038-.074-.063.012-.025-.105-.05-.105-.05s-.105-.101-.068-.088c.037.013.019-.044.019-.044s-.074.013-.093.006c-.019-.006-.012-.063-.012-.063s-.074-.019-.074 0 .025.019.037.056c.012.038.006.101.062.113.056.013.068.025.074.05.006.025.074.031.074.031l.05.025.148.126v-.05c-.001.001-.007-.049-.038-.049zm-.65-.804c.002.002.006-.005.008-.005-.021-.01-.034-.015-.008.005zm.192 0l-.043-.031s-.068-.006-.068-.025c0-.017-.045.054-.072.052.03.015.078.042.078.042.049 0 .08.038.08.057s.068.013.068.013l.006-.044-.049-.064zm1.77-.018s.116.137.111.069c-.012-.188-.099-.195-.13-.232-.031-.038-.164.007-.155.057.006.031.031.063.08.075l.094.031zm-2.389-.729v-.069l-.024-.025-.025-.088-.08-.025-.08.031-.087.057-.093.013-.05.056.198.019.037.063.142.013.093.094c.081.025.099-.013.05-.056l-.081-.083zm.57-.308h-.111c-.006-.044-.105-.025-.111 0-.006.025-.043.031-.043.031l-.142.013c-.012.038-.087.063-.093.038-.014-.055-.093.069-.012.094.08.025.161 0 .161 0l.019-.038.309.006c.025-.025.037-.063.037-.063s.074-.025.105-.013c.031.013.006-.088-.025-.075-.032.013-.094.007-.094.007zm-1.671 1.306c.006.019.068.025.074.006.006-.019.031-.057-.025-.057s-.043-.031-.062-.05c-.019-.019-.147-.016-.142.006.006.031.056.069.056.069s.093.008.099.026zm.292 5.662c.028-.005.046-.019.069-.024.023-.005.033-.042.042-.08.009-.038-.009-.057-.009-.057s-.023.038-.06 0-.07.085-.084.113c.001.001.015.052.042.048z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..d51f600ab11eff5c782a04a3ed3dbd8704857d3f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#B22334" d="M35.445 7C34.752 5.809 33.477 5 32 5H18v2h17.445zM0 25h36v2H0zm18-8h18v2H18zm0-4h18v2H18zM0 21h36v2H0zm4 10h28c1.477 0 2.752-.809 3.445-2H.555c.693 1.191 1.968 2 3.445 2zM18 9h18v2H18z"/><path fill="#EEE" d="M.068 27.679c.017.093.036.186.059.277.026.101.058.198.092.296.089.259.197.509.333.743L.555 29h34.89l.002-.004c.135-.233.243-.483.332-.741.034-.099.067-.198.093-.301.023-.09.042-.182.059-.275.041-.22.069-.446.069-.679H0c0 .233.028.458.068.679zM0 23h36v2H0zm0-4v2h36v-2H18zm18-4h18v2H18zm0-4h18v2H18zM0 9c0-.233.03-.457.068-.679C.028 8.542 0 8.767 0 9zm.555-2l-.003.005L.555 7zM.128 8.044c.025-.102.06-.199.092-.297-.034.098-.066.196-.092.297zM18 9h18c0-.233-.028-.459-.069-.68-.017-.092-.035-.184-.059-.274-.027-.103-.059-.203-.094-.302-.089-.258-.197-.507-.332-.74.001-.001 0-.003-.001-.004H18v2z"/><path fill="#3C3B6E" d="M18 5H4C1.791 5 0 6.791 0 9v10h18V5z"/><path fill="#FFF" d="M2.001 7.726l.618.449-.236.725L3 8.452l.618.448-.236-.725L4 7.726h-.764L3 7l-.235.726zm2 2l.618.449-.236.725.617-.448.618.448-.236-.725L6 9.726h-.764L5 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 9l-.235.726zm-8 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L5 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 13l-.235.726zm-6-6l.618.449-.236.725L7 8.452l.618.448-.236-.725L8 7.726h-.764L7 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 7l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 11l-.235.726zM6.383 12.9L7 12.452l.618.448-.236-.725.618-.449h-.764L7 11l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 11l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 11l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 15l-.235.726zM6.383 16.9L7 16.452l.618.448-.236-.725.618-.449h-.764L7 15l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 15l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 15l-.235.726z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1fe.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1fe.svg new file mode 100644 index 0000000000000000000000000000000000000000..796244c9d1432a42b29c07f584baac87e0c3347f --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1fe.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0038A8" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-1H0v1zm0-8h36v4H0z"/><path fill="#EEE" d="M0 23h36v3H0z"/><path fill="#0038A8" d="M36 9c0-2.209-1.791-4-4-4H16v4h20zm-20 3h20v4H16z"/><path fill="#EEE" d="M16 9V5H4C1.791 5 0 6.791 0 9v10h36v-3H16v-4h20V9H16z"/><path fill="#FFD983" d="M13 12c0-2.762-2.238-5-5-5s-5 2.239-5 5 2.239 5 5 5c2.762 0 5-2.239 5-5z"/><path fill="#FFCC4D" d="M12 12c0-2.209-1.79-4-4-4-2.209 0-4 1.791-4 4 0 2.208 1.791 4 4 4 2.21 0 4-1.792 4-4z"/><path fill="#FFAC33" d="M8 5.597l.633 4.041 2.569-3.183-1.473 3.816 3.816-1.473-3.183 2.569 4.041.633-4.041.633 3.183 2.569-3.816-1.473 1.473 3.816-2.569-3.183L8 18.403l-.633-4.041-2.569 3.183 1.473-3.816-3.816 1.473 3.183-2.569L1.597 12l4.041-.633-3.183-2.569 3.816 1.473-1.473-3.816 2.569 3.183z"/><path fill="#C1694F" d="M11 12c0-1.657-1.343-3-3-3s-3 1.343-3 3c0 1.656 1.343 3 3 3s3-1.344 3-3z"/><path fill="#FFAC33" d="M5.834 12.004c0-1.19.964-2.154 2.153-2.154s2.153.964 2.153 2.154c0 1.189-.964 2.152-2.153 2.152s-2.153-.964-2.153-2.152z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ff.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..b913772edf921906c3c2a035de9875d32003dd64 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fa-1f1ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#0099B5" d="M0 9v4h36V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9z"/><path fill="#1EB53A" d="M36 27v-4H0v4c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4z"/><path fill="#CE1126" d="M0 13h36v1.5H0zm0 8.5h36V23H0z"/><path fill="#EEE" d="M0 18v3.5h36v-7H0z"/><path fill="#FFF" d="M4.2 9.16c0-1.546 1.125-2.828 2.6-3.076-.169-.028-.343-.044-.52-.044-1.723 0-3.12 1.397-3.12 3.12s1.397 3.12 3.12 3.12c.177 0 .351-.016.52-.044-1.475-.248-2.6-1.53-2.6-3.076zm4.683 2.303l-.14-.431-.14.431h-.454l.367.267-.14.431.367-.267.366.267-.14-.431.367-.267zm2.702 0l-.14-.431-.14.431h-.453l.367.267-.14.431.366-.267.367.267-.14-.431.367-.267zm-.14-2.927l-.14.431h-.453l.367.267-.14.431.366-.267.367.267-.14-.431.367-.267h-.454zm2.843 2.927l-.14-.431-.14.431h-.453l.366.267-.14.431.367-.267.367.267-.14-.431.366-.267zm-.14-2.927l-.14.431h-.453l.366.267-.14.431.367-.267.367.267-.14-.431.366-.267h-.453zm0-2.496l-.14.431h-.453l.366.267-.14.431.367-.267.367.267-.14-.431.366-.267h-.453zm2.843 5.423l-.14-.431-.14.431h-.454l.367.267-.14.431.367-.267.366.267-.14-.431.367-.267zm-.14-2.927l-.14.431h-.454l.367.267-.14.431.367-.267.366.267-.14-.431.367-.267h-.453zm0-2.496l-.14.431h-.454l.367.267-.14.431.367-.267.366.267-.14-.431.367-.267h-.453zm2.842 5.423l-.14-.431-.14.431h-.453l.367.267-.14.431.366-.267.367.267-.14-.431.367-.267zm-.14-2.927l-.14.431h-.453l.367.267-.14.431.366-.267.367.267-.14-.431.367-.267h-.454zm0-2.496l-.14.431h-.453l.367.267-.14.431.366-.267.367.267-.14-.431.367-.267h-.454z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..7b2bffa76b034c772b615ac910223259b522f33c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FDDF00" d="M19 31H9c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h10v26z"/><path fill="#EEE" d="M31 27c0 2.209-1.791 4-4 4h-9V5h9c2.209 0 4 1.791 4 4v18z"/><path fill="#A1A1A1" d="M28.816 14.234l.329-.609-.672.305z"/><path fill="#A1A1A1" d="M28.846 13.682c0 .137.11.248.247.248s.247-.111.247-.248c0-.136-.11-.247-.247-.247s-.247.111-.247.247zm-.576.145c-.116.115-.057.362.131.549.188.189.434.247.549.131.116-.115.058-.361-.131-.549-.186-.188-.433-.248-.549-.131z"/><path fill="#CB9C2B" d="M22.561 19.562c.379.359.701-.105 1.306-.641.553-.49 4.188-3.87 4.578-4.214.391-.344.028-.864-.425-.442s-4.801 4.062-5.127 4.359c-.327.298-.752.54-.332.938z"/><path fill="#CB9C2B" d="M28.348 14.558l.437.488-.219.188.219.187.219-.187.312.344v.343l-.609.517-.359-.235v-.282h-.297v.267l.156.015.141.156.015.36-.54.437-1.108-1.051zm-8.688 6.103c0 .822.667 1.489 1.489 1.489.822 0 1.489-.667 1.489-1.489 0-.822-.667-1.489-1.489-1.489-.822 0-1.489.667-1.489 1.489zm.954.001c-.267-.004-.482-.22-.482-.486 0-.27.219-.488.488-.488.27 0 .488.219.488.488l-.001.007c.014-.001.026-.009.041-.009.001-.268.22-.486.488-.486.27 0 .488.219.488.488 0 .267-.215.482-.481.486.267.005.481.221.481.487 0 .269-.219.488-.488.488s-.487-.219-.488-.487c-.015 0-.027-.008-.042-.009l.002.008c0 .269-.219.488-.488.488-.27 0-.488-.219-.488-.488.001-.266.216-.482.482-.487z"/><path fill="#A1A1A1" d="M22.122 19.247c-.116.115-.057.362.131.549.188.188.434.247.549.131.116-.115.058-.361-.131-.549-.187-.188-.434-.247-.549-.131zm-2.394.188c0 .141.114.255.256.255.141 0 .255-.114.255-.255 0-.142-.114-.256-.255-.256-.142 0-.256.114-.256.256zm2.223 2.461c0 .141.114.255.256.255.141 0 .255-.114.255-.255 0-.142-.114-.256-.255-.256-.142 0-.256.114-.256.256zm-2.291-.083c0 .141.114.255.256.255.141 0 .255-.114.255-.255 0-.142-.114-.256-.255-.256-.142.001-.256.115-.256.256z"/><path fill="#B4B4B5" d="M26.77 17.083c.139-.091.245-.215.316-.37.299-.652-.072-1.701-.299-2.106-.277-.497-.107-.821.026-.976-.037-.014-.082-.025-.131-.025-.109 0-.215.053-.312.158-.292.311-.154.726.253 1.669.306.707.425 1.217.147 1.65z"/><path fill="#B4B4B5" d="M26.211 14.043c.143-.208.363-.324.633-.324.219 0 .445.082.635.226l.28-.422c-.124-.103-.423-.317-.761-.317-.089 0-.175.015-.258.044-.383.137-.512.49-.529.793z"/><path fill="#CB9C2B" d="M20.184 14.234l-.329-.609.672.305z"/><path fill="#CB9C2B" d="M20.154 13.682c0 .137-.11.248-.247.248s-.247-.111-.247-.248c0-.136.11-.247.247-.247s.247.111.247.247zm.575.145c.116.115.057.362-.131.549-.188.189-.434.247-.549.131-.116-.115-.058-.361.131-.549.187-.188.434-.248.549-.131z"/><path fill="#A1A1A1" d="M26.439 19.562c-.379.359-.701-.105-1.306-.641-.553-.49-4.188-3.87-4.578-4.214-.391-.344-.028-.864.425-.442s4.801 4.062 5.127 4.359c.327.298.752.54.332.938z"/><path fill="#A1A1A1" d="M20.652 14.558l-.437.488.219.188-.219.187-.219-.187-.312.344v.343l.609.517.359-.235v-.282h.297v.267l-.156.015-.141.156-.015.36.54.437 1.108-1.051zm7.199 4.614c-.822 0-1.489.667-1.489 1.489 0 .822.667 1.489 1.489 1.489.822 0 1.489-.667 1.489-1.489 0-.822-.667-1.489-1.489-1.489zm1.016 1.977c0 .269-.219.488-.488.488-.27 0-.488-.219-.488-.488l.002-.008c-.015.001-.027.009-.042.009-.001.268-.219.487-.488.487s-.488-.219-.488-.488c0-.267.215-.482.481-.487-.267-.004-.481-.22-.481-.486 0-.27.219-.488.488-.488s.487.218.488.486c.015 0 .027.008.041.009l-.001-.007c0-.27.219-.488.488-.488.27 0 .488.219.488.488 0 .267-.215.482-.481.486.266.005.481.221.481.487z"/><path fill="#CB9C2B" d="M26.878 19.247c.116.115.057.362-.131.549-.188.188-.434.247-.549.131-.116-.115-.058-.361.131-.549.187-.188.434-.247.549-.131zm2.394.188c0 .141-.114.255-.256.255-.141 0-.255-.114-.255-.255 0-.142.114-.256.255-.256.142 0 .256.114.256.256zm-2.223 2.461c0 .141-.114.255-.256.255-.141 0-.255-.114-.255-.255 0-.142.114-.256.255-.256.142 0 .256.114.256.256zm2.291-.083c0 .141-.114.255-.256.255-.141 0-.255-.114-.255-.255 0-.142.114-.256.255-.256.142.001.256.115.256.256z"/><path d="M25.918 13.719c0 1.467-.639 1.427-1.428 1.427-.788 0-1.427.04-1.427-1.427s.639-3.052 1.427-3.052c.789 0 1.428 1.585 1.428 3.052z"/><path fill="#FFF" d="M24.427 15.046c-.424 0-.72-.013-.923-.17-.232-.181-.341-.548-.341-1.157 0-1.49.657-2.952 1.327-2.952.67 0 1.328 1.462 1.328 2.952 0 1.327-.533 1.327-1.208 1.327h-.183z"/><path fill="#CB9C2B" d="M25.236 14.042c-.5-.146-.419-.625-.746-.625s-.246.479-.746.625c-.499.146-.746-.083-.746-.083l.233.958s.419-.354 1.259-.354c.84 0 1.259.354 1.259.354l.233-.958c0-.001-.247.228-.746.083z"/><path fill="#CB9C2B" d="M25.318 12.774c-.555-.153-.465-.658-.828-.658-.363 0-.274.505-.828.658-.554.153-.827-.087-.827-.087l.258 1.008s.466-.373 1.397-.373c.932 0 1.397.373 1.397.373l.258-1.008c0 .001-.273.241-.827.087z"/><path fill="#CB9C2B" d="M25.187 11.445c-.467-.129-.392-.554-.697-.554-.306 0-.23.425-.697.554-.466.129-.696-.073-.696-.073l.218.849s.392-.236 1.176-.236c.784 0 1.176.236 1.176.236l.218-.849c-.001 0-.232.202-.698.073zm-.875-.947c0 .148.08.269.178.269.098 0 .178-.12.178-.269 0-.149-.08-.269-.178-.269-.097 0-.178.12-.178.269z"/><path fill="#CB9C2B" d="M24.041 10.206c0 .102.201.185.449.185s.449-.083.449-.185c0-.103-.201-.186-.449-.186-.248.001-.449.084-.449.186z"/><path fill="#CB9C2B" d="M24.312 9.935c0 .103.08.186.178.186.098 0 .178-.083.178-.186s-.08-.185-.178-.185c-.097 0-.178.083-.178.185z"/><path fill="#B4B4B5" d="M22.211 17.083c-.139-.091-.245-.215-.316-.37-.299-.652.072-1.701.299-2.106.277-.497.107-.821-.026-.976.037-.014.082-.025.131-.025.109 0 .215.053.312.158.292.311.154.726-.253 1.669-.306.707-.425 1.217-.147 1.65z"/><path fill="#B4B4B5" d="M22.77 14.043c-.144-.208-.363-.324-.633-.324-.219 0-.445.082-.635.226l-.28-.422c.124-.103.423-.317.761-.317.089 0 .175.015.258.044.382.137.511.49.529.793z"/><path fill="#EC1C24" d="M24.49 17c.2.154.246.75.246 1.453v5.484s.307.078.213.891c-.027.232-.484.188-.562 0-.078-.188-.04-.791.104-.875V18.5c0-.812-.136-1.127-.178-1.281-.043-.154.081-.294.177-.219z"/><path fill="#EC1C24" d="M26.375 20.799c-.196-.137-.471-.482-.707-.812-.312-.438-.391-.736-.701-1.111-.31-.375-1.122-1.152-1.314-1.125-.076.011-.156.188-.083.25s.302.312.817.703c.516.391.594.828 1.024 1.453.397.577.74.971 1.049 1.024-.045-.121-.072-.249-.085-.382z"/><path fill="#EC1C24" d="M25.36 17.551c-.183.175-.749.729-1.057 1.089-.308.36-.698 1.22-1.042 1.61-.221.25-.46.464-.642.596-.017.136-.046.267-.097.389.248-.083.602-.311 1.046-.953.614-.891.911-1.547 1.208-1.797s.416-.324.583-.498c.168-.175.185-.612.001-.436z"/><path fill="#EC1C24" d="M24.124 18.281v5.781c-.331.266-.237.707-.175.924.062.217.603.216.687.108.084-.108.107-.844-.202-1.094v-5.359c0-.141-.31-.575-.31-.36z"/><path fill="#EC1C24" d="M22.095 20.982c-.297.207-.552.564.112.83s1.543.625 2.283.625 2.123-.502 2.447-.728c.324-.226.464-.495-.052-.647-.271-.08-.312.125-.171.172s.305.193-.051.323c-.355.13-1.168.511-2.23.511s-2.062-.453-2.226-.511c-.164-.058-.209-.245-.093-.323s.114-.344-.019-.252z"/><path fill="#CB9C2B" d="M24.856 23.759c0 .117-.095.211-.212.211-.116 0-.211-.094-.211-.211 0-.117.095-.212.211-.212.118 0 .212.095.212.212z"/><path fill="#CB9C2B" d="M24.5 23.899c0 .117-.095.211-.212.211-.116 0-.211-.094-.211-.211 0-.117.095-.212.211-.212.117.001.212.095.212.212z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e8.svg new file mode 100644 index 0000000000000000000000000000000000000000..fb97611b43c11b8c9543a52709abf9a923b6aecb --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1e8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#009E60" d="M32 5h-5v26h5c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#0072C6" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h5V5H4z"/><path fill="#FCD116" d="M9 5h18v26H9z"/><path d="M15.833 23.526L18 27.859l2.167-4.333L18 19.193l-2.167 4.333zm-2.708-5.417l2.167 4.333 2.167-4.333-2.167-4.333-2.167 4.333zm5.417 0l2.167 4.333 2.167-4.333-2.167-4.333-2.167 4.333z" fill="#009E60"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..294b5c69ee23a5ffdc95880958e1b2dce273e799 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CF142B" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#00247D" d="M0 23h36V13H0v10zm25.316-3.55l.269.74.787-.027-.62.485.269.74-.653-.44-.62.485.217-.757-.653-.44.787-.027.217-.759zM24.1 17.785l.73-.295-.417.667.506.603-.764-.19-.417.667-.055-.785-.764-.19.73-.295-.055-.785.506.603zm-2.9-2.145l.682.394.585-.527-.164.77.682.394-.783.082-.164.77-.32-.719-.783.082.585-.527-.32-.719zm-2.002-.493l.37-.695.11.779.775.137-.707.345.11.779-.547-.566-.709.345.37-.695-.547-.566.775.137zm-2.875.084l.11-.779.37.695.775-.137-.547.566.37.695-.707-.345-.547.566.11-.779-.707-.345.773-.137zm-2.789.276l.585.527.681-.394-.32.719.585.527-.783-.082-.32.719-.164-.77-.783-.082.682-.394-.163-.77zM11.17 17.49l.73.295.506-.603-.055.785.73.295-.764.19-.055.785-.417-.667-.764.19.506-.603-.417-.667zm-.756 2.699l.269-.74.217.757.787.027-.653.44.217.757-.62-.485-.653.44.269-.74-.62-.485.787.029z"/><path fill="#FC0" d="M32 5H4C1.791 5 0 6.791 0 9v4h36V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M18.6 16.271l.707-.345.547.566-.11-.779.708-.345-.775-.137-.11-.779-.369.695-.776-.137.547.566zm3.118.532l.32.719.163-.769.783-.083-.681-.393.163-.77-.585.526-.681-.393.32.719-.585.527zm1.201 1.459l.764.19.055.785.417-.667.763.19-.506-.603.418-.667-.73.295-.506-.603.055.785zm2.046 2.412l-.217.756.621-.484.652.44-.269-.74.62-.484-.786.027-.27-.739-.217.756-.786.028zm-8.819-4.182l.547-.566.707.345-.369-.695.547-.566-.776.137-.369-.695-.11.779-.775.137.708.345zm-2.347.261l.163.769.32-.719.783.083-.585-.527.32-.719-.681.393-.585-.526.163.77-.681.393zm-1.954 1.817l.417.667.055-.785.764-.19-.73-.295.055-.785-.506.603-.73-.295.418.667-.506.603zm-1.866 2.816l.652-.44.621.484-.217-.756.652-.44-.786-.028-.217-.756-.27.739-.786-.027.62.484z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ec.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..d8194cd05c01821378995185257fb2dc31406d5a --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#00247D" d="M32 5H4c-.205 0-.407.015-.604.045l-.004 1.754-2.73-.004C.244 7.427 0 8.185 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFF" d="M33.466 22.644c-.281-.184-.694-.577-.766-.693-.282-.469-.605-.566-.827-.566-.027 0-.058.005-.089.008.106-.177.175-.352.175-.517v-9.229H21.875v9.229c0 .165.069.339.175.517-.031-.004-.062-.008-.089-.008-.222 0-.545.098-.827.566-.071.116-.484.51-.766.693-.231.149-.367.389-.384.672-.023.399.206.861.586 1.178.155.13.34.197.533.197.26 0 .482-.119.657-.262 1.661 1.372 3.353 2.04 5.156 2.04s3.495-.668 5.156-2.04c.175.143.398.262.657.262.193 0 .378-.067.533-.197.38-.316.609-.778.586-1.178-.015-.284-.152-.523-.382-.672z"/><path fill="#006129" d="M26.917 24.037c-2.23-.995-4.542-2.47-4.542-3.162v-8.729h9.084v8.729c0 .693-2.312 2.168-4.542 3.162z"/><path fill="#FFC6B5" d="M25.078 17.891c-.204.079-.266-.469 0-.859.266-.391 1.047-1.188 1.219-1.922s.475-.625.62-.828c.146-.203.167-.438 0-.484s-.401-.109-.245-.719c.156-.609.828-.547.828-.125 0 .422-.156.797 0 1.125.156.328.516.25.734.875.219.625.297 1.234.156 1.5s-.219 1.281-.406 1.547-.438.156-.391-.328c.047-.484.359-1.141.453-1.484.094-.344-.141-1.047-.484-1.125-.344-.078-.969.719-1.25 1.047-.281.328-.891.578-.922.844-.031.264-.109.857-.312.936z"/><path fill="#FFF" d="M28.766 21.875c-.359.078-1.156.375-1.594.266-.438-.109-1.219.172-1.328.024-.109-.149.109-.961.141-1.336.031-.375.078-.75.016-.75s-.326 0-.187-.672c.14-.672.374-1.906.374-1.906s-.234-.094-.094-.469c.141-.375.312-1.266.266-1.469s-.391-.141-.266-.453.219-.375.312-.609c.094-.234.286-.419.422-.359s.289.234.441.141c.152-.094.168-.234.371-.219.203.016.638.424.547.516s-.256.41-.284.807c-.028.396-.278 1.365-.356 1.678s.266 1.062.453 1.766c.188.7.766 3.044.766 3.044z"/><path fill="#9C5100" d="M26.682 12.628c.091-.241.537-.441.912-.144s.531.844.266 1.172c-.266.328-.42.25-.522 0-.103-.25.007-.474-.134-.549-.141-.076-.016-.294-.141-.341-.125-.047-.512.21-.381-.138z"/><path fill="red" d="M23.114 12.484c-.063-.07-.223.22-.16.423.062.204.046.395.169.364.123-.031.093-.208.174-.35.062-.11-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M22.859 13.203h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016.594.016.266.203c-.328.188-.141-.203-.328 0s-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.435-.061-.404-.186.031-.125-.172-.172-.406-.219-.235-.046-.329-.265-.329-.265z"/><path fill="red" d="M23.114 14.072c-.063-.07-.223.22-.16.423s.046.396.169.365c.123-.031.093-.209.174-.35.062-.11-.188-.078-.109-.203l-.074-.235z"/><path fill="#F8C600" d="M22.859 14.791h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016c.172-.109.594.016.266.203-.328.188-.141-.203-.328 0s-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.435-.061-.404-.186.031-.125-.172-.172-.406-.219-.235-.046-.329-.265-.329-.265z"/><path fill="red" d="M23.114 15.838c-.063-.07-.223.22-.16.423s.046.395.169.364c.123-.031.093-.208.174-.35.062-.11-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M22.859 16.557h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016.594.016.266.203c-.328.188-.141-.203-.328 0s-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.435-.062-.404-.187.031-.125-.172-.172-.406-.219-.235-.046-.329-.264-.329-.264z"/><path fill="red" d="M24.114 17.557c-.063-.07-.223.22-.16.423s.046.395.169.364c.123-.031.093-.208.174-.35.062-.11-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M23.859 18.275h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016c.172-.109.594.016.266.203-.328.188-.141-.203-.328 0-.188.203-.359.281-.328.359.031.078-.098.14-.361.14-.264 0-.435-.062-.404-.187.031-.125-.172-.172-.406-.219s-.329-.264-.329-.264z"/><path fill="red" d="M23.056 18.957c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M22.801 19.676h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016c.172-.109.594.016.266.203-.328.188-.141-.203-.328 0-.188.203-.359.281-.328.359.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219s-.329-.264-.329-.264z"/><path fill="red" d="M23.056 20.629c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M22.801 21.348h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016.594.016.266.203c-.328.188-.141-.203-.328 0-.188.203-.359.281-.328.359.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219s-.329-.264-.329-.264z"/><path fill="red" d="M29.021 20.629c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 21.348h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0c-.188.203-.359.281-.328.359.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219-.236-.046-.329-.264-.329-.264z"/><path fill="red" d="M29.021 19.059c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 19.777h.828s.109-.375.281-.391.219.375.219.375.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219-.236-.045-.329-.264-.329-.264z"/><path fill="red" d="M29.021 17.452c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 18.17h.828s.109-.375.281-.391.219.375.219.375.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.436-.061-.404-.186.031-.125-.172-.172-.406-.219-.236-.046-.329-.265-.329-.265z"/><path fill="red" d="M29.021 15.838c-.063-.07-.223.22-.16.424.062.203.046.395.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 16.557h.828s.109-.375.281-.391.219.375.219.375.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219-.236-.046-.329-.264-.329-.264z"/><path fill="red" d="M29.021 14.174c-.063-.07-.223.22-.16.424.062.203.046.394.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 14.893h.828s.109-.375.281-.391c.172-.016.219.375.219.375s.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0c-.188.203-.359.281-.328.359.031.078-.098.14-.361.14-.264 0-.436-.062-.404-.187.031-.125-.172-.172-.406-.219-.236-.046-.329-.264-.329-.264z"/><path fill="red" d="M29.021 12.484c-.063-.07-.223.22-.16.424.062.203.046.394.169.363.123-.03.093-.208.174-.35.062-.109-.188-.078-.109-.203l-.074-.234z"/><path fill="#F8C600" d="M28.766 13.203h.828s.109-.375.281-.391.219.375.219.375.391.094.562-.016c.172-.109.594.016.266.203s-.141-.203-.328 0-.359.281-.328.359c.031.078-.098.14-.361.14-.264 0-.436-.061-.404-.186.031-.125-.172-.172-.406-.219-.236-.046-.329-.265-.329-.265zm4.427 9.859c-.312-.203-.797-.646-.922-.854s-.375-.499-.641-.189c-.266.309-2.381 2.372-4.714 2.372s-4.448-2.062-4.714-2.372c-.266-.31-.516-.019-.641.189s-.609.651-.922.854-.125.734.25 1.047.828-.375.828-.375c1.297 1.156 2.984 2.234 5.198 2.234s3.901-1.078 5.198-2.234c0 0 .453.688.828.375s.565-.843.252-1.047z"/><path fill="#00247D" d="M19 18V5H4c-.32 0-.604.045-.604.045l-.004 1.754-2.73-.004S.62 6.854.535 7C.195 7.589 0 8.272 0 9v9h19z"/><path fill="#EEE" d="M19 5h-2.331L12 8.269V5H7v2.569L3.396 5.045c-.614.094-1.19.325-1.672.665L6.426 9H4.69L.967 6.391c-.11.129-.211.262-.305.404L3.813 9H0v5h3.885L0 16.766V18h3.332L7 15.432V18h5v-3.269L16.668 18H19v-2.029L16.185 14H19V9h-2.814L19 7.029V5z"/><path fill="#CF1B2B" d="M11 5H8v5H0v3h8v5h3v-5h8v-3h-8z"/><path fill="#CF1B2B" d="M19 5h-1.461L12 8.879V9h1.571L19 5.198zm-17.276.71c-.281.195-.534.423-.757.681L4.69 9h1.735L1.724 5.71zM6.437 14L.734 18h1.727L7 14.822V14zM19 17.802v-1.22L15.313 14H13.57z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ee.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..d0602d299919f3f418f772fb75daaaf407fae8dc --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#379543" d="M13 24.812s-.188.126-.375.084-.458.009-.458.009l-1.613-2.777s-.866.81-1.658.102c.417.125.916-.709 1.521-.354-.563-.522-1.646.395-2.188-.876.75.459 1.188-.271 1.875.188-.667-.75-1.646.069-2.042-.944.604.216 1.104-.444 1.646 0-.458-.931-1.854.361-2.125-1.201.604.312 1.271-.083 1.646.229-.708-1.354-1.354.207-1.958-1.771.417.583 1 .021 1.604.938-.438-1.667-1.625-.271-2-2.229.75-.25 1.062.854 1.667 1.083-.375-1.293-1.167-.918-.688-2.439 1.083.542.604 1.458.958 2.521.271-.375-.083-.854.105-1.187s.292-.5.229-.667c.979 1.125-.209 2.083-.104 2.479.104.396.271.542.271.542s-.104-.604.104-.958.542-.479.521-.792c.229.271.146.896-.125 1.208s-.313 1.084-.146 1.354c-.064-.845.688-.792.563-1.646.417.083.564 1.042.104 1.396-.459.354-.104 1.333-.104 1.333s.021-.624.271-.916.396-.605.333-.896c.333.271.375 1.042.146 1.417s-.583.583-.229 1.188c-.042-1.104.708-.896.688-1.604.438.334.188 1.043-.062 1.271s-.208.75-.208.75.271-.376.479-.521.352-.564.352-.564.258 1.299-.562 1.354c-.021.605 1.145 2.396 1.562 2.896z"/><path fill="#0081C7" d="M27.35 19.129l.43.21-2.356 2.791 2.196-4.172.324.456.618-2.766-1.803 2.054.468.104-1.644 3.088.521-2.186.417.375V16.25l-1.313 2.396h.48l-.925 3.789-.487.915-.56.216-.227.398-.159.021-1.834 1.955.924.006.184.908.782-.933-.282.912.834-.399.562.733.646-2.584-.295-.558-.008-.026.164-.69 3.121-3.732.209.518 1.242-2.547zM3.646 15.062H1.729s.417.083.604.521 1.361 3.882 1.458 4.296c.146.62-.312.745-.312.745h1.896s-.542-.095-.375-.745S6.271 16 6.396 15.604s.479-.542.479-.542H4.979s.646.144.458.666c-.188.521-1.021 3.313-1.021 3.313s-.938-2.793-1.104-3.313.334-.666.334-.666zm30.198 0h-1.75s.34.234.34.688c0 .461-.012 3.933-.012 4.266 0 .438-.4.609-.4.609h1.895s-.509-.266-.509-.641v-4.336c-.001-.398.436-.586.436-.586z"/><path fill="#F4C63D" d="M32.998 8.479c-.49.062-2.072.917-4.969 1.479-.167-.125-.479-.062-.979.167s-2.896.896-3.562 1.146-1.018.766-.938 1.208c.146.792.729.917.521 1.146-.208.229-.833-.312-1.25-.062-.215.129-1.416-.162-1.445-.292-.104-.458-.562-.854-.562-.854s.354-.062.438-.208c-.584-.333-.958-.979-.958-.979s.375.167.5 0c-.479-.438-.438-1.438-.667-1.875s-.5-.771-1.058-.792c-.558-.021-.775.021-1.109.458-.25-.021-.3.271-.3.271s-.221.021-.575.083-.583.5-.438.896c.083-.229.542-.271.917-.312s.646.417.5.562-.188.333-.271.688-.698.521-.698.521.177.188.448.167c-.146.229-.583.542-.896.583.188.229.479.188.479.188s-.167.458-.479.729c0 0-1.159.296-1.375.167-.417-.25-1.042.292-1.25.062s.375-.354.521-1.146c.081-.442-.271-.958-.938-1.208s-3.062-.917-3.562-1.146-.814-.293-.981-.168c-2.895-.562-4.479-1.416-4.968-1.479s-.636.75.093 1.083c-.208.229-.083.854.542.896-.25.271.062.833 1.188 1.083-.146.292.167.979 1.521 1.208-.146.417.312.854 1.333.979-.188.292.167.75 1.146.854-.312.479.521.812 1.583.792-.354.208-.208.792.292.896-.167.333.292.896.833.812.042.271.417.479.771.229 0 .354.771.75 1 .292.176.175.675.286 1.015-.056.015.083.035.164.056.245-.14.414-.438.858-.926 1.228-.521.396-.791 1.041-.771 1.458s-.146.729-.396.833l.229.084s-.375.499-.583.541-1.208-.083-1.396.104-.562.937-.312 1.083.354.396.5.542.937-.084 1.104-.229.146-.875.292-.958 1.521-.708 1.521-.708l.021.312s.229-.271.417-.354.229-.479.333-.667c.096-.173.778-.781 1.698-.975.116.067-.073.204-.073.204-.366-.081-.521.396-.5.583-.396.042-1.313 1.312-1.458 1.75s-.021.626.167.604c-.021.312.229.573.5.484.021.328.208.537.438.516.042.354.25.562.5.5.042.354.312.542.667.438.021.479.375.937.875.416.083.959 1.271 1.273 1.396.063.437.396 1 .188 1-.479.25.188.604-.062.625-.438.25.104.459-.146.459-.562.271.146.459-.155.438-.474.291.099.562-.192.5-.526.271.104.457-.324.125-.854-.521-.833-1.334-1.438-1.334-1.438s.126-.496-.541-.592c-.09-.013-.189-.135-.09-.193.914.197 1.589.8 1.685.972.104.188.146.584.333.667s.417.354.417.354l.021-.312s1.375.625 1.521.708c.144.083.125.812.291.958.168.146.959.375 1.104.229s.25-.396.5-.542-.125-.896-.312-1.083-1.188-.062-1.396-.104c-.209-.042-.584-.541-.584-.541l.229-.084c-.25-.104-.417-.416-.396-.833.019-.417-.25-1.062-.771-1.458-.477-.363-.772-.795-.915-1.203.023-.09.047-.178.064-.27.34.341.84.23 1.015.055.229.458 1 .062 1-.292.354.25.73.042.771-.229.541.083 1-.479.833-.812.5-.104.646-.688.292-.896 1.062.021 1.896-.312 1.583-.792.979-.104 1.333-.563 1.146-.854 1.021-.125 1.48-.562 1.334-.979 1.354-.229 1.666-.917 1.521-1.208 1.125-.25 1.438-.812 1.188-1.083.625-.042.751-.667.542-.896.725-.331.578-1.143.09-1.081z"/><path fill="#FFF" d="M13.805 15.501c.01 1.006.244 1.883.602 2.646.207.441.454.845.727 1.21l.605.717c.22.232.446.442.671.635l.605.481c.258.191.505.358.727.497.107.067.209.13.303.186.094-.056.196-.119.303-.186.205-.13.432-.282.67-.456l.606-.474c.244-.207.491-.436.73-.688l.605-.717c.273-.364.518-.767.725-1.207.359-.763.593-1.64.602-2.646h-8.481z"/><path fill="#A70033" d="M14.407 15.501v2.646c.207.441.454.845.727 1.21V15.5h.605v4.573c.22.232.446.442.671.635v-5.209h.605v5.69c.258.191.505.358.727.497v-6.188h.605v6.188c.205-.13.432-.282.67-.456v-5.732h.606v5.258c.244-.207.491-.436.73-.688v-4.57h.605v3.853c.273-.364.518-.767.725-1.207v-2.646h-7.276z"/><path fill="#172668" d="M18.046 12.521s-1.043.544-2.182.544-2.062-.523-2.062-.523v2.896c0 .1.01.194.014.291h8.46c.005-.097.015-.191.015-.291v-2.896s-.924.523-2.062.523c-1.14 0-2.183-.544-2.183-.544z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1f3.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1f3.svg new file mode 100644 index 0000000000000000000000000000000000000000..4e0e1b586d882672a8eb08dc42187929e5d843ff --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1f3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DA251D" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FF0" d="M19.753 16.037L18 10.642l-1.753 5.395h-5.672l4.589 3.333-1.753 5.395L18 21.431l4.589 3.334-1.753-5.395 4.589-3.333z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1fa.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..151e7aaa7c9bf01fe1a40004654e222edb3cbef9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fb-1f1fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D21034" d="M32 5H4C1.791 5 0 6.791 0 9v9h36V9c0-2.209-1.791-4-4-4z"/><path fill="#009543" d="M4 31h28c2.209 0 4-1.791 4-4v-9H0v9c0 2.209 1.791 4 4 4z"/><path fill="#141414" d="M17 15L1.732 5.705c-.474.327-.874.754-1.17 1.25l-.002.002C.205 7.555 0 8.254 0 9v18c0 .747.205 1.447.562 2.045l.001.003c.301.504.71.937 1.195 1.265h.001L17 21h19v-6H17z"/><path fill="#FDCE12" d="M.562 6.955l-.002.002C.205 7.555 0 8.254 0 9l15 9-15 9c0 .747.205 1.447.562 2.045L17 19h19v-2H17L.562 6.955z"/><path fill="#FDCE12" d="M4.375 21.606s3.25-.5 3.25-3.71c0-1.974-1.708-3.062-3.042-3.062-1.333 0-2.75 1-2.75 2.75s1.625 2.292 2.417 2.292 2-.625 1.833-2c-.464 1.913-2.413 1.858-3.167.708-.833-1.271.459-3.084 2.126-2.584 1.579.474 1.661 2.081 1.125 3.084-.667 1.25-1.771 1.188-1.771 1.188l-.021 1.334z"/><path fill="#FDCE12" d="M5.376 18.021c-.183-.242-.407-.461-.636-.653.492-.505.911-.648.781-.722-.089-.051-.549.156-1.041.516-.492-.36-.952-.567-1.041-.516-.13.075.289.218.781.722-.229.192-.453.41-.636.653-.199.263-.167.708-.167.708s.269-.108.5-.333c.187-.181.347-.446.563-.723.216.277.376.542.563.723.231.225.5.333.5.333s.032-.445-.167-.708z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1eb.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1eb.svg new file mode 100644 index 0000000000000000000000000000000000000000..9895422507e6693cbbf8a595d78809cc59a2ecce --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1eb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED2939" d="M32 5H18v12H0v10c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 16h19v2H0z"/><path fill="#002395" d="M6 17H0V9c0-2.209 1.791-4 4-4h2v12z"/><path fill="#EEE" d="M6 5h6v12H6zm11 0h2v13h-2z"/><path fill="#ED2939" d="M12 5h6v12h-6z"/><path d="M24.38 22.32h6.24L27.5 19.2zM30.62 14h-6.24l3.12 3.12zm1.04 7.28v-6.24l-3.12 3.12zm-8.32-6.24v6.24l3.12-3.12z" fill="#FFF"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1f8.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..6b075cb0615aa253732c6da5ea22044ef1da74c6 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fc-1f1f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CE1126" d="M32 5H19v13H0v9c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#002B7F" d="M19 5H4C1.791 5 0 6.791 0 9v9h19V5zM9.076 6.591l.341-1.049.341 1.049h1.103l-.893.649.341 1.049-.892-.648-.893.648.341-1.049-.893-.649h1.104zm-2.739 4.948l-.893-.649-.893.649.341-1.049L4 9.841h1.103l.341-1.049.341 1.049h1.103l-.892.649.341 1.049zm4.196 5.919l-1.116-.811-1.116.811.426-1.312-1.116-.811H8.99l.426-1.312.426 1.312h1.379l-1.116.811.428 1.312zm1.428-4.152l-.558-.406-.558.405.213-.656-.558-.405h.69l.213-.656.213.656h.69l-.558.405.213.657zm2.355-2.48l-.837-.608-.837.608.32-.984-.837-.608h1.034l.32-.984.32.984h1.034l-.837.608.32.984z"/><path fill="#FFF" d="M8.524 8.289l.893-.648.892.648-.341-1.049.893-.649H9.758l-.341-1.049-.341 1.049H7.972l.893.649zM5.785 9.841l-.341-1.049-.341 1.049H4l.893.649-.341 1.049.892-.648.893.648-.341-1.049.893-.649zm8.014-.607l-.32-.984-.32.984h-1.034l.837.608-.32.984.837-.608.837.608-.32-.984.837-.608zm-2.183 3.01l-.213-.656-.213.656h-.69l.558.406-.213.656.558-.406.558.406-.213-.656.558-.406zm-1.773 3.092l-.426-1.312-.427 1.312H7.611l1.116.81-.426 1.312 1.116-.81 1.116.81-.427-1.312 1.116-.81z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fd-1f1f0.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fd-1f1f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..39890a907e6feb58920cb4a5a303e025f5c2aa19 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fd-1f1f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#244AA5" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#D0A650" d="M17.013 13.696l.209-.005c.123.128.25.253.376.378-.002.097.038.167.136.196-.087.023-.177.03-.265.04-.037.05-.082.089-.136.117.015.143.146.224.235.321.094.009.198.007.27.079l.206.005.001.268c.085-.009.192.007.217-.1.15-.001.3-.002.451.001.039.083.132.088.206.123l.036.186c.076-.098.148-.223.287-.227.043.06.088.119.133.178.078.006.16.014.195.099l.139.005c0 .167-.012.335.01.501l.082.05c.002.134.002.268 0 .401.084.071.225.136.299.012h.119c.051.074.113.139.189.188.002.131 0 .262.002.392.174.063.062.3.096.441.088.06.158.139.199.239.023-.045.051-.089.076-.133l.301.006c.045.053.09.105.139.158l.082.089c.07.018.139.039.195.087l.178.011c.047.107.168.092.264.112l-.131.098c-.004.219.016.439-.01.657l-.08.045c-.002.111-.021.221-.096.311l.184-.002.008.102h.085c.002-.025.006-.076.01-.102h.16l.006.098c.096.018.234-.035.287.075.246.005.492.003.74.001l.01.131c.039.044.076.088.113.133.082 0 .166 0 .25.002l-.008.146c.076.068.16.129.267.129l.002-.183.162.002.012-.101c.117.007.27-.029.297.127l.096-.143c.078.023.143.075.207.123l.002.133c.135.028.082.174.094.271l-.17.134c0 .138 0 .276-.002.415l-.166.004v.474c-.096.077-.182.163-.27.246v.29c-.065.054-.125.107-.188.16v.122c-.068.061-.145.108-.236.12-.043.051-.086.103-.127.155-.029.009-.088.024-.117.031l.145.086c-.002.19-.004.381-.002.571-.115.097-.266.091-.406.09l-.148.18c-.105-.001-.18.069-.244.142.002.091.004.182.008.272.16.085.223.319.428.311.002.151.029.325-.115.424-.064-.002-.131-.002-.193-.002-.1.144-.318.046-.467.071v-.166l-.139-.004c-.047.055-.094.108-.143.161-.082.011-.15.052-.213.101-.1.007-.199.004-.297.004l-.008.103-.223-.005c-.062.062-.113.135-.119.227l-.154.132c.004.107.006.223-.107.272.023.121-.066.333.106.366l-.006.133c-.232.008-.465.004-.697.005l-.004-.235c-.168-.048-.064-.264-.094-.389l-.1-.006.002-.156c-.076-.008-.164.004-.195-.082h-.137l-.012-.189-.424-.001c-.004.033-.008.099-.01.131-.041.044-.08.088-.119.133l-.215.001c-.039.055-.075.108-.112.164-.104.002-.21.003-.315.007-.037.044-.078.086-.122.123l-.005.132c-.081.008-.169.009-.191.104h-.208c-.044.056-.087.112-.129.169l-.384.001c-.06.149-.241.076-.363.098-.052.073-.115.136-.19.185-.002.081-.003.163-.003.246l-.101.006-.002.238c-.058.044-.114.09-.171.136.006.213.005.425.001.639l.171.137v.563c-.04.038-.079.077-.117.117l-.145.003-.004.148-.113.111c-.156 0-.312 0-.467.002-.071.091-.146.179-.221.267l-.312-.002c-.015-.08-.031-.161-.086-.225-.008-.208-.004-.415-.004-.623.086-.084.171-.17.261-.252v-.271l-.086-.049c-.019-.281-.001-.565-.006-.849h-.155c-.013-.087.003-.201-.115-.211-.001-.213-.001-.425.003-.638l-.156-.134c-.014-.082-.014-.176-.108-.207l-.004-.183c-.112-.05-.093-.229.026-.254-.099-.087-.191-.181-.286-.27l-.002-.116c-.11-.022-.208-.075-.315-.104-.03-.076-.105-.083-.177-.086l-.069-.076c-.067-.008-.124-.035-.17-.082l-.123-.003c-.039-.167-.116-.323-.095-.5-.043-.038-.083-.08-.121-.123-.216-.009-.431.003-.646-.004-.055.002-.102-.016-.14-.056-.048-.049-.098-.096-.149-.141-.003-.144.005-.288-.006-.431-.038-.1-.101-.186-.159-.272l-.005-.131-.096-.014.001-.135c-.104-.062-.062-.193-.078-.292l-.258-.006v-.133l-.129-.122-.139-.009-.003-.136c-.079-.05-.101-.132-.098-.221l.175-.007c0-.158.002-.317-.006-.476-.052-.099-.096-.205-.179-.282l-.083-.102-.123-.01-.114-.114-.001-.195c-.132-.027-.083-.172-.1-.269-.159-.104-.019-.297.026-.427.03-.037.062-.072.096-.106.059-.059.112-.124.161-.191h.229l.136.174.152-.01v.178c.287 0 .574-.002.861.002.008-.084-.007-.187.1-.205.002-.164.002-.328.007-.492.1-.008.215.012.29-.075l.136-.008v-.266c.138 0 .278.007.416-.007l.047-.099c.093-.005.15.044.174.131.051-.062.103-.122.156-.181.088-.02.169-.057.227-.128.091-.076.206-.113.309-.171l-.101-.1c-.004-.123-.087-.209-.183-.273-.002-.121-.002-.242 0-.363.073-.066.145-.135.213-.206h.187c.11-.151.248-.279.394-.395v-.138c.036.002.108.002.144.003.014.089.089.097.162.099.035-.048.075-.092.12-.132l.009-.11c.136-.091.043-.293.073-.431.067-.066.162-.118.192-.213-.027-.094-.123-.144-.187-.211.048-.221-.158-.32-.271-.469l-.154-.017c-.017-.074-.01-.165-.084-.212-.003-.104-.003-.209-.002-.314.223-.005.447.015.669-.01l.044-.076c.095-.059.199-.101.284-.174.093-.003.186-.004.279-.004.044-.058.09-.113.135-.17l.152.005c.004-.019.01-.066.013-.091z"/><path fill="#EDEDED" d="M28.021 9.212l-.385 1.181-1.223-.013 1.004.731-.391 1.159 1.004-.729.982.729-.381-1.181.996-.709h-1.242l-.364-1.168zm-4.007-1.08l-.385 1.181-1.225-.013 1.006.729-.391 1.16 1.004-.729.983.729-.383-1.181.998-.708h-1.242l-.365-1.168zm-4.009-.527l-.385 1.18-1.224-.012 1.005.729-.391 1.16 1.004-.73.983.73-.383-1.182.998-.708H20.37l-.365-1.167zM7.979 9.212l.384 1.181 1.224-.013-1.005.73.39 1.159-1.004-.729-.982.729.383-1.181-.998-.708h1.241l.367-1.168zm4.008-1.08l.384 1.181 1.224-.013-1.004.729.39 1.16-1.004-.729-.983.729.384-1.181-.998-.708h1.241l.366-1.168zm4.009-.527l.384 1.18 1.224-.012-1.005.729.391 1.16-1.004-.73-.983.73.384-1.182-.997-.708 1.241-.001.365-1.166z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1ea.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..a82532c3cbbd0902ea5b4fc4778056f934f3cd39 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M0 27.063C0 29.272 1.791 31 4 31h28c2.209 0 4-1.728 4-3.937V22H0v5.063z"/><path fill="#EEE" d="M0 14h36v8H0z"/><path fill="#CE1126" d="M32 5H4C1.791 5 0 6.854 0 9.063V14h36V9.063C36 6.854 34.209 5 32 5z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1f9.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..76765b938bd32ec38890c649ad5901115d1d4ebd --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1fe-1f1f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path d="M8.775 8.131h.557l.825 2.426.819-2.426h.553V11h-.371V9.307c0-.059.001-.156.004-.291s.004-.281.004-.436l-.82 2.42h-.385l-.827-2.42v.088c0 .07.002.177.006.321s.006.25.006.317V11h-.371V8.131zm4.579 0h.438L14.834 11h-.426l-.299-.859h-1.126l-.311.859h-.398l1.08-2.869zm.645 1.693l-.442-1.268-.459 1.268h.901zm.669-1.693h.453l.825 1.379.825-1.379h.457l-1.086 1.713V11h-.389V9.844l-1.085-1.713zm5.253.41c.189.254.285.579.285.975 0 .428-.109.785-.326 1.068-.256.333-.619.5-1.092.5-.441 0-.789-.146-1.041-.438-.225-.281-.338-.637-.338-1.066 0-.388.096-.72.289-.996.248-.354.613-.531 1.098-.531.506 0 .881.162 1.125.488zm-.343 1.829c.152-.246.229-.528.229-.847 0-.337-.089-.609-.265-.815-.177-.206-.418-.309-.724-.309-.297 0-.539.102-.727.306-.188.204-.281.504-.281.902 0 .318.081.586.241.804s.421.328.782.328c.344-.001.592-.124.745-.369zm3.177-2.239v.342h-.967V11h-.393V8.473h-.967v-.342h2.327zm2.602 0v.342h-.967V11h-.393V8.473h-.967v-.342h2.327zm.635 0h2.082v.352h-1.703v.871h1.574v.332h-1.574v.973h1.732V11h-2.111V8.131z" fill="#D42E11"/><path fill="#231F20" d="M18 24.91c-.069 0-.125-.056-.125-.124v-.001c0-.035-.015-.875-.875-.875h-2c-1.105 0-1.847-.854-1.847-2.125v-8.449c0-.069.056-.125.125-.125h9.423c.069 0 .125.056.125.125v8.449c0 1.271-.733 2.125-1.826 2.125h-2c-.86 0-.875.84-.875.875v.001c0 .068-.056.124-.125.124z"/><path fill="#EEE" d="M13.403 13.461v8.324c0 .934.494 1.875 1.597 1.875h2c.552 0 .852.283 1 .591.148-.308.448-.591 1-.591h2c.957 0 1.576-.736 1.576-1.875v-8.324h-9.173z"/><path fill="#269" d="M20.5 16.525c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#269" d="M20.5 18.025c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#269" d="M19 16.525c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#269" d="M19 18.025c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#269" d="M17.5 16.525c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#269" d="M17.5 18.025c0 .538-.448.975-1 .975-.553 0-1.001-.437-1.001-.975s.448-.975 1.001-.975c.552.001 1 .437 1 .975z"/><path fill="#171796" d="M22 16.525c0-.308-.156-.571-.386-.75.23-.178.386-.441.386-.75 0-.538-.448-.975-1-.975-.294 0-.552.128-.735.325-.183-.223-.451-.375-.765-.375-.305 0-.568.142-.752.354-.183-.212-.445-.354-.748-.354-.304 0-.567.143-.75.357-.184-.214-.447-.357-.75-.357-.304 0-.567.143-.75.357-.184-.214-.446-.357-.75-.357-.553 0-1 .448-1 1 0 .304.143.566.356.75-.213.184-.356.446-.356.75s.143.566.356.75c-.213.184-.356.446-.356.75 0 .552.447 1.25 1 1.25h6c.552 0 1-.562 1-1.1 0-.308-.156-.634-.386-.812.23-.179.386-.504.386-.813z"/><path fill="#D42E11" d="M22 19.025c0-.194-.06-.374-.16-.525h-7.681c-.1.152-.16.331-.16.525 0 .304.146.571.369.75-.224.179-.369.446-.369.75s.146.571.369.75c-.224.179-.369.446-.369.75 0 .538.448.975 1.001.975.3 0 .566-.132.75-.336.183.204.449.336.75.336.3 0 .566-.132.75-.336.183.204.449.336.75.336.3 0 .566-.132.75-.336.183.204.449.336.75.336.3 0 .566-.132.75-.336.183.204.449.336.75.336.552 0 1-.437 1-.975 0-.304-.146-.571-.369-.75.223-.178.369-.446.369-.75s-.146-.571-.369-.75c.223-.178.369-.446.369-.75z"/><path fill="#EEE" d="M18 17c-.931 0-1.706-.639-1.93-1.5-.041.161-.07.326-.07.5 0 1.104.896 2 2 2s2-.896 2-2c0-.174-.029-.339-.071-.5-.223.861-.998 1.5-1.929 1.5z"/><path fill="#FFAC33" d="M16.869 20.627c-.101-.058-.196-.098-.286-.127.089-.029.185-.069.286-.127.287-.165.475-.377.42-.473-.056-.096-.333-.039-.62.127-.101.058-.182.121-.252.184.019-.092.033-.194.033-.311 0-.332-.089-.601-.2-.601-.111 0-.2.269-.2.601 0 .116.014.219.033.311-.07-.062-.152-.126-.253-.184-.287-.166-.564-.223-.62-.127-.055.096.132.307.42.473.101.058.196.098.285.127-.089.029-.185.069-.285.127-.288.166-.476.378-.42.473.055.096.333.039.62-.127.101-.058.183-.121.253-.184-.019.092-.033.194-.033.311 0 .332.089.601.2.601.11 0 .2-.269.2-.601 0-.116-.014-.219-.033-.31.07.063.152.126.253.184.287.165.564.222.62.126.054-.096-.134-.308-.421-.473zm3.5 0c-.101-.058-.196-.098-.285-.127.089-.029.185-.069.285-.127.287-.165.475-.377.42-.473-.056-.096-.333-.039-.62.127-.1.058-.182.121-.252.183.019-.092.033-.194.033-.31 0-.332-.09-.601-.2-.601s-.2.269-.2.601c0 .116.014.219.033.311-.07-.063-.152-.126-.253-.184-.287-.166-.564-.223-.62-.127-.055.096.133.307.42.473.101.058.197.098.286.127-.089.029-.185.069-.286.127-.287.166-.475.378-.42.473.056.096.333.039.62-.127.101-.058.183-.121.253-.184-.019.092-.033.194-.033.311 0 .332.09.601.2.601s.2-.269.2-.601c0-.116-.014-.218-.033-.31.07.062.151.126.252.184.287.165.565.222.62.126.056-.096-.133-.308-.42-.473z"/><path fill="#CCD6DD" d="M9.181 28.658s2.397-1.298 3.167-1.473c.771-.177 1.65-.198 1.299.329-.353.527.065 1.166-.484 1.1s-1.804.506-2.266.705c-.462.197-1.145.55-1.145.55l-.571-1.211z"/><path fill="#66757F" d="M13.998 27.845c-.132-.33-.306-.659-.306-.659s-.085.2-.387.337c-.262.119-.521.33-.451.477.097.204 1.144-.155 1.144-.155z"/><path fill="#CCD6DD" d="M27.154 28.658s-2.398-1.298-3.169-1.473c-.769-.177-1.649-.198-1.298.329.354.527-.065 1.166.485 1.1.551-.066 1.803.506 2.266.705.462.197 1.145.55 1.145.55l.571-1.211z"/><path fill="#66757F" d="M22.336 27.845c.132-.33.306-.659.306-.659s.086.2.388.337c.262.119.521.33.45.477-.096.204-1.144-.155-1.144-.155z"/><path fill="#CCD6DD" d="M21.963 27.339c-.595-.198-2.222-.309-2.751-.309h-2.089c-.528 0-2.155.11-2.75.309-.594.198-1.108.672-1.518.66.03.125.065.285.22.77.153.484.572.462 1.056.221.484-.243 1.189-.396 1.849-.396h4.377c.661 0 1.365.153 1.849.396.483.241.902.264 1.057-.221.153-.484.188-.645.219-.77-.413.012-.926-.462-1.519-.66z"/><path fill="#99AAB5" d="M15.585 27.5h1.73v.819h-1.73zm2.593 0h2.949v.819h-2.949z"/><path fill="#CCD6DD" d="M6.464 12.875l.99.25.833-.667s1-.375 1.542-.083c.541.292.083.25-.417.375s-.606.622-.479.812c.188.281.759.304.688-.125-.031-.188.792.229.708.688l-.083.458s-.042 1.042.625 1.25.594.833-.031.792-1.677-.833-1.677-.833-.542.375-.667.125c0 0-1.292-.292-1.125-1.458 0 0-.406 1.292.406 1.729 1.17.63 1.316.196 2.302.979 1.167.927 2.083 2.646 1.792 5.021s-.958 3.969-3.625 3.969c-1.562 0-2.406-1.167-2.406-2.312C5.839 22.698 6.87 22 7.526 22c.781 0 1.031.75.938.938-.314.628-.615.194-.375-.094.156-.188-.157-.484-.531-.469-.75.031-1.156.76-1.156 1.469 0 .709.802 1.781 1.802 1.781s2.125-.916 2.125-2.333-.584-2.333-1.542-3.125l-.479.927s-1.833-.261-2.875-1.344c-1.042-1.083-.941-2.463-.75-2.312.438.344 1.479.396 1.479.396s-.416-.875-.708-1.042c-.292-.167-.886-1.063-.427-2.104.458-1.042 1.136-1.354 1.302-1.021.166.333.604.104.479-.229s-.344-.563-.344-.563z"/><path fill="#99AAB5" d="M5.933 17.406c.594.812 1.281 1.875 2.281 2.406 1 .531 2.156 1.906 2.156 3.281s-.927 2.531-2.166 2.531c-1.24 0-1.833-1.156-1.833-1.906s.656-1.156.656-1.156-.719.156-.875 1.094c-.139.832.656 2.188 1.969 2.188 1.937 0 2.656-1.312 2.656-2.75s-1.25-3-2.094-3.844c-.844-.844-2-1.812-2.531-2.375s-.219.531-.219.531z"/><path fill="#CCD6DD" d="M29.479 12.875l-.989.25-.834-.667s-1-.375-1.541-.083c-.542.292-.084.25.416.375s.607.622.479.812c-.188.281-.759.304-.688-.125.031-.188-.792.229-.708.688l.083.458s.042 1.042-.625 1.25-.594.833.031.792 1.677-.833 1.677-.833.542.375.667.125c0 0 1.292-.292 1.125-1.458 0 0 .406 1.292-.406 1.729-1.171.63-1.315.196-2.302.979-1.167.927-2.084 2.646-1.792 5.021s.958 3.969 3.625 3.969c1.562 0 2.406-1.167 2.406-2.312 0-1.146-1.031-1.844-1.688-1.844-.781 0-1.031.75-.938.938.313.628.615.194.375-.094-.156-.188.157-.484.531-.469.75.031 1.156.76 1.156 1.469 0 .709-.802 1.781-1.802 1.781s-2.125-.916-2.125-2.333.584-2.333 1.541-3.125l.479.927s1.833-.261 2.875-1.344.94-2.463.75-2.312c-.438.344-1.479.396-1.479.396s.416-.875.709-1.042c.291-.167.885-1.063.427-2.104s-1.136-1.354-1.302-1.021c-.167.333-.604.104-.479-.229s.346-.564.346-.564z"/><path fill="#99AAB5" d="M30.01 17.406c-.594.812-1.281 1.875-2.281 2.406-1 .531-2.156 1.906-2.156 3.281s.927 2.531 2.167 2.531c1.239 0 1.833-1.156 1.833-1.906s-.656-1.156-.656-1.156.719.156.875 1.094c.139.832-.656 2.188-1.969 2.188-1.938 0-2.656-1.312-2.656-2.75s1.25-3 2.094-3.844c.844-.844 2-1.812 2.531-2.375.53-.563.218.531.218.531z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1e6.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..275c136da087b5f28267a137f179472e1566b990 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DE3830" d="M32 5H6.5L19 13.5h17V9c0-2.209-1.791-4-4-4z"/><path fill="#002395" d="M6.5 31H32c2.209 0 4-1.791 4-4v-4.5H19L6.5 31z"/><path fill="#141414" d="M0 11v14l10.5-7z"/><path fill="#FFB611" d="M0 9v2l10.5 7L0 25v2l13.5-9z"/><path fill="#007A4D" d="M3.541 5.028C1.548 5.257 0 6.947 0 9l13.5 9L0 27c0 2.053 1.548 3.743 3.541 3.972L18.5 20.5H36v-5H18.5L3.541 5.028z"/><path fill="#EEE" d="M6.5 5H4c-.156 0-.308.011-.459.028L18.5 15.5H36v-2H19L6.5 5zM3.541 30.972c.151.017.303.028.459.028h2.5L19 22.5h17v-2H18.5L3.541 30.972z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1f2.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..d27689638e9dbe598c0324861b1890f1c4cfda60 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#1A8A00" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#EF7D00" d="M31 31h1c2.209 0 4-1.791 4-4V15h-5v16z"/><path fill="#141414" d="M26 15h5v16h-5z"/><path fill="#DE200F" d="M21 15h5v16h-5z"/><path fill="#EF7D00" d="M35.083 8.256c-.109-.021-.716.325-.716.325s.564-.65.434-.65c-.13 0-.866.346-.866.346s.455-.563.303-.498c-.152.065-.976.433-1.604.696.088-.149.065-.372 0-.372-.064 0-.434.238-.997.369-.564.13-1.408.607-1.777.542-.368-.065-1.105 0-1.105 0s-.216-.325-.043-.412c.172-.087.304.13.304.13s.304-.13.304-.314-.521-.206-.521-.206-.218-.281-.563-.281c-.91 0-.976.975-.976.975s-.369-.13-.715-.217c-.347-.087-.954-.043-1.56-.412-.606-.369-.997-.498-.261.282-1.084-.369-1.646-1.105-1.799-.786-.152.32.412.699.412.699s-.304-.086-.563-.325c-.26-.239-.629-.39-.281.13-.455-.13-.13.347-.13.347s-.369.108 0 .368c.368.26 1.04.369 1.04.369s-.304.216-.109.303.521.022.521.022-.26.216 0 .303.585 0 .585 0-.108.217.151.314c.261.098.673-.119.673-.119s-.195.13 0 .238c.195.108.498-.119.498-.119s-.173.292 0 .336c.173.043.455-.173.455-.173s-.173.281 0 .303c.173.022.563-.195.563-.195s-.238.303 0 .303c.239 0 .521-.151.521-.151s-.065.238.13.325c.195.087.476-.152.476-.152s.066.456.022.715c-.043.26.281.065.281.065s-.044.39-.304.369c-.26-.022-.521.325-.433.412.087.087.433-.065.433-.065s-.021.477.108.437c.13-.04.347-.307.347-.307s.13.347.218.304c.087-.044.13-.238.13-.347s.237-.152.237-.152.065.433.152.349c.088-.085.108-.371.238-.457.13-.086.087.498.217.455.131-.043.065-.434.022-.564-.043-.13.261.108.239 0-.021-.109-.261-.325-.261-.325s.303.109.217 0-.13-.39 0-.329.239-.191.239-.191.346.26.562.173c.216-.086-.281-.39-.281-.39s.759.26.926.217c.168-.044-.255-.325-.255-.325s.477.108.564 0c.086-.109-.31-.195-.31-.195s.525.087.591 0c.065-.087-.151-.195-.151-.195s.866-.021 1.04-.325c.867.022 1.82-.671 1.907-.823.086-.152-.151-.152-.151-.152s.521-.412.455-.477c-.065-.065-.347.086-.347.086s.672-.585.564-.606zm-6.436 3.727c-.28 0-.088-.151-.132-.303-.044-.152.152-.021.13-.152-.023-.13 0-.758 0-.758.217.217.325.499.304.715-.021.217.108.238.151.347.044.109-.172.151-.453.151z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1fc.svg b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..15a8464566cfcc8b88a9e2049269a80361e07b74 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/1f1ff-1f1fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EEE" d="M10.154 12L1.833 5.637c-.176.114-.344.242-.5.381v.001C.515 6.752 0 7.816 0 9v18c0 1.184.515 2.248 1.333 2.981.156.14.324.267.501.382L18 18l-7.846-6z"/><path fill="#DE200F" d="M6.682 11.597l1.783 3.613 3.989.58-2.887 2.813.682 3.972-3.567-1.876-3.567 1.876.681-3.972L.91 15.79l3.988-.58z"/><path fill="#FFD200" d="M7.5 15.458c-.917-.75-1.292-1.292-1.958-2.333s-1.542-.917-1.917 0c-.583.125-.75.75-.75.75.958-.292 1.583.333 1.667 1.667s-.25 1.708-.833 2.875.083 1.458.083 1.458l.384 2.026h5.958l.825-3.568h.5c-.001 0-3.042-2.125-3.959-2.875z"/><path fill="#FFAC33" d="M5.812 16.531l-.344.236s.625 1.369 1.531 1.566 3.837.523 3.837.523l.121-.523s-3.031-.365-3.792-.49-1.353-1.312-1.353-1.312zm-.75 3.376s1.281-.106 1.938 0c.613.099 3.193.242 3.534.261l.113-.49c-.349-.056-3.075-.491-3.835-.536-.812-.048-1.624.346-1.75.765zm.657.968l.156 1.026h4.258l.182-.785c-2.073-.41-4.596-.241-4.596-.241z"/><path fill="#F15A29" d="M10.173 21.951H4.134l-.008-.04-.379-2.003c-.058-.032-.201-.132-.278-.345-.109-.3-.043-.693.194-1.169.088-.176.171-.334.247-.481.42-.806.651-1.25.582-2.369-.047-.746-.264-1.273-.627-1.525-.263-.182-.591-.214-.975-.097l-.086.026.023-.087c.007-.026.176-.638.762-.78.186-.438.494-.707.847-.739.407-.035.814.231 1.148.755.643 1.004 1.021 1.564 1.948 2.322.905.74 3.925 2.852 3.956 2.873l.13.091h-.619l-.826 3.568zm-5.956-.099h5.876l.825-3.568h.382c-.591-.415-3.032-2.132-3.832-2.787-.938-.768-1.32-1.332-1.968-2.345-.313-.491-.694-.744-1.055-.709-.322.029-.604.285-.774.701l-.01.024-.026.005c-.418.09-.612.458-.681.627.376-.094.701-.048.968.137.39.27.622.824.67 1.601.072 1.147-.164 1.6-.592 2.422-.076.146-.158.304-.246.479-.221.442-.287.817-.191 1.087.081.225.243.3.25.303l.024.011.005.025.375 1.987z"/><path fill="#319209" d="M35.873 8C35.429 6.275 33.864 5 32 5H4c-.798 0-1.542.234-2.166.636l-.001.001L4.923 8h30.95zm0 20c-.444 1.725-2.01 3-3.873 3H4c-.798 0-1.542-.234-2.166-.636l-.001-.001L4.923 28h30.95z"/><path fill="#FFD200" d="M4.923 8L18 18 4.923 28h30.95c.083-.321.127-.653.127-1V9c0-.343-.046-.682-.127-1 0-.002-30.95 0-30.95 0z"/><path fill="#DE200F" d="M10.154 12l5.231 4H36v-4zm0 12H36v-4H15.385z"/><path fill="#141414" d="M15.385 16L1.833 5.637c-.176.114-.344.242-.5.381v.001L17 18 1.333 29.981c.156.14.324.267.501.382L15.385 20H36v-4H15.385z"/></svg> \ No newline at end of file diff --git a/browser/components/torcircuit/content/tor-circuit-flags/README.txt b/browser/components/torcircuit/content/tor-circuit-flags/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..08cee867d4c9e991862ba2a0156a5408e5a4f6bc --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-flags/README.txt @@ -0,0 +1 @@ +Generated by tools/torbrowser/update_emojis.py on 2024-08-06 diff --git a/browser/components/torcircuit/content/tor-circuit-icon-mask.svg b/browser/components/torcircuit/content/tor-circuit-icon-mask.svg new file mode 100644 index 0000000000000000000000000000000000000000..b9a82c8fc523b7b1c7b426c2ae48fbcfd544b524 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-icon-mask.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<!-- NOTE: We fill with #000000 since this image is used as a CSS mask-image. --> +<path fill-rule="evenodd" d="M5.27778 3.13889C5.27778 4.10273 4.64025 4.91767 3.76389 5.18502V11.9028C3.76389 12.9 4.57226 13.7083 5.56944 13.7083C6.56662 13.7083 7.375 12.9 7.375 11.9028V9.85169C7.3881 9.85568 7.40125 9.85955 7.41445 9.8633C6.51783 9.60866 5.86111 8.7838 5.86111 7.80556C5.86111 6.84172 6.49864 6.02678 7.375 5.75943L7.375 4.09722C7.375 2.40969 8.74302 1.04167 10.4306 1.04167C12.1181 1.04167 13.4861 2.40969 13.4861 4.09722V10.815C14.3625 11.0823 15 11.8973 15 12.8611C15 14.0424 14.0424 15 12.8611 15C11.6798 15 10.7222 14.0424 10.7222 12.8611C10.7222 11.8973 11.3597 11.0823 12.2361 10.815V4.09722C12.2361 3.10004 11.4277 2.29167 10.4306 2.29167C9.43337 2.29167 8.625 3.10004 8.625 4.09722V5.75943C9.50137 6.02678 10.1389 6.84172 10.1389 7.80556C10.1389 8.7694 9.50137 9.58433 8.625 9.85168V11.9028C8.625 13.5903 7.25698 14.9583 5.56944 14.9583C3.88191 14.9583 2.51389 13.5903 2.51389 11.9028V5.18502C1.63752 4.91766 1 4.10273 1 3.13889C1 1.95761 1.95761 1 3.13889 1C4.32016 1 5.27778 1.95761 5.27778 3.13889ZM4.02778 3.13889C4.02778 3.62981 3.62981 4.02778 3.13889 4.02778C2.64797 4.02778 2.25 3.62981 2.25 3.13889C2.25 2.64797 2.64797 2.25 3.13889 2.25C3.62981 2.25 4.02778 2.64797 4.02778 3.13889ZM8.88889 7.80556C8.88889 8.29648 8.49092 8.69444 8 8.69444C7.50908 8.69444 7.11111 8.29648 7.11111 7.80556C7.11111 7.31464 7.50908 6.91667 8 6.91667C8.49092 6.91667 8.88889 7.31464 8.88889 7.80556ZM13.75 12.8611C13.75 13.352 13.352 13.75 12.8611 13.75C12.3702 13.75 11.9722 13.352 11.9722 12.8611C11.9722 12.3702 12.3702 11.9722 12.8611 11.9722C13.352 11.9722 13.75 12.3702 13.75 12.8611Z" fill="#000000"/> +</svg> diff --git a/browser/components/torcircuit/content/tor-circuit-node-end.svg b/browser/components/torcircuit/content/tor-circuit-node-end.svg new file mode 100644 index 0000000000000000000000000000000000000000..b12c561090c61f1398f7935edfcf438b8af652d4 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-node-end.svg @@ -0,0 +1,4 @@ +<svg width="12" height="30" viewBox="0 0 12 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="5" width="2" height="10" fill="context-fill"/> +<circle cx="6" cy="16" r="5" stroke="context-fill" stroke-width="2"/> +</svg> diff --git a/browser/components/torcircuit/content/tor-circuit-node-middle.svg b/browser/components/torcircuit/content/tor-circuit-node-middle.svg new file mode 100644 index 0000000000000000000000000000000000000000..b0e8b29ad6c66bd8ef9bb7af85d1dc7855403aab --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-node-middle.svg @@ -0,0 +1,5 @@ +<svg width="12" height="30" viewBox="0 0 12 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="5" width="2" height="9" fill="context-fill"/> +<circle cx="6" cy="15" r="5" stroke="context-fill" stroke-width="2"/> +<rect x="5" y="21" width="2" height="9" fill="context-fill"/> +</svg> diff --git a/browser/components/torcircuit/content/tor-circuit-node-relays.svg b/browser/components/torcircuit/content/tor-circuit-node-relays.svg new file mode 100644 index 0000000000000000000000000000000000000000..54e7d26678e8a78b6de3870cf2bfe475d85b8c71 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-node-relays.svg @@ -0,0 +1,7 @@ +<svg width="12" height="30" viewBox="0 0 12 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="5" width="2" height="4.5" fill="context-fill"/> +<circle cx="6" cy="10" r="1.5" fill="context-fill"/> +<circle cx="6" cy="15" r="1.5" fill="context-fill"/> +<circle cx="6" cy="20" r="1.5" fill="context-fill"/> +<rect x="5" y="25.5" width="2" height="4.5" fill="context-fill"/> +</svg> diff --git a/browser/components/torcircuit/content/tor-circuit-node-start.svg b/browser/components/torcircuit/content/tor-circuit-node-start.svg new file mode 100644 index 0000000000000000000000000000000000000000..8491b7dcd9e1a7b2c7241feb71efdb87663318c9 --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-node-start.svg @@ -0,0 +1,4 @@ +<svg width="12" height="30" viewBox="0 0 12 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="6" cy="14" r="5" stroke="context-fill" stroke-width="2"/> +<rect x="5" y="20" width="2" height="10" fill="context-fill"/> +</svg> diff --git a/browser/components/torcircuit/content/tor-circuit-redirect.svg b/browser/components/torcircuit/content/tor-circuit-redirect.svg new file mode 100644 index 0000000000000000000000000000000000000000..08414355cc33d21f8eefa65457d3f6c871cc809c --- /dev/null +++ b/browser/components/torcircuit/content/tor-circuit-redirect.svg @@ -0,0 +1,4 @@ +<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M8.9002 3.80003C8.7002 3.60003 8.8002 3.30003 9.0002 3.10003C9.2002 3.00003 9.6002 3.00003 9.7002 3.30003C10.2002 4.00003 10.5002 4.90003 10.5002 5.80003C10.5002 8.30003 8.5002 10.3 6.0002 10.3V11.8C6.0002 12 5.80019 12.1 5.7002 11.9L3.7002 10V9.60003L5.6002 7.70003C5.8002 7.50003 6.0002 7.60003 6.0002 7.80003V9.30003C7.9002 9.30003 9.5002 7.70003 9.5002 5.80003C9.5002 5.10003 9.3002 4.40003 8.9002 3.80003Z" fill="context-fill"/> +<path d="M3.1 8.19998C3.3 8.39998 3.2 8.69998 3 8.89998C2.8 8.99998 2.4 8.99998 2.3 8.69998C1.8 7.99998 1.5 7.09998 1.5 6.19998C1.5 3.69998 3.5 1.69998 6 1.69998V0.199984C6 -1.62125e-05 6.2 -0.100016 6.3 0.0999838L8.3 1.99998V2.39998L6.3 4.39998C6.2 4.49998 6 4.39998 6 4.19998V2.69998C4.1 2.69998 2.5 4.29998 2.5 6.19998C2.5 6.89998 2.7 7.59998 3.1 8.19998Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torcircuit/content/torCircuitPanel.css b/browser/components/torcircuit/content/torCircuitPanel.css new file mode 100644 index 0000000000000000000000000000000000000000..c0acffd8165929f63ec58ddfa2dda8bfc62e857f --- /dev/null +++ b/browser/components/torcircuit/content/torCircuitPanel.css @@ -0,0 +1,187 @@ +/* Toolbar button */ + +#tor-circuit-button-icon { + width: 16px; + height: 16px; + /* We want to set flat fill if we have prefers-contrast. Otherwise, we want a + * gradient fill depending on the dark mode. + * context-fill is insufficient for a linear gradient, so we instead use the + * image as a mask and set the <xul:image> background color to the fill we + * want. */ + mask-image: url("chrome://browser/content/tor-circuit-icon-mask.svg"); + mask-origin: content-box; + mask-size: cover; + mask-position: center; + mask-repeat: no-repeat; + /* High-Contrast fill. */ + background: currentColor; +} + +@media not ((prefers-contrast) or (forced-colors)) { + #tor-circuit-button-icon { + background: linear-gradient(315deg, #008799 0%, #6153C6 50%, #CA00CC 100%); + } + + @media (prefers-color-scheme: dark) { + #tor-circuit-button-icon { + background: linear-gradient(315deg, #4CEAFF 0%, #808FFF 50%, #FD66FF 100%); + } + } +} + +/* Panel */ + +#tor-circuit-alias, +#tor-circuit-node-list-name, +.tor-circuit-addresses, +.tor-circuit-button-description { + color: var(--text-color-deemphasized); +} + +#tor-circuit-panel .panel-header { + /* .panel-header already inherits these same rules from panelUI-shared.css and + * xul.css. But .panel-header is normally "flex-direction: row", but we are + * using a vbox (i.e flex-direction: column) so that the heading is placed + * vertically above the #tor-circuit-alias when it is shown. We want to + * ensure the layout rules we need for our different case so we are less + * vulnerable to changes in panelUI-shared.css. */ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; +} + +.panel-header > h1#tor-circuit-heading { + /* Overwrite rule from panelUI-shared.css which gives this "flex: auto". + * Otherwise the heading will be stretched vertically and not be + * center-aligned. */ + flex: 0 0 auto; +} + +#tor-circuit-alias:not([hidden]) { + /* Same as padding for .panel-header */ + margin-block-start: var(--arrowpanel-menuitem-margin-inline); + display: flex; + align-items: center; +} + +#tor-circuit-alias img { + -moz-context-properties: fill; + fill: currentColor; + width: 14px; + height: 14px; + flex: 0 0 auto; + margin-inline-end: 0.25em; +} + +#tor-circuit-alias-label { + margin: 0; + white-space: nowrap; +} + +#tor-circuit-panel-body { + /* May grow larger than 480px if we have a long domain name or ip address. */ + min-width: 480px; + /* Line up with the button at the bottom of the panel. */ + margin: var(--arrowpanel-menuitem-margin); + padding: var(--arrowpanel-menuitem-padding); + gap: var(--arrowpanel-menuitem-padding-block); +} + +#tor-circuit-node-list-name, +#tor-circuit-node-list { + margin: 0; +} + +#tor-circuit-node-list { + list-style: none; + padding-inline-start: var(--arrowpanel-menuitem-margin-inline); + /* Do not allow an item to wrap since this would break the circuit diagram. */ + white-space: nowrap; +} + +.tor-circuit-node-item { + /* We want the "bullets" of the list to act as the circuit diagram, and we + * also want them to be vertically aligned and scaled to the height of the + * list item so that the different parts visually connect. + * Using list-style-image does not give us enough control over sizing the + * image. So instead we use a background-image. */ + padding-inline-start: 1.5em; + padding-block: 6px; + background-image: url("chrome://browser/content/tor-circuit-node-middle.svg"); + -moz-context-properties: fill; + /* Light Gray 50 */ + fill: rgb(191, 191, 201); + background-position-x: right; + background-position-y: center; + /* Bump the size by small amount to prevent rendering gaps. + * We're assuming here that each line will have the same height so that each + * image has the same size. */ + background-size: auto calc(100% + 0.5px); + background-repeat: no-repeat; +} + +.tor-circuit-node-item:not([hidden]) { + display: flex; + align-items: baseline; +} + +.tor-circuit-node-item > * { + flex: 0 0 auto; +} + +@media (prefers-color-scheme: dark) { + .tor-circuit-node-item { + /* Light Gray 90 */ + fill: rgb(128, 128, 142); + } +} + +.tor-circuit-node-item:dir(ltr) { + background-position-x: left; +} + +.tor-circuit-node-item#tor-circuit-start-item { + background-image: url("chrome://browser/content/tor-circuit-node-start.svg"); +} + +.tor-circuit-node-item#tor-circuit-end-item { + background-image: url("chrome://browser/content/tor-circuit-node-end.svg"); +} + +.tor-circuit-node-item#tor-circuit-relays-item { + background-image: url("chrome://browser/content/tor-circuit-node-relays.svg"); +} + +.tor-circuit-region-flag { + margin-inline-end: 0.5em; + height: 16px; + align-self: center; + /* Don't occupy any vertical height. */ + margin-block: -8px; +} + +.tor-circuit-region-flag.no-region-flag-src { + display: none; +} + +.tor-circuit-addresses { + font-size: 0.9em; + font-family: monospace; + margin-inline-start: 0.75em; +} + +.tor-circuit-ip-address { + /* Override the rule for <code>, which is -moz-fixed. */ + font-family: inherit; +} + +/* Footer buttons */ +.tor-circuit-button label { + margin: 0; +} + +.tor-circuit-button .tor-circuit-button-description { + margin-block-start: var(--space-xsmall); +} diff --git a/browser/components/torcircuit/content/torCircuitPanel.inc.xhtml b/browser/components/torcircuit/content/torCircuitPanel.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..23424670bd7b2ad8a4aad1e0f1284a03301b0cc1 --- /dev/null +++ b/browser/components/torcircuit/content/torCircuitPanel.inc.xhtml @@ -0,0 +1,99 @@ +<panel id="tor-circuit-panel" + role="dialog" + aria-labelledby="tor-circuit-heading" + type="arrow" + orient="vertical" + class="cui-widget-panel panel-no-padding"> + <!-- Use same semantic structure as #identity-popup and #protections-popup + - with a role="alertdialog" wrapping a role="document", except we use a + - "dialog" rather than an "alertdialog". + - Moreover, since this "dialog" may just be for reading, we also make the + - "document" part of the focus cycle and receive the initial focus, rather + - than finding the first focusable target within. + - We do not set "aria-describedby" for this "dialog" because the content + - is complex, so a flat string would not make sense. --> + <!-- NOTE: Currently Orca fails to read the content of this panel, so the + - circuit details are not accessible. This effects mozilla-central as well. + - See bugzilla bug 1820765 and bugzilla bug 1926374. + - The focusable elements are still operable though. --> + <vbox id="tor-circuit-panel-document" role="document" tabindex="0"> + <vbox class="panel-header"> + <html:h1 id="tor-circuit-heading"></html:h1> + <html:div id="tor-circuit-alias" hidden="hidden"> + <html:img + src="chrome://browser/content/tor-circuit-redirect.svg" + alt="" + /> + <html:p id="tor-circuit-alias-label"> + <html:a class="tor-circuit-alias-link" data-l10n-name="alias-link" /> + </html:p> + </html:div> + </vbox> + <toolbarseparator/> + <vbox id="tor-circuit-panel-body" class="panel-subview-body"> + <html:p + id="tor-circuit-node-list-name" + data-l10n-id="tor-circuit-panel-node-list-introduction" + ></html:p> + <html:ol id="tor-circuit-node-list"> + <html:li + id="tor-circuit-start-item" + class="tor-circuit-node-item" + data-l10n-id="tor-circuit-panel-node-browser" + ></html:li> + <html:li + id="tor-circuit-relays-item" + class="tor-circuit-node-item tor-circuit-relays-item" + data-l10n-id="tor-circuit-panel-node-onion-relays" + ></html:li> + <html:li + id="tor-circuit-end-item" + class="tor-circuit-node-item" + ></html:li> + </html:ol> + <html:template id="tor-circuit-node-item-template"> + <html:li class="tor-circuit-node-item"> + <html:img class="tor-circuit-region-flag" alt="" /> + <html:span class="tor-circuit-node-name"></html:span> + <html:span class="tor-circuit-addresses"></html:span> + </html:li> + </html:template> + </vbox> + <toolbarseparator/> + <!-- NOTE: To fully benefit from the .subviewbutton styling, we need to use + - a xul:toolbarbutton rather than a html:button. + - By default, a xul:toolbarbutton is not focusable so we need to add + - tabindex. --> + <toolbarbutton + id="tor-circuit-new-circuit" + class="subviewbutton panel-subview-footer-button tor-circuit-button" + tabindex="0" + aria-labelledby="tor-circuit-new-circuit-label" + aria-describedby="tor-circuit-new-circuit-description" + > + <vbox align="start"> + <label + id="tor-circuit-new-circuit-label" + class="toolbarbutton-text" + data-l10n-id="tor-circuit-panel-new-button" + /> + <!-- NOTE: Use html:span rather than xul:label. Otherwise Orca will + - treat this as a label for the dialog. --> + <html:span + id="tor-circuit-new-circuit-description" + class="tor-circuit-button-description" + ></html:span> + </vbox> + </toolbarbutton> + </vbox> +</panel> +<menupopup id="tor-circuit-panel-alias-menu"> + <!-- Copied from browser/base/content/browser-context.inc --> + <menuitem id="tor-circuit-panel-alias-menu-new-tab" + data-l10n-id="main-context-menu-open-link-new-tab"/> + <menuitem id="tor-circuit-panel-alias-menu-new-window" + data-l10n-id="main-context-menu-open-link-new-private-window"/> + <menuseparator/> + <menuitem id="tor-circuit-panel-alias-menu-copy" + data-l10n-id="main-context-menu-copy-link-simple"/> +</menupopup> diff --git a/browser/components/torcircuit/content/torCircuitPanel.js b/browser/components/torcircuit/content/torCircuitPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..112192536507021e512b8c302593c836b8356c4a --- /dev/null +++ b/browser/components/torcircuit/content/torCircuitPanel.js @@ -0,0 +1,695 @@ +/* eslint-env mozilla/browser-window */ + +/** + * Data about the current domain and circuit for a xul:browser. + * + * @typedef BrowserCircuitData + * @property {string?} domain - The first party domain. + * @property {string?} scheme - The scheme. + * @property {NodeData[]} nodes - The circuit in use for the browser. + */ + +var gTorCircuitPanel = { + /** + * The panel node. + * + * @type {MozPanel} + */ + panel: null, + /** + * The toolbar button that opens the panel. + * + * @type {Element} + */ + toolbarButton: null, + /** + * The data for the currently shown browser. + * + * @type {BrowserCircuitData?} + */ + _currentBrowserData: null, + /** + * Whether the panel has been initialized and has not yet been uninitialized. + * + * @type {bool} + */ + _isActive: false, + /** + * The template element for circuit nodes. + * + * @type {HTMLTemplateElement?} + */ + _nodeItemTemplate: null, + + /** + * The topic on which circuit changes are broadcast. + * + * @type {string} + */ + TOR_CIRCUIT_TOPIC: "TorCircuitChange", + + /** + * Initialize the panel. + */ + init() { + this._isActive = true; + + this._log = console.createInstance({ + prefix: "TorCircuitPanel", + maxLogLevelPref: "browser.torcircuitpanel.loglevel", + }); + + this.panel = document.getElementById("tor-circuit-panel"); + this._panelElements = { + doc: document.getElementById("tor-circuit-panel-document"), + heading: document.getElementById("tor-circuit-heading"), + alias: document.getElementById("tor-circuit-alias"), + aliasLabel: document.getElementById("tor-circuit-alias-label"), + aliasMenu: document.getElementById("tor-circuit-panel-alias-menu"), + list: document.getElementById("tor-circuit-node-list"), + relaysItem: document.getElementById("tor-circuit-relays-item"), + endItem: document.getElementById("tor-circuit-end-item"), + newCircuitDescription: document.getElementById( + "tor-circuit-new-circuit-description" + ), + }; + this.toolbarButton = document.getElementById("tor-circuit-button"); + + // We add listeners for the .tor-circuit-alias-link. + // NOTE: We have to add the listeners to the parent element because the + // link (with data-l10n-name="alias-link") will be replaced with a new + // cloned instance every time the parent gets re-translated. + this._panelElements.aliasLabel.addEventListener("click", event => { + if (!this._aliasLink.contains(event.target)) { + return; + } + event.preventDefault(); + if (event.button !== 0) { + return; + } + this._openAlias("tab"); + }); + this._panelElements.aliasLabel.addEventListener("contextmenu", event => { + if (!this._aliasLink.contains(event.target)) { + return; + } + event.preventDefault(); + this._panelElements.aliasMenu.openPopupAtScreen( + event.screenX, + event.screenY, + true + ); + }); + + // Commands similar to nsContextMenu.js + document + .getElementById("tor-circuit-panel-alias-menu-new-tab") + .addEventListener("command", () => { + this._openAlias("tab"); + }); + document + .getElementById("tor-circuit-panel-alias-menu-new-window") + .addEventListener("command", () => { + this._openAlias("window"); + }); + document + .getElementById("tor-circuit-panel-alias-menu-copy") + .addEventListener("command", () => { + const alias = this._aliasLink?.href; + if (!alias) { + return; + } + Cc["@mozilla.org/widget/clipboardhelper;1"] + .getService(Ci.nsIClipboardHelper) + .copyString(alias); + }); + + // Button is a xul:toolbarbutton, so we use "command" rather than "click". + document + .getElementById("tor-circuit-new-circuit") + .addEventListener("command", () => { + TorDomainIsolator.newCircuitForBrowser(gBrowser.selectedBrowser); + }); + + // Update the display just before opening. + this.panel.addEventListener("popupshowing", event => { + if (event.target !== this.panel) { + return; + } + this._updateCircuitPanel(); + }); + + // Set the initial focus to the panel document itself, which has been made a + // focusable target. Similar to webextension-popup-browser. + // Switching to a document should prompt screen readers to enter "browse + // mode" and allow the user to navigate the dialog content. + // NOTE: We could set the focus to the first focusable child within the + // document, but this would usually be the "New circuit" button, which would + // skip over the rest of the document content. + this.panel.addEventListener("popupshown", event => { + if (event.target !== this.panel) { + return; + } + this._panelElements.doc.focus(); + }); + + // this.toolbarButton follows "identity-button" markup, so is a <xul:box> + // rather than a <html:button>, or <xul:toolbarbutton>, so we need to set up + // listeners for both "click" and "keydown", and not for "command". + this.toolbarButton.addEventListener("keydown", event => { + if (event.key !== "Enter" && event.key !== " ") { + return; + } + event.stopPropagation(); + this.show(); + }); + this.toolbarButton.addEventListener("click", event => { + event.stopPropagation(); + if (event.button !== 0) { + return; + } + this.show(); + }); + + this._nodeItemTemplate = document.getElementById( + "tor-circuit-node-item-template" + ); + // Prepare the unknown region name for the current locale. + // NOTE: We expect this to complete before the first call to _updateBody. + this._localeChanged(); + + this._locationListener = { + onLocationChange: (webProgress, request, locationURI, flags) => { + if ( + webProgress.isTopLevel && + !(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) + ) { + // We have switched tabs or finished loading a new page, this can hide + // the toolbar button if the new page has no circuit. + this._updateCurrentBrowser(); + } + }, + }; + // Notified of new locations for the currently selected browser (tab) *and* + // switching selected browser. + gBrowser.addProgressListener(this._locationListener); + + // Get notifications for circuit changes. + Services.obs.addObserver(this, this.TOR_CIRCUIT_TOPIC); + Services.obs.addObserver(this, "intl:app-locales-changed"); + }, + + /** + * Uninitialize the panel. + */ + uninit() { + this._isActive = false; + gBrowser.removeProgressListener(this._locationListener); + Services.obs.removeObserver(this, this.TOR_CIRCUIT_TOPIC); + Services.obs.removeObserver(this, "intl:app-locales-changed"); + }, + + /** + * Observe circuit changes. + * + * @param {nsISupports} subject Notification-specific data + * @param {string} topic The notification topic + */ + observe(subject, topic) { + switch (topic) { + case this.TOR_CIRCUIT_TOPIC: + // TODO: Maybe check if we actually need to do something earlier. + this._updateCurrentBrowser(); + break; + case "intl:app-locales-changed": + this._localeChanged(); + break; + } + }, + + /** + * Show the circuit panel. + * + * This should only be called if the toolbar button is visible. + */ + show() { + this.panel.openPopup(this.toolbarButton, "bottomleft topleft", 0, 0); + }, + + /** + * Hide the circuit panel. + */ + hide() { + this.panel.hidePopup(); + }, + + /** + * Get the current alias link instance. + * + * Note that this element instance may change whenever its parent element + * (#tor-circuit-alias-label) is re-translated. Attributes should be copied to + * the new instance. + * + * @returns {Element?} + */ + get _aliasLink() { + return this._panelElements.aliasLabel.querySelector( + ".tor-circuit-alias-link" + ); + }, + + /** + * Open the onion alias present in the alias link. + * + * @param {"window"|"tab"} where - Whether to open in a new tab or a new + * window. + */ + _openAlias(where) { + const url = this._aliasLink?.href; + if (!url) { + return; + } + // We hide the panel before opening the link. + this.hide(); + window.openWebLinkIn(url, where); + }, + + /** + * A list of schemes to never show the circuit display for. + * + * NOTE: Some of these pages may still have remote content within them, so + * will still use tor circuits. But it doesn't make much sense to show the + * circuit for the page itself. + * + * @type {string[]} + */ + // FIXME: Check if we find a UX to handle some of these cases, and if we + // manage to solve some technical issues. + // See tor-browser#41700 and tor-browser!699. + _ignoredSchemes: ["about", "file", "chrome", "resource"], + + /** + * Update the current circuit and domain data for the currently selected + * browser, possibly changing the UI. + */ + _updateCurrentBrowser() { + const browser = gBrowser.selectedBrowser; + const domain = TorDomainIsolator.getDomainForBrowser(browser); + const nodes = TorDomainIsolator.getCircuit( + browser, + domain, + browser.contentPrincipal.originAttributes.userContextId + ); + // We choose the currentURI, which matches what is shown in the URL bar and + // will match up with the domain. + // In contrast, documentURI corresponds to the shown page. E.g. it could + // point to "about:certerror". + let scheme = browser.currentURI?.scheme; + if (scheme === "about" && browser.currentURI?.filePath === "reader") { + const searchParams = new URLSearchParams(browser.currentURI.query); + if (searchParams.has("url")) { + try { + const uri = Services.io.newURI(searchParams.get("url")); + scheme = uri.scheme; + } catch (err) { + this._log.error(err); + } + } + } + + if ( + this._currentBrowserData && + this._currentBrowserData.domain === domain && + this._currentBrowserData.scheme === scheme && + this._currentBrowserData.nodes.length === nodes.length && + // The fingerprints of the nodes match. + nodes.every( + (n, index) => + n.fingerprint === this._currentBrowserData.nodes[index].fingerprint + ) + ) { + // No change. + this._log.debug( + "Skipping browser update because the data is already up to date." + ); + return; + } + + this._currentBrowserData = { domain, scheme, nodes }; + this._log.debug("Updating current browser.", this._currentBrowserData); + + if ( + // Schemes where we always want to hide the display. + this._ignoredSchemes.includes(scheme) || + // Can't show the display without a domain. Don't really expect this + // outside of "about" pages. + !domain || + // As a fall back, we do not show the circuit for new pages which have no + // circuit nodes (yet). + // FIXME: Have a back end that handles this instead, and can tell us + // whether the circuit is being established, even if the path details are + // unknown right now. See tor-browser#41700. + !nodes.length + ) { + // Only show the Tor circuit if we have credentials and node data. + this._log.debug("No circuit found for current document."); + // Make sure we close the popup. + if ( + this.panel.contains(document.activeElement) || + this.toolbarButton.contains(document.activeElement) + ) { + // Focus is about to be lost. + // E.g. navigating back to a page without a circuit with Alt+ArrowLeft + // whilst the popup is open, or focus on the toolbar button. + // By default when the panel closes after being opened with a keyboard, + // focus will move back to the toolbar button. But we are about to hide + // the toolbar button, and ToolbarKeyboardNavigator does not currently + // handle re-assigning focus when the current item is hidden or removed. + // See bugzilla bug 1823664. + // Without editing ToolbarKeyboardNavigator, it is difficult to + // re-assign focus to the next focusable item, so as a compromise we + // focus the URL bar, which is close by. + gURLBar.focus(); + } + this.hide(); + this.toolbarButton.hidden = true; + return; + } + + this.toolbarButton.hidden = false; + + this._updateCircuitPanel(); + }, + + /** + * Get the tor onion address alias for the given domain. + * + * @param {string} domain An .onion domain to query an alias for. + * @returns {string} The alias domain, or null if it has no alias. + */ + _getOnionAlias(domain) { + let alias = null; + try { + const service = Cc["@torproject.org/onion-alias-service;1"].getService( + Ci.IOnionAliasService + ); + alias = service.getOnionAlias(domain); + } catch (e) { + this._log.error( + `Cannot verify if we are visiting an onion alias: ${e.message}` + ); + return null; + } + if (alias === domain) { + return null; + } + return alias; + }, + + /** + * Updates the circuit display in the panel to show the current browser data. + */ + _updateCircuitPanel() { + if (this.panel.state !== "open" && this.panel.state !== "showing") { + // Don't update the panel content if it is not open or about to open. + return; + } + + // NOTE: The _currentBrowserData.nodes data may be stale. In particular, the + // circuit may have expired already, or we're still waiting on the new + // circuit. + if ( + !this._currentBrowserData?.domain || + !this._currentBrowserData?.nodes.length + ) { + // Unexpected since the toolbar button should be hidden in this case. + this._log.warn( + "Hiding panel since we have no domain, or no circuit data." + ); + this.hide(); + return; + } + + this._log.debug("Updating circuit panel"); + + let domain = this._currentBrowserData.domain; + const onionAlias = this._getOnionAlias(domain); + + this._updateHeading(domain, onionAlias, this._currentBrowserData.scheme); + + if (onionAlias) { + // Show the circuit ending with the alias instead. + domain = onionAlias; + } + this._updateBody(this._currentBrowserData.nodes, domain); + }, + + /** + * Update the display of the heading to show the given domain. + * + * @param {string} domain - The domain to show. + * @param {string?} onionAlias - The onion alias address for this domain, if + * it has one. + * @param {string?} scheme - The scheme in use for the current domain. + */ + _updateHeading(domain, onionAlias, scheme) { + document.l10n.setAttributes( + this._panelElements.heading, + "tor-circuit-panel-heading", + // Only shorten the onion domain if it has no alias. + { host: TorUIUtils.shortenOnionAddress(domain) } + ); + + if (onionAlias) { + if (scheme === "http" || scheme === "https") { + // We assume the same scheme as the current page for the alias, which we + // expect to be either http or https. + // NOTE: The href property is partially presentational so that the link + // location appears on hover. + // NOTE: The href attribute should be copied to any new instances of + // .tor-circuit-alias-link (with data-l10n-name="alias-link") when the + // parent _panelElements.aliasLabel gets re-translated. + this._aliasLink.href = `${scheme}://${onionAlias}`; + } else { + this._aliasLink.removeAttribute("href"); + } + document.l10n.setAttributes( + this._panelElements.aliasLabel, + "tor-circuit-panel-alias", + { alias: TorUIUtils.shortenOnionAddress(onionAlias) } + ); + this._showPanelElement(this._panelElements.alias, true); + } else { + this._showPanelElement(this._panelElements.alias, false); + } + }, + + /** + * The currently shown circuit node items. + * + * @type {HTMLLIElement[]} + */ + _nodeItems: [], + + /** + * Update the display of the circuit body. + * + * @param {NodeData[]} nodes - The non-empty circuit nodes to show. + * @param {string} domain - The domain to show for the last node. + */ + _updateBody(nodes, domain) { + // NOTE: Rather than re-creating the <li> nodes from scratch, we prefer + // updating existing <li> nodes so that the display does not "flicker" in + // width as we wait for Fluent DOM to fill the nodes with text content. I.e. + // the existing node and text will remain in place, occupying the same + // width, up until it is replaced by Fluent DOM. + for (let index = 0; index < nodes.length; index++) { + if (index >= this._nodeItems.length) { + const newItem = + this._nodeItemTemplate.content.children[0].cloneNode(true); + const flagEl = newItem.querySelector(".tor-circuit-region-flag"); + // Hide region flag whenever the flag src does not exist. + flagEl.addEventListener("error", () => { + flagEl.classList.add("no-region-flag-src"); + flagEl.removeAttribute("src"); + }); + this._panelElements.list.insertBefore( + newItem, + this._panelElements.relaysItem + ); + + this._nodeItems.push(newItem); + } + this._updateCircuitNodeItem( + this._nodeItems[index], + nodes[index], + index === 0 + ); + } + + // Remove excess items. + // NOTE: We do not expect focus within a removed node. + while (nodes.length < this._nodeItems.length) { + this._nodeItems.pop().remove(); + } + + this._showPanelElement( + this._panelElements.relaysItem, + domain.endsWith(".onion") + ); + + // Set the address that we want to copy. + this._panelElements.endItem.textContent = + TorUIUtils.shortenOnionAddress(domain); + + // Button description text, depending on whether our first node was a + // bridge, or otherwise a guard. + document.l10n.setAttributes( + this._panelElements.newCircuitDescription, + nodes[0].bridgeType === null + ? "tor-circuit-panel-new-button-description-guard" + : "tor-circuit-panel-new-button-description-bridge" + ); + }, + + /** + * Update a node item for the given circuit node data. + * + * @param {Element} nodeItem - The item to update. + * @param {NodeData} node - The circuit node data to create an item for. + * @param {bool} isCircuitStart - Whether this is the first node in the + * circuit. + */ + _updateCircuitNodeItem(nodeItem, node, isCircuitStart) { + const nameEl = nodeItem.querySelector(".tor-circuit-node-name"); + let flagSrc = null; + + if (node.bridgeType === null) { + const regionCode = node.regionCode; + flagSrc = this._regionFlagSrc(regionCode); + + const regionName = regionCode + ? Services.intl.getRegionDisplayNames(undefined, [regionCode])[0] + : this._unknownRegionName; + + if (isCircuitStart) { + document.l10n.setAttributes( + nameEl, + "tor-circuit-panel-node-region-guard", + { region: regionName } + ); + } else { + // Set the text content directly, rather than using Fluent. + nameEl.removeAttribute("data-l10n-id"); + nameEl.removeAttribute("data-l10n-args"); + nameEl.textContent = regionName; + } + } else { + // Do not show a flag for bridges. + + let bridgeType = node.bridgeType; + if (bridgeType === "meek_lite") { + bridgeType = "meek"; + } else if (bridgeType === "vanilla") { + bridgeType = ""; + } + if (bridgeType) { + document.l10n.setAttributes( + nameEl, + "tor-circuit-panel-node-typed-bridge", + { "bridge-type": bridgeType } + ); + } else { + document.l10n.setAttributes(nameEl, "tor-circuit-panel-node-bridge"); + } + } + const flagEl = nodeItem.querySelector(".tor-circuit-region-flag"); + flagEl.classList.toggle("no-region-flag-src", !flagSrc); + if (flagSrc) { + flagEl.setAttribute("src", flagSrc); + } else { + flagEl.removeAttribute("src"); + } + + const addressesEl = nodeItem.querySelector(".tor-circuit-addresses"); + // Empty children. + addressesEl.replaceChildren(); + let firstAddr = true; + for (const ip of node.ipAddrs) { + if (firstAddr) { + firstAddr = false; + } else { + addressesEl.append(", "); + } + // Use semantic <code> block for the ip addresses, so the content + // (especially punctuation) can be better interpreted by screen readers, + // if they support this. + const ipEl = document.createElement("code"); + ipEl.classList.add("tor-circuit-ip-address"); + ipEl.textContent = ip; + addressesEl.append(ipEl); + } + }, + + /** + * The string to use for unknown region names. + * + * Will be updated to match the current locale. + * + * @type {string} + */ + _unknownRegionName: "Unknown region", + + /** + * Update the name for regions to match the current locale. + */ + _localeChanged() { + document.l10n + .formatValue("tor-circuit-panel-node-unknown-region") + .then(name => { + this._unknownRegionName = name; + // Update the panel for the new region names, if it is shown. + this._updateCircuitPanel(); + }); + }, + + /** + * Convert a region code into an emoji flag sequence. + * + * @param {string?} regionCode - The code to convert. It should be an upper + * case 2-letter BCP47 Region subtag to be converted into a flag. + * + * @returns {src?} The emoji flag img src, or null if there is no flag. + */ + _regionFlagSrc(regionCode) { + if (!regionCode?.match(/^[A-Z]{2}$/)) { + return null; + } + // Convert the regionCode into an emoji flag sequence. + const regionalIndicatorA = 0x1f1e6; + const flagName = [ + regionalIndicatorA + (regionCode.codePointAt(0) - 65), + regionalIndicatorA + (regionCode.codePointAt(1) - 65), + ] + .map(cp => cp.toString(16)) + .join("-"); + + return `chrome://browser/content/tor-circuit-flags/${flagName}.svg`; + }, + + /** + * Show or hide an element. + * + * Handles moving focus if it is contained within the element. + * + * @param {Element} element - The element to show or hide. + * @param {bool} show - Whether to show the element. + */ + _showPanelElement(element, show) { + if (!show && element.contains(document.activeElement)) { + // Move focus to the panel, otherwise it will be lost to the top-level. + this.panel.focus(); + } + element.hidden = !show; + }, +}; diff --git a/browser/components/torcircuit/jar.mn b/browser/components/torcircuit/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..0c343971b838c1b68443a883639a9e75bc31365e --- /dev/null +++ b/browser/components/torcircuit/jar.mn @@ -0,0 +1,10 @@ +browser.jar: + content/browser/torCircuitPanel.js (content/torCircuitPanel.js) + content/browser/torCircuitPanel.css (content/torCircuitPanel.css) + content/browser/tor-circuit-icon-mask.svg (content/tor-circuit-icon-mask.svg) + content/browser/tor-circuit-redirect.svg (content/tor-circuit-redirect.svg) + content/browser/tor-circuit-node-start.svg (content/tor-circuit-node-start.svg) + content/browser/tor-circuit-node-middle.svg (content/tor-circuit-node-middle.svg) + content/browser/tor-circuit-node-end.svg (content/tor-circuit-node-end.svg) + content/browser/tor-circuit-node-relays.svg (content/tor-circuit-node-relays.svg) + content/browser/tor-circuit-flags/ (content/tor-circuit-flags/*) diff --git a/browser/components/torcircuit/moz.build b/browser/components/torcircuit/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..2661ad7cb9f3df2b3953a6e1e999aee82d29be78 --- /dev/null +++ b/browser/components/torcircuit/moz.build @@ -0,0 +1 @@ +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/components/torpreferences/content/bridge-bot.svg b/browser/components/torpreferences/content/bridge-bot.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab584f3639858fb799bba2743830db6b0520a0ad --- /dev/null +++ b/browser/components/torpreferences/content/bridge-bot.svg @@ -0,0 +1,13 @@ +<svg width="40" height="44" viewBox="0 0 40 44" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M37.1877 22.7584C38.7409 25.1504 38.9178 27.7923 37.5828 28.6591C36.2478 29.5259 33.9065 28.2895 32.3533 25.8975C30.8001 23.5055 30.6232 20.8637 31.9582 19.9969C33.2932 19.13 35.6345 20.3664 37.1877 22.7584Z" fill="#C069FF"/> +<path d="M2.81234 22.7584C1.25915 25.1504 1.08224 27.7923 2.41721 28.6591C3.75217 29.5259 6.09349 28.2895 7.64668 25.8975C9.19987 23.5055 9.37678 20.8637 8.04181 19.9969C6.70685 19.13 4.36553 20.3664 2.81234 22.7584Z" fill="#C069FF"/> +<path d="M32.2002 19.4754C33.9149 19.4754 35.3181 20.8678 35.1823 22.5772C34.7579 27.9186 33.2458 32.9181 30.8541 36.7668C28.0043 41.3527 24.1391 43.9291 20.1088 43.9291C16.0785 43.9291 12.2133 41.3527 9.36344 36.7668C6.97177 32.9181 5.45965 27.9186 5.03525 22.5772C4.89944 20.8678 6.30265 19.4754 8.0174 19.4754L32.2002 19.4754Z" fill="#C069FF"/> +<path d="M28.4375 32.1121C28.4375 27.4522 24.6599 23.6746 20 23.6746C15.3401 23.6746 11.5625 27.4522 11.5625 32.1121V33.5139H12.8809V32.1121C12.8809 28.1803 16.0682 24.9929 20 24.9929C23.9318 24.9929 27.1191 28.1803 27.1191 32.1121V33.5139H28.4375V32.1121Z" fill="#15141A"/> +<path d="M25.9062 32.1121C25.9062 28.8501 23.2619 26.2058 20 26.2058C16.7381 26.2058 14.0937 28.8501 14.0937 32.1121L14.0936 33.5139H15.412L15.4121 32.1121C15.4121 29.5782 17.4662 27.5242 20 27.5242C22.5338 27.5242 24.5879 29.5782 24.5879 32.1121L24.588 33.5139H25.9064L25.9062 32.1121Z" fill="#15141A"/> +<path d="M20 28.7371C21.864 28.7371 23.375 30.2481 23.375 32.1121L23.3753 33.5139H22.0569L22.0566 32.1121C22.0566 30.9762 21.1359 30.0554 20 30.0554C18.8642 30.0554 17.9434 30.9762 17.9434 32.1121L17.9431 33.5139H16.6247V32.1121C16.6247 30.2481 18.136 28.7371 20 28.7371Z" fill="#15141A"/> +<path d="M8.9145 17.8162C7.19975 17.8162 5.78665 16.4193 6.02668 14.7215C6.53221 11.1456 7.9061 7.82078 9.99195 5.21826C12.6698 1.87706 16.3018 -1.07451e-07 20.0889 0C23.8759 1.07451e-07 27.5079 1.87706 30.1858 5.21826C32.2716 7.82078 33.6455 11.1456 34.151 14.7215C34.3911 16.4193 32.978 17.8162 31.2632 17.8162H8.9145Z" fill="#C069FF"/> +<path d="M13.1064 15.1091C11.3916 15.1091 9.96814 13.7048 10.3139 12.0252C10.7578 9.86855 11.6634 7.87853 12.956 6.27814C14.8477 3.93602 17.4134 2.62024 20.0887 2.62024C22.7639 2.62024 25.3296 3.93602 27.2213 6.27814C28.514 7.87853 29.4195 9.86855 29.8635 12.0252C30.2092 13.7048 28.7857 15.1091 27.071 15.1091H13.1064Z" fill="#EBD0FF"/> +<path d="M17.5125 6.81215C17.5125 7.58388 16.9065 8.2095 16.1589 8.2095C15.4112 8.2095 14.8052 7.58388 14.8052 6.81215C14.8052 6.04041 15.4112 5.41479 16.1589 5.41479C16.9065 5.41479 17.5125 6.04041 17.5125 6.81215Z" fill="#15141A"/> +<path d="M25.1981 6.81215C25.1981 7.58388 24.592 8.2095 23.8444 8.2095C23.0968 8.2095 22.4907 7.58388 22.4907 6.81215C22.4907 6.04041 23.0968 5.41479 23.8444 5.41479C24.592 5.41479 25.1981 6.04041 25.1981 6.81215Z" fill="#15141A"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M22.4395 9.01993L22.4044 9.11353C21.5971 11.2673 18.526 11.1951 17.8208 9.0058L18.427 8.81052C18.9472 10.4254 21.2125 10.4787 21.808 8.88998L21.8431 8.79639L22.4395 9.01993Z" fill="#15141A"/> +</svg> diff --git a/browser/components/torpreferences/content/bridge-qr.svg b/browser/components/torpreferences/content/bridge-qr.svg new file mode 100644 index 0000000000000000000000000000000000000000..e25fefc75a088821fbe488d78916bd55bee89090 --- /dev/null +++ b/browser/components/torpreferences/content/bridge-qr.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="context-fill" xmlns="http://www.w3.org/2000/svg"> + <path d="M5.5 3C4.83696 3 4.20107 3.26339 3.73223 3.73223C3.26339 4.20107 3 4.83696 3 5.5V9H4.75V5.5C4.75 5.30109 4.82902 5.11032 4.96967 4.96967C5.11032 4.82902 5.30109 4.75 5.5 4.75H9V3H5.5ZM11 10.25C11 10.4489 10.921 10.6397 10.7803 10.7803C10.6397 10.921 10.4489 11 10.25 11H7.75C7.55109 11 7.36032 10.921 7.21967 10.7803C7.07902 10.6397 7 10.4489 7 10.25V7.75C7 7.55109 7.07902 7.36032 7.21967 7.21967C7.36032 7.07902 7.55109 7 7.75 7H10.25C10.4489 7 10.6397 7.07902 10.7803 7.21967C10.921 7.36032 11 7.55109 11 7.75V10.25ZM17 15H15V13H17V11H15V9H17V7H15V9H13V11H15V13H13V15H11V13H9V15H7V17H9V15H11V17H13V15H15V17H17V15ZM3 18.5V15H4.75V18.5C4.75 18.914 5.086 19.25 5.5 19.25H9V21H5.5C4.83696 21 4.20107 20.7366 3.73223 20.2678C3.26339 19.7989 3 19.163 3 18.5ZM15 3H18.5C19.163 3 19.7989 3.26339 20.2678 3.73223C20.7366 4.20107 21 4.83696 21 5.5V9H19.25V5.5C19.25 5.30109 19.171 5.11032 19.0303 4.96967C18.8897 4.82902 18.6989 4.75 18.5 4.75H15V3ZM21 18.5V15H19.25V18.5C19.25 18.6989 19.171 18.8897 19.0303 19.0303C18.8897 19.171 18.6989 19.25 18.5 19.25H15V21H18.5C19.163 21 19.7989 20.7366 20.2678 20.2678C20.7366 19.7989 21 19.163 21 18.5Z"/> +</svg> diff --git a/browser/components/torpreferences/content/bridge.svg b/browser/components/torpreferences/content/bridge.svg new file mode 100644 index 0000000000000000000000000000000000000000..35519fa63d26a0b76952ab1b4d764793aae85c1f --- /dev/null +++ b/browser/components/torpreferences/content/bridge.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg"> + <path d="M15.5 11.5C15.5 7.35786 12.1421 4 8 4C3.85786 4 0.5 7.35786 0.5 11.5V12.7461H1.67188V11.5C1.67188 8.00507 4.50507 5.17188 8 5.17188C11.4949 5.17188 14.3281 8.00507 14.3281 11.5V12.7461H15.5V11.5Z"/> + <path d="M13.25 11.5C13.25 8.6005 10.8995 6.24999 7.99999 6.24999C5.1005 6.24999 2.74999 8.6005 2.74999 11.5L2.74989 12.7461H3.92177L3.92187 11.5C3.92187 9.24771 5.74771 7.42187 7.99999 7.42187C10.2523 7.42187 12.0781 9.24771 12.0781 11.5L12.0782 12.7461H13.2501L13.25 11.5Z"/> + <path d="M8 8.5C9.65686 8.5 11 9.84315 11 11.5L11.0002 12.7461H9.82836L9.82813 11.5C9.82813 10.4904 9.00965 9.67188 8 9.67188C6.99036 9.67188 6.17188 10.4904 6.17188 11.5L6.17164 12.7461H4.99977V11.5C4.99977 9.84315 6.34315 8.5 8 8.5Z"/> +</svg> diff --git a/browser/components/torpreferences/content/bridgeQrDialog.js b/browser/components/torpreferences/content/bridgeQrDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..bb6a84340e59c6ff6dec17bb76b2df68f6f1f9e8 --- /dev/null +++ b/browser/components/torpreferences/content/bridgeQrDialog.js @@ -0,0 +1,29 @@ +"use strict"; + +const { QRCode } = ChromeUtils.importESModule( + "resource://gre/modules/QRCode.sys.mjs" +); + +window.addEventListener( + "DOMContentLoaded", + () => { + const bridgeString = window.arguments[0]; + + const target = document.getElementById("bridgeQr-target"); + const style = window.getComputedStyle(target); + // We are assuming that the style width and height have "px" units. + // Trailing "px" is not parsed. + // NOTE: Our QRCode module doesn't seem to use the width or height + // attributes. + const width = parseInt(style.width, 10); + const height = parseInt(style.height, 10); + new QRCode(target, { + text: bridgeString, + width, + height, + colorDark: style.color, + colorLight: style.backgroundColor, + }); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/bridgeQrDialog.xhtml b/browser/components/torpreferences/content/bridgeQrDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..610e513496c3ebbe6b917051746a6c373ec32e70 --- /dev/null +++ b/browser/components/torpreferences/content/bridgeQrDialog.xhtml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="bridge-qr-dialog-title" +> + <dialog id="bridgeQr-dialog" buttons="accept"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/bridgeQrDialog.js" /> + + <html:div id="bridgeQr"> + <html:div id="bridgeQr-target"></html:div> + <html:div id="bridgeQr-icon"></html:div> + </html:div> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/bridgemoji/BridgeEmoji.js b/browser/components/torpreferences/content/bridgemoji/BridgeEmoji.js new file mode 100644 index 0000000000000000000000000000000000000000..b2479e4488123d483fba66758eb60a7972809eff --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/BridgeEmoji.js @@ -0,0 +1,199 @@ +"use strict"; + +{ + /** + * Element to display a single bridge emoji, with a localized name. + */ + class BridgeEmoji extends HTMLElement { + static #activeInstances = new Set(); + static #observer(subject, topic) { + if (topic === "intl:app-locales-changed") { + BridgeEmoji.#updateEmojiLangCode(); + } + } + + static #addActiveInstance(inst) { + if (this.#activeInstances.size === 0) { + Services.obs.addObserver(this.#observer, "intl:app-locales-changed"); + this.#updateEmojiLangCode(); + } + this.#activeInstances.add(inst); + } + + static #removeActiveInstance(inst) { + this.#activeInstances.delete(inst); + if (this.#activeInstances.size === 0) { + Services.obs.removeObserver(this.#observer, "intl:app-locales-changed"); + } + } + + /** + * The language code for emoji annotations. + * + * null if unset. + * + * @type {string?} + */ + static #emojiLangCode = null; + /** + * A promise that resolves to two JSON structures for bridge-emojis.json and + * annotations.json, respectively. + * + * @type {Promise} + */ + static #emojiPromise = Promise.all([ + fetch( + "chrome://browser/content/torpreferences/bridgemoji/bridge-emojis.json" + ).then(response => response.json()), + fetch( + "chrome://browser/content/torpreferences/bridgemoji/annotations.json" + ).then(response => response.json()), + ]); + + static #unknownStringPromise = null; + + /** + * Update #emojiLangCode. + */ + static async #updateEmojiLangCode() { + let langCode; + const emojiAnnotations = (await BridgeEmoji.#emojiPromise)[1]; + // Find the first desired locale we have annotations for. + // Add "en" as a fallback. + for (const bcp47 of [...Services.locale.appLocalesAsBCP47, "en"]) { + langCode = bcp47; + if (langCode in emojiAnnotations) { + break; + } + // Remove everything after the dash, if there is one. + langCode = bcp47.replace(/-.*/, ""); + if (langCode in emojiAnnotations) { + break; + } + } + if (langCode !== this.#emojiLangCode) { + this.#emojiLangCode = langCode; + this.#unknownStringPromise = document.l10n.formatValue( + "tor-bridges-emoji-unknown" + ); + for (const inst of this.#activeInstances) { + inst.update(); + } + } + } + + /** + * Update the bridge emoji to show their corresponding emoji with an + * annotation that matches the current locale. + */ + async update() { + if (!this.#active) { + return; + } + + if (!BridgeEmoji.#emojiLangCode) { + // No lang code yet, wait until it is updated. + return; + } + + const doc = this.ownerDocument; + const [unknownString, [emojiList, emojiAnnotations]] = await Promise.all([ + BridgeEmoji.#unknownStringPromise, + BridgeEmoji.#emojiPromise, + ]); + + const emoji = emojiList[this.#index]; + let emojiName; + if (!emoji) { + // Unexpected. + this.#img.removeAttribute("src"); + } else { + const cp = emoji.codePointAt(0).toString(16); + this.#img.setAttribute( + "src", + `chrome://browser/content/torpreferences/bridgemoji/svgs/${cp}.svg` + ); + emojiName = emojiAnnotations[BridgeEmoji.#emojiLangCode][cp]; + } + if (!emojiName) { + doc.defaultView.console.error(`No emoji for index ${this.#index}`); + emojiName = unknownString; + } + doc.l10n.setAttributes(this.#img, "tor-bridges-emoji-image", { + emojiName, + }); + } + + /** + * The index for this bridge emoji. + * + * @type {integer?} + */ + #index = null; + /** + * Whether we are active (i.e. in the DOM). + * + * @type {boolean} + */ + #active = false; + /** + * The image element. + * + * @type {HTMLImgElement?} + */ + #img = null; + + constructor(index) { + super(); + this.#index = index; + } + + connectedCallback() { + if (!this.#img) { + this.#img = this.ownerDocument.createElement("img"); + this.#img.classList.add("tor-bridges-emoji-icon"); + this.#img.setAttribute("alt", ""); + this.appendChild(this.#img); + } + + this.#active = true; + BridgeEmoji.#addActiveInstance(this); + this.update(); + } + + disconnectedCallback() { + this.#active = false; + BridgeEmoji.#removeActiveInstance(this); + } + + /** + * Create four bridge emojis for the given address. + * + * @param {string} bridgeLine - The bridge address. + * + * @returns {BridgeEmoji[4]} - The bridge emoji elements. + */ + static createForAddress(bridgeLine) { + // JS uses UTF-16. While most of these emojis are surrogate pairs, a few + // ones fit one UTF-16 character. So we could not use neither indices, + // nor substr, nor some function to split the string. + // FNV-1a implementation that is compatible with other languages + const prime = 0x01000193; + const offset = 0x811c9dc5; + let hash = offset; + const encoder = new TextEncoder(); + for (const byte of encoder.encode(bridgeLine)) { + hash = Math.imul(hash ^ byte, prime); + } + + return [ + ((hash & 0x7f000000) >> 24) | (hash < 0 ? 0x80 : 0), + (hash & 0x00ff0000) >> 16, + (hash & 0x0000ff00) >> 8, + hash & 0x000000ff, + ].map(index => new BridgeEmoji(index)); + } + } + + customElements.define("tor-bridge-emoji", BridgeEmoji); +} diff --git a/browser/components/torpreferences/content/bridgemoji/annotations.json b/browser/components/torpreferences/content/bridgemoji/annotations.json new file mode 100644 index 0000000000000000000000000000000000000000..8336a4410953983b1a6f86873950153a54ed1d3e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/annotations.json @@ -0,0 +1,10323 @@ +{ + "_comment": "Generated by tools/torbrowser/update_emojis.py on 2024-08-06", + "ar": { + "1f47d": "كائن فضائي", + "1f916": "وجه روبوت", + "1f9e0": "دماغ", + "1f441": "عين", + "1f9d9": "سحرة", + "1f9da": "جنيّة خيالية", + "1f9dc": "مخلوق بحري بجسد بشري وذيل سمكة", + "1f435": "وجه قرد", + "1f9a7": "إنسان الغاب", + "1f436": "وجه كلب", + "1f43a": "وجه ذئب", + "1f98a": "وجه ثعلب", + "1f99d": "راكون", + "1f431": "وجه قطة", + "1f981": "وجه أسد", + "1f42f": "وجه نمر", + "1f434": "وجه حصان", + "1f984": "وجه أحادي قرن", + "1f993": "حمار وحشي", + "1f98c": "غزال", + "1f42e": "وجه بقرة", + "1f437": "وجه خنزير", + "1f417": "خنزير بري", + "1f42a": "جمل وحيد السنام", + "1f999": "لاما", + "1f992": "زرافة", + "1f418": "فيل", + "1f9a3": "ماموث", + "1f98f": "وحيد القرن", + "1f42d": "وجه فأر", + "1f430": "وجه أرنب", + "1f43f": "سنجاب", + "1f994": "قنفد", + "1f987": "خفاش", + "1f43b": "وجه دب", + "1f428": "دب كوالا", + "1f9a5": "كسلان", + "1f9a6": "قندس", + "1f998": "كنغر", + "1f425": "كتكوت صغير بوجه للأمام", + "1f426": "طائر", + "1f54a": "حمامة", + "1f986": "بطة", + "1f989": "بومة", + "1f9a4": "طائر الدودو", + "1fab6": "ريشة", + "1f9a9": "فلامينغو", + "1f99a": "طاووس", + "1f99c": "ببغاء", + "1f40a": "تمساح", + "1f422": "سلحفاة", + "1f98e": "سحلية", + "1f40d": "ثعبان", + "1f432": "وجه تنين", + "1f995": "ديناصور صوروبودا", + "1f433": "حوت بنافورة", + "1f42c": "دولفين", + "1f9ad": "فقمة", + "1f41f": "سمكة", + "1f420": "سمكة استوائية", + "1f988": "سمكة قرش", + "1f419": "أخطبوط", + "1f41a": "صدفة حلزونية", + "1f40c": "حلزون", + "1f98b": "فراشة", + "1f41b": "بق", + "1f41d": "نحلة", + "1f41e": "دعسوقة", + "1f490": "باقة زهور", + "1f339": "وردة", + "1f33a": "كركديه", + "1f33b": "دوار الشمس", + "1f337": "زهرة التوليب", + "1f332": "شجرة دائمة الخضرة", + "1f333": "شجرة زائلة الخضرة", + "1f334": "نخلة", + "1f335": "صبار", + "1f33f": "عشب", + "1f341": "ورقة شجر القيقب", + "1f344": "عيش الغراب", + "1f347": "عنب", + "1f348": "شمام", + "1f349": "بطيخ", + "1f34a": "يوسفي", + "1f34b": "ليمون", + "1f34c": "موز", + "1f34d": "أناناس", + "1f96d": "مانجو", + "1f34f": "تفاح أخضر", + "1f350": "كمثرى", + "1f351": "خوخ", + "1f352": "كرز", + "1f353": "فراولة", + "1fad0": "توت برّي", + "1f95d": "كيوي", + "1f345": "طماطم", + "1fad2": "زيتون", + "1f965": "جوز الهند", + "1f951": "أفوكادو", + "1f346": "باذنجان", + "1f955": "جزر", + "1f33d": "ذرة", + "1f336": "فلفل حار", + "1f96c": "خضار ورقي", + "1f966": "بروكولي", + "1f9c5": "بصل", + "1f95c": "فول سوداني", + "1f950": "كرواسون", + "1f956": "الخبز الفرنسي", + "1f968": "بريتزل", + "1f96f": "خبز البيغل", + "1f95e": "فطائر", + "1f9c7": "وافل", + "1f354": "همبرغر", + "1f355": "بيتزا", + "1f32d": "هوت دوغ", + "1f32e": "تاكو", + "1f37f": "فشار", + "1f980": "سرطان", + "1f99e": "كركند", + "1f368": "آيس كريم", + "1f369": "كعكة محلاة", + "1f36a": "كعكة", + "1f382": "كعكة عيد ميلاد", + "1f9c1": "كعكة صغيرة", + "1f36b": "لوح شوكولاتة", + "1f36c": "حلوى", + "1f36d": "مصاصة", + "1fad6": "إبريق شاي", + "1f9c3": "علبة عصير", + "1f9c9": "متة", + "1f9ed": "بوصلة", + "1f3d4": "جبل بقمة ثلجية", + "1f30b": "بركان", + "1f3d5": "تخييم", + "1f3dd": "جزيرة صحراوية", + "1f3e1": "منزل بحديقة", + "26f2": "نافورة", + "1f3a0": "حصان الدوامة", + "1f3a1": "عجلة دوارة", + "1f3a2": "قطار ملاهي", + "1f488": "محل حلاقة", + "1f686": "قطار", + "1f68b": "سيارة ترام", + "1f68d": "حافلة مقتربة", + "1f695": "تاكسي", + "1f697": "سيارة", + "1f69a": "شاحنة توصيل طلبات", + "1f69c": "جرار", + "1f6f5": "سكوتر بمحرك", + "1f6fa": "توكتوك", + "1f6f4": "سكوتر بدون محرك", + "1f6f9": "لوح التزلج", + "1f6fc": "حذاء مع عجلات", + "2693": "مرساة", + "26f5": "مركب شراعي", + "1f6f6": "زورق", + "1f6a4": "قارب سريع", + "1f6a2": "سفينة", + "2708": "طائرة", + "1f681": "هليكوبتر", + "1f6a0": "قطار جبلي", + "1f6f0": "قمر صناعي", + "1f680": "صاروخ", + "1f6f8": "صحن طائر", + "23f0": "ساعة منبه", + "1f319": "هلال", + "1f321": "ترمومتر", + "2600": "شمس", + "1fa90": "كوكب داخل حلقة", + "1f31f": "نجم ساطع", + "1f300": "عاصفة", + "1f308": "ألوان الطيف", + "2602": "شمسية", + "2744": "كتلة ثلج", + "2604": "مذنّب", + "1f525": "حريق", + "1f4a7": "قطرة", + "1f30a": "موجة", + "1f383": "هالوين", + "2728": "ومضات", + "1f388": "بالون", + "1f389": "فرقعة حفلة", + "1f38f": "قصاصات ملونة", + "1f380": "شريط", + "1f381": "هدية ملفوفة", + "1f39f": "تذكرتا دخول", + "1f3c6": "كأس", + "26bd": "كرة قدم", + "1f3c0": "كرة سلة", + "1f3c8": "كرة قدم أمريكية", + "1f3be": "تنس", + "1f94f": "قرص طائر", + "1f3d3": "تنس الطاولة", + "1f3f8": "تنس الريشة", + "1f93f": "قناع غطس", + "1f94c": "حجرة لعبة الكرلنغ", + "1f3af": "نشان", + "1fa80": "يويو", + "1fa81": "طائرة ورقية", + "1f52e": "كرة كريستال", + "1f3b2": "زهر", + "1f9e9": "أحجية الصور المقطوعة", + "1f3a8": "لوحة ألوان الرسام", + "1f9f5": "بكرة خيط", + "1f455": "تي شيرت", + "1f9e6": "جورب", + "1f457": "فستان", + "1fa73": "شورت", + "1f392": "حقيبة مدرسة", + "1f45f": "حذاء رياضي", + "1f451": "تاج", + "1f9e2": "قبعة رياضية", + "1f484": "أحمر شفاه", + "1f48d": "خاتم", + "1f48e": "جوهرة", + "1f4e2": "مكبر صوت", + "1f3b6": "نوتات موسيقية", + "1f399": "ميكروفون استوديو", + "1f4fb": "راديو", + "1f3b7": "ساكسفون", + "1fa97": "أكورديون", + "1f3b8": "غيتار", + "1f3ba": "آلة نفخ", + "1f3bb": "كمان", + "1fa95": "آلة بانجو", + "1f941": "طبلة", + "260e": "هاتف أرضي", + "1f50b": "بطارية", + "1f4bf": "سي دي", + "1f9ee": "معداد", + "1f3ac": "كلاكيت", + "1f4a1": "مصباح مضاء", + "1f526": "ضوء فلاش", + "1f3ee": "فانوس بورق أحمر", + "1f4d5": "كتاب مغلق", + "1f3f7": "ملصق", + "1f4b3": "بطاقة ائتمان", + "270f": "قلم رصاص", + "1f58c": "فرشاة ألوان", + "1f58d": "قلم شمع ملون", + "1f4cc": "دبوس ضغط", + "1f4ce": "مشبك ورق", + "1f511": "مفتاح", + "1fa83": "خذوف مرتد", + "1f3f9": "قوس وسهم", + "2696": "ميزان", + "1f9f2": "مغناطيس", + "1f9ea": "أنبوب اختبار", + "1f9ec": "الحامض النووي", + "1f52c": "ميكروسكوب", + "1f52d": "تليسكوب", + "1f4e1": "طبق قمر صناعي", + "1fa91": "كرسي", + "1f9f9": "مكنسة", + "1f5ff": "تمثال" + }, + "be": { + "1f47d": "іншапланецянін", + "1f916": "робат", + "1f9e0": "мозг", + "1f441": "вока", + "1f9d9": "чараўнік", + "1f9da": "фея", + "1f9dc": "русалкі", + "1f435": "пыска малпы", + "1f9a7": "арангутан", + "1f436": "сабачая пыска", + "1f43a": "воўк", + "1f98a": "ліс", + "1f99d": "янот", + "1f431": "каціная пыска", + "1f981": "леў", + "1f42f": "пыска тыгра", + "1f434": "пыска каня", + "1f984": "пыска аднарога", + "1f993": "зебра", + "1f98c": "алень", + "1f42e": "пыска каровы", + "1f437": "пыска свінні", + "1f417": "дзік", + "1f42a": "вярблюд", + "1f999": "лама", + "1f992": "жыраф", + "1f418": "слон", + "1f9a3": "мамант", + "1f98f": "насарог", + "1f42d": "мышыная пыска", + "1f430": "заечая пыска", + "1f43f": "бурундук", + "1f994": "вожык", + "1f987": "кажан", + "1f43b": "мядзведжая пыска", + "1f428": "каала", + "1f9a5": "лянівец", + "1f9a6": "выдра", + "1f998": "кенгуру", + "1f425": "кураня спераду", + "1f426": "птушка", + "1f54a": "голуб", + "1f986": "качка", + "1f989": "сава", + "1f9a4": "дадо", + "1fab6": "пяро", + "1f9a9": "фламінга", + "1f99a": "паўлін", + "1f99c": "папугай", + "1f40a": "кракадзіл", + "1f422": "чарапаха", + "1f98e": "яшчарка", + "1f40d": "змяя", + "1f432": "галава цмока", + "1f995": "заўрапод", + "1f433": "фантануючы кіт", + "1f42c": "дэльфін", + "1f9ad": "цюлень", + "1f41f": "рыба", + "1f420": "трапічная рыба", + "1f988": "акула", + "1f419": "васьміног", + "1f41a": "спіральная ракушка", + "1f40c": "смоўж", + "1f98b": "матылёк", + "1f41b": "кузурка", + "1f41d": "пчала", + "1f41e": "божая кароўка", + "1f490": "букет", + "1f339": "ружа", + "1f33a": "гібіскус", + "1f33b": "сланечнік", + "1f337": "цюльпан", + "1f332": "вечназялёнае дрэва", + "1f333": "ліставое дрэва", + "1f334": "пальма", + "1f335": "кактус", + "1f33f": "лекавая трава", + "1f341": "кляновы ліст", + "1f344": "грыб", + "1f347": "вінаград", + "1f348": "дыня", + "1f349": "кавун", + "1f34a": "мандарын", + "1f34b": "лімон", + "1f34c": "банан", + "1f34d": "ананас", + "1f96d": "манга", + "1f34f": "зялёны яблык", + "1f350": "груша", + "1f351": "персік", + "1f352": "вішні", + "1f353": "клубніцы", + "1fad0": "буякі", + "1f95d": "ківі", + "1f345": "памідор", + "1fad2": "аліва", + "1f965": "какос", + "1f951": "авакада", + "1f346": "баклажан", + "1f955": "морква", + "1f33d": "катах кукурузы", + "1f336": "востры перац", + "1f96c": "зеляніна", + "1f966": "брокалі", + "1f9c5": "цыбуля", + "1f95c": "арахіс", + "1f950": "круасан", + "1f956": "багет", + "1f968": "крэндзель", + "1f96f": "пышка", + "1f95e": "бліны", + "1f9c7": "вафля", + "1f354": "гамбургер", + "1f355": "піца", + "1f32d": "хот-дог", + "1f32e": "така", + "1f37f": "папкорн", + "1f980": "краб", + "1f99e": "амар", + "1f368": "марожанае", + "1f369": "пончык", + "1f36a": "пячэнне", + "1f382": "імянінны торт", + "1f9c1": "кекс", + "1f36b": "плітка шакаладу", + "1f36c": "цукерка", + "1f36d": "ледзянец", + "1fad6": "чайнік", + "1f9c3": "пачак з напоем", + "1f9c9": "матэ", + "1f9ed": "компас", + "1f3d4": "заснежаная гара", + "1f30b": "вулкан", + "1f3d5": "кемпінг", + "1f3dd": "ненаселены востраў", + "1f3e1": "дом з садам", + "26f2": "фантан", + "1f3a0": "конік з каруселі", + "1f3a1": "кола агляду", + "1f3a2": "амерыканскія горкі", + "1f488": "каляровы слуп", + "1f686": "цягнік", + "1f68b": "трамвайны вагон", + "1f68d": "набліжаецца аўтобус", + "1f695": "таксі", + "1f697": "аўтамабіль", + "1f69a": "грузавік", + "1f69c": "трактар", + "1f6f5": "скутар", + "1f6fa": "аўтарыкша", + "1f6f4": "самакат", + "1f6f9": "скейтборд", + "1f6fc": "ролікавы канёк", + "2693": "якар", + "26f5": "паруснік", + "1f6f6": "каноэ", + "1f6a4": "быстраходны катар", + "1f6a2": "карабель", + "2708": "самалёт", + "1f681": "верталёт", + "1f6a0": "горны фунікулёр", + "1f6f0": "спадарожнік", + "1f680": "ракета", + "1f6f8": "лятаючая талерка", + "23f0": "будзільнік", + "1f319": "паўмесяц", + "1f321": "тэрмометр", + "2600": "сонца", + "1fa90": "планета з кальцом", + "1f31f": "бліскучая зорка", + "1f300": "цыклон", + "1f308": "вясёлка", + "2602": "парасон", + "2744": "сняжынка", + "2604": "камета", + "1f525": "агонь", + "1f4a7": "кропелька", + "1f30a": "хваля", + "1f383": "гарбузны ліхтар", + "2728": "іскры", + "1f388": "паветраны шарык", + "1f389": "хлапушка", + "1f38f": "каінаборы", + "1f380": "стужка", + "1f381": "запакаваны падарунак", + "1f39f": "уваходныя білеты", + "1f3c6": "кубак", + "26bd": "футбольны мяч", + "1f3c0": "баскетбол", + "1f3c8": "амерыканскі футбол", + "1f3be": "тэніс", + "1f94f": "фрысбі", + "1f3d3": "пінг-понг", + "1f3f8": "бадмінтон", + "1f93f": "маска для падводнага плавання", + "1f94c": "шайба для кёрлінгу", + "1f3af": "прамое пападанне", + "1fa80": "ё-ё", + "1fa81": "паветраны змей", + "1f52e": "крыштальны шар", + "1f3b2": "ігральная косць", + "1f9e9": "частка пазла", + "1f3a8": "палітра мастака", + "1f9f5": "нітка", + "1f455": "футболка", + "1f9e6": "шкарпэткі", + "1f457": "сукенка", + "1fa73": "шорты", + "1f392": "школьны ранец", + "1f45f": "красовак", + "1f451": "карона", + "1f9e2": "кепка", + "1f484": "памада", + "1f48d": "кальцо", + "1f48e": "каштоўны самацвет", + "1f4e2": "гучнагаварыцель", + "1f3b6": "музычныя ноты", + "1f399": "студыйны мікрафон", + "1f4fb": "радыё", + "1f3b7": "саксафон", + "1fa97": "акардэон", + "1f3b8": "гітара", + "1f3ba": "труба", + "1f3bb": "скрыпка", + "1fa95": "банджа", + "1f941": "барабан", + "260e": "хатні тэлефон", + "1f50b": "батарэйка", + "1f4bf": "аптычны дыск", + "1f9ee": "лічыльнікі", + "1f3ac": "нумаратар з хлапушкай", + "1f4a1": "лямпачка", + "1f526": "ліхтарык", + "1f3ee": "чырвоны папяровы ліхтар", + "1f4d5": "закрытая кніга", + "1f3f7": "бірка", + "1f4b3": "крэдытная карта", + "270f": "аловак", + "1f58c": "пэндзаль", + "1f58d": "пастэль", + "1f4cc": "канцылярская кнопка", + "1f4ce": "сашчэпка", + "1f511": "ключ", + "1fa83": "бумеранг", + "1f3f9": "лук са стралой", + "2696": "шалі", + "1f9f2": "магніт", + "1f9ea": "прабірка", + "1f9ec": "ДНК", + "1f52c": "мікраскоп", + "1f52d": "тэлескоп", + "1f4e1": "спадарожнікавая антэна", + "1fa91": "крэсла", + "1f9f9": "мятла", + "1f5ff": "мааі" + }, + "bg": { + "1f47d": "извънземно", + "1f916": "Лице на робот", + "1f9e0": "мозък", + "1f441": "око", + "1f9d9": "жена магьосник", + "1f9da": "фея", + "1f9dc": "жена амфибия", + "1f435": "Лице на маймуна", + "1f9a7": "орангутан", + "1f436": "муцуна на куче", + "1f43a": "вълк", + "1f98a": "лисица", + "1f99d": "енот", + "1f431": "муцуна на котка", + "1f981": "лъв", + "1f42f": "муцуна на тигър", + "1f434": "муцуна на кон", + "1f984": "еднорог", + "1f993": "зебра", + "1f98c": "елен", + "1f42e": "муцуна на крава", + "1f437": "зурла на прасе", + "1f417": "глиган", + "1f42a": "камила", + "1f999": "лама", + "1f992": "жираф", + "1f418": "слон", + "1f9a3": "мамут", + "1f98f": "носорог", + "1f42d": "муцуна на мишка", + "1f430": "муцуна на заек", + "1f43f": "катерица", + "1f994": "таралеж", + "1f987": "прилеп", + "1f43b": "мечка", + "1f428": "коала", + "1f9a5": "ленивец", + "1f9a6": "видра", + "1f998": "кенгуру", + "1f425": "пиленце, гледано отпред", + "1f426": "птица", + "1f54a": "гълъб", + "1f986": "патица", + "1f989": "бухал", + "1f9a4": "Додо", + "1fab6": "перо", + "1f9a9": "фламинго", + "1f99a": "паун", + "1f99c": "папагал", + "1f40a": "крокодил", + "1f422": "костенурка", + "1f98e": "гущер", + "1f40d": "змия", + "1f432": "глава на дракон", + "1f995": "завропод", + "1f433": "пръскащ кит", + "1f42c": "делфин", + "1f9ad": "тюлен", + "1f41f": "риба", + "1f420": "тропическа риба", + "1f988": "акула", + "1f419": "октопод", + "1f41a": "спирална раковина", + "1f40c": "охлюв", + "1f98b": "пеперуда", + "1f41b": "буболечка", + "1f41d": "пчела", + "1f41e": "калинка", + "1f490": "букет", + "1f339": "роза", + "1f33a": "хибискус", + "1f33b": "слънчоглед", + "1f337": "лале", + "1f332": "вечнозелено дърво", + "1f333": "листопадно дърво", + "1f334": "палма", + "1f335": "кактус", + "1f33f": "билка", + "1f341": "кленов лист", + "1f344": "гъба", + "1f347": "грозде", + "1f348": "пъпеш", + "1f349": "диня", + "1f34a": "мандарина", + "1f34b": "лимон", + "1f34c": "банан", + "1f34d": "ананас", + "1f96d": "манго", + "1f34f": "зелена ябълка", + "1f350": "круша", + "1f351": "праскова", + "1f352": "череши", + "1f353": "ягода", + "1fad0": "черни боровинки", + "1f95d": "плод киви", + "1f345": "домат", + "1fad2": "маслина", + "1f965": "кокосов орех", + "1f951": "авокадо", + "1f346": "патладжан", + "1f955": "морков", + "1f33d": "царевичен кочан", + "1f336": "люта чушка", + "1f96c": "листен зеленчук", + "1f966": "броколи", + "1f9c5": "лук", + "1f95c": "фъстъци", + "1f950": "кроасан", + "1f956": "багета", + "1f968": "брецел", + "1f96f": "геврек", + "1f95e": "палачинки", + "1f9c7": "гофрета", + "1f354": "хамбургер", + "1f355": "пица", + "1f32d": "хотдог", + "1f32e": "тако", + "1f37f": "пуканки", + "1f980": "рак", + "1f99e": "омар", + "1f368": "сладолед", + "1f369": "поничка", + "1f36a": "бисквитка", + "1f382": "торта за рожден ден", + "1f9c1": "къпкейк", + "1f36b": "шоколадово блокче", + "1f36c": "бонбон", + "1f36d": "близалка", + "1fad6": "чайник", + "1f9c3": "кутия за напитки", + "1f9c9": "мате", + "1f9ed": "компас", + "1f3d4": "покрита със сняг планина", + "1f30b": "вулкан", + "1f3d5": "къмпинг", + "1f3dd": "необитаем остров", + "1f3e1": "къща с градина", + "26f2": "фонтан", + "1f3a0": "кон от въртележка", + "1f3a1": "виенско колело", + "1f3a2": "влакче в увеселителен парк", + "1f488": "знак на бръснар", + "1f686": "влак", + "1f68b": "трамваен вагон", + "1f68d": "приближаващ автобус", + "1f695": "такси", + "1f697": "автомобил", + "1f69a": "камион за доставки", + "1f69c": "трактор", + "1f6f5": "моторен скутер", + "1f6fa": "авторикша", + "1f6f4": "тротинетка", + "1f6f9": "скейтборд", + "1f6fc": "ролери", + "2693": "котва", + "26f5": "яхта", + "1f6f6": "кану", + "1f6a4": "моторна лодка", + "1f6a2": "кораб", + "2708": "самолет", + "1f681": "хеликоптер", + "1f6a0": "лифт", + "1f6f0": "спътник", + "1f680": "ракета", + "1f6f8": "летяща чиния", + "23f0": "будилник", + "1f319": "полумесец", + "1f321": "термометър", + "2600": "слънце", + "1fa90": "планета с пръстен", + "1f31f": "блестяща звезда", + "1f300": "циклон", + "1f308": "дъга", + "2602": "чадър", + "2744": "снежинка", + "2604": "комета", + "1f525": "огън", + "1f4a7": "капка", + "1f30a": "вълна", + "1f383": "тиквен фенер", + "2728": "звездички", + "1f388": "балон", + "1f389": "конфети", + "1f38f": "коинобори", + "1f380": "панделка", + "1f381": "опакован подарък", + "1f39f": "билети за вход", + "1f3c6": "спортна купа", + "26bd": "футболна топка", + "1f3c0": "баскетболна топка", + "1f3c8": "топка за американски футбол", + "1f3be": "тенис", + "1f94f": "фризби", + "1f3d3": "тенис на маса", + "1f3f8": "бадминтон", + "1f93f": "маска за гмуркане", + "1f94c": "камък за кърлинг", + "1f3af": "точен удар", + "1fa80": "йо-йо", + "1fa81": "хвърчило", + "1f52e": "Кристално кълбо", + "1f3b2": "зар за игра", + "1f9e9": "част от пъзел", + "1f3a8": "палитра на художник", + "1f9f5": "конец", + "1f455": "тениска", + "1f9e6": "чорапи", + "1f457": "рокля", + "1fa73": "плувни шорти", + "1f392": "ученическа раница", + "1f45f": "спортна обувка", + "1f451": "корона", + "1f9e2": "шапка с козирка", + "1f484": "червило", + "1f48d": "пръстен", + "1f48e": "скъпоценен камък", + "1f4e2": "Високоговорител за обществени места", + "1f3b6": "ноти", + "1f399": "студиен микрофон", + "1f4fb": "радио", + "1f3b7": "саксофон", + "1fa97": "акордеон", + "1f3b8": "китара", + "1f3ba": "тромпет", + "1f3bb": "цигулка", + "1fa95": "банджо", + "1f941": "барабан", + "260e": "телефон", + "1f50b": "батерия", + "1f4bf": "оптичен диск", + "1f9ee": "сметало", + "1f3ac": "клапа", + "1f4a1": "електрическа крушка", + "1f526": "фенерче", + "1f3ee": "червен хартиен фенер", + "1f4d5": "затворена книга", + "1f3f7": "етикет", + "1f4b3": "кредитна карта", + "270f": "молив", + "1f58c": "четка", + "1f58d": "пастел", + "1f4cc": "кабърче", + "1f4ce": "кламер", + "1f511": "ключ", + "1fa83": "бумеранг", + "1f3f9": "лък и стрела", + "2696": "везна", + "1f9f2": "магнит", + "1f9ea": "епруветка", + "1f9ec": "ДНК", + "1f52c": "микроскоп", + "1f52d": "телескоп", + "1f4e1": "сателитна антена", + "1fa91": "стол", + "1f9f9": "метла", + "1f5ff": "моаи" + }, + "ca": { + "1f47d": "alienígena", + "1f916": "robot", + "1f9e0": "cervell", + "1f441": "ull", + "1f9d9": "mag", + "1f9da": "fada", + "1f9dc": "persona sirena", + "1f435": "cara de mona", + "1f9a7": "orangutan", + "1f436": "cara de gos", + "1f43a": "llop", + "1f98a": "guineu", + "1f99d": "os rentador", + "1f431": "cara de gat", + "1f981": "cara de lleó", + "1f42f": "cara de tigre", + "1f434": "cara de cavall", + "1f984": "unicorn", + "1f993": "zebra", + "1f98c": "cérvol", + "1f42e": "cara de vaca", + "1f437": "cara de porc", + "1f417": "senglar", + "1f42a": "dromedari", + "1f999": "llama", + "1f992": "girafa", + "1f418": "elefant", + "1f9a3": "mamut", + "1f98f": "rinoceront", + "1f42d": "cara de ratolí", + "1f430": "cara de conill", + "1f43f": "esquirol", + "1f994": "eriçó", + "1f987": "ratapinyada", + "1f43b": "cara d’os", + "1f428": "coala", + "1f9a5": "peresós", + "1f9a6": "llúdria", + "1f998": "cangur", + "1f425": "pollet de cara", + "1f426": "ocell", + "1f54a": "colom", + "1f986": "ànec", + "1f989": "mussol", + "1f9a4": "dodo", + "1fab6": "ploma", + "1f9a9": "flamenc", + "1f99a": "paó", + "1f99c": "lloro", + "1f40a": "cocodril", + "1f422": "tortuga", + "1f98e": "llangardaix", + "1f40d": "serp", + "1f432": "cara de drac", + "1f995": "sauròpode", + "1f433": "balena que treu aigua", + "1f42c": "dofí", + "1f9ad": "foca", + "1f41f": "peix", + "1f420": "peix tropical", + "1f988": "tauró", + "1f419": "pop", + "1f41a": "cargol de mar", + "1f40c": "cargol", + "1f98b": "papallona", + "1f41b": "eruga", + "1f41d": "abella", + "1f41e": "marieta", + "1f490": "ram de flors", + "1f339": "rosa", + "1f33a": "hibisc", + "1f33b": "gira-sol", + "1f337": "tulipa", + "1f332": "arbre de fulla perenne", + "1f333": "arbre de fulla caduca", + "1f334": "palmera", + "1f335": "cactus", + "1f33f": "herba", + "1f341": "fulla d’auró", + "1f344": "bolet", + "1f347": "raïm", + "1f348": "meló", + "1f349": "síndria", + "1f34a": "mandarina", + "1f34b": "llimona", + "1f34c": "plàtan", + "1f34d": "pinya", + "1f96d": "mango", + "1f34f": "poma verda", + "1f350": "pera", + "1f351": "préssec", + "1f352": "cireres", + "1f353": "maduixa", + "1fad0": "nabius", + "1f95d": "kiwi", + "1f345": "tomàquet", + "1fad2": "oliva", + "1f965": "coco", + "1f951": "alvocat", + "1f346": "albergínia", + "1f955": "pastanaga", + "1f33d": "panotxa", + "1f336": "bitxo", + "1f96c": "fulla verda", + "1f966": "bròcoli", + "1f9c5": "ceba", + "1f95c": "cacauets", + "1f950": "croissant", + "1f956": "baguet", + "1f968": "brètzel", + "1f96f": "bagel", + "1f95e": "creps americanes", + "1f9c7": "gofra", + "1f354": "hamburguesa", + "1f355": "pizza", + "1f32d": "frankfurt", + "1f32e": "taco", + "1f37f": "crispetes", + "1f980": "cranc", + "1f99e": "llagosta", + "1f368": "gelat", + "1f369": "dònut", + "1f36a": "galeta", + "1f382": "pastís d’aniversari", + "1f9c1": "cupcake", + "1f36b": "rajola de xocolata", + "1f36c": "caramel", + "1f36d": "piruleta", + "1fad6": "tetera", + "1f9c3": "bric", + "1f9c9": "mate", + "1f9ed": "brúixola", + "1f3d4": "muntanya amb neu al cim", + "1f30b": "volcà", + "1f3d5": "acampada", + "1f3dd": "illa deserta", + "1f3e1": "casa amb jardí", + "26f2": "font", + "1f3a0": "cavallets", + "1f3a1": "roda de fira", + "1f3a2": "muntanya russa", + "1f488": "barberia", + "1f686": "tren", + "1f68b": "vagó de tramvia", + "1f68d": "autobús que arriba", + "1f695": "taxi", + "1f697": "automòbil", + "1f69a": "camió de repartiment", + "1f69c": "tractor", + "1f6f5": "escúter", + "1f6fa": "bicitaxi amb motor", + "1f6f4": "patinet", + "1f6f9": "monopatí", + "1f6fc": "patí de rodes", + "2693": "àncora", + "26f5": "veler", + "1f6f6": "canoa", + "1f6a4": "llanxa ràpida", + "1f6a2": "vaixell", + "2708": "avió", + "1f681": "helicòpter", + "1f6a0": "telefèric de muntanya", + "1f6f0": "satèl·lit", + "1f680": "coet", + "1f6f8": "plat volador", + "23f0": "despertador", + "1f319": "lluna creixent", + "1f321": "termòmetre", + "2600": "sol", + "1fa90": "planeta amb anell", + "1f31f": "estrella brillant", + "1f300": "cicló", + "1f308": "arc de Sant Martí", + "2602": "paraigua", + "2744": "floc de neu", + "2604": "cometa", + "1f525": "foc", + "1f4a7": "gota", + "1f30a": "onada", + "1f383": "carabassa de Halloween", + "2728": "espurnes", + "1f388": "globus", + "1f389": "tub de confeti", + "1f38f": "banderins de carpes", + "1f380": "llaç", + "1f381": "regal embolicat", + "1f39f": "bitllet d’entrada", + "1f3c6": "trofeu", + "26bd": "pilota de futbol", + "1f3c0": "pilota de bàsquet", + "1f3c8": "pilota de futbol americà", + "1f3be": "tennis", + "1f94f": "disc volador", + "1f3d3": "tennis de taula", + "1f3f8": "bàdminton", + "1f93f": "ulleres de busseig", + "1f94c": "pedra de cúrling", + "1f3af": "dards", + "1fa80": "io-io", + "1fa81": "estel", + "1f52e": "bola de vidre", + "1f3b2": "daus", + "1f9e9": "peces de trencaclosques", + "1f3a8": "paleta d’artista", + "1f9f5": "fil", + "1f455": "samarreta", + "1f9e6": "mitjons", + "1f457": "vestit", + "1fa73": "pantalons curts", + "1f392": "motxilla d’escola", + "1f45f": "sabatilla de córrer", + "1f451": "corona", + "1f9e2": "gorra", + "1f484": "pintallavis", + "1f48d": "anell", + "1f48e": "gemma", + "1f4e2": "altaveu de megafonia", + "1f3b6": "notes musicals", + "1f399": "micròfon d’estudi", + "1f4fb": "ràdio", + "1f3b7": "saxofon", + "1fa97": "acordió", + "1f3b8": "guitarra", + "1f3ba": "trompeta", + "1f3bb": "violí", + "1fa95": "banjo", + "1f941": "tambor", + "260e": "telèfon", + "1f50b": "bateria", + "1f4bf": "disc òptic", + "1f9ee": "àbac", + "1f3ac": "claqueta", + "1f4a1": "bombeta", + "1f526": "llanterna", + "1f3ee": "fanal de paper vermell", + "1f4d5": "llibre tancat", + "1f3f7": "etiqueta", + "1f4b3": "targeta de crèdit", + "270f": "llapis", + "1f58c": "pinzell", + "1f58d": "llapis de color", + "1f4cc": "xinxeta", + "1f4ce": "clip", + "1f511": "clau", + "1fa83": "bumerang", + "1f3f9": "arc i fletxa", + "2696": "balança (aparell)", + "1f9f2": "imant", + "1f9ea": "tub d’assaig", + "1f9ec": "adn", + "1f52c": "microscopi", + "1f52d": "telescopi", + "1f4e1": "antena de satèl·lit", + "1fa91": "cadira", + "1f9f9": "escombra", + "1f5ff": "moai" + }, + "cs": { + "1f47d": "mimozemšťan", + "1f916": "obličej robota", + "1f9e0": "mozek", + "1f441": "oko", + "1f9d9": "mág", + "1f9da": "víla", + "1f9dc": "mořská bytost", + "1f435": "hlava opice", + "1f9a7": "orangutan", + "1f436": "hlava psa", + "1f43a": "hlava vlka", + "1f98a": "hlava lišky", + "1f99d": "mýval", + "1f431": "hlava kočky", + "1f981": "hlava lva", + "1f42f": "hlava tygra", + "1f434": "hlava koně", + "1f984": "hlava jednorožce", + "1f993": "zebra", + "1f98c": "jelen", + "1f42e": "hlava krávy", + "1f437": "hlava prasete", + "1f417": "kanec", + "1f42a": "velbloud jednohrbý", + "1f999": "lama", + "1f992": "žirafa", + "1f418": "slon", + "1f9a3": "mamut", + "1f98f": "nosorožec", + "1f42d": "hlava myši", + "1f430": "hlava králíka", + "1f43f": "veverka", + "1f994": "ježek", + "1f987": "netopýr", + "1f43b": "hlava medvěda", + "1f428": "koala", + "1f9a5": "lenochod", + "1f9a6": "vydra", + "1f998": "klokan", + "1f425": "kuřátko zepředu", + "1f426": "pták", + "1f54a": "holubice", + "1f986": "kachna", + "1f989": "sova", + "1f9a4": "dodo", + "1fab6": "pírko", + "1f9a9": "plameňák", + "1f99a": "páv", + "1f99c": "papoušek", + "1f40a": "krokodýl", + "1f422": "želva", + "1f98e": "ještěrka", + "1f40d": "had", + "1f432": "hlava draka", + "1f995": "brontosaurus", + "1f433": "velryba stříkající vodu", + "1f42c": "delfín", + "1f9ad": "tuleň", + "1f41f": "ryba", + "1f420": "tropická ryba", + "1f988": "žralok", + "1f419": "chobotnice", + "1f41a": "ulita", + "1f40c": "hlemýžď", + "1f98b": "motýl", + "1f41b": "housenka", + "1f41d": "včela", + "1f41e": "beruška", + "1f490": "kytice", + "1f339": "růže", + "1f33a": "ibišek", + "1f33b": "slunečnice", + "1f337": "tulipán", + "1f332": "jehličnatý strom", + "1f333": "listnatý strom", + "1f334": "palma", + "1f335": "kaktus", + "1f33f": "bylina", + "1f341": "javorový list", + "1f344": "houba", + "1f347": "hrozny", + "1f348": "cukrový meloun", + "1f349": "meloun", + "1f34a": "mandarinka", + "1f34b": "citron", + "1f34c": "banán", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "zelené jablko", + "1f350": "hruška", + "1f351": "broskev", + "1f352": "třešně", + "1f353": "jahoda", + "1fad0": "borůvky", + "1f95d": "kiwi", + "1f345": "rajče", + "1fad2": "oliva", + "1f965": "kokos", + "1f951": "avokádo", + "1f346": "lilek", + "1f955": "mrkev", + "1f33d": "kukuřičný klas", + "1f336": "feferonka", + "1f96c": "salátové listy", + "1f966": "brokolice", + "1f9c5": "cibule", + "1f95c": "arašídy", + "1f950": "croissant", + "1f956": "bageta", + "1f968": "preclík", + "1f96f": "bagel", + "1f95e": "palačinky", + "1f9c7": "vafle", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "párek v rohlíku", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "krab", + "1f99e": "humr", + "1f368": "kopečková zmrzlina", + "1f369": "donut", + "1f36a": "koláček", + "1f382": "narozeninový dort", + "1f9c1": "košíček", + "1f36b": "tabulka čokolády", + "1f36c": "bonbon", + "1f36d": "lízátko", + "1fad6": "čajová konvice", + "1f9c3": "nápoj v krabičce", + "1f9c9": "maté", + "1f9ed": "kompas", + "1f3d4": "zasněžená hora", + "1f30b": "sopka", + "1f3d5": "tábor", + "1f3dd": "pustý ostrov", + "1f3e1": "domek se zahradou", + "26f2": "fontána", + "1f3a0": "kolotočový kůň", + "1f3a1": "ruské kolo", + "1f3a2": "horská dráha", + "1f488": "značka holičství", + "1f686": "vlak", + "1f68b": "vagón tramvaje", + "1f68d": "přijíždějící autobus", + "1f695": "taxík", + "1f697": "auto", + "1f69a": "dodávka", + "1f69c": "traktor", + "1f6f5": "skútr", + "1f6fa": "autorikša", + "1f6f4": "koloběžka", + "1f6f9": "skateboard", + "1f6fc": "kolečková brusle", + "2693": "kotva", + "26f5": "plachetnice", + "1f6f6": "kánoe", + "1f6a4": "motorový člun", + "1f6a2": "loď", + "2708": "letadlo", + "1f681": "vrtulník", + "1f6a0": "horská lanovka", + "1f6f0": "satelit", + "1f680": "raketa", + "1f6f8": "létající talíř", + "23f0": "budík", + "1f319": "srpek měsíce", + "1f321": "teploměr", + "2600": "slunce", + "1fa90": "planeta s prstencem", + "1f31f": "zářící hvězda", + "1f300": "cyklóna", + "1f308": "duha", + "2602": "deštník", + "2744": "sněhová vločka", + "2604": "kometa", + "1f525": "oheň", + "1f4a7": "kapka", + "1f30a": "vodní vlna", + "1f383": "dýňová lucerna", + "2728": "jiskry", + "1f388": "balónek", + "1f389": "vystřelovací konfety", + "1f38f": "koinobori", + "1f380": "mašle", + "1f381": "zabalený dárek", + "1f39f": "vstupenky", + "1f3c6": "trofejní pohár", + "26bd": "fotbalový míč", + "1f3c0": "basketbalový míč", + "1f3c8": "míč na americký fotbal", + "1f3be": "tenis", + "1f94f": "frisbee", + "1f3d3": "stolní tenis", + "1f3f8": "badminton", + "1f93f": "potápěčská maska", + "1f94c": "curlingový kámen", + "1f3af": "přesný zásah do terče", + "1fa80": "jojo", + "1fa81": "papírový drak", + "1f52e": "křišťálová koule", + "1f3b2": "hrací kostka", + "1f9e9": "puzzle", + "1f3a8": "malířská paleta", + "1f9f5": "cívka nití", + "1f455": "tričko", + "1f9e6": "ponožky", + "1f457": "šaty", + "1fa73": "šortky", + "1f392": "školní batoh", + "1f45f": "běžecká bota", + "1f451": "koruna", + "1f9e2": "kšiltovka", + "1f484": "rtěnka", + "1f48d": "prsten", + "1f48e": "drahokam", + "1f4e2": "tlampač", + "1f3b6": "noty", + "1f399": "studiový mikrofon", + "1f4fb": "rádio", + "1f3b7": "saxofon", + "1fa97": "akordeon", + "1f3b8": "kytara", + "1f3ba": "trubka", + "1f3bb": "housle", + "1fa95": "banjo", + "1f941": "buben", + "260e": "telefon", + "1f50b": "baterie", + "1f4bf": "optický disk", + "1f9ee": "počitadlo", + "1f3ac": "filmová klapka", + "1f4a1": "žárovka", + "1f526": "baterka", + "1f3ee": "červený lampion", + "1f4d5": "zavřená kniha", + "1f3f7": "visačka", + "1f4b3": "platební karta", + "270f": "tužka", + "1f58c": "štětec", + "1f58d": "pastelka", + "1f4cc": "připínáček", + "1f4ce": "kancelářská sponka", + "1f511": "klíč", + "1fa83": "bumerang", + "1f3f9": "luk a šíp", + "2696": "miskové váhy", + "1f9f2": "magnet", + "1f9ea": "zkumavka", + "1f9ec": "DNA", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "satelitní anténa", + "1fa91": "židle", + "1f9f9": "koště", + "1f5ff": "socha moai" + }, + "da": { + "1f47d": "rumvæsen", + "1f916": "robot", + "1f9e0": "hjerne", + "1f441": "øje", + "1f9d9": "magiker", + "1f9da": "fe", + "1f9dc": "havvæsen", + "1f435": "abehoved", + "1f9a7": "orangutang", + "1f436": "hundehoved", + "1f43a": "ulvehoved", + "1f98a": "rævehoved", + "1f99d": "vaskebjørn", + "1f431": "kattehoved", + "1f981": "løvehoved", + "1f42f": "tigerhoved", + "1f434": "hestehoved", + "1f984": "enhjørningehoved", + "1f993": "zebra", + "1f98c": "hjort", + "1f42e": "kohoved", + "1f437": "grisehoved", + "1f417": "vildsvin", + "1f42a": "dromedar", + "1f999": "lama", + "1f992": "giraf", + "1f418": "elefant", + "1f9a3": "mammut", + "1f98f": "næsehorn", + "1f42d": "musehoved", + "1f430": "kaninhoved", + "1f43f": "jordegern", + "1f994": "pindsvin", + "1f987": "flagermus", + "1f43b": "bjørnehoved", + "1f428": "koala", + "1f9a5": "dovendyr", + "1f9a6": "odder", + "1f998": "kænguru", + "1f425": "kylling forfra", + "1f426": "fugl", + "1f54a": "due", + "1f986": "and", + "1f989": "ugle", + "1f9a4": "dronte", + "1fab6": "fjer", + "1f9a9": "flamingo", + "1f99a": "påfugl", + "1f99c": "papegøje", + "1f40a": "krokodille", + "1f422": "skildpadde", + "1f98e": "firben", + "1f40d": "slange", + "1f432": "dragehoved", + "1f995": "sauropod", + "1f433": "hval med vandsprøjt", + "1f42c": "delfin", + "1f9ad": "sæl", + "1f41f": "fisk", + "1f420": "tropisk fisk", + "1f988": "haj", + "1f419": "blæksprutte", + "1f41a": "konkylie", + "1f40c": "snegl", + "1f98b": "sommerfugl", + "1f41b": "larve", + "1f41d": "honningbi", + "1f41e": "mariehøne", + "1f490": "blomsterbuket", + "1f339": "rose", + "1f33a": "hibiscus", + "1f33b": "solsikke", + "1f337": "tulipan", + "1f332": "nåletræ", + "1f333": "løvtræ", + "1f334": "palme", + "1f335": "kaktus", + "1f33f": "urt", + "1f341": "ahornblad", + "1f344": "svamp", + "1f347": "vindruer", + "1f348": "melon", + "1f349": "vandmelon", + "1f34a": "appelsin", + "1f34b": "citron", + "1f34c": "banan", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "grønt æble", + "1f350": "pære", + "1f351": "fersken", + "1f352": "kirsebær", + "1f353": "jordbær", + "1fad0": "blåbær", + "1f95d": "kiwifrugt", + "1f345": "tomat", + "1fad2": "oliven", + "1f965": "kokosnød", + "1f951": "avokado", + "1f346": "aubergine", + "1f955": "gulerod", + "1f33d": "majs", + "1f336": "chili", + "1f96c": "bladgrønt", + "1f966": "broccoli", + "1f9c5": "løg", + "1f95c": "jordnødder", + "1f950": "croissant", + "1f956": "flute", + "1f968": "kringle", + "1f96f": "bagel", + "1f95e": "pandekager", + "1f9c7": "vaffel", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hotdog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "krabbe", + "1f99e": "hummer", + "1f368": "is", + "1f369": "donut", + "1f36a": "småkage", + "1f382": "fødselsdagskage", + "1f9c1": "cupcake", + "1f36b": "chokolade", + "1f36c": "bolsje", + "1f36d": "slikkepind", + "1fad6": "tekande", + "1f9c3": "brik", + "1f9c9": "mate", + "1f9ed": "kompas", + "1f3d4": "sneklædt bjerg", + "1f30b": "vulkan", + "1f3d5": "camping", + "1f3dd": "øde ø", + "1f3e1": "hus med have", + "26f2": "springvand", + "1f3a0": "karrusel", + "1f3a1": "pariserhjul", + "1f3a2": "rutsjebane", + "1f488": "barber", + "1f686": "tog", + "1f68b": "vogn", + "1f68d": "bus forfra", + "1f695": "taxa", + "1f697": "bil", + "1f69a": "lastbil", + "1f69c": "traktor", + "1f6f5": "scooter", + "1f6fa": "motor-rickshaw", + "1f6f4": "løbehjul", + "1f6f9": "skateboard", + "1f6fc": "rulleskøjte", + "2693": "anker", + "26f5": "sejlbåd", + "1f6f6": "kano", + "1f6a4": "speedbåd", + "1f6a2": "skib", + "2708": "fly", + "1f681": "helikopter", + "1f6a0": "kabelbane", + "1f6f0": "satellit", + "1f680": "raket", + "1f6f8": "ufo", + "23f0": "vækkeur", + "1f319": "halvmåne", + "1f321": "termometer", + "2600": "sol", + "1fa90": "planet med ringe", + "1f31f": "blinkende stjerne", + "1f300": "cyklon", + "1f308": "regnbue", + "2602": "paraply", + "2744": "snefnug", + "2604": "komet", + "1f525": "ild", + "1f4a7": "dråbe", + "1f30a": "bølge", + "1f383": "græskarmand", + "2728": "stjerner", + "1f388": "ballon", + "1f389": "bordbombe", + "1f38f": "karpevimpel", + "1f380": "sløjfe", + "1f381": "gave", + "1f39f": "adgangsbillet", + "1f3c6": "pokal", + "26bd": "fodbold", + "1f3c0": "basketball", + "1f3c8": "amerikansk fodbold", + "1f3be": "tennis", + "1f94f": "frisbee", + "1f3d3": "bordtennis", + "1f3f8": "badminton", + "1f93f": "dykkermaske", + "1f94c": "curlingsten", + "1f3af": "pletskud", + "1fa80": "yoyo", + "1fa81": "legetøjsdrage", + "1f52e": "krystalkugle", + "1f3b2": "terning", + "1f9e9": "brik til puslespil", + "1f3a8": "palet", + "1f9f5": "tråd", + "1f455": "T-shirt", + "1f9e6": "sokker", + "1f457": "kjole", + "1fa73": "shorts", + "1f392": "rygsæk", + "1f45f": "løbesko", + "1f451": "krone", + "1f9e2": "kasket", + "1f484": "læbestift", + "1f48d": "ring", + "1f48e": "ædelsten", + "1f4e2": "elektrisk megafon", + "1f3b6": "noder", + "1f399": "studiemikrofon", + "1f4fb": "radio", + "1f3b7": "saxofon", + "1fa97": "akkordeon", + "1f3b8": "guitar", + "1f3ba": "trompet", + "1f3bb": "violin", + "1fa95": "banjo", + "1f941": "tromme", + "260e": "telefon", + "1f50b": "batteri", + "1f4bf": "cd", + "1f9ee": "kugleramme", + "1f3ac": "klaptræ", + "1f4a1": "elpære", + "1f526": "lommelygte", + "1f3ee": "papirlanterne", + "1f4d5": "lukket bog", + "1f3f7": "mærkat", + "1f4b3": "kreditkort", + "270f": "blyant", + "1f58c": "malerpensel", + "1f58d": "farvekridt", + "1f4cc": "tegnestift", + "1f4ce": "papirclips", + "1f511": "nøgle", + "1fa83": "boomerang", + "1f3f9": "bue og pil", + "2696": "vægt", + "1f9f2": "magnet", + "1f9ea": "reagensglas", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "parabolantenne", + "1fa91": "stol", + "1f9f9": "kost", + "1f5ff": "statue" + }, + "de": { + "1f47d": "Außerirdischer", + "1f916": "Roboter", + "1f9e0": "Gehirn", + "1f441": "Auge", + "1f9d9": "Magier(in)", + "1f9da": "Märchenfee", + "1f9dc": "Wassermensch", + "1f435": "Affengesicht", + "1f9a7": "Orang-Utan", + "1f436": "Hundegesicht", + "1f43a": "Wolf", + "1f98a": "Fuchs", + "1f99d": "Waschbär", + "1f431": "Katzengesicht", + "1f981": "Löwe", + "1f42f": "Tigergesicht", + "1f434": "Pferdegesicht", + "1f984": "Einhorn", + "1f993": "Zebra", + "1f98c": "Hirsch", + "1f42e": "Kuhgesicht", + "1f437": "Schweinegesicht", + "1f417": "Wildschwein", + "1f42a": "Dromedar", + "1f999": "Lama", + "1f992": "Giraffe", + "1f418": "Elefant", + "1f9a3": "Mammut", + "1f98f": "Nashorn", + "1f42d": "Mäusegesicht", + "1f430": "Hasengesicht", + "1f43f": "Streifenhörnchen", + "1f994": "Igel", + "1f987": "Fledermaus", + "1f43b": "Bär", + "1f428": "Koala", + "1f9a5": "Faultier", + "1f9a6": "Otter", + "1f998": "Känguru", + "1f425": "Küken von vorne", + "1f426": "Vogel", + "1f54a": "Taube", + "1f986": "Ente", + "1f989": "Eule", + "1f9a4": "Dodo", + "1fab6": "Feder", + "1f9a9": "Flamingo", + "1f99a": "Pfau", + "1f99c": "Papagei", + "1f40a": "Krokodil", + "1f422": "Schildkröte", + "1f98e": "Eidechse", + "1f40d": "Schlange", + "1f432": "Drachengesicht", + "1f995": "Sauropode", + "1f433": "blasender Wal", + "1f42c": "Delfin", + "1f9ad": "Seehund", + "1f41f": "Fisch", + "1f420": "Tropenfisch", + "1f988": "Hai", + "1f419": "Oktopus", + "1f41a": "Schneckenhaus", + "1f40c": "Schnecke", + "1f98b": "Schmetterling", + "1f41b": "Raupe", + "1f41d": "Biene", + "1f41e": "Marienkäfer", + "1f490": "Blumenstrauß", + "1f339": "Rose", + "1f33a": "Hibiskus", + "1f33b": "Sonnenblume", + "1f337": "Tulpe", + "1f332": "Nadelbaum", + "1f333": "Laubbaum", + "1f334": "Palme", + "1f335": "Kaktus", + "1f33f": "Kräuter", + "1f341": "Ahornblatt", + "1f344": "Fliegenpilz", + "1f347": "Trauben", + "1f348": "Honigmelone", + "1f349": "Wassermelone", + "1f34a": "Mandarine", + "1f34b": "Zitrone", + "1f34c": "Banane", + "1f34d": "Ananas", + "1f96d": "Mango", + "1f34f": "grüner Apfel", + "1f350": "Birne", + "1f351": "Pfirsich", + "1f352": "Kirschen", + "1f353": "Erdbeere", + "1fad0": "Blaubeeren", + "1f95d": "Kiwi", + "1f345": "Tomate", + "1fad2": "Olive", + "1f965": "Kokosnuss", + "1f951": "Avocado", + "1f346": "Aubergine", + "1f955": "Karotte", + "1f33d": "Maiskolben", + "1f336": "Peperoni", + "1f96c": "Blattgemüse", + "1f966": "Brokkoli", + "1f9c5": "Zwiebel", + "1f95c": "Erdnuss", + "1f950": "Croissant", + "1f956": "Baguette", + "1f968": "Brezel", + "1f96f": "Bagel", + "1f95e": "Pfannkuchen", + "1f9c7": "Waffel", + "1f354": "Hamburger", + "1f355": "Pizza", + "1f32d": "Hotdog", + "1f32e": "Taco", + "1f37f": "Popcorn", + "1f980": "Krebs", + "1f99e": "Hummer", + "1f368": "Eiscreme", + "1f369": "Donut", + "1f36a": "Keks", + "1f382": "Geburtstagskuchen", + "1f9c1": "Cupcake", + "1f36b": "Schokoladentafel", + "1f36c": "Bonbon", + "1f36d": "Lutscher", + "1fad6": "Teekanne", + "1f9c3": "Trinkpäckchen", + "1f9c9": "Mate-Tee", + "1f9ed": "Kompass", + "1f3d4": "schneebedeckter Berg", + "1f30b": "Vulkan", + "1f3d5": "Camping", + "1f3dd": "einsame Insel", + "1f3e1": "Haus mit Garten", + "26f2": "Springbrunnen", + "1f3a0": "Karussellpferd", + "1f3a1": "Riesenrad", + "1f3a2": "Achterbahn", + "1f488": "Barbershop-Säule", + "1f686": "Zug", + "1f68b": "Straßenbahnwagen", + "1f68d": "Bus von vorne", + "1f695": "Taxi", + "1f697": "Auto", + "1f69a": "Lieferwagen", + "1f69c": "Traktor", + "1f6f5": "Motorroller", + "1f6fa": "Autorikscha", + "1f6f4": "Tretroller", + "1f6f9": "Skateboard", + "1f6fc": "Rollschuh", + "2693": "Anker", + "26f5": "Segelboot", + "1f6f6": "Kanu", + "1f6a4": "Schnellboot", + "1f6a2": "Schiff", + "2708": "Flugzeug", + "1f681": "Hubschrauber", + "1f6a0": "Bergschwebebahn", + "1f6f0": "Satellit", + "1f680": "Rakete", + "1f6f8": "fliegende Untertasse", + "23f0": "Wecker", + "1f319": "Mondsichel", + "1f321": "Thermometer", + "2600": "Sonne", + "1fa90": "Ringplanet", + "1f31f": "funkelnder Stern", + "1f300": "Wirbel", + "1f308": "Regenbogen", + "2602": "Regenschirm", + "2744": "Schneeflocke", + "2604": "Komet", + "1f525": "Feuer", + "1f4a7": "Tropfen", + "1f30a": "Welle", + "1f383": "Halloweenkürbis", + "2728": "funkelnde Sterne", + "1f388": "Luftballon", + "1f389": "Konfettibombe", + "1f38f": "traditionelle japanische Windsäcke", + "1f380": "pinke Schleife", + "1f381": "Geschenk", + "1f39f": "Eintrittskarten", + "1f3c6": "Pokal", + "26bd": "Fußball", + "1f3c0": "Basketball", + "1f3c8": "Football", + "1f3be": "Tennisball", + "1f94f": "Frisbee", + "1f3d3": "Tischtennis", + "1f3f8": "Badminton", + "1f93f": "Tauchmaske", + "1f94c": "Curlingstein", + "1f3af": "Darts", + "1fa80": "Jo-Jo", + "1fa81": "Drachen", + "1f52e": "Kristallkugel", + "1f3b2": "Spielwürfel", + "1f9e9": "Puzzleteil", + "1f3a8": "Mischpalette", + "1f9f5": "Faden", + "1f455": "T-Shirt", + "1f9e6": "Socken", + "1f457": "Kleid", + "1fa73": "Shorts", + "1f392": "Schulranzen", + "1f45f": "Sportschuh", + "1f451": "Krone", + "1f9e2": "Baseballmütze", + "1f484": "Lippenstift", + "1f48d": "Ring", + "1f48e": "Edelstein", + "1f4e2": "Lautsprecher", + "1f3b6": "Musiknoten", + "1f399": "Studiomikrofon", + "1f4fb": "Radio", + "1f3b7": "Saxofon", + "1fa97": "Akkordeon", + "1f3b8": "Gitarre", + "1f3ba": "Trompete", + "1f3bb": "Geige", + "1fa95": "Banjo", + "1f941": "Trommel", + "260e": "Telefon", + "1f50b": "Batterie", + "1f4bf": "CD", + "1f9ee": "Abakus", + "1f3ac": "Filmklappe", + "1f4a1": "Glühbirne", + "1f526": "Taschenlampe", + "1f3ee": "rote Papierlaterne", + "1f4d5": "geschlossenes Buch", + "1f3f7": "Etikett", + "1f4b3": "Kreditkarte", + "270f": "Bleistift", + "1f58c": "Pinsel", + "1f58d": "Wachsmalstift", + "1f4cc": "Reißzwecke", + "1f4ce": "Büroklammer", + "1f511": "Schlüssel", + "1fa83": "Bumerang", + "1f3f9": "Pfeil und Bogen", + "2696": "Waage", + "1f9f2": "Magnet", + "1f9ea": "Reagenzglas", + "1f9ec": "DNA", + "1f52c": "Mikroskop", + "1f52d": "Teleskop", + "1f4e1": "Satellitenschüssel", + "1fa91": "Stuhl", + "1f9f9": "Besen", + "1f5ff": "Statue" + }, + "el": { + "1f47d": "εξωγήινος", + "1f916": "ρομπότ", + "1f9e0": "μυαλό", + "1f441": "μάτι", + "1f9d9": "μάγος", + "1f9da": "νεράιδα", + "1f9dc": "γοργόνα", + "1f435": "πρόσωπο μαϊμούς", + "1f9a7": "ουρακοτάγκος", + "1f436": "πρόσωπο σκύλου", + "1f43a": "λύκος", + "1f98a": "αλεπού", + "1f99d": "ρακούν", + "1f431": "πρόσωπο γάτας", + "1f981": "λιοντάρι", + "1f42f": "πρόσωπο τίγρης", + "1f434": "πρόσωπο αλόγου", + "1f984": "μονόκερος", + "1f993": "ζέβρα", + "1f98c": "ελάφι", + "1f42e": "πρόσωπο αγελάδας", + "1f437": "πρόσωπο γουρουνιού", + "1f417": "αγριογούρουνο", + "1f42a": "καμήλα", + "1f999": "λάμα", + "1f992": "καμηλοπάρδαλη", + "1f418": "ελέφαντας", + "1f9a3": "μαμούθ", + "1f98f": "ρινόκερος", + "1f42d": "πρόσωπο ποντικιού", + "1f430": "πρόσωπο κουνελιού", + "1f43f": "σκιουράκι", + "1f994": "σκαντζόχοιρος", + "1f987": "νυχτερίδα", + "1f43b": "αρκούδα", + "1f428": "κοάλα", + "1f9a5": "βραδύπους", + "1f9a6": "βίδρα", + "1f998": "καγκουρό", + "1f425": "κοτοπουλάκι που κοιτά μπροστά", + "1f426": "πουλί", + "1f54a": "περιστέρι", + "1f986": "πάπια", + "1f989": "κουκουβάγια", + "1f9a4": "ντόντο", + "1fab6": "πούπουλο", + "1f9a9": "φλαμίνγκο", + "1f99a": "παγώνι", + "1f99c": "παπαγάλος", + "1f40a": "κροκόδειλος", + "1f422": "χελώνα", + "1f98e": "σαύρα", + "1f40d": "φίδι", + "1f432": "πρόσωπο δράκου", + "1f995": "σαυρόποδο", + "1f433": "φάλαινα που πετά νερό", + "1f42c": "δελφίνι", + "1f9ad": "φώκια", + "1f41f": "ψάρι", + "1f420": "τροπικό ψάρι", + "1f988": "καρχαρίας", + "1f419": "χταπόδι", + "1f41a": "σπειροειδές κοχύλι", + "1f40c": "σαλιγκάρι", + "1f98b": "πεταλούδα", + "1f41b": "κάμπια", + "1f41d": "μέλισσα", + "1f41e": "πασχαλίτσα", + "1f490": "μπουκέτο λουλούδια", + "1f339": "τριαντάφυλλο", + "1f33a": "ιβίσκος", + "1f33b": "ηλιοτρόπιο", + "1f337": "τουλίπα", + "1f332": "αειθαλές δέντρο", + "1f333": "φυλλοβόλο δέντρο", + "1f334": "φοινικόδεντρο", + "1f335": "κάκτος", + "1f33f": "βότανο", + "1f341": "φύλλο σφενδάμου", + "1f344": "μανιτάρι", + "1f347": "σταφύλι", + "1f348": "πεπόνι", + "1f349": "καρπούζι", + "1f34a": "μανταρίνι", + "1f34b": "λεμόνι", + "1f34c": "μπανάνα", + "1f34d": "ανανάς", + "1f96d": "μάνγκο", + "1f34f": "πράσινο μήλο", + "1f350": "αχλάδι", + "1f351": "ροδάκινο", + "1f352": "κεράσια", + "1f353": "φράουλα", + "1fad0": "μύρτιλο", + "1f95d": "ακτινίδιο", + "1f345": "ντομάτα", + "1fad2": "ελιά", + "1f965": "καρύδα", + "1f951": "αβοκάντο", + "1f346": "μελιτζάνα", + "1f955": "καρότο", + "1f33d": "καλαμπόκι", + "1f336": "καυτερή πιπεριά", + "1f96c": "πράσινο φυλλώδες", + "1f966": "μπρόκολο", + "1f9c5": "κρεμμύδι", + "1f95c": "φιστίκια", + "1f950": "κρουασάν", + "1f956": "μπαγκέτα", + "1f968": "πρέτσελ", + "1f96f": "μπέιγκελ", + "1f95e": "τηγανίτες", + "1f9c7": "βάφλα", + "1f354": "χάμπουργκερ", + "1f355": "πίτσα", + "1f32d": "χοτ ντογκ", + "1f32e": "τάκο", + "1f37f": "ποπ-κορν", + "1f980": "κάβουρας", + "1f99e": "αστακός", + "1f368": "παγωτό", + "1f369": "ντόνατ", + "1f36a": "μπισκότο", + "1f382": "τούρτα γενεθλίων", + "1f9c1": "κεκάκι", + "1f36b": "σοκολάτα", + "1f36c": "καραμέλα", + "1f36d": "γλειφιτζούρι", + "1fad6": "τσαγιέρα", + "1f9c3": "κουτί ροφήματος", + "1f9c9": "μάτε", + "1f9ed": "πυξίδα", + "1f3d4": "χιονισμένο βουνό", + "1f30b": "ηφαίστειο", + "1f3d5": "κατασκήνωση", + "1f3dd": "ερημονήσι", + "1f3e1": "σπίτι με κήπο", + "26f2": "σιντριβάνι", + "1f3a0": "αλογάκι καρουσέλ", + "1f3a1": "ρόδα λούνα-παρκ", + "1f3a2": "τρενάκι", + "1f488": "σύμβολο κουρείου", + "1f686": "τρένο", + "1f68b": "βαγόνι τραμ", + "1f68d": "διερχόμενο λεωφορείο", + "1f695": "ταξί", + "1f697": "αυτοκίνητο", + "1f69a": "φορτηγό", + "1f69c": "τρακτέρ", + "1f6f5": "σκουτεράκι", + "1f6fa": "ποδήλατο-ταξί", + "1f6f4": "πατίνι", + "1f6f9": "σκέιτμπορντ", + "1f6fc": "πατίνια", + "2693": "άγκυρα", + "26f5": "ιστιοφόρο", + "1f6f6": "κανό", + "1f6a4": "ταχύπλοο", + "1f6a2": "πλοίο", + "2708": "αεροπλάνο", + "1f681": "ελικόπτερο", + "1f6a0": "τελεφερίκ", + "1f6f0": "δορυφόρος", + "1f680": "πύραυλος", + "1f6f8": "ιπτάμενος δίσκος", + "23f0": "ξυπνητήρι", + "1f319": "ημισέληνος", + "1f321": "θερμόμετρο", + "2600": "ήλιος", + "1fa90": "πλανήτης με δακτύλιο", + "1f31f": "λαμπερό αστέρι", + "1f300": "κυκλώνας", + "1f308": "ουράνιο τόξο", + "2602": "ομπρέλα", + "2744": "χιονονιφάδα", + "2604": "κομήτης", + "1f525": "φωτιά", + "1f4a7": "σταγόνα", + "1f30a": "θαλάσσιο κύμα", + "1f383": "φανάρι από κολοκύθα", + "2728": "αστράκια", + "1f388": "μπαλόνι", + "1f389": "χαρτοπόλεμος", + "1f38f": "διακοσμητικοί κυπρίνοι", + "1f380": "κορδέλα", + "1f381": "τυλιγμένο δώρο", + "1f39f": "κάρτες εισόδου", + "1f3c6": "τρόπαιο", + "26bd": "μπάλα ποδοσφαίρου", + "1f3c0": "μπάλα μπάσκετ", + "1f3c8": "μπάλα αμερικάνικου ποδοσφαίρου", + "1f3be": "μπάλα τένις", + "1f94f": "φρίσμπι", + "1f3d3": "πινγκ πονγκ", + "1f3f8": "μπάντμιντον", + "1f93f": "μάσκα κατάδυσης", + "1f94c": "πέτρα κέρλινγκ", + "1f3af": "βελάκια", + "1fa80": "γιογιό", + "1fa81": "χαρταετός", + "1f52e": "κρυστάλλινη σφαίρα", + "1f3b2": "ζάρι", + "1f9e9": "κομμάτι παζλ", + "1f3a8": "παλέτα ζωγράφου", + "1f9f5": "κλωστή", + "1f455": "μπλουζάκι", + "1f9e6": "κάλτσες", + "1f457": "φόρεμα", + "1fa73": "σορτσάκι", + "1f392": "σχολική σάκα", + "1f45f": "αθλητικό παπούτσι", + "1f451": "στέμμα", + "1f9e2": "καπελάκι", + "1f484": "κραγιόν", + "1f48d": "δαχτυλίδι", + "1f48e": "διαμάντι", + "1f4e2": "ντουντούκα", + "1f3b6": "νότες μουσικής", + "1f399": "μικρόφωνο στούντιο", + "1f4fb": "ραδιόφωνο", + "1f3b7": "σαξόφωνο", + "1fa97": "ακορντεόν", + "1f3b8": "κιθάρα", + "1f3ba": "τρομπέτα", + "1f3bb": "βιολί", + "1fa95": "μπάντζο", + "1f941": "τύμπανο", + "260e": "τηλέφωνο", + "1f50b": "μπαταρία", + "1f4bf": "οπτικός δίσκος", + "1f9ee": "άβακας", + "1f3ac": "κλακέτα φιλμ", + "1f4a1": "λαμπτήρας", + "1f526": "φακός", + "1f3ee": "κόκκινο χάρτινο φανάρι", + "1f4d5": "κλειστό βιβλίο", + "1f3f7": "ετικέτα", + "1f4b3": "πιστωτική κάρτα", + "270f": "μολύβι", + "1f58c": "πινέλο", + "1f58d": "κηρομπογιά", + "1f4cc": "πινέζα", + "1f4ce": "συνδετήρας", + "1f511": "κλειδί", + "1fa83": "μπούμερανγκ", + "1f3f9": "τόξο και βέλος", + "2696": "ζυγαριά", + "1f9f2": "μαγνήτης", + "1f9ea": "δοκιμαστικός σωλήνας", + "1f9ec": "dna", + "1f52c": "μικροσκόπιο", + "1f52d": "τηλεσκόπιο", + "1f4e1": "δορυφορική κεραία", + "1fa91": "καρέκλα", + "1f9f9": "σκούπα", + "1f5ff": "μοάι" + }, + "en": { + "1f47d": "alien", + "1f916": "robot", + "1f9e0": "brain", + "1f441": "eye", + "1f9d9": "mage", + "1f9da": "fairy", + "1f9dc": "merperson", + "1f435": "monkey face", + "1f9a7": "orangutan", + "1f436": "dog face", + "1f43a": "wolf", + "1f98a": "fox", + "1f99d": "raccoon", + "1f431": "cat face", + "1f981": "lion", + "1f42f": "tiger face", + "1f434": "horse face", + "1f984": "unicorn", + "1f993": "zebra", + "1f98c": "deer", + "1f42e": "cow face", + "1f437": "pig face", + "1f417": "boar", + "1f42a": "camel", + "1f999": "llama", + "1f992": "giraffe", + "1f418": "elephant", + "1f9a3": "mammoth", + "1f98f": "rhinoceros", + "1f42d": "mouse face", + "1f430": "rabbit face", + "1f43f": "chipmunk", + "1f994": "hedgehog", + "1f987": "bat", + "1f43b": "bear", + "1f428": "koala", + "1f9a5": "sloth", + "1f9a6": "otter", + "1f998": "kangaroo", + "1f425": "front-facing baby chick", + "1f426": "bird", + "1f54a": "dove", + "1f986": "duck", + "1f989": "owl", + "1f9a4": "dodo", + "1fab6": "feather", + "1f9a9": "flamingo", + "1f99a": "peacock", + "1f99c": "parrot", + "1f40a": "crocodile", + "1f422": "turtle", + "1f98e": "lizard", + "1f40d": "snake", + "1f432": "dragon face", + "1f995": "sauropod", + "1f433": "spouting whale", + "1f42c": "dolphin", + "1f9ad": "seal", + "1f41f": "fish", + "1f420": "tropical fish", + "1f988": "shark", + "1f419": "octopus", + "1f41a": "spiral shell", + "1f40c": "snail", + "1f98b": "butterfly", + "1f41b": "bug", + "1f41d": "honeybee", + "1f41e": "lady beetle", + "1f490": "bouquet", + "1f339": "rose", + "1f33a": "hibiscus", + "1f33b": "sunflower", + "1f337": "tulip", + "1f332": "evergreen tree", + "1f333": "deciduous tree", + "1f334": "palm tree", + "1f335": "cactus", + "1f33f": "herb", + "1f341": "maple leaf", + "1f344": "mushroom", + "1f347": "grapes", + "1f348": "melon", + "1f349": "watermelon", + "1f34a": "tangerine", + "1f34b": "lemon", + "1f34c": "banana", + "1f34d": "pineapple", + "1f96d": "mango", + "1f34f": "green apple", + "1f350": "pear", + "1f351": "peach", + "1f352": "cherries", + "1f353": "strawberry", + "1fad0": "blueberries", + "1f95d": "kiwi fruit", + "1f345": "tomato", + "1fad2": "olive", + "1f965": "coconut", + "1f951": "avocado", + "1f346": "eggplant", + "1f955": "carrot", + "1f33d": "ear of corn", + "1f336": "hot pepper", + "1f96c": "leafy green", + "1f966": "broccoli", + "1f9c5": "onion", + "1f95c": "peanuts", + "1f950": "croissant", + "1f956": "baguette bread", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "pancakes", + "1f9c7": "waffle", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "crab", + "1f99e": "lobster", + "1f368": "ice cream", + "1f369": "doughnut", + "1f36a": "cookie", + "1f382": "birthday cake", + "1f9c1": "cupcake", + "1f36b": "chocolate bar", + "1f36c": "candy", + "1f36d": "lollipop", + "1fad6": "teapot", + "1f9c3": "beverage box", + "1f9c9": "mate", + "1f9ed": "compass", + "1f3d4": "snow-capped mountain", + "1f30b": "volcano", + "1f3d5": "camping", + "1f3dd": "desert island", + "1f3e1": "house with garden", + "26f2": "fountain", + "1f3a0": "carousel horse", + "1f3a1": "ferris wheel", + "1f3a2": "roller coaster", + "1f488": "barber pole", + "1f686": "train", + "1f68b": "tram car", + "1f68d": "oncoming bus", + "1f695": "taxi", + "1f697": "automobile", + "1f69a": "delivery truck", + "1f69c": "tractor", + "1f6f5": "motor scooter", + "1f6fa": "auto rickshaw", + "1f6f4": "kick scooter", + "1f6f9": "skateboard", + "1f6fc": "roller skate", + "2693": "anchor", + "26f5": "sailboat", + "1f6f6": "canoe", + "1f6a4": "speedboat", + "1f6a2": "ship", + "2708": "airplane", + "1f681": "helicopter", + "1f6a0": "mountain cableway", + "1f6f0": "satellite", + "1f680": "rocket", + "1f6f8": "flying saucer", + "23f0": "alarm clock", + "1f319": "crescent moon", + "1f321": "thermometer", + "2600": "sun", + "1fa90": "ringed planet", + "1f31f": "glowing star", + "1f300": "cyclone", + "1f308": "rainbow", + "2602": "umbrella", + "2744": "snowflake", + "2604": "comet", + "1f525": "fire", + "1f4a7": "droplet", + "1f30a": "water wave", + "1f383": "jack-o-lantern", + "2728": "sparkles", + "1f388": "balloon", + "1f389": "party popper", + "1f38f": "carp streamer", + "1f380": "ribbon", + "1f381": "wrapped gift", + "1f39f": "admission tickets", + "1f3c6": "trophy", + "26bd": "soccer ball", + "1f3c0": "basketball", + "1f3c8": "american football", + "1f3be": "tennis", + "1f94f": "flying disc", + "1f3d3": "ping pong", + "1f3f8": "badminton", + "1f93f": "diving mask", + "1f94c": "curling stone", + "1f3af": "bullseye", + "1fa80": "yo-yo", + "1fa81": "kite", + "1f52e": "crystal ball", + "1f3b2": "game die", + "1f9e9": "puzzle piece", + "1f3a8": "artist palette", + "1f9f5": "thread", + "1f455": "t-shirt", + "1f9e6": "socks", + "1f457": "dress", + "1fa73": "shorts", + "1f392": "backpack", + "1f45f": "running shoe", + "1f451": "crown", + "1f9e2": "billed cap", + "1f484": "lipstick", + "1f48d": "ring", + "1f48e": "gem stone", + "1f4e2": "loudspeaker", + "1f3b6": "musical notes", + "1f399": "studio microphone", + "1f4fb": "radio", + "1f3b7": "saxophone", + "1fa97": "accordion", + "1f3b8": "guitar", + "1f3ba": "trumpet", + "1f3bb": "violin", + "1fa95": "banjo", + "1f941": "drum", + "260e": "telephone", + "1f50b": "battery", + "1f4bf": "optical disk", + "1f9ee": "abacus", + "1f3ac": "clapper board", + "1f4a1": "light bulb", + "1f526": "flashlight", + "1f3ee": "red paper lantern", + "1f4d5": "closed book", + "1f3f7": "label", + "1f4b3": "credit card", + "270f": "pencil", + "1f58c": "paintbrush", + "1f58d": "crayon", + "1f4cc": "pushpin", + "1f4ce": "paperclip", + "1f511": "key", + "1fa83": "boomerang", + "1f3f9": "bow and arrow", + "2696": "balance scale", + "1f9f2": "magnet", + "1f9ea": "test tube", + "1f9ec": "dna", + "1f52c": "microscope", + "1f52d": "telescope", + "1f4e1": "satellite antenna", + "1fa91": "chair", + "1f9f9": "broom", + "1f5ff": "moai" + }, + "es": { + "1f47d": "alienígena", + "1f916": "robot", + "1f9e0": "cerebro", + "1f441": "ojo", + "1f9d9": "persona maga", + "1f9da": "hada", + "1f9dc": "persona sirena", + "1f435": "cara de mono", + "1f9a7": "orangután", + "1f436": "cara de perro", + "1f43a": "lobo", + "1f98a": "zorro", + "1f99d": "mapache", + "1f431": "cara de gato", + "1f981": "león", + "1f42f": "cara de tigre", + "1f434": "cara de caballo", + "1f984": "unicornio", + "1f993": "cebra", + "1f98c": "ciervo", + "1f42e": "cara de vaca", + "1f437": "cara de cerdo", + "1f417": "jabalí", + "1f42a": "dromedario", + "1f999": "llama", + "1f992": "jirafa", + "1f418": "elefante", + "1f9a3": "mamut", + "1f98f": "rinoceronte", + "1f42d": "cara de ratón", + "1f430": "cara de conejo", + "1f43f": "ardilla", + "1f994": "erizo", + "1f987": "murciélago", + "1f43b": "oso", + "1f428": "koala", + "1f9a5": "perezoso", + "1f9a6": "nutria", + "1f998": "canguro", + "1f425": "pollito de frente", + "1f426": "pájaro", + "1f54a": "paloma", + "1f986": "pato", + "1f989": "búho", + "1f9a4": "dodo", + "1fab6": "pluma", + "1f9a9": "flamenco", + "1f99a": "pavo real", + "1f99c": "loro", + "1f40a": "cocodrilo", + "1f422": "tortuga", + "1f98e": "lagarto", + "1f40d": "serpiente", + "1f432": "cara de dragón", + "1f995": "saurópodo", + "1f433": "ballena soltando un chorro", + "1f42c": "delfín", + "1f9ad": "foca", + "1f41f": "pez", + "1f420": "pez tropical", + "1f988": "tiburón", + "1f419": "pulpo", + "1f41a": "caracola", + "1f40c": "caracol", + "1f98b": "mariposa", + "1f41b": "bicho", + "1f41d": "abeja", + "1f41e": "mariquita", + "1f490": "ramo de flores", + "1f339": "rosa", + "1f33a": "flor de hibisco", + "1f33b": "girasol", + "1f337": "tulipán", + "1f332": "árbol de hoja perenne", + "1f333": "árbol de hoja caduca", + "1f334": "palmera", + "1f335": "cactus", + "1f33f": "hierba", + "1f341": "hoja de arce", + "1f344": "champiñón", + "1f347": "uvas", + "1f348": "melón", + "1f349": "sandía", + "1f34a": "mandarina", + "1f34b": "limón", + "1f34c": "plátano", + "1f34d": "piña", + "1f96d": "mango", + "1f34f": "manzana verde", + "1f350": "pera", + "1f351": "melocotón", + "1f352": "cerezas", + "1f353": "fresa", + "1fad0": "arándanos", + "1f95d": "kiwi", + "1f345": "tomate", + "1fad2": "aceituna", + "1f965": "coco", + "1f951": "aguacate", + "1f346": "berenjena", + "1f955": "zanahoria", + "1f33d": "espiga de maíz", + "1f336": "chile picante", + "1f96c": "verdura de hoja verde", + "1f966": "brócoli", + "1f9c5": "cebolla", + "1f95c": "cacahuetes", + "1f950": "cruasán", + "1f956": "baguete", + "1f968": "bretzel", + "1f96f": "bagel", + "1f95e": "tortitas", + "1f9c7": "gofre", + "1f354": "hamburguesa", + "1f355": "pizza", + "1f32d": "perrito caliente", + "1f32e": "taco", + "1f37f": "palomitas", + "1f980": "cangrejo", + "1f99e": "bogavante", + "1f368": "helado", + "1f369": "dónut", + "1f36a": "galleta", + "1f382": "tarta de cumpleaños", + "1f9c1": "magdalena", + "1f36b": "tableta de chocolate", + "1f36c": "caramelo", + "1f36d": "piruleta", + "1fad6": "tetera", + "1f9c3": "tetrabrik", + "1f9c9": "mate", + "1f9ed": "brújula", + "1f3d4": "montaña con nieve", + "1f30b": "volcán", + "1f3d5": "camping", + "1f3dd": "isla desierta", + "1f3e1": "casa con jardín", + "26f2": "fuente", + "1f3a0": "caballo de tiovivo", + "1f3a1": "noria de feria", + "1f3a2": "montaña rusa", + "1f488": "poste de barbero", + "1f686": "tren", + "1f68b": "vagón de tranvía", + "1f68d": "autobús próximo", + "1f695": "taxi", + "1f697": "coche", + "1f69a": "camión de reparto", + "1f69c": "tractor", + "1f6f5": "scooter", + "1f6fa": "mototaxi", + "1f6f4": "patinete", + "1f6f9": "monopatín", + "1f6fc": "patines", + "2693": "ancla", + "26f5": "velero", + "1f6f6": "canoa", + "1f6a4": "lancha motora", + "1f6a2": "barco", + "2708": "avión", + "1f681": "helicóptero", + "1f6a0": "teleférico de montaña", + "1f6f0": "satélite", + "1f680": "cohete", + "1f6f8": "platillo volante", + "23f0": "reloj despertador", + "1f319": "luna", + "1f321": "termómetro", + "2600": "sol", + "1fa90": "planeta con anillos", + "1f31f": "estrella brillante", + "1f300": "ciclón", + "1f308": "arcoíris", + "2602": "paraguas", + "2744": "copo de nieve", + "2604": "meteorito", + "1f525": "fuego", + "1f4a7": "gota", + "1f30a": "ola de mar", + "1f383": "calabaza de Halloween", + "2728": "chispas", + "1f388": "globo", + "1f389": "cañón de confeti", + "1f38f": "banderín de carpas", + "1f380": "lazo", + "1f381": "regalo", + "1f39f": "entradas", + "1f3c6": "trofeo", + "26bd": "balón de fútbol", + "1f3c0": "balón de baloncesto", + "1f3c8": "balón de fútbol americano", + "1f3be": "pelota de tenis", + "1f94f": "disco volador", + "1f3d3": "tenis de mesa", + "1f3f8": "bádminton", + "1f93f": "máscara de buceo", + "1f94c": "piedra de curling", + "1f3af": "diana", + "1fa80": "yoyó", + "1fa81": "cometa", + "1f52e": "bola de cristal", + "1f3b2": "dado", + "1f9e9": "pieza de puzle", + "1f3a8": "paleta de pintor", + "1f9f5": "hilo", + "1f455": "camiseta", + "1f9e6": "calcetines", + "1f457": "vestido", + "1fa73": "pantalones cortos", + "1f392": "mochila escolar", + "1f45f": "zapatilla deportiva", + "1f451": "corona", + "1f9e2": "gorra con visera", + "1f484": "pintalabios", + "1f48d": "anillo", + "1f48e": "piedra preciosa", + "1f4e2": "altavoz de mano", + "1f3b6": "notas musicales", + "1f399": "micrófono de estudio", + "1f4fb": "radio", + "1f3b7": "saxofón", + "1fa97": "acordeón", + "1f3b8": "guitarra", + "1f3ba": "trompeta", + "1f3bb": "violín", + "1fa95": "banjo", + "1f941": "tambor", + "260e": "teléfono", + "1f50b": "pila", + "1f4bf": "disco óptico", + "1f9ee": "ábaco", + "1f3ac": "claqueta", + "1f4a1": "bombilla", + "1f526": "linterna", + "1f3ee": "lámpara japonesa", + "1f4d5": "libro cerrado", + "1f3f7": "etiqueta", + "1f4b3": "tarjeta de crédito", + "270f": "lápiz", + "1f58c": "pincel", + "1f58d": "lápiz de cera", + "1f4cc": "chincheta", + "1f4ce": "clip", + "1f511": "llave", + "1fa83": "bumerán", + "1f3f9": "arco y flecha", + "2696": "balanza", + "1f9f2": "imán", + "1f9ea": "tubo de ensayo", + "1f9ec": "adn", + "1f52c": "microscopio", + "1f52d": "telescopio", + "1f4e1": "antena de satélite", + "1fa91": "silla", + "1f9f9": "escoba", + "1f5ff": "estatua moái" + }, + "fa": { + "1f47d": "موجود فضایی", + "1f916": "روبات", + "1f9e0": "مغز", + "1f441": "چشم", + "1f9d9": "ساحر", + "1f9da": "پری", + "1f9dc": "دریامردمان", + "1f435": "صورت میمون", + "1f9a7": "اورانگوتان", + "1f436": "صورت سگ", + "1f43a": "گرگ", + "1f98a": "روباه", + "1f99d": "راکون", + "1f431": "صورت گربه", + "1f981": "شیر", + "1f42f": "صورت ببر", + "1f434": "صورت اسب", + "1f984": "تکشاخ", + "1f993": "گورخر", + "1f98c": "گوزن", + "1f42e": "صورت گاو", + "1f437": "صورت خوک", + "1f417": "گراز نر", + "1f42a": "شتر", + "1f999": "لاما", + "1f992": "زرافه", + "1f418": "فیل", + "1f9a3": "ماموت", + "1f98f": "کرگدن", + "1f42d": "صورت موش", + "1f430": "صورت خرگوش", + "1f43f": "سنجاب راهراه", + "1f994": "جوجهتیغی", + "1f987": "خفاش", + "1f43b": "خرس", + "1f428": "کوآلا", + "1f9a5": "تنبل", + "1f9a6": "سمور آبی", + "1f998": "کانگورو", + "1f425": "جوجه از روبرو", + "1f426": "پرنده", + "1f54a": "کبوتر", + "1f986": "مرغابی", + "1f989": "جغد", + "1f9a4": "دودو", + "1fab6": "پَر", + "1f9a9": "فلامینگو", + "1f99a": "طاووس", + "1f99c": "طوطی", + "1f40a": "تمساح", + "1f422": "لاکپشت", + "1f98e": "مارمولک", + "1f40d": "مار", + "1f432": "صورت اژدها", + "1f995": "سوسمار", + "1f433": "نهنگ در حال آبفشانی", + "1f42c": "دلفین", + "1f9ad": "فُک", + "1f41f": "ماهی", + "1f420": "ماهی استوایی", + "1f988": "کوسه", + "1f419": "هشتپا", + "1f41a": "صدف مارپیچی", + "1f40c": "حلزون", + "1f98b": "پروانه", + "1f41b": "حشره", + "1f41d": "زنبور عسل", + "1f41e": "کفشدوزک", + "1f490": "دسته گل", + "1f339": "رز", + "1f33a": "گل ختمی", + "1f33b": "گل آفتابگردان", + "1f337": "لاله", + "1f332": "همیشهسبز", + "1f333": "درخت سبز", + "1f334": "نخل", + "1f335": "کاکتوس", + "1f33f": "گیاه دارویی", + "1f341": "برگ افرا", + "1f344": "قارچ", + "1f347": "انگور", + "1f348": "طالبی", + "1f349": "هندوانه", + "1f34a": "نارنگی", + "1f34b": "لیمو ترش", + "1f34c": "موز", + "1f34d": "آناناس", + "1f96d": "انبه", + "1f34f": "سیب سبز", + "1f350": "گلابی", + "1f351": "هلو", + "1f352": "گیلاس", + "1f353": "توتفرنگی", + "1fad0": "توت آبی", + "1f95d": "کیوی", + "1f345": "گوجهفرنگی", + "1fad2": "زیتون", + "1f965": "نارگیل", + "1f951": "آووکادو", + "1f346": "بادمجان", + "1f955": "هویج", + "1f33d": "بلال ذرت", + "1f336": "فلفل قرمز", + "1f96c": "برگسبز", + "1f966": "بروکلی", + "1f9c5": "پیاز", + "1f95c": "بادام زمینی", + "1f950": "کرواسان", + "1f956": "نان باگت", + "1f968": "چوبشور", + "1f96f": "نان بیگل", + "1f95e": "پنکیک", + "1f9c7": "وافل", + "1f354": "همبرگر", + "1f355": "پیتزا", + "1f32d": "هات داگ", + "1f32e": "تاکو", + "1f37f": "ذرت بوداده", + "1f980": "خرچنگ", + "1f99e": "لابستر", + "1f368": "بستنی", + "1f369": "دونات", + "1f36a": "کلوچه", + "1f382": "کیک تولد", + "1f9c1": "کیک فنجانی", + "1f36b": "تخته شکلات", + "1f36c": "آبنبات", + "1f36d": "آبنباتچوبی", + "1fad6": "قوری", + "1f9c3": "پاکت نوشیدنی", + "1f9c9": "ماته", + "1f9ed": "قطبنما", + "1f3d4": "قلهٔ برفی", + "1f30b": "آتشفشان", + "1f3d5": "چادرزنی", + "1f3dd": "جزیرهٔ خالی از سکنه", + "1f3e1": "خانهٔ حیاطدار", + "26f2": "فواره", + "1f3a0": "چرخوفلک اسبی", + "1f3a1": "چرخوفلک", + "1f3a2": "ترن هوایی", + "1f488": "چراغ سلمانی", + "1f686": "قطار", + "1f68b": "قطار خیابانی", + "1f68d": "اتوبوس روبهجلو", + "1f695": "تاکسی", + "1f697": "خودرو", + "1f69a": "کامیون پخش", + "1f69c": "تراکتور", + "1f6f5": "اسکوتر", + "1f6fa": "اتوریکشا", + "1f6f4": "چرخ پایی", + "1f6f9": "تختهٔ اسکیت", + "1f6fc": "کفش اسکیت", + "2693": "لنگر", + "26f5": "قایق بادبانی", + "1f6f6": "بلم", + "1f6a4": "قایق تندرو", + "1f6a2": "کشتی", + "2708": "هواپیما", + "1f681": "هلیکوپتر", + "1f6a0": "تلهکابین کوهستانی", + "1f6f0": "ماهواره", + "1f680": "موشک", + "1f6f8": "بشقابپرنده", + "23f0": "ساعت رومیزی", + "1f319": "هلال ماه", + "1f321": "دماسنج", + "2600": "خورشید", + "1fa90": "سیاره حلقهدار", + "1f31f": "ستاره درخشان", + "1f300": "چرخند", + "1f308": "رنگین کمان", + "2602": "چتر", + "2744": "برفدانه", + "2604": "ستاره دنبالهدار", + "1f525": "آتش", + "1f4a7": "قطره", + "1f30a": "موج آب", + "1f383": "فانوس کدو تنبل", + "2728": "درخشش", + "1f388": "بادکنک", + "1f389": "بمب کاغذ رنگی", + "1f38f": "پرچمهای ماهی در باد", + "1f380": "روبان", + "1f381": "هدیهٔ کادوشده", + "1f39f": "بلیت ورود", + "1f3c6": "جام ورزشی", + "26bd": "توپ فوتبال", + "1f3c0": "بسکتبال", + "1f3c8": "فوتبال امریکایی", + "1f3be": "تنیس", + "1f94f": "فریزبی", + "1f3d3": "پینگپونگ", + "1f3f8": "بدمینتون", + "1f93f": "ماسک غواصی", + "1f94c": "سنگ کرلینگ", + "1f3af": "پیکان در قلب هدف", + "1fa80": "یویو", + "1fa81": "بادبادک", + "1f52e": "گوی", + "1f3b2": "تاس بازی", + "1f9e9": "قطعه پازل", + "1f3a8": "پالت نقاشی", + "1f9f5": "نخ", + "1f455": "تیشرت", + "1f9e6": "جوراب", + "1f457": "پیراهن زنانه", + "1fa73": "شلوارک", + "1f392": "کولهپشتی", + "1f45f": "کفش دویدن", + "1f451": "تاج", + "1f9e2": "کلاه لبهدار", + "1f484": "رژلب", + "1f48d": "حلقه", + "1f48e": "جواهر", + "1f4e2": "بلندگو", + "1f3b6": "نتهای موسیقی", + "1f399": "میکروفون استودیویی", + "1f4fb": "رادیو", + "1f3b7": "ساکسیفون", + "1fa97": "آکوردئون", + "1f3b8": "گیتار", + "1f3ba": "ترومپت", + "1f3bb": "ویولن", + "1fa95": "بانجو", + "1f941": "طبل", + "260e": "تلفن", + "1f50b": "باتری", + "1f4bf": "سیدی", + "1f9ee": "چرتکه", + "1f3ac": "کلاکت", + "1f4a1": "لامپ", + "1f526": "چراغقوه", + "1f3ee": "فانوس کاغذی قرمز", + "1f4d5": "کتاب بسته", + "1f3f7": "برچسب", + "1f4b3": "کارت اعتباری", + "270f": "مداد", + "1f58c": "قلممو", + "1f58d": "مدادشمعی", + "1f4cc": "سنجاق", + "1f4ce": "گیرهٔ کاغذ", + "1f511": "کلید", + "1fa83": "بومرنگ", + "1f3f9": "تیر و کمان", + "2696": "ترازو", + "1f9f2": "آهنربا", + "1f9ea": "لولهٔ آزمایشگاه", + "1f9ec": "دیانای", + "1f52c": "میکروسکوپ", + "1f52d": "تلسکوپ", + "1f4e1": "آنتن ماهواره", + "1fa91": "صندلی", + "1f9f9": "جارو", + "1f5ff": "سردیس موآی" + }, + "fi": { + "1f47d": "avaruusolio", + "1f916": "robotti", + "1f9e0": "aivot", + "1f441": "silmä", + "1f9d9": "velho", + "1f9da": "keiju", + "1f9dc": "merenväki", + "1f435": "apinan naama", + "1f9a7": "oranki", + "1f436": "koiran naama", + "1f43a": "susi", + "1f98a": "kettu", + "1f99d": "pesukarhu", + "1f431": "kissan naama", + "1f981": "leijona", + "1f42f": "tiikerin naama", + "1f434": "hevosen naama", + "1f984": "yksisarvinen", + "1f993": "seepra", + "1f98c": "peura", + "1f42e": "lehmän naama", + "1f437": "sian naama", + "1f417": "villisika", + "1f42a": "kameli", + "1f999": "laama", + "1f992": "kirahvi", + "1f418": "elefantti", + "1f9a3": "mammutti", + "1f98f": "sarvikuono", + "1f42d": "hiiren naama", + "1f430": "jäniksen naama", + "1f43f": "maaorava", + "1f994": "siili", + "1f987": "lepakko", + "1f43b": "karhu", + "1f428": "koala", + "1f9a5": "laiskiainen", + "1f9a6": "saukko", + "1f998": "kenguru", + "1f425": "tipu edestäpäin", + "1f426": "lintu", + "1f54a": "kyyhky", + "1f986": "sorsa", + "1f989": "pöllö", + "1f9a4": "dodo", + "1fab6": "höyhen", + "1f9a9": "flamingo", + "1f99a": "riikinkukko", + "1f99c": "papukaija", + "1f40a": "krokotiili", + "1f422": "kilpikonna", + "1f98e": "lisko", + "1f40d": "käärme", + "1f432": "lohikäärmeen naama", + "1f995": "sauropodi", + "1f433": "suihkuttava valas", + "1f42c": "delfiini", + "1f9ad": "hylje", + "1f41f": "kala", + "1f420": "trooppinen kala", + "1f988": "hai", + "1f419": "mustekala", + "1f41a": "kotilo", + "1f40c": "etana", + "1f98b": "perhonen", + "1f41b": "ötökkä", + "1f41d": "mehiläinen", + "1f41e": "leppäkerttu", + "1f490": "kukkakimppu", + "1f339": "ruusu", + "1f33a": "kiinanruusu", + "1f33b": "auringonkukka", + "1f337": "tulppaani", + "1f332": "ikivihreä", + "1f333": "lehtipuu", + "1f334": "palmu", + "1f335": "kaktus", + "1f33f": "yrtti", + "1f341": "vaahteranlehti", + "1f344": "sieni", + "1f347": "viinirypäleet", + "1f348": "meloni", + "1f349": "vesimeloni", + "1f34a": "mandariini", + "1f34b": "sitruuna", + "1f34c": "banaani", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "vihreä omena", + "1f350": "päärynä", + "1f351": "persikka", + "1f352": "kirsikat", + "1f353": "mansikka", + "1fad0": "mustikat", + "1f95d": "kiivi", + "1f345": "tomaatti", + "1fad2": "oliivi", + "1f965": "kookospähkinä", + "1f951": "avokado", + "1f346": "munakoiso", + "1f955": "porkkana", + "1f33d": "maissintähkä", + "1f336": "jalapeno", + "1f96c": "lehtivihannes", + "1f966": "parsakaali", + "1f9c5": "sipuli", + "1f95c": "maapähkinä", + "1f950": "voisarvi", + "1f956": "patonki", + "1f968": "rinkilä", + "1f96f": "vesirinkeli", + "1f95e": "letut", + "1f9c7": "vohveli", + "1f354": "hampurilainen", + "1f355": "pizza", + "1f32d": "hodari", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "rapu", + "1f99e": "hummeri", + "1f368": "jäätelö", + "1f369": "donitsi", + "1f36a": "keksi", + "1f382": "syntymäpäiväkakku", + "1f9c1": "vuokaleivos", + "1f36b": "suklaapatukka", + "1f36c": "karkki", + "1f36d": "tikkari", + "1fad6": "teepannu", + "1f9c3": "juomatetra", + "1f9c9": "mate", + "1f9ed": "kompassi", + "1f3d4": "lumihuippuinen vuori", + "1f30b": "tulivuori", + "1f3d5": "telttailu", + "1f3dd": "autiosaari", + "1f3e1": "talo ja puutarha", + "26f2": "suihkulähde", + "1f3a0": "karusellihevonen", + "1f3a1": "maailmanpyörä", + "1f3a2": "vuoristorata", + "1f488": "punasiniraitainen pylväs", + "1f686": "juna", + "1f68b": "raitiovaunu", + "1f68d": "saapuva bussi", + "1f695": "taksi", + "1f697": "auto", + "1f69a": "kuljetusauto", + "1f69c": "traktori", + "1f6f5": "skootteri", + "1f6fa": "autorikša", + "1f6f4": "potkulauta", + "1f6f9": "rullalauta", + "1f6fc": "rullaluistin", + "2693": "ankkuri", + "26f5": "purjevene", + "1f6f6": "kanootti", + "1f6a4": "pikavene", + "1f6a2": "laiva", + "2708": "lentokone", + "1f681": "helikopteri", + "1f6a0": "gondolihissi", + "1f6f0": "satelliitti", + "1f680": "raketti", + "1f6f8": "lentävä lautanen", + "23f0": "herätyskello", + "1f319": "kuunsirppi", + "1f321": "lämpömittari", + "2600": "aurinko", + "1fa90": "rengasplaneetta", + "1f31f": "loistava tähti", + "1f300": "pyörremyrsky", + "1f308": "sateenkaari", + "2602": "sateenvarjo", + "2744": "lumihiutale", + "2604": "komeetta", + "1f525": "tuli", + "1f4a7": "pisara", + "1f30a": "aalto", + "1f383": "kurpitsalyhty", + "2728": "säihke", + "1f388": "ilmapallo", + "1f389": "paukkuserpentiini", + "1f38f": "karppiviiri", + "1f380": "rusetti", + "1f381": "lahjapaketti", + "1f39f": "pääsylippu", + "1f3c6": "pokaali", + "26bd": "jalkapallo", + "1f3c0": "koripallo", + "1f3c8": "amerikkalainen jalkapallo", + "1f3be": "tennis", + "1f94f": "liitokiekko", + "1f3d3": "pingis", + "1f3f8": "sulkapallo", + "1f93f": "sukellusmaski", + "1f94c": "curling-kivi", + "1f3af": "napakymppi", + "1fa80": "jojo", + "1fa81": "leija", + "1f52e": "kristallipallo", + "1f3b2": "noppa", + "1f9e9": "palapeli", + "1f3a8": "taiteilijan paletti", + "1f9f5": "lankarulla", + "1f455": "t-paita", + "1f9e6": "sukat", + "1f457": "mekko", + "1fa73": "uimashortsit", + "1f392": "koulureppu", + "1f45f": "juoksukenkä", + "1f451": "kruunu", + "1f9e2": "lippalakki", + "1f484": "huulipuna", + "1f48d": "sormus", + "1f48e": "jalokivi", + "1f4e2": "kovaääninen", + "1f3b6": "nuotteja", + "1f399": "studiomikrofoni", + "1f4fb": "radio", + "1f3b7": "saksofoni", + "1fa97": "harmonikka", + "1f3b8": "kitara", + "1f3ba": "trumpetti", + "1f3bb": "viulu", + "1fa95": "banjo", + "1f941": "rumpu", + "260e": "puhelin", + "1f50b": "akku", + "1f4bf": "CD", + "1f9ee": "helmitaulu", + "1f3ac": "klaffitaulu", + "1f4a1": "hehkulamppu", + "1f526": "taskulamppu", + "1f3ee": "punainen paperilyhty", + "1f4d5": "suljettu kirja", + "1f3f7": "lappu", + "1f4b3": "luottokortti", + "270f": "lyijykynä", + "1f58c": "sivellin", + "1f58d": "väriliitu", + "1f4cc": "nuppineula", + "1f4ce": "paperiliitin", + "1f511": "avain", + "1fa83": "bumerangi", + "1f3f9": "jousi ja nuoli", + "2696": "vaaka", + "1f9f2": "magneetti", + "1f9ea": "koeputki", + "1f9ec": "dna", + "1f52c": "mikroskooppi", + "1f52d": "kaukoputki", + "1f4e1": "lautasantenni", + "1fa91": "tuoli", + "1f9f9": "luuta", + "1f5ff": "moai" + }, + "fr": { + "1f47d": "alien", + "1f916": "robot", + "1f9e0": "cerveau", + "1f441": "œil", + "1f9d9": "mage", + "1f9da": "personnage féérique", + "1f9dc": "créature aquatique", + "1f435": "tête de singe", + "1f9a7": "orang-outan", + "1f436": "tête de chien", + "1f43a": "loup", + "1f98a": "renard", + "1f99d": "raton laveur", + "1f431": "tête de chat", + "1f981": "tête de lion", + "1f42f": "tête de tigre", + "1f434": "tête de cheval", + "1f984": "licorne", + "1f993": "zèbre", + "1f98c": "cerf", + "1f42e": "tête de vache", + "1f437": "tête de cochon", + "1f417": "sanglier", + "1f42a": "dromadaire", + "1f999": "lama", + "1f992": "girafe", + "1f418": "éléphant", + "1f9a3": "mammouth", + "1f98f": "rhinocéros", + "1f42d": "tête de souris", + "1f430": "tête de lapin", + "1f43f": "écureuil", + "1f994": "hérisson", + "1f987": "chauve-souris", + "1f43b": "ours", + "1f428": "koala", + "1f9a5": "paresseux", + "1f9a6": "loutre", + "1f998": "kangourou", + "1f425": "poussin de face", + "1f426": "oiseau", + "1f54a": "colombe", + "1f986": "canard", + "1f989": "chouette", + "1f9a4": "dodo", + "1fab6": "plume", + "1f9a9": "flamant", + "1f99a": "paon", + "1f99c": "perroquet", + "1f40a": "crocodile", + "1f422": "tortue", + "1f98e": "lézard", + "1f40d": "serpent", + "1f432": "tête de dragon", + "1f995": "sauropode", + "1f433": "baleine soufflant par son évent", + "1f42c": "dauphin", + "1f9ad": "phoque", + "1f41f": "poisson", + "1f420": "poisson tropical", + "1f988": "requin", + "1f419": "pieuvre", + "1f41a": "coquille en spirale", + "1f40c": "escargot", + "1f98b": "papillon", + "1f41b": "chenille", + "1f41d": "abeille", + "1f41e": "coccinelle", + "1f490": "bouquet", + "1f339": "rose", + "1f33a": "hibiscus", + "1f33b": "tournesol", + "1f337": "tulipe", + "1f332": "conifère", + "1f333": "arbre à feuilles caduques", + "1f334": "palmier", + "1f335": "cactus", + "1f33f": "feuille", + "1f341": "feuille d’érable", + "1f344": "champignon", + "1f347": "raisin", + "1f348": "melon", + "1f349": "pastèque", + "1f34a": "mandarine", + "1f34b": "citron", + "1f34c": "banane", + "1f34d": "ananas", + "1f96d": "mangue", + "1f34f": "pomme verte", + "1f350": "poire", + "1f351": "pêche", + "1f352": "cerises", + "1f353": "fraise", + "1fad0": "myrtilles", + "1f95d": "kiwi", + "1f345": "tomate", + "1fad2": "olive", + "1f965": "noix de coco", + "1f951": "avocat", + "1f346": "aubergine", + "1f955": "carotte", + "1f33d": "épi de maïs", + "1f336": "piment rouge", + "1f96c": "légume à feuilles vertes", + "1f966": "brocoli", + "1f9c5": "oignon", + "1f95c": "cacahuètes", + "1f950": "croissant", + "1f956": "baguette", + "1f968": "bretzel", + "1f96f": "bagel", + "1f95e": "pancakes", + "1f9c7": "gaufre", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "pop-corn", + "1f980": "crabe", + "1f99e": "homard", + "1f368": "glace", + "1f369": "doughnut", + "1f36a": "cookie", + "1f382": "gâteau d’anniversaire", + "1f9c1": "cupcake", + "1f36b": "barre chocolatée", + "1f36c": "bonbon", + "1f36d": "sucette", + "1fad6": "théière", + "1f9c3": "briquette de jus", + "1f9c9": "maté", + "1f9ed": "boussole", + "1f3d4": "montagne enneigée", + "1f30b": "volcan", + "1f3d5": "camping", + "1f3dd": "île déserte", + "1f3e1": "maison avec jardin", + "26f2": "fontaine", + "1f3a0": "cheval de manège", + "1f3a1": "grande roue", + "1f3a2": "montagnes russes", + "1f488": "enseigne de barbier", + "1f686": "train", + "1f68b": "wagon de tramway", + "1f68d": "bus de face", + "1f695": "taxi", + "1f697": "voiture", + "1f69a": "camion de livraison", + "1f69c": "tracteur", + "1f6f5": "scooter", + "1f6fa": "tuk tuk", + "1f6f4": "trottinette", + "1f6f9": "planche à roulettes", + "1f6fc": "patin à roulettes", + "2693": "ancre", + "26f5": "voilier", + "1f6f6": "canoë", + "1f6a4": "hors-bord", + "1f6a2": "navire", + "2708": "avion", + "1f681": "hélicoptère", + "1f6a0": "téléphérique", + "1f6f0": "satellite", + "1f680": "fusée", + "1f6f8": "soucoupe volante", + "23f0": "réveil", + "1f319": "croissant de lune", + "1f321": "thermomètre", + "2600": "soleil", + "1fa90": "planète à anneaux", + "1f31f": "étoile brillante", + "1f300": "cyclone", + "1f308": "arc-en-ciel", + "2602": "parapluie ouvert", + "2744": "flocon", + "2604": "comète", + "1f525": "feu", + "1f4a7": "goutte d’eau", + "1f30a": "vague", + "1f383": "citrouille", + "2728": "étincelles", + "1f388": "ballon gonflable", + "1f389": "cotillons", + "1f38f": "koinobori", + "1f380": "ruban", + "1f381": "cadeau", + "1f39f": "billet d’entrée", + "1f3c6": "trophée", + "26bd": "ballon de football", + "1f3c0": "basket", + "1f3c8": "football américain", + "1f3be": "tennis", + "1f94f": "disque volant", + "1f3d3": "ping-pong", + "1f3f8": "badminton", + "1f93f": "masque de plongée", + "1f94c": "pierre de curling", + "1f3af": "dans le mille", + "1fa80": "yoyo", + "1fa81": "cerf-volant", + "1f52e": "boule de cristal", + "1f3b2": "dés", + "1f9e9": "pièce de puzzle", + "1f3a8": "palette de peinture", + "1f9f5": "bobine de fil", + "1f455": "T-shirt", + "1f9e6": "chaussettes", + "1f457": "robe", + "1fa73": "short", + "1f392": "cartable", + "1f45f": "chaussure de sport", + "1f451": "couronne", + "1f9e2": "casquette américaine", + "1f484": "rouge à lèvres", + "1f48d": "bague", + "1f48e": "pierre précieuse", + "1f4e2": "haut-parleur", + "1f3b6": "notes de musique", + "1f399": "micro de studio", + "1f4fb": "radio", + "1f3b7": "saxophone", + "1fa97": "accordéon", + "1f3b8": "guitare", + "1f3ba": "trompette", + "1f3bb": "violon", + "1fa95": "banjo", + "1f941": "batterie", + "260e": "téléphone", + "1f50b": "pile", + "1f4bf": "CD", + "1f9ee": "abaque", + "1f3ac": "clap", + "1f4a1": "ampoule", + "1f526": "torche", + "1f3ee": "lampion rouge", + "1f4d5": "livre fermé", + "1f3f7": "étiquette", + "1f4b3": "carte bancaire", + "270f": "crayon", + "1f58c": "pinceau", + "1f58d": "crayon pastel", + "1f4cc": "punaise", + "1f4ce": "trombone", + "1f511": "clé", + "1fa83": "boomerang", + "1f3f9": "arc et flèche", + "2696": "balance à poids", + "1f9f2": "aimant", + "1f9ea": "tube à essai", + "1f9ec": "adn", + "1f52c": "microscope", + "1f52d": "télescope", + "1f4e1": "antenne satellite", + "1fa91": "chaise", + "1f9f9": "balai", + "1f5ff": "moai" + }, + "ga": { + "1f47d": "eachtrán", + "1f916": "róbat", + "1f9e0": "inchinn", + "1f441": "súil", + "1f9d9": "duine draíochta", + "1f9da": "síog", + "1f9dc": "duine murúch", + "1f435": "aghaidh moncaí", + "1f9a7": "órang-útan", + "1f436": "aghaidh madra", + "1f43a": "aghaidh mic tíre", + "1f98a": "aghaidh sionnaigh", + "1f99d": "racún", + "1f431": "aghaidh cait", + "1f981": "aghaidh leoin", + "1f42f": "aghaidh tíogair", + "1f434": "aghaidh capaill", + "1f984": "aghaidh aonbheannaigh", + "1f993": "séabra", + "1f98c": "fia", + "1f42e": "aghaidh bó", + "1f437": "aghaidh muice", + "1f417": "torc", + "1f42a": "camall", + "1f999": "láma", + "1f992": "sioráf", + "1f418": "eilifint", + "1f9a3": "mamat", + "1f98f": "srónbheannach", + "1f42d": "aghaidh luiche", + "1f430": "aghaidh coinín", + "1f43f": "iora talún", + "1f994": "gráinneog", + "1f987": "ialtóg", + "1f43b": "aghaidh béair", + "1f428": "cóála", + "1f9a5": "spadán", + "1f9a6": "madra uisce", + "1f998": "cangarú", + "1f425": "gearrshicín éadain", + "1f426": "éan", + "1f54a": "colm", + "1f986": "lacha", + "1f989": "ulchabhán", + "1f9a4": "dódó", + "1fab6": "cleite", + "1f9a9": "lasairéan", + "1f99a": "péacóg", + "1f99c": "pearóid", + "1f40a": "crogall", + "1f422": "turtar", + "1f98e": "earc luachra", + "1f40d": "nathair", + "1f432": "aghaidh dragain", + "1f995": "sárapód", + "1f433": "míol mór ag séideadh", + "1f42c": "deilf", + "1f9ad": "rón", + "1f41f": "iasc", + "1f420": "iasc teochreasa", + "1f988": "siorc", + "1f419": "ochtapas", + "1f41a": "sliogán", + "1f40c": "seilide", + "1f98b": "féileacán", + "1f41b": "míol", + "1f41d": "beach mheala", + "1f41e": "bóín", + "1f490": "crobhaing bláthanna", + "1f339": "rós", + "1f33a": "roiseog", + "1f33b": "lus na gréine", + "1f337": "tiúilip", + "1f332": "crann síorghlas", + "1f333": "crann duillsilteach", + "1f334": "pailm", + "1f335": "cachtas", + "1f33f": "luibh", + "1f341": "duilleog mhailpe", + "1f344": "beacán", + "1f347": "caora fíniúna", + "1f348": "mealbhacán", + "1f349": "mealbhacán uisce", + "1f34a": "táinséirín", + "1f34b": "líomóid", + "1f34c": "banana", + "1f34d": "anann", + "1f96d": "mangó", + "1f34f": "úll glas", + "1f350": "piorra", + "1f351": "péitseog", + "1f352": "silíní", + "1f353": "sú talún", + "1fad0": "fraochán", + "1f95d": "cíobhaí", + "1f345": "tráta", + "1fad2": "ológ", + "1f965": "cnó cócó", + "1f951": "abhacád", + "1f346": "ubhthoradh", + "1f955": "meacan dearg", + "1f33d": "dias arbhair", + "1f336": "píobar te", + "1f96c": "glasra duilleach", + "1f966": "brocailí", + "1f9c5": "oiniún", + "1f95c": "pis talún", + "1f950": "croissant", + "1f956": "baguette", + "1f968": "preatsal", + "1f96f": "béigeal", + "1f95e": "pancóga", + "1f9c7": "vaifeal", + "1f354": "burgar", + "1f355": "píotsa", + "1f32d": "brocaire te", + "1f32e": "taco", + "1f37f": "grán rósta", + "1f980": "portán", + "1f99e": "gliomach", + "1f368": "uachtar reoite", + "1f369": "taoschnó", + "1f36a": "briosca", + "1f382": "cáca breithe", + "1f9c1": "cístín cupa", + "1f36b": "seacláid", + "1f36c": "milseán", + "1f36d": "líreacán", + "1fad6": "taephota", + "1f9c3": "bosca dí", + "1f9c9": "maité", + "1f9ed": "compás", + "1f3d4": "sliabh le sneachta", + "1f30b": "bolcán", + "1f3d5": "ag campáil", + "1f3dd": "oileán díthreibhe", + "1f3e1": "teach le gairdín", + "26f2": "scairdeán", + "1f3a0": "capall an roithleagáin ró", + "1f3a1": "roth Ferris", + "1f3a2": "rollchóstóir", + "1f488": "cuaille bearbóra", + "1f686": "traein", + "1f68b": "carráiste tram", + "1f68d": "bus atá ag teacht", + "1f695": "tacsaí", + "1f697": "gluaisteán", + "1f69a": "trucail seachadta", + "1f69c": "tarracóir", + "1f6f5": "scútar", + "1f6fa": "ricseá uathoibríoch", + "1f6f4": "scútar gan inneall", + "1f6f9": "clár scátála", + "1f6fc": "scáta rothach", + "2693": "ancaire", + "26f5": "bád seoil", + "1f6f6": "canú", + "1f6a4": "luasbhád", + "1f6a2": "long", + "2708": "eitleán", + "1f681": "héileacaptar", + "1f6a0": "cáblabhealach sléibhe", + "1f6f0": "satailít", + "1f680": "roicéad", + "1f6f8": "sásar eitilte", + "23f0": "clog aláraim", + "1f319": "corrán gealaí", + "1f321": "teirmiméadar", + "2600": "grian", + "1fa90": "pláinéad le fáinne", + "1f31f": "réalta ag lonrú", + "1f300": "cioclón", + "1f308": "bogha báistí", + "2602": "scáth báistí", + "2744": "calóg shneachta", + "2604": "cóiméad", + "1f525": "tine", + "1f4a7": "braoinín", + "1f30a": "tonn san uisce", + "1f383": "Seán na gealaí", + "2728": "drithlí", + "1f388": "balún", + "1f389": "pléiscín cóisire", + "1f38f": "sraoilleán éisc", + "1f380": "ribín", + "1f381": "bronntanas", + "1f39f": "ticéid cead isteach", + "1f3c6": "corn", + "26bd": "liathróid sacair", + "1f3c0": "cispheil", + "1f3c8": "peil Mheiriceánach", + "1f3be": "leadóg", + "1f94f": "diosca eitilte", + "1f3d3": "ping pang", + "1f3f8": "badmantan", + "1f93f": "masc tumadóireachta", + "1f94c": "cloch churlála", + "1f3af": "buille díreach", + "1fa80": "yó-yó", + "1fa81": "eitleog", + "1f52e": "cruinneog chriostail", + "1f3b2": "dísle", + "1f9e9": "mír mearaí", + "1f3a8": "pailéad dathanna", + "1f9f5": "snáth", + "1f455": "t-léine", + "1f9e6": "stocaí", + "1f457": "gúna", + "1fa73": "brístí gearra", + "1f392": "mála scoile", + "1f45f": "bróg reatha", + "1f451": "coróin", + "1f9e2": "caipín speiceach", + "1f484": "béaldath", + "1f48d": "fáinne", + "1f48e": "geamchloch", + "1f4e2": "callaire", + "1f3b6": "nótaí ceoil", + "1f399": "micreafón stiúideo", + "1f4fb": "raidió", + "1f3b7": "sacsafón", + "1fa97": "bosca ceoil", + "1f3b8": "giotár", + "1f3ba": "trumpa", + "1f3bb": "veidhlín", + "1fa95": "bainseó", + "1f941": "druma", + "260e": "teileafón", + "1f50b": "ceallra", + "1f4bf": "diosca optúil", + "1f9ee": "abacas", + "1f3ac": "clabaire", + "1f4a1": "bolgán solais", + "1f526": "tóirse", + "1f3ee": "laindéar dearg", + "1f4d5": "leabhar dúnta", + "1f3f7": "lipéad", + "1f4b3": "cárta creidmheasa", + "270f": "peann luaidhe", + "1f58c": "scuab phéinteála", + "1f58d": "crián", + "1f4cc": "tacóid ordóige", + "1f4ce": "fáiscín páipéir", + "1f511": "eochair", + "1fa83": "búmarang", + "1f3f9": "saighead is bogha", + "2696": "scála", + "1f9f2": "maighnéad", + "1f9ea": "triaileadán", + "1f9ec": "ADN", + "1f52c": "micreascóp", + "1f52d": "teileascóp", + "1f4e1": "aeróg satailíte", + "1fa91": "cathaoir", + "1f9f9": "scruab", + "1f5ff": "dealbh Oileán na Cásca" + }, + "he": { + "1f47d": "חייזר", + "1f916": "רובוט", + "1f9e0": "מוח", + "1f441": "עין", + "1f9d9": "קוסם", + "1f9da": "פיה", + "1f9dc": "בתולת ים", + "1f435": "פני קוף", + "1f9a7": "אורנגאוטן", + "1f436": "פני כלב", + "1f43a": "זאב", + "1f98a": "שועל", + "1f99d": "רקון", + "1f431": "פני חתול", + "1f981": "אריה", + "1f42f": "פני טיגריס", + "1f434": "פני סוס", + "1f984": "חד קרן", + "1f993": "זברה", + "1f98c": "אייל", + "1f42e": "פני פרה", + "1f437": "פני חזיר", + "1f417": "חזיר בר", + "1f42a": "גמל", + "1f999": "למה", + "1f992": "ג׳ירף", + "1f418": "פיל", + "1f9a3": "ממותה", + "1f98f": "קרנף", + "1f42d": "פני עכבר", + "1f430": "פני ארנב", + "1f43f": "סנאי", + "1f994": "קיפוד", + "1f987": "עטלף", + "1f43b": "דוב", + "1f428": "קואלה", + "1f9a5": "עצלן", + "1f9a6": "לוטרה", + "1f998": "קנגורו", + "1f425": "אפרוח מלפנים", + "1f426": "ציפור", + "1f54a": "יונה", + "1f986": "ברווז", + "1f989": "ינשוף", + "1f9a4": "ציפור דודו", + "1fab6": "נוצה", + "1f9a9": "פלמינגו", + "1f99a": "טווס", + "1f99c": "תוכי", + "1f40a": "תנין", + "1f422": "צב", + "1f98e": "לטאה", + "1f40d": "נחש", + "1f432": "פני דרקון", + "1f995": "סרופוד", + "1f433": "לווייתן מתיז סילון מים", + "1f42c": "דולפין", + "1f9ad": "כלב ים", + "1f41f": "דג", + "1f420": "דג טרופי", + "1f988": "כריש", + "1f419": "תמנון", + "1f41a": "צדף מסולסל", + "1f40c": "חלזון", + "1f98b": "פרפר", + "1f41b": "זחל", + "1f41d": "דבורה", + "1f41e": "פרת משה רבנו", + "1f490": "זר פרחים", + "1f339": "ורד", + "1f33a": "היביסקוס", + "1f33b": "חמניה", + "1f337": "צבעוני", + "1f332": "עץ ירוק-עד", + "1f333": "עץ נשיר", + "1f334": "עץ דקל", + "1f335": "קקטוס", + "1f33f": "צמח תבלין", + "1f341": "עלה מייפל", + "1f344": "פטריה", + "1f347": "ענבים", + "1f348": "מלון", + "1f349": "אבטיח", + "1f34a": "קלמנטינה", + "1f34b": "לימון", + "1f34c": "בננה", + "1f34d": "אננס", + "1f96d": "מנגו", + "1f34f": "תפוח ירוק", + "1f350": "אגס", + "1f351": "אפרסק", + "1f352": "דובדבנים", + "1f353": "תות שדה", + "1fad0": "אוכמניות", + "1f95d": "קיווי", + "1f345": "עגבנייה", + "1fad2": "זית", + "1f965": "קוקוס", + "1f951": "אבוקדו", + "1f346": "חציל", + "1f955": "גזר", + "1f33d": "קלח תירס", + "1f336": "פלפל חריף", + "1f96c": "עלים ירוקים", + "1f966": "ברוקולי", + "1f9c5": "בצל", + "1f95c": "בוטנים", + "1f950": "קרואסון", + "1f956": "באגט", + "1f968": "בייגלה", + "1f96f": "בייגל", + "1f95e": "פנקייקס", + "1f9c7": "וופל", + "1f354": "המבורגר", + "1f355": "פיצה", + "1f32d": "נקניקייה בלחמניה", + "1f32e": "טאקו", + "1f37f": "פופקורן", + "1f980": "סרטן", + "1f99e": "לובסטר", + "1f368": "גלידה", + "1f369": "סופגניה", + "1f36a": "עוגיה", + "1f382": "עוגת יום הולדת", + "1f9c1": "קפקייק", + "1f36b": "חפיסת שוקולד", + "1f36c": "סוכריה", + "1f36d": "סוכריה על מקל", + "1fad6": "קנקן תה", + "1f9c3": "קופסת מיץ", + "1f9c9": "מאטה", + "1f9ed": "מצפן", + "1f3d4": "הר עם פסגה מושלגת", + "1f30b": "הר געש", + "1f3d5": "מחנאות", + "1f3dd": "אי בודד", + "1f3e1": "בית עם גינה", + "26f2": "מזרקה", + "1f3a0": "סוס בקרוסלה", + "1f3a1": "גלגל ענק", + "1f3a2": "רכבת הרים", + "1f488": "עמוד מספרה", + "1f686": "רכבת", + "1f68b": "קרון חשמלית", + "1f68d": "אוטובוס מלפנים", + "1f695": "מונית", + "1f697": "מכונית", + "1f69a": "משאית", + "1f69c": "טרקטור", + "1f6f5": "קטנוע", + "1f6fa": "ריקשה ממונעת", + "1f6f4": "קורקינט", + "1f6f9": "סקייטבורד", + "1f6fc": "גלגיליות", + "2693": "עוגן", + "26f5": "סירת מפרש", + "1f6f6": "קאנו", + "1f6a4": "סירת מירוץ", + "1f6a2": "ספינה", + "2708": "מטוס", + "1f681": "מסוק", + "1f6a0": "קרון רכבל", + "1f6f0": "לוויין", + "1f680": "טיל", + "1f6f8": "צלחת מעופפת", + "23f0": "שעון מעורר", + "1f319": "סהר", + "1f321": "מדחום", + "2600": "שמש", + "1fa90": "כוכב לכת עם טבעות", + "1f31f": "כוכב זוהר", + "1f300": "הוריקן", + "1f308": "קשת בענן", + "2602": "מטריה", + "2744": "פתית שלג", + "2604": "שביט", + "1f525": "אש", + "1f4a7": "טיפה", + "1f30a": "גל", + "1f383": "מנורת דלעת", + "2728": "נצנוץ", + "1f388": "בלון", + "1f389": "פצצת קונפטי", + "1f38f": "דגלים בצורת דגי קוי", + "1f380": "סרט מתנה", + "1f381": "קופסת מתנה", + "1f39f": "כרטיס כניסה", + "1f3c6": "גביע", + "26bd": "כדורגל", + "1f3c0": "כדור סל", + "1f3c8": "פוטבול אמריקאי", + "1f3be": "כדור טניס", + "1f94f": "פריזבי", + "1f3d3": "פינג פונג", + "1f3f8": "בדמינטון", + "1f93f": "מסיכת צלילה", + "1f94c": "אבן קרלינג", + "1f3af": "פגיעה בול", + "1fa80": "יו-יו", + "1fa81": "עפיפון", + "1f52e": "כדור בדולח", + "1f3b2": "קוביית משחק", + "1f9e9": "חלק בפאזל", + "1f3a8": "פלטת צבעים", + "1f9f5": "חוט", + "1f455": "חולצת טי", + "1f9e6": "גרביים", + "1f457": "שמלה", + "1fa73": "מכנסיים קצרים", + "1f392": "ילקוט", + "1f45f": "נעל ריצה", + "1f451": "כתר", + "1f9e2": "כובע מצחייה", + "1f484": "שפתון", + "1f48d": "טבעת", + "1f48e": "יהלום", + "1f4e2": "מגפון", + "1f3b6": "תווים מוזיקליים", + "1f399": "מיקרופון אולפן", + "1f4fb": "רדיו", + "1f3b7": "סקסופון", + "1fa97": "אקורדיון", + "1f3b8": "גיטרה", + "1f3ba": "חצוצרה", + "1f3bb": "כינור", + "1fa95": "בנג׳ו", + "1f941": "תוף", + "260e": "טלפון רגיל", + "1f50b": "סוללה", + "1f4bf": "דיסק אופטי", + "1f9ee": "חשבונייה", + "1f3ac": "קלאפר", + "1f4a1": "נורה", + "1f526": "פנס", + "1f3ee": "פנס נייר אדום", + "1f4d5": "ספר סגור", + "1f3f7": "תווית", + "1f4b3": "כרטיס אשראי", + "270f": "עיפרון", + "1f58c": "מכחול", + "1f58d": "צבע פנדה", + "1f4cc": "נעץ", + "1f4ce": "אטב נייר", + "1f511": "מפתח", + "1fa83": "בומרנג", + "1f3f9": "חץ וקשת", + "2696": "מאזניים", + "1f9f2": "מגנט", + "1f9ea": "מבחנה", + "1f9ec": "די אנ איי", + "1f52c": "מיקרוסקופ", + "1f52d": "טלסקופ", + "1f4e1": "צלחת לוויין", + "1fa91": "כיסא", + "1f9f9": "מטאטא", + "1f5ff": "פסל מאיי הפסחא" + }, + "hu": { + "1f47d": "földönkívüli", + "1f916": "robot", + "1f9e0": "agy", + "1f441": "szem", + "1f9d9": "varázsló", + "1f9da": "tündér", + "1f9dc": "sellő", + "1f435": "majomfej", + "1f9a7": "orangután", + "1f436": "kutyafej", + "1f43a": "farkasfej", + "1f98a": "rókafej", + "1f99d": "mosómedve", + "1f431": "macskafej", + "1f981": "oroszlánfej", + "1f42f": "tigrisfej", + "1f434": "lófej", + "1f984": "unikornisfej", + "1f993": "zebra", + "1f98c": "szarvas", + "1f42e": "tehénfej", + "1f437": "malacfej", + "1f417": "vaddisznó", + "1f42a": "teve", + "1f999": "láma", + "1f992": "zsiráf", + "1f418": "elefánt", + "1f9a3": "mamut", + "1f98f": "orrszarvú", + "1f42d": "egérfej", + "1f430": "nyúlfej", + "1f43f": "mókus", + "1f994": "sün", + "1f987": "denevér", + "1f43b": "medvefej", + "1f428": "koala", + "1f9a5": "lajhár", + "1f9a6": "vidra", + "1f998": "kenguru", + "1f425": "előre néző kiscsibe", + "1f426": "madár", + "1f54a": "galamb", + "1f986": "kacsa", + "1f989": "bagoly", + "1f9a4": "dodó", + "1fab6": "madártoll", + "1f9a9": "flamingó", + "1f99a": "páva", + "1f99c": "papagáj", + "1f40a": "krokodil", + "1f422": "teknős", + "1f98e": "gyík", + "1f40d": "kígyó", + "1f432": "sárkányfej", + "1f995": "sauropoda", + "1f433": "fröcskölő bálna", + "1f42c": "delfin", + "1f9ad": "fóka", + "1f41f": "hal", + "1f420": "trópusi hal", + "1f988": "cápa", + "1f419": "polip", + "1f41a": "tengeri csiga", + "1f40c": "csiga", + "1f98b": "pillangó", + "1f41b": "rovar", + "1f41d": "méh", + "1f41e": "katica", + "1f490": "csokor", + "1f339": "rózsa", + "1f33a": "hibiszkusz", + "1f33b": "napraforgó", + "1f337": "tulipán", + "1f332": "örökzöld", + "1f333": "lombhullató fa", + "1f334": "pálmafa", + "1f335": "kaktusz", + "1f33f": "gyógynövény", + "1f341": "juharlevél", + "1f344": "gomba", + "1f347": "szőlő", + "1f348": "sárgadinnye", + "1f349": "görögdinnye", + "1f34a": "mandarin", + "1f34b": "citrom", + "1f34c": "banán", + "1f34d": "ananász", + "1f96d": "mangó", + "1f34f": "zöld alma", + "1f350": "körte", + "1f351": "őszibarack", + "1f352": "cseresznye", + "1f353": "eper", + "1fad0": "áfonya", + "1f95d": "kivi", + "1f345": "paradicsom", + "1fad2": "olajbogyó", + "1f965": "kókuszdió", + "1f951": "avokádó", + "1f346": "padlizsán", + "1f955": "sárgarépa", + "1f33d": "kukoricacső", + "1f336": "erőspaprika", + "1f96c": "leveles zöldség", + "1f966": "brokkoli", + "1f9c5": "hagyma", + "1f95c": "földimogyoró", + "1f950": "croissant", + "1f956": "bagett", + "1f968": "perec", + "1f96f": "bagel", + "1f95e": "palacsinta", + "1f9c7": "gofri", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "pattogatott kukorica", + "1f980": "rák", + "1f99e": "homár", + "1f368": "fagylalt", + "1f369": "fánk", + "1f36a": "sütemény", + "1f382": "születésnapi torta", + "1f9c1": "cupcake", + "1f36b": "csokoládé", + "1f36c": "cukorka", + "1f36d": "nyalóka", + "1fad6": "teáskanna", + "1f9c3": "italos doboz", + "1f9c9": "maté", + "1f9ed": "iránytű", + "1f3d4": "hegy hótakaróval", + "1f30b": "vulkán", + "1f3d5": "sátorozás", + "1f3dd": "lakatlan sziget", + "1f3e1": "ház kerttel", + "26f2": "szökőkút", + "1f3a0": "ló a körhintáról", + "1f3a1": "óriáskerék", + "1f3a2": "hullámvasút", + "1f488": "fodrászcégér", + "1f686": "vonat", + "1f68b": "villamoskocsi", + "1f68d": "érkező busz", + "1f695": "taxi", + "1f697": "autó", + "1f69a": "teherautó", + "1f69c": "traktor", + "1f6f5": "robogó", + "1f6fa": "motoros riksa", + "1f6f4": "roller", + "1f6f9": "gördeszka", + "1f6fc": "görkorcsolya", + "2693": "vasmacska", + "26f5": "vitorlás hajó", + "1f6f6": "kenu", + "1f6a4": "motoros siklócsónak", + "1f6a2": "hajó", + "2708": "repülőgép", + "1f681": "helikopter", + "1f6a0": "hegyi felvonó", + "1f6f0": "műhold", + "1f680": "rakéta", + "1f6f8": "repülő csészealj", + "23f0": "ébresztőóra", + "1f319": "növekvő hold", + "1f321": "hőmérő", + "2600": "nap", + "1fa90": "gyűrűs bolygó", + "1f31f": "fénylő csillag", + "1f300": "ciklon", + "1f308": "szivárvány", + "2602": "esernyő", + "2744": "hópehely", + "2604": "üstökös", + "1f525": "tűz", + "1f4a7": "csepp", + "1f30a": "vízhullám", + "1f383": "töklámpás", + "2728": "szikrák", + "1f388": "léggömb", + "1f389": "partikellékek", + "1f38f": "rizspapír pontyok", + "1f380": "szalag", + "1f381": "becsomagolt ajándék", + "1f39f": "belépőjegyek", + "1f3c6": "kupa", + "26bd": "foci", + "1f3c0": "kosárlabda", + "1f3c8": "amerikai foci", + "1f3be": "tenisz", + "1f94f": "frizbi", + "1f3d3": "pingpong", + "1f3f8": "tollaslabda", + "1f93f": "búvármaszk", + "1f94c": "curlingkő", + "1f3af": "telitalálat", + "1fa80": "jojó", + "1fa81": "papírsárkány", + "1f52e": "kristálygömb", + "1f3b2": "dobókocka", + "1f9e9": "kirakó", + "1f3a8": "festőpaletta", + "1f9f5": "cérna", + "1f455": "póló", + "1f9e6": "zokni", + "1f457": "ruha", + "1fa73": "rövidnadrág", + "1f392": "iskolatáska", + "1f45f": "futócipő", + "1f451": "korona", + "1f9e2": "sildes sapka", + "1f484": "ajakrúzs", + "1f48d": "gyűrű", + "1f48e": "ékkő", + "1f4e2": "hangosbeszélő", + "1f3b6": "hangjegyek", + "1f399": "stúdiómikrofon", + "1f4fb": "rádió", + "1f3b7": "szaxofon", + "1fa97": "harmonika", + "1f3b8": "gitár", + "1f3ba": "trombita", + "1f3bb": "hegedű", + "1fa95": "bendzsó", + "1f941": "dob", + "260e": "telefon", + "1f50b": "elem", + "1f4bf": "optikai lemez", + "1f9ee": "abakusz", + "1f3ac": "csapó", + "1f4a1": "villanykörte", + "1f526": "zseblámpa", + "1f3ee": "piros papírlámpa", + "1f4d5": "becsukott könyv", + "1f3f7": "címke", + "1f4b3": "hitelkártya", + "270f": "ceruza", + "1f58c": "ecset", + "1f58d": "zsírkréta", + "1f4cc": "rajzszög", + "1f4ce": "gemkapocs", + "1f511": "kulcs", + "1fa83": "bumeráng", + "1f3f9": "íj és nyíl", + "2696": "kétkarú mérleg", + "1f9f2": "mágnes", + "1f9ea": "kémcső", + "1f9ec": "DNS", + "1f52c": "mikroszkóp", + "1f52d": "távcső", + "1f4e1": "parabolaantenna", + "1fa91": "szék", + "1f9f9": "seprű", + "1f5ff": "moai" + }, + "id": { + "1f47d": "alien", + "1f916": "robot", + "1f9e0": "otak", + "1f441": "satu mata", + "1f9d9": "magi", + "1f9da": "peri", + "1f9dc": "orang duyung", + "1f435": "wajah monyet", + "1f9a7": "orangutan", + "1f436": "wajah anjing", + "1f43a": "serigala", + "1f98a": "rubah", + "1f99d": "rakun", + "1f431": "wajah kucing", + "1f981": "singa", + "1f42f": "wajah harimau", + "1f434": "wajah kuda", + "1f984": "unicorn", + "1f993": "zebra", + "1f98c": "rusa", + "1f42e": "wajah sapi", + "1f437": "wajah babi", + "1f417": "babi hutan", + "1f42a": "unta", + "1f999": "llama", + "1f992": "jerapah", + "1f418": "gajah", + "1f9a3": "mamut", + "1f98f": "badak", + "1f42d": "wajah tikus", + "1f430": "wajah kelinci", + "1f43f": "tupai", + "1f994": "landak", + "1f987": "kelelawar", + "1f43b": "beruang", + "1f428": "koala", + "1f9a5": "kungkang", + "1f9a6": "berang-berang", + "1f998": "kanguru", + "1f425": "itik bayi menghadap ke depan", + "1f426": "burung", + "1f54a": "merpati", + "1f986": "bebek", + "1f989": "burung hantu", + "1f9a4": "dodo", + "1fab6": "bulu", + "1f9a9": "flamingo", + "1f99a": "merak", + "1f99c": "nuri", + "1f40a": "buaya", + "1f422": "kura-kura", + "1f98e": "kadal", + "1f40d": "ular", + "1f432": "wajah naga", + "1f995": "sauropod", + "1f433": "ikan paus menyembur", + "1f42c": "lumba-lumba", + "1f9ad": "anjing laut", + "1f41f": "ikan", + "1f420": "ikan tropis", + "1f988": "hiu", + "1f419": "gurita", + "1f41a": "cangkang spiral", + "1f40c": "siput", + "1f98b": "kupu-kupu", + "1f41b": "serangga kecil", + "1f41d": "lebah madu", + "1f41e": "kumbang betina", + "1f490": "karangan bunga", + "1f339": "mawar", + "1f33a": "kembang sepatu", + "1f33b": "bunga matahari", + "1f337": "tulip", + "1f332": "pohon hijau abadi", + "1f333": "pohon meranggas", + "1f334": "pohon palem", + "1f335": "kaktus", + "1f33f": "herba", + "1f341": "daun maple", + "1f344": "jamur", + "1f347": "anggur", + "1f348": "melon", + "1f349": "semangka", + "1f34a": "buah jeruk", + "1f34b": "lemon", + "1f34c": "pisang", + "1f34d": "nanas", + "1f96d": "mangga", + "1f34f": "apel hijau", + "1f350": "pir", + "1f351": "persik", + "1f352": "ceri", + "1f353": "stroberi", + "1fad0": "blueberry", + "1f95d": "buah kiwi", + "1f345": "tomat", + "1fad2": "zaitun", + "1f965": "kelapa", + "1f951": "alpukat", + "1f346": "terung", + "1f955": "wortel", + "1f33d": "bonggol jagung", + "1f336": "cabai pedas", + "1f96c": "selada hijau", + "1f966": "brokoli", + "1f9c5": "bawang bombay", + "1f95c": "kacang tanah", + "1f950": "croissant", + "1f956": "roti baguette", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "panekuk", + "1f9c7": "wafel", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "kepiting", + "1f99e": "lobster", + "1f368": "es krim", + "1f369": "donat", + "1f36a": "biskuit", + "1f382": "kue ulang tahun", + "1f9c1": "kue mangkuk", + "1f36b": "sebatang cokelat", + "1f36c": "permen", + "1f36d": "permen lolipop", + "1fad6": "teko", + "1f9c3": "kotak minuman", + "1f9c9": "teh mate", + "1f9ed": "kompas", + "1f3d4": "gunung dengan puncak bersalju", + "1f30b": "gunung berapi", + "1f3d5": "berkemah", + "1f3dd": "pulau terpencil", + "1f3e1": "rumah dengan taman", + "26f2": "air mancur", + "1f3a0": "komidi putar", + "1f3a1": "kincir ria", + "1f3a2": "roller coaster", + "1f488": "tanda salon", + "1f686": "kereta", + "1f68b": "gerbong trem", + "1f68d": "bus datang", + "1f695": "taksi", + "1f697": "mobil", + "1f69a": "truk pengiriman", + "1f69c": "traktor", + "1f6f5": "motor skuter", + "1f6fa": "bajaj", + "1f6f4": "otoped", + "1f6f9": "papan luncur", + "1f6fc": "sepatu roda", + "2693": "jangkar", + "26f5": "perahu layar", + "1f6f6": "kano", + "1f6a4": "perahu cepat", + "1f6a2": "kapal", + "2708": "pesawat", + "1f681": "helikopter", + "1f6a0": "kereta gantung", + "1f6f0": "satelit", + "1f680": "roket", + "1f6f8": "piring terbang", + "23f0": "jam weker", + "1f319": "bulan sabit", + "1f321": "termometer", + "2600": "matahari", + "1fa90": "planet bercincin", + "1f31f": "bintang bersinar", + "1f300": "topan", + "1f308": "pelangi", + "2602": "payung", + "2744": "serpihan salju", + "2604": "komet", + "1f525": "api", + "1f4a7": "tetesan air", + "1f30a": "ombak", + "1f383": "jack-o-lantern", + "2728": "berkilau", + "1f388": "balon", + "1f389": "party popper", + "1f38f": "bendera ikan koi", + "1f380": "pita", + "1f381": "kado", + "1f39f": "tiket masuk", + "1f3c6": "piala", + "26bd": "bola sepak", + "1f3c0": "bola basket", + "1f3c8": "American football", + "1f3be": "tenis", + "1f94f": "lempar cakram", + "1f3d3": "ping pong", + "1f3f8": "bulu tangkis", + "1f93f": "kacamata selam", + "1f94c": "batu curling", + "1f3af": "dart", + "1fa80": "yo-yo", + "1fa81": "layang-layang", + "1f52e": "bola kristal", + "1f3b2": "dadu", + "1f9e9": "keping puzzle", + "1f3a8": "palet pelukis", + "1f9f5": "benang", + "1f455": "kaos", + "1f9e6": "kaus kaki", + "1f457": "gaun", + "1fa73": "celana pendek", + "1f392": "tas sekolah", + "1f45f": "sepatu lari", + "1f451": "mahkota", + "1f9e2": "topi berlidah", + "1f484": "lipstik", + "1f48d": "cincin", + "1f48e": "batu permata", + "1f4e2": "pengeras suara", + "1f3b6": "not-not musik", + "1f399": "mikrofon studio", + "1f4fb": "radio", + "1f3b7": "saksofon", + "1fa97": "akordeon", + "1f3b8": "gitar", + "1f3ba": "trompet", + "1f3bb": "biola", + "1fa95": "banjo", + "1f941": "drum", + "260e": "telepon", + "1f50b": "baterai", + "1f4bf": "disk optik", + "1f9ee": "sempoa", + "1f3ac": "papan sutradara", + "1f4a1": "bohlam", + "1f526": "lampu senter", + "1f3ee": "lampion merah", + "1f4d5": "buku tertutup", + "1f3f7": "label", + "1f4b3": "kartu kredit", + "270f": "pensil", + "1f58c": "kuas", + "1f58d": "krayon", + "1f4cc": "paku penanda", + "1f4ce": "klip kertas", + "1f511": "kunci", + "1fa83": "bumerang", + "1f3f9": "busur dan panah", + "2696": "timbangan gantung", + "1f9f2": "magnet", + "1f9ea": "tabung uji", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "antena satelit", + "1fa91": "bangku", + "1f9f9": "sapu", + "1f5ff": "moai" + }, + "is": { + "1f47d": "geimvera", + "1f916": "vélmennisandlit", + "1f9e0": "heili", + "1f441": "auga", + "1f9d9": "galdramaður", + "1f9da": "álfur", + "1f9dc": "sæbúi", + "1f435": "apahöfuð", + "1f9a7": "órangútan", + "1f436": "hundshöfuð", + "1f43a": "úlfur", + "1f98a": "refur", + "1f99d": "þvottabjörn", + "1f431": "kattarhöfuð", + "1f981": "ljón", + "1f42f": "tígrisdýrshöfuð", + "1f434": "hestshöfuð", + "1f984": "einhyrningur", + "1f993": "sebrahestur", + "1f98c": "hjartardýr", + "1f42e": "kýrhöfuð", + "1f437": "svínshöfuð", + "1f417": "villisvín", + "1f42a": "drómedari", + "1f999": "lamadýr", + "1f992": "gíraffi", + "1f418": "fíll", + "1f9a3": "loðfíll", + "1f98f": "nashyrningur", + "1f42d": "músarhöfuð", + "1f430": "kanínuhöfuð", + "1f43f": "jarðíkorni", + "1f994": "broddgöltur", + "1f987": "leðurblaka", + "1f43b": "björn", + "1f428": "kóalabjörn", + "1f9a5": "letidýr", + "1f9a6": "otur", + "1f998": "kengúra", + "1f425": "framhlið hænuunga", + "1f426": "fugl", + "1f54a": "dúfa", + "1f986": "önd", + "1f989": "ugla", + "1f9a4": "dúdúfugl", + "1fab6": "fjöður", + "1f9a9": "flamingói", + "1f99a": "páfugl", + "1f99c": "páfagaukur", + "1f40a": "krókódíll", + "1f422": "skjaldbaka", + "1f98e": "eðla", + "1f40d": "snákur", + "1f432": "drekahöfuð", + "1f995": "graseðla", + "1f433": "blásandi hvalur", + "1f42c": "höfrungur", + "1f9ad": "selur", + "1f41f": "fiskur", + "1f420": "hitabeltisfiskur", + "1f988": "hákarl", + "1f419": "kolkrabbi", + "1f41a": "kuðungur", + "1f40c": "snigill", + "1f98b": "fiðrildi", + "1f41b": "skordýr", + "1f41d": "hunangsfluga", + "1f41e": "maríuhæna", + "1f490": "blómvöndur", + "1f339": "rós", + "1f33a": "Havaírós", + "1f33b": "sólblóm", + "1f337": "túlípani", + "1f332": "sígrænt tré", + "1f333": "sumargrænt tré", + "1f334": "pálmatré", + "1f335": "kaktus", + "1f33f": "kryddjurt", + "1f341": "hlynslauf", + "1f344": "sveppur", + "1f347": "vínber", + "1f348": "melóna", + "1f349": "vatnsmelóna", + "1f34a": "mandarína", + "1f34b": "sítróna", + "1f34c": "banani", + "1f34d": "ananas", + "1f96d": "mangó", + "1f34f": "grænt epli", + "1f350": "pera", + "1f351": "ferskja", + "1f352": "kirsuber", + "1f353": "jarðarber", + "1fad0": "bláber", + "1f95d": "kíví", + "1f345": "tómatur", + "1fad2": "ólífa", + "1f965": "kókoshneta", + "1f951": "avókadó", + "1f346": "eggaldin", + "1f955": "gulrót", + "1f33d": "maís", + "1f336": "chilipipar", + "1f96c": "kál", + "1f966": "brokkólí", + "1f9c5": "laukur", + "1f95c": "jarðhneta", + "1f950": "smjördeigshorn", + "1f956": "fransbrauð", + "1f968": "saltkringla", + "1f96f": "beygla", + "1f95e": "pönnukökur", + "1f9c7": "vaffla", + "1f354": "hamborgari", + "1f355": "pítsusneið", + "1f32d": "pylsa í brauði", + "1f32e": "takó", + "1f37f": "popp", + "1f980": "krabbi", + "1f99e": "humar", + "1f368": "kúluís", + "1f369": "kleinuhringur", + "1f36a": "smákaka", + "1f382": "afmæliskaka", + "1f9c1": "bollakaka", + "1f36b": "súkkulaði", + "1f36c": "nammi", + "1f36d": "sleikibrjóstsykur", + "1fad6": "tekanna", + "1f9c3": "ferna", + "1f9c9": "mate", + "1f9ed": "áttaviti", + "1f3d4": "snæviþakinn fjallstindur", + "1f30b": "eldfjall", + "1f3d5": "tjaldstæði", + "1f3dd": "eyðieyja", + "1f3e1": "hús með garði", + "26f2": "gosbrunnur", + "1f3a0": "hringekjuhestur", + "1f3a1": "parísarhjól", + "1f3a2": "rússíbani", + "1f488": "rakarastofa", + "1f686": "lest", + "1f68b": "sporvagn", + "1f68d": "strætó á móti", + "1f695": "leigubíll", + "1f697": "bíll", + "1f69a": "flutningabíll", + "1f69c": "dráttarvél", + "1f6f5": "vespa", + "1f6fa": "vélknúinn léttvagn", + "1f6f4": "hlaupahjól", + "1f6f9": "hjólabretti", + "1f6fc": "hjólaskautar", + "2693": "akkeri", + "26f5": "seglskúta", + "1f6f6": "kanó", + "1f6a4": "hraðbátur", + "1f6a2": "skip", + "2708": "flugvél", + "1f681": "þyrla", + "1f6a0": "kláfferja í fjalli", + "1f6f0": "gervihnöttur", + "1f680": "eldflaug", + "1f6f8": "fljúgandi diskur", + "23f0": "vekjaraklukka", + "1f319": "hálfmáni", + "1f321": "hitamælir", + "2600": "sól", + "1fa90": "pláneta með hringi", + "1f31f": "skínandi stjarna", + "1f300": "fellibylur", + "1f308": "regnbogi", + "2602": "regnhlíf", + "2744": "snjókorn", + "2604": "halastjarna", + "1f525": "eldur", + "1f4a7": "dropi", + "1f30a": "alda", + "1f383": "hrekkjavökugrasker", + "2728": "stjörnur", + "1f388": "blaðra", + "1f389": "knall", + "1f38f": "fiskveifur", + "1f380": "borði", + "1f381": "gjöf", + "1f39f": "aðgöngumiðar", + "1f3c6": "verðlaunabikar", + "26bd": "fótbolti", + "1f3c0": "körfubolti", + "1f3c8": "amerískur fótbolti", + "1f3be": "tennis", + "1f94f": "frisbídiskur", + "1f3d3": "borðtennis", + "1f3f8": "badminton", + "1f93f": "köfunargríma", + "1f94c": "krullusteinn", + "1f3af": "skotmark", + "1fa80": "jójó", + "1fa81": "flugdreki", + "1f52e": "kristalskúla", + "1f3b2": "teningur", + "1f9e9": "púsl", + "1f3a8": "litapalletta", + "1f9f5": "tvinni", + "1f455": "stuttermabolur", + "1f9e6": "sokkar", + "1f457": "kjóll", + "1fa73": "stuttbuxur", + "1f392": "skólataska", + "1f45f": "íþróttaskór", + "1f451": "kóróna", + "1f9e2": "derhúfa", + "1f484": "varalitur", + "1f48d": "hringur", + "1f48e": "gimsteinn", + "1f4e2": "Almannavarnahátalari", + "1f3b6": "nótur", + "1f399": "hljóðnemi í hljóðveri", + "1f4fb": "útvarp", + "1f3b7": "saxófónn", + "1fa97": "harmonika", + "1f3b8": "gítar", + "1f3ba": "trompet", + "1f3bb": "fiðla", + "1fa95": "banjó", + "1f941": "tromma", + "260e": "sími", + "1f50b": "rafhlaða", + "1f4bf": "blu-ray", + "1f9ee": "talnagrind", + "1f3ac": "klapptré", + "1f4a1": "ljósapera", + "1f526": "vasaljós", + "1f3ee": "rauður lampi", + "1f4d5": "lokuð bók", + "1f3f7": "merkimiði", + "1f4b3": "kreditkort", + "270f": "blýantur", + "1f58c": "málningarpensill", + "1f58d": "vaxlitur", + "1f4cc": "teiknibóla", + "1f4ce": "bréfaklemma", + "1f511": "lykill", + "1fa83": "búmerang", + "1f3f9": "bogi og ör", + "2696": "vog", + "1f9f2": "segull", + "1f9ea": "tilraunaglas", + "1f9ec": "dna", + "1f52c": "smásjá", + "1f52d": "sjónauki", + "1f4e1": "gervihnattaloftnet", + "1fa91": "stóll", + "1f9f9": "kústur", + "1f5ff": "moyai-stytta" + }, + "it": { + "1f47d": "alieno", + "1f916": "faccina di robot", + "1f9e0": "cervello", + "1f441": "occhio", + "1f9d9": "mago", + "1f9da": "fata", + "1f9dc": "sirena", + "1f435": "muso di scimmia", + "1f9a7": "orangotango", + "1f436": "muso di cane", + "1f43a": "lupo", + "1f98a": "volpe", + "1f99d": "procione", + "1f431": "muso di gatto", + "1f981": "leone", + "1f42f": "muso di tigre", + "1f434": "muso di cavallo", + "1f984": "unicorno", + "1f993": "zebra", + "1f98c": "cervo", + "1f42e": "muso di mucca", + "1f437": "muso di maiale", + "1f417": "cinghiale", + "1f42a": "dromedario", + "1f999": "lama", + "1f992": "giraffa", + "1f418": "elefante", + "1f9a3": "mammut", + "1f98f": "rinoceronte", + "1f42d": "muso di topo", + "1f430": "muso di coniglio", + "1f43f": "scoiattolo", + "1f994": "riccio", + "1f987": "pipistrello", + "1f43b": "orso", + "1f428": "koala", + "1f9a5": "bradipo", + "1f9a6": "lontra", + "1f998": "canguro", + "1f425": "pulcino visto di fronte", + "1f426": "uccello", + "1f54a": "colomba", + "1f986": "anatra", + "1f989": "gufo", + "1f9a4": "dodo", + "1fab6": "piuma", + "1f9a9": "fenicottero", + "1f99a": "pavone", + "1f99c": "pappagallo", + "1f40a": "coccodrillo", + "1f422": "tartaruga", + "1f98e": "lucertola", + "1f40d": "serpente", + "1f432": "testa di drago", + "1f995": "sauropode", + "1f433": "balena che spruzza acqua", + "1f42c": "delfino", + "1f9ad": "foca", + "1f41f": "pesce", + "1f420": "pesce tropicale", + "1f988": "squalo", + "1f419": "polpo", + "1f41a": "conchiglia", + "1f40c": "lumaca", + "1f98b": "farfalla", + "1f41b": "insetto", + "1f41d": "ape", + "1f41e": "coccinella", + "1f490": "mazzo di fiori", + "1f339": "rosa", + "1f33a": "ibisco", + "1f33b": "girasole", + "1f337": "tulipano", + "1f332": "albero sempreverde", + "1f333": "albero deciduo", + "1f334": "palma", + "1f335": "cactus", + "1f33f": "pianta", + "1f341": "foglia d’acero", + "1f344": "fungo", + "1f347": "uva", + "1f348": "melone", + "1f349": "anguria", + "1f34a": "mandarino", + "1f34b": "limone", + "1f34c": "banana", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "mela verde", + "1f350": "pera", + "1f351": "pesca", + "1f352": "ciliegie", + "1f353": "fragola", + "1fad0": "mirtilli", + "1f95d": "kiwi", + "1f345": "pomodoro", + "1fad2": "oliva", + "1f965": "cocco", + "1f951": "avocado", + "1f346": "melanzana", + "1f955": "carota", + "1f33d": "pannocchia", + "1f336": "peperoncino", + "1f96c": "verdure a foglia", + "1f966": "broccoli", + "1f9c5": "cipolla", + "1f95c": "arachidi", + "1f950": "croissant", + "1f956": "baguette", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "pancake", + "1f9c7": "waffle", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "granchio", + "1f99e": "aragosta", + "1f368": "coppa di gelato", + "1f369": "ciambella", + "1f36a": "biscotto", + "1f382": "torta di compleanno", + "1f9c1": "cupcake", + "1f36b": "cioccolato", + "1f36c": "caramella", + "1f36d": "lecca lecca", + "1fad6": "teiera", + "1f9c3": "bevanda monodose", + "1f9c9": "mate", + "1f9ed": "bussola", + "1f3d4": "montagna innevata", + "1f30b": "vulcano", + "1f3d5": "campeggio", + "1f3dd": "isola deserta", + "1f3e1": "casa con giardino", + "26f2": "fontana", + "1f3a0": "cavallo da giostra", + "1f3a1": "ruota panoramica", + "1f3a2": "montagne russe", + "1f488": "barbiere", + "1f686": "treno", + "1f68b": "vagone del tram", + "1f68d": "bus in arrivo", + "1f695": "taxi", + "1f697": "auto", + "1f69a": "camion", + "1f69c": "trattore", + "1f6f5": "scooter", + "1f6fa": "risciò a motore", + "1f6f4": "monopattino", + "1f6f9": "skateboard", + "1f6fc": "pattini a rotelle", + "2693": "ancora", + "26f5": "barca a vela", + "1f6f6": "canoa", + "1f6a4": "motoscafo", + "1f6a2": "nave", + "2708": "aeroplano", + "1f681": "elicottero", + "1f6a0": "funivia", + "1f6f0": "satellite", + "1f680": "razzo", + "1f6f8": "disco volante", + "23f0": "sveglia", + "1f319": "spicchio di luna", + "1f321": "termometro", + "2600": "sole", + "1fa90": "pianeta con satellite", + "1f31f": "stella che brilla", + "1f300": "ciclone", + "1f308": "arcobaleno", + "2602": "ombrello", + "2744": "fiocco di neve", + "2604": "cometa", + "1f525": "fuoco", + "1f4a7": "goccia", + "1f30a": "onda", + "1f383": "zucca di Halloween", + "2728": "stelline", + "1f388": "palloncino", + "1f389": "spara coriandoli", + "1f38f": "aquilone a forma di carpa", + "1f380": "fiocco", + "1f381": "regalo", + "1f39f": "biglietto d’ingresso", + "1f3c6": "coppa", + "26bd": "pallone da calcio", + "1f3c0": "palla da pallacanestro", + "1f3c8": "football americano", + "1f3be": "tennis", + "1f94f": "frisbee", + "1f3d3": "ping pong", + "1f3f8": "badminton", + "1f93f": "maschera da sub", + "1f94c": "stone da curling", + "1f3af": "bersaglio", + "1fa80": "yo-yo", + "1fa81": "aquilone", + "1f52e": "sfera di cristallo", + "1f3b2": "dado", + "1f9e9": "pezzo di puzzle", + "1f3a8": "tavolozza", + "1f9f5": "filo", + "1f455": "t-shirt", + "1f9e6": "calzini", + "1f457": "vestito", + "1fa73": "pantaloncini", + "1f392": "zaino", + "1f45f": "scarpa sportiva", + "1f451": "corona", + "1f9e2": "cappello con visiera", + "1f484": "rossetto", + "1f48d": "anello", + "1f48e": "gemma", + "1f4e2": "altoparlante", + "1f3b6": "note musicali", + "1f399": "microfono radiofonico", + "1f4fb": "radio", + "1f3b7": "sassofono", + "1fa97": "fisarmonica", + "1f3b8": "chitarra", + "1f3ba": "tromba", + "1f3bb": "violino", + "1fa95": "banjo", + "1f941": "tamburo", + "260e": "telefono fisso", + "1f50b": "batteria", + "1f4bf": "disco ottico", + "1f9ee": "abaco", + "1f3ac": "ciak", + "1f4a1": "lampadina", + "1f526": "torcia", + "1f3ee": "lanterna rossa", + "1f4d5": "libro chiuso", + "1f3f7": "etichetta", + "1f4b3": "carta di credito", + "270f": "matita", + "1f58c": "pennello", + "1f58d": "pastello a cera", + "1f4cc": "puntina", + "1f4ce": "graffetta", + "1f511": "chiave", + "1fa83": "boomerang", + "1f3f9": "arco e freccia", + "2696": "bilancia a doppio piatto", + "1f9f2": "calamita", + "1f9ea": "provetta", + "1f9ec": "dna", + "1f52c": "microscopio", + "1f52d": "telescopio", + "1f4e1": "antenna satellitare", + "1fa91": "sedia", + "1f9f9": "scopa", + "1f5ff": "Moai" + }, + "ja": { + "1f47d": "エイリアン", + "1f916": "ロボット", + "1f9e0": "脳", + "1f441": "片目", + "1f9d9": "魔法使い", + "1f9da": "妖精", + "1f9dc": "人魚", + "1f435": "サルの顔", + "1f9a7": "オランウータン", + "1f436": "イヌの顔", + "1f43a": "オオカミの顔", + "1f98a": "キツネの顔", + "1f99d": "アライグマ", + "1f431": "ネコの顔", + "1f981": "ライオンの顔", + "1f42f": "トラの顔", + "1f434": "馬の顔", + "1f984": "ユニコーンの顔", + "1f993": "シマウマ", + "1f98c": "シカ", + "1f42e": "牛の顔", + "1f437": "ブタの顔", + "1f417": "イノシシ", + "1f42a": "ラクダ", + "1f999": "ラマ", + "1f992": "キリン", + "1f418": "ゾウ", + "1f9a3": "マンモス", + "1f98f": "サイ", + "1f42d": "ネズミの顔", + "1f430": "ウサギの顔", + "1f43f": "リス", + "1f994": "ハリネズミ", + "1f987": "コウモリ", + "1f43b": "クマの顔", + "1f428": "コアラ", + "1f9a5": "ナマケモノ", + "1f9a6": "カワウソ", + "1f998": "カンガルー", + "1f425": "前を向いているひよこ", + "1f426": "鳥", + "1f54a": "ハト", + "1f986": "カモ", + "1f989": "フクロウ", + "1f9a4": "ドードー", + "1fab6": "羽", + "1f9a9": "フラミンゴ", + "1f99a": "クジャク", + "1f99c": "オウム", + "1f40a": "ワニ", + "1f422": "カメ", + "1f98e": "トカゲ", + "1f40d": "ヘビ", + "1f432": "ドラゴンの顔", + "1f995": "草食恐竜", + "1f433": "潮吹きクジラ", + "1f42c": "イルカ", + "1f9ad": "アザラシ", + "1f41f": "魚", + "1f420": "熱帯魚", + "1f988": "サメ", + "1f419": "タコ", + "1f41a": "巻き貝", + "1f40c": "かたつむり", + "1f98b": "チョウ", + "1f41b": "毛虫", + "1f41d": "ミツバチ", + "1f41e": "テントウムシ", + "1f490": "花束", + "1f339": "バラ", + "1f33a": "ハイビスカス", + "1f33b": "ヒマワリ", + "1f337": "チューリップ", + "1f332": "常緑樹", + "1f333": "落葉樹", + "1f334": "ヤシの木", + "1f335": "サボテン", + "1f33f": "ハーブ", + "1f341": "かえで", + "1f344": "キノコ", + "1f347": "ぶどう", + "1f348": "メロン", + "1f349": "スイカ", + "1f34a": "みかん", + "1f34b": "レモン", + "1f34c": "バナナ", + "1f34d": "パイナップル", + "1f96d": "マンゴー", + "1f34f": "青リンゴ", + "1f350": "洋ナシ", + "1f351": "桃", + "1f352": "さくらんぼ", + "1f353": "いちご", + "1fad0": "ブルーベリー", + "1f95d": "キウイフルーツ", + "1f345": "トマト", + "1fad2": "オリーブ", + "1f965": "ココナツ", + "1f951": "アボカド", + "1f346": "ナス", + "1f955": "人参", + "1f33d": "とうもろこし", + "1f336": "とうがらし", + "1f96c": "葉野菜", + "1f966": "ブロッコリー", + "1f9c5": "タマネギ", + "1f95c": "ピーナッツ", + "1f950": "クロワッサン", + "1f956": "バゲット", + "1f968": "プレッツェル", + "1f96f": "ベーグル", + "1f95e": "パンケーキ", + "1f9c7": "ワッフル", + "1f354": "ハンバーガー", + "1f355": "ピザ", + "1f32d": "ホットドッグ", + "1f32e": "タコス", + "1f37f": "ポップコーン", + "1f980": "カニ", + "1f99e": "ザリガニ", + "1f368": "アイスクリーム", + "1f369": "ドーナツ", + "1f36a": "クッキー", + "1f382": "バースデーケーキ", + "1f9c1": "カップケーキ", + "1f36b": "チョコレート", + "1f36c": "キャンディ", + "1f36d": "ぺろぺろキャンディ", + "1fad6": "ティーポット", + "1f9c3": "紙パック飲料", + "1f9c9": "マテ茶", + "1f9ed": "コンパス", + "1f3d4": "雪山", + "1f30b": "火山", + "1f3d5": "キャンプ", + "1f3dd": "無人島", + "1f3e1": "庭付きの家", + "26f2": "噴水", + "1f3a0": "メリーゴーランド", + "1f3a1": "観覧車", + "1f3a2": "ジェットコースター", + "1f488": "床屋", + "1f686": "電車正面", + "1f68b": "路面電車", + "1f68d": "バス正面", + "1f695": "タクシー", + "1f697": "自動車", + "1f69a": "トラック", + "1f69c": "トラクター", + "1f6f5": "スクーター", + "1f6fa": "三輪タクシー", + "1f6f4": "キックボード", + "1f6f9": "スケートボード", + "1f6fc": "ローラースケート", + "2693": "錨", + "26f5": "ヨット", + "1f6f6": "カヌー", + "1f6a4": "スピードボート", + "1f6a2": "船", + "2708": "飛行機", + "1f681": "ヘリコプター", + "1f6a0": "ケーブルカー", + "1f6f0": "人工衛星", + "1f680": "ロケット", + "1f6f8": "空飛ぶ円盤", + "23f0": "目覚まし時計", + "1f319": "三日月", + "1f321": "温度計", + "2600": "太陽", + "1fa90": "環のある惑星", + "1f31f": "きらきら星", + "1f300": "渦巻き", + "1f308": "虹", + "2602": "傘", + "2744": "雪の結晶", + "2604": "彗星", + "1f525": "火", + "1f4a7": "水滴", + "1f30a": "波", + "1f383": "ハロウィンかぼちゃ", + "2728": "きらきら", + "1f388": "風船", + "1f389": "クラッカー", + "1f38f": "こいのぼり", + "1f380": "リボン", + "1f381": "プレゼント", + "1f39f": "入場券", + "1f3c6": "トロフィー", + "26bd": "サッカー", + "1f3c0": "バスケットボール", + "1f3c8": "アメフト", + "1f3be": "テニス", + "1f94f": "フリスビー", + "1f3d3": "卓球", + "1f3f8": "バドミントン", + "1f93f": "ダイビング マスク", + "1f94c": "カーリング", + "1f3af": "的", + "1fa80": "ヨーヨー", + "1fa81": "たこ", + "1f52e": "水晶玉", + "1f3b2": "サイコロ", + "1f9e9": "ジグソーパズル", + "1f3a8": "絵の具パレット", + "1f9f5": "糸", + "1f455": "Tシャツ", + "1f9e6": "ソックス", + "1f457": "ワンピース", + "1fa73": "ショーツ", + "1f392": "バックパック", + "1f45f": "スニーカー", + "1f451": "王冠", + "1f9e2": "キャップ", + "1f484": "口紅", + "1f48d": "指輪", + "1f48e": "宝石", + "1f4e2": "拡声器", + "1f3b6": "複数の音符", + "1f399": "スタジオマイク", + "1f4fb": "ラジオ", + "1f3b7": "サックス", + "1fa97": "アコーディオン", + "1f3b8": "ギター", + "1f3ba": "トランペット", + "1f3bb": "バイオリン", + "1fa95": "バンジョー", + "1f941": "ドラム", + "260e": "固定電話", + "1f50b": "電池", + "1f4bf": "CD", + "1f9ee": "そろばん", + "1f3ac": "カチンコ", + "1f4a1": "電球", + "1f526": "懐中電灯", + "1f3ee": "赤ちょうちん", + "1f4d5": "閉じた本", + "1f3f7": "荷札", + "1f4b3": "クレジットカード", + "270f": "鉛筆", + "1f58c": "絵筆", + "1f58d": "クレヨン", + "1f4cc": "押しピン", + "1f4ce": "クリップ", + "1f511": "鍵", + "1fa83": "ブーメラン", + "1f3f9": "弓矢", + "2696": "天秤", + "1f9f2": "U字型磁石", + "1f9ea": "試験管", + "1f9ec": "DNA", + "1f52c": "顕微鏡", + "1f52d": "望遠鏡", + "1f4e1": "パラボラアンテナ", + "1fa91": "椅子", + "1f9f9": "ほうき", + "1f5ff": "モアイ" + }, + "ka": { + "1f47d": "უცხოპლანეტელი", + "1f916": "რობოტის სახე", + "1f9e0": "ტვინი", + "1f441": "თვალი", + "1f9d9": "ჯადოქარი", + "1f9da": "ფერია", + "1f9dc": "ადამიანთევზა", + "1f435": "მაიმუნის სახე", + "1f9a7": "ორანგუტანი", + "1f436": "ძაღლის სახე", + "1f43a": "მგლის სახე", + "1f98a": "მელიის თავი", + "1f99d": "ენოტი", + "1f431": "კატის სახე", + "1f981": "ლომის სახე", + "1f42f": "ვეფხვის სახე", + "1f434": "ცხენის სახე", + "1f984": "ზღაპრული მარტორქის სახე", + "1f993": "ზებრა", + "1f98c": "ირემი", + "1f42e": "ძროხის სახე", + "1f437": "ღორის სახე", + "1f417": "ტახი", + "1f42a": "აქლემი", + "1f999": "ლამა", + "1f992": "ჟირაფი", + "1f418": "სპილო", + "1f9a3": "მამონტი", + "1f98f": "მარტორქა", + "1f42d": "თაგვის სახე", + "1f430": "კურდღლის სახე", + "1f43f": "ციყვი", + "1f994": "ზღარბი", + "1f987": "ღამურა", + "1f43b": "დათვის სახე", + "1f428": "კოალა", + "1f9a5": "ზარმაცა", + "1f9a6": "წავი", + "1f998": "კენგურუ", + "1f425": "პატარა წიწილა წინიდან", + "1f426": "ჩიტი", + "1f54a": "მტრედი", + "1f986": "იხვი", + "1f989": "ბუ", + "1f9a4": "დოდო", + "1fab6": "ბუმბული", + "1f9a9": "ფლამინგო", + "1f99a": "ფარშევანგი", + "1f99c": "თუთიყუში", + "1f40a": "ნიანგი", + "1f422": "კუ", + "1f98e": "ხვლიკი", + "1f40d": "გველი", + "1f432": "დრაკონის სახე", + "1f995": "ზაუროპოდი", + "1f433": "ვეშაპი ჭავლით", + "1f42c": "დელფინი", + "1f9ad": "სელაპი", + "1f41f": "თევზი", + "1f420": "ტროპიკული თევზი", + "1f988": "ზვიგენი", + "1f419": "რვაფეხა", + "1f41a": "სპირალური ნიჟარა", + "1f40c": "ლოკოკინა", + "1f98b": "პეპელა", + "1f41b": "ბაღლინჯო", + "1f41d": "ფუტკარი", + "1f41e": "ჭიამაია", + "1f490": "თაიგული", + "1f339": "ვარდი", + "1f33a": "ჰიბისკუსი", + "1f33b": "მზესუმზირა", + "1f337": "ტიტა", + "1f332": "მარადმწვანე", + "1f333": "ფოთლოვანი ხე", + "1f334": "პალმა", + "1f335": "კაქტუსი", + "1f33f": "სამკურნალო მცენარე", + "1f341": "ნეკერჩხლის ფოთოლი", + "1f344": "სოკო", + "1f347": "ყურძენი", + "1f348": "ნესვი", + "1f349": "საზამთრო", + "1f34a": "მანდარინი", + "1f34b": "ლიმონი", + "1f34c": "ბანანი", + "1f34d": "ანანასი", + "1f96d": "მანგო", + "1f34f": "მწვანე ვაშლი", + "1f350": "მსხალი", + "1f351": "ატამი", + "1f352": "ალუბალი", + "1f353": "მარწყვი", + "1fad0": "მოცვი", + "1f95d": "კივი", + "1f345": "პამიდორი", + "1fad2": "ზეითუნი", + "1f965": "ქოქოსი", + "1f951": "ავოკადო", + "1f346": "ბადრიჯანი", + "1f955": "სტაფილო", + "1f33d": "სიმინდის ტარო", + "1f336": "ცხარე წიწაკა", + "1f96c": "სალათის ფოთოლი", + "1f966": "ბროკოლი", + "1f9c5": "ხახვი", + "1f95c": "მიწის თხილი", + "1f950": "კრუასანი", + "1f956": "ბაგეტი", + "1f968": "პრეცელი", + "1f96f": "ბეიგელი", + "1f95e": "ბლინები", + "1f9c7": "ვაფლი", + "1f354": "ჰამბურგერი", + "1f355": "პიცა", + "1f32d": "ჰოთდოგი", + "1f32e": "ტაკო", + "1f37f": "ბატი-ბუტი", + "1f980": "კიბორჩხალა", + "1f99e": "კიბო", + "1f368": "ნაყინი", + "1f369": "დონატი", + "1f36a": "ფხვიერი ნამცხვარი", + "1f382": "დაბადების დღის ტორტი", + "1f9c1": "ქაფქეიქი", + "1f36b": "შოკოლადის ფილა", + "1f36c": "კანფეტი", + "1f36d": "კანფეტი ჯოხზე", + "1fad6": "ჩაიდანი", + "1f9c3": "წვენი პაკეტში", + "1f9c9": "მატე", + "1f9ed": "კომპასი", + "1f3d4": "თოვლით დაფარული მთა", + "1f30b": "ვულკანი", + "1f3d5": "კემპინგი", + "1f3dd": "უკაცრიელი კუნძული", + "1f3e1": "სახლი ბაღით", + "26f2": "შადრევანი", + "1f3a0": "კარუსელის ცხენი", + "1f3a1": "ეშმაკის ბორბალი", + "1f3a2": "ამერიკული გორაკები", + "1f488": "დალაქის სვეტი", + "1f686": "მატარებელი", + "1f68b": "ტრამვაის ვაგონი", + "1f68d": "მომავალი ავტობუსი", + "1f695": "ტაქსი", + "1f697": "ავტომობილი", + "1f69a": "მიმწოდებელი სატვირთო მანქანა", + "1f69c": "ტრაქტორი", + "1f6f5": "სკუტერი ძრავით", + "1f6fa": "ავტორიქშა", + "1f6f4": "ფეხის სკუტერი", + "1f6f9": "სკეიტბორდი", + "1f6fc": "გორგოლაჭიანი ციგურები", + "2693": "ღუზა", + "26f5": "იალქნიანი ნავი", + "1f6f6": "კანოე", + "1f6a4": "გლისერი", + "1f6a2": "გემი", + "2708": "თვითმფრინავი", + "1f681": "ვერტმფრენი", + "1f6a0": "მთის საბაგირო", + "1f6f0": "თანამგზავრი", + "1f680": "რაკეტა", + "1f6f8": "მფრინავი თეფში", + "23f0": "მაღვიძარა", + "1f319": "ნამგალა მთვარე", + "1f321": "თერმომეტრი", + "2600": "მზე", + "1fa90": "პლანეტა სარტყელით", + "1f31f": "მბრწყინავი ვარსკვლავი", + "1f300": "ციკლონი", + "1f308": "ცისარტყელა", + "2602": "ქოლგა", + "2744": "თოვლის ფანტელი", + "2604": "კომეტა", + "1f525": "ცეცხლი", + "1f4a7": "წვეთი", + "1f30a": "წყლის ტალღა", + "1f383": "ჰელოუინის გოგრა", + "2728": "ნაპერწკლები", + "1f388": "ბუშტი", + "1f389": "ტკაცუნა", + "1f38f": "კობრებიანი ალამი", + "1f380": "ლენტი", + "1f381": "შეფუთული საჩუქარი", + "1f39f": "ბილეთები", + "1f3c6": "პრიზი", + "26bd": "ფეხბურთი", + "1f3c0": "კალათბურთი", + "1f3c8": "ამერიკული ფეხბურთი", + "1f3be": "ჩოგბურთი", + "1f94f": "მფრინავი დისკი", + "1f3d3": "მაგიდის ჩოგბურთი", + "1f3f8": "ბადმინტონი", + "1f93f": "წყლის ნიღაბი", + "1f94c": "კერლინგის ქვა", + "1f3af": "პირდაპირი მოხვედრა", + "1fa80": "იო-იო", + "1fa81": "ფრანი", + "1f52e": "კრისტალის ბურთი", + "1f3b2": "კამათელი", + "1f9e9": "პაზლი", + "1f3a8": "მხატვრის პალიტრა", + "1f9f5": "ძაფის კოჭა", + "1f455": "მაისური", + "1f9e6": "წინდები", + "1f457": "კაბა", + "1fa73": "შორტები", + "1f392": "სკოლის ზურგჩანთა", + "1f45f": "ბოტასი", + "1f451": "გვირგვინი", + "1f9e2": "ბეისბოლის კეპი", + "1f484": "ტუჩის პომადა", + "1f48d": "ბეჭედი", + "1f48e": "ძვირფასი ქვა", + "1f4e2": "რუპორი", + "1f3b6": "მუსიკალური ნოტები", + "1f399": "სტუდიური მიკროფონი", + "1f4fb": "რადიო", + "1f3b7": "საქსოფონი", + "1fa97": "აკორდეონი", + "1f3b8": "გიტარა", + "1f3ba": "საყვირი", + "1f3bb": "ვიოლინო", + "1fa95": "ბანჯო", + "1f941": "ბარაბანი", + "260e": "ტელეფონი", + "1f50b": "ბატარეა", + "1f4bf": "ოპტიკური დისკი", + "1f9ee": "საანგარიშო დაფა", + "1f3ac": "ნუმერატორი ტკაცუნათი", + "1f4a1": "ნათურა", + "1f526": "ფანარი", + "1f3ee": "ქაღალდის წითელი ფარანი", + "1f4d5": "დახურული წიგნი", + "1f3f7": "იარლიყი", + "1f4b3": "საკრედიტო ბარათი", + "270f": "ფანქარი", + "1f58c": "სახატავი ფუნჯი", + "1f58d": "ფერადი ფანქარი", + "1f4cc": "ჭიკარტი", + "1f4ce": "ქაღალდის სამაგრი", + "1f511": "გასაღები", + "1fa83": "ბუმერანგი", + "1f3f9": "მშვილდ-ისარი", + "2696": "ბერკეტიანი სასწორი", + "1f9f2": "მაგნიტი", + "1f9ea": "სინჯარა", + "1f9ec": "დნმ", + "1f52c": "მიკროსკოპი", + "1f52d": "ტელესკოპი", + "1f4e1": "თანამგზავრული ანტენა", + "1fa91": "სკამი", + "1f9f9": "ცოცხი", + "1f5ff": "მოაი" + }, + "ko": { + "1f47d": "외계인", + "1f916": "로봇 얼굴", + "1f9e0": "뇌", + "1f441": "눈", + "1f9d9": "마법사", + "1f9da": "요정", + "1f9dc": "인어", + "1f435": "원숭이 얼굴", + "1f9a7": "오랑우탄", + "1f436": "강아지 얼굴", + "1f43a": "늑대 얼굴", + "1f98a": "여우 얼굴", + "1f99d": "너구리", + "1f431": "고양이 얼굴", + "1f981": "사자 얼굴", + "1f42f": "호랑이 얼굴", + "1f434": "말 얼굴", + "1f984": "유니콘 얼굴", + "1f993": "얼룩말", + "1f98c": "사슴", + "1f42e": "소 얼굴", + "1f437": "돼지 얼굴", + "1f417": "멧돼지", + "1f42a": "낙타", + "1f999": "라마", + "1f992": "기린", + "1f418": "코끼리", + "1f9a3": "매머드", + "1f98f": "코뿔소", + "1f42d": "쥐 얼굴", + "1f430": "토끼 얼굴", + "1f43f": "얼룩다람쥐", + "1f994": "고슴도치", + "1f987": "박쥐", + "1f43b": "곰 얼굴", + "1f428": "코알라", + "1f9a5": "나무늘보", + "1f9a6": "수달", + "1f998": "캥거루", + "1f425": "정면을 향해 날개를 편 병아리", + "1f426": "새", + "1f54a": "비둘기", + "1f986": "오리", + "1f989": "부엉이", + "1f9a4": "도도새", + "1fab6": "깃털", + "1f9a9": "홍학", + "1f99a": "공작", + "1f99c": "앵무새", + "1f40a": "악어", + "1f422": "거북이", + "1f98e": "도마뱀", + "1f40d": "뱀", + "1f432": "용 얼굴", + "1f995": "초식 공룡", + "1f433": "물 뿜는 고래", + "1f42c": "돌고래", + "1f9ad": "물개", + "1f41f": "물고기", + "1f420": "열대어", + "1f988": "상어", + "1f419": "문어", + "1f41a": "달팽이집", + "1f40c": "달팽이", + "1f98b": "나비", + "1f41b": "송충이", + "1f41d": "꿀벌", + "1f41e": "무당벌레", + "1f490": "꽃다발", + "1f339": "장미꽃", + "1f33a": "무궁화", + "1f33b": "해바라기", + "1f337": "튤립", + "1f332": "소나무", + "1f333": "나무", + "1f334": "야자수", + "1f335": "선인장", + "1f33f": "풀", + "1f341": "단풍잎", + "1f344": "버섯", + "1f347": "포도", + "1f348": "멜론", + "1f349": "수박", + "1f34a": "귤", + "1f34b": "레몬", + "1f34c": "바나나", + "1f34d": "파인애플", + "1f96d": "망고", + "1f34f": "초록 사과", + "1f350": "배", + "1f351": "복숭아", + "1f352": "체리", + "1f353": "딸기", + "1fad0": "블루베리", + "1f95d": "키위", + "1f345": "토마토", + "1fad2": "올리브", + "1f965": "코코넛", + "1f951": "아보카도", + "1f346": "가지", + "1f955": "당근", + "1f33d": "옥수수", + "1f336": "홍고추", + "1f96c": "녹색 채소", + "1f966": "브로콜리", + "1f9c5": "양파", + "1f95c": "땅콩", + "1f950": "크루아상", + "1f956": "바게트", + "1f968": "프레첼", + "1f96f": "베이글", + "1f95e": "팬케이크", + "1f9c7": "와플", + "1f354": "햄버거", + "1f355": "피자", + "1f32d": "핫도그", + "1f32e": "타코", + "1f37f": "팝콘", + "1f980": "꽃게", + "1f99e": "바닷가재", + "1f368": "아이스크림", + "1f369": "도넛", + "1f36a": "쿠키", + "1f382": "생일 케이크", + "1f9c1": "컵케이크", + "1f36b": "초콜렛", + "1f36c": "사탕", + "1f36d": "롤리팝", + "1fad6": "찻주전자", + "1f9c3": "음료 팩", + "1f9c9": "마테차", + "1f9ed": "나침반", + "1f3d4": "눈 덮인 산", + "1f30b": "화산", + "1f3d5": "캠핑", + "1f3dd": "사막 섬", + "1f3e1": "정원이 있는 집", + "26f2": "분수", + "1f3a0": "회전 목마", + "1f3a1": "관람차", + "1f3a2": "롤러코스터", + "1f488": "이발소", + "1f686": "기차", + "1f68b": "트램 차량", + "1f68d": "오고 있는 버스", + "1f695": "택시", + "1f697": "자동차", + "1f69a": "운송 트럭", + "1f69c": "트랙터", + "1f6f5": "스쿠터", + "1f6fa": "경삼륜차", + "1f6f4": "킥보드", + "1f6f9": "스케이트보드", + "1f6fc": "롤러스케이트", + "2693": "닻", + "26f5": "돛단배", + "1f6f6": "카누", + "1f6a4": "쾌속정", + "1f6a2": "선박", + "2708": "비행기", + "1f681": "헬리콥터", + "1f6a0": "산악 케이블카", + "1f6f0": "인공위성", + "1f680": "로켓", + "1f6f8": "비행접시", + "23f0": "알람 시계", + "1f319": "초승달", + "1f321": "온도계", + "2600": "태양", + "1fa90": "고리가 있는 행성", + "1f31f": "반짝이는 별", + "1f300": "태풍", + "1f308": "무지개", + "2602": "우산", + "2744": "눈송이", + "2604": "혜성", + "1f525": "불", + "1f4a7": "물방울", + "1f30a": "파도", + "1f383": "할로윈", + "2728": "블링블링", + "1f388": "풍선", + "1f389": "파티", + "1f38f": "물고기 깃발", + "1f380": "리본", + "1f381": "선물", + "1f39f": "입장 티켓", + "1f3c6": "트로피", + "26bd": "축구공", + "1f3c0": "농구", + "1f3c8": "미식축구공", + "1f3be": "테니스", + "1f94f": "원반", + "1f3d3": "탁구", + "1f3f8": "배드민턴", + "1f93f": "다이빙 마스크", + "1f94c": "컬링 스톤", + "1f3af": "과녁 명중", + "1fa80": "요요", + "1fa81": "연", + "1f52e": "수정 구슬", + "1f3b2": "주사위", + "1f9e9": "퍼즐", + "1f3a8": "팔레트", + "1f9f5": "실타래", + "1f455": "티셔츠", + "1f9e6": "양말", + "1f457": "원피스", + "1fa73": "반바지", + "1f392": "학교 가방", + "1f45f": "운동화", + "1f451": "왕관", + "1f9e2": "야구모자", + "1f484": "립스틱", + "1f48d": "반지", + "1f48e": "원석", + "1f4e2": "확성기", + "1f3b6": "노래 음표", + "1f399": "스튜디오 마이크", + "1f4fb": "라디오", + "1f3b7": "색소폰", + "1fa97": "아코디언", + "1f3b8": "기타", + "1f3ba": "트럼펫", + "1f3bb": "바이올린", + "1fa95": "밴조", + "1f941": "드럼", + "260e": "전화기", + "1f50b": "배터리", + "1f4bf": "씨디", + "1f9ee": "주판", + "1f3ac": "슬레이트", + "1f4a1": "전구", + "1f526": "손전등", + "1f3ee": "일본식 등", + "1f4d5": "펼치지 않은 책", + "1f3f7": "라벨", + "1f4b3": "신용카드", + "270f": "연필", + "1f58c": "붓", + "1f58d": "크레용", + "1f4cc": "압정", + "1f4ce": "클립", + "1f511": "열쇠", + "1fa83": "부메랑", + "1f3f9": "활과 화살", + "2696": "접시저울", + "1f9f2": "자석", + "1f9ea": "시험관", + "1f9ec": "DNA", + "1f52c": "현미경", + "1f52d": "망원경", + "1f4e1": "위성 안테나", + "1fa91": "의자", + "1f9f9": "빗자루", + "1f5ff": "모아이" + }, + "lt": { + "1f47d": "ateivis", + "1f916": "roboto veidas", + "1f9e0": "smegenys", + "1f441": "akis", + "1f9d9": "magas", + "1f9da": "fėja", + "1f9dc": "undinius", + "1f435": "beždžionės snukutis", + "1f9a7": "orangutangas", + "1f436": "šuns snukutis", + "1f43a": "vilko snukis", + "1f98a": "lapės snukis", + "1f99d": "meškėnas", + "1f431": "katės snukutis", + "1f981": "liūto snukis", + "1f42f": "tigro snukis", + "1f434": "arklio snukis", + "1f984": "vienaragio snukis", + "1f993": "zebras", + "1f98c": "elnias", + "1f42e": "karvės snukis", + "1f437": "kiaulės snukis", + "1f417": "šernas", + "1f42a": "kupranugaris", + "1f999": "lama", + "1f992": "žirafa", + "1f418": "dramblys", + "1f9a3": "mamutas", + "1f98f": "raganosis", + "1f42d": "pelės snukutis", + "1f430": "triušio snukutis", + "1f43f": "voverė", + "1f994": "ežys", + "1f987": "šikšnosparnis", + "1f43b": "meškos snukis", + "1f428": "koala", + "1f9a5": "tinginys", + "1f9a6": "ūdra", + "1f998": "kengūra", + "1f425": "atsisukęs snapu viščiukas", + "1f426": "paukštis", + "1f54a": "balandis", + "1f986": "antis", + "1f989": "pelėda", + "1f9a4": "drontas", + "1fab6": "plunksna", + "1f9a9": "flamingas", + "1f99a": "povas", + "1f99c": "papūga", + "1f40a": "krokodilas", + "1f422": "vėžlys", + "1f98e": "driežas", + "1f40d": "gyvatė", + "1f432": "drakono snukis", + "1f995": "sauropodas", + "1f433": "purškiantis banginis", + "1f42c": "delfinas", + "1f9ad": "ruonis", + "1f41f": "žuvis", + "1f420": "tropinė žuvis", + "1f988": "ryklys", + "1f419": "aštuonkojis", + "1f41a": "susisukusi kriauklė", + "1f40c": "sraigė", + "1f98b": "drugelis", + "1f41b": "vabalas", + "1f41d": "bitė", + "1f41e": "boružė", + "1f490": "puokštė", + "1f339": "rožė", + "1f33a": "kinrožė", + "1f33b": "saulėgrąža", + "1f337": "tulpė", + "1f332": "amžinai žaliuojantis medis", + "1f333": "lapuotis", + "1f334": "palmė", + "1f335": "kaktusas", + "1f33f": "žolelė", + "1f341": "klevo lapas", + "1f344": "grybas", + "1f347": "vynuogės", + "1f348": "melionas", + "1f349": "arbūzas", + "1f34a": "mandarinas", + "1f34b": "citrina", + "1f34c": "bananas", + "1f34d": "ananasas", + "1f96d": "mangas", + "1f34f": "žalias obuolys", + "1f350": "kriaušė", + "1f351": "persikas", + "1f352": "vyšnios", + "1f353": "braškė", + "1fad0": "mėlynės", + "1f95d": "kivis", + "1f345": "pomidoras", + "1fad2": "alyvuogė", + "1f965": "kokosas", + "1f951": "avokadas", + "1f346": "baklažanas", + "1f955": "morka", + "1f33d": "kukurūzo burbuolė", + "1f336": "aštrusis pipiras", + "1f96c": "lapinė daržovė", + "1f966": "brokolis", + "1f9c5": "svogūnas", + "1f95c": "žemės riešutas", + "1f950": "raguolis", + "1f956": "ilgas batonas", + "1f968": "riestainis", + "1f96f": "apvalus riestainis", + "1f95e": "blynai", + "1f9c7": "vaflis", + "1f354": "mėsainis", + "1f355": "pica", + "1f32d": "dešrainis", + "1f32e": "meksikietiškas paplotėlis", + "1f37f": "spragėsiai", + "1f980": "krabas", + "1f99e": "omaras", + "1f368": "ledai", + "1f369": "spurga", + "1f36a": "sausainis", + "1f382": "gimtadienio tortas", + "1f9c1": "keksiukas", + "1f36b": "šokolado batonėlis", + "1f36c": "saldainis", + "1f36d": "ledinukas ant pagaliuko", + "1fad6": "arbatinukas", + "1f9c3": "gėrimo pakelis", + "1f9c9": "matė", + "1f9ed": "kompasas", + "1f3d4": "kalnas su snieguota viršūne", + "1f30b": "ugnikalnis", + "1f3d5": "stovyklavimas", + "1f3dd": "atoki sala", + "1f3e1": "namas su sodu", + "26f2": "fontanas", + "1f3a0": "karuselės arkliukas", + "1f3a1": "apžvalgos ratas", + "1f3a2": "linksmieji kalneliai", + "1f488": "kirpėjo suktukas", + "1f686": "traukinys", + "1f68b": "tramvajaus vagonas", + "1f68d": "artėjantis autobusas", + "1f695": "taksi", + "1f697": "automobilis", + "1f69a": "krovininis sunkvežimis", + "1f69c": "traktorius", + "1f6f5": "motoroleris", + "1f6fa": "autorikša", + "1f6f4": "paspirtukas", + "1f6f9": "riedlentė", + "1f6fc": "riedučiai", + "2693": "inkaras", + "26f5": "burlaivis", + "1f6f6": "kanoja", + "1f6a4": "motorinis kateris", + "1f6a2": "laivas", + "2708": "lėktuvas", + "1f681": "sraigstasparnis", + "1f6a0": "kalnų keltuvas", + "1f6f0": "palydovas", + "1f680": "raketa", + "1f6f8": "skraidanti lėkštė", + "23f0": "žadintuvas", + "1f319": "pusmėnulis", + "1f321": "termometras", + "2600": "saulė", + "1fa90": "planeta su žiedu", + "1f31f": "žėrinti žvaigždė", + "1f300": "ciklonas", + "1f308": "vaivorykštė", + "2602": "skėtis", + "2744": "snaigė", + "2604": "kometa", + "1f525": "ugnis", + "1f4a7": "lašas", + "1f30a": "vandens banga", + "1f383": "žibintas iš moliūgo", + "2728": "kibirkštėlės", + "1f388": "balionas", + "1f389": "konfeti šaudyklė", + "1f38f": "karpio vėtrungė", + "1f380": "kaspinas", + "1f381": "supakuota dovana", + "1f39f": "įėjimo bilietai", + "1f3c6": "trofėjus", + "26bd": "futbolo kamuolys", + "1f3c0": "krepšinio kamuolys", + "1f3c8": "amerikietiškojo futbolo kamuolys", + "1f3be": "teniso kamuoliukas", + "1f94f": "skraidantis diskas", + "1f3d3": "stalo tenisas", + "1f3f8": "badmintonas", + "1f93f": "nardymo kaukė", + "1f94c": "akmenslydis", + "1f3af": "smūgis tiesiai į taikinį", + "1fa80": "jo-jo", + "1fa81": "aitvaras", + "1f52e": "krištolinis rutulys", + "1f3b2": "kauliukas", + "1f9e9": "dėlionė", + "1f3a8": "dailininko paletė", + "1f9f5": "siūlas", + "1f455": "marškinėliai", + "1f9e6": "kojinės", + "1f457": "suknelė", + "1fa73": "šortai", + "1f392": "mokyklinė kuprinė", + "1f45f": "bėgimo batelis", + "1f451": "karūna", + "1f9e2": "reklaminė kepurė", + "1f484": "lūpų dažai", + "1f48d": "žiedas", + "1f48e": "brangakmenis", + "1f4e2": "garsiakalbio simbolis", + "1f3b6": "muzikos natos", + "1f399": "studijos mikrofonas", + "1f4fb": "radijas", + "1f3b7": "saksofonas", + "1fa97": "akordeonas", + "1f3b8": "gitara", + "1f3ba": "trimitas", + "1f3bb": "smuikas", + "1fa95": "bandža", + "1f941": "būgnas", + "260e": "telefonas", + "1f50b": "baterija", + "1f4bf": "optinis diskas", + "1f9ee": "skaitytuvai", + "1f3ac": "pliauškė", + "1f4a1": "lemputė", + "1f526": "žibintuvėlis", + "1f3ee": "raudonas popierinis žibintas", + "1f4d5": "užversta knyga", + "1f3f7": "etiketė", + "1f4b3": "kredito kortelė", + "270f": "pieštukas", + "1f58c": "teptukas", + "1f58d": "kreidelė", + "1f4cc": "smeigtukas", + "1f4ce": "sąvaržėlė", + "1f511": "raktas", + "1fa83": "bumerangas", + "1f3f9": "lankas ir strėlė", + "2696": "svarstyklės su lėkštėmis", + "1f9f2": "magnetas", + "1f9ea": "mėgintuvėlis", + "1f9ec": "DNR", + "1f52c": "mikroskopas", + "1f52d": "teleskopas", + "1f4e1": "palydovinė antena", + "1fa91": "kėdė", + "1f9f9": "šluota", + "1f5ff": "moai" + }, + "mk": { + "1f47d": "вонземјанин", + "1f916": "робот", + "1f9e0": "мозок", + "1f441": "око", + "1f9d9": "магичар", + "1f9da": "самовила", + "1f9dc": "морско лице", + "1f435": "глава на мајмун", + "1f9a7": "орангутан", + "1f436": "глава на куче", + "1f43a": "волк", + "1f98a": "лисица", + "1f99d": "ракун", + "1f431": "глава на мачка", + "1f981": "лав", + "1f42f": "глава на тигар", + "1f434": "глава на коњ", + "1f984": "еднорог", + "1f993": "зебра", + "1f98c": "елен", + "1f42e": "глава на крава", + "1f437": "глава на прасе", + "1f417": "дива свиња", + "1f42a": "камила", + "1f999": "лама", + "1f992": "жирафа", + "1f418": "слон", + "1f9a3": "мамут", + "1f98f": "носорог", + "1f42d": "глава на глушец", + "1f430": "глава на зајак", + "1f43f": "верверица", + "1f994": "еж", + "1f987": "лилјак", + "1f43b": "мечка", + "1f428": "коала", + "1f9a5": "мрзливец", + "1f9a6": "видра", + "1f998": "кенгур", + "1f425": "пиле свртено нанапред", + "1f426": "птица", + "1f54a": "гулабица", + "1f986": "патка", + "1f989": "був", + "1f9a4": "додо", + "1fab6": "пердув", + "1f9a9": "фламинго", + "1f99a": "паун", + "1f99c": "папагал", + "1f40a": "крокодил", + "1f422": "желка", + "1f98e": "гуштер", + "1f40d": "змија", + "1f432": "глава на змеј", + "1f995": "сауропод", + "1f433": "кит што прска вода", + "1f42c": "делфин", + "1f9ad": "фока", + "1f41f": "риба", + "1f420": "тропска риба", + "1f988": "ајкула", + "1f419": "октопод", + "1f41a": "спирална школка", + "1f40c": "полжав", + "1f98b": "пеперутка", + "1f41b": "бубачка", + "1f41d": "пчела", + "1f41e": "бубамара", + "1f490": "букет", + "1f339": "роза", + "1f33a": "хибискус", + "1f33b": "сончоглед", + "1f337": "лале", + "1f332": "зимзелено дрво", + "1f333": "листопадно дрво", + "1f334": "палма", + "1f335": "кактус", + "1f33f": "билка", + "1f341": "јаворов лист", + "1f344": "печурка", + "1f347": "грозје", + "1f348": "диња", + "1f349": "лубеница", + "1f34a": "мандарина", + "1f34b": "лимон", + "1f34c": "банана", + "1f34d": "ананас", + "1f96d": "манго", + "1f34f": "зелено јаболко", + "1f350": "круша", + "1f351": "праска", + "1f352": "цреши", + "1f353": "јагода", + "1fad0": "боровинки", + "1f95d": "киви", + "1f345": "домат", + "1fad2": "маслинка", + "1f965": "кокосов орев", + "1f951": "авокадо", + "1f346": "модар патлиџан", + "1f955": "морков", + "1f33d": "клас пченка", + "1f336": "лута пиперка", + "1f96c": "зелени листови", + "1f966": "брокола", + "1f9c5": "кромид", + "1f95c": "кикиритки", + "1f950": "кроасан", + "1f956": "багет", + "1f968": "перек", + "1f96f": "ѓеврек", + "1f95e": "палачинки", + "1f9c7": "вафла", + "1f354": "хамбургер", + "1f355": "пица", + "1f32d": "хот дог", + "1f32e": "тако", + "1f37f": "пуканки", + "1f980": "рак", + "1f99e": "јастог", + "1f368": "сладолед", + "1f369": "крофна", + "1f36a": "колаче", + "1f382": "роденденска торта", + "1f9c1": "тортичка", + "1f36b": "чоколадо", + "1f36c": "бонбона", + "1f36d": "лижалче", + "1fad6": "чајник", + "1f9c3": "сокче во тетрапак", + "1f9c9": "мате", + "1f9ed": "компас", + "1f3d4": "планина со снежен врв", + "1f30b": "вулкан", + "1f3d5": "кампување", + "1f3dd": "пуст остров", + "1f3e1": "куќа со градина", + "26f2": "фонтана", + "1f3a0": "коњче од вртелешка", + "1f3a1": "панорамско тркало", + "1f3a2": "тобоган", + "1f488": "столб пред берберница", + "1f686": "воз", + "1f68b": "вагон на трамвај", + "1f68d": "автобус што пристигнува", + "1f695": "такси", + "1f697": "автомобил", + "1f69a": "камион за испорака", + "1f69c": "трактор", + "1f6f5": "скутер", + "1f6fa": "моторизирана рикша", + "1f6f4": "тротинет", + "1f6f9": "скејтборд", + "1f6fc": "ролшуи", + "2693": "сидро", + "26f5": "едреник", + "1f6f6": "кајак", + "1f6a4": "глисер", + "1f6a2": "брод", + "2708": "авион", + "1f681": "хеликоптер", + "1f6a0": "планинска жичарница", + "1f6f0": "сателит", + "1f680": "ракета", + "1f6f8": "летечка чинија", + "23f0": "часовник со аларм", + "1f319": "месечев срп", + "1f321": "термометар", + "2600": "сонце", + "1fa90": "планета со прстени", + "1f31f": "светлечка ѕвезда", + "1f300": "циклон", + "1f308": "виножито", + "2602": "чадор", + "2744": "снегулка", + "2604": "комета", + "1f525": "оган", + "1f4a7": "капка", + "1f30a": "бран", + "1f383": "фенер од тиква", + "2728": "светки", + "1f388": "балон", + "1f389": "прскалка со конфети", + "1f38f": "летало со крапови", + "1f380": "панделка", + "1f381": "завиткан подарок", + "1f39f": "влезни билети", + "1f3c6": "трофеј", + "26bd": "фудбалска топка", + "1f3c0": "баскет", + "1f3c8": "топка за американски фудбал", + "1f3be": "тениско топче", + "1f94f": "летечки диск", + "1f3d3": "пинг понг", + "1f3f8": "бадминтон", + "1f93f": "нуркачка маска", + "1f94c": "камен за карлинг", + "1f3af": "пикадо", + "1fa80": "јојо", + "1fa81": "летечки змеј", + "1f52e": "кристална топка", + "1f3b2": "коцка", + "1f9e9": "сложувалка", + "1f3a8": "сликарска палета", + "1f9f5": "конец", + "1f455": "маица", + "1f9e6": "чорапи", + "1f457": "фустан", + "1fa73": "шорцеви", + "1f392": "училишен ранец", + "1f45f": "патика", + "1f451": "круна", + "1f9e2": "капче", + "1f484": "кармин", + "1f48d": "прстен", + "1f48e": "скапоцен камен", + "1f4e2": "разглас", + "1f3b6": "музички ноти", + "1f399": "студиски микрофон", + "1f4fb": "радио", + "1f3b7": "саксофон", + "1fa97": "хармоника", + "1f3b8": "гитара", + "1f3ba": "труба", + "1f3bb": "виолина", + "1fa95": "бенџо", + "1f941": "тапан", + "260e": "телефон", + "1f50b": "батерија", + "1f4bf": "цд", + "1f9ee": "сметалка", + "1f3ac": "филмска клапа", + "1f4a1": "светилка", + "1f526": "батериска ламба", + "1f3ee": "црвен фенер", + "1f4d5": "затворена книга", + "1f3f7": "етикета", + "1f4b3": "кредитна картичка", + "270f": "молив", + "1f58c": "четка за боење", + "1f58d": "мрсна боица", + "1f4cc": "притискач", + "1f4ce": "спојувалка", + "1f511": "клуч", + "1fa83": "бумеранг", + "1f3f9": "лак и стрела", + "2696": "механичка вага", + "1f9f2": "магнет", + "1f9ea": "епрувета", + "1f9ec": "днк", + "1f52c": "микроскоп", + "1f52d": "телескоп", + "1f4e1": "сателитска антена", + "1fa91": "стол", + "1f9f9": "метла", + "1f5ff": "монолитни статуи" + }, + "ms": { + "1f47d": "makhluk asing", + "1f916": "robot", + "1f9e0": "otak", + "1f441": "mata", + "1f9d9": "ahli silap mata", + "1f9da": "pari-pari", + "1f9dc": "manusia duyung", + "1f435": "muka monyet", + "1f9a7": "orang utan", + "1f436": "muka anjing", + "1f43a": "serigala", + "1f98a": "rubah", + "1f99d": "rakun", + "1f431": "muka kucing", + "1f981": "singa", + "1f42f": "muka harimau", + "1f434": "muka kuda", + "1f984": "unikorn", + "1f993": "zebra", + "1f98c": "rusa", + "1f42e": "muka lembu", + "1f437": "muka khinzir", + "1f417": "babi hutan", + "1f42a": "unta", + "1f999": "llama", + "1f992": "zirafah", + "1f418": "gajah", + "1f9a3": "mamot", + "1f98f": "badak sumbu", + "1f42d": "muka tikus", + "1f430": "muka arnab", + "1f43f": "tupai tanah", + "1f994": "landak kecil", + "1f987": "kelawar", + "1f43b": "beruang", + "1f428": "koala", + "1f9a5": "sloth", + "1f9a6": "memerang", + "1f998": "kanggaru", + "1f425": "anak ayam menghadap depan", + "1f426": "burung", + "1f54a": "burung merpati", + "1f986": "itik", + "1f989": "burung hantu", + "1f9a4": "dodo", + "1fab6": "bulu pelepah", + "1f9a9": "flamingo", + "1f99a": "merak", + "1f99c": "kakak tua", + "1f40a": "buaya", + "1f422": "penyu", + "1f98e": "cicak", + "1f40d": "ular", + "1f432": "muka naga", + "1f995": "sauropod", + "1f433": "ikan paus memancutkan air", + "1f42c": "ikan lumba-lumba", + "1f9ad": "anjing laut", + "1f41f": "ikan", + "1f420": "ikan tropika", + "1f988": "jerung", + "1f419": "sotong kurita", + "1f41a": "kulit kerang berpilin", + "1f40c": "siput", + "1f98b": "rama-rama", + "1f41b": "ulat", + "1f41d": "lebah madu", + "1f41e": "kumbang kura-kura", + "1f490": "sejambak bunga", + "1f339": "bunga mawar", + "1f33a": "bunga raya", + "1f33b": "bunga matahari", + "1f337": "bunga tulip", + "1f332": "malar hijau", + "1f333": "pokok daun luruh", + "1f334": "pokok palma", + "1f335": "kaktus", + "1f33f": "herba", + "1f341": "daun mapel", + "1f344": "cendawan", + "1f347": "anggur", + "1f348": "tembikai susu", + "1f349": "tembikai", + "1f34a": "limau tangerin", + "1f34b": "lemon", + "1f34c": "pisang", + "1f34d": "nanas", + "1f96d": "mangga", + "1f34f": "epal hijau", + "1f350": "buah pear", + "1f351": "buah pic", + "1f352": "buah ceri", + "1f353": "buah strawberi", + "1fad0": "beri biru", + "1f95d": "buah kiwi", + "1f345": "tomato", + "1fad2": "buah zaitun", + "1f965": "kelapa", + "1f951": "avokado", + "1f346": "terung", + "1f955": "lobak merah", + "1f33d": "tongkol jagung", + "1f336": "cili api", + "1f96c": "sayuran hijau", + "1f966": "brokoli", + "1f9c5": "bawang", + "1f95c": "kacang tanah", + "1f950": "kroisan", + "1f956": "roti baguette", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "penkek", + "1f9c7": "wafel", + "1f354": "hamburger", + "1f355": "piza", + "1f32d": "hot dog", + "1f32e": "tako", + "1f37f": "bertih jagung", + "1f980": "ketam", + "1f99e": "udang karang", + "1f368": "ais krim", + "1f369": "donat", + "1f36a": "biskut", + "1f382": "kek hari jadi", + "1f9c1": "kek cawan", + "1f36b": "sekeping coklat", + "1f36c": "gula-gula", + "1f36d": "lolipop", + "1fad6": "teko teh", + "1f9c3": "minuman air kotak", + "1f9c9": "mate", + "1f9ed": "kompas", + "1f3d4": "gunung dengan puncak bersalji", + "1f30b": "gunung berapi", + "1f3d5": "berkhemah", + "1f3dd": "pulau padang pasir", + "1f3e1": "rumah dengan taman", + "26f2": "air pancut", + "1f3a0": "kuda karusel", + "1f3a1": "roda ferris", + "1f3a2": "roller coaster", + "1f488": "jalur kedai gunting rambut", + "1f686": "kereta api", + "1f68b": "gerabak trem", + "1f68d": "bas dari arah depan", + "1f695": "teksi", + "1f697": "kereta", + "1f69a": "trak penghantaran", + "1f69c": "traktor", + "1f6f5": "skuter bermotor", + "1f6fa": "lanca auto", + "1f6f4": "skuter tolak", + "1f6f9": "papan luncur", + "1f6fc": "kasut roda", + "2693": "sauh", + "26f5": "perahu layar", + "1f6f6": "kanu", + "1f6a4": "bot laju", + "1f6a2": "kapal", + "2708": "kapal terbang", + "1f681": "helikopter", + "1f6a0": "jalan kabel gunung", + "1f6f0": "satelit", + "1f680": "roket", + "1f6f8": "piring terbang", + "23f0": "jam loceng", + "1f319": "bulan sabit", + "1f321": "termometer", + "2600": "matahari", + "1fa90": "planet bergelang", + "1f31f": "bintang bersinar", + "1f300": "taufan", + "1f308": "pelangi", + "2602": "payung", + "2744": "emping salji", + "2604": "komet", + "1f525": "api", + "1f4a7": "titisan air", + "1f30a": "ombak laut", + "1f383": "tanglung labu", + "2728": "berkilauan", + "1f388": "belon", + "1f389": "pencetus bunyi parti", + "1f38f": "panji-panji kap", + "1f380": "reben", + "1f381": "bungkusan hadiah", + "1f39f": "tiket masuk", + "1f3c6": "piala", + "26bd": "bola sepak", + "1f3c0": "bola keranjang", + "1f3c8": "bola sepak amerika", + "1f3be": "tenis", + "1f94f": "cakera terbang", + "1f3d3": "ping pong", + "1f3f8": "badminton", + "1f93f": "topeng menyelam", + "1f94c": "batu curling", + "1f3af": "balingan tepat", + "1fa80": "yo-yo", + "1fa81": "layang-layang", + "1f52e": "bola kristal", + "1f3b2": "dadu permainan", + "1f9e9": "kepingan suai gambar", + "1f3a8": "palet artis", + "1f9f5": "benang", + "1f455": "kemeja-t", + "1f9e6": "stoking", + "1f457": "gaun", + "1fa73": "seluar pendek", + "1f392": "beg galas sekolah", + "1f45f": "kasut lari", + "1f451": "mahkota", + "1f9e2": "kep berbil", + "1f484": "gincu", + "1f48d": "cincin", + "1f48e": "batu permata", + "1f4e2": "corong pembesar suara", + "1f3b6": "nota-nota muzik", + "1f399": "mikrofon studio", + "1f4fb": "radio", + "1f3b7": "saksofon", + "1fa97": "akordion", + "1f3b8": "gitar", + "1f3ba": "trompet", + "1f3bb": "biola", + "1fa95": "banjo", + "1f941": "dram", + "260e": "telefon", + "1f50b": "bateri", + "1f4bf": "cakera optik", + "1f9ee": "sempua", + "1f3ac": "papan pengetap", + "1f4a1": "mentol lampu", + "1f526": "lampu suluh", + "1f3ee": "tanglung kertas merah", + "1f4d5": "buku tertutup", + "1f3f7": "label", + "1f4b3": "kad kredit", + "270f": "pensel", + "1f58c": "berus cat", + "1f58d": "krayon", + "1f4cc": "paku tekan", + "1f4ce": "klip kertas", + "1f511": "kunci", + "1fa83": "bumerang", + "1f3f9": "panah dan busur", + "2696": "neraca timbang", + "1f9f2": "magnet", + "1f9ea": "tabung uji", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "antena satelit", + "1fa91": "kerusi", + "1f9f9": "penyapu", + "1f5ff": "moyai" + }, + "my": { + "1f47d": "ဂြိုဟ်သား", + "1f916": "စက်ရုပ် မျက်နှာ", + "1f9e0": "ဦးနှောက်", + "1f441": "မျက်လုံး", + "1f9d9": "မှော်ဆရာ", + "1f9da": "နတ်သမီး", + "1f9dc": "ရေလူ", + "1f435": "မျောက်ရုပ်", + "1f9a7": "အိုရန်အူတန်", + "1f436": "ခွေးရုပ်", + "1f43a": "ဝံပုလွေရုပ်", + "1f98a": "မြေခွေးရုပ်", + "1f99d": "ရက်ကွန်းဝံ", + "1f431": "ကြောင်ရုပ်", + "1f981": "ခြင်္သေ့ရုပ်", + "1f42f": "ကျားရုပ်", + "1f434": "မြင်းရုပ်", + "1f984": "ချိုတစ်ချောင်းမြင်းရုပ်", + "1f993": "မြင်းကျား", + "1f98c": "သမင်", + "1f42e": "နွားမရုပ်", + "1f437": "ဝက်ရုပ်", + "1f417": "တောဝက်", + "1f42a": "ကုလားအုတ်", + "1f999": "လာမာ ကုလားအုတ်", + "1f992": "သစ်ကုလားအုတ်", + "1f418": "ဆင်", + "1f9a3": "ရှေးဆင်", + "1f98f": "ကြံ့", + "1f42d": "ကြွက် မျက်နှာ", + "1f430": "ယုန်ရုပ်", + "1f43f": "ကျောရိုးတွင် အဖြူအနက်စင်းပါ ရှဥ့်ငယ်တမျိုး", + "1f994": "ဖြူငယ်", + "1f987": "လင်းနို့", + "1f43b": "ဝက်ဝံရုပ်", + "1f428": "ကိုအာလာ", + "1f9a5": "မျောက်မောင်းမ", + "1f9a6": "ဖျံ", + "1f998": "သားပိုက်ကောင်", + "1f425": "ရှေ့သို့မျက်နှာမူထားသည့် ကြက်ပေါက်စ", + "1f426": "ငှက်", + "1f54a": "ချိုးငှက်", + "1f986": "ဘဲ", + "1f989": "ဇီးကွက်", + "1f9a4": "ဒိုဒို", + "1fab6": "အတောင်", + "1f9a9": "ကြိုးကြာနီ", + "1f99a": "ဒေါင်း", + "1f99c": "ကြက်တူရွေး", + "1f40a": "မိကျောင်း", + "1f422": "လိပ်", + "1f98e": "အိမ်မြှောင်", + "1f40d": "မြွေ", + "1f432": "နဂါးရုပ်", + "1f995": "ဆော်ရိုပေါ့ဒ်", + "1f433": "ရေမှုတ်ထုတ်နေသည့် ဝေလငါး", + "1f42c": "လင်းပိုင်", + "1f9ad": "ပင်လယ်ဖျံ", + "1f41f": "ငါး", + "1f420": "အပူပိုင်း ငါး", + "1f988": "ငါးမန်း", + "1f419": "ဘဝဲ", + "1f41a": "ခရုခွံ", + "1f40c": "ခရု", + "1f98b": "လိပ်ပြာ", + "1f41b": "ပိုးကောင်ကလေး", + "1f41d": "ပျား", + "1f41e": "ပိုးတောင်မာ", + "1f490": "ပန်းစည်း", + "1f339": "နှင်းဆီပန်း", + "1f33a": "ခေါင်ရန်းပန်း", + "1f33b": "နေကြာပန်း", + "1f337": "ကျူးလစ်ပန်း", + "1f332": "အမြဲစိမ်း သစ်ပင်", + "1f333": "ရွက်ပြတ်ပင်", + "1f334": "ထန်းပင်", + "1f335": "ရှားစောင်းပင်", + "1f33f": "ဆေးဖက်ဝင်အပင်", + "1f341": "မေပယ်ရွက်", + "1f344": "မှို", + "1f347": "စပျစ်သီး", + "1f348": "သခွားမွှေး", + "1f349": "ဖရဲသီး", + "1f34a": "အခွံပွလိမ္မော်သီး", + "1f34b": "ရှောက်သီး", + "1f34c": "ငှက်ပျောသီး", + "1f34d": "နာနတ်သီး", + "1f96d": "သရက်သီး", + "1f34f": "ပန်းသီးစိမ်း", + "1f350": "သစ်တော်သီး", + "1f351": "မက်မွန်သီး", + "1f352": "ချယ်ရီသီးများ", + "1f353": "စတော်ဘယ်ရီ", + "1fad0": "ဘလူးဘယ်ရီ", + "1f95d": "ကီဝီသီး", + "1f345": "ခရမ်းချဉ်သီး", + "1fad2": "သံလွင်", + "1f965": "အုန်းသီး", + "1f951": "ထောပတ်သီး", + "1f346": "ခရမ်းသီး", + "1f955": "မုန်လာဥ", + "1f33d": "ပြောင်းနှံ", + "1f336": "ငရုတ်သီး", + "1f96c": "အရွက်ဖားဖား သစ်ရွက်စိမ်း", + "1f966": "ပန်းဂေါ်ဖီစိမ်း", + "1f9c5": "ကြက်သွန်နီ", + "1f95c": "မြေပဲ", + "1f950": "လခြမ်းကွေးပေါင်မုန့်", + "1f956": "ပြင်သစ်ပေါင်မုန့်", + "1f968": "မုန့်ကြိုးလိမ်", + "1f96f": "ပေါင်မုန့်အကွင်း", + "1f95e": "မုန့်အိုးကင်းကြော်", + "1f9c7": "ဒေါင်းဖန်ဝါ မုန့်", + "1f354": "ဟမ်ဘာဂါ", + "1f355": "ပီဇာ", + "1f32d": "ဟော့ဒေါ့", + "1f32e": "တာကို", + "1f37f": "ပြောင်းဖူးပေါက်ပေါက်", + "1f980": "ကဏန်း", + "1f99e": "ကျောက်ပုစွန်", + "1f368": "ရေခဲမုန့်", + "1f369": "ဒိုးနတ်", + "1f36a": "ကွတ်ကီး", + "1f382": "မွေးနေ့ ကိတ်မုန့်", + "1f9c1": "ကြက်ဥမုန့်", + "1f36b": "ချောကလက် အချောင်း", + "1f36c": "သကြားလုံး", + "1f36d": "ချိုချဉ်ပလုတ်တုတ်", + "1fad6": "ကရား", + "1f9c3": "အဖျော်ရေ ဘူး", + "1f9c9": "ချီမာရအို", + "1f9ed": "သံလိုက်အိမ်မြှောင်", + "1f3d4": "ဆီးနှင်းဖုံးနေသည့် တောင်", + "1f30b": "မီးတောင်", + "1f3d5": "စခန်းချနေခြင်း", + "1f3dd": "လူသူမဲ့ကျွန်း", + "1f3e1": "ပန်းခြံနှင့် အိမ်", + "26f2": "အလှပြ ရေပန်း", + "1f3a0": "ချားရဟတ် မြင်း", + "1f3a1": "ချားရဟတ်", + "1f3a2": "သည်းဖိုရထား", + "1f488": "ဆံပင်ညှပ်ဆိုင် တိုင်", + "1f686": "ရထား", + "1f68b": "ဓာတ်ရထားတွဲ", + "1f68d": "လာနေသည့် ဘတ်စ်ကား", + "1f695": "တက်ကစီ", + "1f697": "မော်တော်ကား", + "1f69a": "ပစ္စည်းပို့သည့် ထရပ်ကား", + "1f69c": "လယ်ထွန်စက်", + "1f6f5": "မော်တာစက်တပ် စကူတာ", + "1f6fa": "သုံးဘီး", + "1f6f4": "စကူတာ", + "1f6f9": "စကိတ်လျှောပြား", + "1f6fc": "ရိုလာ စကိတ်", + "2693": "ကျောက်ဆူး", + "26f5": "ရွက်လှေ", + "1f6f6": "ကနူး", + "1f6a4": "အမြန်စက်လှေ", + "1f6a2": "သင်္ဘော", + "2708": "လေယာဉ်", + "1f681": "ရဟတ်ယာဉ်", + "1f6a0": "တောင်တက် ဓာတ်ကြိုးရထားလမ်း", + "1f6f0": "ဂြိုဟ်တု", + "1f680": "ဒုံးယာဉ်", + "1f6f8": "ပန်းကန်ပြားပျံ", + "23f0": "နှိုးစက်နာရီ", + "1f319": "လခြမ်း", + "1f321": "သာမိုမီတာ", + "2600": "နေ", + "1fa90": "ကွင်းပါရှိသည့် ဂြိုဟ်", + "1f31f": "တောက်ပသည့် ကြယ်", + "1f300": "ဆိုင်ကလုန်း", + "1f308": "သက်တံ", + "2602": "ထီး", + "2744": "နှင်းပွင့်", + "2604": "ကြယ်တံခွန်", + "1f525": "မီး", + "1f4a7": "အစက်ကလေး", + "1f30a": "ရေလှိုင်း", + "1f383": "ဖရုံသီး မီးအိမ်", + "2728": "မီးပွင့်များ", + "1f388": "လေပူဖောင်း", + "1f389": "ပါတီဗြောက်အိုး", + "1f38f": "ငါးကြင်း တံခွန်", + "1f380": "ဖဲကြိုး", + "1f381": "ထုပ်ပိုးထားသည့် လက်ဆောင်", + "1f39f": "ဝင်ခွင့် လက်မှတ်များ", + "1f3c6": "ဖလားဆု", + "26bd": "ဘောလုံး", + "1f3c0": "ဘတ်စကက်ဘော", + "1f3c8": "အမေရိကန် ဘောလုံး", + "1f3be": "တင်းနစ်", + "1f94f": "ချပ်ပြားဝိုင်း ပစ်", + "1f3d3": "စားပွဲတင် တင်းနစ်", + "1f3f8": "ကြက်တောင်ရိုက်ခြင်း", + "1f93f": "ရေငုပ် မျက်နှာဖုံး", + "1f94c": "ရေခဲပြင်ကျောက်ပြားဝိုင်း", + "1f3af": "ဗဟိုချက်ထိမှန်ခြင်း", + "1fa80": "ယိုယို", + "1fa81": "စွန်", + "1f52e": "ကသိုဏ်းဖန်လုံး", + "1f3b2": "အန်စာတုံး", + "1f9e9": "ဂျစ်စော အပိုင်းအစ", + "1f3a8": "ဆေးစပ်ရာ အပြား", + "1f9f5": "အပ်ချည်", + "1f455": "တီရှပ်", + "1f9e6": "ခြေအိတ်", + "1f457": "ဝတ်စုံ", + "1fa73": "ဘောင်းဘီတို", + "1f392": "ကျောင်းသား ကျောပိုးအိတ်", + "1f45f": "အပြေး ဖိနပ်", + "1f451": "သရဖူ", + "1f9e2": "ကက်ဦးထုတ်", + "1f484": "နှုတ်ခမ်းနီ", + "1f48d": "လက်စွပ်", + "1f48e": "ကျောက်မျက် ရတနာ", + "1f4e2": "အသံချဲ့စက်", + "1f3b6": "ဂီတ သင်္ကေတများ", + "1f399": "စတူဒီယို မိုက်ကရိုဖုန်း", + "1f4fb": "ရေဒီယို", + "1f3b7": "ဆက်ဆိုဖုန်း", + "1fa97": "အကော်ဒီယံ", + "1f3b8": "ဂစ်တာ", + "1f3ba": "ခရာ", + "1f3bb": "တယော", + "1fa95": "ဘင်ဂျို", + "1f941": "ဗုံ", + "260e": "တယ်လီဖုန်း", + "1f50b": "ဘက်ထရီ", + "1f4bf": "အလင်းသုံးဒစ်", + "1f9ee": "ပေသီးတွက်ခုံ", + "1f3ac": "ရုပ်ရှင် ကလက်ဘုတ်", + "1f4a1": "မီးလုံး", + "1f526": "ဓာတ်မီး", + "1f3ee": "စက္ကူမီးအိမ် အနီ", + "1f4d5": "ပိတ်ထားသည့် စာအုပ်", + "1f3f7": "တံဆိပ်", + "1f4b3": "ခရက်ဒစ်ကတ်", + "270f": "ခဲတံ", + "1f58c": "စုတ်တံ", + "1f58d": "ရောင်စုံဖယောင်းခဲတံ", + "1f4cc": "ဖိထိုးရသည့် ပင်အပ်", + "1f4ce": "စက္ကူညှပ်", + "1f511": "သော့", + "1fa83": "ထိကပြန်", + "1f3f9": "လေးနှင့် မြား", + "2696": "ချိန်ခွင်", + "1f9f2": "သံလိုက်", + "1f9ea": "ဖန်ပြွန်", + "1f9ec": "မျိုးရိုးဗီဇ", + "1f52c": "အဏုကြည့်မှန်ပြောင်း", + "1f52d": "အဝေးကြည့်မှန်ပြောင်း", + "1f4e1": "ဂြိုဟ်တု စလောင်း", + "1fa91": "ကုလားထိုင်", + "1f9f9": "တံမြက်စည်း", + "1f5ff": "မိုအိုင်" + }, + "nb": { + "1f47d": "romvesen", + "1f916": "robot", + "1f9e0": "hjerne", + "1f441": "øye", + "1f9d9": "trollperson", + "1f9da": "fe", + "1f9dc": "havperson", + "1f435": "apefjes", + "1f9a7": "orangutang", + "1f436": "hundefjes", + "1f43a": "ulv", + "1f98a": "rev", + "1f99d": "vaskebjørn", + "1f431": "kattefjes", + "1f981": "løve", + "1f42f": "tigerfjes", + "1f434": "hestefjes", + "1f984": "enhjørning", + "1f993": "sebra", + "1f98c": "hjort", + "1f42e": "kufjes", + "1f437": "grisefjes", + "1f417": "villsvin", + "1f42a": "dromedar", + "1f999": "lama", + "1f992": "sjiraff", + "1f418": "elefant", + "1f9a3": "mammut", + "1f98f": "neshorn", + "1f42d": "musefjes", + "1f430": "kaninfjes", + "1f43f": "ekorn", + "1f994": "pinnsvin", + "1f987": "flaggermus", + "1f43b": "bjørn", + "1f428": "koala", + "1f9a5": "dovendyr", + "1f9a6": "oter", + "1f998": "kenguru", + "1f425": "kylling forfra", + "1f426": "fugl", + "1f54a": "fredsdue", + "1f986": "and", + "1f989": "ugle", + "1f9a4": "dronte", + "1fab6": "fjær", + "1f9a9": "flamingo", + "1f99a": "påfugl", + "1f99c": "papegøye", + "1f40a": "krokodille", + "1f422": "skilpadde", + "1f98e": "firfisle", + "1f40d": "slange", + "1f432": "dragefjes", + "1f995": "sauropod", + "1f433": "sprutende hval", + "1f42c": "delfin", + "1f9ad": "sel", + "1f41f": "fisk", + "1f420": "tropisk fisk", + "1f988": "hai", + "1f419": "blekksprut", + "1f41a": "spiralskjell", + "1f40c": "snegle", + "1f98b": "sommerfugl", + "1f41b": "insekt", + "1f41d": "honningbie", + "1f41e": "marihøne", + "1f490": "bukett", + "1f339": "rose", + "1f33a": "hibiskus", + "1f33b": "solsikke", + "1f337": "tulipan", + "1f332": "bartre", + "1f333": "løvtre", + "1f334": "palme", + "1f335": "kaktus", + "1f33f": "urteblader", + "1f341": "lønneblad", + "1f344": "sopp", + "1f347": "druer", + "1f348": "melon", + "1f349": "vannmelon", + "1f34a": "mandarin", + "1f34b": "sitron", + "1f34c": "banan", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "grønt eple", + "1f350": "pære", + "1f351": "fersken", + "1f352": "kirsebær", + "1f353": "jordbær", + "1fad0": "blåbær", + "1f95d": "kiwi", + "1f345": "tomat", + "1fad2": "oliven", + "1f965": "kokosnøtt", + "1f951": "avokado", + "1f346": "aubergine", + "1f955": "gulrot", + "1f33d": "maiskolbe", + "1f336": "rød chili", + "1f96c": "bladgrønnsaker", + "1f966": "brokkoli", + "1f9c5": "løk", + "1f95c": "peanøtter", + "1f950": "croissant", + "1f956": "bagett", + "1f968": "saltkringle", + "1f96f": "bagel", + "1f95e": "pannekaker", + "1f9c7": "belgisk vaffel", + "1f354": "hamburger", + "1f355": "pizzastykke", + "1f32d": "pølse med brød", + "1f32e": "taco", + "1f37f": "popkorn", + "1f980": "krabbe", + "1f99e": "hummer", + "1f368": "iskrem", + "1f369": "donut", + "1f36a": "kjeks", + "1f382": "bursdagskake", + "1f9c1": "cupcake", + "1f36b": "sjokoladeplate", + "1f36c": "godteri", + "1f36d": "kjærlighet på pinne", + "1fad6": "tekanne", + "1f9c3": "drikkekartong", + "1f9c9": "mate", + "1f9ed": "kompass", + "1f3d4": "snødekt fjell", + "1f30b": "vulkan", + "1f3d5": "telttur", + "1f3dd": "øde øy", + "1f3e1": "hus med hage", + "26f2": "fontene", + "1f3a0": "karusellhest", + "1f3a1": "pariserhjul", + "1f3a2": "berg-og-dal-bane", + "1f488": "barberskilt", + "1f686": "tog", + "1f68b": "trikkevogn", + "1f68d": "motgående buss", + "1f695": "taxi", + "1f697": "bil", + "1f69a": "varebil", + "1f69c": "traktor", + "1f6f5": "scooter", + "1f6fa": "autorickshaw", + "1f6f4": "sparkesykkel", + "1f6f9": "skateboard", + "1f6fc": "rulleskøyter", + "2693": "anker", + "26f5": "seilbåt", + "1f6f6": "kano", + "1f6a4": "speedbåt", + "1f6a2": "skip", + "2708": "fly", + "1f681": "helikopter", + "1f6a0": "kabelbane", + "1f6f0": "satellitt", + "1f680": "rakett", + "1f6f8": "flygende tallerken", + "23f0": "vekkerklokke", + "1f319": "månesigd", + "1f321": "termometer", + "2600": "sol", + "1fa90": "planet med ringer", + "1f31f": "lysende stjerne", + "1f300": "syklon", + "1f308": "regnbue", + "2602": "paraply", + "2744": "snøfnugg", + "2604": "komet", + "1f525": "ild", + "1f4a7": "dråpe", + "1f30a": "bølge", + "1f383": "gresskarlykt", + "2728": "stjerner", + "1f388": "ballong", + "1f389": "smell-bon-bon", + "1f38f": "koinobori", + "1f380": "sløyfe", + "1f381": "gave", + "1f39f": "inngangsbilletter", + "1f3c6": "trofé", + "26bd": "fotball", + "1f3c0": "basketball", + "1f3c8": "amerikansk fotball", + "1f3be": "tennis", + "1f94f": "frisbee", + "1f3d3": "bordtennis", + "1f3f8": "badminton", + "1f93f": "dykkermaske", + "1f94c": "curlingstein", + "1f3af": "blink", + "1fa80": "jojo", + "1fa81": "papirdrage", + "1f52e": "krystallkule", + "1f3b2": "terning", + "1f9e9": "puslespillbrikke", + "1f3a8": "malerpalett", + "1f9f5": "tråd", + "1f455": "t-skjorte", + "1f9e6": "sokker", + "1f457": "kjole", + "1fa73": "shorts", + "1f392": "skolesekk", + "1f45f": "joggesko", + "1f451": "krone", + "1f9e2": "caps", + "1f484": "leppestift", + "1f48d": "ring", + "1f48e": "diamant", + "1f4e2": "høyttaler", + "1f3b6": "noter", + "1f399": "studiomikrofon", + "1f4fb": "radio", + "1f3b7": "saksofon", + "1fa97": "trekkspill", + "1f3b8": "gitar", + "1f3ba": "trompet", + "1f3bb": "fiolin", + "1fa95": "banjo", + "1f941": "tromme", + "260e": "telefon", + "1f50b": "batteri", + "1f4bf": "optisk plate", + "1f9ee": "kuleramme", + "1f3ac": "filmklapper", + "1f4a1": "lyspære", + "1f526": "lommelykt", + "1f3ee": "rød papirlykt", + "1f4d5": "lukket bok", + "1f3f7": "etikett", + "1f4b3": "kredittkort", + "270f": "blyant", + "1f58c": "pensel", + "1f58d": "fargestift", + "1f4cc": "stift", + "1f4ce": "binders", + "1f511": "nøkkel", + "1fa83": "bumerang", + "1f3f9": "pil og bue", + "2696": "likearmet skålvekt", + "1f9f2": "magnet", + "1f9ea": "prøverør", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "satellittantenne", + "1fa91": "stol", + "1f9f9": "feiekost", + "1f5ff": "moai-statue" + }, + "nl": { + "1f47d": "buitenaards wezen", + "1f916": "robot", + "1f9e0": "brein", + "1f441": "oog", + "1f9d9": "magiër", + "1f9da": "elfje", + "1f9dc": "zeemeermin", + "1f435": "apengezicht", + "1f9a7": "orang-oetang", + "1f436": "hondengezicht", + "1f43a": "wolf", + "1f98a": "vos", + "1f99d": "wasbeer", + "1f431": "kattengezicht", + "1f981": "leeuw", + "1f42f": "tijgergezicht", + "1f434": "paardengezicht", + "1f984": "eenhoorn", + "1f993": "zebra", + "1f98c": "hert", + "1f42e": "koeiengezicht", + "1f437": "varkensgezicht", + "1f417": "zwijn", + "1f42a": "dromedaris", + "1f999": "lama", + "1f992": "giraffe", + "1f418": "olifant", + "1f9a3": "mammoet", + "1f98f": "neushoorn", + "1f42d": "muizengezicht", + "1f430": "konijnengezicht", + "1f43f": "eekhoorn", + "1f994": "egel", + "1f987": "vleermuis", + "1f43b": "beer", + "1f428": "koala", + "1f9a5": "luiaard", + "1f9a6": "otter", + "1f998": "kangoeroe", + "1f425": "naar voren kijkend kuikentje", + "1f426": "vogel", + "1f54a": "duif", + "1f986": "eend", + "1f989": "uil", + "1f9a4": "dodo", + "1fab6": "veer", + "1f9a9": "flamingo", + "1f99a": "pauw", + "1f99c": "papegaai", + "1f40a": "krokodil", + "1f422": "schildpad", + "1f98e": "hagedis", + "1f40d": "slang", + "1f432": "drakengezicht", + "1f995": "sauropode", + "1f433": "spuitende walvis", + "1f42c": "dolfijn", + "1f9ad": "zeehond", + "1f41f": "vis", + "1f420": "tropische vis", + "1f988": "haai", + "1f419": "octopus", + "1f41a": "schelp", + "1f40c": "slak", + "1f98b": "vlinder", + "1f41b": "insect", + "1f41d": "honingbij", + "1f41e": "lieveheersbeestje", + "1f490": "boeket", + "1f339": "roos", + "1f33a": "hibiscus", + "1f33b": "zonnebloem", + "1f337": "tulp", + "1f332": "naaldboom", + "1f333": "loofboom", + "1f334": "palmboom", + "1f335": "cactus", + "1f33f": "kruid", + "1f341": "esdoornblad", + "1f344": "paddenstoel", + "1f347": "druiven", + "1f348": "meloen", + "1f349": "watermeloen", + "1f34a": "mandarijn", + "1f34b": "citroen", + "1f34c": "banaan", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "groene appel", + "1f350": "peer", + "1f351": "perzik", + "1f352": "kersen", + "1f353": "aardbei", + "1fad0": "bosbessen", + "1f95d": "kiwi", + "1f345": "tomaat", + "1fad2": "olijf", + "1f965": "kokosnoot", + "1f951": "avocado", + "1f346": "aubergine", + "1f955": "wortel", + "1f33d": "maïskolf", + "1f336": "hete peper", + "1f96c": "bladgroente", + "1f966": "broccoli", + "1f9c5": "ui", + "1f95c": "pinda’s", + "1f950": "croissant", + "1f956": "stokbrood", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "pannenkoeken", + "1f9c7": "wafel", + "1f354": "hamburger", + "1f355": "pizzapunt", + "1f32d": "hotdog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "krab", + "1f99e": "kreeft", + "1f368": "ijs", + "1f369": "donut", + "1f36a": "koekje", + "1f382": "verjaardagstaart", + "1f9c1": "cupcake", + "1f36b": "chocoladereep", + "1f36c": "snoep", + "1f36d": "lolly", + "1fad6": "theepot", + "1f9c3": "pakje drinken", + "1f9c9": "maté", + "1f9ed": "kompas", + "1f3d4": "berg met besneeuwde toppen", + "1f30b": "vulkaan", + "1f3d5": "kamperen", + "1f3dd": "onbewoond eiland", + "1f3e1": "huis met tuin", + "26f2": "fontein", + "1f3a0": "draaimolenpaard", + "1f3a1": "reuzenrad", + "1f3a2": "achtbaan", + "1f488": "kapperspaal", + "1f686": "trein", + "1f68b": "tramwagon", + "1f68d": "naderende bus", + "1f695": "taxi", + "1f697": "auto", + "1f69a": "bestelbus", + "1f69c": "tractor", + "1f6f5": "scooter", + "1f6fa": "riksja", + "1f6f4": "step", + "1f6f9": "skateboard", + "1f6fc": "rolschaats", + "2693": "anker", + "26f5": "zeilboot", + "1f6f6": "kano", + "1f6a4": "speedboot", + "1f6a2": "schip", + "2708": "vliegtuig", + "1f681": "helikopter", + "1f6a0": "bergkabelbaan", + "1f6f0": "satelliet", + "1f680": "raket", + "1f6f8": "vliegende schotel", + "23f0": "wekker", + "1f319": "maansikkel", + "1f321": "thermometer", + "2600": "zon", + "1fa90": "planeet met ringen", + "1f31f": "stralende ster", + "1f300": "cycloon", + "1f308": "regenboog", + "2602": "paraplu", + "2744": "sneeuwvlok", + "2604": "komeet", + "1f525": "vuur", + "1f4a7": "druppel", + "1f30a": "golf", + "1f383": "halloweenlantaarn", + "2728": "sterretjes", + "1f388": "ballon", + "1f389": "feestknaller", + "1f38f": "karperslinger", + "1f380": "strik", + "1f381": "ingepakt cadeau", + "1f39f": "entreekaartjes", + "1f3c6": "trofee", + "26bd": "voetbal", + "1f3c0": "basketbal", + "1f3c8": "american football", + "1f3be": "tennis", + "1f94f": "frisbee", + "1f3d3": "pingpong", + "1f3f8": "badminton", + "1f93f": "duikbril", + "1f94c": "curlingsteen", + "1f3af": "directe treffer", + "1fa80": "jojo", + "1fa81": "vlieger", + "1f52e": "kristallen bol", + "1f3b2": "dobbelsteen", + "1f9e9": "puzzelstukje", + "1f3a8": "schilderspalet", + "1f9f5": "garen", + "1f455": "T-shirt", + "1f9e6": "sokken", + "1f457": "jurk", + "1fa73": "korte broek", + "1f392": "schooltas", + "1f45f": "sportschoen", + "1f451": "kroon", + "1f9e2": "pet", + "1f484": "lippenstift", + "1f48d": "ring", + "1f48e": "edelsteen", + "1f4e2": "luidspreker", + "1f3b6": "muzieknoten", + "1f399": "studiomicrofoon", + "1f4fb": "radio", + "1f3b7": "saxofoon", + "1fa97": "accordeon", + "1f3b8": "gitaar", + "1f3ba": "trompet", + "1f3bb": "viool", + "1fa95": "banjo", + "1f941": "trommel", + "260e": "telefoon", + "1f50b": "batterij", + "1f4bf": "optische schijf", + "1f9ee": "abacus", + "1f3ac": "klapbord", + "1f4a1": "gloeilamp", + "1f526": "zaklamp", + "1f3ee": "rode papieren lantaarn", + "1f4d5": "gesloten boek", + "1f3f7": "label", + "1f4b3": "creditcard", + "270f": "potlood", + "1f58c": "kwast", + "1f58d": "krijtje", + "1f4cc": "punaise", + "1f4ce": "paperclip", + "1f511": "sleutel", + "1fa83": "boemerang", + "1f3f9": "pijl en boog", + "2696": "weegschaal", + "1f9f2": "magneet", + "1f9ea": "reageerbuis", + "1f9ec": "DNA", + "1f52c": "microscoop", + "1f52d": "telescoop", + "1f4e1": "satellietschotel", + "1fa91": "hoge stoel", + "1f9f9": "bezem", + "1f5ff": "moai-beeld" + }, + "pl": { + "1f47d": "ufoludek", + "1f916": "głowa robota", + "1f9e0": "mózg", + "1f441": "oko", + "1f9d9": "mag", + "1f9da": "wróżka", + "1f9dc": "syrena", + "1f435": "głowa małpy", + "1f9a7": "orangutan", + "1f436": "głowa psa", + "1f43a": "głowa wilka", + "1f98a": "głowa lisa", + "1f99d": "szop", + "1f431": "głowa kota", + "1f981": "głowa lwa", + "1f42f": "głowa tygrysa", + "1f434": "głowa konia", + "1f984": "głowa jednorożca", + "1f993": "zebra", + "1f98c": "jeleń", + "1f42e": "głowa krowy", + "1f437": "głowa świni", + "1f417": "dzik", + "1f42a": "wielbłąd", + "1f999": "lama", + "1f992": "żyrafa", + "1f418": "słoń", + "1f9a3": "mamut", + "1f98f": "nosorożec", + "1f42d": "głowa myszy", + "1f430": "głowa królika", + "1f43f": "pręgowiec", + "1f994": "jeż", + "1f987": "nietoperz", + "1f43b": "głowa niedźwiedzia", + "1f428": "koala", + "1f9a5": "leniwiec", + "1f9a6": "wydra", + "1f998": "kangur", + "1f425": "kurczątko od przodu", + "1f426": "ptak", + "1f54a": "gołąb", + "1f986": "kaczka", + "1f989": "sowa", + "1f9a4": "dodo", + "1fab6": "pióro", + "1f9a9": "flaming", + "1f99a": "paw", + "1f99c": "papuga", + "1f40a": "krokodyl", + "1f422": "żółw", + "1f98e": "jaszczurka", + "1f40d": "wąż", + "1f432": "głowa smoka", + "1f995": "zauropod", + "1f433": "wieloryb tryskający wodą", + "1f42c": "delfin", + "1f9ad": "foka", + "1f41f": "ryba", + "1f420": "ryba tropikalna", + "1f988": "rekin", + "1f419": "ośmiornica", + "1f41a": "muszla spiralna", + "1f40c": "ślimak", + "1f98b": "motyl", + "1f41b": "gąsienica", + "1f41d": "pszczoła", + "1f41e": "biedronka", + "1f490": "bukiet kwiatów", + "1f339": "róża", + "1f33a": "kwiat hibiskusa", + "1f33b": "słonecznik", + "1f337": "tulipan", + "1f332": "wiecznie zielone drzewo", + "1f333": "drzewo liściaste", + "1f334": "palma", + "1f335": "kaktus", + "1f33f": "zioło", + "1f341": "liść klonowy", + "1f344": "grzyb", + "1f347": "winogrona", + "1f348": "melon", + "1f349": "arbuz", + "1f34a": "mandarynka", + "1f34b": "cytryna", + "1f34c": "banan", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "zielone jabłko", + "1f350": "gruszka", + "1f351": "brzoskwinia", + "1f352": "wiśnie", + "1f353": "truskawka", + "1fad0": "borówka amerykańska", + "1f95d": "owoc kiwi", + "1f345": "pomidor", + "1fad2": "oliwka", + "1f965": "kokos", + "1f951": "awokado", + "1f346": "bakłażan", + "1f955": "marchew", + "1f33d": "kolba kukurydzy", + "1f336": "ostra papryka", + "1f96c": "zielenina liściasta", + "1f966": "brokuł", + "1f9c5": "cebula", + "1f95c": "orzeszki ziemne", + "1f950": "rogalik", + "1f956": "bagietka", + "1f968": "precel", + "1f96f": "bajgiel", + "1f95e": "naleśniki", + "1f9c7": "gofr", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "krab", + "1f99e": "homar", + "1f368": "lody", + "1f369": "pączek z dziurką", + "1f36a": "ciastko", + "1f382": "tort urodzinowy", + "1f9c1": "babeczka", + "1f36b": "tabliczka czekolady", + "1f36c": "cukierek", + "1f36d": "lizak", + "1fad6": "czajniczek", + "1f9c3": "napój w kartoniku", + "1f9c9": "yerba mate", + "1f9ed": "kompas", + "1f3d4": "góra z czapą lodową", + "1f30b": "wulkan", + "1f3d5": "kemping", + "1f3dd": "bezludna wyspa", + "1f3e1": "dom z ogrodem", + "26f2": "fontanna", + "1f3a0": "koń z karuzeli", + "1f3a1": "diabelski młyn", + "1f3a2": "kolejka górska", + "1f488": "słup fryzjerski", + "1f686": "pociąg", + "1f68b": "wagon tramwajowy", + "1f68d": "nadjeżdżający autobus", + "1f695": "taksówka", + "1f697": "samochód", + "1f69a": "samochód dostawczy", + "1f69c": "ciągnik", + "1f6f5": "skuter", + "1f6fa": "autoriksza", + "1f6f4": "hulajnoga", + "1f6f9": "deskorolka", + "1f6fc": "wrotka", + "2693": "kotwica", + "26f5": "żaglówka", + "1f6f6": "kajak", + "1f6a4": "ścigacz wodny", + "1f6a2": "statek", + "2708": "samolot", + "1f681": "helikopter", + "1f6a0": "górska kolej linowa", + "1f6f0": "satelita", + "1f680": "rakieta", + "1f6f8": "latający talerz", + "23f0": "budzik", + "1f319": "półksiężyc", + "1f321": "termometr", + "2600": "słońce", + "1fa90": "planeta z pierścieniami", + "1f31f": "błyszcząca gwiazda", + "1f300": "cyklon", + "1f308": "tęcza", + "2602": "parasol", + "2744": "płatek śniegu", + "2604": "kometa", + "1f525": "ogień", + "1f4a7": "kropla", + "1f30a": "fala", + "1f383": "dynia na halloween", + "2728": "gwiazdki", + "1f388": "balon", + "1f389": "tuba z konfetti", + "1f38f": "flaga w kształcie karpia", + "1f380": "wstążka", + "1f381": "zapakowany prezent", + "1f39f": "bilety wstępu", + "1f3c6": "puchar", + "26bd": "piłka nożna", + "1f3c0": "koszykówka", + "1f3c8": "futbol amerykański", + "1f3be": "tenis", + "1f94f": "frisbee", + "1f3d3": "tenis stołowy", + "1f3f8": "badminton", + "1f93f": "maska do nurkowania", + "1f94c": "kamień do curlingu", + "1f3af": "strzał w 10", + "1fa80": "jojo", + "1fa81": "latawiec", + "1f52e": "kryształowa kula", + "1f3b2": "kostka do gry", + "1f9e9": "element układanki", + "1f3a8": "paleta malarska", + "1f9f5": "nić", + "1f455": "koszulka", + "1f9e6": "skarpetki", + "1f457": "sukienka", + "1fa73": "szorty", + "1f392": "tornister", + "1f45f": "but do biegania", + "1f451": "korona", + "1f9e2": "bejsbolówka", + "1f484": "szminka", + "1f48d": "pierścionek", + "1f48e": "kamień szlachetny", + "1f4e2": "głośnik", + "1f3b6": "nuty", + "1f399": "mikrofon studyjny", + "1f4fb": "radio", + "1f3b7": "saksofon", + "1fa97": "akordeon", + "1f3b8": "gitara", + "1f3ba": "trąbka", + "1f3bb": "skrzypce", + "1fa95": "banjo", + "1f941": "bęben", + "260e": "telefon", + "1f50b": "bateria", + "1f4bf": "dysk optyczny", + "1f9ee": "liczydło", + "1f3ac": "klaps", + "1f4a1": "żarówka", + "1f526": "latarka", + "1f3ee": "czerwony lampion", + "1f4d5": "zamknięta książka", + "1f3f7": "przywieszka do kluczy", + "1f4b3": "karta kredytowa", + "270f": "ołówek", + "1f58c": "pędzel", + "1f58d": "kredka", + "1f4cc": "pinezka", + "1f4ce": "spinacz", + "1f511": "klucz", + "1fa83": "bumerang", + "1f3f9": "łuk i strzała", + "2696": "waga szalkowa", + "1f9f2": "magnes", + "1f9ea": "probówka", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "antena satelitarna", + "1fa91": "krzesło", + "1f9f9": "miotła", + "1f5ff": "moai" + }, + "pt": { + "1f47d": "alienígena", + "1f916": "rosto de robô", + "1f9e0": "cérebro", + "1f441": "olho", + "1f9d9": "mago", + "1f9da": "fada", + "1f9dc": "pessoa sereia", + "1f435": "rosto de macaco", + "1f9a7": "orangotango", + "1f436": "rosto de cachorro", + "1f43a": "rosto de lobo", + "1f98a": "rosto de raposa", + "1f99d": "guaxinim", + "1f431": "rosto de gato", + "1f981": "rosto de leão", + "1f42f": "rosto de tigre", + "1f434": "rosto de cavalo", + "1f984": "rosto de unicórnio", + "1f993": "zebra", + "1f98c": "cervo", + "1f42e": "rosto de vaca", + "1f437": "rosto de porco", + "1f417": "javali", + "1f42a": "camelo", + "1f999": "lhama", + "1f992": "girafa", + "1f418": "elefante", + "1f9a3": "mamute", + "1f98f": "rinoceronte", + "1f42d": "rosto de camundongo", + "1f430": "rosto de coelho", + "1f43f": "esquilo", + "1f994": "porco-espinho", + "1f987": "morcego", + "1f43b": "rosto de urso", + "1f428": "coala", + "1f9a5": "preguiça", + "1f9a6": "lontra", + "1f998": "canguru", + "1f425": "pintinho de frente", + "1f426": "pássaro", + "1f54a": "pomba branca", + "1f986": "pato", + "1f989": "coruja", + "1f9a4": "dodô", + "1fab6": "pena", + "1f9a9": "flamingo", + "1f99a": "pavão", + "1f99c": "papagaio", + "1f40a": "crocodilo", + "1f422": "tartaruga", + "1f98e": "lagartixa", + "1f40d": "cobra", + "1f432": "rosto de dragão", + "1f995": "saurópode", + "1f433": "baleia esguichando água", + "1f42c": "golfinho", + "1f9ad": "foca", + "1f41f": "peixe", + "1f420": "peixe tropical", + "1f988": "tubarão", + "1f419": "polvo", + "1f41a": "caramujo", + "1f40c": "caracol", + "1f98b": "borboleta", + "1f41b": "inseto", + "1f41d": "abelha", + "1f41e": "joaninha", + "1f490": "buquê", + "1f339": "rosa", + "1f33a": "hibisco", + "1f33b": "girassol", + "1f337": "tulipa", + "1f332": "conífera", + "1f333": "árvore caidiça", + "1f334": "palmeira", + "1f335": "cacto", + "1f33f": "erva", + "1f341": "folha de bordo", + "1f344": "cogumelo", + "1f347": "uvas", + "1f348": "melão", + "1f349": "melancia", + "1f34a": "tangerina", + "1f34b": "limão", + "1f34c": "banana", + "1f34d": "abacaxi", + "1f96d": "manga", + "1f34f": "maçã verde", + "1f350": "pera", + "1f351": "pêssego", + "1f352": "cereja", + "1f353": "morango", + "1fad0": "mirtilos", + "1f95d": "kiwi", + "1f345": "tomate", + "1fad2": "azeitona", + "1f965": "coco", + "1f951": "abacate", + "1f346": "berinjela", + "1f955": "cenoura", + "1f33d": "milho", + "1f336": "pimenta", + "1f96c": "verdura", + "1f966": "brócolis", + "1f9c5": "cebola", + "1f95c": "amendoim", + "1f950": "croissant", + "1f956": "baguete", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "panquecas", + "1f9c7": "waffle", + "1f354": "hambúrguer", + "1f355": "pizza", + "1f32d": "cachorro-quente", + "1f32e": "taco", + "1f37f": "pipoca", + "1f980": "caranguejo", + "1f99e": "lagosta", + "1f368": "sorvete", + "1f369": "donut", + "1f36a": "biscoito", + "1f382": "bolo de aniversário", + "1f9c1": "cupcake", + "1f36b": "chocolate", + "1f36c": "bala", + "1f36d": "pirulito", + "1fad6": "bule", + "1f9c3": "suco de caixa", + "1f9c9": "mate", + "1f9ed": "bússola", + "1f3d4": "montanha com neve", + "1f30b": "vulcão", + "1f3d5": "acampamento", + "1f3dd": "ilha deserta", + "1f3e1": "casa com jardim", + "26f2": "fonte", + "1f3a0": "carrossel", + "1f3a1": "roda gigante", + "1f3a2": "montanha russa", + "1f488": "barbearia", + "1f686": "trem", + "1f68b": "bonde", + "1f68d": "ônibus se aproximando", + "1f695": "táxi", + "1f697": "carro", + "1f69a": "caminhão de entrega", + "1f69c": "trator", + "1f6f5": "scooter", + "1f6fa": "automóvel riquixá", + "1f6f4": "patinete", + "1f6f9": "skate", + "1f6fc": "patins de rodas", + "2693": "âncora", + "26f5": "barco a vela", + "1f6f6": "canoa", + "1f6a4": "lancha", + "1f6a2": "navio", + "2708": "avião", + "1f681": "helicóptero", + "1f6a0": "cabo suspenso usado em teleféricos nas montanhas", + "1f6f0": "satélite", + "1f680": "foguete", + "1f6f8": "disco voador", + "23f0": "despertador", + "1f319": "lua crescente", + "1f321": "termômetro", + "2600": "sol", + "1fa90": "planeta com anéis", + "1f31f": "estrela brilhante", + "1f300": "ciclone", + "1f308": "arco-íris", + "2602": "guarda-chuva", + "2744": "floco de neve", + "2604": "cometa", + "1f525": "fogo", + "1f4a7": "gota", + "1f30a": "onda", + "1f383": "abóbora de halloween", + "2728": "brilhos", + "1f388": "balão", + "1f389": "cone de festa", + "1f38f": "bandeira de carpas", + "1f380": "laço de fita", + "1f381": "presente", + "1f39f": "ingresso de cinema", + "1f3c6": "troféu", + "26bd": "bola de futebol", + "1f3c0": "bola de basquete", + "1f3c8": "bola de futebol americano", + "1f3be": "tênis", + "1f94f": "frisbee", + "1f3d3": "pingue-pongue", + "1f3f8": "badminton", + "1f93f": "máscara de mergulho", + "1f94c": "pedra de curling", + "1f3af": "no alvo", + "1fa80": "ioiô", + "1fa81": "pipa", + "1f52e": "bola de cristal", + "1f3b2": "jogo de dado", + "1f9e9": "quebra-cabeça", + "1f3a8": "paleta de tintas", + "1f9f5": "carretel", + "1f455": "camiseta", + "1f9e6": "meias", + "1f457": "vestido", + "1fa73": "shorts", + "1f392": "mochila", + "1f45f": "tênis de corrida", + "1f451": "coroa", + "1f9e2": "boné", + "1f484": "batom", + "1f48d": "anel", + "1f48e": "pedra preciosa", + "1f4e2": "buzina", + "1f3b6": "notas musicais", + "1f399": "microfone de estúdio", + "1f4fb": "rádio", + "1f3b7": "saxofone", + "1fa97": "acordeão", + "1f3b8": "guitarra", + "1f3ba": "trompete", + "1f3bb": "violino", + "1fa95": "banjo", + "1f941": "tambor", + "260e": "telefone no gancho", + "1f50b": "pilha", + "1f4bf": "cd", + "1f9ee": "ábaco", + "1f3ac": "claquete", + "1f4a1": "lâmpada", + "1f526": "lanterna", + "1f3ee": "lanterna vermelha de papel", + "1f4d5": "livro fechado", + "1f3f7": "etiqueta", + "1f4b3": "cartão de crédito", + "270f": "lápis", + "1f58c": "pincel", + "1f58d": "giz de cera", + "1f4cc": "tacha", + "1f4ce": "clipe de papel", + "1f511": "chave", + "1fa83": "bumerangue", + "1f3f9": "arco e flecha", + "2696": "balança", + "1f9f2": "ímã", + "1f9ea": "tubo de ensaio", + "1f9ec": "dna", + "1f52c": "microscópio", + "1f52d": "telescópio", + "1f4e1": "antena parabólica", + "1fa91": "cadeira", + "1f9f9": "vassoura", + "1f5ff": "moai" + }, + "ro": { + "1f47d": "extraterestru", + "1f916": "robot", + "1f9e0": "creier", + "1f441": "un ochi", + "1f9d9": "mag", + "1f9da": "zână", + "1f9dc": "persoană sirenă", + "1f435": "față de maimuță", + "1f9a7": "urangutan", + "1f436": "față de câine", + "1f43a": "lup", + "1f98a": "vulpe", + "1f99d": "raton", + "1f431": "față de pisică", + "1f981": "leu", + "1f42f": "față de tigru", + "1f434": "față de cal", + "1f984": "unicorn", + "1f993": "zebră", + "1f98c": "cerb", + "1f42e": "cap de vacă", + "1f437": "cap de porc", + "1f417": "mistreț", + "1f42a": "dromader", + "1f999": "lamă", + "1f992": "girafă", + "1f418": "elefant", + "1f9a3": "mamut", + "1f98f": "rinocer", + "1f42d": "față de șoarece", + "1f430": "față de iepure", + "1f43f": "veveriță", + "1f994": "arici", + "1f987": "liliac", + "1f43b": "urs", + "1f428": "koala", + "1f9a5": "leneș", + "1f9a6": "vidră", + "1f998": "cangur", + "1f425": "pui de găină din față", + "1f426": "pasăre", + "1f54a": "porumbiță", + "1f986": "rață", + "1f989": "bufniță", + "1f9a4": "dodo", + "1fab6": "pană", + "1f9a9": "flamingo", + "1f99a": "păun", + "1f99c": "papagal mare", + "1f40a": "crocodil", + "1f422": "broască țestoasă", + "1f98e": "șopârlă", + "1f40d": "șarpe", + "1f432": "față de dragon", + "1f995": "sauropod", + "1f433": "balenă împroșcând apă", + "1f42c": "delfin", + "1f9ad": "focă", + "1f41f": "pește", + "1f420": "pește tropical", + "1f988": "rechin", + "1f419": "caracatiță", + "1f41a": "cochilie spiralată", + "1f40c": "melc", + "1f98b": "fluture", + "1f41b": "gândac", + "1f41d": "albină", + "1f41e": "buburuză", + "1f490": "buchet de flori", + "1f339": "trandafir", + "1f33a": "hibiscus", + "1f33b": "floarea soarelui", + "1f337": "lalea", + "1f332": "arbore conifer", + "1f333": "arbore foios", + "1f334": "palmier", + "1f335": "cactus", + "1f33f": "plantă aromatică", + "1f341": "frunză de arțar", + "1f344": "ciupercă", + "1f347": "struguri", + "1f348": "pepene galben", + "1f349": "pepene verde", + "1f34a": "mandarină", + "1f34b": "lămâie", + "1f34c": "banană", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "măr verde", + "1f350": "pară", + "1f351": "piersică", + "1f352": "cireșe", + "1f353": "căpșună", + "1fad0": "afine", + "1f95d": "kiwi", + "1f345": "roșie", + "1fad2": "măslină", + "1f965": "nucă de cocos", + "1f951": "avocado", + "1f346": "vânătă", + "1f955": "morcov", + "1f33d": "știulete de porumb", + "1f336": "ardei iute", + "1f96c": "verdețuri", + "1f966": "broccoli", + "1f9c5": "ceapă", + "1f95c": "arahide", + "1f950": "croasant", + "1f956": "baghetă de pâine", + "1f968": "covrig", + "1f96f": "bagel", + "1f95e": "clătite", + "1f9c7": "gofră", + "1f354": "hamburger", + "1f355": "pizza", + "1f32d": "hot dog", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "rac", + "1f99e": "homar", + "1f368": "înghețată", + "1f369": "gogoașă americană", + "1f36a": "fursec", + "1f382": "tort aniversar", + "1f9c1": "brioșă", + "1f36b": "baton de ciocolată", + "1f36c": "bomboană", + "1f36d": "acadea", + "1fad6": "ceainic", + "1f9c3": "cutie de băutură", + "1f9c9": "mate", + "1f9ed": "busolă", + "1f3d4": "vârf de munte înzăpezit", + "1f30b": "vulcan", + "1f3d5": "camping", + "1f3dd": "insulă pustie", + "1f3e1": "casă cu grădină", + "26f2": "fântână arteziană", + "1f3a0": "căluț de carusel", + "1f3a1": "roata mare", + "1f3a2": "montagne russe", + "1f488": "semn de frizerie", + "1f686": "tren", + "1f68b": "vagon de tramvai", + "1f68d": "autobuz care se apropie", + "1f695": "taxi", + "1f697": "automobil", + "1f69a": "camion de marfă", + "1f69c": "tractor", + "1f6f5": "scuter", + "1f6fa": "autoricșă", + "1f6f4": "trotinetă", + "1f6f9": "skateboard", + "1f6fc": "patină cu rotile", + "2693": "ancoră", + "26f5": "barcă cu pânze", + "1f6f6": "canoe", + "1f6a4": "barcă de viteză", + "1f6a2": "vapor", + "2708": "avion", + "1f681": "elicopter", + "1f6a0": "telecabină montană", + "1f6f0": "satelit", + "1f680": "rachetă", + "1f6f8": "farfurie zburătoare", + "23f0": "ceas deșteptător", + "1f319": "semilună", + "1f321": "termometru", + "2600": "soare", + "1fa90": "planetă cu inele", + "1f31f": "stea strălucitoare", + "1f300": "ciclon", + "1f308": "curcubeu", + "2602": "umbrelă", + "2744": "fulg de nea", + "2604": "cometă", + "1f525": "foc", + "1f4a7": "picătură", + "1f30a": "val", + "1f383": "dovleac cu felinar", + "2728": "steluțe", + "1f388": "balon", + "1f389": "tun cu confetti", + "1f38f": "crap decorativ în vânt", + "1f380": "fundă", + "1f381": "cadou împachetat", + "1f39f": "bilete de intrare", + "1f3c6": "trofeu", + "26bd": "minge de fotbal", + "1f3c0": "baschet", + "1f3c8": "fotbal american", + "1f3be": "tenis", + "1f94f": "disc zburător", + "1f3d3": "ping pong", + "1f3f8": "badminton", + "1f93f": "mască de scufundări", + "1f94c": "piatră de curling", + "1f3af": "fix la țintă", + "1fa80": "yo-yo", + "1fa81": "zmeu", + "1f52e": "glob de cristal", + "1f3b2": "zar", + "1f9e9": "piesă de puzzle", + "1f3a8": "paletă de pictor", + "1f9f5": "ață", + "1f455": "tricou", + "1f9e6": "șosete", + "1f457": "rochie", + "1fa73": "șort", + "1f392": "rucsac", + "1f45f": "pantof sport", + "1f451": "coroană", + "1f9e2": "șapcă", + "1f484": "ruj", + "1f48d": "inel", + "1f48e": "piatră prețioasă", + "1f4e2": "portavoce", + "1f3b6": "note muzicale", + "1f399": "microfon de studio", + "1f4fb": "radio", + "1f3b7": "saxofon", + "1fa97": "acordeon", + "1f3b8": "chitară", + "1f3ba": "trompetă", + "1f3bb": "vioară", + "1fa95": "banjo", + "1f941": "tobă", + "260e": "telefon", + "1f50b": "baterie", + "1f4bf": "cd", + "1f9ee": "abac", + "1f3ac": "clachetă", + "1f4a1": "bec", + "1f526": "lanternă", + "1f3ee": "felinar din hârtie roșie", + "1f4d5": "carte închisă", + "1f3f7": "etichetă", + "1f4b3": "card de credit", + "270f": "creion", + "1f58c": "pensulă", + "1f58d": "creion colorat", + "1f4cc": "piuneză", + "1f4ce": "agrafă de hârtie", + "1f511": "cheie", + "1fa83": "bumerang", + "1f3f9": "arc și săgeată", + "2696": "balanță", + "1f9f2": "magnet", + "1f9ea": "eprubetă", + "1f9ec": "ADN", + "1f52c": "microscop", + "1f52d": "telescop", + "1f4e1": "antenă satelit", + "1fa91": "scaun", + "1f9f9": "mătură", + "1f5ff": "statuie moai" + }, + "ru": { + "1f47d": "инопланетянин", + "1f916": "робот", + "1f9e0": "мозг", + "1f441": "глаз", + "1f9d9": "маг", + "1f9da": "фея", + "1f9dc": "русалка", + "1f435": "морда обезьяны", + "1f9a7": "орангутан", + "1f436": "морда собаки", + "1f43a": "морда волка", + "1f98a": "морда лисицы", + "1f99d": "морда енота", + "1f431": "морда кошки", + "1f981": "морда льва", + "1f42f": "морда тигра", + "1f434": "морда лошади", + "1f984": "голова единорога", + "1f993": "зебра", + "1f98c": "олень", + "1f42e": "морда коровы", + "1f437": "морда свиньи", + "1f417": "кабан", + "1f42a": "одногорбый верблюд", + "1f999": "лама", + "1f992": "жираф", + "1f418": "слон", + "1f9a3": "мамонт", + "1f98f": "носорог", + "1f42d": "морда мыши", + "1f430": "морда кролика", + "1f43f": "бурундук", + "1f994": "еж", + "1f987": "летучая мышь", + "1f43b": "морда медведя", + "1f428": "морда коалы", + "1f9a5": "ленивец", + "1f9a6": "выдра", + "1f998": "кенгуру", + "1f425": "цыпленок", + "1f426": "птица", + "1f54a": "голубь", + "1f986": "утка", + "1f989": "сова", + "1f9a4": "дронт", + "1fab6": "перо", + "1f9a9": "фламинго", + "1f99a": "павлин", + "1f99c": "попугай", + "1f40a": "крокодил", + "1f422": "черепаха", + "1f98e": "ящерица", + "1f40d": "змея", + "1f432": "голова дракона", + "1f995": "зауропод", + "1f433": "кит с фонтанчиком", + "1f42c": "дельфин", + "1f9ad": "тюлень", + "1f41f": "рыба", + "1f420": "тропическая рыба", + "1f988": "акула", + "1f419": "осьминог", + "1f41a": "раковина", + "1f40c": "улитка", + "1f98b": "бабочка", + "1f41b": "гусеница", + "1f41d": "пчела", + "1f41e": "божья коровка", + "1f490": "букет", + "1f339": "роза", + "1f33a": "гибискус", + "1f33b": "подсолнух", + "1f337": "тюльпан", + "1f332": "елка", + "1f333": "дерево", + "1f334": "пальма", + "1f335": "кактус", + "1f33f": "веточка", + "1f341": "кленовый лист", + "1f344": "гриб", + "1f347": "виноград", + "1f348": "дыня", + "1f349": "арбуз", + "1f34a": "мандарин", + "1f34b": "лимон", + "1f34c": "банан", + "1f34d": "ананас", + "1f96d": "манго", + "1f34f": "зеленое яблоко", + "1f350": "груша", + "1f351": "персик", + "1f352": "вишня", + "1f353": "клубника", + "1fad0": "голубика", + "1f95d": "киви", + "1f345": "помидор", + "1fad2": "оливка", + "1f965": "кокос", + "1f951": "авокадо", + "1f346": "баклажан", + "1f955": "морковь", + "1f33d": "кукурузный початок", + "1f336": "острый перец", + "1f96c": "зеленый салат", + "1f966": "брокколи", + "1f9c5": "лук", + "1f95c": "арахис", + "1f950": "круассан", + "1f956": "багет", + "1f968": "крендель", + "1f96f": "бублик", + "1f95e": "блины", + "1f9c7": "вафля", + "1f354": "гамбургер", + "1f355": "пицца", + "1f32d": "хот-дог", + "1f32e": "тако", + "1f37f": "попкорн", + "1f980": "краб", + "1f99e": "омар", + "1f368": "мороженое", + "1f369": "пончик", + "1f36a": "печенье", + "1f382": "торт ко дню рождения", + "1f9c1": "капкейк", + "1f36b": "шоколад", + "1f36c": "конфета", + "1f36d": "леденец", + "1fad6": "чайник", + "1f9c3": "пакетик сока", + "1f9c9": "мате", + "1f9ed": "компас", + "1f3d4": "гора со снежной шапкой", + "1f30b": "вулкан", + "1f3d5": "кемпинг", + "1f3dd": "остров", + "1f3e1": "дом с садом", + "26f2": "фонтан", + "1f3a0": "лошадь на карусели", + "1f3a1": "колесо обозрения", + "1f3a2": "американские горки", + "1f488": "парикмахерская", + "1f686": "поезд", + "1f68b": "трамвайный вагон", + "1f68d": "автобус спереди", + "1f695": "такси", + "1f697": "автомобиль", + "1f69a": "грузовик", + "1f69c": "трактор", + "1f6f5": "скутер", + "1f6fa": "авторикша", + "1f6f4": "самокат", + "1f6f9": "скейтборд", + "1f6fc": "роликовые коньки", + "2693": "якорь", + "26f5": "парусник", + "1f6f6": "каноэ", + "1f6a4": "катер", + "1f6a2": "корабль", + "2708": "самолет", + "1f681": "вертолет", + "1f6a0": "вагон фуникулера", + "1f6f0": "спутник", + "1f680": "ракета", + "1f6f8": "летающая тарелка", + "23f0": "будильник", + "1f319": "полумесяц", + "1f321": "термометр", + "2600": "солнце", + "1fa90": "планета с кольцом", + "1f31f": "сияющая звезда", + "1f300": "циклон", + "1f308": "радуга", + "2602": "зонт", + "2744": "снежинка", + "2604": "комета", + "1f525": "огонь", + "1f4a7": "капля", + "1f30a": "волна", + "1f383": "тыква-фонарь", + "2728": "блестки", + "1f388": "воздушный шарик", + "1f389": "хлопушка", + "1f38f": "вымпелы в виде карпов", + "1f380": "бантик", + "1f381": "подарок", + "1f39f": "билеты", + "1f3c6": "кубок", + "26bd": "футбол", + "1f3c0": "баскетбол", + "1f3c8": "американский футбол", + "1f3be": "теннис", + "1f94f": "летающий диск", + "1f3d3": "настольный теннис", + "1f3f8": "бадминтон", + "1f93f": "маска с трубкой", + "1f94c": "керлинг", + "1f3af": "мишень", + "1fa80": "йо-йо", + "1fa81": "воздушный змей", + "1f52e": "хрустальный шар", + "1f3b2": "игральная кость", + "1f9e9": "пазл", + "1f3a8": "палитра с красками", + "1f9f5": "катушка ниток", + "1f455": "футболка", + "1f9e6": "носки", + "1f457": "платье", + "1fa73": "шорты", + "1f392": "ранец", + "1f45f": "кроссовки", + "1f451": "корона", + "1f9e2": "бейсболка", + "1f484": "помада", + "1f48d": "кольцо", + "1f48e": "драгоценный камень", + "1f4e2": "громкоговоритель", + "1f3b6": "ноты", + "1f399": "студийный микрофон", + "1f4fb": "радио", + "1f3b7": "саксофон", + "1fa97": "аккордеон", + "1f3b8": "гитара", + "1f3ba": "труба", + "1f3bb": "скрипка", + "1fa95": "банджо", + "1f941": "барабан", + "260e": "телефон", + "1f50b": "батарейка", + "1f4bf": "CD", + "1f9ee": "счеты", + "1f3ac": "хлопушка-нумератор", + "1f4a1": "лампочка", + "1f526": "фонарик", + "1f3ee": "красный бумажный фонарик", + "1f4d5": "закрытая книга", + "1f3f7": "бирка", + "1f4b3": "кредитная карта", + "270f": "карандаш", + "1f58c": "кисточка", + "1f58d": "восковой мелок", + "1f4cc": "канцелярская кнопка", + "1f4ce": "скрепка", + "1f511": "ключ", + "1fa83": "бумеранг", + "1f3f9": "лук со стрелой", + "2696": "весы", + "1f9f2": "магнит", + "1f9ea": "пробирка", + "1f9ec": "ДНК", + "1f52c": "микроскоп", + "1f52d": "телескоп", + "1f4e1": "спутниковая антенна", + "1fa91": "стул", + "1f9f9": "метла", + "1f5ff": "истукан" + }, + "sq": { + "1f47d": "alien", + "1f916": "fytyrë roboti", + "1f9e0": "tru", + "1f441": "sy", + "1f9d9": "magjistar", + "1f9da": "zanë", + "1f9dc": "sirenë deti", + "1f435": "fytyrë majmuni", + "1f9a7": "orangutang", + "1f436": "fytyrë qeni", + "1f43a": "fytyrë ujku", + "1f98a": "fytyrë dhelpre", + "1f99d": "rakun", + "1f431": "fytyrë maceje", + "1f981": "fytyrë luani", + "1f42f": "fytyrë tigri", + "1f434": "fytyrë kali", + "1f984": "fytyrë njëbrirëshi", + "1f993": "zebër", + "1f98c": "dre", + "1f42e": "fytyrë lope", + "1f437": "fytyrë derri", + "1f417": "derr i egër", + "1f42a": "gamile", + "1f999": "lamë", + "1f992": "gjirafë", + "1f418": "elefant", + "1f9a3": "mamuth", + "1f98f": "rinoqeront", + "1f42d": "fytyrë miu", + "1f430": "fytyrë lepuri", + "1f43f": "ketër", + "1f994": "iriq", + "1f987": "lakuriq nate", + "1f43b": "fytyrë ariu", + "1f428": "koalë", + "1f9a5": "majmun i Bengalit", + "1f9a6": "vidër", + "1f998": "kangur", + "1f425": "zog pule përballë", + "1f426": "zog", + "1f54a": "pëllumb", + "1f986": "rosak", + "1f989": "buf", + "1f9a4": "zog i rëndë", + "1fab6": "pendë", + "1f9a9": "flamingo", + "1f99a": "pallua", + "1f99c": "papagall", + "1f40a": "krokodil", + "1f422": "breshkë", + "1f98e": "hardhucë", + "1f40d": "gjarpër", + "1f432": "fytyrë dragoi", + "1f995": "sauropod", + "1f433": "balenë që hedh ujë", + "1f42c": "delfin", + "1f9ad": "fokë", + "1f41f": "peshk", + "1f420": "peshk tropikal", + "1f988": "peshkaqen", + "1f419": "oktapod", + "1f41a": "guaskë spirale", + "1f40c": "kërmill", + "1f98b": "flutur", + "1f41b": "shumëkëmbësh", + "1f41d": "bletë", + "1f41e": "mollëkuqe", + "1f490": "buqetë", + "1f339": "trëndafil", + "1f33a": "hibisk", + "1f33b": "luledielli", + "1f337": "tulipan", + "1f332": "gjelbërim i përjetshëm", + "1f333": "pemë gjetherënëse", + "1f334": "palmë", + "1f335": "kaktus", + "1f33f": "erëza", + "1f341": "gjethe panje", + "1f344": "kërpudhë", + "1f347": "rrush", + "1f348": "pjepër", + "1f349": "shalqi", + "1f34a": "mandarinë", + "1f34b": "limon", + "1f34c": "banane", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "mollë jeshile", + "1f350": "dardhë", + "1f351": "pjeshkë", + "1f352": "qershi", + "1f353": "luleshtrydhe", + "1fad0": "boronica", + "1f95d": "kivi", + "1f345": "domate", + "1fad2": "ulli", + "1f965": "arrë kokosi", + "1f951": "avokado", + "1f346": "patëllxhan", + "1f955": "karotë", + "1f33d": "kalli misri", + "1f336": "spec djegës", + "1f96c": "sallatë", + "1f966": "brokoli", + "1f9c5": "qepë", + "1f95c": "kikirik", + "1f950": "kroasant", + "1f956": "bagetë", + "1f968": "gjevrek i përdredhur", + "1f96f": "gjevrek", + "1f95e": "petulla", + "1f9c7": "vafer", + "1f354": "hamburger", + "1f355": "pica", + "1f32d": "hot-dog", + "1f32e": "tako", + "1f37f": "kokoshka", + "1f980": "gaforre", + "1f99e": "karavidhe", + "1f368": "akullore", + "1f369": "petull e ëmbël", + "1f36a": "biskotë", + "1f382": "tortë ditëlindjeje", + "1f9c1": "kek i vogël", + "1f36b": "çokollatë", + "1f36c": "ëmbëlsirë", + "1f36d": "lëpirëse", + "1fad6": "çajnik", + "1f9c3": "kuti pijeje", + "1f9c9": "kimarrao", + "1f9ed": "busull", + "1f3d4": "mal i mbuluar me borë në majë", + "1f30b": "vullkan", + "1f3d5": "kamp", + "1f3dd": "ishull shkretëtirë", + "1f3e1": "shtëpi me kopsht", + "26f2": "shatërvan", + "1f3a0": "kalë në karusel", + "1f3a1": "rrotullame", + "1f3a2": "tren lojërash me valëzim", + "1f488": "shenja e berberit", + "1f686": "tren", + "1f68b": "vagon tramvaji", + "1f68d": "autobus që vjen", + "1f695": "taksi", + "1f697": "automobil", + "1f69a": "kamion transporti", + "1f69c": "traktor", + "1f6f5": "skuter", + "1f6fa": "autorikshë", + "1f6f4": "ballëz dyrrotëshe", + "1f6f9": "dërrasë rrëshqitëse", + "1f6fc": "rollerskejt", + "2693": "spirancë", + "26f5": "varkë me vela", + "1f6f6": "kaike", + "1f6a4": "motobarkë e shpejtë", + "1f6a2": "anije", + "2708": "aeroplan", + "1f681": "helikopter", + "1f6a0": "teleferik në mal", + "1f6f0": "satelit", + "1f680": "raketë", + "1f6f8": "disk fluturues", + "23f0": "orë me zile", + "1f319": "hënë e ngrënë", + "1f321": "termometër", + "2600": "diell", + "1fa90": "planet me unazë", + "1f31f": "yll që shkëlqen", + "1f300": "ciklon", + "1f308": "ylber", + "2602": "çadër", + "2744": "flokë bore", + "2604": "kometë", + "1f525": "zjarr", + "1f4a7": "pikëz", + "1f30a": "dallgë uji", + "1f383": "kungulli i Halloween", + "2728": "xixëllima", + "1f388": "tullumbace", + "1f389": "fishek feste", + "1f38f": "koinobori", + "1f380": "fjongo", + "1f381": "dhuratë e mbështjellë", + "1f39f": "biletat e hyrjes", + "1f3c6": "trofe", + "26bd": "top futbolli", + "1f3c0": "basketboll", + "1f3c8": "futboll amerikan", + "1f3be": "tenis", + "1f94f": "hedhje disku", + "1f3d3": "pingpong", + "1f3f8": "badminton", + "1f93f": "maskë zhytjeje", + "1f94c": "gur kurlingu", + "1f3af": "goditje e drejtpërdrejtë", + "1fa80": "jo-jo", + "1fa81": "balonë", + "1f52e": "top kristali", + "1f3b2": "zar loje", + "1f9e9": "lojë me bashkim pjesësh figure", + "1f3a8": "paleta e artistit", + "1f9f5": "fije", + "1f455": "bluzë", + "1f9e6": "çorape", + "1f457": "fustan", + "1fa73": "pantallona të shkurtra", + "1f392": "çantë shkolle", + "1f45f": "atlete", + "1f451": "kurorë", + "1f9e2": "kapelë \"sqep\"", + "1f484": "buzëkuq", + "1f48d": "unazë", + "1f48e": "gur i çmuar", + "1f4e2": "altoparlant me zë", + "1f3b6": "nota muzikore", + "1f399": "mikrofon studioje", + "1f4fb": "radio", + "1f3b7": "saksofon", + "1fa97": "fizarmonikë", + "1f3b8": "kitarë", + "1f3ba": "trombë", + "1f3bb": "violinë", + "1fa95": "banxho", + "1f941": "daulle", + "260e": "telefon", + "1f50b": "bateri", + "1f4bf": "disk optik", + "1f9ee": "abak", + "1f3ac": "tabelë dublimi e skenës", + "1f4a1": "llambë", + "1f526": "elektrik dore", + "1f3ee": "fener me letër të kuqe", + "1f4d5": "libër i mbyllur", + "1f3f7": "etiketë", + "1f4b3": "kartë krediti", + "270f": "laps", + "1f58c": "furçë piktori", + "1f58d": "shkumës me ngjyrë", + "1f4cc": "gjilpërë kapëse", + "1f4ce": "kapëse letrash", + "1f511": "çelës", + "1fa83": "bumerang", + "1f3f9": "hark dhe shigjetë", + "2696": "peshore", + "1f9f2": "magnet", + "1f9ea": "epruvetë", + "1f9ec": "ADN", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "antenë satelitore", + "1fa91": "karrige", + "1f9f9": "fshesë", + "1f5ff": "moai" + }, + "sv": { + "1f47d": "utomjording", + "1f916": "robotansikte", + "1f9e0": "hjärna", + "1f441": "öga", + "1f9d9": "magiker", + "1f9da": "fé", + "1f9dc": "vattenväsen", + "1f435": "apansikte", + "1f9a7": "orangutang", + "1f436": "hundansikte", + "1f43a": "vargansikte", + "1f98a": "rävansikte", + "1f99d": "tvättbjörn", + "1f431": "kattansikte", + "1f981": "lejonansikte", + "1f42f": "tigeransikte", + "1f434": "hästansikte", + "1f984": "enhörningsansikte", + "1f993": "zebra", + "1f98c": "hjort", + "1f42e": "koansikte", + "1f437": "grisansikte", + "1f417": "vildsvin", + "1f42a": "dromedar", + "1f999": "lama", + "1f992": "giraff", + "1f418": "elefant", + "1f9a3": "mammut", + "1f98f": "noshörning", + "1f42d": "musansikte", + "1f430": "kaninansikte", + "1f43f": "jordekorre", + "1f994": "igelkott", + "1f987": "fladdermus", + "1f43b": "björnansikte", + "1f428": "koala", + "1f9a5": "sengångare", + "1f9a6": "utter", + "1f998": "känguru", + "1f425": "kyckling framifrån", + "1f426": "fågel", + "1f54a": "duva", + "1f986": "and", + "1f989": "uggla", + "1f9a4": "dront", + "1fab6": "fågelfjäder", + "1f9a9": "flamingo", + "1f99a": "påfågel", + "1f99c": "papegoja", + "1f40a": "krokodil", + "1f422": "sköldpadda", + "1f98e": "ödla", + "1f40d": "orm", + "1f432": "drakansikte", + "1f995": "sauropod", + "1f433": "val som sprutar vatten", + "1f42c": "delfin", + "1f9ad": "säl", + "1f41f": "fisk", + "1f420": "tropisk fisk", + "1f988": "haj", + "1f419": "bläckfisk", + "1f41a": "snäcka", + "1f40c": "snigel", + "1f98b": "fjäril", + "1f41b": "tusenfoting", + "1f41d": "bi", + "1f41e": "nyckelpiga", + "1f490": "blombukett", + "1f339": "ros", + "1f33a": "hibiskus", + "1f33b": "solros", + "1f337": "tulpan", + "1f332": "barrträd", + "1f333": "lövträd", + "1f334": "palm", + "1f335": "kaktus", + "1f33f": "ört", + "1f341": "lönnlöv", + "1f344": "svamp", + "1f347": "vindruvor", + "1f348": "melon", + "1f349": "vattenmelon", + "1f34a": "mandarin", + "1f34b": "citron", + "1f34c": "banan", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "grönt äpple", + "1f350": "päron", + "1f351": "persika", + "1f352": "körsbär", + "1f353": "jordgubbe", + "1fad0": "blåbär", + "1f95d": "kiwifrukt", + "1f345": "tomat", + "1fad2": "oliv", + "1f965": "kokosnöt", + "1f951": "avokado", + "1f346": "aubergine", + "1f955": "morot", + "1f33d": "majskolv", + "1f336": "chili", + "1f96c": "sallat", + "1f966": "broccoli", + "1f9c5": "lök", + "1f95c": "jordnötter", + "1f950": "croissant", + "1f956": "baguette", + "1f968": "pretzel", + "1f96f": "bagel", + "1f95e": "pannkakor", + "1f9c7": "våffla", + "1f354": "hamburgare", + "1f355": "pizzabit", + "1f32d": "varmkorv", + "1f32e": "taco", + "1f37f": "popcorn", + "1f980": "krabba", + "1f99e": "hummer", + "1f368": "glass", + "1f369": "munk", + "1f36a": "kaka", + "1f382": "födelsedagstårta", + "1f9c1": "muffin", + "1f36b": "chokladkaka", + "1f36c": "godis", + "1f36d": "klubba", + "1fad6": "tekanna", + "1f9c3": "dryckeskartong", + "1f9c9": "mate-te", + "1f9ed": "kompass", + "1f3d4": "snöklätt berg", + "1f30b": "vulkan", + "1f3d5": "camping", + "1f3dd": "öde ö", + "1f3e1": "hus med trädgård", + "26f2": "fontän", + "1f3a0": "karusellhäst", + "1f3a1": "pariserhjul", + "1f3a2": "berg- och dalbana", + "1f488": "barberarstolpe", + "1f686": "tåg", + "1f68b": "spårvagnsvagn", + "1f68d": "mötande buss", + "1f695": "taxi", + "1f697": "bil", + "1f69a": "budbil", + "1f69c": "traktor", + "1f6f5": "skoter", + "1f6fa": "automatisk riksha", + "1f6f4": "sparkcykel", + "1f6f9": "skateboard", + "1f6fc": "rullskridsko", + "2693": "ankare", + "26f5": "segelbåt", + "1f6f6": "kanot", + "1f6a4": "racerbåt", + "1f6a2": "fartyg", + "2708": "flygplan", + "1f681": "helikopter", + "1f6a0": "linbana", + "1f6f0": "satellit", + "1f680": "raket", + "1f6f8": "flygande tefat", + "23f0": "väckarklocka", + "1f319": "månskära", + "1f321": "termometer", + "2600": "sol", + "1fa90": "planet med ringar", + "1f31f": "blänkande stjärna", + "1f300": "cyklon", + "1f308": "regnbåge", + "2602": "paraply", + "2744": "snöflinga", + "2604": "komet", + "1f525": "eld", + "1f4a7": "droppe", + "1f30a": "våg", + "1f383": "lyktgubbe", + "2728": "gnistrande stjärnor", + "1f388": "ballong", + "1f389": "konfettismällare", + "1f38f": "karpvindstrut", + "1f380": "rosett", + "1f381": "inslagen present", + "1f39f": "inträdesbiljetter", + "1f3c6": "pokal", + "26bd": "fotboll", + "1f3c0": "basketboll", + "1f3c8": "amerikansk fotboll", + "1f3be": "tennis", + "1f94f": "frisbee", + "1f3d3": "bordtennis", + "1f3f8": "badminton", + "1f93f": "dykmask", + "1f94c": "curlingsten", + "1f3af": "mitt i prick", + "1fa80": "jojo", + "1fa81": "flygande drake", + "1f52e": "kristallkula", + "1f3b2": "speltärning", + "1f9e9": "pusselbit", + "1f3a8": "färgpalett", + "1f9f5": "tråd", + "1f455": "t-shirt", + "1f9e6": "sockor", + "1f457": "klänning", + "1fa73": "shorts", + "1f392": "ryggsäck", + "1f45f": "gympasko", + "1f451": "krona", + "1f9e2": "skärmmössa", + "1f484": "läppstift", + "1f48d": "ring", + "1f48e": "ädelsten", + "1f4e2": "handhögtalare", + "1f3b6": "musiknoter", + "1f399": "studiomikrofon", + "1f4fb": "radio", + "1f3b7": "saxofon", + "1fa97": "dragspel", + "1f3b8": "gitarr", + "1f3ba": "trumpet", + "1f3bb": "fiol", + "1fa95": "banjo", + "1f941": "trumma", + "260e": "telefon", + "1f50b": "batteri", + "1f4bf": "optisk skiva", + "1f9ee": "kulram", + "1f3ac": "filmklappa", + "1f4a1": "glödlampa", + "1f526": "ficklampa", + "1f3ee": "röd papperslykta", + "1f4d5": "stängd bok", + "1f3f7": "etikett", + "1f4b3": "kreditkort", + "270f": "blyertspenna", + "1f58c": "målarpensel", + "1f58d": "krita", + "1f4cc": "kartnål", + "1f4ce": "gem", + "1f511": "nyckel", + "1fa83": "boomerang", + "1f3f9": "pil och båge", + "2696": "balansvåg", + "1f9f2": "magnet", + "1f9ea": "provrör", + "1f9ec": "DNA", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "tv-satellit", + "1fa91": "stol", + "1f9f9": "kvast", + "1f5ff": "staty" + }, + "th": { + "1f47d": "เอเลี่ยน", + "1f916": "หุ่นยนต์", + "1f9e0": "สมอง", + "1f441": "ตาข้างเดียว", + "1f9d9": "นักเวทย์", + "1f9da": "นางฟ้า", + "1f9dc": "ครึ่งคนครึ่งปลา", + "1f435": "หน้าลิง", + "1f9a7": "อุรังอุตัง", + "1f436": "หน้าสุนัข", + "1f43a": "หมาป่า", + "1f98a": "จิ้งจอก", + "1f99d": "แรคคูน", + "1f431": "หน้าแมว", + "1f981": "สิงโต", + "1f42f": "หน้าเสือ", + "1f434": "หน้าม้า", + "1f984": "ยูนิคอร์น", + "1f993": "ม้าลาย", + "1f98c": "กวาง", + "1f42e": "หน้าวัว", + "1f437": "หน้าหมู", + "1f417": "หมูป่าตัวผู้", + "1f42a": "อูฐโหนกเดียว", + "1f999": "ลามะ", + "1f992": "ยีราฟ", + "1f418": "ช้าง", + "1f9a3": "ช้างแมมมอธ", + "1f98f": "แรด", + "1f42d": "หน้าหนู", + "1f430": "หน้ากระต่าย", + "1f43f": "ชิปมังก์", + "1f994": "เฮดจ์ฮ็อก", + "1f987": "ค้างคาว", + "1f43b": "หมี", + "1f428": "โคอาล่า", + "1f9a5": "สลอธ", + "1f9a6": "ตัวนาก", + "1f998": "จิงโจ้", + "1f425": "ลูกเจี๊ยบยืนหันหน้า", + "1f426": "นก", + "1f54a": "นกพิราบขาว", + "1f986": "เป็ด", + "1f989": "นกฮูก", + "1f9a4": "นกโดโด", + "1fab6": "ขนนก", + "1f9a9": "นกฟลามิงโก", + "1f99a": "นกยูง", + "1f99c": "นกแก้ว", + "1f40a": "จระเข้", + "1f422": "เต่า", + "1f98e": "จิ้งจก", + "1f40d": "งู", + "1f432": "หน้ามังกร", + "1f995": "ไดโนเสาร์", + "1f433": "ปลาวาฬพ่นน้ำ", + "1f42c": "ปลาโลมา", + "1f9ad": "แมวน้ำ", + "1f41f": "ปลา", + "1f420": "ปลาเขตร้อน", + "1f988": "ฉลาม", + "1f419": "ปลาหมึกยักษ์", + "1f41a": "หอย", + "1f40c": "หอยทาก", + "1f98b": "ผีเสื้อ", + "1f41b": "แมลง", + "1f41d": "ผึ้ง", + "1f41e": "เต่าทอง", + "1f490": "ช่อดอกไม้", + "1f339": "ดอกกุหลาบ", + "1f33a": "ดอกชบา", + "1f33b": "ดอกทานตะวัน", + "1f337": "ทิวลิป", + "1f332": "ต้นสน", + "1f333": "ต้นไม้ร่มรื่น", + "1f334": "ต้นมะพร้าว", + "1f335": "ตะบองเพชร", + "1f33f": "สมุนไพร", + "1f341": "ใบเมเปิ้ล", + "1f344": "เห็ด", + "1f347": "องุ่น", + "1f348": "เมลอน", + "1f349": "แตงโม", + "1f34a": "ส้ม", + "1f34b": "เลมอน", + "1f34c": "กล้วย", + "1f34d": "สับปะรด", + "1f96d": "มะม่วง", + "1f34f": "แอปเปิ้ลเขียว", + "1f350": "ลูกแพร์", + "1f351": "ลูกพีช", + "1f352": "เชอร์รี่", + "1f353": "สตรอว์เบอร์รี่", + "1fad0": "บลูเบอร์รี่", + "1f95d": "กีวี", + "1f345": "มะเขือเทศ", + "1fad2": "มะกอก", + "1f965": "มะพร้าว", + "1f951": "อาโวคาโด", + "1f346": "มะเขือยาว", + "1f955": "แครอท", + "1f33d": "ข้าวโพด", + "1f336": "พริก", + "1f96c": "ผักใบเขียว", + "1f966": "บรอกโคลี", + "1f9c5": "หอมหัวใหญ่", + "1f95c": "ถั่ว", + "1f950": "ครัวซอง", + "1f956": "ขนมปังฝรั่งเศส", + "1f968": "เพรตเซล", + "1f96f": "เบเกิล", + "1f95e": "แพนเค้ก", + "1f9c7": "วาฟเฟิล", + "1f354": "แฮมเบอร์เกอร์", + "1f355": "พิซซ่า 1 ชิ้น", + "1f32d": "ฮอทด็อก", + "1f32e": "ทาโก้", + "1f37f": "ป๊อปคอร์น", + "1f980": "ปู", + "1f99e": "กุ้งมังกร", + "1f368": "ไอศกรีม", + "1f369": "โดนัท", + "1f36a": "คุกกี้", + "1f382": "เค้กวันเกิด", + "1f9c1": "คัพเค้ก", + "1f36b": "ช็อกโกแลต", + "1f36c": "ลูกอม", + "1f36d": "อมยิ้ม", + "1fad6": "กาน้ำชา", + "1f9c3": "เครื่องดื่มแบบกล่อง", + "1f9c9": "ชามาเต", + "1f9ed": "เข็มทิศ", + "1f3d4": "ภูเขามีหิมะ", + "1f30b": "ภูเขาไฟ", + "1f3d5": "ตั้งแคมป์", + "1f3dd": "เกาะ", + "1f3e1": "บ้านพร้อมสวน", + "26f2": "น้ำพุ", + "1f3a0": "ม้าหมุน", + "1f3a1": "ชิงช้าสวรรค์", + "1f3a2": "รถไฟเหาะ", + "1f488": "ร้านตัดผม", + "1f686": "รถไฟ", + "1f68b": "ตู้รถราง", + "1f68d": "รถบัสกำลังมา", + "1f695": "แท็กซี่", + "1f697": "รถ", + "1f69a": "รถขนส่ง", + "1f69c": "แทร็กเตอร์", + "1f6f5": "รถสกู๊ตเตอร์", + "1f6fa": "รถสามล้อ", + "1f6f4": "สกู๊ตเตอร์", + "1f6f9": "สเก็ตบอร์ด", + "1f6fc": "รองเท้าสเก็ต", + "2693": "สมอเรือ", + "26f5": "เรือใบ", + "1f6f6": "แคนู", + "1f6a4": "เรือด่วน", + "1f6a2": "เรือ", + "2708": "เครื่องบิน", + "1f681": "เฮลิคอปเตอร์", + "1f6a0": "เคเบิลคาร์", + "1f6f0": "ดาวเทียม", + "1f680": "จรวด", + "1f6f8": "จานบิน", + "23f0": "นาฬิกาปลุก", + "1f319": "พระจันทร์เสี้ยว", + "1f321": "เครื่องวัดอุณหภูมิ", + "2600": "พระอาทิตย์", + "1fa90": "ดาวเคราะห์ที่มีวงแหวน", + "1f31f": "ดาวส่องแสง", + "1f300": "ไซโคลน", + "1f308": "รุ้ง", + "2602": "ร่ม", + "2744": "เกล็ดหิมะ", + "2604": "ดาวหาง", + "1f525": "ไฟ", + "1f4a7": "หยดน้ำ", + "1f30a": "คลื่น", + "1f383": "ฟักทองฮาโลวีน", + "2728": "ประกายวิบวับ", + "1f388": "ลูกโป่ง", + "1f389": "ปาร์ตี้", + "1f38f": "ธงปลาคาร์พ", + "1f380": "ริบบิ้น", + "1f381": "ของขวัญ", + "1f39f": "ตั๋วเข้าชม", + "1f3c6": "ถ้วยรางวัล", + "26bd": "ลูกฟุตบอล", + "1f3c0": "บาสเกตบอล", + "1f3c8": "อเมริกันฟุตบอล", + "1f3be": "เทนนิส", + "1f94f": "จานร่อน", + "1f3d3": "ปิงปอง", + "1f3f8": "แบดมินตัน", + "1f93f": "หน้ากากดำน้ำ", + "1f94c": "ลูกกลิ้งหิน", + "1f3af": "กลางเป้า", + "1fa80": "โยโย่", + "1fa81": "ว่าว", + "1f52e": "ลูกแก้ววิเศษ", + "1f3b2": "ลูกเต๋า", + "1f9e9": "จิ๊กซอว์", + "1f3a8": "จานสีวาดรูป", + "1f9f5": "ด้าย", + "1f455": "เสื้อยืด", + "1f9e6": "ถุงเท้า", + "1f457": "ชุดกระโปรง", + "1fa73": "กางเกงขาสั้น", + "1f392": "เป้นักเรียน", + "1f45f": "รองเท้ากีฬา", + "1f451": "มงกุฎ", + "1f9e2": "หมวกแก๊ป", + "1f484": "ลิปสติก", + "1f48d": "แหวน", + "1f48e": "อัญมณี", + "1f4e2": "เครื่องขยายเสียง", + "1f3b6": "โน้ตดนตรีหลายตัว", + "1f399": "ไมค์สตูดิโอ", + "1f4fb": "วิทยุ", + "1f3b7": "แซ็กโซโฟน", + "1fa97": "แอคคอร์เดียน", + "1f3b8": "กีต้าร์", + "1f3ba": "ทรัมเป็ต", + "1f3bb": "ไวโอลิน", + "1fa95": "แบนโจ", + "1f941": "กลอง", + "260e": "โทรศัพท์", + "1f50b": "แบตเตอรี่", + "1f4bf": "บลูเรย์", + "1f9ee": "ลูกคิด", + "1f3ac": "สเลท", + "1f4a1": "หลอดไฟ", + "1f526": "ไฟฉาย", + "1f3ee": "โคมไฟแดง", + "1f4d5": "หนังสือปิด", + "1f3f7": "ป้าย", + "1f4b3": "บัตรเครดิต", + "270f": "ดินสอ", + "1f58c": "แปรงทาสี", + "1f58d": "ดินสอสี", + "1f4cc": "หมุดปัก", + "1f4ce": "คลิปหนีบกระดาษ", + "1f511": "กุญแจ", + "1fa83": "บูมเมอแรง", + "1f3f9": "ธนูและลูกศร", + "2696": "ตราชั่ง", + "1f9f2": "แม่เหล็ก", + "1f9ea": "หลอดทดลอง", + "1f9ec": "ดีเอ็นเอ", + "1f52c": "กล้องจุลทรรศน์", + "1f52d": "กล้องโทรทรรศน์", + "1f4e1": "จานดาวเทียม", + "1fa91": "เก้าอี้", + "1f9f9": "ไม้กวาด", + "1f5ff": "รูปปั้นโมไอ" + }, + "tr": { + "1f47d": "uzaylı", + "1f916": "robot", + "1f9e0": "beyin", + "1f441": "göz", + "1f9d9": "büyücü", + "1f9da": "peri", + "1f9dc": "balık insan", + "1f435": "maymun yüzü", + "1f9a7": "orangutan", + "1f436": "köpek yüzü", + "1f43a": "kurt", + "1f98a": "tilki", + "1f99d": "rakun", + "1f431": "kedi yüzü", + "1f981": "aslan", + "1f42f": "kaplan yüzü", + "1f434": "at yüzü", + "1f984": "tek boynuzlu at", + "1f993": "zebra", + "1f98c": "geyik", + "1f42e": "inek yüzü", + "1f437": "domuz yüzü", + "1f417": "yaban domuzu", + "1f42a": "deve", + "1f999": "lama", + "1f992": "zürafa", + "1f418": "fil", + "1f9a3": "mamut", + "1f98f": "gergedan", + "1f42d": "fare yüzü", + "1f430": "tavşan yüzü", + "1f43f": "sincap", + "1f994": "kirpi", + "1f987": "yarasa", + "1f43b": "ayı", + "1f428": "koala", + "1f9a5": "tembel hayvan", + "1f9a6": "su samuru", + "1f998": "kanguru", + "1f425": "önden civciv", + "1f426": "kuş", + "1f54a": "güvercin", + "1f986": "ördek", + "1f989": "baykuş", + "1f9a4": "dodo kuşu", + "1fab6": "kuş tüyü", + "1f9a9": "flamingo", + "1f99a": "tavus kuşu", + "1f99c": "papağan", + "1f40a": "timsah", + "1f422": "kaplumbağa", + "1f98e": "kertenkele", + "1f40d": "yılan", + "1f432": "ejderha yüzü", + "1f995": "soropod", + "1f433": "su püskürten balina", + "1f42c": "yunus", + "1f9ad": "fok", + "1f41f": "balık", + "1f420": "tropikal balık", + "1f988": "köpek balığı", + "1f419": "ahtapot", + "1f41a": "deniz kabuğu", + "1f40c": "salyangoz", + "1f98b": "kelebek", + "1f41b": "tırtıl", + "1f41d": "bal arısı", + "1f41e": "uğur böceği", + "1f490": "buket", + "1f339": "gül", + "1f33a": "çingülü", + "1f33b": "ayçiçeği", + "1f337": "lale", + "1f332": "yaprak dökmeyen ağaç", + "1f333": "yaprak döken ağaç", + "1f334": "palmiye ağacı", + "1f335": "kaktüs", + "1f33f": "ot", + "1f341": "akçaağaç yaprağı", + "1f344": "mantar", + "1f347": "üzüm", + "1f348": "kavun", + "1f349": "karpuz", + "1f34a": "mandalina", + "1f34b": "limon", + "1f34c": "muz", + "1f34d": "ananas", + "1f96d": "mango", + "1f34f": "yeşil elma", + "1f350": "armut", + "1f351": "şeftali", + "1f352": "kiraz", + "1f353": "çilek", + "1fad0": "yaban mersini", + "1f95d": "kivi", + "1f345": "domates", + "1fad2": "zeytin", + "1f965": "Hindistan cevizi", + "1f951": "avokado", + "1f346": "patlıcan", + "1f955": "havuç", + "1f33d": "mısır koçanı", + "1f336": "acı biber", + "1f96c": "yeşil yapraklı sebze", + "1f966": "brokoli", + "1f9c5": "soğan", + "1f95c": "yer fıstığı", + "1f950": "kruvasan", + "1f956": "baget ekmek", + "1f968": "pretzel", + "1f96f": "simit", + "1f95e": "krep", + "1f9c7": "waffle", + "1f354": "hamburger", + "1f355": "pizza dilimi", + "1f32d": "sosisli sandviç", + "1f32e": "tako", + "1f37f": "patlamış mısır", + "1f980": "yengeç", + "1f99e": "ıstakoz", + "1f368": "dondurma", + "1f369": "donut", + "1f36a": "kurabiye", + "1f382": "doğum günü pastası", + "1f9c1": "cupcake", + "1f36b": "çikolata", + "1f36c": "şekerleme", + "1f36d": "lolipop", + "1fad6": "demlik", + "1f9c3": "içecek kutusu", + "1f9c9": "mate çayı", + "1f9ed": "pusula", + "1f3d4": "karla kaplı dağ", + "1f30b": "yanardağ", + "1f3d5": "kamp", + "1f3dd": "ıssız ada", + "1f3e1": "bahçeli ev", + "26f2": "fıskiye", + "1f3a0": "atlıkarınca", + "1f3a1": "dönme dolap", + "1f3a2": "hız treni", + "1f488": "berber dükkanı", + "1f686": "tren", + "1f68b": "tramvay vagonu", + "1f68d": "yaklaşan otobüs", + "1f695": "taksi", + "1f697": "araba", + "1f69a": "nakliye kamyonu", + "1f69c": "traktör", + "1f6f5": "motorlu skuter", + "1f6fa": "elektrikli çekçek", + "1f6f4": "ayakla sürülen skuter", + "1f6f9": "kaykay", + "1f6fc": "paten", + "2693": "çıpa", + "26f5": "yelkenli tekne", + "1f6f6": "kano", + "1f6a4": "sürat teknesi", + "1f6a2": "gemi", + "2708": "uçak", + "1f681": "helikopter", + "1f6a0": "dağ teleferik hattı", + "1f6f0": "uydu", + "1f680": "roket", + "1f6f8": "uçan daire", + "23f0": "çalar saat", + "1f319": "hilal", + "1f321": "termometre", + "2600": "güneş", + "1fa90": "halkalı gezegen", + "1f31f": "parıldayan yıldız", + "1f300": "siklon", + "1f308": "gökkuşağı", + "2602": "şemsiye", + "2744": "kar tanesi", + "2604": "kuyruklu yıldız", + "1f525": "ateş", + "1f4a7": "damlacık", + "1f30a": "dalga", + "1f383": "kabak fener", + "2728": "parıltılar", + "1f388": "balon", + "1f389": "parti konfetisi", + "1f38f": "sazan şekilli flama", + "1f380": "kurdele", + "1f381": "paketlenmiş hediye", + "1f39f": "giriş bileti", + "1f3c6": "zafer kupası", + "26bd": "futbol topu", + "1f3c0": "basketbol", + "1f3c8": "amerikan futbolu", + "1f3be": "tenis", + "1f94f": "frizbi", + "1f3d3": "masa tenisi", + "1f3f8": "badminton", + "1f93f": "dalgıç maskesi", + "1f94c": "curling taşı", + "1f3af": "tam isabet", + "1fa80": "yoyo", + "1fa81": "uçurtma", + "1f52e": "kristal küre", + "1f3b2": "oyun zarı", + "1f9e9": "yapboz parçası", + "1f3a8": "boya paleti", + "1f9f5": "iplik", + "1f455": "tişört", + "1f9e6": "çorap", + "1f457": "elbise", + "1fa73": "şort", + "1f392": "okul çantası", + "1f45f": "koşu ayakkabısı", + "1f451": "taç", + "1f9e2": "siperli şapka", + "1f484": "ruj", + "1f48d": "yüzük", + "1f48e": "mücevher", + "1f4e2": "hoparlör", + "1f3b6": "müzik notaları", + "1f399": "stüdyo mikrofonu", + "1f4fb": "radyo", + "1f3b7": "saksafon", + "1fa97": "akordiyon", + "1f3b8": "gitar", + "1f3ba": "trompet", + "1f3bb": "keman", + "1fa95": "banjo", + "1f941": "davul", + "260e": "telefon", + "1f50b": "pil", + "1f4bf": "optik disk", + "1f9ee": "abaküs", + "1f3ac": "film tahtası", + "1f4a1": "ampul", + "1f526": "el feneri", + "1f3ee": "kırmızı kağıt fener", + "1f4d5": "kapalı kitap", + "1f3f7": "etiket", + "1f4b3": "kredi kartı", + "270f": "kurşun kalem", + "1f58c": "boya fırçası", + "1f58d": "pastel boya", + "1f4cc": "raptiye", + "1f4ce": "ataş", + "1f511": "anahtar", + "1fa83": "bumerang", + "1f3f9": "ok ve yay", + "2696": "terazi", + "1f9f2": "mıknatıs", + "1f9ea": "deney tüpü", + "1f9ec": "dna", + "1f52c": "mikroskop", + "1f52d": "teleskop", + "1f4e1": "uydu anteni", + "1fa91": "sandalye", + "1f9f9": "süpürge", + "1f5ff": "moyai heykeli" + }, + "uk": { + "1f47d": "прибулець", + "1f916": "робот", + "1f9e0": "мозок", + "1f441": "око", + "1f9d9": "маг", + "1f9da": "фея", + "1f9dc": "казкова водяна істота", + "1f435": "морда мавпи", + "1f9a7": "орангутанг", + "1f436": "морда собаки", + "1f43a": "вовк", + "1f98a": "лис", + "1f99d": "єнот", + "1f431": "морда кота", + "1f981": "лев", + "1f42f": "морда тигра", + "1f434": "голова коня", + "1f984": "єдиноріг", + "1f993": "зебра", + "1f98c": "олень", + "1f42e": "морда корови", + "1f437": "рило свині", + "1f417": "вепр", + "1f42a": "одногорбий верблюд", + "1f999": "лама", + "1f992": "жирафа", + "1f418": "слон", + "1f9a3": "мамонт", + "1f98f": "носоріг", + "1f42d": "морда миші", + "1f430": "морда кроля", + "1f43f": "бурундук", + "1f994": "їжак", + "1f987": "кажан", + "1f43b": "ведмідь", + "1f428": "коала", + "1f9a5": "лінивець", + "1f9a6": "видра", + "1f998": "кенгуру", + "1f425": "курча, що стоїть", + "1f426": "птах", + "1f54a": "голуб", + "1f986": "качка", + "1f989": "сова", + "1f9a4": "дронт", + "1fab6": "пір’їна", + "1f9a9": "фламінго", + "1f99a": "павич", + "1f99c": "папуга", + "1f40a": "крокодил", + "1f422": "черепаха", + "1f98e": "ящірка", + "1f40d": "змія", + "1f432": "голова дракона", + "1f995": "завропод", + "1f433": "кит, що пускає фонтан", + "1f42c": "дельфін", + "1f9ad": "тюлень", + "1f41f": "риба", + "1f420": "тропічна риба", + "1f988": "акула", + "1f419": "восьминіг", + "1f41a": "морська мушля", + "1f40c": "равлик", + "1f98b": "метелик", + "1f41b": "комаха", + "1f41d": "бджола", + "1f41e": "сонечко", + "1f490": "букет", + "1f339": "троянда", + "1f33a": "гібіскус", + "1f33b": "соняшник", + "1f337": "тюльпан", + "1f332": "вічнозелене дерево", + "1f333": "листяне дерево", + "1f334": "пальма", + "1f335": "кактус", + "1f33f": "лікарська рослина", + "1f341": "кленовий листок", + "1f344": "гриб", + "1f347": "виноград", + "1f348": "диня", + "1f349": "кавун", + "1f34a": "танжерин", + "1f34b": "лимон", + "1f34c": "банан", + "1f34d": "ананас", + "1f96d": "манго", + "1f34f": "зелене яблуко", + "1f350": "груша", + "1f351": "персик", + "1f352": "вишні", + "1f353": "полуниця", + "1fad0": "лохина", + "1f95d": "ківі", + "1f345": "томат", + "1fad2": "оливка", + "1f965": "кокос", + "1f951": "авокадо", + "1f346": "баклажан", + "1f955": "морква", + "1f33d": "качан кукурудзи", + "1f336": "гострий перець", + "1f96c": "листя салату", + "1f966": "броколі", + "1f9c5": "цибуля", + "1f95c": "арахіс", + "1f950": "круасан", + "1f956": "багет", + "1f968": "крендель", + "1f96f": "бейгл", + "1f95e": "млинці", + "1f9c7": "вафля", + "1f354": "гамбургер", + "1f355": "піца", + "1f32d": "хот-дог", + "1f32e": "тако", + "1f37f": "попкорн", + "1f980": "краб", + "1f99e": "омар", + "1f368": "морозиво", + "1f369": "пончик", + "1f36a": "печиво", + "1f382": "торт на день народження", + "1f9c1": "капкейк", + "1f36b": "плитка шоколаду", + "1f36c": "цукерка", + "1f36d": "льодяник", + "1fad6": "чайник", + "1f9c3": "пакетик із напоєм", + "1f9c9": "мате", + "1f9ed": "компас", + "1f3d4": "гора із засніженою верхівкою", + "1f30b": "вулкан", + "1f3d5": "кемпінг", + "1f3dd": "безлюдний острів", + "1f3e1": "будинок із садом", + "26f2": "фонтан", + "1f3a0": "коник на каруселі", + "1f3a1": "чортове колесо", + "1f3a2": "американські гірки", + "1f488": "вивіска перукаря (смугастий стовп)", + "1f686": "потяг", + "1f68b": "вагон трамвая", + "1f68d": "автобус, що наближається", + "1f695": "таксі", + "1f697": "автомобіль", + "1f69a": "вантажівка для доставки", + "1f69c": "трактор", + "1f6f5": "мопед", + "1f6fa": "авторикша", + "1f6f4": "самокат", + "1f6f9": "скейтборд", + "1f6fc": "роликовий ковзан", + "2693": "якір", + "26f5": "вітрильник", + "1f6f6": "каное", + "1f6a4": "швидкохідний катер", + "1f6a2": "корабель", + "2708": "літак", + "1f681": "гелікоптер", + "1f6a0": "канатна дорога в горах", + "1f6f0": "супутник", + "1f680": "ракета", + "1f6f8": "летюча тарілка", + "23f0": "будильник", + "1f319": "серп місяця", + "1f321": "термометр", + "2600": "сонце", + "1fa90": "планета з кільцем", + "1f31f": "сяйна зірка", + "1f300": "циклон", + "1f308": "веселка", + "2602": "парасолька", + "2744": "сніжинка", + "2604": "комета", + "1f525": "вогонь", + "1f4a7": "крапля", + "1f30a": "хвиля", + "1f383": "ліхтар-гарбуз", + "2728": "блискітки", + "1f388": "повітряна кулька", + "1f389": "хлопавка", + "1f38f": "вітровказ у формі коропів", + "1f380": "бант зі стрічки", + "1f381": "подарунок", + "1f39f": "вхідні квитки", + "1f3c6": "приз", + "26bd": "футбольний м’яч", + "1f3c0": "баскетбольний м’яч", + "1f3c8": "мʼяч для американського футболу", + "1f3be": "тенісний м’яч", + "1f94f": "літаючий диск", + "1f3d3": "ракетка і кулька для пінг-понгу", + "1f3f8": "ракетка і волан для бадмінтону", + "1f93f": "маска з трубкою", + "1f94c": "камʼяна шайба для керлінгу", + "1f3af": "мішень із прямим влученням", + "1fa80": "йо-йо", + "1fa81": "повітряний змій", + "1f52e": "кришталева куля", + "1f3b2": "гральна кість", + "1f9e9": "елемент пазла", + "1f3a8": "палітра художника", + "1f9f5": "нитка", + "1f455": "теніска поло", + "1f9e6": "шкарпетки", + "1f457": "сукня", + "1fa73": "шорти", + "1f392": "шкільний рюкзак", + "1f45f": "кросівка", + "1f451": "корона", + "1f9e2": "бейсболка", + "1f484": "помада", + "1f48d": "каблучка", + "1f48e": "коштовний камінь", + "1f4e2": "гучномовець", + "1f3b6": "музичні ноти", + "1f399": "студійний мікрофон", + "1f4fb": "радіоприймач", + "1f3b7": "саксофон", + "1fa97": "акордеон", + "1f3b8": "гітара", + "1f3ba": "труба", + "1f3bb": "скрипка", + "1fa95": "банджо", + "1f941": "барабан", + "260e": "телефон", + "1f50b": "батарея", + "1f4bf": "компакт-диск", + "1f9ee": "рахівниця", + "1f3ac": "кінохлопавка", + "1f4a1": "лампочка", + "1f526": "ліхтарик", + "1f3ee": "червоний паперовий ліхтар", + "1f4d5": "закрита книга", + "1f3f7": "бирка", + "1f4b3": "кредитна картка", + "270f": "олівець", + "1f58c": "пензель", + "1f58d": "пастель", + "1f4cc": "канцелярська кнопка", + "1f4ce": "скріпка", + "1f511": "ключ", + "1fa83": "бумеранг", + "1f3f9": "лук і стріла", + "2696": "ваги", + "1f9f2": "магніт", + "1f9ea": "пробірка", + "1f9ec": "ДНК", + "1f52c": "мікроскоп", + "1f52d": "телескоп", + "1f4e1": "супутникова антена", + "1fa91": "стілець", + "1f9f9": "мітла", + "1f5ff": "статуя з Острова Пасхи" + }, + "vi": { + "1f47d": "người ngoài hành tinh", + "1f916": "mặt rô-bốt", + "1f9e0": "não", + "1f441": "mắt", + "1f9d9": "pháp sư", + "1f9da": "tiên", + "1f9dc": "người cá", + "1f435": "mặt khỉ", + "1f9a7": "đười ươi", + "1f436": "mặt cún", + "1f43a": "mặt chó sói", + "1f98a": "cáo", + "1f99d": "gấu trúc", + "1f431": "mặt mèo", + "1f981": "mặt sư tử", + "1f42f": "mặt hổ", + "1f434": "mặt ngựa", + "1f984": "kỳ lân", + "1f993": "ngựa vằn", + "1f98c": "hươu", + "1f42e": "mặt bò", + "1f437": "mặt lợn", + "1f417": "lợn rừng", + "1f42a": "lạc đà", + "1f999": "lạc đà không bướu", + "1f992": "hươu cao cổ", + "1f418": "voi", + "1f9a3": "voi ma mút", + "1f98f": "tê giác", + "1f42d": "mặt chuột", + "1f430": "mặt thỏ", + "1f43f": "sóc chuột", + "1f994": "nhím", + "1f987": "dơi", + "1f43b": "gấu", + "1f428": "gấu túi", + "1f9a5": "con lười", + "1f9a6": "rái cá", + "1f998": "chuột túi", + "1f425": "mặt trước gà con", + "1f426": "chim", + "1f54a": "bồ câu", + "1f986": "vịt", + "1f989": "cú", + "1f9a4": "chim cưu", + "1fab6": "lông chim", + "1f9a9": "hồng hạc", + "1f99a": "con công", + "1f99c": "con vẹt", + "1f40a": "cá sấu", + "1f422": "rùa", + "1f98e": "thằn lằn", + "1f40d": "rắn", + "1f432": "mặt rồng", + "1f995": "khủng long chân thằn lằn", + "1f433": "cá voi đang phun nước", + "1f42c": "cá heo", + "1f9ad": "chó biển", + "1f41f": "cá", + "1f420": "cá nhiệt đới", + "1f988": "cá mập", + "1f419": "bạch tuộc", + "1f41a": "vỏ xoắn ốc", + "1f40c": "ốc sên", + "1f98b": "bướm", + "1f41b": "con bọ", + "1f41d": "ong mật", + "1f41e": "bọ rùa", + "1f490": "bó hoa", + "1f339": "hoa hồng", + "1f33a": "hoa dâm bụt", + "1f33b": "hoa hướng dương", + "1f337": "hoa tulip", + "1f332": "cây thường xanh", + "1f333": "cây rụng lá", + "1f334": "cây cọ", + "1f335": "cây xương rồng", + "1f33f": "thảo mộc", + "1f341": "lá phong", + "1f344": "nấm", + "1f347": "chùm nho", + "1f348": "dưa", + "1f349": "dưa hấu", + "1f34a": "quýt", + "1f34b": "chanh tây", + "1f34c": "chuối", + "1f34d": "dứa", + "1f96d": "xoài", + "1f34f": "táo xanh", + "1f350": "lê", + "1f351": "đào", + "1f352": "anh đào", + "1f353": "dâu tây", + "1fad0": "quả việt quất", + "1f95d": "quả kiwi", + "1f345": "cà chua", + "1fad2": "ôliu", + "1f965": "dừa", + "1f951": "quả bơ", + "1f346": "cà tím", + "1f955": "cà rốt", + "1f33d": "bắp ngô", + "1f336": "quả ớt", + "1f96c": "xanh lá", + "1f966": "xúp lơ xanh", + "1f9c5": "hành", + "1f95c": "đậu phộng", + "1f950": "bánh sừng bò", + "1f956": "bánh mì que", + "1f968": "bánh quy xoắn", + "1f96f": "bánh mỳ vòng", + "1f95e": "bánh kếp", + "1f9c7": "bánh quế", + "1f354": "bánh hamburger", + "1f355": "bánh pizza", + "1f32d": "bánh mì xúc xích", + "1f32e": "bánh taco", + "1f37f": "bỏng ngô", + "1f980": "cua", + "1f99e": "tôm hùm", + "1f368": "kem", + "1f369": "bánh rán vòng", + "1f36a": "bánh quy", + "1f382": "bánh sinh nhật", + "1f9c1": "bánh nướng nhỏ", + "1f36b": "thanh sô cô la", + "1f36c": "kẹo", + "1f36d": "kẹo mút", + "1fad6": "ấm trà", + "1f9c3": "hộp đồ uống", + "1f9c9": "trà nhựa ruồi", + "1f9ed": "la bàn", + "1f3d4": "đỉnh núi phủ tuyết", + "1f30b": "núi lửa", + "1f3d5": "cắm trại", + "1f3dd": "đảo hoang", + "1f3e1": "nhà có vườn", + "26f2": "đài phun nước", + "1f3a0": "ngựa đu quay", + "1f3a1": "vòng đu quay", + "1f3a2": "tàu lượn siêu tốc", + "1f488": "biển hiệu của thợ cắt tóc", + "1f686": "tàu hỏa", + "1f68b": "tàu điện", + "1f68d": "xe buýt đang tới", + "1f695": "taxi", + "1f697": "ô tô", + "1f69a": "xe tải giao hàng", + "1f69c": "máy kéo", + "1f6f5": "xe tay ga", + "1f6fa": "xe lam", + "1f6f4": "xe hẩy", + "1f6f9": "ván trượt", + "1f6fc": "giày trượt patin", + "2693": "mỏ neo", + "26f5": "thuyền buồm", + "1f6f6": "xuồng", + "1f6a4": "xuồng cao tốc", + "1f6a2": "tàu thủy", + "2708": "máy bay", + "1f681": "máy bay trực thăng", + "1f6a0": "cáp treo trên núi", + "1f6f0": "vệ tinh", + "1f680": "tên lửa", + "1f6f8": "đĩa bay", + "23f0": "đồng hồ báo thức", + "1f319": "trăng lưỡi liềm", + "1f321": "nhiệt kế", + "2600": "mặt trời", + "1fa90": "hành tinh có vành đai bao quanh", + "1f31f": "ngôi sao lấp lánh", + "1f300": "hình lốc xoáy", + "1f308": "cầu vồng", + "2602": "cái ô", + "2744": "bông tuyết", + "2604": "sao chổi", + "1f525": "lửa", + "1f4a7": "giọt nước", + "1f30a": "sóng nước", + "1f383": "đèn lồng bí ngô", + "2728": "ánh lấp lánh", + "1f388": "bóng bay", + "1f389": "pháo giấy buổi tiệc", + "1f38f": "cờ cá chép", + "1f380": "ruy băng", + "1f381": "gói quà", + "1f39f": "vé vào cửa", + "1f3c6": "cúp", + "26bd": "bóng đá", + "1f3c0": "bóng rổ", + "1f3c8": "bóng bầu dục Mỹ", + "1f3be": "quần vợt", + "1f94f": "đĩa bay trò chơi", + "1f3d3": "bóng bàn", + "1f3f8": "cầu lông", + "1f93f": "mặt nạ lặn", + "1f94c": "bi đá trên băng", + "1f3af": "trúng đích", + "1fa80": "yo-yo", + "1fa81": "diều", + "1f52e": "quả cầu pha lê", + "1f3b2": "trò xúc xắc", + "1f9e9": "ghép hình", + "1f3a8": "bảng màu", + "1f9f5": "sợi chỉ", + "1f455": "áo phông", + "1f9e6": "tất", + "1f457": "váy", + "1fa73": "quần soóc", + "1f392": "ba lô đi học", + "1f45f": "giày chạy", + "1f451": "vương miện", + "1f9e2": "mũ lưỡi trai", + "1f484": "son môi", + "1f48d": "nhẫn", + "1f48e": "đá quý", + "1f4e2": "loa phát thanh", + "1f3b6": "các nốt nhạc", + "1f399": "micrô phòng thu âm", + "1f4fb": "radio", + "1f3b7": "kèn saxophone", + "1fa97": "phong cầm", + "1f3b8": "đàn ghi-ta", + "1f3ba": "kèn trumpet", + "1f3bb": "đàn violin", + "1fa95": "đàn banjo", + "1f941": "trống", + "260e": "điện thoại bàn", + "1f50b": "pin", + "1f4bf": "đĩa quang", + "1f9ee": "bàn tính", + "1f3ac": "bảng clapper", + "1f4a1": "bóng đèn", + "1f526": "đèn pin", + "1f3ee": "đèn lồng giấy màu đỏ", + "1f4d5": "sách đóng", + "1f3f7": "nhãn", + "1f4b3": "thẻ tín dụng", + "270f": "bút chì", + "1f58c": "cọ vẽ tranh", + "1f58d": "bút sáp màu", + "1f4cc": "đinh ghim", + "1f4ce": "kẹp giấy", + "1f511": "chìa khóa", + "1fa83": "bumơrang", + "1f3f9": "cung tên", + "2696": "cân thăng bằng", + "1f9f2": "nam châm", + "1f9ea": "ống nghiệm", + "1f9ec": "adn", + "1f52c": "kính hiển vi", + "1f52d": "kính viễn vọng", + "1f4e1": "ăng-ten vệ tinh", + "1fa91": "ghế", + "1f9f9": "cây chổi", + "1f5ff": "tượng moai" + }, + "zh-CN": { + "1f47d": "外星人", + "1f916": "机器人", + "1f9e0": "脑", + "1f441": "眼睛", + "1f9d9": "法师", + "1f9da": "精灵", + "1f9dc": "人鱼", + "1f435": "猴头", + "1f9a7": "红毛猩猩", + "1f436": "狗脸", + "1f43a": "狼", + "1f98a": "狐狸", + "1f99d": "浣熊", + "1f431": "猫脸", + "1f981": "狮子", + "1f42f": "老虎头", + "1f434": "马头", + "1f984": "独角兽", + "1f993": "斑马", + "1f98c": "鹿", + "1f42e": "奶牛头", + "1f437": "猪头", + "1f417": "野猪", + "1f42a": "骆驼", + "1f999": "美洲鸵", + "1f992": "长颈鹿", + "1f418": "大象", + "1f9a3": "猛犸", + "1f98f": "犀牛", + "1f42d": "老鼠头", + "1f430": "兔子头", + "1f43f": "松鼠", + "1f994": "刺猬", + "1f987": "蝙蝠", + "1f43b": "熊", + "1f428": "考拉", + "1f9a5": "树懒", + "1f9a6": "水獭", + "1f998": "袋鼠", + "1f425": "正面朝向的小鸡", + "1f426": "鸟", + "1f54a": "鸽", + "1f986": "鸭子", + "1f989": "猫头鹰", + "1f9a4": "渡渡鸟", + "1fab6": "羽毛", + "1f9a9": "火烈鸟", + "1f99a": "孔雀", + "1f99c": "鹦鹉", + "1f40a": "鳄鱼", + "1f422": "龟", + "1f98e": "蜥蜴", + "1f40d": "蛇", + "1f432": "龙头", + "1f995": "蜥蜴类", + "1f433": "喷水的鲸", + "1f42c": "海豚", + "1f9ad": "海豹", + "1f41f": "鱼", + "1f420": "热带鱼", + "1f988": "鲨鱼", + "1f419": "章鱼", + "1f41a": "海螺", + "1f40c": "蜗牛", + "1f98b": "蝴蝶", + "1f41b": "毛毛虫", + "1f41d": "蜜蜂", + "1f41e": "瓢虫", + "1f490": "花束", + "1f339": "玫瑰", + "1f33a": "芙蓉", + "1f33b": "向日葵", + "1f337": "郁金香", + "1f332": "松树", + "1f333": "落叶树", + "1f334": "棕榈树", + "1f335": "仙人掌", + "1f33f": "药草", + "1f341": "枫叶", + "1f344": "蘑菇", + "1f347": "葡萄", + "1f348": "甜瓜", + "1f349": "西瓜", + "1f34a": "橘子", + "1f34b": "柠檬", + "1f34c": "香蕉", + "1f34d": "菠萝", + "1f96d": "芒果", + "1f34f": "青苹果", + "1f350": "梨", + "1f351": "桃", + "1f352": "樱桃", + "1f353": "草莓", + "1fad0": "蓝莓", + "1f95d": "猕猴桃", + "1f345": "西红柿", + "1fad2": "橄榄", + "1f965": "椰子", + "1f951": "鳄梨", + "1f346": "茄子", + "1f955": "胡萝卜", + "1f33d": "玉米", + "1f336": "红辣椒", + "1f96c": "绿叶蔬菜", + "1f966": "西兰花", + "1f9c5": "洋葱", + "1f95c": "花生", + "1f950": "羊角面包", + "1f956": "法式长棍面包", + "1f968": "椒盐卷饼", + "1f96f": "面包圈", + "1f95e": "烙饼", + "1f9c7": "华夫饼", + "1f354": "汉堡", + "1f355": "披萨", + "1f32d": "热狗", + "1f32e": "墨西哥卷饼", + "1f37f": "爆米花", + "1f980": "蟹", + "1f99e": "龙虾", + "1f368": "冰淇淋", + "1f369": "甜甜圈", + "1f36a": "饼干", + "1f382": "生日蛋糕", + "1f9c1": "纸杯蛋糕", + "1f36b": "巧克力", + "1f36c": "糖", + "1f36d": "棒棒糖", + "1fad6": "茶壶", + "1f9c3": "饮料盒", + "1f9c9": "马黛茶", + "1f9ed": "指南针", + "1f3d4": "雪山", + "1f30b": "火山", + "1f3d5": "露营", + "1f3dd": "无人荒岛", + "1f3e1": "别墅", + "26f2": "喷泉", + "1f3a0": "旋转木马", + "1f3a1": "摩天轮", + "1f3a2": "过山车", + "1f488": "理发店", + "1f686": "火车", + "1f68b": "有轨电车", + "1f68d": "迎面驶来的公交车", + "1f695": "出租车", + "1f697": "汽车", + "1f69a": "货车", + "1f69c": "拖拉机", + "1f6f5": "小型摩托车", + "1f6fa": "三轮摩托车", + "1f6f4": "滑板车", + "1f6f9": "滑板", + "1f6fc": "四轮滑冰鞋", + "2693": "锚", + "26f5": "帆船", + "1f6f6": "独木舟", + "1f6a4": "快艇", + "1f6a2": "船", + "2708": "飞机", + "1f681": "直升机", + "1f6a0": "缆车", + "1f6f0": "卫星", + "1f680": "火箭", + "1f6f8": "飞碟", + "23f0": "闹钟", + "1f319": "弯月", + "1f321": "温度计", + "2600": "太阳", + "1fa90": "有环行星", + "1f31f": "闪亮的星星", + "1f300": "台风", + "1f308": "彩虹", + "2602": "伞", + "2744": "雪花", + "2604": "彗星", + "1f525": "火焰", + "1f4a7": "水滴", + "1f30a": "浪花", + "1f383": "南瓜灯", + "2728": "闪亮", + "1f388": "气球", + "1f389": "拉炮彩带", + "1f38f": "鲤鱼旗", + "1f380": "蝴蝶结", + "1f381": "礼物", + "1f39f": "入场券", + "1f3c6": "奖杯", + "26bd": "足球", + "1f3c0": "篮球", + "1f3c8": "美式橄榄球", + "1f3be": "网球", + "1f94f": "飞盘", + "1f3d3": "乒乓球", + "1f3f8": "羽毛球", + "1f93f": "潜水面罩", + "1f94c": "冰壶", + "1f3af": "正中靶心的飞镖", + "1fa80": "悠悠球", + "1fa81": "风筝", + "1f52e": "水晶球", + "1f3b2": "骰子", + "1f9e9": "拼图", + "1f3a8": "调色盘", + "1f9f5": "线", + "1f455": "T恤", + "1f9e6": "袜子", + "1f457": "连衣裙", + "1fa73": "短裤", + "1f392": "书包", + "1f45f": "跑鞋", + "1f451": "皇冠", + "1f9e2": "鸭舌帽", + "1f484": "唇膏", + "1f48d": "戒指", + "1f48e": "宝石", + "1f4e2": "喇叭", + "1f3b6": "多个音符", + "1f399": "录音室麦克风", + "1f4fb": "收音机", + "1f3b7": "萨克斯管", + "1fa97": "手风琴", + "1f3b8": "吉他", + "1f3ba": "小号", + "1f3bb": "小提琴", + "1fa95": "班卓琴", + "1f941": "鼓", + "260e": "电话", + "1f50b": "电池", + "1f4bf": "光盘", + "1f9ee": "算盘", + "1f3ac": "场记板", + "1f4a1": "灯泡", + "1f526": "手电筒", + "1f3ee": "红灯笼", + "1f4d5": "合上的书本", + "1f3f7": "标签", + "1f4b3": "信用卡", + "270f": "铅笔", + "1f58c": "画笔", + "1f58d": "蜡笔", + "1f4cc": "图钉", + "1f4ce": "回形针", + "1f511": "钥匙", + "1fa83": "回旋镖", + "1f3f9": "弓和箭", + "2696": "天平", + "1f9f2": "磁铁", + "1f9ea": "试管", + "1f9ec": "DNA", + "1f52c": "显微镜", + "1f52d": "望远镜", + "1f4e1": "卫星天线", + "1fa91": "椅子", + "1f9f9": "扫帚", + "1f5ff": "摩埃" + }, + "zh-TW": { + "1f47d": "外星人", + "1f916": "機器人", + "1f9e0": "腦", + "1f441": "眼睛", + "1f9d9": "魔術師", + "1f9da": "仙女", + "1f9dc": "人魚", + "1f435": "猴子頭", + "1f9a7": "猩猩", + "1f436": "狗頭", + "1f43a": "狼", + "1f98a": "狐狸", + "1f99d": "浣熊", + "1f431": "貓頭", + "1f981": "獅子", + "1f42f": "老虎頭", + "1f434": "馬頭", + "1f984": "獨角獸", + "1f993": "斑馬", + "1f98c": "鹿", + "1f42e": "牛頭", + "1f437": "豬頭", + "1f417": "野豬", + "1f42a": "單峰駱駝", + "1f999": "羊駝", + "1f992": "長頸鹿", + "1f418": "大象", + "1f9a3": "毛象", + "1f98f": "犀牛", + "1f42d": "老鼠頭", + "1f430": "兔子頭", + "1f43f": "松鼠", + "1f994": "刺蝟", + "1f987": "蝙蝠", + "1f43b": "熊", + "1f428": "無尾熊", + "1f9a5": "樹懶", + "1f9a6": "水獺", + "1f998": "袋鼠", + "1f425": "小雞", + "1f426": "鳥", + "1f54a": "飛鳥", + "1f986": "鴨子", + "1f989": "貓頭鷹", + "1f9a4": "渡渡鳥", + "1fab6": "羽毛", + "1f9a9": "紅鶴", + "1f99a": "孔雀", + "1f99c": "鸚鵡", + "1f40a": "鱷魚", + "1f422": "烏龜", + "1f98e": "蜥蜴", + "1f40d": "蛇", + "1f432": "龍頭", + "1f995": "蜥腳類恐龍", + "1f433": "鯨魚", + "1f42c": "海豚", + "1f9ad": "海豹", + "1f41f": "魚", + "1f420": "熱帶魚", + "1f988": "鯊魚", + "1f419": "章魚", + "1f41a": "海螺", + "1f40c": "蝸牛", + "1f98b": "蝴蝶", + "1f41b": "毛毛蟲", + "1f41d": "蜜蜂", + "1f41e": "瓢蟲", + "1f490": "花束", + "1f339": "玫瑰", + "1f33a": "芙蓉", + "1f33b": "向日葵", + "1f337": "鬱金香", + "1f332": "常青樹", + "1f333": "落葉樹", + "1f334": "棕櫚樹", + "1f335": "仙人掌", + "1f33f": "草藥", + "1f341": "楓葉", + "1f344": "蘑菇", + "1f347": "葡萄", + "1f348": "瓜", + "1f349": "西瓜", + "1f34a": "橘子", + "1f34b": "檸檬", + "1f34c": "香蕉", + "1f34d": "鳳梨", + "1f96d": "芒果", + "1f34f": "青蘋果", + "1f350": "梨子", + "1f351": "桃子", + "1f352": "櫻桃", + "1f353": "草莓", + "1fad0": "藍莓", + "1f95d": "奇異果", + "1f345": "番茄", + "1fad2": "橄欖", + "1f965": "椰子", + "1f951": "酪梨", + "1f346": "茄子", + "1f955": "胡蘿蔔", + "1f33d": "玉米", + "1f336": "辣椒", + "1f96c": "綠葉蔬菜", + "1f966": "花椰菜", + "1f9c5": "洋蔥", + "1f95c": "花生", + "1f950": "可頌", + "1f956": "法國麵包", + "1f968": "蝴蝶餅", + "1f96f": "貝果", + "1f95e": "鬆餅", + "1f9c7": "格子鬆餅", + "1f354": "漢堡", + "1f355": "披薩", + "1f32d": "熱狗", + "1f32e": "夾餅", + "1f37f": "爆米花", + "1f980": "螃蟹", + "1f99e": "龍蝦", + "1f368": "冰淇淋", + "1f369": "甜甜圈", + "1f36a": "餅乾", + "1f382": "生日蛋糕", + "1f9c1": "杯子蛋糕", + "1f36b": "巧克力", + "1f36c": "糖", + "1f36d": "棒棒糖", + "1fad6": "茶壺", + "1f9c3": "鋁箔包", + "1f9c9": "瑪黛茶", + "1f9ed": "指南針", + "1f3d4": "雪山", + "1f30b": "火山", + "1f3d5": "露營", + "1f3dd": "熱帶小島", + "1f3e1": "別墅", + "26f2": "噴泉", + "1f3a0": "旋轉木馬", + "1f3a1": "摩天輪", + "1f3a2": "雲霄飛車", + "1f488": "理髮店", + "1f686": "火車", + "1f68b": "電纜車", + "1f68d": "公共汽車", + "1f695": "計程車", + "1f697": "汽車", + "1f69a": "貨車", + "1f69c": "拖弋機", + "1f6f5": "摩托車", + "1f6fa": "嘟嘟車", + "1f6f4": "滑板車", + "1f6f9": "滑板", + "1f6fc": "輪式溜冰鞋", + "2693": "錨", + "26f5": "帆船", + "1f6f6": "獨木舟", + "1f6a4": "快艇", + "1f6a2": "船", + "2708": "飛機", + "1f681": "直升機", + "1f6a0": "纜車", + "1f6f0": "衛星", + "1f680": "火箭", + "1f6f8": "飛碟", + "23f0": "鬧鐘", + "1f319": "彎月", + "1f321": "溫度計", + "2600": "太陽", + "1fa90": "帶行星環的行星", + "1f31f": "閃爍的星星", + "1f300": "颱風", + "1f308": "彩虹", + "2602": "雨傘", + "2744": "雪花", + "2604": "慧星", + "1f525": "火", + "1f4a7": "水滴", + "1f30a": "波浪", + "1f383": "南瓜燈", + "2728": "閃爍", + "1f388": "氣球", + "1f389": "拉炮", + "1f38f": "鯉魚旗", + "1f380": "蝴蝶結", + "1f381": "禮物", + "1f39f": "入場券", + "1f3c6": "獎盃", + "26bd": "足球", + "1f3c0": "籃球", + "1f3c8": "美式足球", + "1f3be": "網球", + "1f94f": "飛盤", + "1f3d3": "桌球", + "1f3f8": "羽毛球", + "1f93f": "潛水面罩", + "1f94c": "冰石壺", + "1f3af": "命中", + "1fa80": "溜溜球", + "1fa81": "風箏", + "1f52e": "水晶球", + "1f3b2": "骰子", + "1f9e9": "拼圖", + "1f3a8": "調色板", + "1f9f5": "線", + "1f455": "T恤", + "1f9e6": "襪子", + "1f457": "洋裝", + "1fa73": "短泳褲", + "1f392": "書包", + "1f45f": "運動鞋", + "1f451": "皇冠", + "1f9e2": "鴨舌帽", + "1f484": "口紅", + "1f48d": "戒指", + "1f48e": "鑽石", + "1f4e2": "大聲公", + "1f3b6": "樂符", + "1f399": "錄音室麥克風", + "1f4fb": "收音機", + "1f3b7": "薩克斯風", + "1fa97": "手風琴", + "1f3b8": "吉他", + "1f3ba": "小號", + "1f3bb": "小提琴", + "1fa95": "斑鳩琴", + "1f941": "鼓", + "260e": "電話", + "1f50b": "電池", + "1f4bf": "光碟", + "1f9ee": "算盤", + "1f3ac": "場記板", + "1f4a1": "燈泡", + "1f526": "手電筒", + "1f3ee": "燈籠", + "1f4d5": "合起來的書本", + "1f3f7": "吊牌", + "1f4b3": "信用卡", + "270f": "鉛筆", + "1f58c": "畫筆", + "1f58d": "蠟筆", + "1f4cc": "圖釘", + "1f4ce": "迴紋針", + "1f511": "鑰匙", + "1fa83": "迴力鏢", + "1f3f9": "弓箭", + "2696": "天平", + "1f9f2": "磁鐵", + "1f9ea": "試管", + "1f9ec": "DNA", + "1f52c": "顯微鏡", + "1f52d": "望遠鏡", + "1f4e1": "衛星天線", + "1fa91": "椅子", + "1f9f9": "掃帚", + "1f5ff": "復活節島" + } +} diff --git a/browser/components/torpreferences/content/bridgemoji/bridge-emojis.json b/browser/components/torpreferences/content/bridgemoji/bridge-emojis.json new file mode 100644 index 0000000000000000000000000000000000000000..60cb98915557302ccbadb78e42803d8a6dc323ab --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/bridge-emojis.json @@ -0,0 +1,258 @@ +[ + "👽️", + "🤖", + "🧠", + "👁️", + "🧙", + "🧚", + "🧜", + "🐵", + "🦧", + "🐶", + "🐺", + "🦊", + "🦝", + "🐱", + "🦁", + "🐯", + "🐴", + "🦄", + "🦓", + "🦌", + "🐮", + "🐷", + "🐗", + "🐪", + "🦙", + "🦒", + "🐘", + "🦣", + "🦏", + "🐭", + "🐰", + "🐿️", + "🦔", + "🦇", + "🐻", + "🐨", + "🦥", + "🦦", + "🦘", + "🐥", + "🐦️", + "🕊️", + "🦆", + "🦉", + "🦤", + "🪶", + "🦩", + "🦚", + "🦜", + "🐊", + "🐢", + "🦎", + "🐍", + "🐲", + "🦕", + "🐳", + "🐬", + "🦭", + "🐟️", + "🐠", + "🦈", + "🐙", + "🐚", + "🐌", + "🦋", + "🐛", + "🐝", + "🐞", + "💐", + "🌹", + "🌺", + "🌻", + "🌷", + "🌲", + "🌳", + "🌴", + "🌵", + "🌿", + "🍁", + "🍇", + "🍈", + "🍉", + "🍊", + "🍋", + "🍌", + "🍍", + "🥭", + "🍏", + "🍐", + "🍑", + "🍒", + "🍓", + "🫐", + "🥝", + "🍅", + "🫒", + "🥥", + "🥑", + "🍆", + "🥕", + "🌽", + "🌶️", + "🥬", + "🥦", + "🧅", + "🍄", + "🥜", + "🥐", + "🥖", + "🥨", + "🥯", + "🥞", + "🧇", + "🍔", + "🍕", + "🌭", + "🌮", + "🍿", + "🦀", + "🦞", + "🍨", + "🍩", + "🍪", + "🎂", + "🧁", + "🍫", + "🍬", + "🍭", + "🫖", + "🧃", + "🧉", + "🧭", + "🏔️", + "🌋", + "🏕️", + "🏝️", + "🏡", + "⛲️", + "🎠", + "🎡", + "🎢", + "💈", + "🚆", + "🚋", + "🚍️", + "🚕", + "🚗", + "🚚", + "🚜", + "🛵", + "🛺", + "🛴", + "🛹", + "🛼", + "⚓️", + "⛵️", + "🛶", + "🚤", + "🚢", + "✈️", + "🚁", + "🚠", + "🛰️", + "🚀", + "🛸", + "⏰", + "🌙", + "🌡️", + "☀️", + "🪐", + "🌟", + "🌀", + "🌈", + "☂️", + "❄️", + "☄️", + "🔥", + "💧", + "🌊", + "🎃", + "✨", + "🎈", + "🎉", + "🎏", + "🎀", + "🎁", + "🎟️", + "🏆️", + "⚽️", + "🏀", + "🏈", + "🎾", + "🥏", + "🏓", + "🏸", + "🤿", + "🥌", + "🎯", + "🪀", + "🪁", + "🔮", + "🎲", + "🧩", + "🎨", + "🧵", + "👕", + "🧦", + "👗", + "🩳", + "🎒", + "👟", + "👑", + "🧢", + "💄", + "💍", + "💎", + "📢", + "🎶", + "🎙️", + "📻️", + "🎷", + "🪗", + "🎸", + "🎺", + "🎻", + "🪕", + "🥁", + "☎️", + "🔋", + "💿️", + "🧮", + "🎬️", + "💡", + "🔦", + "🏮", + "📕", + "🏷️", + "💳️", + "✏️", + "🖌️", + "🖍️", + "📌", + "📎", + "🔑", + "🪃", + "🏹", + "⚖️", + "🧲", + "🧪", + "🧬", + "🔬", + "🔭", + "📡", + "🪑", + "🧹", + "🗿" +] diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f300.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f300.svg new file mode 100644 index 0000000000000000000000000000000000000000..1de6f256cb52c215d656f959d83b9f85068f3232 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f300.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M35.782 24.518c-.13-.438-.422-.799-.821-1.016-.802-.436-1.879-.116-2.316.683-1.797 3.296-4.771 5.695-8.372 6.757-3.563 1.051-7.437.634-10.698-1.144-2.558-1.394-4.419-3.699-5.242-6.493-.74-2.514-.495-5.016.552-7.033-.363 1.605-.313 3.285.164 4.908.737 2.507 2.407 4.575 4.701 5.823 2.733 1.492 5.989 1.841 8.979.961 3.025-.892 5.521-2.906 7.026-5.672 1.832-3.358 2.246-7.228 1.165-10.898-1.08-3.669-3.524-6.698-6.883-8.529C19.984.657 15.165.14 10.738 1.446 6.261 2.764 2.566 5.746.332 9.843c-.451.826-.145 1.865.681 2.317.804.439 1.884.117 2.319-.682C5.127 8.183 8.1 5.784 11.703 4.723c3.563-1.048 7.438-.634 10.699 1.142 2.556 1.394 4.416 3.7 5.239 6.495.741 2.514.496 5.017-.552 7.033.363-1.604.315-3.285-.162-4.911-.739-2.504-2.409-4.573-4.702-5.824-2.734-1.49-5.99-1.838-8.98-.959-3.022.89-5.518 2.904-7.025 5.671-1.832 3.357-2.245 7.227-1.165 10.897 1.081 3.671 3.525 6.7 6.883 8.529 2.567 1.4 5.451 2.141 8.341 2.141 1.669 0 3.337-.242 4.958-.72 4.477-1.317 8.173-4.301 10.406-8.399.219-.399.269-.862.139-1.3zM16.784 14.002c.373-.11.758-.166 1.143-.166 1.779 0 3.372 1.193 3.875 2.901.629 2.138-.599 4.39-2.737 5.02-.373.11-.757.166-1.142.166-1.778 0-3.372-1.193-3.875-2.902-.63-2.137.598-4.389 2.736-5.019z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f308.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f308.svg new file mode 100644 index 0000000000000000000000000000000000000000..ffe6a12398cf02a09c0563de277a809310ed7e57 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f308.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8767AC" d="M36 1C16.118 1 1 16.118 1 36h17.042c0-9.917 8.042-17.958 17.958-17.958V1z"/><path fill="#EB2027" d="M0 35.999h3.042c0-18.189 14.734-32.935 32.917-32.957V0C16.095.023 0 16.131 0 35.999z"/><path fill="#F19020" d="M3.083 36h3C6.083 19.468 19.473 6.065 36 6.043v-3C17.817 3.065 3.083 17.811 3.083 36z"/><path fill="#FFCB4C" d="M6.083 36h3C9.083 21.125 21.13 9.065 36 9.043v-3C19.473 6.065 6.083 19.468 6.083 36z"/><path fill="#5C903F" d="M9.083 36h3c0-13.217 10.705-23.935 23.917-23.957v-3C21.13 9.065 9.083 21.125 9.083 36z"/><path fill="#226798" d="M12.083 36h3c0-11.56 9.362-20.934 20.917-20.956v-3.001C22.788 12.065 12.083 22.783 12.083 36z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f30a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f30a.svg new file mode 100644 index 0000000000000000000000000000000000000000..0e68ec3614f89f62b1b465d8c5fb4c501e136e8f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f30a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#269" d="M33.398 23.678c-7.562 4.875-20.062-.438-18.375-8.062 1.479-6.684 9.419-4.763 11.225-3.861 1.806.902.713-3.889-3.475-5.327C17.1 4.48 10.156 4.893 7.961 14.678c-1.5 6.687 1.438 16.062 12.719 16.187 11.281.125 12.718-7.187 12.718-7.187z"/><path fill="#55ACEE" d="M35.988 25.193c0-2.146-2.754-2.334-4-1.119-2.994 2.919-7.402 4.012-13.298 2.861-10.25-2-10.341-14.014-3.333-17.441 3.791-1.854 8.289.341 9.999 1.655 1.488 1.143 4.334 2.66 4.185.752C29.223 7.839 21.262-.86 10.595 4.64-.071 10.14 0 22.553 0 24.803v7.25C0 34.262 1.814 36 4.023 36h28C34.232 36 36 34.262 36 32.053c0 0-.004-6.854-.012-6.86z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f30b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f30b.svg new file mode 100644 index 0000000000000000000000000000000000000000..88d989d73c53d52f53003526da6e3e8d5a0ce846 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f30b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M12 36V16s-1.17 1.053-2.354 1.929c-.313.231-1.977.79-2.312 1.04-1.762 1.315-2.552 3.841-2.792 4.167C4.083 23.76 0 36 0 36h12z"/><path fill="#4B545D" d="M32 36l-5.5-17.75-8.5-5.656-6.458 2.208C11.135 15.583 10 18.25 10 18.25L8.75 22 0 36h32z"/><path fill="#292F33" d="M18.135 25.726c-.145-.513-.026-.97-.177-1.476-.148-.499-.566-1.047-.693-1.478-.265-.899-.454-1.583-.445-1.772.024-.469.894-.401 1.102.469.293 1.224.688 1.594.688 1.594s.084-3.381-.632-4.068c.145-.231.289-.476.418-.744.625-1.292.646-2.104.646-2.104S16.521 19.208 15.82 21c-.701 1.792 1 8 1 8l-4 7h4.467s-.474-1.469-.467-1.969c.007-.5 1.899-3.688 2-5.031.041-.545-.285-1.861-.685-3.274zm15.74.024c-.515-.586-1.841-1.42-3.128-2.154 0 0-2.335-5.596-3.622-7.263s-3.667-3-3.667-3l-2.646 1.479s1.705 1.446 2.646 3.062.689 3.519.745 3.908c.067.467.059.973.588 1.759 1.045 1.553 1.726 1.541 2.183 2.276.049.145.099.291.15.432.14.385.68.656.792 1.021.175.576.878 2.284.682 3.09-.106.437-.224 1.521-.307 2.014-.341 2.043.766 3.626.766 3.626H36s-1-8.969-2.125-10.25z"/><path fill="#FFAC33" d="M26.098 22.256c-.772-.754-1.187-1.898-1.229-3.294.173-1.667-4.662-4.923-4.662-4.923l-1.915.316s4.112 1.681 4.708 4.453c.297 1.381-.107 3.271-.208 4.11-.136 1.119.661 1.768.875 2.832.111.55.007 1.694-.14 2.878-.075.602-.348 1.175-.422 1.726-.192 1.424-.12 2.472.229 1.812.422-.796.653-1.922 1.263-3.606.293-.81.311-1.743.239-2.811-.031-.461.111-1.009.061-1.521-.051-.528-.294-1.02-.333-1.604-.011-.166.03-.738.092-1.444.074.012.146.054.216.172.938 1.562.764 3.025 1.276 2.581.41-.356.493-1.146-.05-1.677z"/><path fill="#292F33" d="M8.77 24.997s-4.437 3.087-5.603 4.545S0 36 0 36h4.5s.042-1.896-.156-2.688.312-2.455.906-2.875c1.417-1 2.381-2.31 2.52-2.149.521.604.521 1.208.521 1.208s.499-1.378.521-2.542-.042-1.957-.042-1.957z"/><path fill="#FFAC33" d="M18 12.594s-3.844-1.094-6.458 1.25C10.351 14.911 10.48 15.896 10 18.25s-1.861 3.086-2.062 4.021c-.396 1.833-1.852 3.23-2.417 4.104-.328.508-.758 1.336-1.038 1.802-.586.978-1.014 1.805-1.066 2.239-.125 1.042 1.833-1.208 1.833-1.208l3.281-4.035c-.107 2.301-.924 4.738-.031 4.514.75-.188 1.363-1.136 1.016-2.156-.454-1.336-.338-2.483-.094-3.456.05-.089 2.252-4.007 2.787-7.117.542-3.146 5.381-3.976 5.381-3.976l2.244.862.417-1.066L18 12.594z"/><path fill="#E95F28" d="M27.953 17c-1.328-1.75-3.286-3.685-4.234-3.988-.823-.263-.428.815-.428.815s2.833 1.236 4.271 6.736c.686 2.625 2.765 3.711 3.344 5.344 1.938 5.469 4.166 6.463 2.943 4.747S29.281 18.75 27.953 17zm-9.972 1.535c-.108-.166-.205-.306-.294-.437 1.259-1.904 2.751-4.035 2.751-4.035s-2.912-.294-3 .031c-.875 3.219-1.669 4.238-2.312 6.281-1.876 5.958 1.21 9.869 1.694 8.625.388-1-.211-3.746-.672-5.373s-.266-2.002-.169-2.669c.034-.233.594-1.153 1.303-2.244.089.071.172.163.243.29.446.8.653 2.26.753 3.251.115 1.139 1.134 1.653 1.696 1.25s-.188-2.422-1.41-3.726c-.289-.31-.392-.95-.583-1.244z"/><path fill="#E95F28" d="M23.969 13.125s.594 1.156-1.635 1.135c-.584-.005-.861.512-1.625.576-.636.053-1.509-.243-2.229-.243-.72 0-1.55.491-2.186.438-.766-.064-1.659-.834-2.231-.959-1.062-.232-1.792-.289-1.792-.646 0-.357 1.207-.789 2.271-1.021.571-.125 1.058.285 1.822.221.636-.053 1.291-.101 2.011-.101.72 0 1.415-.431 2.051-.377.766.064 1.403.432 1.979.535.683.123 1.088.244 1.314.329.185.069.25.113.25.113z"/><path fill="#FFAC33" d="M25.531 6.906s-3.455-1.365-6.764-1.365-7.392 1.886-7.392 1.886c3.25 2.764 3.119 5.697 3.119 5.697h7.688c0 .001 1.162-4.052 3.349-6.218z"/><path fill="#FFAC33" d="M22.182 13.125s-.056.21-.4.312c-.091.027-.307-.048-.453 0-.174.057-.486.201-.641.219-.166.02-.546-.094-.734-.078-.344.028-.519.159-.922.172-.273.008-.401-.098-.693-.098-.109 0-.341-.097-.525-.089-.303.012-.583.13-.75.125-.453-.014-.545-.216-.922-.25-.365-.032-.625.141-.891.094-.502-.089-.756-.406-.756-.406 0-.291 1.721-.527 3.844-.527s3.843.526 3.843.526z"/><path fill="#E95F28" d="M17.145 13.682s-.07-.575-.301-1.367c-.615-2.107-.594-3.628-.594-3.628l-1.396.667s.729 1.396 1.305 4.093c0 0 .2.005.429.129s.557.106.557.106zm1.698.063c.004-.228.01-.715.074-1.214.063-.492.321-1.677.417-2.26.163-.995.117-1.696.333-2.083l-2.229.083s.471.931.583 2.042c.088.866.001 2.239.195 3.327 0 0 .063.017.149.024.043.003.14.003.192.012.157.026.286.069.286.069zm2.212-.2s.462-1.455.62-2.446c.257-1.613 1.714-3.985 2.106-4.38l-2.828-.094s.069 2.111-.058 3.491c-.096 1.043-.598 1.991-.519 3.503 0 0 .134.05.311.037.155-.012.368-.111.368-.111z"/><path fill="#CCD6DD" d="M30.375 2.039c-.045 0-.088.01-.132.013-.193-.446-.635-.76-1.153-.76-.235 0-.443.082-.631.194-.448-.72-1.241-1.204-2.152-1.204-.814 0-1.531.39-1.996.985-.493-.336-1.088-.534-1.729-.534-1.154 0-2.148.644-2.674 1.585-.265-.612-.874-1.041-1.583-1.041-.55 0-1.035.263-1.351.664C16.584.815 15.525 0 14.266 0c-1.015 0-1.902.528-2.414 1.322-.141-.021-.283-.043-.43-.043-.802 0-1.526.33-2.048.859-.068-.005-.132-.02-.201-.02-.034 0-.066.009-.099.01-.308-.398-.783-.657-1.323-.657-.526 0-.99.247-1.297.626-.17-.05-.347-.084-.534-.084-1.06 0-1.92.86-1.92 1.921s.86 1.921 1.921 1.921c.055 0 .106-.012.16-.016.217.271.536.456.91.456.046 0 .085-.021.129-.026.473.62 1.212 1.026 2.051 1.026.19 0 .374-.023.552-.062.35.278.758.485 1.213.576.644 1.121 1.839 1.885 3.224 1.885 1.311 0 2.459-.679 3.125-1.701.552.677 1.382 1.118 2.323 1.118 1.392 0 2.552-.95 2.897-2.233.026.001.05.008.076.008.367 0 .714-.075 1.041-.193.516.403 1.157.653 1.863.653 1.062 0 1.995-.546 2.539-1.37.194.139.419.238.676.238.482 0 .893-.291 1.078-.704.188.067.387.11.597.11.988 0 1.789-.801 1.789-1.789s-.801-1.792-1.789-1.792z"/><circle fill="#AAB8C2" cx="14.25" cy="4.703" r="2.024"/><circle fill="#AAB8C2" cx="11.75" cy="4.537" r="2.001"/><circle fill="#AAB8C2" cx="9.784" cy="4.628" r="1.11"/><circle fill="#AAB8C2" cx="23.659" cy="3.669" r="1.11"/><circle fill="#AAB8C2" cx="26.208" cy="3.287" r="1.495"/><circle fill="#AAB8C2" cx="15.976" cy="4.263" r="1.632"/><circle fill="#AAB8C2" cx="25.555" cy="4.163" r="1.784"/><circle fill="#AAB8C2" cx="17.421" cy="4.841" r="1.532"/><circle fill="#AAB8C2" cx="14.203" cy="3.531" r="1.7"/><circle fill="#AAB8C2" cx="14.162" cy="5.274" r="2.86"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f319.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f319.svg new file mode 100644 index 0000000000000000000000000000000000000000..d98dc2f9f42ff601d50554564fe549ac1ee2f1f6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f319.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFD983" d="M30.312.776C32 19 20 32 .776 30.312c8.199 7.717 21.091 7.588 29.107-.429C37.9 21.867 38.03 8.975 30.312.776z"/><path d="M30.705 15.915c-.453.454-.453 1.189 0 1.644.454.453 1.189.453 1.643 0 .454-.455.455-1.19 0-1.644-.453-.454-1.189-.454-1.643 0zm-16.022 14.38c-.682.681-.682 1.783 0 2.465.68.682 1.784.682 2.464 0 .681-.682.681-1.784 0-2.465-.68-.682-1.784-.682-2.464 0zm13.968-2.147c-1.135 1.135-2.974 1.135-4.108 0-1.135-1.135-1.135-2.975 0-4.107 1.135-1.136 2.974-1.136 4.108 0 1.135 1.133 1.135 2.973 0 4.107z" fill="#FFCC4D"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f31f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f31f.svg new file mode 100644 index 0000000000000000000000000000000000000000..a4695dd6df575431e417aa6b58a89554aa055adc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f31f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M28.84 17.638c-.987 1.044-1.633 3.067-1.438 4.493l.892 6.441c.197 1.427-.701 2.087-1.996 1.469l-5.851-2.796c-1.295-.62-3.408-.611-4.7.018l-5.826 2.842c-1.291.629-2.193-.026-2.007-1.452l.843-6.449c.186-1.427-.475-3.444-1.47-4.481l-4.494-4.688c-.996-1.037-.655-2.102.755-2.365l6.37-1.188c1.41-.263 3.116-1.518 3.793-2.789L16.762.956c.675-1.271 1.789-1.274 2.473-.009L22.33 6.66c.686 1.265 2.4 2.507 3.814 2.758l6.378 1.141c1.412.252 1.761 1.314.774 2.359l-4.456 4.72z"/><path fill="#FFD983" d="M9.783 2.181c1.023 1.413 2.446 4.917 1.717 5.447-.728.531-3.607-1.91-4.63-3.323-1.022-1.413-.935-2.668-.131-3.254.804-.587 2.02-.282 3.044 1.13zm19.348 2.124C28.109 5.718 25.23 8.16 24.5 7.627c-.729-.53.695-4.033 1.719-5.445C27.242.768 28.457.463 29.262 1.051c.803.586.89 1.841-.131 3.254zM16.625 33.291c-.001-1.746.898-5.421 1.801-5.421.897 0 1.798 3.675 1.797 5.42 0 1.747-.804 2.712-1.8 2.71-.994.002-1.798-.962-1.798-2.709zm16.179-9.262c-1.655-.539-4.858-2.533-4.579-3.395.277-.858 4.037-.581 5.69-.041 1.655.54 2.321 1.605 2.013 2.556-.308.95-1.469 1.42-3.124.88zM2.083 20.594c1.655-.54 5.414-.817 5.694.044.276.857-2.928 2.854-4.581 3.392-1.654.54-2.818.07-3.123-.88-.308-.95.354-2.015 2.01-2.556z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f321.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f321.svg new file mode 100644 index 0000000000000000000000000000000000000000..95a75984e1ff237410e995fe28df4e3cda9532d1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f321.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M33.536 2.464c-1.953-1.953-5.118-1.953-7.071 0l-1.197 1.199 2.842 2.843c.391.391.391 1.024 0 1.414-.195.195-.451.293-.707.293s-.512-.098-.707-.293l-2.841-2.842-2.11 2.112 2.841 2.84c.391.39.391 1.023 0 1.414-.195.195-.451.293-.707.293s-.512-.098-.707-.293l-2.84-2.839-2.12 2.122 2.837 2.838c.391.391.391 1.024 0 1.414-.195.195-.451.293-.707.293s-.512-.098-.707-.293l-2.837-2.837-2.12 2.123 2.836 2.836c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293s-.512-.098-.707-.293l-2.835-2.835-2.12 2.123 2.833 2.833c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293s-.512-.098-.707-.293l-2.833-2.832-1.781 1.785C4.107 21.03 1 24.151 1 28c0 3.866 3.134 7 7 7 3.832 0 6.941-3.081 6.995-6.9L33.536 9.536c1.952-1.953 1.952-5.119 0-7.072z"/><path fill="#DD2E44" d="M30.938 5.091c-.781-.781-2.047-.781-2.828 0L9.045 24.156c-1.338-.362-2.823-.035-3.873 1.015-1.562 1.562-1.562 4.095 0 5.657 1.562 1.562 4.095 1.562 5.657 0C11.867 29.79 12.2 28.326 11.858 27l19.08-19.08c.781-.781.781-2.048 0-2.829z"/><path fill="#292F33" d="M13.272 22.343c.256 0 .512-.098.707-.293.391-.391.391-1.023 0-1.414l-2.833-2.833-1.413 1.415 2.833 2.832c.194.195.45.293.706.293zm3.536-3.535c.256 0 .512-.098.707-.293.391-.391.391-1.023 0-1.414l-2.836-2.836-1.413 1.415 2.835 2.835c.195.195.451.293.707.293zm3.535-3.536c.256 0 .512-.098.707-.293.391-.39.391-1.023 0-1.414l-2.837-2.838-1.413 1.415 2.837 2.837c.194.195.45.293.706.293zm3.536-3.536c.256 0 .512-.098.707-.293.391-.391.391-1.024 0-1.414l-2.841-2.84-1.413 1.415 2.84 2.839c.195.196.451.293.707.293zm3.523-3.523c.256 0 .512-.098.707-.293.391-.39.391-1.023 0-1.414l-2.842-2.843-1.413 1.415 2.841 2.842c.196.195.451.293.707.293z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f32d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f32d.svg new file mode 100644 index 0000000000000000000000000000000000000000..a450dbba085ece1bd34c88f3f92c98911aab130a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f32d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M31.42 31.471c-3.515 3.515-9.213 3.515-12.728 0L4.55 17.328c-3.515-3.515-3.515-9.213 0-12.728 3.515-3.515 9.213-3.515 12.728 0L31.42 18.743c3.515 3.514 3.515 9.213 0 12.728z"/><path fill="#F7BBA6" d="M29.335 20.9c3.515 3.515 4.609 8.119 2.475 10.253-2.135 2.134-6.739 1.039-10.253-2.475L7.414 14.536c-3.515-3.515-4.609-8.12-2.475-10.253 2.134-2.134 6.738-1.04 10.253 2.475L29.335 20.9z"/><path fill="#DD2E44" d="M33.167 28.974c1.415 1.415 1.611 3.51.44 4.682-1.172 1.171-3.267.975-4.682-.44L2.732 7.025c-1.414-1.414-1.61-3.51-.439-4.682 1.171-1.171 3.268-.975 4.682.439l26.192 26.192z"/><path fill="#FFCC4D" d="M32.127 31.764c-.256 0-.512-.098-.707-.293-.916-.916-1.598-1.07-2.462-1.266-.988-.224-2.109-.478-3.435-1.803s-1.578-2.446-1.802-3.435c-.195-.863-.35-1.546-1.266-2.462-.915-.915-1.597-1.069-2.46-1.264-.989-.224-2.11-.477-3.434-1.801-1.323-1.324-1.576-2.444-1.799-3.432-.194-.862-.348-1.543-1.262-2.458-.914-.914-1.595-1.067-2.457-1.262-.988-.223-2.108-.476-3.432-1.799-1.322-1.322-1.575-2.442-1.798-3.43-.195-.863-.348-1.544-1.263-2.458-.391-.39-.391-1.023 0-1.414s1.023-.391 1.414 0c1.324 1.323 1.577 2.443 1.8 3.432.195.862.348 1.543 1.263 2.458.914.914 1.595 1.067 2.457 1.262.988.223 2.108.476 3.432 1.799 1.324 1.324 1.576 2.444 1.799 3.432.194.862.348 1.543 1.262 2.458.916.916 1.597 1.07 2.46 1.264.988.224 2.109.477 3.434 1.801 1.325 1.325 1.578 2.446 1.802 3.435.195.863.35 1.546 1.266 2.462s1.599 1.07 2.462 1.266c.989.224 2.11.478 3.435 1.803.391.391.391 1.023 0 1.414-.197.193-.453.291-.709.291z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f32e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f32e.svg new file mode 100644 index 0000000000000000000000000000000000000000..5b08f1f7d1997be13de64d7afb1cf337da57b78a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f32e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFE8B6" d="M12 7C5.374 7 0 14.164 0 23h6v6h17.119c.564-1.854.881-3.877.881-6 0-8.836-5.373-16-12-16z"/><path fill="#FFE8B6" d="M29 21h4.896C33.156 13.11 28.118 7 22 7c-6.627 0-12 7.164-12 16 0 2.123.317 4.146.88 6H29v-8z"/><path fill="#FFAC33" d="M36 23c0-8.836-5.373-16-12-16-6.626 0-12 7.164-12 16 0 2.123.317 4.146.88 6H30c3.314 0 6-2.685 6-6z"/><path fill="#FFAC33" d="M6 23h10v6H6z"/><path fill="#FFE8B6" d="M0 23c0-3.312 2.687-6 6-6s6 2.687 6 6c0 3.315-2.687 6-6 6s-6-2.685-6-6z"/><path fill="#FFAC33" d="M14 7C7.374 7 2 14.164 2 23c0 2.21 1.791 4 4 4s4-1.79 4-4c0-6.963 3.342-12.871 8-15.069C16.747 7.339 15.405 7 14 7z"/><circle fill="#D99E82" cx="4" cy="23" r="1"/><path fill="#C1694F" d="M9.975 23.25C9.855 22.541 9.243 22 8.5 22c-.18 0-.35.037-.51.095.002-.033.01-.063.01-.095 0-1.104-.896-2-2-2s-2 .896-2 2c0 .525.207 1 .539 1.357-.327.276-.539.682-.539 1.143 0 .678.453 1.244 1.07 1.43.167.557.651.962 1.241 1.039 1.978-.156 3.54-1.733 3.664-3.719z"/><path fill="#D99E82" d="M9.5 21c-.828 0-1.5.672-1.5 1.5S8.672 24 9.5 24c.13 0 .254-.021.375-.053.075-.305.125-.619.125-.947 0-.637.037-1.261.091-1.878C9.91 21.044 9.711 21 9.5 21z"/><ellipse fill="#FFCC4D" cx="6.5" cy="20" rx="1.5" ry="1"/><circle fill="#FFCC4D" cx="7" cy="21" r="1"/><circle fill="#C1694F" cx="9" cy="21" r="1"/><circle fill="#D99E82" cx="5" cy="22" r="1"/><circle fill="#D99E82" cx="7" cy="22" r="1"/><circle fill="#FFD983" cx="8" cy="20" r="1"/><circle fill="#FFE8B6" cx="7" cy="18" r="1"/><circle fill="#FFE8B6" cx="6" cy="20" r="1"/><circle fill="#FFD983" cx="9" cy="18" r="1"/><circle fill="#FFD983" cx="9" cy="20" r="1"/><circle fill="#FFD983" cx="9" cy="19" r="1"/><circle fill="#FFE8B6" cx="9" cy="19" r="1"/><path fill="#77B255" d="M10.572 12.453C10.3 12.174 9.921 12 9.5 12c-.738 0-1.348.533-1.473 1.235-.215-.139-.478-.235-.777-.235-.69 0-1.25.448-1.25 1 0 .19.084.358.2.51-.123.146-.2.311-.2.49-.552 0-1 .448-1 1 0 .202.075.379.178.537-.11.139-.178.295-.178.463 0 .552.671 1 1.5 1 .43 0 .815-.122 1.089-.316.254.195.567.316.911.316.198 0 .385-.041.558-.11.163.602.69 1.042 1.331 1.091.495-2.544 1.45-4.835 2.738-6.72C12.806 12.097 12.419 12 12 12c-.56 0-1.065.174-1.428.453z"/><circle fill="#A6D388" cx="8" cy="15" r="1"/><path fill="#A6D388" d="M10 13.5c0 .276-.224.5-.5.5s-.5-.223-.5-.5c0-.276.224-.5.5-.5s.5.224.5.5z"/><circle fill="#A6D388" cx="6.5" cy="16.5" r=".5"/><path fill="#A6D388" d="M10 16.5c0 .276-.224.5-.5.5s-.5-.223-.5-.5.224-.5.5-.5.5.224.5.5z"/><circle fill="#A6D388" cx="10" cy="15" r="1"/><circle fill="#DD2E44" cx="9" cy="12" r="1"/><circle fill="#FFD983" cx="11" cy="12" r="1"/><circle fill="#FFD983" cx="12" cy="10" r="1"/><circle fill="#FFD983" cx="9" cy="14" r="1"/><path fill="#A6D388" d="M15 9c-.552 0-1 .448-1 1 0 .035.016.064.02.098-.162-.06-.336-.098-.52-.098-.829 0-1.5.671-1.5 1.5 0 .561.311 1.043.767 1.301.845-1.354 1.856-2.513 2.989-3.436C15.573 9.147 15.308 9 15 9z"/><circle fill="#DD2E44" cx="12" cy="11" r="1"/><ellipse transform="rotate(-80.781 14 9)" fill="#DD2E44" cx="14" cy="9" rx="1" ry="1"/><circle fill="#F4900C" cx="17" cy="25" r="1"/><circle fill="#F4900C" cx="13" cy="28" r="1"/><circle fill="#F4900C" cx="19" cy="28" r="1"/><circle fill="#F4900C" cx="22" cy="27" r="1"/><circle fill="#F4900C" cx="26" cy="27" r="1"/><circle fill="#F4900C" cx="29" cy="28" r="1"/><circle fill="#F4900C" cx="31" cy="26" r="1"/><circle fill="#F4900C" cx="21" cy="22" r="1"/><circle fill="#F4900C" cx="15" cy="22" r="1"/><circle fill="#F4900C" cx="34" cy="24" r="1"/><circle fill="#F4900C" cx="17" cy="18" r="1"/><circle fill="#F4900C" cx="22" cy="16" r="1"/><path fill="#F4900C" d="M20 12c0 .552-.447 1-1 1-.552 0-1-.448-1-1s.448-1 1-1c.553 0 1 .448 1 1z"/><circle fill="#F4900C" cx="27" cy="13" r="1"/><circle fill="#F4900C" cx="24" cy="10" r="1"/><circle fill="#F4900C" cx="31" cy="19" r="1"/><circle fill="#F4900C" cx="26" cy="19" r="1"/><circle fill="#F4900C" cx="24" cy="23" r="1"/><circle fill="#F4900C" cx="29" cy="22" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f332.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f332.svg new file mode 100644 index 0000000000000000000000000000000000000000..540f1860cc166445f52c06ecb4262b6bf16804af --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f332.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M22 33c0 2.209-1.791 3-4 3s-4-.791-4-3l1-9c0-2.209.791-2 3-2s3-.209 3 2l1 9z"/><path fill="#5C913B" d="M31.406 27.297C24.443 21.332 21.623 12.791 18 12.791c-3.623 0-6.443 8.541-13.405 14.506-2.926 2.507-1.532 3.957 2.479 3.667 3.576-.258 6.919-1.069 10.926-1.069s7.352.812 10.926 1.069c4.012.29 5.405-1.16 2.48-3.667z"/><path fill="#3E721D" d="M29.145 24.934C23.794 20.027 20.787 13 18 13c-2.785 0-5.793 7.027-11.144 11.934-4.252 3.898 5.572 4.773 11.144 0 5.569 4.773 15.396 3.898 11.145 0z"/><path fill="#5C913B" d="M29.145 20.959C23.794 16.375 20.787 9.811 18 9.811c-2.785 0-5.793 6.564-11.144 11.148-4.252 3.642 5.572 4.459 11.144 0 5.569 4.459 15.396 3.642 11.145 0z"/><path fill="#3E721D" d="M26.7 17.703C22.523 14.125 20.176 9 18 9c-2.174 0-4.523 5.125-8.7 8.703-3.319 2.844 4.35 3.482 8.7 0 4.349 3.482 12.02 2.844 8.7 0z"/><path fill="#5C913B" d="M26.7 14.726c-4.177-3.579-6.524-8.703-8.7-8.703-2.174 0-4.523 5.125-8.7 8.703-3.319 2.844 4.35 3.481 8.7 0 4.349 3.481 12.02 2.843 8.7 0z"/><path fill="#3E721D" d="M25.021 12.081C21.65 9.193 19.756 5.057 18 5.057c-1.755 0-3.65 4.136-7.021 7.024-2.679 2.295 3.511 2.809 7.021 0 3.51 2.81 9.701 2.295 7.021 0z"/><path fill="#5C913B" d="M25.021 9.839C21.65 6.951 19.756 2.815 18 2.815c-1.755 0-3.65 4.136-7.021 7.024-2.679 2.295 3.511 2.809 7.021 0 3.51 2.81 9.701 2.295 7.021 0z"/><path fill="#3E721D" d="M23.343 6.54C20.778 4.342 19.336 1.195 18 1.195c-1.335 0-2.778 3.148-5.343 5.345-2.038 1.747 2.671 2.138 5.343 0 2.671 2.138 7.382 1.746 5.343 0z"/><path fill="#5C913B" d="M23.343 5.345C20.778 3.148 19.336 0 18 0c-1.335 0-2.778 3.148-5.343 5.345-2.038 1.747 2.671 2.138 5.343 0 2.671 2.138 7.382 1.746 5.343 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f333.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f333.svg new file mode 100644 index 0000000000000000000000000000000000000000..3937fc499f8b528bb6e90462e22054cc118eaceb --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f333.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M22 33c0 2.209-1.791 3-4 3s-4-.791-4-3l1-9c0-2.209.791-2 3-2s3-.209 3 2l1 9z"/><path fill="#5C913B" d="M34 17c0 8.837-7.163 12-16 12-8.836 0-16-3.163-16-12C2 8.164 11 0 18 0s16 8.164 16 17z"/><g fill="#3E721D"><ellipse cx="6" cy="21" rx="2" ry="1"/><ellipse cx="30" cy="21" rx="2" ry="1"/><ellipse cx="10" cy="25" rx="2" ry="1"/><ellipse cx="14" cy="22" rx="2" ry="1"/><ellipse cx="10" cy="16" rx="2" ry="1"/><ellipse cx="7" cy="12" rx="2" ry="1"/><ellipse cx="29" cy="12" rx="2" ry="1"/><ellipse cx="14" cy="10" rx="2" ry="1"/><ellipse cx="22" cy="10" rx="2" ry="1"/><ellipse cx="26" cy="16" rx="2" ry="1"/><ellipse cx="18" cy="17" rx="2" ry="1"/><ellipse cx="22" cy="22" rx="2" ry="1"/><ellipse cx="18" cy="26" rx="2" ry="1"/><ellipse cx="26" cy="25" rx="2" ry="1"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f334.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f334.svg new file mode 100644 index 0000000000000000000000000000000000000000..55d246a2fe7a056d5114d90a838796bdf1cbba04 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f334.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M21.978 20.424c-.054-.804-.137-1.582-.247-2.325-.133-.89-.299-1.728-.485-2.513-.171-.723-.356-1.397-.548-2.017-.288-.931-.584-1.738-.852-2.4-.527-1.299-.943-2.043-.943-2.043l-3.613.466s.417.87.868 2.575c.183.692.371 1.524.54 2.495.086.49.166 1.012.238 1.573.1.781.183 1.632.242 2.549.034.518.058 1.058.074 1.619.006.204.015.401.018.611.01.656-.036 1.323-.118 1.989-.074.6-.182 1.197-.311 1.789-.185.848-.413 1.681-.67 2.475-.208.643-.431 1.261-.655 1.84-.344.891-.69 1.692-.989 2.359-.502 1.119-.871 1.863-.871 2.018 0 .49.35 1.408 2.797 2.02 3.827.956 4.196-.621 4.196-.621s.243-.738.526-2.192c.14-.718.289-1.605.424-2.678.081-.642.156-1.348.222-2.116.068-.8.125-1.667.165-2.605.03-.71.047-1.47.055-2.259.002-.246.008-.484.008-.737 0-.64-.03-1.261-.071-1.872z"/><path fill="#D99E82" d="M18.306 30.068c-1.403-.244-2.298-.653-2.789-.959-.344.891-.69 1.692-.989 2.359.916.499 2.079.895 3.341 1.114.729.127 1.452.191 2.131.191.414 0 .803-.033 1.176-.08.14-.718.289-1.605.424-2.678-.444.157-1.548.357-3.294.053zm1.06-4.673c-1.093-.108-1.934-.348-2.525-.602-.185.848-.413 1.681-.67 2.475.864.326 1.881.561 2.945.666.429.042.855.064 1.27.064.502 0 .978-.039 1.435-.099.068-.8.125-1.667.165-2.605-.628.135-1.509.21-2.62.101zm.309-2.133c.822 0 1.63-.083 2.366-.228.002-.246.008-.484.008-.737 0-.641-.029-1.262-.071-1.873-.529.138-1.285.272-2.352.286-1.084-.005-1.847-.155-2.374-.306.006.204.015.401.018.611.01.656-.036 1.323-.118 1.989.763.161 1.605.253 2.461.257l.062.001zm-.249-4.577c.825-.119 1.59-.333 2.304-.585-.133-.89-.299-1.728-.485-2.513-.496.204-1.199.431-2.181.572-.91.132-1.605.124-2.129.077.1.781.183 1.632.242 2.549.152.006.29.029.446.029.588.001 1.2-.043 1.803-.129zm1.271-5.116c-.288-.931-.584-1.738-.852-2.4-.443.222-1.004.456-1.737.659-.795.221-1.437.309-1.951.339.183.692.371 1.524.54 2.495.681-.068 1.383-.179 2.094-.376.679-.188 1.31-.44 1.906-.717z"/><path fill="#3E721D" d="M32.61 4.305c-.044-.061-4.48-5.994-10.234-3.39-2.581 1.167-4.247 3.074-4.851 5.535-1.125-1.568-2.835-2.565-5.093-2.968C6.233 2.376 2.507 9.25 2.47 9.32c-.054.102-.031.229.056.305s.217.081.311.015c.028-.02 2.846-1.993 7.543-1.157 4.801.854 8.167 1.694 8.201 1.702.02.005.041.007.061.007.069 0 .136-.028.184-.08.032-.035 3.22-3.46 6.153-4.787 4.339-1.961 7.298-.659 7.326-.646.104.046.227.018.298-.07.072-.087.075-.213.007-.304z"/><path fill="#5C913B" d="M27.884 7.63c-4.405-2.328-7.849-1.193-9.995.22-2.575-.487-7.334-.459-11.364 4.707-4.983 6.387-.618 14.342-.573 14.422.067.119.193.191.327.191.015 0 .031-.001.046-.003.151-.019.276-.127.316-.274.015-.054 1.527-5.52 5.35-10.118 2.074-2.496 4.55-4.806 6.308-6.34 1.762.298 4.327.947 6.846 2.354 4.958 2.773 7.234 7.466 7.257 7.513.068.144.211.226.379.212.158-.018.289-.133.325-.287.02-.088 1.968-8.8-5.222-12.597z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f335.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f335.svg new file mode 100644 index 0000000000000000000000000000000000000000..097dc13c440eb6229d1b862849e97a94462e9ad5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f335.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M30 4c-2.209 0-4 1.791-4 4v9.125c0 1.086-.887 1.96-2 2.448V6c0-3.313-2.687-6-6-6s-6 2.687-6 6v17.629c-1.122-.475-2-1.371-2-2.504V16c0-2.209-1.791-4-4-4s-4 1.791-4 4v7c0 2.209 1.75 3.875 3.375 4.812 1.244.718 4.731 1.6 6.625 1.651V33c0 3.313 12 3.313 12 0v-7.549c1.981-.119 5.291-.953 6.479-1.639C32.104 22.875 34 21.209 34 19V8c0-2.209-1.791-4-4-4z"/><g fill="#3E721D"><circle cx="12" cy="6" r="1"/><circle cx="23" cy="3" r="1"/><circle cx="21" cy="9" r="1"/><circle cx="14" cy="16" r="1"/><circle cx="20" cy="20" r="1"/><circle cx="13" cy="26" r="1"/><circle cx="5" cy="27" r="1"/><circle cx="9" cy="20" r="1"/><circle cx="2" cy="18" r="1"/><circle cx="34" cy="8" r="1"/><circle cx="28" cy="11" r="1"/><circle cx="32" cy="16" r="1"/><circle cx="29" cy="24" r="1"/><circle cx="22" cy="30" r="1"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f336.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f336.svg new file mode 100644 index 0000000000000000000000000000000000000000..eaeef864dc485c548b8aad7cbf6a30d148523c08 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f336.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DA2F47" d="M4.042 27.916c4.89.551 9.458-1.625 13.471-5.946 4.812-5.182 5-13 5-14s11.31-3.056 11 5c-.43 11.196-7.43 20.946-19.917 21.916-5.982.465-9.679-.928-11.387-2.345-2.69-2.231-.751-4.916 1.833-4.625z"/><path fill="#77B255" d="M30.545 6.246c.204-1.644.079-3.754-.747-4.853-1.111-1.479-4.431-.765-3.569.113.96.979 2.455 2.254 2.401 4.151-.044-.01-.085-.022-.13-.032-3.856-.869-6.721 1.405-7.167 2.958-.782 2.722 4.065.568 4.68 1.762 1.82 3.53 3.903.155 4.403 1.28s4.097 4.303 4.097.636c0-3.01-1.192-4.903-3.968-6.015z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f337.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f337.svg new file mode 100644 index 0000000000000000000000000000000000000000..86a1a36f99dba9e3dc1a3fe96f5589d8e01d0a79 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f337.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M34.751 22c-3.382 0-11.9 3.549-15.751 7.158V17c0-.553-.447-1-1-1-.552 0-1 .447-1 1v12.341C13.247 25.669 4.491 22 1.052 22 .123 22 11.913 35.992 17 34.599V35c0 .553.448 1 1 1 .553 0 1-.447 1-1v-.356C24.188 35.638 35.668 22 34.751 22z"/><path fill="#EA596E" d="M25 13.417C25 19.768 23.293 23 18 23s-7-3.232-7-9.583S16 0 18 0s7 7.066 7 13.417z"/><path fill="#F4ABBA" d="M22.795 2c-.48 0-4.106 14.271-4.803 19.279C17.246 16.271 13.481 2 13 2c-1 0-6 9-6 13s5.707 8 11 8 10.795-4 10.795-8-5-13-6-13z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f339.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f339.svg new file mode 100644 index 0000000000000000000000000000000000000000..500d9257cece8e373226c1b2aab032f492681c6b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f339.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M19.32 25.358c-.113 0-.217.003-.32.005v-.415c4.805-.479 8.548-4.264 8.548-7.301 0-3.249 0 1.47-9.562 1.47-9.558 0-9.558-4.719-9.558-1.47 0 3.043 3.757 6.838 8.572 7.305v.411c-.104-.002-.207-.005-.321-.005-2.553 0-6.603-2.05-6.603-1.32 0 .646 4.187 4.017 6.924 4.796V35c0 .553.447 1 1 1s1-.447 1-1v-6.166c2.738-.779 6.924-4.15 6.924-4.796 0-.729-4.05 1.32-6.604 1.32z"/><path fill="#A0041E" d="M26.527 7.353c-3.887-4.412 1.506-5.882-2.592-5.882-.713 0-1.921.44-3.29 1.189C19.951 1.088 19.023 0 18 0c-2.05 0-3.726 4.342-3.873 8.269-1.108 1.543-1.855 3.235-1.855 4.966 0 6.092 2.591 8.823 6.479 8.823 7.776.001 13.644-8.047 7.776-14.705z"/><path fill="#BE1931" d="M23.728 13.235c0 6.092-2.59 8.823-6.48 8.823-7.776 0-13.643-8.048-7.776-14.706C13.361 2.94 7.967 1.47 12.064 1.47c2.593.001 11.664 5.674 11.664 11.765z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f33a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f33a.svg new file mode 100644 index 0000000000000000000000000000000000000000..19c2f896020e15c08380b9392c6fea438f6064e2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f33a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M19.602 32.329c6.509 6.506 17.254-7.669 15.72-7.669-7.669 0-22.227 1.161-15.72 7.669z"/><path fill="#77B255" d="M15.644 33.372C9.612 39.404-.07 26.263 1.352 26.263c3.81 0 9.374-.348 12.79.867 2.958 1.052 4.304 3.442 1.502 6.242z"/><path fill="#F4ABBA" d="M34.613 15.754c-.052-.901-.175-2.585-1.398-4.227-1.16-1.549-3.805-3.371-5.534-2.585.516-1.676-.264-4.125-1.191-5.49-1.179-1.736-4.262-3.843-8.146-3.026-1.754.369-4.18 2.036-4.632 3.864-1.18-1.471-4.22-1.675-6.015-1.222-2.026.511-3.154 1.777-3.739 2.461l.003-.005-.03.034-.027.033c-.583.689-1.656 1.994-1.847 4.074-.193 2.146.75 5.832 3.026 6.042.149.014.324.031.514.051-2.271.098-3.572 3.654-3.595 5.8-.022 2.102.926 3.506 1.443 4.243l-.003-.004c.008.01.019.024.025.036.007.011.02.023.026.036.523.733 1.525 2.094 3.515 2.776 1.958.669 5.553.656 6.567-1.236-.273 2.244 3.027 4.077 5.169 4.438 2.115.358 3.71-.358 4.55-.753l-.005.003c.013-.008.028-.015.041-.021l.041-.02c.838-.4 2.398-1.178 3.462-3.04.729-1.282 1.27-3.403.951-5.015l.192.127c1.826 1.224 4.63-1.119 5.705-2.938 1.044-1.761.932-4.424.932-4.436z"/><path fill="#EA596E" d="M27.542 13.542c-1.786-.997-4.874-.434-6.792.308-.266-.468-.621-.875-1.051-1.196 1.393-1.607 3.526-4.593 1.468-6.362-2.191-1.883-3.74 2.154-3.575 5.605-.068-.003-.132-.02-.201-.02-1.019 0-1.94.402-2.632 1.045-1.401-2.277-3.942-4.244-5.314-2.392-1.482 2.002 1.148 3.153 4.222 4.2-.09.329-.154.668-.154 1.025 0 .456.093.887.238 1.293-2.541.732-6.236 2.718-4.21 4.91 2.122 2.296 4.472-1.238 5.604-3.053.635.454 1.407.727 2.247.727.225 0 .441-.029.655-.066-.109 4.802 1.443 7.07 4.036 5.892 2.295-1.043-.137-5.299-1.781-7.165.316-.362.564-.779.729-1.241 7.008 2.544 8.589-2.351 6.511-3.51z"/><path fill="#BE1931" d="M17.707 17.459c-.679 0-.668-.562-.832-1.25-.532-2.233-2.381-6.308-4.601-9.163-.509-.654-.391-1.596.263-2.105.654-.508 1.596-.391 2.105.263 2.439 3.136 3.264 7.404 3.982 10.421.191.806.237 1.601-.569 1.792-.116.028-.233.042-.348.042z"/><path fill="#FFCC4D" d="M15.904 5.327c.498.684.079 1.838-.936 2.578l-.475.347c-1.016.739-2.243.785-2.741.101l-2.78-3.817c-.498-.684-.079-1.838.936-2.577l.475-.347c1.015-.739 2.242-.785 2.74-.101l2.781 3.816z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f33b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f33b.svg new file mode 100644 index 0000000000000000000000000000000000000000..413e6fcbf87b634a9fb7d2c16497adcd78320181 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f33b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M28 27c-8 0-8 6-8 6V22h-4v11s0-6-8-6c-4 0-7-2-7-2s0 9 9 9h6s0 2 2 2 2-2 2-2h6c9 0 9-9 9-9s-3 2-7 2z"/><path fill="#FFAC33" d="M21.125 27.662c-.328 0-.651-.097-.927-.283l-2.323-1.575-2.322 1.575c-.277.186-.601.283-.929.283-.143 0-.287-.018-.429-.057-.462-.123-.851-.441-1.06-.874l-1.225-2.527-2.797.204c-.04.002-.079.004-.119.004-.438 0-.86-.174-1.17-.484-.34-.342-.516-.81-.481-1.288l.201-2.8-2.523-1.225c-.432-.209-.751-.598-.876-1.062-.125-.464-.042-.958.228-1.356l1.573-2.323-1.573-2.322c-.27-.398-.353-.892-.228-1.357.125-.462.444-.851.876-1.06L7.544 7.91l-.201-2.797c-.034-.48.142-.951.481-1.289.31-.312.732-.485 1.17-.485.04 0 .079 0 .119.003l2.797.201 1.225-2.523c.209-.432.598-.751 1.06-.876.142-.038.285-.057.429-.057.328 0 .651.098.929.285l2.322 1.573L20.198.372c.275-.188.599-.285.927-.285.144 0 .29.02.428.057.465.125.854.444 1.062.876l1.225 2.523 2.8-.201c.037-.003.078-.003.116-.003.438 0 .858.173 1.172.485.338.338.515.809.48 1.289l-.204 2.797 2.527 1.225c.433.209.751.598.874 1.06.124.465.043.96-.227 1.357l-1.575 2.322 1.575 2.323c.269.398.351.892.227 1.356-.123.464-.441.852-.874 1.062l-2.527 1.225.204 2.8c.034.478-.143.946-.48 1.288-.313.311-.734.484-1.172.484-.038 0-.079-.002-.116-.004l-2.8-.204-1.225 2.527c-.209.433-.598.751-1.062.874-.139.04-.284.057-.428.057z"/><circle fill="#732700" cx="18" cy="14" r="7"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f33d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f33d.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c4ae3bf53b02b897eeedb2af02f65dce6379bda --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f33d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M15.373 1.022C13.71 2.686 8.718 9.34 11.214 15.164c2.495 5.823 5.909 2.239 7.486-2.495.832-2.496.832-5.824-.831-10.815-.832-2.496-2.496-.832-2.496-.832zm19.304 19.304c-1.663 1.663-8.319 6.655-14.142 4.159-5.824-2.496-2.241-5.909 2.495-7.486 2.497-.832 5.823-.833 10.814.832 2.496.831.833 2.495.833 2.495z"/><path fill="#F4900C" d="M32.314 6.317s-.145-1.727-.781-2.253c-.435-.546-2.018-.546-2.018-.546-1.664 0-20.798 2.496-24.125 19.133-.595 2.973 4.627 8.241 7.638 7.638C29.667 26.963 32.313 7.98 32.314 6.317z"/><path d="M24.769 8.816l-1.617-1.617c-.446-.446-1.172-.446-1.618 0-.446.447-.446 1.171 0 1.617l1.618 1.618c.445.446 1.171.446 1.617 0 .446-.446.446-1.17 0-1.618zm-9.705 1.619c.446.446 1.171.446 1.617 0 .447-.447.447-1.171 0-1.618l-.77-.77c-.654.398-1.302.829-1.938 1.297l1.091 1.091zm2.426-2.427c.447.447 1.17.447 1.617 0 .446-.446.446-1.17 0-1.617l-.025-.025c-.711.325-1.431.688-2.149 1.086l.557.556zm-4.853 4.853c.447.446 1.171.446 1.619 0 .446-.447.446-1.171 0-1.618l-1.198-1.196c-.586.474-1.156.985-1.707 1.528l1.286 1.286zM23.96 4.773c-.447.447-.447 1.17 0 1.617l1.617 1.617c.447.447 1.171.447 1.617 0 .446-.446.446-1.17 0-1.617l-1.617-1.617c-.447-.446-1.17-.446-1.617 0zm2.408-.796c.006.007.008.016.015.023L28 5.617c.447.447 1.171.447 1.617 0 .446-.446.446-1.17 0-1.617l-.462-.462c-.54.044-1.516.172-2.787.439zm-4.025 8.884c.446-.447.446-1.171 0-1.618l-1.618-1.617c-.446-.447-1.171-.447-1.617 0-.447.446-.447 1.17 0 1.617l1.617 1.618c.446.446 1.171.446 1.618 0zm-2.428 2.426c.447-.447.447-1.171 0-1.618l-1.617-1.617c-.446-.447-1.17-.447-1.617 0-.446.447-.446 1.171 0 1.617l1.617 1.618c.447.446 1.172.446 1.617 0zm-4.851 4.852c.447-.447.446-1.17 0-1.618l-1.618-1.617c-.446-.446-1.169-.447-1.617 0-.446.447-.446 1.171 0 1.617l1.617 1.618c.447.446 1.171.446 1.618 0zm-.808-5.661c-.447.446-.447 1.171 0 1.618l1.617 1.617c.447.446 1.17.446 1.618 0 .447-.447.447-1.171 0-1.617l-1.618-1.618c-.447-.447-1.171-.447-1.617 0z" fill="#F7B82D"/><path fill="#77B255" d="M27.866 23.574c-7.125-2.374-15.097.652-19.418 3.576 2.925-4.321 5.95-12.294 3.576-19.418-.934-2.8-5.602-5.601-8.402-2.801-.934.934-1.867 1.868 0 1.868s4.667 2.8 3.735 5.601c-.835 2.505-6.889 8.742-4.153 15.375-.27.115-.523.279-.744.499l-.715.714c-.919.919-.919 2.409 0 3.329l.716.716c.919.92 2.409.92 3.328 0l.715-.716c.123-.123.227-.258.316-.398 6.999 3.84 13.747-2.799 16.379-3.677 2.8-.933 5.6 1.868 5.6 3.734 0 1.867.934.934 1.867 0 2.801-2.8-.001-7.47-2.8-8.402z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f33f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f33f.svg new file mode 100644 index 0000000000000000000000000000000000000000..9243e96857bf60c42eb9edfa36c28636b650fe94 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f33f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M20.917 22.502c-2.706-.331-3.895-1.852-6.273-4.889 3.039-2.376 4.559-3.565 7.266-3.235 2.71.332 5.25 2.016 6.273 4.889-1.683 2.543-4.557 3.563-7.266 3.235zm-5.959 8.814c-2.549-.187-3.733-1.553-6.098-4.288 2.735-2.364 4.102-3.547 6.652-3.364 2.551.185 5.009 1.644 6.098 4.287-1.459 2.458-4.1 3.548-6.652 3.365zm-6.22-15.707c1.338 1.631 1.191 3.117.898 6.088-2.97-.294-4.456-.44-5.795-2.071-1.339-1.634-1.861-3.935-.898-6.088 2.301-.524 4.456.439 5.795 2.071zm21.116-5.448c-2.435 1.02-4.16.314-7.613-1.097 1.411-3.453 2.118-5.18 4.549-6.203 2.434-1.021 5.378-.826 7.612 1.096-.194 2.944-2.117 5.181-4.548 6.204zM17.103 6.608c.874 2.869-.124 4.742-2.119 8.488-3.745-1.996-5.619-2.994-6.494-5.864-.876-2.872-.315-6.18 2.118-8.49 3.308.561 5.619 2.993 6.495 5.866z"/><path fill="#A6D388" d="M8.49 9.232c.862 2.828 2.702 3.843 6.338 5.781v-.005c-.07-2.521-2.733-10.876-4.267-14.214C8.172 3.102 7.62 6.381 8.49 9.232zm-5.592 4.429c-.89 2.118-.371 4.362.943 5.965 1.34 1.632 2.826 1.777 5.795 2.071-.997-1.937-4.911-6.388-6.738-8.036z"/><path fill="#5C913B" d="M21.91 14.378c-2.563-.312-4.077.75-6.808 2.879 1.746.105 8.786.745 13.06 2.037.006-.01.015-.017.021-.027-1.023-2.873-3.563-4.557-6.273-4.889zm-.304 13.565c-1.091-2.637-3.545-4.094-6.094-4.279-2.5-.179-3.87.961-6.498 3.232 2.767-.305 7.905-.87 12.592 1.047z"/><path fill="#A6D388" d="M22.421 9.137c3.327 1.359 5.043 2.024 7.432 1.024 2.419-1.018 4.332-3.239 4.542-6.16-3.922.761-10.391 4.15-11.974 5.136z"/><path fill="#A06253" d="M4.751 35.061c-.584-.091-1.363-.831-1.273-1.416.546-3.562 2.858-12.168 18.298-24.755.458-.375.976-.659 1.364-.212.391.447-.052.95-.498 1.339C9.354 21.587 7.128 30.751 6.619 34.082c-.091.585-1.283 1.067-1.868.979z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f341.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f341.svg new file mode 100644 index 0000000000000000000000000000000000000000..7cd7ad977b13b1c355489473b61073ac7012b844 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f341.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M36 20.917c0-.688-2.895-.5-3.125-1s3.208-4.584 2.708-5.5-5.086 1.167-5.375.708c-.288-.458.292-3.5-.208-3.875s-5.25 4.916-5.917 4.292c-.666-.625 1.542-10.5 1.086-10.698-.456-.198-3.419 1.365-3.793 1.282C21.002 6.042 18.682 0 18 0s-3.002 6.042-3.376 6.125c-.374.083-3.337-1.48-3.793-1.282-.456.198 1.752 10.073 1.085 10.698C11.25 16.166 6.5 10.875 6 11.25s.08 3.417-.208 3.875c-.289.458-4.875-1.625-5.375-.708s2.939 5 2.708 5.5-3.125.312-3.125 1 8.438 5.235 9 5.771c.562.535-2.914 2.802-2.417 3.229.576.496 3.839-.83 10.417-.957V35c0 .553.448 1 1 1 .553 0 1-.447 1-1v-6.04c6.577.127 9.841 1.453 10.417.957.496-.428-2.979-2.694-2.417-3.229.562-.536 9-5.084 9-5.771z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f344.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f344.svg new file mode 100644 index 0000000000000000000000000000000000000000..0cf7a79142409b2b686269d572829acc895abd8d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f344.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M27 33c0 2.209-1.791 3-4 3H13c-2.209 0-4-.791-4-3s3-7 3-13 12-6 12 0 3 10.791 3 13z"/><path fill="#DD2E44" d="M34.666 11.189l-.001-.002c-.96-2.357-2.404-4.453-4.208-6.182h-.003C27.222 1.904 22.839 0 18 0 13.638 0 9.639 1.541 6.524 4.115c-2.19 1.809-3.941 4.13-5.076 6.785C.518 13.075 0 15.473 0 18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4 0-2.417-.48-4.713-1.334-6.811z"/><g fill="#F4ABBA"><path d="M7.708 16.583c3.475 0 6.292-2.817 6.292-6.292S11.184 4 7.708 4c-.405 0-.8.042-1.184.115-2.19 1.809-3.941 4.13-5.076 6.785.306 3.189 2.991 5.683 6.26 5.683z"/><path d="M7.708 4.25c3.331 0 6.041 2.71 6.041 6.042s-2.71 6.042-6.041 6.042c-3.107 0-5.678-2.314-6.006-5.394 1.097-2.541 2.8-4.817 4.931-6.59.364-.067.726-.1 1.075-.1m0-.25c-.405 0-.8.042-1.184.115-2.19 1.809-3.941 4.13-5.076 6.785.306 3.189 2.992 5.683 6.261 5.683 3.475 0 6.291-2.817 6.291-6.292S11.184 4 7.708 4zM26 9.5c0 2.485 2.015 4.5 4.5 4.5 1.887 0 3.497-1.164 4.166-2.811l-.001-.002c-.96-2.357-2.404-4.453-4.208-6.182C27.992 5.028 26 7.029 26 9.5z"/><circle cx="21.5" cy="16" r="4.5"/><circle cx="20" cy="5" r="3"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f345.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f345.svg new file mode 100644 index 0000000000000000000000000000000000000000..411c2a50e38b228c5e56979c02abbd38c4b6b487 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f345.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M22.494 5.344c-.687 0-1.352.066-1.991.177-.819-.104-2.74-.231-3.591-.231-8.473 0-15.886 3.177-15.886 14.298 0 9.036 7.049 16.361 16.976 16.361s17.974-7.325 17.974-16.361C35.975 8.339 26.59 5.344 22.494 5.344z"/><path fill="#77B255" d="M8.439.091c1.637 1.636 2.77 2.266 3.274 4.91.298 1.564 2.266 1.51 2.266 1.51s-3.903 1.763-5.54 3.4c0 0 4.91-1.637 6.547-1.637 0 0 3.273 1.637 3.273 3.273 0 0 0-3.273-1.636-3.273 0 0 4.909 0 4.909 3.273 0 0 0-4.91-1.637-4.91 0 0 4.911-1.636 6.548 0 0 0-1.686-1.72-4.911-1.636 0 0 1.638-1.637 4.911-1.637 0 0-5.288-1.511-6.925 1.763 0 0-1.385-1.385 1.385-4.155 0 0-4.28.755-4.28 4.029 0 0-1.552-.04-2.644-1.259C11.838 1.35 8.439.091 8.439.091z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f346.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f346.svg new file mode 100644 index 0000000000000000000000000000000000000000..14688a6dd5fa2ae76048fb9568645a5d088cbc0b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f346.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#744EAA" d="M6 4c3 0 5 2 8 6s7.957 7.191 12 8c5 1 9 5 9 11 0 4.897-3.846 7-9 7-5 0-9-3-14-8S2 14 2 10s1-6 4-6z"/><path fill="#77B255" d="M3.515 0c1.248 0 1.248 1.248 1.248 2.495 0 1.764 1.248 1.129 2.496 1.129C8.505 3.624 11 6 11 6H7.258c-1.248 0 0 2.614-1.248 2.614S4.762 7.426 3.515 7.426 2 11 2 11s-1.604-4.153.267-6.024C3.515 3.728 1.02 0 3.515 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f347.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f347.svg new file mode 100644 index 0000000000000000000000000000000000000000..e52e2f851970bd538da692bbca693abaac686049 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f347.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M9.999 12c-.15 0-.303-.034-.446-.106-4.38-2.19-7.484-7.526-8.501-10.578C.876.792 1.16.226 1.684.051c.525-.176 1.091.109 1.265.632.877 2.632 3.688 7.517 7.499 9.422.494.247.694.848.447 1.342-.176.351-.529.553-.896.553z"/><circle fill="#553788" cx="19" cy="29" r="7"/><circle fill="#9266CC" cx="10" cy="15" r="7"/><circle fill="#AA8DD8" cx="19" cy="12" r="7"/><circle fill="#744EAA" cx="27" cy="18" r="7"/><circle fill="#744EAA" cx="9" cy="26" r="7"/><circle fill="#9266CC" cx="18" cy="21" r="7"/><circle fill="#9266CC" cx="29" cy="29" r="7"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f348.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f348.svg new file mode 100644 index 0000000000000000000000000000000000000000..f3482735105c8579c73e8c75cfc169b6d15ab00c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f348.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A6D388" d="M31.924 10.982c4.418 7.652 1.99 17.326-5.424 21.607-7.414 4.28-16.505 2.413-20.924-5.241C.577 18.688 3.086 9.156 10.5 4.876c7.414-4.28 17.924.044 21.424 6.106z"/><path fill="#77B255" d="M24 6c3 1 6 4 8 7 .836 1.254.729-.078-.294-2.348C28.02 4.768 17.777.675 10.5 4.876c-3.01 1.738-5.194 4.349-6.413 7.408C4.808 11.471 5.52 11 6 11c1 0-1.896 3.279 1 11 3 8 3 4 3 4s-2-9-1-12 2-5 3-4 5 9 7 14c2.259 5.647 2-1-1-8-2.841-6.628-3-8-2-8s3.465 1.464 7 5c2 2 3 5 4 6s1-1 0-4c-.707-2.121-3-6-6-8-2.496-1.664 0-2 3-1z"/><path fill="#5C913B" d="M11.934 6.358c-.479.276-1.091.112-1.367-.366-1.104-1.914-1.26-4.303-1.266-4.404-.033-.55.387-1.022.937-1.058.552-.034 1.025.385 1.061.936.001.021.137 2.027 1.001 3.525.275.479.112 1.091-.366 1.367z"/><path fill="#77B255" d="M11.961 30.533C11 30 10.234 28.557 9.552 27.308c-.682-1.249.276-1.276.886-.159.681 1.249 1.204 1.612 1.886 2.861.682 1.249.194.832-.363.523zm9.543.373c-.874-2.059-.812-3.057-1.686-5.114-.874-2.059-.749-4.055.124-1.997.874 2.059 1.748 4.118 1.687 5.115-.064.999-.125 1.996-.125 1.996zM27 19c1 3 0 2 1 5s1 5 1 0c0-3.162-1-6-2-7-1.581-1.581 0 2 0 2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f349.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f349.svg new file mode 100644 index 0000000000000000000000000000000000000000..0f5ec06a4d4031de65415734e66cb92aa975f0f0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f349.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M2.472 6.572C1.528 8.698 1 11.038 1 13.5 1 23.165 9.059 31 19 31c7.746 0 14.33-4.767 16.868-11.44L2.472 6.572z"/><path fill="#FFE8B6" d="M4.332 7.295C3.479 9.197 3 11.293 3 13.5c0 8.591 7.164 15.556 16 15.556 6.904 0 12.77-4.26 15.013-10.218L4.332 7.295z"/><path fill="#DD2E44" d="M6.191 8.019C5.43 9.697 5 11.548 5 13.5c0 7.518 6.268 13.611 14 13.611 6.062 0 11.21-3.753 13.156-8.995L6.191 8.019z"/><path d="M9.916 14.277c-.307.46-.741.708-.971.555-.23-.153-.168-.649.139-1.109.307-.46.741-.708.971-.555.23.153.168.649-.139 1.109zm6 1c-.307.46-.741.708-.971.555-.23-.153-.168-.649.139-1.109.307-.46.741-.708.971-.555.23.153.168.649-.139 1.109zm5.082 4.678c.05.551-.132 1.016-.406 1.041-.275.025-.538-.4-.588-.951-.051-.551.132-1.016.406-1.04.275-.026.538.398.588.95zm-9-2c.05.551-.132 1.016-.406 1.041-.275.025-.538-.4-.588-.951-.05-.551.132-1.016.406-1.04.276-.026.538.398.588.95zm3.901 5.346c-.333.441-.78.663-1 .497-.221-.166-.129-.658.205-1.099.333-.441.781-.663 1-.497.221.166.13.657-.205 1.099zm8.036.454c.273.481.299.979.06 1.115-.241.137-.656-.143-.929-.624-.273-.48-.299-.979-.059-1.115.241-.138.655.141.928.624zm-7.017-5.028c.303.463.362.958.131 1.109-.231.152-.663-.1-.966-.562-.303-.462-.361-.958-.131-1.108.231-.154.663.097.966.561zm8.981 1.574c-.333.441-.78.663-1.001.497-.221-.166-.129-.658.205-1.099.333-.442.78-.663 1-.497.222.166.131.657-.204 1.099z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f34a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f34a.svg new file mode 100644 index 0000000000000000000000000000000000000000..82c0c52b1d0dedd8bf75dfbe0625282084fe6b27 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f34a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M3 19.5C3 10.388 10.387 3 19.499 3c9.113 0 16.5 7.387 16.5 16.5S28.612 36 19.499 36C10.387 36 3 28.613 3 19.5z"/><path fill="#662113" d="M11.414 7.585c-.267-.267-.797-.197-1.355.12-3.3-2.732-8.653-3.652-8.895-3.692-.546-.089-1.059.277-1.15.821-.091.544.276 1.06.821 1.151.053.009 4.934.854 7.821 3.16-.275.525-.324 1.015-.07 1.268.39.391 1.34.074 2.121-.707.781-.78 1.097-1.73.707-2.121z"/><path fill="#5C913B" d="M21 1s-3.106 4.318-7.021 5.273C11 7 7.041 7.07 6.646 6.15c-.394-.919 1.572-3.937 4.969-5.393C15.012-.698 21 1 21 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f34b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f34b.svg new file mode 100644 index 0000000000000000000000000000000000000000..ffbdc0886c9e7748cc8b7e129ba229ad6e12b66f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f34b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M11.405 3.339c6.48-1.275 8.453 1.265 11.655.084 3.202-1.181.093 2.82-.745 3.508-.84.688-8.141 4.809-11.307 3.298-3.166-1.511-3.182-6.186.397-6.89z"/><path fill="#77B255" d="M15.001 16c-.304 0-.605-.138-.801-.4-.687-.916-1.308-1.955-1.965-3.056C9.967 8.749 7.396 4.446.783 2.976c-.539-.12-.879-.654-.759-1.193.12-.54.654-.878 1.193-.759C8.671 2.68 11.599 7.581 13.952 11.519c.63 1.054 1.224 2.049 1.848 2.881.332.442.242 1.069-.2 1.4-.18.135-.39.2-.599.2z"/><path fill="#FFCC4D" d="M34.3 31.534c.002-.017-.003-.028-.003-.043 2.774-5.335 2.647-15.113-3.346-21.107-5.801-5.8-13.68-5.821-18.767-4.067-1.579.614-2.917.066-3.815.965-.881.881-.351 2.719-.714 3.819-3.169 5.202-3.405 13.025 2.688 19.117 4.962 4.962 10.438 6.842 19.98 4.853.002-.002.005-.001.008-.002 1.148-.218 2.95.523 3.566-.094 1.085-1.085.309-2.358.403-3.441z"/><path fill="#77B255" d="M8.208 6.583s-4.27-.59-6.857 4.599c-2.587 5.188.582 9.125.29 12.653-.293 3.53 1.566 1.265 2.621-.445s4.23-4.895 4.938-9.269c.707-4.376-.07-6.458-.992-7.538z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f34c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f34c.svg new file mode 100644 index 0000000000000000000000000000000000000000..b4120ba34cbf23a6467ff78d6d68aaf00956af02 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f34c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFE8B6" d="M28 2c2.684-1.342 5 4 3 13-1.106 4.977-5 9-9 12s-11-1-7-5 8-7 10-13c1.304-3.912 1-6 3-7z"/><path fill="#FFD983" d="M31 8c0 3-1 9-4 13s-7 5-4 1 5-7 6-11 2-7 2-3z"/><path fill="#FFCC4D" d="M22 20c-.296.592 1.167-3.833-3-6-1.984-1.032-10 1-4 1 3 0 4 2 2 4-.291.292-.489.603-.622.912-.417.346-.873.709-1.378 1.088-2.263 1.697-5.84 4.227-10 7-3 2-4 3-4 4 0 3 9 3 14 1s10-7 10-7l4-4c-3-4-7-2-7-2z"/><path fill="#FFE8B6" d="M22 20s1.792-4.729-3-7c-4.042-1.916-8-1-11 1s-2 4-3 5 1 2 3 0 8.316-4.895 11-4c3 1 2 2.999 3 5z"/><path fill="#A6D388" d="M26 35h-4c-2 0-3 1-4 1s-2-2 0-2 4 0 5-1 5 2 3 2z"/><circle fill="#3E721D" cx="18" cy="35" r="1"/><path fill="#FFCC4D" d="M32.208 28S28 35 26 35h-4c-2 0 0-1 1-2s5 0 5-6c0-3 4.208 1 4.208 1z"/><path fill="#FFE8B6" d="M26 19c3 0 8 3 7 9s-5 7-7 7h-2c-2 0-1-1 0-2s4 0 4-6c0-3-4-7-6-7 0 0 2-1 4-1z"/><path fill="#FFD983" d="M17 21c3 0 5 1 3 3-1.581 1.581-6 5-10 6s-8 1-5-1 9.764-8 12-8z"/><path fill="#C1694F" d="M2 31c1 0 1 0 1 .667C3 32.333 3 33 2 33s-1-1.333-1-1.333S1 31 2 31z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f34d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f34d.svg new file mode 100644 index 0000000000000000000000000000000000000000..e96999db7a0e90023bfb5209ae4a4015edd4d1e0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f34d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M18.241 9.633c-.277-3.307 2.17-4.72 2.17-4.72-3.199.113-4.894 2.826-4.894 2.826-.752-1.3.946-4.012 2.169-4.719-3.198.113-3.67 2.12-3.67 2.12-1.503-2.601-1.03-4.607-1.03-4.607-1.121.647-1.767 2.113-2.141 3.512l-2.318-2.67c-.23 1.044.157 3.174.573 4.959-3.055-1.79-5.903-.15-5.903-.15 3.95 1.188 5.45 3.788 5.45 3.788s-3.948-1.187-5.646 1.526c2.597-.092 4.5.499 5.856 1.23-1.163.289-3.145-.236-4.355 1.371 0 0 3.198-.113 3.851 1.055-2.172.614-3.575 2.251-3.575 2.251 4.422-.818 9.123 1.669 9.123 1.669l6.119-3.532c-1.029-4.607 2.642-6.727 2.642-6.727-2.724-1.895-4.421.818-4.421.818z"/><path fill="#FFAC33" d="M29.56 22.88c2.488 4.309 1.218 9.7-2.837 12.041-4.055 2.341-9.359.746-11.846-3.562l-1.589-2.753c-2.488-4.31-1.217-9.699 2.837-12.04 4.055-2.341 9.359-.747 11.846 3.562l1.589 2.752z"/><path fill="#FFCC4D" d="M30.562 25.364c-.209-.848-.54-1.685-1.002-2.484l-.186-.323v.001l-1.951-.828.624-1.471-.075-.131c-2.025-3.51-5.92-5.217-9.486-4.466l-.818 1.926-1.884-.8c-3.28 2.122-4.567 6.319-3.262 10.128l1.006.427-.401.946c.055.105.102.212.163.315l1.589 2.753c.685 1.187 1.59 2.16 2.618 2.909l.229-.538 1.951.828-.324.764c.665.277 1.357.465 2.061.572l.215-.507 1.403.595c1.144-.048 2.28-.336 3.343-.883l-.017-.007.828-1.951 1.189.504c.522-.521.973-1.104 1.334-1.736l-1.693-.72.828-1.951 1.667.707c.191-.7.301-1.427.316-2.167l-1.155-.49.828-1.951.062.029zm-6.212-7.243l1.95.829-.828 1.95-1.951-.828.829-1.951zm.294 4.731l-.828 1.95-1.951-.827.828-1.951 1.951.828zm-4.197-6.387l1.951.828-.829 1.952-1.951-.828.829-1.952zm-1.656 3.902l1.951.828-.828 1.951-1.95-.828.827-1.951zm-3.902-1.655l1.95.828-.828 1.949-1.95-.828.828-1.949zm-2.484 5.853l.828-1.952 1.951.828-.829 1.952-1.95-.828zm4.196 6.385l-1.951-.827.828-1.951 1.951.828-.828 1.95zm-.295-4.73l.829-1.951 1.951.827-.829 1.952-1.951-.828zm4.196 6.386l-1.95-.828.828-1.95 1.95.829-.828 1.949zm-.294-4.73l.828-1.952 1.951.829-.828 1.952-1.951-.829zm4.197 6.388l-1.951-.828.828-1.951 1.951.828-.828 1.951zm1.657-3.904l-1.95-.827.828-1.952 1.95.828-.828 1.951zm1.656-3.901l-1.951-.828.828-1.95 1.951.827-.828 1.951z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f34f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f34f.svg new file mode 100644 index 0000000000000000000000000000000000000000..1423d8aa8e2cb55da8150957a782cafc3cf87cf2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f34f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M24 7c-3 0-3 1-6 1s-3-1-6-1c-4 0-9 2-9 9 0 11 6 20 10 20 3 0 3-1 5-1s2 1 5 1c4 0 10-9 10-20 0-7.001-5-9-9-9z"/><path fill="#3E721D" d="M17.311 7.88s-1.775-4.674-6.58-6.06c-3.843-1.108-6.318.26-6.318.26s3.012 3.991 5.895 4.822c2.882.83 7.003.978 7.003.978z"/><path fill="#662113" d="M18 10c-.552 0-1-.448-1-1 0-3.441 1.2-6.615 3.293-8.707.391-.391 1.023-.391 1.414 0s.391 1.024 0 1.414C19.986 3.427 19 6.085 19 9c0 .552-.448 1-1 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f350.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f350.svg new file mode 100644 index 0000000000000000000000000000000000000000..2888963f457ac1db65adb5c525b2cb9c3e0f8172 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f350.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A6D388" d="M7.681 9.097c1.587-3.151 7.698-1.916 11.958 2.171 2.697 2.586 8.056 1.498 11.498 4.804 3.493 3.354 3.259 9.361-3.053 15.767C23 37 16 37 11.835 33.384c-4.388-3.811-2.476-8.61-4.412-13.585C5.487 14.823 3.1 9.375 7.681 9.097z"/><path fill="#662113" d="M8.178 9.534c-.43.448-1.114.489-1.527.093-3.208-3.079-3.918-7.544-3.946-7.776-.074-.586.348-1.157.939-1.278.592-.121 1.131.257 1.205.842.006.05.657 3.997 3.359 6.59.413.397.4 1.081-.03 1.529z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f351.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f351.svg new file mode 100644 index 0000000000000000000000000000000000000000..84e81f5e6ee2c52ee5482ea9000ca26e735394b1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f351.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M1.062 5.125s4.875-5 10-5C17.188.125 19 5.062 19 5.062s.625-4 5-4 6.938 3.125 6.938 3.125-3.562 2.125-4.625 2.562c-2.801 1.153-11.375 3.562-15.375 2.562S1.062 5.125 1.062 5.125z"/><path fill="#FF886C" d="M18 6s1.042-.896 6-.896c6.542 0 12 4.812 12 12.927 0 11.531-14.958 17.881-14.958 17.881S1 34.833 1 17.977C1 8.018 7.75 5 12 5c4.958 0 6 1 6 1z"/><path fill="#77B255" d="M1.062 5.125s4.875-5 10-5C17.188.125 19 5.062 19 5.062s-4.062 5.25-8.062 4.25-9.876-4.187-9.876-4.187z"/><path fill="#DD2E44" d="M22.999 30c-.19 0-.383-.055-.554-.168-.46-.307-.584-.927-.277-1.387C22.183 28.423 24 25.538 24 19c0-6.445-4.578-10.182-4.625-10.219-.431-.345-.501-.974-.156-1.405.346-.431.975-.501 1.406-.156C20.844 7.395 26 11.604 26 19c0 7.22-2.079 10.422-2.168 10.555-.192.289-.51.445-.833.445z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f352.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f352.svg new file mode 100644 index 0000000000000000000000000000000000000000..bdba6bd679c560c624c9db32b31b192cf50afc79 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f352.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M25.999 24c-.198 0-.397-.059-.572-.181-6.543-4.58-12.166-12.366-15.397-17.439 1.699 10.528.997 16.458.962 16.744-.068.548-.562.93-1.115.868-.548-.068-.937-.567-.869-1.115.009-.079.936-8.033-1.986-21.668-.105-.487.166-.978.634-1.148.466-.172.991.028 1.226.468.079.148 8.007 14.873 17.691 21.652.453.316.562.94.246 1.392-.194.279-.504.427-.82.427z"/><path fill="#5C913B" d="M26.547 8.818c-3.476.96-5.051 2.546-10.749.667-4.72-1.557-7.037-4.207-6.345-6.305.692-2.098 3.18-3.163 7.9-1.606 4.749 1.567 4.123 3.466 9.194 7.244z"/><circle fill="#BE1931" cx="26" cy="28" r="8"/><circle fill="#BE1931" cx="11" cy="28" r="8"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f353.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f353.svg new file mode 100644 index 0000000000000000000000000000000000000000..26a41ee246bf0238a42611c7d8a133457dfb7bf3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f353.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M22.614 34.845c3.462-1.154 6.117-3.034 6.12-9.373C28.736 21.461 33 17 32.999 12.921 32.998 9 28.384 2.537 17.899 3.635 7.122 4.764 3 8 2.999 15.073c0 4.927 5.304 8.381 8.127 13.518C13 32 18.551 38.187 22.614 34.845z"/><path fill="#77B255" d="M26.252 3.572c-1.278-1.044-3.28-1.55-5.35-1.677.273-.037.542-.076.82-.094.973-.063 3.614-1.232 1.4-1.087-.969.063-1.901.259-2.837.423.237-.154.479-.306.74-.442C21 0 17 0 14.981 1.688 14.469 1.576 14 1 11 1c-2 0-4.685.926-3 1 .917.041 2 0 1.858.365C9.203 2.425 6 3 6 4c0 .353 2.76-.173 3 0-1.722.644-3 2-3 3 0 .423 2.211-.825 3-1-1 1-1.4 1.701-1.342 2.427.038.475 2.388-.09 2.632-.169.822-.27 3.71-1.258 4.6-2.724.117.285 2.963 1.341 4.11 1.466.529.058 2.62.274 2.141-.711C21 6 20 5 19.695 4.025c.446-.019 8.305.975 6.557-.453z"/><path fill="#F4ABBA" d="M9.339 17.306c-.136-1.46-2.54-3.252-2.331-1 .136 1.46 2.54 3.252 2.331 1zm7.458.553c-.069-.622-.282-1.191-.687-1.671-.466-.55-1.075-.362-1.234.316-.187.799.082 1.752.606 2.372l.041.048c-.213-.525-.427-1.05-.642-1.574l.006.047c.071.64.397 1.73 1.136 1.906.754.182.826-.988.774-1.444zm5.752-4.841c.476-.955.17-3.962-.831-1.954-.476.954-.171 3.962.831 1.954zm7.211-1.457c-.03-.357-.073-.78-.391-1.01-1.189-.858-2.381 2.359-1.385 3.08.02.012.036.025.055.039l-.331-.919c0 .018.001.035.003.052.049.564.376 1.377 1.084.948.667-.406 1.028-1.444.965-2.19zm-1.345 8.567c1.016-1.569-.545-3.451-1.78-1.542-1.016 1.568.546 3.45 1.78 1.542zm-5.748 2.894c.173-1.938-2.309-2.752-2.51-.496-.173 1.938 2.309 2.752 2.51.496zm-9.896-1.212l-.049.004 1.362.715c-.006-.004-.011-.011-.018-.017-.306-.28-1.353-1.083-1.788-.592-.44.497.498 1.421.804 1.703.342.314.928.763 1.429.73 1.437-.093-.783-2.605-1.74-2.543zm13.227 5.907c.969-1.066.725-4.05-.798-2.376-.969 1.066-.724 4.05.798 2.376zM12.599 13.753c.093-.005.187-.012.28-.019.703-.046 1.004-1.454 1.042-1.952.044-.571-.043-1.456-.785-1.407l-.281.019c-.702.047-1.004 1.454-1.042 1.952-.044.571.044 1.457.786 1.407zm7.846 15.257c.395.764.252 1.623-.32 1.919s-1.357-.081-1.753-.844c-.395-.764-.252-1.623.32-1.919.573-.296 1.357.081 1.753.844z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f354.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f354.svg new file mode 100644 index 0000000000000000000000000000000000000000..a129dccb3ba4219ce94ca89a303bee0a65f3709a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f354.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M18 20.411c-9.371 0-16.967-.225-16.967 6.427C1.033 33.487 8.629 35 18 35c9.371 0 16.967-1.513 16.967-8.162 0-6.651-7.596-6.427-16.967-6.427z"/><path fill="#662113" d="M34.47 20.916S26.251 19.932 18 19.89c-8.251.042-16.47 1.026-16.47 1.026C.717 27.39 7.467 30.057 18 30.057s17.283-2.667 16.47-9.141z"/><path fill="#FFCC4D" d="M33.886 18.328l-31.855.646c-1.1 0-2.021 2.229-.854 2.812 8.708 2.708 15.708 5.448 15.708 5.448.962.532 1.287.534 2.25.003 0 0 9.666-3.868 15.875-5.493.881-.23-.025-3.416-1.124-3.416z"/><path fill="#77B255" d="M34.725 18.412c-1.9-1.751-1.79-.819-3.246-1.23-.553-.156-4.51-5.271-13.529-5.271h-.02c-9.019 0-12.976 5.115-13.529 5.271-1.456.411-1.346-.521-3.246 1.23-.872.804-1.108 1.222-.188 1.43 1.386.313 1.26 1.152 2.253 1.444 1.202.353 1.696-.292 3.634-.028 1.653.225 1.761 2.369 3.429 2.369s1.668-.8 3.335-.8 2.653 2.146 4.321 2.146 2.653-2.146 4.321-2.146c1.668 0 1.668.8 3.335.8 1.668 0 1.776-2.144 3.429-2.369 1.938-.263 2.433.381 3.634.028.993-.292.867-1.13 2.253-1.444.922-.207.687-.626-.186-1.43z"/><path fill="#DD2E44" d="M34.077 16.52c0 2.984-7.198 4.393-16.077 4.393S1.923 19.504 1.923 16.52c0-5.403.966-5.403 16.077-5.403s16.077.001 16.077 5.403z"/><path fill="#D99E82" d="M18 .524C8.629.524 1.033 4.915 1.033 11.566c0 6.125 7.596 6.375 16.967 6.375s16.967-.25 16.967-6.375C34.967 4.914 27.371.524 18 .524z"/><path d="M10.784 3.695c-.498-.319-1.159-.173-1.477.325-.318.498-.173 1.16.325 1.477.498.319 1.76.557 2.079.059.318-.498-.429-1.543-.927-1.861zm9.734-1.035c-.562.182-1.549 1.006-1.366 1.568.183.562 1.464.648 2.026.466s.869-.786.686-1.348c-.182-.561-.786-.869-1.346-.686zm10.909 7.035c-.452-.38-1.585.225-1.966.677-.38.453-.321 1.127.131 1.507.452.38 1.127.321 1.507-.131.381-.453.781-1.673.328-2.053zm-3.643-5c-.498-.318-1.159-.172-1.478.326-.318.498-.172 1.159.326 1.477.498.319 1.76.557 2.078.059.319-.499-.428-1.544-.926-1.862zm-15 7c-.498-.318-1.159-.172-1.478.326-.318.497-.172 1.159.326 1.476.498.319 1.76.558 2.078.059.319-.498-.428-1.543-.926-1.861zm3.046-4.808c-.336.486-.62 1.739-.133 2.075.486.336 1.557-.374 1.893-.86.336-.486.213-1.152-.273-1.488-.485-.336-1.152-.213-1.487.273zm7.954 4.808c-.498-.318-1.159-.172-1.478.326-.318.497-.172 1.16.326 1.476.498.319 1.76.558 2.078.059.319-.498-.428-1.543-.926-1.861zM4.948 7.808c-.394.441-.833 1.648-.392 2.042.439.394 1.591-.174 1.985-.615.395-.44.357-1.116-.083-1.511-.439-.394-1.116-.356-1.51.084z" fill="#FFE8B6"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f355.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f355.svg new file mode 100644 index 0000000000000000000000000000000000000000..3a44bba9a045b1b4d31b5a9b8dca305551d943a6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f355.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M18 4c7.257 0 13 4 14.699 2 .197-.323.301-.657.301-1 0-2-6.716-5-15-5C9.716 0 3 3 3 5c0 .343.104.677.301 1C5 8 10.743 4 18 4z"/><path fill="#FFCC4D" d="M18 3C11.787 3 7.384 4.81 5.727 5.618c-.477.233-.539.84-.415 1.278S16 34 16 34s.896 2 2 2 2-2 2-2L30.704 6.779s.213-.842-.569-1.229C28.392 4.689 24.047 3 18 3z"/><g fill="#BE1931"><path d="M18 31c0-2.208-1.791-4-4-4-.254 0-.5.029-.741.075L16 34s.071.14.19.342C17.279 33.627 18 32.399 18 31zm-1-11c0-2.209-1.792-4-4-4-1.426 0-2.67.752-3.378 1.876l2.362 5.978c.327.086.663.146 1.016.146 2.208 0 4-1.792 4-4z"/><circle cx="16" cy="8" r="4"/><path d="M25 9c-2.208 0-4 1.791-4 4s1.792 4 4 4c.682 0 1.315-.187 1.877-.488l1.89-4.806C28.227 10.135 26.752 9 25 9zm-6 16c0 1.868 1.288 3.425 3.019 3.864l2.893-7.357C24.342 21.194 23.697 21 23 21c-2.208 0-4 1.792-4 4zm-9-13c0-2.209-1.791-4-4-4-.087 0-.169.02-.255.026.55 1.412 1.575 4.016 2.775 7.057C9.416 14.349 10 13.248 10 12z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f368.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f368.svg new file mode 100644 index 0000000000000000000000000000000000000000..187b2f4c9a417b70e328e8e291fe8c31df678f73 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f368.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M20 28.625S30.661 25.9 33.356 15.72c.396-1.495-1.518-2.72-3.868-2.72H5.999c-1.175 0-3.74.493-3.072 2.894C5.711 25.9 16 28.625 16 28.625v1.173s-4.634 2.443-5.588 3.01c-1.027.588-.268 1.526.144 1.689.684.269 2.39 1.15 7.116 1.15 4.847 0 7.497-.954 8.083-1.15.226-.075 1.197-.973-.198-1.799-2.484-1.47-5.557-2.9-5.557-2.9v-1.173z"/><path fill="#3B88C3" d="M33.291 15.248c0 1.692-6.835 3.064-15.269 3.064-8.432 0-15.268-1.371-15.268-3.064s6.836-3.064 15.268-3.064c8.434 0 15.269 1.371 15.269 3.064z"/><path fill="#F4ABBA" d="M25.982 6.908c0 1.613-3.133 4.745-7.832 4.745-4.325 0-7.831-2.088-7.831-4.745 0-4.325 3.505-6.787 7.831-6.787 4.327.001 7.832 2.462 7.832 6.787z"/><path fill="#FFE8B6" d="M33.291 14.217c0 1.613-3.132 4.223-7.83 4.223-4.326 0-7.832 1.393-7.832-4.223 0-4.325 3.506-7.831 7.832-7.831 4.325 0 7.83 3.506 7.83 7.831z"/><path fill="#8A4B38" d="M18.672 14.217c0 5.182-3.132 4.311-7.831 4.311-4.325 0-7.831-1.653-7.831-4.311 0-4.325 3.506-7.831 7.831-7.831 4.326 0 7.831 3.506 7.831 7.831z"/><path fill="#3B88C3" d="M30.837 21.098c.824-1.161 1.541-2.487 2.082-3.995-13.485 4.732-26.07 1.375-29.477.336.49 1.279 1.103 2.425 1.797 3.446 11.35 3.251 21.551 1.204 25.598.213z"/><path fill="#55ACEE" d="M2.837 15.177c1.396.6 15.488 5.046 30.498.087 0 .652-.411 2.477-.653 3.175-.391 1.132-15.401 4.83-28.888.261-.392-.173-1.566-3.784-.957-3.523z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f369.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f369.svg new file mode 100644 index 0000000000000000000000000000000000000000..3c2aa5826ec6dcc16daf7b6e17f0aef3e253549c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f369.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M35.337 23.549C34.291 29.819 27.615 34 18.092 34S1.894 29.819.849 23.549c-.247-1.479.156-8.12 1.054-9.406 2.559-3.664 3.474 10.365 16.189 10.365 13.847 0 13.64-14.028 16.199-10.365.898 1.286 1.292 7.927 1.046 9.406z"/><path fill="#8A4B38" d="M18.092 5.995c-9.331 0-16.895 4.584-16.895 10.239 0 5.655 7.564 10.24 16.895 10.24 9.33 0 16.895-4.585 16.895-10.24S27.422 5.995 18.092 5.995zm0 13.374c-3.174 0-5.748-.702-5.748-1.568 0-.866 2.574-1.567 5.748-1.567 3.173 0 5.747.701 5.747 1.567.001.866-2.573 1.568-5.747 1.568z"/><path fill="#8A4B38" d="M1.72 14.623c-.653 1.045-.92 5.494.479 7.577 2.134 3.18 3.179 1.567 4.747 2.047 2.335.715 2.508 2.56 4.354 3.483 2.09 1.045 3.306.741 6.27 0 4.181-1.045 6.837 1.088 9.405 0 2.107-.893 3.312-4.137 4.486-4.528 3.728-1.242 4.515-7.124 1.741-9.537-.87 1.829-5.138 8.404-7.881 8.71-2.744.305-10.974 1-14.457-.784-3.484-1.785-7.01-4.006-7.446-4.616-.436-.611-1.698-2.352-1.698-2.352z"/><path fill="#F4900C" d="M18.092 13.882c-3.752 0-6.793 1.228-6.793 2.743 0 .589.463 1.133 1.245 1.58-.126-.129-.2-.264-.2-.404 0-.866 2.574-1.567 5.748-1.567 3.173 0 5.747.701 5.747 1.567 0 .14-.073.274-.2.404.782-.447 1.246-.991 1.246-1.58.001-1.515-3.041-2.743-6.793-2.743z"/><path fill="#F4ABBA" d="M4.42 18.15c-.375 0-.737-.203-.925-.557-.27-.51-.075-1.143.436-1.412l2.308-1.22c.509-.272 1.142-.075 1.412.436.27.51.075 1.143-.436 1.412l-2.308 1.22c-.156.082-.323.121-.487.121zm11.887 7.794c-.41 0-.799-.242-.966-.646l-.74-1.786c-.221-.533.032-1.144.565-1.365.534-.22 1.144.032 1.365.566l.74 1.786c.221.533-.032 1.145-.566 1.365-.129.055-.265.08-.398.08z"/><path fill="#55ACEE" d="M28.151 21.764c-.181 0-.364-.047-.53-.146-.497-.293-.662-.935-.368-1.431l1.132-1.916c.293-.496.938-.661 1.431-.368.497.294.662.935.368 1.432l-1.132 1.915c-.195.33-.543.514-.901.514z"/><path fill="#F4ABBA" d="M29.893 14c-.56 0-1.023-.481-1.043-1.046-.021-.576.431-1.079 1.007-1.1l1.218-.052c.587-.007 1.062.426 1.081 1.003.021.577-.431 1.096-1.007 1.116L29.931 14h-.038zM19.792 9.876c-.444 0-.855-.285-.997-.73-.174-.55.131-1.137.681-1.312l.826-.261c.556-.174 1.138.131 1.312.682.175.55-.131 1.137-.681 1.312l-.826.261c-.105.033-.211.048-.315.048z"/><path fill="#88C9F9" d="M13.998 11.574c-.157 0-.316-.036-.466-.11l-.784-.392c-.516-.258-.726-.886-.468-1.402.258-.516.886-.726 1.402-.468l.784.392c.516.258.726.886.468 1.402-.184.366-.553.578-.936.578zm9.102 13.28c-.156 0-.315-.035-.465-.109l-.784-.391c-.517-.258-.727-.885-.47-1.401.257-.517.884-.727 1.401-.47l.784.391c.517.258.727.885.47 1.401-.182.367-.553.579-.936.579z"/><path fill="#55ACEE" d="M9.426 22.548c-.138 0-.277-.026-.412-.085-.53-.228-.776-.842-.548-1.372l.392-.914c.228-.529.843-.779 1.373-.548.53.227.776.842.548 1.372l-.392.914c-.17.395-.555.633-.961.633zm15.592-9.885c-.403 0-.787-.234-.958-.627-.232-.529.01-1.145.538-1.376l.696-.305c.53-.232 1.146.01 1.376.538.231.529-.01 1.145-.538 1.377l-.696.305c-.137.06-.279.088-.418.088zM8.035 12.62c-.078 0-.157-.009-.235-.027l-.566-.13c-.562-.13-.914-.691-.784-1.253.129-.563.691-.913 1.253-.784l.566.13c.562.13.914.691.784 1.253-.112.483-.543.811-1.018.811z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f36a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f36a.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f5368a41dd26453b80f3da668e225c3ce76eae7 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f36a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DA9F83" d="M34.966 17.87c.414 4.649-2.082 8.731-4.831 12.206-2.304 2.554-5.602 3.631-8.901 4.285-3.198 1.089-6.766.739-9.716-.895-1.034-.43-2.248-.559-3.167-1.176-2.879-1.846-4.524-4.927-5.779-8.029-1.627-2.916-1.74-6.483-1.414-9.742.219-1.107.967-2.032 1.388-3.051.729-2.127 1.916-3.963 3.569-5.475.786-.787 1.377-1.823 2.303-2.444.919-.617 2.103-.758 3.137-1.188 1.016-.422 1.968-1.08 3.072-1.299 1.072-.213 2.201.106 3.335.106 2.235-.056 4.482.148 6.575.789 1.034.43 1.781 1.38 2.7 1.997.926.622 1.999 1.04 2.784 1.827 1.603 1.566 2.984 3.411 3.94 5.446.65 2.109.957 4.389 1.005 6.643z"/><path fill="#8A4B38" d="M22.638 16.947c1.177-.385 2.444.261 2.827 1.44.384 1.179-.26 2.447-1.441 2.831-1.181.384-3.871.201-4.255-.978-.383-1.181 1.687-2.911 2.869-3.293zm8.57-.672c-.38.452-1.055.512-1.507.131-.452-.381-.511-1.055-.131-1.508.381-.451 1.514-1.057 1.966-.677.453.381.053 1.601-.328 2.054zm-22-7c-.38.452-1.055.512-1.507.131-.452-.381-.511-1.054-.131-1.508.381-.451 1.514-1.057 1.966-.677.453.381.053 1.601-.328 2.054zm12.093-1.894c-.748-.478-.969-1.472-.49-2.22.479-.749 1.473-.968 2.222-.49.749.479 1.872 2.05 1.394 2.798-.48.75-2.377.392-3.126-.088zm-7.926 6.217c-.515-1.066-.064-2.351 1.005-2.864s2.351-.061 2.864 1.008c.513 1.07.682 3.643-.387 4.154-1.071.514-2.971-1.227-3.482-2.298zm1.024 14.099c.602-.874 1.8-1.096 2.672-.492.874.605 1.094 1.801.49 2.675s-2.528 2.147-3.4 1.544c-.875-.604-.366-2.854.238-3.727zm10.013-.406c-.687-.436-.889-1.348-.449-2.034.438-.685 1.349-.886 2.035-.447.686.438 1.715 1.878 1.276 2.562-.438.688-2.176.359-2.862-.081zM5.536 18.42c.762-.853 2.071-.926 2.923-.163.852.764.924 2.071.161 2.922-.763.854-2.992 1.955-3.843 1.191-.854-.763-.005-3.099.759-3.95z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f36b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f36b.svg new file mode 100644 index 0000000000000000000000000000000000000000..a993c9b4b7f8ec337eba510b61192957031cb389 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f36b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M26.339 33.496c-1.562 1.561-4.095 1.561-5.657 0L1.59 14.404c-1.562-1.562-1.562-2.681 0-4.243l8.485-8.485c1.562-1.562 2.681-1.562 4.243 0L33.41 20.768c1.562 1.562 1.562 4.095 0 5.657l-7.071 7.071z"/><path fill="#8A4B38" d="M16.582 15.253l-4.885-4.885 5.657-5.657-1.415-1.414-5.656 5.657L6.54 5.211 5.126 6.626l3.743 3.742-5.657 5.657 1.414 1.414 5.657-5.657 4.885 4.885z"/><path fill="#DD2E44" d="M26.339 34.91c-1.562 1.562-4.095 1.562-5.657 0l-9.899-9.899 14.142-14.142 9.899 9.899c1.562 1.562 1.562 4.095 0 5.657l-8.485 8.485z"/><path fill="#BE1931" d="M12.825 27.053l4.673 4.674 7.955-20.33-.528-.529-1.504-.932z"/><path fill="#CCD6DD" d="M22.804 8.747l2.121 2.121c-.707 2.122-8.485 15.557-9.9 18.385 0 0-.707 2.121-2.475.354l-5.304-5.304c-.679-.679-.685-2.142 0-2.828L19.975 8.747c1.414-1.414 2.829 0 2.829 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f36c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f36c.svg new file mode 100644 index 0000000000000000000000000000000000000000..f6fbf3b70bba83c0d9f6d587eaafd0b82734ae81 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f36c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M13.298 3.538c-.531-4.075-5.627-4.3-6.248-2.125l-.933 4.041-4.041.933c-2.175.621-1.949 5.717 2.125 6.248l3.054.399c4.074.531 6.973-2.367 6.441-6.441l-.398-3.055zm18.993 18.991c4.074.531 4.299 5.629 2.125 6.249l-4.041.933-.934 4.042c-.62 2.174-5.717 1.948-6.248-2.126l-.398-3.055c-.531-4.074 2.367-6.973 6.441-6.441l3.055.398z"/><path fill="#BE1931" d="M30.49 22.294l-1.254-.164c-4.074-.531-6.973 2.367-6.441 6.441l.087.667c1.622-.268 3.45-1.236 5.014-2.8 1.29-1.288 2.172-2.758 2.594-4.144zM6.906 12.988l.349.046c4.074.531 6.973-2.367 6.441-6.441l-.119-.91c-1.317.447-2.697 1.304-3.915 2.523-1.49 1.489-2.437 3.219-2.756 4.782z"/><circle fill="#DD2E44" cx="18.779" cy="17.323" r="10.651"/><g fill="#F5F8FA"><path d="M18.75 17c.39 2.943-.632 6.74-2.593 9.092.84.25 1.72.381 2.621.381.731 0 1.447-.095 2.14-.261.563-2.586.256-5.927-2.168-9.212zm0 0c3.407.635 6.232 3.286 6.779 6.484 1.326-1.45 2.143-3.251 2.347-5.19-1.861-1.889-4.902-3.208-9.126-1.294zm0 0c1.049-2.269 4.509-4.338 7.836-4.438-.375-.613-.816-1.19-1.337-1.711-.767-.767-1.641-1.358-2.571-1.795-2.373 1.241-4.452 3.647-3.928 7.944z"/><path d="M18.792 17.042c-2.81-1.481-4.577-5.04-3.817-8.031-.966.44-1.874 1.047-2.667 1.84-.563.563-1.027 1.187-1.412 1.844 1.287 1.959 3.754 3.829 7.896 4.347zm-.084 0c-2.57 1.557-6.231 2.391-8.958 1.683.235 1.541.862 3.03 1.886 4.309 2.374-.71 5.065-2.503 7.072-5.992z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f36d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f36d.svg new file mode 100644 index 0000000000000000000000000000000000000000..e13447edec3c8c8126ccccd39c15c74244f3ee9a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f36d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M35.066 35.066c-.766.766-2.006.766-2.771 0L12.198 14.97c-.766-.766-.766-2.007 0-2.773.766-.765 2.007-.765 2.772 0l20.096 20.098c.766.764.766 2.006 0 2.771z"/><path fill="#DD2E44" d="M27.8 14.08c0 7.576-6.142 13.72-13.72 13.72C6.503 27.8.36 21.656.36 14.08.36 6.502 6.503.36 14.08.36c7.578 0 13.72 6.142 13.72 13.72z"/><path fill="#F4900C" d="M17.411 27.376c-1.459.092-2.938-.066-4.379-.503-3.156-.961-5.748-3.093-7.3-6.003-1.217-2.283-1.473-4.902-.719-7.376.752-2.474 2.424-4.507 4.707-5.724 1.781-.95 3.822-1.149 5.751-.561 1.929.586 3.514 1.89 4.463 3.67.734 1.377.889 2.958.434 4.451-.454 1.494-1.462 2.721-2.84 3.455-1.056.562-2.267.682-3.412.333-1.144-.348-2.085-1.122-2.648-2.178-.879-1.648-.253-3.704 1.395-4.583.592-.317 1.272-.384 1.915-.187.231.07.447.171.644.299-.672-.327-1.486-.34-2.194.037-1.347.719-1.858 2.399-1.14 3.746.404.758 1.079 1.313 1.901 1.564.822.25 1.692.166 2.45-.239 1.836-.98 2.534-3.271 1.555-5.108-.562-1.055-1.502-1.827-2.645-2.174-1.143-.349-2.353-.231-3.408.332-2.601 1.388-3.589 4.633-2.202 7.235.809 1.517 2.162 2.629 3.807 3.13 1.645.5 3.387.33 4.905-.479 1.839-.98 3.187-2.62 3.794-4.614.605-1.994.399-4.105-.58-5.944-1.195-2.241-3.193-3.884-5.623-4.624-2.432-.74-5.004-.489-7.245.708-2.744 1.463-4.754 3.907-5.66 6.883-.905 2.976-.598 6.125.865 8.869.917 1.721 2.151 3.202 3.623 4.392 1.924 1.028 4.12 1.615 6.455 1.615 1.151.002 2.263-.155 3.331-.422zm-1.325-12.548c.161-.086.288-.211.377-.356-.071.566-.407 1.09-.947 1.378-.297.158-.637.19-.957.093-.321-.098-.585-.314-.743-.611-.21-.393-.06-.884.333-1.094.067-.036.14-.053.212-.053.161 0 .318.086.399.238.255.479.848.661 1.326.405z"/><path fill="#FFCC4D" d="M24.515 8.499C22.946 5.027 18.398 1.187 12.744.564c-.212-.023-.423-.033-.633-.047-3.6.52-6.743 2.429-8.871 5.176 3.382-2.809 6.776-3.214 9.264-2.944 4.835.533 8.694 3.751 10.006 6.655 2.009 4.448.023 9.702-4.424 11.71-1.669.755-3.534.812-5.247.165-1.714-.647-3.074-1.924-3.828-3.594-1.196-2.647-.015-5.774 2.631-6.97 2.007-.906 4.38-.01 5.287 1.997.564 1.251.19 2.691-.822 3.524.263-.27.47-.593.607-.956.261-.692.237-1.444-.067-2.118-.35-.775-.981-1.369-1.777-1.669-.797-.301-1.663-.274-2.437.077-.903.407-1.594 1.142-1.944 2.068-.35.927-.318 1.934.089 2.837.479 1.061 1.343 1.873 2.433 2.284 1.09.412 2.275.373 3.335-.105 2.599-1.174 3.76-4.246 2.586-6.847-1.405-3.111-5.083-4.497-8.195-3.095-3.752 1.696-5.425 6.128-3.731 9.88.997 2.206 2.792 3.891 5.056 4.745 1.042.394 2.124.59 3.205.59 1.269 0 2.534-.27 3.725-.808 5.551-2.51 8.029-9.067 5.523-14.62zm-9.859 6.003c-.054.142-.16.255-.297.318-.554.249-.799.9-.55 1.454.119.264.329.458.576.562-.202-.017-.402-.062-.597-.134-.54-.205-.969-.607-1.206-1.133-.166-.367-.179-.777-.036-1.154.142-.376.423-.676.792-.841.129-.059.267-.088.405-.088.118 0 .236.021.349.064.247.094.442.276.551.518.062.138.066.292.013.434z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f37f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f37f.svg new file mode 100644 index 0000000000000000000000000000000000000000..ddbff6d95f16fd23b42effff5fe80ddff1c80d92 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f37f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M31.301 11H4.668c-1.657 0-3 1.343-3 3s1.343 3 3 3c.182 0 .357-.023.53-.053L5.182 17l.637 14.004C5.918 33.202 7.8 35 10 35h16c2.2 0 4.082-1.798 4.182-3.996L30.818 17l-.015-.05c.163.027.327.05.498.05 1.657 0 3-1.343 3-3s-1.344-3-3-3z"/><path d="M28.668 17v16.989c.863-.734 1.444-1.796 1.492-2.986L30.84 17h-2.172zm-6 0h3v18h-3zm-6 18V17h3v18zm-6-18h3v18h-3zM5.16 17l.68 14.003c.054 1.342.776 2.528 1.828 3.254V17H5.16z" fill="#DA2F47"/><path opacity=".6" fill="#99AAB5" d="M5.16 17l.097 2h25.485l.098-2z"/><path fill="#FFD983" d="M30.929 11.07c.043-.184.071-.373.071-.57 0-.674-.27-1.284-.704-1.733.422-.266.704-.732.704-1.267 0-.829-.672-1.5-1.5-1.5-.197 0-.385.04-.558.11-.139-.513-.539-.913-1.052-1.052.07-.173.11-.36.11-.558 0-.829-.672-1.5-1.5-1.5-.191 0-.372.039-.54.104C25.769 1.913 24.745 1 23.5 1 22.119 1 21 2.119 21 3.5c0 .187.024.368.063.544-.64.113-1.19.469-1.563.969C19.044 4.402 18.322 4 17.5 4 16.119 4 15 5.119 15 6.5l.001.012c-.304-.23-.657-.395-1.047-.466C13.74 4.882 12.725 4 11.5 4c-1.228 0-2.245.887-2.455 2.055C8.866 6.027 8.687 6 8.5 6 6.567 6 5 7.567 5 9.5c0 .545.135 1.054.357 1.514C4.597 11.087 4 11.72 4 12.5c0 .829.672 1.5 1.5 1.5h25c.828 0 1.5-.671 1.5-1.5 0-.678-.453-1.245-1.071-1.43z"/><g fill="#FFAC33"><circle cx="28" cy="8" r="1"/><circle cx="24.5" cy="5.5" r="1.5"/><circle cx="12" cy="7" r="1"/><path d="M31 12.5c0-.828-.672-1.5-1.5-1.5-.658 0-1.212.427-1.414 1.017-.029-.002-.055-.017-.086-.017-.552 0-1 .448-1 1h3.908c.056-.157.092-.324.092-.5zM9.5 12c.198 0 .385.04.558.11.172-.638.75-1.11 1.442-1.11.828 0 1.5.671 1.5 1.5 0 .176-.036.343-.092.5h4.184c-.056-.157-.092-.324-.092-.5 0-.829.672-1.5 1.5-1.5.237 0 .459.06.658.158-.098-.199-.158-.421-.158-.658 0-.829.672-1.5 1.5-1.5s1.5.671 1.5 1.5c0 .198-.04.385-.11.558.638.172 1.11.749 1.11 1.442 0 .176-.036.343-.092.5h2.968l-.566-.5c.42-.367.69-.899.69-1.5 0-1.104-.896-2-2-2-.378 0-.728.111-1.03.294.015-.097.03-.193.03-.294 0-1.104-.896-2-2-2-.808 0-1.501.482-1.816 1.172C18.978 8.066 18.748 8 18.5 8c-.828 0-1.5.672-1.5 1.5 0 .198.04.385.11.558-.638.173-1.11.75-1.11 1.442 0 .198.04.385.11.558-.23.062-.438.177-.61.332-.266-.24-.614-.39-1-.39-.237 0-.459.06-.659.159.099-.2.159-.422.159-.659 0-.828-.672-1.5-1.5-1.5-.198 0-.385.04-.558.11C11.77 9.472 11.192 9 10.5 9 9.672 9 9 9.672 9 10.5c0 .198.04.385.11.558-.23.062-.438.177-.61.332-.266-.24-.614-.39-1-.39-.828 0-1.5.672-1.5 1.5 0 .176.036.343.092.5h2c.207-.581.756-1 1.408-1z"/></g><path fill="#FFF" d="M4 13v1c0 .552.448 1 1 1h26c.553 0 1-.448 1-1v-1H4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f380.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f380.svg new file mode 100644 index 0000000000000000000000000000000000000000..03d4a751065248fb0251a48628f2426f34defdce --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f380.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M19.281 6.392c0 .405-2.37.405-2.37 0 0-.9-14.911-9.899-14.911-2.7v13.499c0 2.487 3.476 1.947 7.193.361-1.429 3.525-4.498 9.68-7.05 13.934-.229.382-.178.868.124 1.194.303.325.783.415 1.181.215l5.258-2.629c.441.726.931 1.868 1.376 2.906.333.778.678 1.582 1.024 2.275.144.287.417.488.734.54.053.009.107.013.16.013.263 0 .518-.104.707-.293 1.42-1.419 3.429-8.395 4.793-14.093 1.364 5.698 3.373 12.674 4.793 14.093.188.189.444.293.707.293.053 0 .106-.004.16-.013.317-.052.591-.253.734-.54.347-.693.691-1.497 1.024-2.275.445-1.038.935-2.181 1.376-2.906l5.258 2.629c.398.198.879.111 1.181-.215.303-.326.352-.812.124-1.194-2.735-4.558-6.061-11.296-7.328-14.643C29.652 18.933 34 20.02 34 17.19V3.691c0-7.198-14.719 1.801-14.719 2.701z"/><path fill="#A0041E" d="M2.114 17.869c1.177 3.199 11.468-1.787 14.86-5.179.31-.31.549-.602.758-.885-10.446.252-14.542 3.857-15.618 6.064zm16.482-6.068c.212.285.453.578.765.89 3.6 3.6 14.639 8.999 14.639 4.5v-.209c-1.671-2.199-6.037-5.022-15.404-5.181z"/><path fill="#EA596E" d="M22 11.4c0 1.988-1.611 3.6-3.599 3.6h-1.802C14.611 15 13 13.388 13 11.4V7.6C13 5.612 14.611 4 16.599 4h1.802C20.389 4 22 5.612 22 7.6v3.8z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f381.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f381.svg new file mode 100644 index 0000000000000000000000000000000000000000..1ab82981c0572dd3fbcdee1ab4832e45327c25e7 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f381.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FDD888" d="M33 31c0 2.2-1.8 4-4 4H7c-2.2 0-4-1.8-4-4V14c0-2.2 1.8-4 4-4h22c2.2 0 4 1.8 4 4v17z"/><path fill="#FDD888" d="M36 11c0 2.2-1.8 4-4 4H4c-2.2 0-4-1.8-4-4s1.8-4 4-4h28c2.2 0 4 1.8 4 4z"/><path fill="#FCAB40" d="M3 15h30v2H3z"/><path fill="#DA2F47" d="M19 3h-2c-1.657 0-3 1.343-3 3v29h8V6c0-1.656-1.343-3-3-3z"/><path fill="#DA2F47" d="M16 7c1.1 0 1.263-.516.361-1.147L9.639 1.147c-.902-.631-2.085-.366-2.631.589L4.992 5.264C4.446 6.219 4.9 7 6 7h10zm4 0c-1.1 0-1.263-.516-.361-1.147l6.723-4.706c.901-.631 2.085-.366 2.631.589l2.016 3.527C31.554 6.219 31.1 7 30 7H20z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f382.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f382.svg new file mode 100644 index 0000000000000000000000000000000000000000..35f9a002a9a7c46255657ef2d1d12515acb24b8c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f382.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#8899A6" cx="18" cy="26" rx="18" ry="10"/><ellipse fill="#CCD6DD" cx="18" cy="24.25" rx="18" ry="10"/><path fill="#DD2E44" d="M32.675 23.685c0 4.26-6.57 7.712-14.675 7.712S3.325 27.945 3.325 23.685c0-4.258 6.57-7.711 14.675-7.711 8.104 0 14.675 3.453 14.675 7.711z"/><path fill="#F4ABBA" d="M32.233 22.543c0 9.854-28.466 9.854-28.466 0v-8.759h28.466v8.759z"/><path fill="#DD2E44" d="M17.984 18.166c-8.984 0-14.218-4.132-14.218-4.132s-.016.924-.016 1.685c0 0 .032 4.898 2.572 4.898 2.459 0 2.28 2.348 3.834 2.591 1.541.241 1.712-.938 3.625-.938s2.25 2.106 4.203 2.106c2.289 0 2.477-2.106 4.389-2.106s2.132 1.224 3.386.885c1.507-.408.814-2.537 3.887-2.537 2.54 0 2.603-4.648 2.603-4.648 0-.76-.017-1.935-.017-1.935s-5.263 4.131-14.248 4.131z"/><path fill="#EA596E" d="M32.675 12.737c0 4.259-6.57 7.712-14.675 7.712S3.325 16.996 3.325 12.737 9.895 5.025 18 5.025c8.104 0 14.675 3.453 14.675 7.712z"/><path fill="#FFF8E8" d="M25.664 13.784c-.605 0-1.095-.49-1.095-1.095V5.025c0-.605.49-1.095 1.095-1.095s1.095.49 1.095 1.095v7.664c0 .605-.49 1.095-1.095 1.095z"/><path fill="#FAAA35" d="M25.664 6.667c-1.162 0-2.076-.532-2.445-1.423-.32-.773-.479-2.45 2.058-4.986.214-.214.56-.214.774 0 2.537 2.537 2.378 4.213 2.058 4.986-.369.891-1.283 1.423-2.445 1.423z"/><path fill="#FFF8E8" d="M18 17.068c-.605 0-1.095-.49-1.095-1.095V8.31c0-.605.49-1.095 1.095-1.095s1.095.49 1.095 1.095v7.664c0 .604-.49 1.094-1.095 1.094z"/><path fill="#FAAA35" d="M18 9.952c-1.162 0-2.076-.532-2.445-1.423-.321-.773-.479-2.45 2.058-4.986.214-.214.56-.214.774 0 2.537 2.537 2.378 4.213 2.058 4.986-.369.891-1.283 1.423-2.445 1.423z"/><path fill="#FFF8E8" d="M10.336 13.784c-.605 0-1.095-.49-1.095-1.095V5.025c0-.605.49-1.095 1.095-1.095s1.095.49 1.095 1.095v7.664c0 .605-.49 1.095-1.095 1.095z"/><path fill="#FAAA35" d="M10.336 6.667c-1.162 0-2.076-.532-2.445-1.423-.321-.773-.479-2.45 2.058-4.986.214-.214.56-.214.774 0 2.537 2.537 2.378 4.213 2.058 4.986-.369.891-1.283 1.423-2.445 1.423z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f383.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f383.svg new file mode 100644 index 0000000000000000000000000000000000000000..591fc66a439db31286a65a8960b11ca4fd1b96cc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f383.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M32.664 8.519C29.364 5.134 23.42 4.75 18 4.75S6.636 5.134 3.336 8.519C.582 11.344 0 15.751 0 19.791c0 5.263 1.982 11.311 6.357 14.244C9.364 36.051 13.95 35.871 18 35.871s8.636.18 11.643-1.836C34.018 31.101 36 25.054 36 19.791c0-4.04-.582-8.447-3.336-11.272z"/><path fill="#3F7123" d="M20.783 5.444c.069.42-.222.764-.647.764h-4.451c-.426 0-.717-.344-.647-.764l.745-4.472c.07-.421.476-.764.902-.764h2.451c.426 0 .832.344.901.764l.746 4.472z"/><path fill="#642116" d="M20.654 21.159l-1.598-2.596c-.291-.542-.673-.813-1.057-.817-.383.004-.766.275-1.057.817l-1.598 2.596c-.587 1.093.873 1.716 2.654 1.716s3.243-.624 2.656-1.716zm9.508 3.192c-.045-.075-.126-.121-.214-.121h-.841c-.068 0-.134.028-.181.077l-2.231 2.334-2.698-2.169c-.051-.041-.117-.058-.185-.053-.066.007-.127.041-.168.094l-2.408 3.062-3.054-3.266c-.013-.014-.033-.017-.048-.028-.015-.01-.025-.027-.043-.034-.006-.002-.013 0-.019-.002-.024-.007-.047-.005-.072-.005-.025 0-.048-.002-.072.006-.006.002-.013-.001-.02.002-.018.007-.027.024-.043.034-.016.01-.035.013-.048.027l-3.053 3.266-2.409-3.062c-.041-.053-.102-.087-.168-.094-.066-.006-.133.012-.185.053l-2.698 2.169-2.23-2.334c-.047-.049-.112-.077-.181-.077h-.841c-.087 0-.169.046-.214.121-.045.075-.048.168-.007.245l2.754 5.219c.034.064.093.11.164.127s.145.002.203-.04l2.034-1.458 3.004 3.633c.043.053.106.085.174.09l.019.001c.062 0 .121-.022.167-.063L18 28.836l3.65 3.268c.046.041.105.063.167.063l.019-.001c.068-.005.131-.037.174-.09l3.005-3.633 2.034 1.458c.06.043.133.06.203.04.07-.017.13-.062.163-.126l2.755-5.219c.04-.077.038-.17-.008-.245zm-2.186-8.93c.129 2.127-.784 3.806-3.205 3.953-2.42.146-3.529-1.411-3.658-3.537s1.232-5.12 3.127-5.234c1.896-.116 3.608 2.691 3.736 4.818zm-19.952 0c-.129 2.127.784 3.806 3.205 3.953 2.42.146 3.529-1.411 3.658-3.537s-1.232-5.12-3.127-5.234-3.608 2.691-3.736 4.818z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f388.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f388.svg new file mode 100644 index 0000000000000000000000000000000000000000..6d431bc8568defe34dc05b4bba93dc11486372c8 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f388.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCAB40" d="M27.999 36c-.448 0-.855-.303-.969-.758-.036-.136-.926-3.436-4.273-4.272C18.054 29.794 18 23.277 18 23c0-.552.447-.998.998-.999.554.034 1 .445 1.002.997 0 .053.054 5.234 3.242 6.032 4.53 1.132 5.682 5.54 5.727 5.728.135.535-.191 1.078-.727 1.212-.081.02-.163.03-.243.03z"/><path fill="#BB1A34" d="M18 25c-1.1 0-1.598-.805-1.105-1.789l1.211-2.422c.492-.984 1.297-.984 1.789 0l1.211 2.422C21.598 24.195 21.1 25 20 25h-2z"/><path fill="#BB1A34" d="M28 9c0 6-7 12-9 12s-9-6-9-12c0-5.799 4.582-9 9-9s9 3.201 9 9z"/><path fill="#FCAB40" d="M20 22h-2c-.552 0-1-.447-1-1s.448-1 1-1h2c.553 0 1 .447 1 1s-.447 1-1 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f389.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f389.svg new file mode 100644 index 0000000000000000000000000000000000000000..a4b8305af6be3450c5961c11b8c77c151abffb99 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f389.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M11.626 7.488c-.112.112-.197.247-.268.395l-.008-.008L.134 33.141l.011.011c-.208.403.14 1.223.853 1.937.713.713 1.533 1.061 1.936.853l.01.01L28.21 24.735l-.008-.009c.147-.07.282-.155.395-.269 1.562-1.562-.971-6.627-5.656-11.313-4.687-4.686-9.752-7.218-11.315-5.656z"/><path fill="#EA596E" d="M13 12L.416 32.506l-.282.635.011.011c-.208.403.14 1.223.853 1.937.232.232.473.408.709.557L17 17l-4-5z"/><path fill="#A0041E" d="M23.012 13.066c4.67 4.672 7.263 9.652 5.789 11.124-1.473 1.474-6.453-1.118-11.126-5.788-4.671-4.672-7.263-9.654-5.79-11.127 1.474-1.473 6.454 1.119 11.127 5.791z"/><path fill="#AA8DD8" d="M18.59 13.609c-.199.161-.459.245-.734.215-.868-.094-1.598-.396-2.109-.873-.541-.505-.808-1.183-.735-1.862.128-1.192 1.324-2.286 3.363-2.066.793.085 1.147-.17 1.159-.292.014-.121-.277-.446-1.07-.532-.868-.094-1.598-.396-2.11-.873-.541-.505-.809-1.183-.735-1.862.13-1.192 1.325-2.286 3.362-2.065.578.062.883-.057 1.012-.134.103-.063.144-.123.148-.158.012-.121-.275-.446-1.07-.532-.549-.06-.947-.552-.886-1.102.059-.549.55-.946 1.101-.886 2.037.219 2.973 1.542 2.844 2.735-.13 1.194-1.325 2.286-3.364 2.067-.578-.063-.88.057-1.01.134-.103.062-.145.123-.149.157-.013.122.276.446 1.071.532 2.037.22 2.973 1.542 2.844 2.735-.129 1.192-1.324 2.286-3.362 2.065-.578-.062-.882.058-1.012.134-.104.064-.144.124-.148.158-.013.121.276.446 1.07.532.548.06.947.553.886 1.102-.028.274-.167.511-.366.671z"/><path fill="#77B255" d="M30.661 22.857c1.973-.557 3.334.323 3.658 1.478.324 1.154-.378 2.615-2.35 3.17-.77.216-1.001.584-.97.701.034.118.425.312 1.193.095 1.972-.555 3.333.325 3.657 1.479.326 1.155-.378 2.614-2.351 3.17-.769.216-1.001.585-.967.702.033.117.423.311 1.192.095.53-.149 1.084.16 1.233.691.148.532-.161 1.084-.693 1.234-1.971.555-3.333-.323-3.659-1.479-.324-1.154.379-2.613 2.353-3.169.77-.217 1.001-.584.967-.702-.032-.117-.422-.312-1.19-.096-1.974.556-3.334-.322-3.659-1.479-.325-1.154.378-2.613 2.351-3.17.768-.215.999-.585.967-.701-.034-.118-.423-.312-1.192-.096-.532.15-1.083-.16-1.233-.691-.149-.53.161-1.082.693-1.232z"/><path fill="#AA8DD8" d="M23.001 20.16c-.294 0-.584-.129-.782-.375-.345-.432-.274-1.061.156-1.406.218-.175 5.418-4.259 12.767-3.208.547.078.927.584.849 1.131-.078.546-.58.93-1.132.848-6.493-.922-11.187 2.754-11.233 2.791-.186.148-.406.219-.625.219z"/><path fill="#77B255" d="M5.754 16c-.095 0-.192-.014-.288-.042-.529-.159-.829-.716-.67-1.245 1.133-3.773 2.16-9.794.898-11.364-.141-.178-.354-.353-.842-.316-.938.072-.849 2.051-.848 2.071.042.551-.372 1.031-.922 1.072-.559.034-1.031-.372-1.072-.923-.103-1.379.326-4.035 2.692-4.214 1.056-.08 1.933.287 2.552 1.057 2.371 2.951-.036 11.506-.542 13.192-.13.433-.528.712-.958.712z"/><circle fill="#5C913B" cx="25.5" cy="9.5" r="1.5"/><circle fill="#9266CC" cx="2" cy="18" r="2"/><circle fill="#5C913B" cx="32.5" cy="19.5" r="1.5"/><circle fill="#5C913B" cx="23.5" cy="31.5" r="1.5"/><circle fill="#FFCC4D" cx="28" cy="4" r="2"/><circle fill="#FFCC4D" cx="32.5" cy="8.5" r="1.5"/><circle fill="#FFCC4D" cx="29.5" cy="12.5" r="1.5"/><circle fill="#FFCC4D" cx="7.5" cy="23.5" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f38f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f38f.svg new file mode 100644 index 0000000000000000000000000000000000000000..5457d1e8d5f12d15b3ead77436b634f6595005b2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f38f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M3 3h2v33H3z"/><circle fill="#F4900C" cx="4" cy="3" r="3"/><path fill="#66757F" d="M9 28H4c-.552 0-1-.447-1-1s.448-1 1-1h5c.552 0 1 .447 1 1s-.448 1-1 1z"/><path fill="#DD2E44" d="M31 27c0-2.209 6.209-6 4-6h-8.447c-1.203-1.464-4.595-3-7.053-3-2.459 0-3.23 1.536-3.435 3H10c-2.209 0-3 1.791-3 4v4c0 2.209.791 4 3 4h25c2.209 0-4-3.791-4-6z"/><circle fill="#FFF" cx="12" cy="25" r="3"/><circle cx="11.5" cy="24.5" r="1.5"/><path fill="#F4ABBA" d="M35 21H15.962c2.068 2.286 4.742 6.465-.037 12H35c2.209 0-4-3.791-4-6s6.209-6 4-6z"/><path fill="#66757F" d="M9 12H4c-.552 0-1-.448-1-1s.448-1 1-1h5c.552 0 1 .448 1 1s-.448 1-1 1z"/><path fill="#55ACEE" d="M31 11c0-2.209 6.209-6 4-6h-8.446c-1.203-1.464-4.595-3-7.054-3-2.459 0-3.23 1.536-3.435 3H10C7.791 5 7 6.791 7 9v4c0 2.209.791 4 3 4h25c2.209 0-4-3.791-4-6z"/><circle fill="#FFF" cx="12" cy="9" r="3"/><circle cx="11.5" cy="8.5" r="1.5"/><path fill="#BBDDF5" d="M35 5H15.962c2.068 2.286 4.742 6.465-.037 12H35c2.209 0-4-3.791-4-6s6.209-6 4-6z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f392.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f392.svg new file mode 100644 index 0000000000000000000000000000000000000000..f44d568064f51aae16729bb2b69be645b9f4d2a4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f392.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path d="M11.946 27C-1.036 7.876 7.524 2.752 9.114 2c.149-.07.242-.105.245-.107.418-.209.638-.675.529-1.125C9.779.318 9.372 0 8.903 0H4.847C1.054 0-4.282 11 5.859 28c.151.253 5.073 0 5.073 0 .559 0 1.324-.541 1.014-1zM31.229 0h-4c-.462 0-.863.318-.971.768-.107.45.109.916.521 1.125.004.002.095.037.242.107 1.568.752 10.01 5.876-2.792 25-.307.459.448 1 1 1 0 0 4.854.253 5.002 0 10-17 4.739-28 .998-28z" fill="#C1694F"/><path d="M6.889 28.836l.004.01c-.064-.293 5.363-1.387 5.053-1.846C-1.036 7.876 7.524 2.752 9.114 2H4.845C1.053 2-3.268 13 6.889 28.836zM31.231 2h-4.21c1.568.752 10.01 5.876-2.792 25-.307.459 4.984 1.839 4.986 1.836C39.231 13 34.971 2 31.231 2z" fill="#662113"/><path fill="#C1694F" d="M9.916 8c-.561 0-1.015-.448-1.015-1 0-3.316-2.028-5-4.056-5-.47 0-.08-.782.029-1.232.11-.45.516-.768.985-.768h5.071c3.791 0 4.938 6.136 5.057 6.835.049.29-.034.586-.226.811-.195.225-.478.354-.775.354h-5.07zm16.315 0c.553 0 1-.448 1-1 0-3.316 2-5 4-5 .463 0 .078-.782-.029-1.232-.107-.45-.508-.768-.971-.768h-5c-3.738 0-4.869 6.136-4.986 6.835-.049.29.033.586.223.811.191.225.47.354.763.354h5z"/><path fill="#BE1931" d="M6 32s0 4 4 4h16s4 0 4-4V10s0-4-4-4H10c-4 0-4 4-4 4v22z"/><path fill="#A0041E" d="M24 28H12c-2.201 0-3-1.794-3-3V11c0-.552.448-1 1-1s1 .448 1 1v14c.012.45.195 1 1 1h12c.45-.012 1-.194 1-1V11c0-.552.447-1 1-1s1 .448 1 1v14c0 2.201-1.794 3-3 3z"/><path fill="#FFF" d="M16 25s0-1 1-1h2s1 0 1 1v5s0 1-1 1h-2s-1 0-1-1v-5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f399.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f399.svg new file mode 100644 index 0000000000000000000000000000000000000000..07881e4aabe6a11341c481f4316b329dffd1908d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f399.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M6 15h24v2H6zm15 15c0 2.208-.792 4-3 4-2.209 0-3-1.792-3-4s.791-2 3-2c2.208 0 3-.208 3 2z"/><path fill="#66757F" d="M18 31c-6.627 0-10 1.343-10 3v2h20v-2c0-1.657-3.373-3-10-3z"/><path fill="#99AAB5" d="M18 0c-4.971 0-9 4.029-9 9v7h18V9c0-4.971-4.029-9-9-9z"/><g fill="#292F33"><circle cx="15.5" cy="2.5" r="1.5"/><circle cx="20.5" cy="2.5" r="1.5"/><circle cx="17.5" cy="6.5" r="1.5"/><circle cx="22.5" cy="6.5" r="1.5"/><circle cx="12.5" cy="6.5" r="1.5"/><circle cx="15.5" cy="10.5" r="1.5"/><circle cx="10.5" cy="10.5" r="1.5"/><circle cx="20.5" cy="10.5" r="1.5"/><circle cx="25.5" cy="10.5" r="1.5"/><circle cx="17.5" cy="14.5" r="1.5"/><circle cx="22.5" cy="14.5" r="1.5"/><circle cx="12.5" cy="14.5" r="1.5"/></g><path fill="#66757F" d="M9 15.062V17c0 4.971 4.029 9 9 9s9-4.029 9-9v-1.938H9z"/><path fill="#66757F" d="M30 14c-.553 0-1 .448-1 1v2c0 6.074-4.925 11-11 11S7 23.074 7 17v-2c0-.552-.448-1-1-1s-1 .448-1 1v2c0 7.18 5.82 13 13 13s13-5.82 13-13v-2c0-.552-.447-1-1-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f39f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f39f.svg new file mode 100644 index 0000000000000000000000000000000000000000..984f2706494221ae5c6014d9f45472571624e2a6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f39f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA596E" d="M26.751 8.007c1.364 1.365 3.364 1.708 5.046 1.032l3.613 3.611c.737.74.738 1.938-.004 2.68L15.319 35.405c-.743.739-1.94.737-2.681 0l-3.606-3.612c.672-1.684.33-3.682-1.032-5.047-1.367-1.365-3.364-1.707-5.047-1.032l-2.359-2.36c-.74-.737-.742-1.938 0-2.68L20.678.596c.739-.74 1.936-.741 2.679.002l2.361 2.361c-.677 1.683-.331 3.681 1.033 5.048z"/><path fill="#BE1931" d="M5.42 18.527l-2.149 2.148c-.739.739-.741 1.939-.003 2.68l.542.541c1.896-.505 3.999-.018 5.482 1.468 1.488 1.486 1.971 3.589 1.467 5.481l1.878 1.883c.741.739 1.941.739 2.682-.002l2.189-2.187L5.42 18.527zm13.521 10.58l10.158-10.152L17.008 6.943 6.854 17.095l12.087 12.012zm1.99-13.993c2.245 2.228 2.745 5.356 1.121 6.989-1.627 1.635-4.762 1.151-7.001-1.075-2.239-2.228-2.738-5.358-1.114-6.991 1.625-1.63 4.755-1.15 6.994 1.077zm11.8-2.464l-1.881-1.881c-1.895.503-3.998.021-5.483-1.468-1.488-1.484-1.976-3.591-1.47-5.484l-.541-.546c-.74-.735-1.94-.735-2.678.003L18.442 5.51l12.092 12.011 2.196-2.195c.74-.737.74-1.936.001-2.676z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3a0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a0.svg new file mode 100644 index 0000000000000000000000000000000000000000..35c75b697034433cd256a5f6541cc94473a9ee8c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M24.357 16.337s2.248-3.959 4.805-4.169c2.557-.21 3.929.934 4.144 3.432.287 3.334-.878 3.802-.033 7.53 0 0-3.546-2.414-2.421-6.07 1.172-3.806-4.81-3.095-3.835.316l-2.66-1.039z"/><path fill="#FFCC4D" d="M14.31 20.375c-.553 0-1 .448-1 1v13.563c0 .552.447 1 1 1s1-.448 1-1V21.375c0-.552-.448-1-1-1z"/><path fill="#F4900C" d="M15.31 25.77l-2 1.047v2.257l2-1.047zm-2 8.054l2-1.047V30.52l-2 1.047z"/><path fill="#8899A6" d="M3.912 21.935c-1.181-.117-1.918 1.621-1.918 1.621.114.814.447 2.255.597 2.778.327 1.141 2.121 3.095 3.262 2.768 1.141-.327.814-1.468.487-2.608-.327-1.141-2.428.622-1.794-1.955.149-.606.865-.756 1.483-.695 2.362.234 2.881-.223 3.788-1.325 1.064-1.296-4.724-.467-5.905-.584zm25.142 6.7c0 2.373 1.187 3.56 3.56 3.56s1.187 0 0-2.373-3.56-3.56-3.56-3.56v2.373z"/><path fill="#CCD6DD" d="M34.987 31.008c-1.187-1.187-2.373 0-2.373-2.373s-1.187-3.56-2.373-3.56-1.187-4.746-1.187-5.933-2.373-5.933-5.933-5.933c-3.56 0-5.933 1.187-8.306 1.187-2.373 0-3.56 0-4.746-4.746-.91-3.64-4.746-4.746-8.306-3.56 0 0-2.582-.995-1.395.192 1.187 1.187-.18.995-.18 3.368 0 .275.066.515.174.73C.354 11.489.343 13.521.369 14c.036.667.294.883 1.131 1.208 1.125.438 1.782-.319 1.854-.708.146-.792.021-1.656.021-1.656s1.167-.469 1.896-1.135c.098.081.625 1.146.052 2.688-.413 1.112-1.187 2.373 1.187 5.933 0 0-3.56 0-4.746 1.187C.577 22.704.288 25.077.312 26.263c.033 1.648 1.452 3.56 2.639 3.56s1.187-1.187 1.187-2.373c0-1.187-2.373 0-1.187-2.373 1.187-2.373 1.187-1.187 2.373-1.187 1.187 0 3.56-1.187 4.746-1.187s3.56 1.187 5.933 1.187c2.373 0 4.746-2.373 7.119 0 2.373 2.373 5.933 2.373 7.119 3.56 1.187 1.187 1.187 2.373 1.187 3.56 0 1.187 2.373 2.373 3.56 2.373s1.186-1.188-.001-2.375z"/><path fill="#3B94D9" d="M10.712 11.761c1.006 2.629 2.154 2.635 4.103 2.635 2 0 4.008-.835 6.718-1.101.143.36.276.728.401 1.101 1.187 3.56 0 5.933-5.933 5.933-3.277 0-5.933-2.656-5.933-5.933.001-.951.246-1.838.644-2.635z"/><path fill="#F4900C" d="M5.629 19.705c.225.026.459-.013.674-.124.17-.087 4.187-2.185 5.919-5.914.276-.594-1.171-1.719-1.446-1.629-.301.099-.56.318-.704.628-1.385 2.98-4.821 4.786-4.854 4.804-.581.301-.81 1.017-.509 1.598.187.367.539.594.92.637z"/><ellipse fill="#1C6399" cx="14.31" cy="15.245" rx="1.455" ry="1.163"/><path fill="#FFCC4D" d="M14.31.25c-.553 0-1 .448-1 1v13.573l.005-.001-.003.001c.006.547.449.989.998.989.553 0 1-.448 1-1V1.25c0-.552-.448-1-1-1z"/><path fill="#F4900C" d="M15.31 2.02l-2 1.047v2.257l2-1.047zm0 4.75l-2 1.047v2.257l2-1.047zm-2 8.043l.01.006 1.99-1.041V11.52l-2 1.047v2.246z"/><path fill="#1C6399" d="M3.274 13.255c-.091 0-.182-.025-.262-.074-1.136-.698-2.341-.72-2.353-.72-.276-.003-.498-.229-.496-.504.002-.275.225-.496.5-.496.057.011 1.129.003 2.35.584.287-.838.765-2.666.466-4.922-.036-.274.156-.525.43-.562.276-.033.525.156.562.43.452 3.409-.695 5.875-.744 5.978-.061.128-.173.225-.31.265-.047.014-.095.021-.143.021z"/><ellipse transform="rotate(-56.453 1.847 8.862)" fill="#292F33" cx="1.846" cy="8.862" rx=".555" ry=".424"/><path fill="#DD2E44" d="M12.442 13.21c-2.373-2.373-1.006-5.256-3.379-7.629-1.876-1.876-4.927-1.863-7.3.51 0 0 1.121 1.086 4.081 1.378 1.43.141 2.649 1.693 3.337 2.782 2.21 4.311 5.056 4.754 3.261 2.959z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3a1.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a1.svg new file mode 100644 index 0000000000000000000000000000000000000000..c35744ab8c82f01f661e2abbfc08a5b1a422598c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M30.806 15.347H19.201l8.205-8.205-.707-.707-8.205 8.205V3.036h-1V14.64L9.288 6.435l-.707.707 8.206 8.205H5.182v1h11.605l-8.206 8.206.707.707 8.206-8.206v11.605h1V17.055l8.205 8.205.707-.707-8.205-8.206h11.605z"/><path fill="#AAB8C2" d="M17.994 1.394c-7.982 0-14.453 6.471-14.453 14.453 0 7.982 6.471 14.453 14.453 14.453 7.983 0 14.454-6.471 14.454-14.453-.001-7.982-6.472-14.453-14.454-14.453zm0 26.683c-6.755 0-12.23-5.475-12.23-12.23s5.475-12.23 12.23-12.23c6.754 0 12.23 5.475 12.23 12.23s-5.475 12.23-12.23 12.23z"/><path fill="#AAB8C2" d="M17.993 23.374c-4.15 0-7.526-3.377-7.526-7.527s3.376-7.526 7.526-7.526c4.151 0 7.528 3.376 7.528 7.526s-3.376 7.527-7.528 7.527zm0-13.553c-3.323 0-6.026 2.704-6.026 6.026s2.704 6.027 6.026 6.027c3.324 0 6.028-2.704 6.028-6.027s-2.704-6.026-6.028-6.026z"/><path fill="#8899A6" d="M27.279 34.429l-8.376-18.344c-.021-.046-.058-.076-.085-.117-.038-.059-.072-.118-.123-.169-.051-.051-.11-.085-.17-.123-.041-.027-.071-.064-.117-.085-.012-.005-.024-.003-.035-.008-.064-.027-.132-.034-.201-.047-.061-.011-.121-.03-.182-.03-.054 0-.106.018-.161.027-.075.013-.149.022-.219.051-.011.005-.023.003-.034.008-.044.02-.074.057-.114.082-.061.039-.121.074-.173.125-.051.051-.086.111-.124.171-.026.04-.063.07-.083.115L8.709 34.429c-.229.502-.008 1.096.494 1.325.135.061.276.09.415.09.379 0 .742-.217.91-.585l7.465-16.351 7.465 16.351c.168.368.531.585.911.585.139 0 .279-.029.414-.091.504-.229.725-.822.496-1.324z"/><path d="M12.9 36H7.079c-.552 0-1-.447-1-1s.448-1 1-1H12.9c.552 0 1 .447 1 1s-.448 1-1 1zm15.999 0h-5.82c-.553 0-1-.447-1-1s.447-1 1-1h5.82c.553 0 1 .447 1 1s-.447 1-1 1z" fill="#553788"/><path fill="#744EAA" d="M21.284 29.819c0 1.535-1.244 2.779-2.779 2.779h-1.112c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.534 0 2.779 1.244 2.779 2.779z"/><path fill="#CBB7EA" d="M21.227 29.263c-.257-1.269-1.378-2.224-2.723-2.224h-1.112c-1.345 0-2.466.954-2.724 2.224h6.559z"/><path fill="#5C913B" d="M11.017 26.527c0 1.535-1.244 2.779-2.779 2.779H7.126c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535 0 2.779 1.244 2.779 2.779z"/><path fill="#C6E5B3" d="M10.96 25.971c-.257-1.269-1.378-2.224-2.723-2.224H7.126c-1.345 0-2.466.954-2.724 2.224h6.558z"/><path fill="#3B94D9" d="M34.977 17.633c0 1.535-1.244 2.779-2.779 2.779h-1.112c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535-.001 2.779 1.243 2.779 2.779z"/><path fill="#BBDDF5" d="M34.921 17.077c-.257-1.269-1.378-2.224-2.723-2.224h-1.112c-1.344 0-2.466.954-2.723 2.224h6.558z"/><path fill="#5C913B" d="M31.644 7.887c0 1.535-1.244 2.779-2.779 2.779h-1.112c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535 0 2.779 1.244 2.779 2.779z"/><path fill="#C6E5B3" d="M31.588 7.331c-.257-1.269-1.378-2.224-2.723-2.224h-1.112c-1.344 0-2.466.954-2.723 2.224h6.558z"/><path fill="#BE1931" d="M31.644 26.527c0 1.535-1.244 2.779-2.779 2.779h-1.112c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535 0 2.779 1.244 2.779 2.779z"/><path fill="#F4ABBA" d="M31.588 25.971c-.257-1.269-1.378-2.224-2.723-2.224h-1.112c-1.344 0-2.466.954-2.723 2.224h6.558z"/><path fill="#BE1931" d="M11.017 7.887c0 1.535-1.244 2.779-2.779 2.779H7.126c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535 0 2.779 1.244 2.779 2.779z"/><path fill="#F4ABBA" d="M10.96 7.331c-.257-1.269-1.378-2.224-2.723-2.224H7.126c-1.345 0-2.466.954-2.724 2.224h6.558z"/><path fill="#744EAA" d="M21.284 2.876c0 1.535-1.244 2.779-2.779 2.779h-1.112c-1.535 0-2.779-1.244-2.779-2.779S15.858.097 17.393.097h1.112c1.534-.001 2.779 1.243 2.779 2.779z"/><path fill="#CBB7EA" d="M21.227 2.32C20.97 1.051 19.849.096 18.504.096h-1.112c-1.345 0-2.466.954-2.724 2.224h6.559z"/><path fill="#3B94D9" d="M7.682 17.633c0 1.535-1.244 2.779-2.779 2.779H3.79c-1.535 0-2.779-1.244-2.779-2.779s1.244-2.779 2.779-2.779h1.112c1.535-.001 2.78 1.243 2.78 2.779z"/><path fill="#BBDDF5" d="M7.625 17.077c-.257-1.269-1.378-2.224-2.723-2.224H3.79c-1.345 0-2.466.954-2.724 2.224h6.559z"/><path fill="#553788" d="M14.952 15.847c0-1.68 1.362-3.041 3.041-3.041 1.68 0 3.042 1.362 3.042 3.041s-1.362 3.041-3.042 3.041c-1.679.001-3.041-1.361-3.041-3.041z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3a2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a2.svg new file mode 100644 index 0000000000000000000000000000000000000000..256d8afb7df444628fdd21018e92a75ffef95075 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M32.612 16.645v-1h-4.083V8.333h-1v7.312h-3.11v1h3.11v4H18.55v-4.604h-1v4.604H12.8v1h4.75v4H8.612v-3.208h-1v3.208H2.205v1h5.407v4H2.205v1h5.407V36h1v-4.355h8.938V36h1v-4.355h8.979V36h1v-4.355h4.083v-1h-4.083v-4h4.083v-1h-4.083v-4h4.083v-1h-4.083v-4h4.083zm-24 14v-4h8.938v4H8.612zm18.917 0H18.55v-4h8.979v4zm0-5H18.55v-4h8.979v4z"/><path fill="#CCD6DD" d="M31.05 6.595h4V36h-4z"/><path fill="#8899A6" d="M34.05 6.595h1V36h-1z"/><path fill="#CCD6DD" d="M25.05 10.208l-4 2.417V36h4zm-14 10.709h4V36h-4zm-10 4.791h4V36h-4z"/><path fill="#8899A6" d="M4.05 25.708h1V36h-1zm10-4.791h1V36h-1zm10-10.709h1V36h-1z"/><path fill="#CCD6DD" d="M18.804 16.378C12.948 21.327 6.491 26.771 0 29.035v1.816c7.387-2.665 14.422-8.66 20.363-13.725 4.789-4.083 9.313-7.939 11.764-7.939 1.46 0 2.746.513 3.873 1.337V8.738c-1.11-.651-2.39-1.05-3.873-1.05-3.041 0-8.035 4.221-13.323 8.69z"/><path fill="#DD2E44" d="M32.127 4.688c-4.139 0-9.292 4.355-15.26 9.399C11.523 18.603 5.653 23.558 0 25.84v3.196c6.491-2.265 12.948-7.708 18.804-12.657 5.288-4.469 10.282-8.69 13.323-8.69 1.483 0 2.763.399 3.873 1.05v-3.36c-1.154-.438-2.439-.691-3.873-.691z"/><path fill="#1C6399" d="M10.912 14.422l-.368.29c-.142.112-.348.087-.459-.054l-.918-1.164c-.112-.142-.087-.348.054-.459l.368-.29c.142-.112.348-.087.459.054l.918 1.164c.112.142.088.347-.054.459zm3.438-2.632l-.368.29c-.142.112-.348.087-.459-.054l-.918-1.164c-.112-.142-.087-.348.054-.459l.368-.29c.142-.112.348-.087.459.054l.918 1.164c.112.142.088.347-.054.459zm6.52-5.208l-.368.29c-.142.112-.348.087-.459-.054l-.918-1.164c-.112-.142-.087-.348.054-.459l.368-.29c.142-.112.348-.087.459.054l.918 1.164c.113.141.088.347-.054.459zm3.471-2.664l-.368.29c-.142.112-.348.087-.459-.054l-.918-1.164c-.112-.142-.087-.348.054-.459l.368-.29c.142-.112.348-.087.459.054l.918 1.164c.112.141.088.347-.054.459zm-8.532 9.678c-.217 0-.433-.094-.581-.275-.262-.32-.215-.793.106-1.055l1.409-1.152c.321-.262.794-.216 1.056.106.262.32.215.793-.106 1.055l-1.409 1.152c-.14.113-.308.169-.475.169z"/><path fill="#EA596E" d="M9.349 14.069c.82 1.044.676 1.731.154 2.141-.522.41-1.224.387-2.044-.656-.82-1.043-1.062-2.222-.54-2.632.523-.411 1.61.103 2.43 1.147z"/><path fill="#A6D388" d="M12.745 11.401c.82 1.044.676 1.731.154 2.141-.522.41-1.224.387-2.044-.656-.82-1.043-1.062-2.222-.54-2.632.523-.411 1.61.103 2.43 1.147z"/><path fill="#3B94D9" d="M13.599 11.67l-5.892 4.629c-1.522 1.196-.604 4.01-.332 4.356.291.371.829.436 1.2.144l7.459-5.86c.742-.583.871-1.657.288-2.399l-.406-.517c-.583-.743-1.62-.901-2.317-.353z"/><path fill="#F4900C" d="M19.178 6.108c.82 1.044.676 1.731.154 2.141-.522.41-1.224.387-2.043-.657-.82-1.044-1.062-2.222-.539-2.632.521-.41 1.608.104 2.428 1.148z"/><path fill="#AA8DD8" d="M22.628 3.387c.82 1.044.676 1.731.154 2.141-.522.41-1.224.387-2.043-.657-.82-1.044-1.062-2.222-.539-2.632.521-.41 1.609.104 2.428 1.148z"/><path fill="#3B94D9" d="M23.429 3.709l-5.893 4.629c-1.522 1.195-.604 4.01-.332 4.356.291.371.829.436 1.2.144l7.46-5.859c.742-.583.871-1.657.288-2.399l-.406-.517c-.583-.743-1.621-.901-2.317-.354z"/><path fill="#E1E8ED" d="M9.096 20.838c-.148 0-.295-.066-.394-.192-.171-.217-.132-.532.086-.702l7.059-5.515c.215-.168.53-.132.701.086.171.217.132.532-.086.702l-7.059 5.515c-.09.072-.198.106-.307.106zm9.787-7.906c-.148 0-.295-.066-.394-.192-.171-.217-.132-.532.086-.702l7.059-5.515c.216-.169.53-.132.701.086.171.217.132.532-.086.702l-7.059 5.515c-.091.071-.199.106-.307.106z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3a8.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a8.svg new file mode 100644 index 0000000000000000000000000000000000000000..3bfdea0c95bfddbb194fb25b8462d2db414178ca --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3a8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M18 3.143c-9.941 0-18 6.908-18 15.428 0 1.066.126 2.107.367 3.112C2.146 24.744 3.377 22.812 9 20c5.727-2.864 0 4-2 8-.615 1.23-.282 2.271.56 3.124C10.506 32.928 14.104 34 18 34c9.941 0 18-6.907 18-15.429 0-8.52-8.059-15.428-18-15.428zm2.849 24.447c-.395 1.346-2.46 1.924-4.613 1.291-2.153-.632-3.578-2.234-3.183-3.581.395-1.346 2.46-1.924 4.613-1.29 2.153.631 3.578 2.233 3.183 3.58z"/><circle fill="#5C913B" cx="10" cy="11" r="3"/><circle fill="#269" cx="20" cy="9" r="3"/><circle fill="#DD2E44" cx="29" cy="15" r="3"/><circle fill="#FFCC4D" cx="28" cy="24" r="3"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3ac.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ac.svg new file mode 100644 index 0000000000000000000000000000000000000000..3a326766110ef0d29e5ad9ce6cb2d8b72df2c1b1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ac.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3F7123" d="M35.845 32c0 2.2-1.8 4-4 4h-26c-2.2 0-4-1.8-4-4V19c0-2.2 1.8-4 4-4h26c2.2 0 4 1.8 4 4v13z"/><path fill="#3F7123" d="M1.845 15h34v6h-34z"/><path fill="#CCD6DD" d="M1.845 15h34v7h-34z"/><path fill="#292F33" d="M1.845 15h4l-4 7v-7zm11 0l-4 7h7l4-7h-7zm14 0l-4 7h7l4-7h-7z"/><path fill="#CCD6DD" d="M.155 8.207L33.148 0l1.69 6.792L1.845 15z"/><path fill="#292F33" d="M.155 8.207l5.572 5.827L1.845 15 .155 8.207zm19.158 2.448l-5.572-5.828-6.793 1.69 5.572 5.828 6.793-1.69zm13.586-3.38l-5.572-5.828-6.793 1.69 5.572 5.827 6.793-1.689z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3af.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3af.svg new file mode 100644 index 0000000000000000000000000000000000000000..073817f2f3163eee059b35b9043a1c1e538c8afb --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3af.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#DD2E44" cx="18" cy="18" r="18"/><circle fill="#FFF" cx="18" cy="18" r="13.5"/><circle fill="#DD2E44" cx="18" cy="18" r="10"/><circle fill="#FFF" cx="18" cy="18" r="6"/><circle fill="#DD2E44" cx="18" cy="18" r="3"/><path opacity=".2" d="M18.24 18.282l13.144 11.754s-2.647 3.376-7.89 5.109L17.579 18.42l.661-.138z"/><path fill="#FFAC33" d="M18.294 19c-.255 0-.509-.097-.704-.292-.389-.389-.389-1.018 0-1.407l.563-.563c.389-.389 1.018-.389 1.408 0 .388.389.388 1.018 0 1.407l-.564.563c-.194.195-.448.292-.703.292z"/><path fill="#55ACEE" d="M24.016 6.981c-.403 2.079 0 4.691 0 4.691l7.054-7.388c.291-1.454-.528-3.932-1.718-4.238-1.19-.306-4.079.803-5.336 6.935zm5.003 5.003c-2.079.403-4.691 0-4.691 0l7.388-7.054c1.454-.291 3.932.528 4.238 1.718.306 1.19-.803 4.079-6.935 5.336z"/><path fill="#3A87C2" d="M32.798 4.485L21.176 17.587c-.362.362-1.673.882-2.51.046-.836-.836-.419-2.08-.057-2.443L31.815 3.501s.676-.635 1.159-.152-.176 1.136-.176 1.136z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3b2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b2.svg new file mode 100644 index 0000000000000000000000000000000000000000..408f2f9206f7a43a8540622720472e6ea3e44533 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A0041E" d="M4 11v.137c0-.042.011-.084.015-.126L4 11zm13 11.137c-.146-.067-.287-.145-.412-.246L4.565 12.245C4.188 11.94 4 11.539 4 11.137v12.238c0 2.042 1.093 2.484 1.093 2.484l11.574 9.099c.205.161.377.259.528.318-.114-.174-.195-.375-.195-.604V22.137zm-8.773.363c-.994 0-2.033-1.007-2.319-2.25-.287-1.242.287-2.249 1.28-2.249.994 0 2.033 1.007 2.319 2.249.287 1.243-.286 2.25-1.28 2.25zM13.81 30c-.994 0-2.033-1.008-2.319-2.25-.287-1.243.287-2.25 1.281-2.25s2.033 1.007 2.319 2.25c.286 1.242-.287 2.25-1.281 2.25z"/><path fill="#DD2E44" d="M31.435 12.161l-12.104 9.73c-.102.083-.214.152-.331.212v12.569c0 .233-.083.437-.2.614.155-.058.335-.16.548-.328 1.821-1.432 11.588-9.099 11.588-9.099S32 25.417 32 23.375V11.053c0 .402-.188.803-.565 1.108zm-7.457 16.731c-.242 1.137-1.119 2.058-1.958 2.058-.838 0-1.322-.921-1.08-2.058.242-1.137 1.118-2.058 1.957-2.058s1.322.921 1.081 2.058zm3.538-5.271c-.254 1.172-1.178 2.121-2.062 2.121-.883 0-1.392-.949-1.138-2.121.255-1.172 1.179-2.121 2.061-2.121.885 0 1.394.949 1.139 2.121zm3.063-5.105c-.251 1.115-1.163 2.017-2.035 2.017-.872 0-1.375-.902-1.123-2.017.251-1.113 1.162-2.016 2.034-2.016.873 0 1.376.903 1.124 2.016zm1.415-7.511c.001.016.006.032.006.048V11l-.006.005z"/><path fill="#EA596E" d="M31.435 9.945L19.289.5c-.753-.61-1.988-.61-2.742 0L4.565 10.029c-.338.273-.515.624-.551.983-.003.042-.014.083-.014.125 0 .402.188.803.565 1.108l12.023 9.646c.125.101.265.178.412.246v12.535c0 .229.081.43.194.604.181.28.466.474.806.474.336 0 .619-.19.8-.464.117-.176.2-.38.2-.614V22.103c.117-.06.229-.129.331-.212l12.104-9.73c.377-.305.565-.706.565-1.108 0-.016-.005-.032-.006-.049-.014-.385-.198-.767-.559-1.059zM18.5 8.667c1.61 0 2.916 1.044 2.916 2.333 0 1.289-1.306 2.333-2.916 2.333-1.611 0-2.916-1.044-2.916-2.333 0-1.289 1.305-2.333 2.916-2.333z"/><ellipse fill="#FFF" cx="18.5" cy="11" rx="2.916" ry="2.333"/><path fill="#FFF" d="M29.455 16.5c-.872 0-1.783.903-2.034 2.016-.252 1.115.251 2.017 1.123 2.017s1.784-.902 2.035-2.017c.252-1.113-.251-2.016-1.124-2.016zm-3.077 5c-.883 0-1.807.949-2.061 2.121-.254 1.172.255 2.121 1.138 2.121.884 0 1.808-.949 2.062-2.121.254-1.172-.255-2.121-1.139-2.121zm-3.482 5.334c-.839 0-1.715.921-1.957 2.058-.242 1.137.242 2.058 1.08 2.058.839 0 1.716-.921 1.958-2.058.242-1.137-.242-2.058-1.081-2.058z"/><path fill="#E1E8ED" d="M7.188 18.001c-.994 0-1.567 1.007-1.28 2.249.287 1.243 1.325 2.25 2.319 2.25s1.567-1.007 1.28-2.25c-.286-1.242-1.325-2.249-2.319-2.249zm5.583 7.499c-.994 0-1.567 1.007-1.281 2.25.287 1.242 1.326 2.25 2.32 2.25.994 0 1.567-1.008 1.281-2.25-.287-1.243-1.326-2.25-2.32-2.25z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3b6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b6.svg new file mode 100644 index 0000000000000000000000000000000000000000..f13b3b8bfb9a7fb4040ef7c7340ba2323d998902 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5DADEC" d="M14.182.168L7.818 1.469C7.368 1.561 7 2.012 7 2.471v15.857C6.387 18.12 5.712 18 5 18c-2.762 0-5 1.741-5 3.889 0 2.147 2.238 3.889 5 3.889 2.713 0 4.908-1.683 4.985-3.777H10V6.477l4.182-.855c.45-.092.818-.543.818-1.002V.835c0-.459-.368-.76-.818-.667zm21 4l-6.363 1.301c-.451.092-.819.543-.819 1.002v15.857c-.613-.209-1.288-.328-2-.328-2.762 0-5 1.741-5 3.889 0 2.147 2.238 3.889 5 3.889 2.713 0 4.908-1.683 4.985-3.777H31V10.477l4.182-.855c.45-.092.818-.543.818-1.002V4.835c0-.459-.368-.76-.818-.667z"/><path fill="#5DADEC" d="M23.182 10.167l-6.363 1.301c-.451.093-.819.544-.819 1.003v15.857c-.613-.209-1.288-.328-2-.328-2.762 0-5 1.741-5 3.889s2.238 3.889 5 3.889c2.713 0 4.908-1.683 4.985-3.777H19V16.477l4.182-.855c.45-.092.818-.543.818-1.002v-3.785c0-.459-.368-.76-.818-.668z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3b7.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b7.svg new file mode 100644 index 0000000000000000000000000000000000000000..ed0f849e0d997448da6ec8dcb5157a0eabe5aff3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill-rule="evenodd" clip-rule="evenodd" fill="#FCAB40" d="M14 16L9 26s-1 2 1 2c1 0 2-2 2-2L26 7s2-4 8-1v2c-3-1-4 1-4 1L15 33s-2 3-7 3c-6 0-7-5-7-8 0-2 1-4 2-6s-2-6-2-6h13z"/><path fill="#FDCB58" d="M7.5 20C4.04 20 0 18.952 0 16c0-2.953 4.04-4 7.5-4s7.5 1.047 7.5 4c0 2.952-4.04 4-7.5 4z"/><circle fill="#CCD6DD" cx="19" cy="17" r="2"/><circle fill="#CCD6DD" cx="22" cy="13" r="2"/><circle fill="#CCD6DD" cx="25" cy="9" r="2"/><path fill="#9AAAB4" d="M33.998 10c-.3 0-.605-.068-.893-.211l-2-1c-.988-.494-1.389-1.695-.895-2.684.493-.986 1.693-1.39 2.684-.895l2 1c.988.494 1.389 1.695.895 2.684-.351.701-1.057 1.106-1.791 1.106z"/><path fill-rule="evenodd" clip-rule="evenodd" fill="#FCAB40" d="M8.806 21.703l1.267-1.547 6.19 5.069-1.267 1.547z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3b8.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b8.svg new file mode 100644 index 0000000000000000000000000000000000000000..22074a11f3f0d4c8ee447a6f486050c6c0b529f3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3b8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M21.828 20.559C19.707 21.266 19 17.731 19 17.731s.965-.968.235-1.829c1.138-1.137.473-1.707.473-1.707-1.954-1.953-5.119-1.953-7.071 0-.246.246-.414.467-.553.678-.061.086-.115.174-.17.262l-.014.027c-.285.475-.491.982-.605 1.509-.156.319-.379.659-.779 1.06-1.414 1.414-4.949-.707-7.778 2.121-.029.029-.045.069-.069.104-.094.084-.193.158-.284.25-3.319 3.319-3.003 9.018.708 12.728 3.524 3.525 8.84 3.979 12.209 1.17.058-.031.117-.061.165-.109.071-.072.126-.14.193-.21.053-.049.109-.093.161-.143 1.693-1.694 2.342-3.73 2.086-5.811-.068-.99-.165-1.766.39-2.321.707-.707 2.828 0 4.242-1.414 2.117-2.122.631-3.983-.711-3.537z"/><path fill="#292F33" d="M14.987 18.91L30.326 3.572l2.121 2.122-15.339 15.339z"/><path fill="#F5F8FA" d="M10.001 29.134c1.782 1.277 1.959 3.473 1.859 4.751-.042.528.519.898.979.637 2.563-1.456 4.602-3.789 4.038-7.853-.111-.735.111-2.117 2.272-2.406 2.161-.29 2.941-1.099 3.208-1.485.153-.221.29-.832-.312-.854-.601-.022-2.094.446-3.431-1.136-1.337-1.582-1.559-2.228-1.604-2.473-.045-.245-1.409-3.694-2.525-1.864-.927 1.521-1.958 4.509-5.287 5.287-1.355.316-3.069 1.005-3.564 1.96-.832 1.604.46 2.725 1.574 3.483 1.115.757 2.793 1.953 2.793 1.953z"/><path fill="#292F33" d="M13.072 19.412l1.414-1.415 3.536 3.535-1.414 1.414zm-4.475 4.474l1.415-1.414 3.535 3.535-1.414 1.414z"/><path fill="#CCD6DD" d="M7.396 27.189L29.198 5.427l.53.531L7.927 27.72zm.869.868L30.067 6.296l.53.531L8.796 28.59z"/><path fill="#292F33" d="M9.815 28.325c.389.389.389 1.025 0 1.414s-1.025.389-1.414 0l-2.122-2.121c-.389-.389-.389-1.025 0-1.414h.001c.389-.389 1.025-.389 1.414 0l2.121 2.121z"/><circle fill="#292F33" cx="13.028" cy="29.556" r="1"/><path fill="#292F33" d="M14.445 31.881c0 .379-.307.686-.686.686-.379 0-.686-.307-.686-.686 0-.379.307-.686.686-.686.379 0 .686.307.686.686z"/><path fill="#BB1A34" d="M35.088 4.54c.415.415.415 1.095-.001 1.51l-4.362 3.02c-.416.415-1.095.415-1.51 0L26.95 6.804c-.415-.415-.415-1.095.001-1.51l3.02-4.361c.416-.415 1.095-.415 1.51 0l3.607 3.607z"/><circle fill="#66757F" cx="32.123" cy="9.402" r=".625"/><circle fill="#66757F" cx="33.381" cy="8.557" r=".625"/><circle fill="#66757F" cx="34.64" cy="7.712" r=".625"/><circle fill="#66757F" cx="26.712" cy="3.811" r=".625"/><circle fill="#66757F" cx="27.555" cy="2.571" r=".625"/><circle fill="#66757F" cx="28.398" cy="1.332" r=".625"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3ba.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ba.svg new file mode 100644 index 0000000000000000000000000000000000000000..454ab7818ac2416fe1936849740b9d35d9da045a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ba.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FCAB40" d="M5.622 33.051l-2.674-2.673L23.337 9.987c3.344-3.343 1.337-8.021 2.007-8.689.666-.67 1.335-.002 1.335-.002l8.023 8.023c.668.668 0 1.336 0 1.336-.669.67-5.778-.908-8.692 2.006L5.622 33.051z"/><path fill="#CCD6DD" d="M5.457 33.891c.925-.925.925-2.424 0-3.35-.924-.924-2.424-.924-3.349 0l.087.087c-.371-.334-.938-.331-1.296.027-.369.368-.369.968 0 1.336L4.008 35.1c.37.369.968.369 1.337 0 .355-.356.36-.919.032-1.29l.08.081z"/><path fill="#FCAB40" d="M13.31 33.709c-1.516 0-2.939-.59-4.011-1.661-1.071-1.07-1.661-2.495-1.661-4.011 0-1.515.59-2.939 1.661-4.011L19.995 13.33c1.071-1.071 2.496-1.661 4.012-1.661 1.515 0 2.94.59 4.011 1.661 2.211 2.212 2.211 5.811 0 8.022L17.322 32.047c-1.072 1.071-2.496 1.662-4.012 1.662zM24.007 15.45c-.506 0-.98.197-1.338.554L11.974 26.7c-.357.357-.554.832-.554 1.337 0 .506.197.979.553 1.336.358.357.832.555 1.337.555s.98-.197 1.337-.555l10.696-10.695c.737-.737.736-1.937-.001-2.674-.356-.357-.83-.554-1.335-.554z"/><path fill="#FCAB40" d="M25.344 24.026c.736.738 1.936.738 2.674 0 .738-.739.738-1.937 0-2.674l-8.022-8.023c-.739-.738-1.935-.738-2.673 0-.739.739-.739 1.937 0 2.675l8.021 8.022zm-4.012 4.011c.738.738 1.937.738 2.674 0 .738-.739.738-1.936.002-2.674l-8.023-8.023c-.739-.738-1.936-.738-2.675 0-.738.738-.738 1.936 0 2.675l8.022 8.022zm-4.01 4.011c.738.738 1.934.738 2.673 0 .738-.738.738-1.937 0-2.674l-8.021-8.022c-.739-.738-1.936-.738-2.675 0-.738.737-.738 1.935 0 2.674l8.023 8.022z"/><path fill="#CCD6DD" d="M14.648 13.329c.369.369.968.369 1.337 0l1.337-1.336c.369-.369.369-.968 0-1.338-.37-.369-.968-.369-1.337 0l-1.337 1.338c-.37.369-.37.967 0 1.336zm-4.011 4.012c.37.371.967.37 1.337 0l1.336-1.337c.37-.37.371-.967 0-1.337-.369-.37-.967-.37-1.337 0l-1.337 1.337c-.369.37-.369.968.001 1.337zm-4.012 4.012c.37.37.967.37 1.337 0l1.337-1.338c.37-.369.37-.967 0-1.337-.369-.369-.967-.369-1.336 0l-1.337 1.338c-.37.369-.37.967-.001 1.337z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3bb.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3bb.svg new file mode 100644 index 0000000000000000000000000000000000000000..efb7d5da7eeb55239d81d1e5d28e815214f73734 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3bb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F18F26" d="M23.912 12.087C22.219 10.394 20.318 9.5 18.415 9.5c-1.626 0-3.189.667-4.402 1.88-1.519 1.519-1.727 2.39-1.865 2.966-.071.295-.106.421-.255.57-.106.106-.155.256-.14.406.015.149.1.286.225.369.013.009.324.22.368.651.039.394-.13 1.08-1.16 2.11-.629.629-1.252.948-1.85.948-.981 0-1.649-.87-1.654-.877-.11-.15-.295-.226-.48-.197-.185.029-.337.159-.396.335-.221.663-.251.668-.535.709-.59.086-1.578.229-3.624 2.275C.972 23.32.381 25.412.939 27.693c.395 1.617 1.408 3.358 2.708 4.659 1.408 1.408 3.802 2.912 6.301 2.912 1.654 0 3.137-.643 4.406-1.912 2.045-2.046 2.189-3.033 2.274-3.624.042-.284.046-.313.71-.534.177-.06.307-.212.336-.396.029-.184-.046-.369-.196-.48-.008-.006-.805-.619-.873-1.527-.047-.638.27-1.302.944-1.976.963-.963 1.622-1.165 2.005-1.165.504 0 .746.357.752.366.08.13.216.216.368.234.142.016.303-.035.411-.144.149-.149.275-.185.57-.255.576-.139 1.446-.348 2.965-1.866 2.286-2.286 2.955-6.234-.708-9.898z"/><path fill="#292F33" d="M34 3L19 20l-3-3L33 2z"/><path fill="#642116" d="M13 27c-.256 0-.512-.098-.707-.293l-3-3c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l3 3c.391.391.391 1.023 0 1.414-.196.195-.452.293-.707.293z"/><path fill="#CCD6DD" d="M4.628 29.935L28.8 5.807l.53.531L5.16 30.466zm.869.869L29.67 6.676l.531.532L6.028 31.335z"/><path fill="#F18F26" d="M34.704 2.685c.438.438.438 1.155-.001 1.592l-3.186 3.186c-.438.438-1.155.438-1.593-.001l-1.39-1.389c-.438-.438-.438-1.155.001-1.592l3.187-3.186c.438-.438 1.155-.438 1.593 0l1.389 1.39z"/><path fill="#292F33" d="M2 32l4-5s1 0 2 1 1 2 1 2l-5 4-2-2z"/><circle fill="#642116" cx="33" cy="8" r="1"/><circle fill="#642116" cx="35" cy="6" r="1"/><circle fill="#642116" cx="28" cy="3" r="1"/><circle fill="#642116" cx="30" cy="1" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3be.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3be.svg new file mode 100644 index 0000000000000000000000000000000000000000..323e5c462ecfb8e493ba5c4c9e7237fe160506f2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3be.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#77B255" cx="18" cy="18" r="18"/><path fill="#A6D388" d="M26 18c0 6.048 2.792 10.221 5.802 11.546C34.42 26.42 36 22.396 36 18c0-4.396-1.58-8.42-4.198-11.546C28.792 7.779 26 11.952 26 18z"/><path fill="#FFF" d="M27 18c0-6.048 1.792-10.221 4.802-11.546-.445-.531-.926-1.028-1.428-1.504C27.406 6.605 25 10.578 25 18c0 7.421 2.406 11.395 5.374 13.05.502-.476.984-.973 1.428-1.504C28.792 28.221 27 24.048 27 18z"/><path fill="#A6D388" d="M10 18c0-6.048-2.792-10.22-5.802-11.546C1.58 9.58 0 13.604 0 18c0 4.396 1.58 8.42 4.198 11.546C7.208 28.22 10 24.048 10 18z"/><path fill="#FFF" d="M4.198 6.454C7.208 7.78 9 11.952 9 18c0 6.048-1.792 10.22-4.802 11.546.445.531.926 1.027 1.428 1.504C8.593 29.395 11 25.421 11 18c0-7.421-2.406-11.395-5.374-13.049-.502.476-.984.972-1.428 1.503z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3c0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c0.svg new file mode 100644 index 0000000000000000000000000000000000000000..24693956f6f9bce9329f4b7f8124fe5917514b4d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F4900C" cx="18" cy="18" r="18"/><path fill="#231F20" d="M36 17h-8.981c.188-5.506 1.943-9.295 4.784-10.546-.445-.531-.926-1.027-1.428-1.504-2.83 1.578-5.145 5.273-5.354 12.049H19V0h-2v17h-6.021c-.208-6.776-2.523-10.471-5.353-12.049-.502.476-.984.972-1.428 1.503C7.039 7.705 8.793 11.494 8.981 17H0v2h8.981c-.188 5.506-1.942 9.295-4.783 10.546.445.531.926 1.027 1.428 1.504 2.831-1.578 5.145-5.273 5.353-12.05H17v17h2V19h6.021c.209 6.776 2.523 10.471 5.354 12.05.502-.476.984-.973 1.428-1.504-2.841-1.251-4.595-5.04-4.784-10.546H36v-2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3c6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c6.svg new file mode 100644 index 0000000000000000000000000000000000000000..00457c31ea308ed51b7b4b4cace04f75aeeafb32 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M5.123 5h6C12.227 5 13 4.896 13 6V4c0-1.104-.773-2-1.877-2h-8c-2 0-3.583 2.125-3 5 0 0 1.791 9.375 1.917 9.958C2.373 18.5 4.164 20 6.081 20h6.958c1.105 0-.039-1.896-.039-3v-2c0 1.104-.773 2-1.877 2h-4c-1.104 0-1.833-1.042-2-2S3.539 7.667 3.539 7.667C3.206 5.75 4.018 5 5.123 5zm25.812 0h-6C23.831 5 22 4.896 22 6V4c0-1.104 1.831-2 2.935-2h8c2 0 3.584 2.125 3 5 0 0-1.633 9.419-1.771 10-.354 1.5-2.042 3-4 3h-7.146C21.914 20 22 18.104 22 17v-2c0 1.104 1.831 2 2.935 2h4c1.104 0 1.834-1.042 2-2s1.584-7.333 1.584-7.333C32.851 5.75 32.04 5 30.935 5zM20.832 22c0-6.958-2.709 0-2.709 0s-3-6.958-3 0-3.291 10-3.291 10h12.292c-.001 0-3.292-3.042-3.292-10z"/><path fill="#FFCC4D" d="M29.123 6.577c0 6.775-6.77 18.192-11 18.192-4.231 0-11-11.417-11-18.192 0-5.195 1-6.319 3-6.319 1.374 0 6.025-.027 8-.027l7-.001c2.917-.001 4 .684 4 6.347z"/><path fill="#C1694F" d="M27 33c0 1.104.227 2-.877 2h-16C9.018 35 9 34.104 9 33v-1c0-1.104 1.164-2 2.206-2h13.917c1.042 0 1.877.896 1.877 2v1z"/><path fill="#C1694F" d="M29 34.625c0 .76.165 1.375-1.252 1.375H8.498C7.206 36 7 35.385 7 34.625v-.25C7 33.615 7.738 33 8.498 33h19.25c.759 0 1.252.615 1.252 1.375v.25z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3c8.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c8.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f5530d29087a49910d198f9d2ebbf51e25a657b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3c8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M7.754 7.754C4.068 11.44 1.64 16.37.843 21.335l13.822 13.822c4.965-.797 9.895-3.225 13.581-6.911s6.114-8.616 6.911-13.581L21.335.843C16.37 1.64 11.44 4.068 7.754 7.754zm25.615-5.123C30.707 1.152 27.634.51 24.472.564l10.965 10.964c.053-3.162-.589-6.235-2.068-8.897zM2.631 33.369c2.662 1.479 5.736 2.121 8.898 2.067L.564 24.472c-.054 3.161.588 6.235 2.067 8.897z"/><path fill="#E1E8ED" d="M22.828 11.757l-2.414 2.414-.707-.707c-.391-.391-1.023-.391-1.414 0s-.391 1.024 0 1.414l.707.708L15.586 19l-.707-.707c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l.707.707-2.414 2.414-.707-.707c-.391-.391-1.023-.391-1.414 0s-.391 1.024 0 1.414l.707.707-1 1c-.391.392-.391 1.024 0 1.415s1.023.391 1.414 0l1-1 .707.707c.391.391 1.023.391 1.414 0 .391-.392.391-1.024 0-1.414l-.707-.707 2.414-2.414.707.707c.391.392 1.023.392 1.414 0 .391-.391.391-1.024 0-1.414L17 20.414 20.414 17l.707.707c.391.391 1.024.391 1.414 0 .391-.391.392-1.023 0-1.414l-.707-.707 2.414-2.414.707.707c.391.391 1.023.39 1.414 0 .391-.391.391-1.023 0-1.414l-.707-.707 1-1c.39-.391.39-1.023 0-1.414-.391-.391-1.024-.391-1.415 0l-1 1-.707-.707c-.39-.391-1.024-.391-1.414 0-.391.39-.391 1.023 0 1.414l.708.706zM.564 24.472l10.965 10.965c1.04-.018 2.088-.111 3.136-.279L.843 21.335c-.168 1.049-.261 2.096-.279 3.137zM24.472.564c-1.04.018-2.088.111-3.136.279l13.822 13.822c.168-1.049.261-2.096.279-3.136L24.472.564z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3d3.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d3.svg new file mode 100644 index 0000000000000000000000000000000000000000..6201ef5ae20b7784dd9abd3665d7764ffc6a8eb6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M23.106 5.971C17.615.48 8.384-.521 3.307 4.557-1.77 9.634-.77 18.865 4.721 24.356c3.554 3.554 7.785 4.323 11.707 3.058l-.015.013.13-.052c.264-.088.527-.179.788-.284.698-.238 1.734-.558 2.942-.806 1.848-.38 3.541 1.606 4.955 3.021 1.414 1.414 4.242 5.657 4.949 6.364.707.707 1.414 0 2.122-.707l.707-.707.707-.707c.707-.708 1.414-1.415.707-2.122-.707-.707-4.95-3.535-6.364-4.949-1.414-1.414-3.4-3.107-3.021-4.955.198-.965.441-1.815.653-2.481 1.974-4.222 1.537-8.952-2.582-13.071z"/><path fill="#D99E82" d="M15.564 27.655c.289-.07.578-.149.864-.241l-.015.013.13-.052c.264-.088.527-.179.788-.284.698-.238 1.734-.558 2.942-.806 1.848-.38 3.541 1.606 4.955 3.021 1.414 1.414 4.242 5.657 4.949 6.364.707.707 1.414 0 2.122-.707l.707-.707.707-.707c.707-.708 1.414-1.415.707-2.122-.707-.707-4.95-3.535-6.364-4.949-1.414-1.414-3.4-3.107-3.021-4.955.198-.965.441-1.815.653-2.481.357-.764.633-1.543.824-2.334L15.564 27.655z"/><path fill="#FFCC4D" d="M20.277 22.942l1.414-1.414 12.022 12.021-1.414 1.414z"/><circle fill="#CCD6DD" cx="31.5" cy="6.5" r="3.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3d4.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d4.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b78f31e4c6420922be523d3c210896511907f80 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M19.083 35.5L12.25 12.292s-1.42.761-2.604 1.637c-.313.231-1.977 2.79-2.312 3.04-1.762 1.315-3.552 2.841-3.792 3.167C3.083 20.76 0 36 0 36l19.083-.5z"/><path fill="#4B545D" d="M32 35l-5.5-19.75L18 4.542l-5.373 4.193-.971 1.172C11.25 10.688 10 15.25 10 15.25L8.75 20 3.252 30.054.917 34.791 32 35z"/><path fill="#FFF" d="M3.252 30.054s7.873-10.783 7.894-11.388C11.167 18.062 10 15.25 10 15.25L8.75 20 3.252 30.054z"/><path fill="#292F33" d="M12 34h2l2-15.75 1.234-1.797 3.578-5.234.094-1.469-3.287 4.454L15 17.752l-2.388 7.362L12 27l-1.791 3.134L8 34zm12.059-17.616l-1.965 5.897L21 26l2.792 7.625 3.552-.062S23 26.625 23 26c0-.12.625-2.687.625-2.687l1.094-4.531L25 17.25l-.941-.866z"/><path fill="#F1F1F1" d="M24.059 16.384l-1.778-.665-1.531.875-1.328-1.063-2.188.922 3.578-5.234zm2.871 7.379l-1.711-1.388-1.594.938 1.094-4.532 1.437 2.282z"/><path fill="#FFF" d="M22.094 22.281L21 26l-.25-2.417zM12 27l-1.791 3.134.353-2.431s.682-.578.938-.911c.255-.333 1.112-1.678 1.112-1.678L12 27zm3.208-11l2.411-1.796L15 17.752z"/><path fill="#292F33" d="M36 36s-.384-3.845-.854-7.083c-.369-2.543-2.757-6.303-4.099-7.115l-1.234-3.536-2.023-5.102-2.258-2.289-1.844-1.626-.505-.621L18 4.542l2.289 5.007.524 1.67 3.246 5.165.66 2.397 1.438 2.281.774 2.701L28 27.5 26 34l10 2z"/><path fill="#5C903F" d="M33.708 32.438c-1.345 0-4.958.562-5.458.562-2 0-4.25-1.75-5.25-1.75S19.406 33 17.406 33c-1.688 0-2.406-.812-4.719-.812-.748 0-4.096.871-4.812.781C6.052 32.741 5.115 32 4.656 32 2 32 0 36 0 36h36s-.875-3.562-2.292-3.562z"/><path fill="#F1F1F1" d="M12.627 8.735l2.123-.485.656 1.844 2.125-.875 2.758.33L18 2.25z"/><path fill="#A8B6C0" d="M23.183 8.628l-1.443-.243-1.451 1.164L18 2.25zM27.953 13l1.859 5.266-1.729-2.828-1.614-1.625-.938-2.938zm7.193 15.917S35 25.032 33.875 23.75 31 21.771 31 21.771l1.438 3.271 1.458 1.417 1.25 2.458z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3d5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d5.svg new file mode 100644 index 0000000000000000000000000000000000000000..7a2fb80eddb76559b1b462fa8ff43b8727cc2796 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3d5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#78B159" d="M18 25.18C3.438 25.18 0 29.844 0 32s1.791 4 4 4h28c2.209 0 4-1.851 4-4s-3.438-6.82-18-6.82z"/><path fill="#662113" d="M28.804 28.15c0 1.531-1.242 2.08-2.773 2.08-1.531 0-2.773-.548-2.773-2.08l.693-6.239c0-1.531.548-1.387 2.08-1.387 1.531 0 2.08-.145 2.08 1.387l.693 6.239z"/><path fill="#5C913B" d="M34.868 19.717c-4.59-4.135-6.449-10.056-8.837-10.056s-4.247 5.921-8.836 10.056c-1.929 1.738-1.01 2.743 1.634 2.542 2.357-.179 4.561-.741 7.202-.741s4.846.563 7.202.741c2.644.201 3.563-.805 1.635-2.542z"/><path fill="#3E721D" d="M33.377 18.078c-3.527-3.401-5.509-8.273-7.346-8.273-1.836 0-3.818 4.872-7.345 8.273-2.803 2.703 3.673 3.309 7.345 0 3.671 3.309 10.148 2.703 7.346 0z"/><path fill="#5C913B" d="M33.377 15.323c-3.527-3.178-5.509-7.729-7.346-7.729-1.836 0-3.818 4.551-7.345 7.729-2.803 2.525 3.673 3.091 7.345 0 3.671 3.091 10.148 2.524 7.346 0z"/><path fill="#3E721D" d="M31.766 13.066c-2.753-2.481-4.301-6.034-5.735-6.034-1.433 0-2.981 3.553-5.735 6.034-2.188 1.971 2.867 2.414 5.735 0 2.867 2.413 7.923 1.971 5.735 0z"/><path fill="#5C913B" d="M31.766 11.001c-2.753-2.481-4.301-6.034-5.735-6.034-1.433 0-2.981 3.553-5.735 6.034-2.188 1.971 2.867 2.414 5.735 0 2.867 2.414 7.923 1.972 5.735 0z"/><path fill="#3E721D" d="M30.659 9.168c-2.222-2.002-3.471-4.869-4.628-4.869s-2.406 2.867-4.628 4.869c-1.766 1.591 2.314 1.948 4.628 0 2.314 1.948 6.395 1.591 4.628 0z"/><path fill="#5C913B" d="M30.659 7.614c-2.222-2.002-3.471-4.869-4.628-4.869s-2.406 2.867-4.628 4.869c-1.766 1.591 2.314 1.948 4.628 0 2.314 1.948 6.395 1.591 4.628 0z"/><path fill="#3E721D" d="M29.553 5.326c-1.69-1.523-2.641-3.705-3.522-3.705-.88 0-1.831 2.182-3.522 3.705-1.344 1.211 1.761 1.482 3.522 0 1.761 1.483 4.866 1.211 3.522 0z"/><path fill="#5C913B" d="M29.553 4.29C27.863 2.767 26.912.585 26.031.585c-.88 0-1.831 2.182-3.522 3.705-1.344 1.211 1.761 1.482 3.522 0 1.761 1.482 4.866 1.211 3.522 0z"/><path fill="#F4900C" d="M15.101 33c-.424 0-.802-.267-.944-.666L9.145 18.301c-.11-.307-.063-.628.125-.896.188-.265.494-.405.82-.405h11.759c.401 0 .764.22.922.589l6.014 14.023c.133.31.101.661-.084.942-.188.282-.502.446-.839.446H15.101z"/><path fill="#FFCC4D" d="M4.075 33c-.337 0-.652-.17-.837-.45-.185-.282-.216-.638-.084-.948L9.172 17.56c.157-.368.521-.607.921-.607.401 0 .765.24.922.607l6.018 14.041c.133.311.1.666-.085.948-.185.281-.5.451-.837.451H4.075z"/><path fill="#292F33" d="M10.09 19.436L8.084 33h4.01z"/><path fill="#FFAC33" d="M14.127 31.887L14.575 33h-2.481zm-8.075 0L5.604 33h2.48z"/><path fill="#FFE8B6" d="M12.094 33s1.823-.465 2.714-1.288L10.09 19.436 12.094 33zm-4.01 0s-1.823-.465-2.714-1.288l4.719-12.277L8.084 33z"/><path fill="#E1E8ED" d="M13.625 5.625c-.018 0-.034.006-.052.006.034-.164.052-.333.052-.507 0-1.381-1.119-2.5-2.5-2.5-.891 0-1.667.469-2.11 1.171-.277-.106-.575-.17-.89-.17-1.275 0-2.315.957-2.469 2.19-.282-.113-.583-.19-.906-.19-1.381 0-2.5 1.119-2.5 2.5s1.119 2.5 2.5 2.5h8.875c1.381 0 2.5-1.119 2.5-2.5s-1.119-2.5-2.5-2.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3dd.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3dd.svg new file mode 100644 index 0000000000000000000000000000000000000000..d66d8d477b43a016ffe817f5a63d48c3716303e6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3dd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#3B88C3" cx="18" cy="30.54" rx="18" ry="5.36"/><path fill="#88C9F9" d="M33.812 28.538c0 1.616-2.5 2.587-14.482 2.587-10.925 0-13.612-.971-13.612-2.587s5.683-2.926 13.612-2.926 14.482 1.31 14.482 2.926z"/><path fill="#F4900C" d="M7 28.25c0-1 1-5 11-5 12 0 15 4 15 5s0 2-14 2c-12 0-12-1-12-2z"/><circle fill="#FFCC4D" cx="7" cy="6.25" r="5"/><circle fill="#FFAC33" cx="7" cy="6.25" r="4"/><path fill="#C1694F" d="M26.949 14.467c-.039-.575-.098-1.131-.177-1.662-.095-.636-.214-1.235-.347-1.797-.122-.517-.255-.999-.392-1.442-.205-.666-.417-1.243-.609-1.716-.377-.929-.674-1.46-.674-1.46l-2.583.333s.298.622.621 1.841c.131.495.265 1.09.386 1.784.061.351.118.724.17 1.125.072.558.131 1.167.173 1.823.024.37.041.756.053 1.158.004.146.011.287.013.437.007.469-.026.946-.084 1.422-.053.429-.13.856-.223 1.279-.133.606-.296 1.202-.479 1.77-.149.46-.308.901-.468 1.316-.246.637-.493 1.209-.707 1.687-.358.798-.622 1.33-.622 1.441 0 .351.25 1.007 2 1.444 2.736.684 3-.444 3-.444s.174-.528.376-1.567c.1-.513.206-1.147.303-1.915.058-.459.112-.964.158-1.513.049-.572.089-1.192.118-1.863.021-.508.034-1.051.039-1.615.002-.176.006-.346.006-.527 0-.459-.021-.903-.051-1.339z"/><path fill="#D99E82" d="M24.324 21.362c-1.003-.175-1.643-.467-1.994-.686-.246.637-.493 1.209-.707 1.687.655.356 1.487.64 2.389.796.521.091 1.038.136 1.523.136.296 0 .574-.023.841-.057.1-.513.206-1.147.303-1.915-.318.113-1.107.257-2.355.039zm.758-3.342c-.782-.077-1.383-.249-1.805-.43-.133.606-.296 1.202-.479 1.77.618.233 1.345.401 2.106.476.307.03.611.045.908.045.359 0 .7-.028 1.026-.071.049-.572.089-1.192.118-1.863-.45.098-1.08.152-1.874.073zm.221-1.524c.588 0 1.165-.059 1.692-.163.001-.176.005-.346.005-.527 0-.458-.021-.902-.051-1.339-.378.099-.919.194-1.682.205-.775-.003-1.32-.111-1.698-.219.004.146.011.287.013.437.007.469-.026.946-.084 1.422.545.115 1.148.181 1.76.184h.045zm-.178-3.273c.59-.085 1.137-.238 1.648-.418-.095-.636-.214-1.235-.347-1.797-.354.146-.857.308-1.56.409-.651.094-1.147.088-1.522.055.072.558.131 1.167.173 1.823.109.004.207.021.319.021.42 0 .857-.031 1.289-.093zm.909-3.658c-.206-.665-.418-1.242-.61-1.715-.317.159-.718.326-1.242.471-.568.158-1.027.221-1.395.243.131.495.265 1.09.386 1.784.487-.049.989-.128 1.497-.269.486-.135.937-.316 1.364-.514z"/><path fill="#3E721D" d="M34.549 2.943c-.032-.042-3.202-4.283-7.313-2.423-1.847.835-3.038 2.2-3.469 3.963-.804-1.125-2.026-1.839-3.644-2.127-4.421-.788-7.092 4.123-7.118 4.172-.039.072-.022.16.039.214.062.053.151.057.217.01.02-.015 2.037-1.427 5.396-.828 3.433.611 5.84 1.211 5.864 1.217.015.003.028.005.043.005.048 0 .095-.02.129-.056.022-.024 2.303-2.475 4.4-3.423 3.104-1.404 5.221-.472 5.24-.462.072.033.158.013.209-.049.051-.061.054-.148.007-.213z"/><path fill="#5C913B" d="M31.129 5.401c-3.134-1.655-5.57-.831-7.083.174-1.813-.351-5.201-.357-8.072 3.324-3.525 4.518-.433 10.152-.402 10.209.031.056.09.089.153.089l.021-.001c.071-.009.129-.06.147-.128.011-.039 1.097-3.967 3.843-7.27 1.501-1.805 3.293-3.474 4.554-4.573 1.27.211 3.136.678 4.969 1.702 3.573 1.998 5.212 5.379 5.228 5.413.032.066.101.112.177.099.074-.008.135-.062.151-.134.014-.063 1.392-6.222-3.686-8.904z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3e1.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3e1.svg new file mode 100644 index 0000000000000000000000000000000000000000..b44b7288b1d66a6f9f8160814250cca911e06dc3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3e1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M36 33.5c0 .828-.672 1.5-1.5 1.5h-33C.672 35 0 34.328 0 33.5S.672 32 1.5 32h33c.828 0 1.5.672 1.5 1.5z"/><path fill="#A0041E" d="M12.344 14.702h-2c-.276 0-.5-.224-.5-.5v-7c0-.276.224-.5.5-.5h2c.276 0 .5.224.5.5v7c0 .276-.224.5-.5.5z"/><path fill="#FFCC4D" d="M5.942 32c-.137-4.657-.506-8-.942-8-.435 0-.804 3.343-.941 8h1.883z"/><path fill="#77B255" d="M10 18.731C10 24.306 7.762 26 5 26c-2.761 0-5-1.694-5-7.269C0 13.154 4 5 5 5s5 8.154 5 13.731z"/><path fill="#FFE8B6" d="M8 16L21 3l13 13v16H8z"/><path fill="#FFCC4D" d="M21 16h1v16h-1z"/><path fill="#66757F" d="M34 17c-.256 0-.512-.098-.707-.293L21 4.414 8.707 16.707c-.391.391-1.023.391-1.414 0s-.391-1.023 0-1.414l13-13c.391-.391 1.023-.391 1.414 0l13 13c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293z"/><path fill="#66757F" d="M21 17c-.256 0-.512-.098-.707-.293-.391-.391-.391-1.023 0-1.414l6.5-6.5c.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414l-6.5 6.5c-.195.195-.451.293-.707.293z"/><path fill="#C1694F" d="M13 26h4v6h-4z"/><path fill="#55ACEE" d="M13 17h4v4h-4zm12.5 0h4v4h-4zm0 9h4v4h-4z"/><path fill="#77B255" d="M10.625 29.991c0 1.613-.858 2.103-1.917 2.103-1.058 0-1.917-.49-1.917-2.103 0-1.613 1.533-3.973 1.917-3.973s1.917 2.359 1.917 3.973zm25.25 0c0 1.613-.858 2.103-1.917 2.103-1.058 0-1.917-.49-1.917-2.103 0-1.613 1.533-3.973 1.917-3.973.384 0 1.917 2.359 1.917 3.973z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3ee.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..a825f2b79b1c33ff0715063e654d50705cb29b3e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M29 34c0 1.104-.896 2-2 2H9c-1.104 0-2-.896-2-2V2c0-1.104.896-2 2-2h18c1.104 0 2 .896 2 2v32z"/><path fill="#BE1931" d="M6.699 32h22.602C33.383 28.7 35 23.658 35 18c0-5.658-1.616-10.7-5.698-14H6.698C2.615 7.3 1 12.342 1 18c0 5.658 1.616 10.7 5.699 14z"/><path d="M1.301 22c.108.682.245 1.35.415 2h32.568c.17-.65.307-1.318.415-2H1.301zm-.229-2h33.855c.049-.657.073-1.324.073-2H1c0 .676.024 1.343.072 2zm31.605 8c.363-.64.684-1.306.956-2H2.367c.272.694.593 1.36.956 2h29.354zM2.366 10c-.254.646-.471 1.313-.651 2h32.569c-.18-.687-.397-1.354-.651-2H2.366zm-1.065 4c-.104.654-.179 1.321-.229 2h33.855c-.049-.679-.125-1.346-.229-2H1.301zm30.014 16H4.685c.591.721 1.26 1.391 2.014 2h22.602c.754-.609 1.422-1.279 2.014-2zM4.685 6c-.515.627-.964 1.298-1.363 2h29.356c-.398-.702-.849-1.373-1.362-2H4.685z" fill="#DD2E44"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3f7.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f7.svg new file mode 100644 index 0000000000000000000000000000000000000000..60462664ebd6ce6f68f7dab4c130eac73121f788 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFD983" d="M32.017 20.181L17.345 5.746C16.687 5.087 15.823 5 14.96 5H4.883C3.029 5 2 6.029 2 7.883v10.082c0 .861.089 1.723.746 2.38L17.3 35.017c1.311 1.31 3.378 1.31 4.688 0l10.059-10.088c1.31-1.312 1.28-3.438-.03-4.748zm-23.596-8.76c-.585.585-1.533.585-2.118 0s-.586-1.533 0-2.118c.585-.586 1.533-.585 2.118 0 .585.586.586 1.533 0 2.118z"/><path fill="#D99E82" d="M9.952 7.772c-1.43-1.431-3.749-1.431-5.179 0-1.431 1.43-1.431 3.749 0 5.18 1.43 1.43 3.749 1.43 5.18 0 1.43-1.431 1.429-3.749-.001-5.18zm-1.53 3.65c-.585.585-1.534.585-2.119 0-.585-.585-.586-1.534 0-2.119.585-.587 1.534-.585 2.119 0 .585.585.586 1.533 0 2.119z"/><path fill="#C1694F" d="M8.507 10.501c-.391.391-1.023.391-1.415 0-.391-.391-.39-1.023 0-1.414L15.577.602c.391-.391 1.023-.391 1.415 0 .391.391.39 1.023 0 1.414l-8.485 8.485z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3f8.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..143f8eaedb2dc2b49a82eb033b27915918ffbf40 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M30.385 29c.382.382.382 1.002 0 1.385-.383.382-1.003.382-1.385 0L15.5 16.884c-.382-.382-.382-1.002 0-1.384.382-.382 1.001-.382 1.384 0L30.385 29z"/><path fill="#292F33" d="M35.561 33.439c.586.586.586 1.536 0 2.121-.585.586-1.535.586-2.121 0l-5.656-5.656c-.586-.586-.586-1.536 0-2.121.585-.586 1.535-.586 2.121 0l5.656 5.656z"/><g fill="#99AAB5"><path d="M2.447 5.2l.707-.707L15.178 16.51l-.707.707zm1.417-2.83l.707-.707 12.728 12.728-.708.707z"/><path d="M1.035 9.441L9.52.956l.707.707-8.485 8.485zm.707 3.535L12.35 2.37l.707.707L2.449 13.684zm2.122 2.122L15.177 3.785l.707.707L4.571 15.805zm2.828 1.415l9.899-9.9.707.707-9.9 9.9zm2.828 1.413l8.485-8.485.707.707-8.485 8.486z"/><path d="M1.035 8.027l.707-.707L12.35 17.926l-.707.707zM7.4 1.663l.706-.707 10.607 10.606-.707.708z"/></g><path fill="#55ACEE" d="M2.468 2.468c-3.471 3.472-3.119 9.452.786 13.357 3.906 3.906 9.885 4.257 13.356.786 3.472-3.472 3.121-9.45-.786-13.356C11.919-.651 5.94-1.003 2.468 2.468zm12.846 12.846c-2.733 2.733-7.535 2.364-10.725-.825C1.4 11.3 1.032 6.499 3.765 3.765c2.734-2.734 7.535-2.364 10.724.825s3.559 7.991.825 10.724z"/><g fill="#269"><path d="M17.298 14.391c.391.391.39 1.024 0 1.414l-1.415 1.415c-.39.39-1.023.391-1.414 0s-.391-1.024 0-1.415l1.414-1.414c.391-.391 1.024-.391 1.415 0z"/><path d="M18.005 16.512c.391.391.391 1.024 0 1.415s-1.024.391-1.414 0l-.707-.707c-.391-.391-.39-1.024 0-1.415.391-.391 1.023-.391 1.415 0l.706.707z"/></g><path fill="#269" d="M29.56 27.44c.586.585-.122.828-.707 1.414-.586.585-.829 1.292-1.414.707-.586-.586-.586-1.536 0-2.121.585-.586 1.536-.586 2.121 0z"/><path fill="#BE1931" d="M21.81 3.182c-.781.781-.781 2.047 0 2.828l.707.707.707-.707 1.414-1.414.709-.707-.709-.707c-.779-.781-2.046-.781-2.828 0z"/><path fill="#99AAB5" d="M22.52 6.716l2.83-2.828.707.707-2.83 2.829z"/><path fill="#E1E8ED" d="M23.225 7.424l2.83-2.828c1.473.488 9.125 5.069 8.861 5.334-.758.759-1.912.201-1.912.201s.844.806.117 1.532-1.531-.118-1.531-.118.969.741.149 1.564c-.826.826-1.562-.149-1.562-.149s.729.981.098 1.613c-.633.631-1.514-.199-1.514-.199s.418.998-.342 1.756c-.362.364-4.609-7.33-5.194-8.706z"/><path d="M26.414 7.823c.578-.683 5.432 3.727 4.58 4.579-.853.851-5.275-3.759-4.58-4.579zm1.705 7.448c.68-.443-3.072-5.816-3.535-5.427-.031.026-.045.072-.053.126.883 1.626 2.006 3.594 2.824 4.867.336.342.616.53.764.434zm.272-9.233c-.391.462 4.984 4.214 5.427 3.535.115-.178-.17-.541-.656-.97-1.215-.782-2.856-1.767-4.285-2.571-.24-.065-.418-.074-.486.006zm-2.989 2.859c.426-.429 4.641 4.589 4.002 5.093-.638.5-4.515-4.576-4.002-5.093zm2.041-2.041c-.428.426 4.59 4.64 5.092 4.002.502-.639-4.574-4.516-5.092-4.002z" fill="#CCD6DD"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f3f9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..37922127ee96541d6de9e70fb22631ac479a0bd0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f3f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M21.279 4.28c-9 0-10.5 1.5-13 4s-4 4-4 13c0 11.181-2 14-1 14s3-2 3-4-2-13 5-20h-.001c7-6.999 18-5 20-5s4-2 4-3-2.818 1-13.999 1z"/><path fill="#D99E82" d="M29.5 29.779c0 .276-.224.5-.5.5H3.78c-.276 0-.5-.224-.5-.5s.224-.5.5-.5H29c.276 0 .5.224.5.5zm.279-.279c-.277 0-.5-.225-.5-.5V3.779c0-.276.223-.5.5-.5.275 0 .5.224.5.5V29c0 .275-.224.5-.5.5z"/><path fill="#99AAB5" d="M0 0l2.793 8.52L4.93 4.955l3.52-2.092z"/><path fill="#DD2E44" d="M26.087 27.393c.364 1.897 0 3.564-.812 3.719-.814.156-1.77-1.256-2.133-3.154-.364-1.898-.001-3.564.812-3.721.814-.157 1.769 1.257 2.133 3.156z"/><path fill="#F4900C" d="M26.568 28.465c.365 1.899 0 3.565-.812 3.721-.813.156-1.769-1.258-2.132-3.154-.365-1.9-.001-3.566.811-3.721.814-.157 1.77 1.255 2.133 3.154z"/><path fill="#A0041E" d="M27.958 29.854c.364 1.899 0 3.564-.812 3.721-.813.156-1.77-1.256-2.133-3.154-.364-1.898 0-3.564.812-3.721.814-.157 1.77 1.255 2.133 3.154z"/><path fill="#DD2E44" d="M29.372 31.268c.365 1.898 0 3.566-.812 3.721-.814.156-1.77-1.256-2.133-3.154-.364-1.899 0-3.564.812-3.721.814-.157 1.77 1.257 2.133 3.154zm-1.979-5.181c1.897.364 3.564 0 3.719-.812.156-.814-1.256-1.77-3.154-2.133-1.898-.364-3.564-.001-3.721.812-.157.814 1.257 1.769 3.156 2.133z"/><path fill="#F4900C" d="M28.465 26.568c1.899.365 3.565 0 3.721-.812.156-.813-1.258-1.769-3.154-2.132-1.9-.365-3.566-.001-3.721.811-.157.814 1.255 1.77 3.154 2.133z"/><path fill="#A0041E" d="M29.854 27.958c1.899.364 3.564 0 3.721-.812.156-.813-1.256-1.77-3.154-2.133-1.898-.364-3.564 0-3.721.812-.157.814 1.255 1.77 3.154 2.133z"/><path fill="#DD2E44" d="M31.268 29.372c1.898.365 3.566 0 3.721-.812.156-.814-1.256-1.77-3.154-2.133-1.899-.364-3.564 0-3.721.812-.157.814 1.257 1.77 3.154 2.133z"/><path fill="#CCD6DD" d="M30.385 29c.382.382.382 1.002 0 1.385-.383.382-1.003.382-1.385 0L4.136 5.52c-.382-.382-.382-1.002 0-1.384.382-.382 1.001-.382 1.384 0L30.385 29z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f40a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f40a.svg new file mode 100644 index 0000000000000000000000000000000000000000..a9a6debcc432f4b1a9b0c8ecf643efff6ea5188b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f40a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M19 32c0 1-1.723 3-3.334 3C14.056 35 14 33.657 14 32s1.306-3 2.916-3C18.527 29 19 30.343 19 32zm11 0c0 1-1.723 3-3.334 3C25.056 35 25 33.657 25 32s1.306-3 2.916-3C29.527 29 30 30.343 30 32z"/><path fill="#5C913B" d="M36 25c0-6-3.172-9.171-6-12-1-1-1.399.321-1 1 .508.862 3 8-2 8h-2c-5 0-6.172-1.172-9-4-4.5-4.5-7 0-9 0-6 0-7-1.812-7 2 0 3 3 4 6 4s3 1 5 4c1.071 1.606 2.836 3.211 5.023 4.155.232 1.119 2.774 3.845 4.311 3.845C21.944 36 22 34.657 22 33h5c.034 0 .066-.01.101-.01.291.005.587.01.899.01 0 1 1.723 3 3.334 3C32.944 36 33 34.657 33 33c0-.302-.057-.587-.137-.861C34.612 31.193 36 29.209 36 25z"/><path fill="#292F33" d="M10 18.123c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0-.829-.671 0-1.5 0s-1.5-.829-1.5 0z"/><g fill="#77B255"><ellipse cx="27.5" cy="24" rx="1.5" ry="1"/><ellipse cx="23.5" cy="24" rx="1.5" ry="1"/><ellipse cx="19.5" cy="24" rx="1.5" ry="1"/><ellipse cx="21.5" cy="26" rx="1.5" ry="1"/><ellipse cx="25.5" cy="26" rx="1.5" ry="1"/></g><path fill="#FFF" d="M6 22c-.389 0-1-1-1-1h2s-.611 1-1 1zm-2 .469C3.611 22.469 3 21 3 21h2s-.611 1.469-1 1.469zM2 23c-.389 0-1-2-1-2h2s-.611 2-1 2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f40c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f40c.svg new file mode 100644 index 0000000000000000000000000000000000000000..2c63658289aed773788eadf6d30e235b49022893 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f40c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#9266CC" d="M9 15.561c0-4 2-8 0-10s-3 2-2 2c1.414 0 2 2 1 5s1 3.999 1 3zm-3.875 0c0-4 2-8 0-10s-3 2-2 2c1.414 0 2 2 1 5s1 3.999 1 3z"/><path fill="#AA8DD8" d="M36 34.936c0 1-1 1-2 1H11c-5 0-7.272-3.09-8-6-1-4 2-11 0-12s-3-1-3-3 4.47-5.265 7-4c4 2 2.767 6.932 2 10-.88 3.522 1.115 3.594 5 5 4.94 1.787 12.32 4.44 14 5 3 1 8 3 8 4z"/><path fill="#FFCC4D" d="M10.925 24.935c2.887 1 3.849 9 13.472 9 6.377 0 8.66-5.479 8.66-11 0-5.523-5.17-10-11.547-10-6.377.001-11.498 11.684-10.585 12z"/><path fill="#FFAC33" d="M24.914 33.938c1.708 0 3.389-.48 4.892-1.418 2.185-1.361 3.729-3.527 4.348-6.098 1.53-6.363-2.206-12.834-8.329-14.425-7.393-1.923-14.919 2.768-16.768 10.455-.258 1.072.369 2.158 1.399 2.426 1.027.271 2.076-.383 2.335-1.455 1.334-5.546 6.761-8.93 12.1-7.544 4.063 1.056 6.544 5.351 5.528 9.574-.369 1.533-1.29 2.826-2.594 3.639-1.305.812-2.836 1.051-4.311.666-1.08-.279-1.991-.98-2.564-1.973-.572-.994-.74-2.158-.469-3.281.19-.795.668-1.465 1.344-1.887.676-.421 1.527-.707 2.234-.345 1.298.665 1.298 2.665.336 3.665-.752.781 1.604 1.065 2.887 0 1.15-.955 1.645-2.492 1.068-4.199-.581-1.724-1.805-2.942-3.358-3.347-1.762-.458-3.59-.176-5.148.797-1.557.971-2.657 2.515-3.098 4.347-.519 2.158-.199 4.398.903 6.307 1.103 1.91 2.853 3.258 4.931 3.797.775.199 1.558.299 2.334.299z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f40d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f40d.svg new file mode 100644 index 0000000000000000000000000000000000000000..17531783ba93dcebfc00e6cf8534336308031fff --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f40d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M11.84 7.634c-.719 0-2.295 2.243-3.567 1.029-.44-.419 1.818-1.278 1.727-2.017-.075-.607-2.842-1.52-1.875-2.099.967-.578 2.418.841 3.513.866 2.382.055 4.212-.853 4.238-.866.541-.274 1.195-.052 1.464.496.27.547.051 1.213-.488 1.486-.131.066-2.225 1.105-5.012 1.105z"/><path fill="#77B255" d="M27.818 36c-3.967 0-8.182-2.912-8.182-8.308 0-1.374-.89-1.661-1.637-1.661-.746 0-1.636.287-1.636 1.661 0 5.396-4.216 8.308-8.182 8.308S0 33.23 0 27.692C0 14.4 14.182 12.565 14.182 14.4c0 1.835-7.636-1.107-7.636 12.185 0 2.215.89 2.769 1.636 2.769.747 0 1.637-.287 1.637-1.661 0-5.395 4.215-8.308 8.182-8.308 3.966 0 8.182 2.912 8.182 8.308 0 1.374.89 1.661 1.637 1.661s1.636-.287 1.636-1.661V11.077c0-3.855-3.417-4.431-5.454-4.431 0 0-3.272 1.108-6.545 1.108s-4.364-2.596-4.364-4.431C13.091 1.488 17.455 0 24 0c6.546 0 12 4.451 12 11.077v16.615C36 33.088 31.784 36 27.818 36z"/><circle fill="#292F33" cx="19" cy="3" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f417.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f417.svg new file mode 100644 index 0000000000000000000000000000000000000000..ad7a77db82d7c72678652d82968fb5a764e06835 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f417.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M33.359 13.254c1.434-3.462 2.06-11.534 1.262-12.004-.704-.416-5.641 1.084-8.34 3.205C23.883 2.909 21.085 2 18 2c-3.085 0-5.883.91-8.281 2.455C7.02 2.334 2.082.834 1.378 1.25c-.797.47-.171 8.543 1.263 12.004C1.59 15.818 1 18.623 1 21.479 1 31.468 2 36 18 36s17-4.532 17-14.521c0-2.856-.59-5.662-1.641-8.225z"/><path fill="#662113" d="M32.878 12.157c.929-3.252 1.081-7.708.524-8.037-.411-.243-2.78.633-5.009 1.972 1.851 1.663 3.373 3.736 4.485 6.065zM7.607 6.092c-2.23-1.339-4.599-2.215-5.01-1.972-.557.329-.405 4.786.525 8.038 1.112-2.33 2.634-4.402 4.485-6.066z"/><path fill="#E1E8ED" d="M7.65 29s-3.641-3-4.641-11.5c-.234-1.986 1.696-1.977 2 0C6.01 24 11.359 28 14 30c2.255 1.708-6.35-1-6.35-1zm20.7 0s3.641-3 4.641-11.5c.234-1.986-1.695-1.977-2 0C29.99 24 24.641 28 22 30c-2.255 1.708 6.35-1 6.35-1z"/><path d="M29 29c0 1.104-3.82 3-11 3S7 30.104 7 29s3.82 1 11 1 11-2.104 11-1z"/><path fill="#662113" d="M28 23.125c0 4.487-3.097 9.375-10 9.375-6.904 0-10-4.888-10-9.375S11.096 17.5 18 17.5c6.903 0 10 1.138 10 5.625z"/><path fill="#C1694F" d="M15 24.6c0 1.857-.34 2.4-1.5 2.4s-1.5-.543-1.5-2.4c0-1.856.34-2.399 1.5-2.399s1.5.542 1.5 2.399zm9 0c0 1.857-.34 2.4-1.5 2.4s-1.5-.543-1.5-2.4c0-1.856.34-2.399 1.5-2.399s1.5.542 1.5 2.399z"/><path fill="#292F33" d="M13 15.002c0 1.104-.896 2-2 2s-2-.896-2-2S9.896 13 11 13s2 .898 2 2.002zm14 0c0 1.104-.896 2-2 2s-2-.896-2-2S23.896 13 25 13s2 .898 2 2.002z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f418.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f418.svg new file mode 100644 index 0000000000000000000000000000000000000000..fb9656cd18f0b1cfc279b91da21e3fcc6ad458c1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f418.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M34.453 15.573c-.864-7.3-5.729-10.447-13.93-10.447-.391 0-.763.017-1.139.031-.013-.01-.022-.021-.035-.031C14.655 1.605 4.091 2.779 1.745 6.3c-3.255 4.883-1.174 22.3 0 24.646 1.173 2.35 4.694 3.521 5.868 2.35 1.174-1.176 0-1.176-1.173-3.521-.85-1.701-.466-5.859.255-8.471.028.168.068.322.1.486.39 2.871 1.993 7.412 1.993 9.744 0 3.564 2.102 4.107 4.694 4.107 2.593 0 4.695-.543 4.695-4.107 0-.24-.008-.463-.012-.695.757.064 1.535.107 2.359.107.497 0 .977-.016 1.448-.039-.004.209-.013.41-.013.627 0 3.564 2.103 4.107 4.694 4.107 2.593 0 4.695-.543 4.695-4.107 0-1.801 1.192-4.625 2.039-6.982.159-.354.291-.732.42-1.117.118 1.307.193 2.706.193 4.206 0 .553.447 1 1 1s1-.447 1-1c0-5.153-.771-9.248-1.547-12.068z"/><path fill="#66757F" d="M19.35 5.126S23 10.641 20 15.641c-3 5-7.838 5-11 5-2 0-1 2 0 2 1.414 0 8.395 1.211 12-6 3-6-1.65-11.515-1.65-11.515z"/><circle fill="#292F33" cx="6.5" cy="14.141" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f419.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f419.svg new file mode 100644 index 0000000000000000000000000000000000000000..d915a8fd2e6b69de2367f55e0b2fcc5639872a0f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f419.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#553788" d="M10 12c3 5 0 10.692-3 9.692s-4 2-1 3 9.465-.465 13-4c1-1 2-1 2-1L10 12z"/><path fill="#553788" d="M26 12c-3 5 0 10.692 3 9.692s4 2 1 3-9.465-.465-13-4c-1-1-2-1-2-1L26 12z"/><path fill="#744EAA" d="M30.188 16c-3 5 0 10.692 3 9.692s4 2 1 3-9.465-.465-13-4c-1-1-2-1-2-1l11-7.692zM5.812 16c3 5 0 10.692-3 9.692s-4 2-1 3 9.465-.465 13-4c1-1 2-1 2-1L5.812 16z"/><path fill="#9266CC" d="M33.188 31.375c-2.729.91-6.425-5.626-4.812-10.578C30.022 17.554 31 13.94 31 11c0-7.18-5.82-11-13-11S5 3.82 5 11c0 2.94.978 6.554 2.624 9.797 1.613 4.952-2.083 11.488-4.812 10.578-3-1-4 3-1 4s8.31-.627 12-4c2.189-2 4.189-2 4.189-2s2 0 4.188 2c3.69 3.373 9 5 12 4s1.999-5-1.001-4z"/><circle fill="#292F33" cx="14" cy="21" r="2"/><circle fill="#292F33" cx="22" cy="21" r="2"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f41a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f41a.svg new file mode 100644 index 0000000000000000000000000000000000000000..804ece8811a339488d8d6c2a2509ee9acf682f42 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f41a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M29.049 7.033c-.07-.07-.141-.126-.211-.188-1.08-1.087-2.497-1.564-4.008-1.373l-3.812.483c-.382-3.003-2.25-4.446-4.351-4.181l-4.24.536C12.075.767 11.011.034 9.827.185L5.033.79C3.71.958 2.773 2.438 2.94 4.097l.606 6.007c.152 1.501 1.425 2.591 2.403 2.693l.514 5.093c.258 2.553 2.509 4.365 4.117 4.38l.498 4.926c.164 1.622.928 3.027 1.917 4.063.23.339.471.656.737.922 4.423 4.423 12.183 5.064 16.607.64 4.42-4.422 3.133-21.365-1.29-25.788z"/><path fill="#66757F" d="M30.609 14.396c.801 2.371 1.545 11.57-1.532 15.543-3.079 3.972-8.043-1.389-5.312-6.205 2.73-4.814 6.036-11.733 6.844-9.338z"/><path fill="#99AAB5" d="M21.018 5.954c.009.072.028.133.036.206.318 3.154-7.686 15.799-10.204 16.119-.085.011-.181-.008-.271-.008l.401 3.971c3.694-1.936 12.412-15.71 13.087-20.673l-3.049.385zm-8.59-3.645c.042.182.079.369.1.574.197 1.942-4.732 9.725-6.28 9.923-.094.012-.196.001-.299-.009l.353 3.502c2.78-2.096 8.093-10.489 9.094-14.365l-2.968.375z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f41b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f41b.svg new file mode 100644 index 0000000000000000000000000000000000000000..f8986dd7818b99db1b3b5363736bb1b9dc950d61 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f41b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#AA8DD8" d="M7.415 4c1-1 .25-4-1.438-4s-1.562 2-.562 2 1 2 1 3 1-1 1-1zM3.232 5.72c1-1 .25-4-1.438-4s-1.562 2-.562 2 1 2 1 3 1-1 1-1z"/><path fill="#744EAA" d="M29.607 32.856c.189.808 1.227 2.28 2.032 2.091.806-.19 1.077-1.971.888-2.777-.189-.808-.998-1.307-1.804-1.117-.805.19-1.306.997-1.116 1.803zm-5.434.649c.003.83.681 2.498 1.509 2.495.828-.004 1.494-1.677 1.491-2.506-.003-.829-.677-1.497-1.505-1.495-.828.004-1.498.677-1.495 1.506zm-5.271-2.446c-.326.764-.365 2.563.396 2.89.763.324 2.037-.947 2.363-1.71.325-.762-.028-1.643-.789-1.97-.762-.325-1.643.027-1.97.79zm-5.031-11.04c-.812.172-2.308 1.173-2.139 1.983.173.81 1.945 1.124 2.757.953.811-.171 1.329-.967 1.16-1.777-.172-.81-.965-1.33-1.778-1.159zm-2.037-5c-.812.172-2.308 1.173-2.139 1.983.173.81 1.945 1.124 2.757.953.811-.171 1.329-.967 1.16-1.777-.172-.81-.966-1.33-1.778-1.159z"/><path fill="#9266CC" d="M27.244 34c2.831 0 4.926-.877 5.266-1.027 2.271-1.01 3.293-3.669 2.284-5.939-.999-2.25-3.616-3.275-5.872-2.314-.133.05-1.793.649-3.343-.072-1.851-.861-2.995-3.309-3.628-5.209-.144-.43-.385-1.274-.686-2.316-1.866-6.471-2.832-8.285-3.983-9.82C13.571 2.352 7.69 2.007 4.799 2.587c-2.437.487-4.018 2.858-3.53 5.295.488 2.438 2.86 4.02 5.296 3.53.162-.026 2.204-.306 3.424 1.169.643 1.287 2.08 5.128 2.63 7.034.346 1.199.629 2.171.794 2.667 1.773 5.317 4.666 8.893 8.603 10.629C23.868 33.729 25.67 34 27.244 34z"/><circle fill="#FFF" cx="6.682" cy="5" r="1"/><path d="M30.923 32.964c-.089 0-.18-.012-.269-.036-.532-.148-.844-.699-.696-1.231.757-2.722-.77-4.542-.785-4.56-.359-.419-.312-1.051.107-1.41.418-.359 1.051-.312 1.41.107.092.107 2.234 2.66 1.195 6.397-.122.443-.525.733-.962.733zm-7.199-.563c-.245 0-.49-.089-.684-.27-.403-.378-.424-1.011-.047-1.414 1.485-1.587 1.453-4.193 1.452-4.22-.016-.552.419-1.012.972-1.028.542-.005 1.013.419 1.028.972.004.139.073 3.437-1.991 5.644-.197.21-.464.316-.73.316zm-8.542-8.696c-.48 0-.904-.347-.985-.837-.09-.544.278-1.06.823-1.149 3.074-.51 4.774-2.377 4.791-2.396.365-.41.998-.449 1.409-.084.412.365.453.993.091 1.406-.087.099-2.156 2.415-5.964 3.046-.056.01-.111.014-.165.014zm2.921 4.857c-.425 0-.819-.272-.954-.698-.166-.526.126-1.089.652-1.255 2.693-.853 3.88-2.83 3.892-2.85.28-.477.892-.637 1.368-.357.477.279.636.893.357 1.368-.063.108-1.595 2.663-5.013 3.744-.101.033-.203.048-.302.048zm-4.619-10.67c-.496 0-.927-.369-.991-.875-.069-.548.319-1.048.867-1.118 2.689-.34 4.657-1.971 4.676-1.988.422-.354 1.053-.303 1.408.119.356.421.305 1.05-.115 1.407-.097.083-2.42 2.029-5.718 2.446-.043.006-.085.009-.127.009zm-1.821-4.767c-.425 0-.819-.273-.954-.701-.165-.527.127-1.088.654-1.254 3.13-.983 4.253-2.692 4.299-2.764.295-.462.911-.605 1.375-.312.465.292.611.899.324 1.366-.06.097-1.506 2.396-5.399 3.619-.099.031-.2.046-.299.046z" fill="#744EAA"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f41d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f41d.svg new file mode 100644 index 0000000000000000000000000000000000000000..31e78828044a0d561337e83fe57711cdd049fd95 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f41d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#31373D" d="M27.816 23.464c.299-1.148.465-2.318.465-3.464 0-4.161-2.122-6.779-5.258-8.035.417-1.008.665-2.108.665-3.2 0-1.581-.495-2.498-1.315-3.032 1.091-.482 2.517-1.5 3.027-2.011.781-.781.94-1.889.354-2.475-.586-.586-1.693-.428-2.475.354-.611.611-1.948 2.53-2.223 3.619C20.172 5.025 19.126 5 18 5c-1.125 0-2.172.025-3.055.219-.275-1.089-1.612-3.007-2.223-3.619-.781-.781-1.889-.94-2.475-.354-.585.587-.427 1.694.354 2.476.511.511 1.937 1.529 3.027 2.011-.821.533-1.316 1.451-1.316 3.032 0 1.093.248 2.192.665 3.2C9.841 13.221 7.719 15.839 7.719 20c0 1.146.167 2.317.465 3.464v.023l.006-.003c1.209 4.621 4.643 8.847 8.812 9.44L17 33c0 1.657.448 3 1 3 .553 0 1-1.343 1-3 0-.026-.002-.049-.003-.075 4.169-.593 7.604-4.819 8.813-9.44l.006.003v-.024z"/><path d="M14.624 19h6.752c-1.462-1.424-2.615-2.881-3.106-4h-.54c-.491 1.119-1.644 2.576-3.106 4zm-5.378 4c-.361.187-.715.349-1.062.488.32 1.219.799 2.407 1.401 3.512h16.83c.602-1.105 1.082-2.293 1.401-3.512-.347-.139-.701-.301-1.063-.488H9.246zm3.593 8c1.518 1.234 3.278 2 5.161 2 1.884 0 3.643-.766 5.162-2H12.839z" fill="#FFCC4D"/><path fill="#CCD6DD" d="M18 13.505c0 2.647-7.858 8.584-12 8.584s-6-2.443-6-5.09c0-2.646 1.858-4.495 6-4.495 4.143.001 12-1.644 12 1.001zm0 0c0 2.647 7.857 8.584 12 8.584s6-2.443 6-5.09c0-2.646-1.857-4.495-6-4.495s-12-1.644-12 1.001z"/><path fill="#99AAB5" d="M2 19c-.552 0-1-.447-1-1 0-.551.446-.999.998-1 .048 0 4.949-.07 13.596-3.914.505-.227 1.096.002 1.32.507.225.505-.003 1.096-.507 1.32C7.317 18.953 2.213 19 2 19zm32 0c-.213 0-5.316-.047-14.406-4.086-.505-.224-.731-.815-.508-1.32.225-.504.817-.732 1.32-.507C29.054 16.93 33.954 17 34.003 17c.551.003.997.452.996 1.003-.002.551-.448.997-.999.997z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f41e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f41e.svg new file mode 100644 index 0000000000000000000000000000000000000000..f314ca9a208e716fd34c1fef85394e8c19d7eca5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f41e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path d="M35 21H1c-.552 0-1-.447-1-1s.448-1 1-1h34c.553 0 1 .447 1 1s-.447 1-1 1zm-22.177-2l-.069-.002c-.092-.007-9.214-.714-10.734-8.235-.109-.542.241-1.069.782-1.178.543-.113 1.069.241 1.178.782 1.221 6.044 8.833 6.631 8.91 6.636.551.038.967.515.93 1.066-.036.527-.476.931-.997.931zM3 31c-.142 0-.286-.03-.423-.094-.5-.234-.716-.829-.482-1.33 3.166-6.77 11.038-7.721 11.372-7.758.548-.056 1.042.334 1.103.882.062.548-.332 1.043-.88 1.106-.071.008-7.099.876-9.783 6.617-.171.364-.532.577-.907.577zm19.753-12c-.522 0-.961-.405-.996-.934-.036-.551.381-1.027.931-1.064.081-.005 8.116-.617 9.332-6.636.108-.541.633-.895 1.179-.782.541.109.892.637.782 1.178-1.521 7.525-10.769 8.21-11.162 8.235l-.066.003zm10.248 12c-.377 0-.737-.213-.907-.576-2.694-5.763-10.124-6.609-10.198-6.617-.55-.058-.948-.55-.89-1.099.058-.55.555-.952 1.099-.89.352.037 8.634.983 11.802 7.758.233.501.018 1.096-.482 1.33-.139.064-.282.094-.424.094z" fill="#31373D"/><path fill="#31373D" d="M24.989 7.766c-.069-2.626-1.277-4.216-3.095-5.04C21.961 2.5 22 2.257 22 2c0-1.105-.672-2-1.5-2S19 .895 19 2c0 .015.003.028.003.043C18.675 2.017 18.342 2 18 2s-.675.017-1.003.043c0-.015.003-.028.003-.043 0-1.105-.671-2-1.5-2S14 .895 14 2c0 .257.04.5.106.726-1.817.824-3.025 2.414-3.095 5.04C7.98 9.551 6 12.662 6 17c0 7.159 5.373 16.923 12 16.923 6.628 0 12-9.764 12-16.923 0-4.338-1.98-7.45-5.011-9.234z"/><path fill="#DD2E44" d="M16.001 34.959C9.564 34.364 4.5 28.064 4.5 20.378 4.5 12.693 9.564 9.597 16 9c.33-.03 1-.046 1 2.294v22.541c0 1.171-.669 1.156-.999 1.124zm3.998 0c6.436-.595 11.501-6.895 11.501-14.581C31.5 12.693 26.435 9.597 20 9c-.33-.03-1-.046-1 2.294v22.541c0 1.171.67 1.156.999 1.124z"/><g fill="#31373D"><circle cx="13" cy="15" r="2"/><circle cx="10" cy="22" r="3"/><circle cx="13" cy="29" r="2"/><circle cx="24.5" cy="14.5" r="2.5"/><circle cx="22.5" cy="20.5" r="1.5"/><circle cx="28" cy="23" r="2"/><circle cx="24" cy="29" r="3"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f41f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f41f.svg new file mode 100644 index 0000000000000000000000000000000000000000..7d9ef4108b41af166868faa9589099e233d1451b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f41f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3B88C3" d="M32.153 24c0-1 1.523-6.212 3.047-7.735 1.522-1.523 0-3.166-1.523-3.166-3.405 0-9.139 6.901-9.139 10.901 0 5 5.733 10.424 9.139 10.424 1.523 0 3.046-1.404 1.523-2.928C33.677 29.974 32.153 26 32.153 24z"/><path fill="#3B88C3" d="M9.021 14.384c0-3.046 1.497-6.093 3.02-6.093 4.569 0 13.322 4.823 14.845 12.439 1.524 7.616-17.865-6.346-17.865-6.346zm4.854 18.278c1.523 1.523 4.57 3.047 7.617 3.047 3.046 0-3.111-4.189-1.523-6.092 2.18-2.617-6.094 3.045-6.094 3.045z"/><path d="M2.071 28.727c.761-2.285.19-3.935-1.143-5.584-1.333-1.651 3.872-1.904 5.585.381s5.713 6.281 2.158 6.22c-3.553-.065-6.6-1.017-6.6-1.017z"/><path fill="#55ACEE" d="M.168 23.488c.959.874 7.223 4.309 7.165 5.137-.058.828-2.279-.088-3.105-.279-1.485-.342-1.905-.598-2.317-.526-.84.321-.554 1.201-.242 1.704 1.498 2.61 7.286 4.662 12.16 4.662 8.412 0 16.802-7.615 16.802-10.662 0-3.046-9.345-10.663-17.757-10.663C4.483 12.86.18 18.922.168 23.488z"/><path d="M7 17c1.104 0 2 .894 2 2 0 1.105-.896 2-2 2-1.105 0-2-.896-2-2 0-1.106.895-2 2-2z"/><path fill="#269" d="M15.08 29.98c-.156 0-.314-.036-.462-.113-.49-.256-.679-.86-.423-1.35 1.585-3.034 2.218-5.768.154-9.243-.282-.475-.126-1.088.349-1.371.475-.283 1.088-.124 1.371.349 2.693 4.535 1.46 8.202-.102 11.191-.178.342-.527.537-.887.537z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f420.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f420.svg new file mode 100644 index 0000000000000000000000000000000000000000..ccc11c48d02436e1b941905632ba7b79f0725b31 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f420.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M8.231 10c6-8 14-10 18-10 1 0 1 1 0 1s-6 2-7 9-11 0-11 0zm-1 18c4 3 13 8 18 8 3 0 2-1 1-1s-9-3-10-7-9 0-9 0z"/><path fill="#FFCC4D" d="M35 9c-1.611 0-4.059 2.972-5.268 6.294-1.475-5.62-6.166-10.739-12.945-10.739-8.273 0-12.061 10.216-14.524 14.479-.629 1.091-4.091 1.034-.989 3.103-3.103 2.068.449 2.243 1.222 3.103 2.625 2.92 8.997 6.205 14.291 6.205 5.655 0 11.12-3.786 12.863-8.958C30.828 25.896 33.353 29 35 29c2.209 0-2-5.582-2-10s4.209-10 2-10z"/><g fill="#F4900C"><path d="M18.001 17.967c-.019.552.414 1.015.966 1.032l.034.001c.536 0 .98-.426.998-.967.201-6.065 5.758-8.816 6.35-9.092-.466-.525-.968-1.018-1.51-1.467-1.885 1.057-6.634 4.323-6.838 10.493zm5.018-2.163c-.108.542.243 1.068.784 1.177.067.013.132.019.198.019.467 0 .885-.329.98-.804.516-2.581 2.296-3.574 3.592-3.956-.305-.609-.645-1.202-1.028-1.768-1.877.691-3.908 2.246-4.526 5.332z"/><path d="M13 20c0 .553.448 1 1 1s1-.447 1-1c0-8.97 5.841-12.544 8.266-13.641-.693-.419-1.424-.785-2.205-1.067C17.888 7.169 13 11.446 13 20z"/></g><circle fill="#292F33" cx="9.5" cy="15.5" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f422.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f422.svg new file mode 100644 index 0000000000000000000000000000000000000000..fe4b659ee0fcc7dcca7f936c7ece9f8b17b81ca5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f422.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M9.842 19.922c0 9.842 6.575 9.673 5.158 10.078-7 2-8.803-7.618-9.464-7.618-2.378 0-5.536-.423-5.536-2.46C0 17.883 2.46 15 6.151 15c2.379 0 3.691 2.883 3.691 4.922zM36 28.638c0 1.104-3.518-.741-5 0-2 1-2-.896-2-2s1.343-1 3-1 4 1.895 4 3z"/><path fill="#77B255" d="M16.715 33.143c0 2.761-1.279 2.857-2.857 2.857S11 35.903 11 33.143c0-.489.085-1.029.234-1.587.69-2.59 2.754-5.556 4.052-5.556 1.578 0 1.429 4.382 1.429 7.143zm8.571 0c0 2.761 1.278 2.857 2.856 2.857C29.721 36 31 35.903 31 33.143c0-.489-.085-1.029-.234-1.587-.691-2.59-2.754-5.556-4.052-5.556-1.578 0-1.428 4.382-1.428 7.143z"/><path fill="#3E721D" d="M32 27c0 4-5.149 4-11.5 4S9 31 9 27c0-6.627 5.149-12 11.5-12S32 20.373 32 27z"/><circle fill="#292F33" cx="5" cy="18" r="1"/><path fill="#5C913B" d="M23.667 25.1c0 3.591-1.418 3.9-3.167 3.9s-3.167-.31-3.167-3.9S18.75 17 20.5 17s3.167 4.51 3.167 8.1zM30 24c.871 3.482-.784 4-2.533 4-1.749 0-2.533.69-2.533-2.9s-1.116-6.5.633-6.5C27.315 18.6 29 20 30 24zm-13.933 1.1c0 3.591-.785 2.9-2.534 2.9s-3.404-.518-2.533-4c1-4 3.251-5.4 5-5.4 1.75 0 .067 2.91.067 6.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f425.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f425.svg new file mode 100644 index 0000000000000000000000000000000000000000..bcbd2181bb0a650aef327b2aa323a888f59bc10c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f425.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M17.38 33.098c-.097-.18-.25-.302-.417-.391C15.366 31.001 16.5 29 16.5 29c0-.553 1-2 0-2l-1 1c-1 1-1 4-1 4h-2c-.553 0-1 .447-1 1s.447 1 1 1h1.108l-.222.12c-.486.263-.667.869-.404 1.355s.869.667 1.356.404l2.639-1.427c.485-.262.666-.868.403-1.354zM23.5 32h-2s0-3-1-4l-1-1c-1 0 0 1.447 0 2 0 0 1.135 2.001-.462 3.707-.168.089-.32.211-.418.391-.263.486-.082 1.093.404 1.355l2.639 1.427c.486.263 1.093.082 1.356-.404.263-.486.082-1.093-.404-1.355L22.393 34H23.5c.553 0 1-.447 1-1s-.447-1-1-1z"/><path fill="#FFCC4D" d="M34 24c-1-2-3-5-4-10h-.008c.001-.052.008-.102.008-.154 0-5.943-4.324-10.864-9.996-11.819 1.189-.26 2.031-.509.996-1.027-1.115-.558-2.23.129-2.999.846h-.002C17.23 1.129 16.116.442 15 1c-1.035.518-.193.767.996 1.026C10.325 2.981 6 7.902 6 13.846c0 .052.007.102.008.154H6c-1 5-3 8-4 10-.447.895 0 3 2 2 1.191-.596 2.377-1.912 3.357-3.715C8.902 26.94 12.066 31 18 31c5.934 0 9.098-4.06 10.643-8.715.98 1.803 2.166 3.119 3.357 3.715 2 1 2.447-1.105 2-2z"/><path fill="#F4900C" d="M21 14c0 1.657-1.343 2-3 2s-3-.343-3-2 1.343-3 3-3 3 1.343 3 3z"/><circle fill="#662113" cx="11.5" cy="11.5" r="1.5"/><circle fill="#662113" cx="24.5" cy="11.5" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f426.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f426.svg new file mode 100644 index 0000000000000000000000000000000000000000..06d93a9162da3ecface2874fd7e3d7a24c18439b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f426.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M8.916 12.88c-.111 1.652 1.768 3.126-.712 2.959-2.48-.167-7.836-2.533-7.768-3.53s3.708-2.757 6.188-2.59c2.48.166 2.404 1.508 2.292 3.161zm20.122 16.049c-.202-.032-.392.015-.564.095-2.325.232-3.225-1.885-3.225-1.885-.439-.336-.981-2.009-1.589-1.215l.187 1.402c.187 1.402 2.57 3.224 2.57 3.224l-1.215 1.589c-.336.439-.252 1.066.187 1.402.439.336 1.066.252 1.402-.187l.673-.88-.039.249c-.087.546.285 1.058.831 1.145.546.087 1.058-.285 1.145-.831l.47-2.963c.085-.546-.287-1.058-.833-1.145zm-6.278.623c-.196-.058-.39-.037-.572.018-2.335-.082-2.944-2.3-2.944-2.3-.39-.392-.703-2.123-1.412-1.417l-.003 1.414c-.003 1.414 2.115 3.539 2.115 3.539l-1.417 1.412c-.392.39-.393 1.023-.003 1.414.39.392 1.023.393 1.414.003l.785-.782-.073.242c-.159.529.141 1.086.67 1.246.529.159 1.087-.141 1.246-.67l.862-2.873c.162-.53-.138-1.087-.668-1.246z"/><path fill="#DD2E44" d="M35.009 6.729c-.383-.17-.758-.057-1.05.244-.054.056-4.225 6.306-14.532 4.944-.34-.045 3.139 11.968 3.199 11.962.124-.014 3.07-.368 6.14-2.553 2.818-2.005 6.284-5.991 6.797-13.598.028-.418-.171-.828-.554-.999z"/><path fill="#DD2E44" d="M34.477 21.108c-.204-.336-.59-.56-.979-.471-1.293.295-3.197.543-4.53.453-6.357-.428-9.361-4.129-9.392-4.16-.275-.282.466 11.552.816 11.576 9.194.62 13.862-6.027 14.057-6.31.222-.326.233-.751.028-1.088z"/><path fill="#DD2E44" d="M24.586 19.016c-.371 5.51 1.316 9.861-4.194 9.489-5.51-.371-10.145-4.92-9.774-10.431s14.34-4.568 13.968.942z"/><path fill="#DD2E44" d="M23.257 12.412c-.353 5.235-3.922 9.257-9.156 8.904-5.235-.353-9.193-4.882-8.84-10.117.353-5.235 4.832-8.444 10.067-8.091 4.001.269 8.24 4.683 7.929 9.304z"/><circle fill="#292F33" cx="10.67" cy="8.989" r="2"/><path fill="#A0041E" d="M18.179 16.645s7.63 5.648 12.387-4.459c.396-.842 1.685.793.099 4.162s-8.175 6.44-12.04 1.536c-.815-1.035-.446-1.239-.446-1.239z"/><path fill="#DD2E44" d="M15.327 3.107s6.246.254 7.798-.477.136 2.932-3.262 3.789-4.536-3.312-4.536-3.312z"/><path fill="#DD2E44" d="M17.428 5.788s4.501.136 6.054-.594.136 2.932-3.262 3.789c-3.399.857-2.792-3.195-2.792-3.195z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f428.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f428.svg new file mode 100644 index 0000000000000000000000000000000000000000..1da7190a6813b032484d6b0b6642d9c79cb5c8ce --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f428.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M36 13.533C36 8.867 32.866 7 29 7c-1.621 0-3.285.354-4.676 1.027C22.523 6.798 20.405 6.062 18 6.062s-4.523.736-6.324 1.965C10.285 7.354 8.621 7 7 7c-3.866 0-7 1.867-7 6.533 0 3.844 2.128 6.417 5.038 7.206-.043.536-.068 1.073-.068 1.611 0 5.729 4.52 7.675 8.581 8.326C14.649 31.487 16.232 32 18 32s3.351-.513 4.449-1.323c4.062-.651 8.581-2.597 8.581-8.326 0-.538-.025-1.075-.068-1.611 2.91-.79 5.038-3.363 5.038-7.207z"/><path fill="#66757F" d="M9.554 9.854C9.236 9.821 8.917 9.8 8.6 9.8 5.507 9.8 3 11.293 3 15.026c0 2.154.838 3.808 2.138 4.824.473-3.797 2.005-7.416 4.416-9.996zM27.4 9.8c-.317 0-.637.021-.955.054 2.412 2.58 3.943 6.199 4.416 9.997C32.162 18.834 33 17.181 33 15.026c0-3.733-2.507-5.226-5.6-5.226z"/><path fill="#292F33" d="M21.728 24.807C21.728 28.152 20 29 18 29s-3.727-.848-3.727-4.193c0-3.345 1.727-6.057 3.727-6.057s3.728 2.712 3.728 6.057z"/><circle fill="#292F33" cx="12.5" cy="19.875" r="1.5"/><circle fill="#292F33" cx="23.5" cy="19.875" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f42a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f42a.svg new file mode 100644 index 0000000000000000000000000000000000000000..278e144ffd3dce79020b2e245ab9f1665fff5427 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f42a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M31.595 15.007c-1.75-3.623-5.934-9.053-9.531-9.053-4.071 0-8.228 7.259-10.071 10.378-.176.299-.321.578-.464.857-3.371-1.182-.536-6.631-.536-10.463 0-.957-.138-1.637-.44-2.119.489-.606.586-1.347.192-1.699-.413-.367-1.195-.163-1.745.456-.08.089-.129.186-.189.28-.424-.067-.903-.102-1.472-.102-.565 0-2.916.266-4.229.791C-.007 5.582.993 9 1.993 9h4c1 0 .756 2.31 0 4.726-.83 2.654-1.439 5.145-1 6.606.808 2.687 3.712 3.589 6.164 3.86 1.059 2.659 1.517 6.455 1.473 7.962-.059 2 1.94 2.059 1.999.059.036-1.211-.102-3.68.143-5.781.658 2.833.935 6.097.899 7.314-.059 1.998 1.94 2.057 1.999.059.047-1.602-.182-6.36.559-8.982.507.017 1.044.03 1.619.035 1.774.09 3.726.085 5.506-.015 1.05 1.592 1.996 2.991 1.982 3.435-.029 1-1.117 3.969-1.146 4.969-.029 1 .94 2.029 1.999.059.648-1.205 1.324-3.419 1.536-5.421.171.364.274.656.269.843-.029 1-.97 3.93-.999 4.93-.029.998.941 2.027 1.999.059 1.059-1.971 1.998-4.898 1.058-6.928-.797-1.72.431-4.165.824-7.914 1.082 1.665 1.117 3.351 1.118 3.459 0 .553.447 1 1 1 .553 0 1-.447 1-1-.001-.215-.067-4.85-4.399-7.327z"/><path fill="#292F33" d="M8.28 5.571c-.016.552-.477.986-1.029.97-.552-.016-.986-.477-.97-1.029.016-.552.477-.986 1.029-.97.552.016.986.477.97 1.029z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f42c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f42c.svg new file mode 100644 index 0000000000000000000000000000000000000000..ee782f2f20e25b2fc3c65b6b820d37a91e1837d5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f42c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#4292E0" d="M30.584 7.854c.27-1.729 1.028-3.908 2.975-5.854.704-.704.25-2-1-2 0 0-6.061.007-9.893 3.327C21.663 3.115 20.625 3 19.559 3c-8 0-12 4-14 12-.444 1.778-.865 1.399-3 3-1.195.896-2.117 3 1 3 3 0 5 .954 9 1 3.629.042 9.504-3.229 11.087-1.292 2.211 2.706 1.396 5.438.597 6.666-2.904 3.396-5.939.541-8.685-.374-3-1-1 1 0 2s1.312 4 0 6 3 0 5-3c.011-.017.022-.028.032-.045C28.392 31.5 34.559 25.936 34.559 18c0-3.918-1.515-7.474-3.975-10.146z"/><circle fill="#1F2326" cx="13.117" cy="14" r="2"/><path fill="#77BCF7" d="M10.396 21.896s4-.876 7.167-2.688c4.625-2.646 7.26-2.594 8.885-.823s1.99 6.594-2.885 9.677c2.604-2.75 1.146-8.349-2.014-7.588-8.153 1.964-8.903 1.547-11.153 1.422z"/><path fill="#4292E0" d="M19.383 17.744l-2.922 1.285c-.254.064-.433.3-.412.561.122 1.504.756 3.625 2.263 4.629 2.354 1.569 2.367 1.897 3 0 .768-2.303-.182-4.462-1.333-6.24-.127-.196-.37-.293-.596-.235z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f42d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f42d.svg new file mode 100644 index 0000000000000000000000000000000000000000..91e126242bda53e6ed20200207dbef9e04b13ba8 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f42d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#99AAB5" cx="8.5" cy="9.5" r="8.5"/><circle fill="#99AAB5" cx="27.5" cy="9.5" r="8.5"/><path fill="#F4ABBA" d="M13.812 10.031c0 3.228-2.617 5.844-5.844 5.844s-5.844-2.616-5.844-5.844c0-3.227 2.617-5.844 5.844-5.844s5.844 2.617 5.844 5.844zm20.063 0c0 3.228-2.617 5.844-5.844 5.844-3.227 0-5.844-2.616-5.844-5.844 0-3.227 2.617-5.844 5.844-5.844 3.227.001 5.844 2.617 5.844 5.844z"/><path fill="#99AAB5" d="M30 18c0 7.18-8 15-12 15S6 25.18 6 18s7-9 12-9 12 1.82 12 9z"/><path fill="#F4ABBA" d="M20.905 29.648C20.905 31.252 18.894 33 18 33c-.894 0-2.905-1.748-2.905-3.352 0-1.605 1.788-1.956 2.905-1.956 1.117 0 2.905.351 2.905 1.956z"/><g fill="#66757F"><path d="M34.999 32.16c-.175 0-.353-.046-.514-.143-4.628-2.777-11.278-1.877-11.345-1.867-.559.079-1.053-.304-1.13-.85-.078-.547.302-1.053.848-1.131.301-.042 7.411-1.014 12.656 2.133.474.284.627.898.343 1.372-.187.313-.518.486-.858.486z"/><path d="M32.001 35.16c-.305 0-.604-.138-.801-.4-2.728-3.637-8.309-4.604-8.364-4.613-.545-.091-.913-.606-.822-1.15.09-.545.606-.92 1.15-.822.262.044 6.433 1.115 9.636 5.387.332.441.242 1.068-.2 1.399-.18.134-.39.199-.599.199zm-31-3c-.34 0-.671-.173-.858-.485-.284-.474-.131-1.088.343-1.372 5.244-3.146 12.355-2.175 12.656-2.133.546.078.926.584.848 1.131-.078.547-.582.93-1.13.85-.066-.009-6.717-.909-11.345 1.867-.161.096-.339.142-.514.142z"/><path d="M3.999 35.16c-.208 0-.419-.065-.599-.2-.442-.331-.531-.958-.2-1.399 3.203-4.271 9.375-5.343 9.635-5.387.548-.097 1.059.276 1.15.821.091.544-.276 1.06-.82 1.151-.056.01-5.648.991-8.366 4.613-.195.263-.496.401-.8.401z"/></g><path fill="#272B2B" d="M12 21s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2zm8 0s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f42e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f42e.svg new file mode 100644 index 0000000000000000000000000000000000000000..40fede032f581ab8ea19ac6326afd4b9d3ff43dd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f42e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M4 8s-4 2-4 11c0 0 6-1 7-3 0 0 2-12.25-3-8zm27.995.043s4 2 4 11c0 0-6-.999-7-2.999 0 0-2-12.251 3-8.001z"/><path fill="#FFE8B6" d="M1 1c-1.01.99 1 8 5 9s4-5 3-5C5 5 3.042-1 1 1zm34.297 0c1.011.99-1 8-5 9s-4-5-3-5c4 0 5.959-6 8-4z"/><path fill="#CCD6DD" d="M21.976 31h-7.951C8.488 31 4 26.512 4 20.976v-8.951C4 6.488 8.488 2 14.025 2h7.951C27.512 2 32 6.488 32 12.025v8.951C32 26.512 27.512 31 21.976 31z"/><path fill="#E6AAAA" d="M35 28c0 5.522-4.478 8-10 8H11c-5.523 0-10-2.478-10-8s4.477-10 10-10h14c5.522 0 10 4.478 10 10z"/><ellipse fill="#C1694F" cx="9.5" cy="26" rx="1.5" ry="3"/><ellipse fill="#C1694F" cx="26.5" cy="26" rx="1.5" ry="3"/><path fill="#272B2B" d="M11 12s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2zm10 0s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f42f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f42f.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ecd980c513054a627719a9a131e3e28336b47c9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f42f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCC4D" cx="7" cy="6" r="6"/><circle fill="#FFCC4D" cx="18" cy="30" r="6"/><circle fill="#DD2E44" cx="18" cy="30" r="4"/><circle fill="#FFCC4D" cx="29" cy="6" r="6"/><circle fill="#E6AAAA" cx="7" cy="6" r="4"/><circle fill="#E6AAAA" cx="29" cy="6" r="4"/><path fill="#FFCC4D" d="M34 22c0 7-4.923 7-4.923 7H6.923S2 29 2 22C2 22 3.231 0 18 0c14.77 0 16 22 16 22z"/><path fill="#272B2B" d="M11 17s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2zm10 0s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2z"/><path fill="#FFF" d="M23.678 23c-2.402 0-4.501.953-5.678 2.378C16.823 23.953 14.723 23 12.321 23 2 23 2.043 23.421 2 26.182c-.087 5.61 6.63 6.9 10.321 6.818 2.401-.053 4.502-.989 5.679-2.397 1.177 1.408 3.276 2.345 5.678 2.397 3.691.082 10.409-1.208 10.321-6.818-.043-2.761 0-3.182-10.321-3.182z"/><path fill="#272B2B" d="M33.66 25.242c.204.279.333.588.339.939.03 1.905-.745 3.303-1.915 4.327L26.999 31l6.661-5.758zM15 25c-1 1 2 4 3 4s4-3 3-4-5-1-6 0zM10 3c2.667 2 8 4 8 4s5.333-2 8-4l-8 1-8-1zm8-1s1.652-.62 3.576-1.514C20.48.178 19.295 0 18 0s-2.481.178-3.576.486C16.348 1.38 18 2 18 2zm-7 7c3 2 7 4 7 4s4-2 7-4l-7 1-7-1zm20.645 2.285L27 15l6.006.75c-.334-1.401-.777-2.928-1.361-4.465zm1.911 7.159L28 24h5.835c.102-.595.165-1.251.165-2 0 0-.081-1.43-.444-3.556zm-31.112 0C2.082 20.57 2 22 2 22c0 .748.063 1.405.165 2H8l-5.556-5.556zm-.105 6.798c-.204.279-.333.588-.339.94-.03 1.905.745 3.303 1.916 4.327L9 31l-6.661-5.758zM9 15l-4.644-3.715c-.584 1.537-1.028 3.064-1.361 4.466L9 15z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f430.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f430.svg new file mode 100644 index 0000000000000000000000000000000000000000..2f70f9669ff7425ed606b8bde12345798f196929 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f430.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M33.799.005c-.467-.178-7.998 3.971-9.969 9.131-1.166 3.052-1.686 6.058-1.652 8.112C20.709 16.459 19.257 16 18 16s-2.709.458-4.178 1.249c.033-2.055-.486-5.061-1.652-8.112C10.2 3.977 2.668-.173 2.201.005c-.455.174 4.268 16.044 7.025 20.838C6.805 23.405 5 26.661 5 29.828c0 3.234 1.635 5.14 4 5.94 2.531.857 5-.94 9-.94s6.469 1.798 9 .94c2.365-.801 4-2.706 4-5.94 0-3.166-1.805-6.423-4.225-8.984C29.53 16.049 34.255.179 33.799.005z"/><path fill="#F4ABBA" d="M12.692 17.922c-.178-1.54-.68-3.55-1.457-5.584-1.534-4.016-5.686-7.245-6.049-7.107-.319.122 2.627 10.14 4.783 14.863.866-.824 1.786-1.563 2.723-2.172zm13.338 2.172c2.156-4.723 5.102-14.741 4.784-14.862-.363-.139-4.516 3.091-6.05 7.107-.777 2.034-1.279 4.043-1.457 5.583.937.609 1.857 1.348 2.723 2.172z"/><path fill="#CCD6DD" d="M25 30c0 2.762-3.06 5-6.834 5-3.773 0-6.833-2.238-6.833-5s3.06-5 6.833-5C21.94 25 25 27.238 25 30z"/><path fill="#FFF" d="M21 30.578c0 2.762-.238 3-3 3-2.761 0-3-.238-3-3 0-1 6-1 6 0z"/><circle fill="#292F33" cx="12.5" cy="24.328" r="1.5"/><circle fill="#292F33" cx="23.5" cy="24.328" r="1.5"/><path fill="#F4ABBA" d="M21 25.828c0 1.657-2 3-3 3s-3-1.343-3-3 6-1.657 6 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f431.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f431.svg new file mode 100644 index 0000000000000000000000000000000000000000..cc75dcc68f5a8afc9de48f7a8417ea6a796afac4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f431.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M32.348 13.999s3.445-8.812 1.651-11.998c-.604-1.073-8 1.998-10.723 5.442 0 0-2.586-.86-5.276-.86s-5.276.86-5.276.86C10.001 3.999 2.605.928 2.001 2.001.207 5.187 3.652 13.999 3.652 13.999c-.897 1.722-1.233 4.345-1.555 7.16-.354 3.086.35 5.546.658 6.089.35.617 2.123 2.605 4.484 4.306 3.587 2.583 8.967 3.445 10.761 3.445s7.174-.861 10.761-3.445c2.361-1.701 4.134-3.689 4.484-4.306.308-.543 1.012-3.003.659-6.089-.324-2.814-.659-5.438-1.556-7.16z"/><path fill="#F18F26" d="M2.359 2.971c.2-.599 5.348 2.173 6.518 5.404 0 0-3.808 2.624-4.528 4.624 0 0-2.99-7.028-1.99-10.028z"/><path fill="#FFCC4D" d="M5.98 7.261c0-1.414 5.457 2.733 4.457 3.733s-1.255.72-2.255 1.72S5.98 8.261 5.98 7.261z"/><path fill="#F18F26" d="M33.641 2.971c-.2-.599-5.348 2.173-6.518 5.404 0 0 3.808 2.624 4.528 4.624 0 0 2.99-7.028 1.99-10.028z"/><path fill="#FFCC4D" d="M30.02 7.261c0-1.414-5.457 2.733-4.457 3.733s1.255.72 2.255 1.72 2.202-4.453 2.202-5.453z"/><path fill="#292F33" d="M14.001 20.001c0 1.105-.896 1.999-2 1.999s-2-.894-2-1.999c0-1.104.896-1.999 2-1.999s2 .896 2 1.999zm11.998 0c0 1.105-.896 1.999-2 1.999-1.105 0-2-.894-2-1.999 0-1.104.895-1.999 2-1.999s2 .896 2 1.999z"/><path fill="#FEE7B8" d="M2.201 30.458c-.148 0-.294-.065-.393-.19-.171-.217-.134-.531.083-.702.162-.127 4.02-3.12 10.648-2.605.275.021.481.261.46.536-.021.275-.257.501-.537.46-6.233-.474-9.915 2.366-9.951 2.395-.093.07-.202.106-.31.106zm8.868-4.663c-.049 0-.1-.007-.149-.022-4.79-1.497-8.737-.347-8.777-.336-.265.081-.543-.07-.623-.335-.079-.265.071-.543.335-.622.173-.052 4.286-1.247 9.362.338.264.083.411.363.328.627-.066.213-.263.35-.476.35zm22.73 4.663c.148 0 .294-.065.393-.19.171-.217.134-.531-.083-.702-.162-.127-4.02-3.12-10.648-2.605-.275.021-.481.261-.46.536.022.275.257.501.537.46 6.233-.474 9.915 2.366 9.951 2.395.093.07.202.106.31.106zm-8.868-4.663c.049 0 .1-.007.149-.022 4.79-1.497 8.737-.347 8.777-.336.265.081.543-.07.623-.335.079-.265-.071-.543-.335-.622-.173-.052-4.286-1.247-9.362.338-.264.083-.411.363-.328.627.066.213.263.35.476.35z"/><path fill="#67757F" d="M24.736 30.898c-.097-.258-.384-.392-.643-.294-.552.206-1.076.311-1.559.311-1.152 0-1.561-.306-2.033-.659-.451-.338-.956-.715-1.99-.803v-2.339c0-.276-.224-.5-.5-.5s-.5.224-.5.5v2.373c-.81.115-1.346.439-1.816.743-.568.367-1.059.685-2.083.685-.482 0-1.006-.104-1.558-.311-.258-.095-.547.035-.643.294-.097.259.035.547.293.644.664.247 1.306.373 1.907.373 1.319 0 2.014-.449 2.627-.845.524-.339.98-.631 1.848-.635.992.008 1.358.278 1.815.621.538.403 1.147.859 2.633.859.601 0 1.244-.126 1.908-.373.259-.097.391-.385.294-.644z"/><path fill="#E75A70" d="M19.4 24.807h-2.8c-.64 0-1.163.523-1.163 1.163 0 .639.523 1.163 1.163 1.163h.237v.345c0 .639.523 1.163 1.163 1.163s1.163-.523 1.163-1.163v-.345h.237c.639 0 1.163-.523 1.163-1.163s-.524-1.163-1.163-1.163z"/><path fill="#F18F26" d="M18.022 17.154c-.276 0-.5-.224-.5-.5V8.37c0-.276.224-.5.5-.5s.5.224.5.5v8.284c0 .277-.223.5-.5.5zM21 15.572c-.276 0-.5-.224-.5-.5 0-2.882 1.232-5.21 1.285-5.308.13-.244.435-.334.677-.204.243.13.334.433.204.677-.012.021-1.166 2.213-1.166 4.835 0 .276-.224.5-.5.5zm-6 0c-.276 0-.5-.224-.5-.5 0-2.623-1.155-4.814-1.167-4.835-.13-.244-.038-.546.205-.677.242-.131.545-.039.676.204.053.098 1.285 2.426 1.285 5.308.001.276-.223.5-.499.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f432.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f432.svg new file mode 100644 index 0000000000000000000000000000000000000000..1c1b4347daa1cde112991ca2989aeabf3903027a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f432.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M35.125 13.344c0-1 .771-2.327.771-2.635 0-.656-1.553-.421-1.626-1.046-.209-1.794 1.887-3.318-1.745-3.312-1.352.002-.274-1.768-.274-2.725 0-.957-2.596-.145-3.552-.145-.957 0-.957-2.87-1.913-2.87-2.87 0-3.827 2.87-4.783 2.87-.957 0-1.744-3.621-2.87-2.87-2.87 1.913-3.826 7.653-3.826 7.653s4.783-3.826 10.522-2.87c5.345.891 4.79 10.821 5.641 16.888L24.609 36h3.359c.344-1.5 1.939-.529 2.375-1.688.381-1.016-.67-1.966-.094-2.969s.978-.755 2.094-1.375c1.184-.657 0-2.199 0-3.156 0-.956 2.312-1.574 2.312-2.531 0-.63-1.068-1.292-.812-2.356.257-1.064 1.586-1.186 1.749-2.184.138-.847-.921-1.455-.796-2.393s1.174-1.378 1.174-2.097c.002-.718-.845-1.001-.845-1.907z"/><path fill="#77B255" d="M34.438 13.458c0-4.038-2.87-9.085-9.566-9.085-6.695 0-17.265 10.024-20.088 10.096C2.87 12.521 0 14.523 0 16.486c0 3.028 5.373 4.61 5.646 4.899 1.088 1.149 3.92 8.083 8.704 1.945.803-1.03 1.302-.422 3.483.542C25.069 27.729 16 36 16 36h9.566c4.782-4.783 8.871-13.844 8.871-21.997l-.021.008c.007-.185.022-.369.022-.553z"/><path fill="#292F33" d="M23.915 12.09c0 1.056-.856 1.913-1.913 1.913s-1.913-.857-1.913-1.913c0-1.057.856-1.913 1.913-1.913 1.057-.001 1.913.856 1.913 1.913z"/><path fill="#3E721D" d="M4.783 17.351c0 .793-.643.479-1.435.479s-1.435.315-1.435-.479c0-.792.643-1.435 1.435-1.435.793 0 1.435.643 1.435 1.435z"/><path fill="#FFF" d="M18.176 18.782c0 1.058-.643.956-1.436.956-.792 0-1.434.101-1.434-.956 0-1.056.642-3.826 1.434-3.826.793 0 1.436 2.771 1.436 3.826zm-3.827.956c0 1.058-.643.957-1.435.957s-1.435.101-1.435-.957c0-1.056.643-3.826 1.435-3.826.792.001 1.435 2.771 1.435 3.826z"/><path fill="#3E721D" d="M18.04 18.795c-5.076.726-10.192 2.007-12.394 2.59.275.29.661.95 1.162 1.674 2.415-.624 6.975-1.724 11.503-2.369.524-.074.887-.561.812-1.083-.075-.524-.563-.888-1.083-.812zm.549-6.186c-.258 0-.515-.098-.709-.295-.388-.391-.388-1.021.001-1.41.129-.129 3.222-3.163 8.36-3.163.553 0 1 .448 1 1s-.447 1-1 1c-4.281 0-6.923 2.554-6.949 2.58-.194.192-.449.288-.703.288z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f433.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f433.svg new file mode 100644 index 0000000000000000000000000000000000000000..f00ea1033e029164dfde9333e90e2f7595958b12 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f433.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3B88C3" d="M32 12c2.122-2.122 5 14.312-3 21-2.757 2.305-6 2.969-8 2.969-2.371 0-10.029.031-13 .031-7.18 0-8-4.925-8-11s.82-11 8-11c6 0 10 2 13 3.996 4.977 3.312 5.992 3.861 8 2.004 3.213-2.97 1-6 3-8z"/><path fill="#55ACEE" d="M34.003 23c-.465 3.727-2.041 7.523-5.003 10-2.757 2.305-6 2.969-8 2.969-2.371 0-10.029.031-13 .031-4.035 0-6.062-1.555-7.062-3.996C.157 30.102 4 33 15 33c14 0 17-5 19.003-10z"/><path fill="#3B88C3" d="M32 14c4.123 0 4-5 4-7s-2 1-5 2-7-2-6 0 3 5 7 5z"/><path fill="#55ACEE" d="M10 7c0 2.209-.896 6-2 6S6 9.209 6 7s.896-2 2-2 2-.209 2 2z"/><path fill="#55ACEE" d="M8 5c0-3-6-2-6 0s3 1 4 3 2-3 2-3zm0 0c0-3 6-2 6 0s-3 1-4 3-2-3-2-3z"/><circle fill="#292F33" cx="6.5" cy="25.5" r="1.5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f434.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f434.svg new file mode 100644 index 0000000000000000000000000000000000000000..9aa7d69356ae769d73149b12363785dcd06e596e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f434.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M23.283 23.275s1.374 1.635 2.733 10.047c.143.883.201 1.775.217 2.678H36V7.448C31.613 3.975 25.601 3.259 18.322 5.69c0 0-5.408-3-6.147-3.739-.719-.72-1.857-1.556-1.235.35.364 1.112.764 2.373 2.358 4.862-3.436 2.036-4.513 4.68-8.558 13.341C1.652 27.12.08 29.269.937 31.797c1.13 3.337 5.316 5.595 8.844 3.021 1.919-1.4 2.246-3.913 6.225-6.223 3.653-.065 7.277-1.604 7.277-5.32z"/><path fill="#292F33" d="M36 6.012C27.665.301 14.354 1.473 15.909 6.19 25.51 4.328 31.77 7.731 36 13.358V6.012z"/><path fill="#292F33" d="M19.663 5.763c-2.878.233-7.157 1.595-9.296 3.967 0 0-.129-5.147 3.566-5.614 6.172-.779 5.809.363 5.809.363l-.079 1.284z"/><path fill="#C1694F" d="M16.357 1.056c.558 1.155 4.006 1.79 5.056 6.029 1.051 4.24-3.134 2.951-4.356.855-1.361-2.334-1.828-4.162-1.867-5.679-.021-.801.039-3.538 1.167-1.205z"/><path fill="#662113" d="M16.596 2.838c1.103.968 2.448 2.472 2.65 3.955.202 1.483-1.125.988-1.736-.372-.612-1.359-.753-2.779-1.134-3.233-.38-.454.22-.35.22-.35z"/><path fill="#292F33" d="M16.94 15.525c0 .687-.557 1.244-1.245 1.244-.687 0-1.244-.557-1.244-1.244 0-.688.557-1.245 1.244-1.245.688.001 1.245.558 1.245 1.245z"/><path fill="#662113" d="M4.222 29.917c0 .881-.532 1.594-1.187 1.594s-1.187-.713-1.187-1.594c0-.882.532-1.596 1.187-1.596s1.187.714 1.187 1.596z"/><path fill="#D99E82" d="M10.354 9.924c-.033-.017-.075-.014-.111-.024-1.543 2.033-2.92 5.102-5.49 10.604-1.356 2.903-2.42 4.946-3.116 6.538 1.628.226 3.285-1.442 3.945-3.271.673-1.866 3.215-5.652 4.927-7.778 1.712-2.127 1.561-5.144-.155-6.069z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f435.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f435.svg new file mode 100644 index 0000000000000000000000000000000000000000..ee6c57cf9e41a0f6d118cd829be47a6c6230ee44 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f435.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse transform="rotate(-14.999 5.05 17.456)" fill="#D79E84" cx="5.05" cy="17.455" rx="3.818" ry="5.455"/><ellipse transform="rotate(-75.001 31.05 17.455)" fill="#D79E84" cx="31.05" cy="17.455" rx="5.455" ry="3.818"/><path fill="#BF6952" d="M19.018 36h-2.036C10.264 36 3.75 30.848 3.75 23.636c0-4.121 1.527-6.182 1.527-6.182s-.509-2.061-.509-4.121C4.768 7.152 11.282 2 18 2c6.718 0 13.232 6.182 13.232 11.333 0 2.061-.509 4.121-.509 4.121s1.527 2.061 1.527 6.182C32.25 30.848 25.736 36 19.018 36z"/><path fill="#D79E84" d="M30 16.042C30 12.153 26.825 9 22.909 9c-1.907 0-3.635.752-4.909 1.968C16.726 9.752 14.998 9 13.091 9 9.175 9 6 12.153 6 16.042c0 2.359 1.172 4.441 2.965 5.719-.503 1.238-.783 2.6-.783 4.031C8.182 31.476 12.578 35 18 35s9.818-3.524 9.818-9.208c0-1.431-.28-2.793-.783-4.031C28.828 20.483 30 18.4 30 16.042z"/><ellipse fill="#292F33" cx="13" cy="17" rx="2.25" ry="3.25"/><ellipse fill="#292F33" cx="23" cy="17" rx="2.25" ry="3.25"/><path fill="#642116" d="M18 32.727c2.838 0 5.254-1.505 6.162-3.61.375-.871-.262-1.844-1.21-1.844h-9.904c-.948 0-1.585.974-1.21 1.844.908 2.105 3.324 3.61 6.162 3.61z"/><circle fill="#642116" cx="16.25" cy="23" r="1"/><circle fill="#642116" cx="19.75" cy="23" r="1"/><path fill="#BF6952" d="M22.66.175s-5.455-1.091-7.636 2.182 4.364 1.091 4.364 1.091S20.478.175 22.66.175z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f436.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f436.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b2e685804d9599cd9eb855d54806a37ea6226bd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f436.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M15 27v6s0 3 3 3 3-3 3-3v-6h-6z"/><path fill="#BE1931" d="M15 33l.001.037c1.041-.035 2.016-.274 2.632-1.286.171-.281.563-.281.735 0 .616 1.011 1.591 1.251 2.632 1.286V27h-6v6z"/><path fill="#D99E82" d="M31.954 21.619c0 6.276-5 6.276-5 6.276h-18s-5 0-5-6.276c0-6.724 5-18.619 14-18.619s14 12.895 14 18.619z"/><path fill="#F4C7B5" d="M18 20c-7 0-10 3.527-10 6.395 0 3.037 2.462 5.5 5.5 5.5 1.605 0 3.042-.664 4.049-2.767.185-.386.716-.386.901 0 1.007 2.103 2.445 2.767 4.049 2.767 3.038 0 5.5-2.463 5.5-5.5C28 23.527 25 20 18 20z"/><path fill="#292F33" d="M15 22.895c-1 1 2 4 3 4s4-3 3-4-5-1-6 0zM13 19c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2s2 .9 2 2v2c0 1.1-.9 2-2 2zm10 0c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2s2 .9 2 2v2c0 1.1-.9 2-2 2z"/><path fill="#662113" d="M15 3.608C13.941 2.199 11.681.881 2.828 4.2-1.316 5.754.708 17.804 3.935 18.585c1.106 0 4.426 0 4.426-8.852 0-.22-.002-.423-.005-.625C10.35 6.298 12.5 4.857 15 3.608zm18.172.592C24.319.881 22.059 2.199 21 3.608c2.5 1.25 4.65 2.691 6.644 5.501-.003.201-.005.404-.005.625 0 8.852 3.319 8.852 4.426 8.852 3.227-.782 5.251-12.832 1.107-14.386z"/><circle fill="#D99E82" cx="23.5" cy="25.5" r=".5"/><circle fill="#D99E82" cx="11.5" cy="25.5" r=".5"/><circle fill="#D99E82" cx="25.5" cy="27.5" r=".5"/><circle fill="#D99E82" cx="10.5" cy="27.5" r=".5"/><circle fill="#D99E82" cx="23" cy="28" r="1"/><circle fill="#D99E82" cx="13" cy="28" r="1"/><path fill="#380F09" d="M9.883 7.232c-.259-.673-.634-1.397-1.176-1.939-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414c.57.57 1.066 1.934 1.068 2.346.145-.404.839-1.15 1.522-1.821zm16.217 0c.259-.672.634-1.397 1.176-1.939.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414c-.57.57-1.066 1.934-1.068 2.346-.145-.404-.839-1.15-1.522-1.821z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f437.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f437.svg new file mode 100644 index 0000000000000000000000000000000000000000..49175ea42aa234cbbf032345115399f1a82461c4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f437.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4ABBA" d="M34.193 13.329c.387-.371.733-.795 1.019-1.28 1.686-2.854.27-10.292-.592-10.8-.695-.411-5.529 1.05-8.246 3.132C23.876 2.884 21.031 2 18 2c-3.021 0-5.856.879-8.349 2.367C6.93 2.293 2.119.839 1.424 1.249c-.861.508-2.276 7.947-.592 10.8.278.471.615.884.989 1.249C.666 15.85 0 18.64 0 21.479 0 31.468 8.011 34 18 34s18-2.532 18-12.521c0-2.828-.66-5.606-1.807-8.15z"/><path fill="#EA596E" d="M7.398 5.965c-2.166-1.267-4.402-2.08-4.8-1.845-.57.337-1.083 4.998-.352 8.265 1.273-2.483 3.04-4.682 5.152-6.42zm26.355 6.419c.733-3.267.219-7.928-.351-8.265-.398-.235-2.635.578-4.801 1.845 2.114 1.739 3.88 3.938 5.152 6.42zM28 23.125c0 4.487-3.097 9.375-10 9.375-6.904 0-10-4.888-10-9.375S11.096 17.5 18 17.5c6.903 0 10 1.138 10 5.625z"/><path fill="#662113" d="M15 24.6c0 1.857-.34 2.4-1.5 2.4s-1.5-.543-1.5-2.4c0-1.856.34-2.399 1.5-2.399s1.5.542 1.5 2.399zm9 0c0 1.857-.34 2.4-1.5 2.4s-1.5-.543-1.5-2.4c0-1.856.34-2.399 1.5-2.399s1.5.542 1.5 2.399z"/><circle fill="#292F33" cx="7" cy="17" r="2"/><circle fill="#292F33" cx="29" cy="17" r="2"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f43a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f43a.svg new file mode 100644 index 0000000000000000000000000000000000000000..af402057ef4110cdb0b921f72e3273a32b461bb1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f43a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M14.858 9.497c.475 2.326-.182 4.236-2.921 4.638-2.741.403-6.7 3.898-8.848-1.798C1.844 9.038 1.092 2.234 2.628 2.009c1.537-.226 11.756 5.162 12.23 7.488z"/><path fill="#CCD6DD" d="M12.784 9.851c.865 1.392-2.205 3.833-3.844 4.568-1.639.736-2.915-.66-4.173-4.1-.55-1.503-1.234-5.532-.634-5.802.599-.268 7.785 3.942 8.651 5.334z"/><path fill="#66757F" d="M21.372 9.497c-.458 2.326.176 4.236 2.818 4.638 2.644.403 6.464 3.898 8.536-1.798 1.201-3.3 1.927-10.103.445-10.329-1.483-.225-11.342 5.163-11.799 7.489z"/><path fill="#CCD6DD" d="M23.373 9.851c-.835 1.392 2.127 3.833 3.708 4.568 1.581.736 2.812-.66 4.026-4.1.531-1.503 1.19-5.532.611-5.802-.577-.268-7.509 3.942-8.345 5.334z"/><path fill="#66757F" d="M32.347 26.912c0-.454-.188-1.091-.407-1.687.585.028 1.519.191 2.77.817-.008-.536-.118-.984-.273-1.393.041.02.075.034.116.055-1.104-3.31-3.309-5.517-3.309-5.517h2.206c-2.331-4.663-4.965-8.015-8.075-9.559-1.39-.873-3.688-1.338-7.373-1.339h-.003c-3.696 0-5.996.468-7.385 1.346-3.104 1.547-5.734 4.896-8.061 9.552H4.76s-2.207 2.206-3.311 5.517l.084-.039c-.201.392-.307.847-.282 1.377 1.263-.632 2.217-.792 2.813-.818-.189.513-.343 1.044-.386 1.475-.123.371-.191.812-.135 1.343 3.207-1.458 4.707-1.25 6.457-.375C11.213 31.29 14.206 34 18.001 34c3.793 0 6.746-2.794 7.958-6.416 1.458-1.25 3.708-.875 6.416.416.066-.413.036-.773-.036-1.093l.008.005z"/><path fill="#CCD6DD" d="M34.553 24.704c-.437-1.313-3.665-3.101-6.973-4.513.26-.664.42-1.401.42-2.191 0-2.761-1.791-5-4-5s-4 2.239-4 5c0 3 4 10-2.001 11.118-5.125-.955-2.954-6.201-2.212-9.58.072-.276.125-.559.158-.853.034-.245.055-.476.055-.685 0-2.761-1.791-5-4-5s-4 2.239-4 5c0 .79.16 1.527.421 2.191-3.308 1.412-6.535 3.2-6.973 4.513C3.655 23.6 4.759 23.6 4.759 23.6s-1.104 2.208-1.104 3.312c2.67-1.78 5.339-2.122 7.429-.452C12.297 30.083 14 33 18.001 30.124c3.999 2.876 5.7-.04 6.912-3.662 2.092-1.673 4.763-1.33 7.434.45 0-1.104-1.103-3.312-1.103-3.312s1.103.001 3.309 1.104z"/><path fill="#292F33" d="M11 17s0-1.5 1.5-1.5S14 17 14 17v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V17zm11 0s0-1.5 1.5-1.5S25 17 25 17v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V17zm-7.061 9.156c-1.021.208 2.041 3.968 3.062 3.968 1.02 0 4.082-3.76 3.062-3.968s-5.103-.208-6.124 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f43b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f43b.svg new file mode 100644 index 0000000000000000000000000000000000000000..50224417b0cefa8dc73b78f6fa3e0430f1a17975 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f43b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#C1694F" cx="7" cy="6" r="6"/><circle fill="#C1694F" cx="29" cy="6" r="6"/><circle fill="#E6AAAA" cx="7" cy="6" r="4"/><circle fill="#E6AAAA" cx="29" cy="6" r="4"/><path fill="#C1694F" d="M35 22S33.692 0 18 0 1 22 1 22c0 5.872 4.499 10.323 12.216 11.61C14.311 35.06 16.044 36 18 36s3.688-.94 4.784-2.39C30.501 32.323 35 27.872 35 22z"/><circle fill="#DD2E44" cx="18" cy="30" r="4"/><path fill="#D99E82" d="M18 20S7 23.687 7 27s2.687 6 6 6c2.088 0 3.925-1.067 5-2.685C19.074 31.933 20.912 33 23 33c3.313 0 6-2.687 6-6s-11-7-11-7z"/><path fill="#272B2B" d="M11 17s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2zm10 0s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2zm-7.875 8c-1.624 1 3.25 4 4.875 4s6.499-3 4.874-4-8.124-1-9.749 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f43f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f43f.svg new file mode 100644 index 0000000000000000000000000000000000000000..3676874901703ac37a65909917bb00c4fd84fa44 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f43f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#AD743D" d="M35.432 22.773c-.195.858-.638 1.773-1.022 2.159 1.399-4.418 1.399-9.111-2.25-11.167.112 1.107-.11 1.691-.265 2.153-.21-2.219-.578-3.744-2.158-4.927-1.82-1.363-2.611-.452-.736 3.765 2.2 4.945 1.475 8.603.827 11.216-.038.154-.08.29-.12.439.804-5.765-.989-11.722-6.825-14.915-2.989-1.636-5.211-1.852-5.329-3.037-.135-1.377-1.218-3.698-3.811-5.327.444-1.309-.485-2.787-1.117-2.841-.631-.054-2.024 1.039-2.16 2.528-4.694 1.399-9.492 7.219-9.345 8.397.148 1.177.341 2.638 6.57 3.656 1.104.18 3.995 1.835 4.4 5.779.456 4.44 2.276 8.054 4.712 11.216h-1.73c-4.132 0-4.132 4.132-1.377 4.132h10.928l-.002-.002c.36-.003.788-.029 1.304-.085 6.931-.612 10.792-7.349 9.506-13.139z"/><path fill="#D99E82" d="M11.325 15.279c3.258-.09 4.524-6.049-.682-6.82-.122-1.077-.763-2.614-2.257-2.724-2.348-.173-5.294 2.116-6.099 7.478.881.601 2.467 1.18 5.405 1.661 1.104.18 3.995 1.835 4.4 5.779.531 5.174 2.914 9.224 5.966 12.747.903-.94 1.636-2.325 2.028-4.285 1.378-6.886-7.384-12.458-8.761-13.836z"/><circle fill="#292F33" cx="7.692" cy="9.459" r="1.377"/><path fill="#662113" d="M21.254 13.564c4.065 3.341 6.158 7.296 5.402 12.37-.318 2.143.83 2.933 1.688.902.599-1.423.936-9.887-6.05-14.311-1.859-1.177-1.961.284-1.04 1.039z"/><path fill="#AD743D" d="M13.234 19.676c-1.243-1.243-4.97 0-6.211-2.488-.786-1.572-3.728 1.245-2.485 3.734 1.242 2.483 4.969 2.483 7.454 1.242 2.485-1.242 1.242-2.488 1.242-2.488z"/><path fill="#662113" d="M6.26 20.146c.304 1.49-.383 4.295-1.874 4.6-1.49.304-3.22-2.007-3.524-3.496-.304-1.49.658-2.947 2.147-3.253 1.492-.305 2.946.659 3.251 2.149z"/><path fill="#AD743D" d="M13.907 21.375c-1.635-1.062-5.388 1.148-7.309-1.259-1.215-1.523-3.753 2.209-1.832 4.615 1.921 2.405 5.962 1.543 8.368-.378 2.407-1.92.773-2.978.773-2.978z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f441.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f441.svg new file mode 100644 index 0000000000000000000000000000000000000000..bd1a45e4e6e440e3a98b835460af7e360de43af9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f441.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M35.059 18c0 3.304-7.642 11-17.067 11C8.566 29 .925 22.249.925 18c0-3.314 34.134-3.314 34.134 0z"/><path fill="#292F33" d="M35.059 18H.925c0-3.313 7.642-11 17.067-11s17.067 7.686 17.067 11z"/><path fill="#F5F8FA" d="M33.817 18c0 2.904-7.087 9.667-15.826 9.667-8.74 0-15.825-5.935-15.825-9.667 0-2.912 7.085-9.666 15.825-9.666C26.73 8.333 33.817 15.088 33.817 18z"/><circle fill="#8B5E3C" cx="18" cy="18" r="8.458"/><circle fill="#292F33" cx="18" cy="18" r="4.708"/><circle fill="#F5F8FA" cx="14.983" cy="15" r="2"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f451.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f451.svg new file mode 100644 index 0000000000000000000000000000000000000000..4db8d2bc357e65c14b1b518b7c00201d0b2c8726 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f451.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M14.174 17.075L6.75 7.594l-3.722 9.481z"/><path fill="#F4900C" d="M17.938 5.534l-6.563 12.389H24.5z"/><path fill="#F4900C" d="M21.826 17.075l7.424-9.481 3.722 9.481z"/><path fill="#FFCC4D" d="M28.669 15.19L23.887 3.523l-5.88 11.668-.007.003-.007-.004-5.88-11.668L7.331 15.19C4.197 10.833 1.28 8.042 1.28 8.042S3 20.75 3 33h30c0-12.25 1.72-24.958 1.72-24.958s-2.917 2.791-6.051 7.148z"/><circle fill="#5C913B" cx="17.957" cy="22" r="3.688"/><circle fill="#981CEB" cx="26.463" cy="22" r="2.412"/><circle fill="#DD2E44" cx="32.852" cy="22" r="1.986"/><circle fill="#981CEB" cx="9.45" cy="22" r="2.412"/><circle fill="#DD2E44" cx="3.061" cy="22" r="1.986"/><path fill="#FFAC33" d="M33 34H3c-.552 0-1-.447-1-1s.448-1 1-1h30c.553 0 1 .447 1 1s-.447 1-1 1zm0-3.486H3c-.552 0-1-.447-1-1s.448-1 1-1h30c.553 0 1 .447 1 1s-.447 1-1 1z"/><circle fill="#FFCC4D" cx="1.447" cy="8.042" r="1.407"/><circle fill="#F4900C" cx="6.75" cy="7.594" r="1.192"/><circle fill="#FFCC4D" cx="12.113" cy="3.523" r="1.784"/><circle fill="#FFCC4D" cx="34.553" cy="8.042" r="1.407"/><circle fill="#F4900C" cx="29.25" cy="7.594" r="1.192"/><circle fill="#FFCC4D" cx="23.887" cy="3.523" r="1.784"/><circle fill="#F4900C" cx="17.938" cy="5.534" r="1.784"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f455.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f455.svg new file mode 100644 index 0000000000000000000000000000000000000000..1db482028323cdead8a051c0e9e7b7e48718632e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f455.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3B88C3" d="M11 2C8 2 0 4 0 6s1 7 2 9 8 0 9-1 2-12 0-12z"/><path fill="#55ACEE" d="M1 4.717C.352 5.088 0 5.565 0 6c0 2 1 7 2 9 .281.562 1.039.777 2 .85C3 13 2 9 1 4.717z"/><path fill="#3B88C3" d="M25 2c3 0 11 2 11 4s-1 7-2 9-8 0-9-1-2-12 0-12z"/><path fill="#55ACEE" d="M35 4.717c.648.371 1 .848 1 1.283 0 2-1 7-2 9-.281.562-1.039.777-2 .85C33 13 34 9 35 4.717z"/><path fill="#3B88C3" d="M25 2h-1.068C23.515 3.695 21.021 5 18 5s-5.515-1.305-5.932-3H11C8.791 2 6 3.791 6 6c0 0 0 20-1 24s1.791 4 4 4h18c2.209 0 5 0 4-4S30 6 30 6c0-2.209-2.791-4-5-4z"/><path fill="#55ACEE" d="M18 7c3.866 0 7-2.239 7-5h-1.068C23.515 3.695 21.021 5 18 5s-5.515-1.305-5.932-3H11c0 2.761 3.134 5 7 5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f457.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f457.svg new file mode 100644 index 0000000000000000000000000000000000000000..29cc45c742cf0fcfb33199da4502bdd3c8e01076 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f457.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M22.42 11.847L26 2s-.398.002-1 .034V0h-2v2.219c-2.271.302-5 1.028-5 2.781 0-1.753-2.729-2.479-5-2.781V0h-2v2.034C10.398 2.002 10 2 10 2l3.581 9.847L1 25.643S7 36 18 36s17-10.357 17-10.357L22.42 11.847z"/><path fill="#BBDDF5" d="M13 11h10v2H13z"/><path fill="#3B88C3" d="M15 13s-6.734 8.106-5.051 9.006C11.633 22.907 15 13 15 13zm6.096 0s6.734 8.105 5.051 9.007c-1.684.9-5.051-9.007-5.051-9.007zM18 13s-2 11 0 11 0-11 0-11z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f45f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f45f.svg new file mode 100644 index 0000000000000000000000000000000000000000..f0c998c6313597746e2b0785489b92b9b6e5f949 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f45f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8899A6" d="M24.161 10.166l-.676-2.034c-.134-.302-.49-.43-.781-.275-.918.487-2.944 1.318-3.684 1.575 1.419.505 3.499 1.503 4.511 1.396.384-.04.787-.308.63-.662zm10.21 24.574c-.399.225-6.509 1.692-18.621-8.906C12.083 22.625 1.2 12.879 1.341 12.547c0 0-.329.36-.602.736-.197.271-.319.559-.274.848.31 1.967 3.112 3.819 6.962 6.781l.549.422.363.279c.588.452 2.316 1.815 4.329 3.403 2.753 2.171 8.284 6.49 8.445 6.61 2.12 1.574 4.635 2.817 7.667 3.672 3.838 1.081 5.591-.558 5.591-.558z"/><path fill="#BE1931" d="M34.371 34.74s.477-.219.97-.918c.493-.699.79-1.924.045-3.248-.745-1.323-3.456-5.121-4.345-6.671-.433-.755-.297-1.447-1.125-2.835 0 0-3.164-5.523-3.864-6.723-1.497-2.567-.84-3.902-1.837-4.668-.665-.511-7.306.166-9.327-1.389-1.397-1.074-1.418-4.428-2.003-5.526-.466-.875-2.02-.475-3.087.11S5.825 6.661 5.123 7.574s-1.601 1.909-1.679 2.928l-.079 1.018S19.226 26.67 23.74 29.726c7.697 5.211 10.631 5.014 10.631 5.014z"/><path fill="#A0041E" d="M24.74 10.464c-.103-.314-.249-.575-.525-.788-.665-.511-7.306.167-9.327-1.389-1.397-1.074-1.418-4.429-2.003-5.526-.182-.341-.532-.485-.952-.502.69 1.4.621 5.574 2.312 6.874 2.038 1.569 8.016 1.133 10.495 1.331z"/><path fill="#DD2E44" d="M13.265 17.873c.505-1.472 1.044-4.915.074-6.962-.909-1.917-4.441-5.955-5.112-6.72C6.987 5.296 5.33 7.229 4.83 7.879c-.66.858-1.455 1.822-1.494 2.801-.014.352.087.51.087.51s9.822 6.741 9.842 6.683z"/><path fill="#CCD6DD" d="M23.107 14.256c-.335 0-.65-.202-.78-.533-.169-.431.043-.917.474-1.087l1.823-.715c.43-.167.919.043 1.087.475.169.431-.043.917-.474 1.087l-1.823.715c-.101.039-.204.058-.307.058zm1.347 3.063c-.291 0-.573-.151-.728-.421-.231-.401-.093-.914.309-1.145l1.793-1.031c.402-.231.915-.092 1.145.309.231.401.093.914-.309 1.145l-1.793 1.031c-.132.076-.275.112-.417.112zm1.821 2.752c-.256 0-.509-.117-.673-.338-.277-.371-.2-.896.171-1.173l1.514-1.129c.371-.277.897-.201 1.173.171.277.372.2.897-.171 1.174l-1.514 1.128c-.15.113-.326.167-.5.167zm1.945 2.571c-.242 0-.482-.104-.648-.307-.294-.358-.241-.887.116-1.181l1.155-.948c.357-.293.887-.242 1.181.116s.241.887-.116 1.181l-1.155.948c-.157.128-.346.191-.533.191zM3.2 10.76s.675.612 1.425.726c.75.114 2.079.95 2.993 1.653.914.703 4.399 3.292 6.534 5.444s5.495 6.58 6.801 7.863c1.306 1.282 3.413 3.193 5.214 4.347s3.455 2.131 4.516 2.686c1.368.716 2.632 1.144 3.688 1.261-.368.216-2.313.946-5.69-.205-3.228-1.101-5.332-2.294-7.071-3.586-1.739-1.292-11.208-8.808-12.759-10.001-1.551-1.193-6.188-4.728-6.92-5.787-1.04-1.504-.99-2.162-.788-2.424.492-.641 1.531-2.382 2.057-1.977z"/><path fill="#DD2E44" d="M35.386 30.574c-.745-1.323-3.456-5.121-4.345-6.671-.174-.304-.257-.599-.347-.931-.091.034-.189.054-.269.109-1.154.792-1.148 3.185.571 5.687 1.378 2.006 3.59 3.552 4.832 3.576.026-.538-.088-1.142-.442-1.77z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f47d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f47d.svg new file mode 100644 index 0000000000000000000000000000000000000000..f6e98d1c1403dbc5214fadb08c2b903dacb3e6d4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f47d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M35 17c0 9.389-13.223 19-17 19-3.778 0-17-9.611-17-19S8.611 0 18 0s17 7.611 17 17z"/><path fill="#292F33" d="M13.503 14.845c3.124 3.124 4.39 6.923 2.828 8.485-1.562 1.562-5.361.297-8.485-2.828-3.125-3.124-4.391-6.923-2.828-8.485s5.361-.296 8.485 2.828zm8.994 0c-3.124 3.124-4.39 6.923-2.828 8.485 1.562 1.562 5.361.297 8.485-2.828 3.125-3.125 4.391-6.923 2.828-8.485-1.562-1.562-5.361-.297-8.485 2.828zM18 31c-2.347 0-3.575-1.16-3.707-1.293-.391-.391-.391-1.023 0-1.414.387-.387 1.013-.391 1.404-.01.051.047.806.717 2.303.717 1.519 0 2.273-.689 2.305-.719.398-.374 1.027-.363 1.408.029.379.393.38 1.011-.006 1.396C21.575 29.84 20.347 31 18 31z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f484.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f484.svg new file mode 100644 index 0000000000000000000000000000000000000000..af7e86169328512f8d13b7514572037da8873f48 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f484.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA596E" d="M16.522.232c2.246 0 4.832 1.375 6.703 3.249C25.098 5.355 27 7.408 27 9.479v17.204l-15.974.031V9.582c-.093-1.506 1.075-9.35 5.496-9.35"/><path fill="#DD2E44" d="M19 11.378V28c0 1.104.896 0 2 0v2c1.104 0 2-.896 2-2V12.333c-1.258-.104-2.65-.262-4-.955z"/><path fill="#F4ABBA" d="M22.072 3.455c2.664 2.391 4.277 5.236 2.961 6.699-1.314 1.463-5.06.991-7.721-1.4-2.661-2.39-3.753-5.516-2.439-6.979 1.316-1.463 4.538-.712 7.199 1.68"/><path fill="#FFCC4D" d="M30 34c0 1.104-.896 2-2 2H10c-1.104 0-2-.896-2-2v-6c0-1.104.896-2 2-2h18c1.104 0 2 .896 2 2v6z"/><path fill="#FFAC33" d="M31 34c0 1.104-.896 2-2 2H9c-1.104 0-2-.896-2-2v-1c0-1.104.896-2 2-2h20c1.104 0 2 .896 2 2v1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f488.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f488.svg new file mode 100644 index 0000000000000000000000000000000000000000..33ed332874ddf28d03ee12eff66d54a3662cac9d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f488.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#CCD6DD" cx="18" cy="6" r="6"/><path fill="#FFF" d="M11 12h14v21H11z"/><path fill="#DD2E44" d="M11 28.487L20.251 33H25v-2.134l-14-6.83z"/><path fill="#55ACEE" d="M11 19.585l14 6.83v-4.45l-14-6.831z"/><path fill="#DD2E44" d="M13.697 12L25 17.514V12z"/><path fill="#99AAB5" d="M27 11c0 1.104-.896 2-2 2H11c-1.104 0-2-.896-2-2s.896-2 2-2h14c1.104 0 2 .896 2 2zm0 23c0 1.104-.896 2-2 2H11c-1.104 0-2-.896-2-2s.896-2 2-2h14c1.104 0 2 .896 2 2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f48d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f48d.svg new file mode 100644 index 0000000000000000000000000000000000000000..0834165960a70a35746dcb3243c820fc3a5c4064 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f48d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#9AAAB4" d="M18 12c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"/><path fill="#5DADEC" d="M29 5l-4-5H11L7 5l11 9z"/><path fill="#8CCAF7" d="M29 5l-4-5H11L7 5h11z"/><path fill="#5DADEC" d="M29 5l-4-5h-7v5h1z"/><path fill="#8CCAF7" d="M18 5h11l-11 9z"/><path fill="#9AAAB4" d="M25 13c0 1.657-1.343 3-3 3h-8c-1.657 0-3-1.343-3-3s1.343-3 3-3h8c1.657 0 3 1.343 3 3z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f48e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f48e.svg new file mode 100644 index 0000000000000000000000000000000000000000..a379f7195f971faf9da9e1b2257d6d4e4983d4da --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f48e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BDDDF4" d="M13 3H7l-7 9h10z"/><path fill="#5DADEC" d="M36 12l-7-9h-6l3 9z"/><path fill="#4289C1" d="M26 12h10L18 33z"/><path fill="#8CCAF7" d="M10 12H0l18 21zm3-9l-3 9h16l-3-9z"/><path fill="#5DADEC" d="M18 33l-8-21h16z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f490.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f490.svg new file mode 100644 index 0000000000000000000000000000000000000000..f080ef7f1593259912d3d1a553e6e6b3e8a821ca --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f490.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M35.01 30.967c-1.385-2.226-3.34-5.001-5.265-7.888-5.141-8.772-1.513-18.411-2.893-21.511-.56-1.259-3.879.966-5.555 4.563-.356-.106-.747-.156-1.17-.148.155-2.397.293-4.31-.193-5.403-.71-1.599-5.867 2.418-6.463 7.729-1.848 1.006-3.223 1.957-3.223 1.957s-.95 1.375-1.954 3.223c-5.312.594-9.331 5.753-7.732 6.464 1.097.488 3.015.349 5.421.192-.006.42.046.807.154 1.159-3.61 1.674-5.848 5.006-4.586 5.567 3.282 1.46 13.9-2.701 23.053 3.892.288.207.479.322.601.371 2.117 1.433 4.113 2.801 5.791 3.846 2.875 1.79 3.962-.007 3.962-.007s1.843-1.13.052-4.006z"/><path fill="#77B255" d="M35.029 34.828c.369-.545.338-1.278-.144-1.761 0 0-11.86-15.812-13.836-23.719-1.977-7.906-4.397-5.737-3.689.474.325 2.848 1.817 6.14 3.806 9.385l-8.941-8.941c-.546-.546-1.431-.546-1.977 0-.545.546-.546 1.431 0 1.977l8.94 8.941c-3.246-1.987-6.536-3.48-9.383-3.805-6.211-.709-8.381 1.712-.475 3.688 7.907 1.976 23.719 13.836 23.719 13.836.481.482 1.215.513 1.758.146.034.007.065.01.078-.004.025-.025.034-.059.058-.086.025-.022.059-.031.083-.056.014-.013.01-.044.003-.075z"/><path fill="#DD2E44" d="M13.771 6.871c1.807 1.806 1.721 4.819-.188 6.73-1.91 1.91-3.771.842-5.577-.964S5.132 8.97 7.042 7.06c1.91-1.91 4.924-1.995 6.729-.189z"/><path fill="#EA596E" d="M12.618 8.024c1.807 1.807 2.874 3.666.965 5.576-1.91 1.91-4.923 1.995-6.729.188-1.806-1.806-.964-5.576-.902-7.82.074-2.627 4.487-.124 6.666 2.056z"/><path fill="#DD2E44" d="M22.665 15.766c1.808 1.807 1.722 4.819-.188 6.729-1.91 1.91-3.77.842-5.576-.964-1.806-1.806-2.874-3.667-.964-5.577 1.91-1.91 4.924-1.994 6.728-.188z"/><path fill="#EA596E" d="M21.514 16.919c1.806 1.807 2.873 3.666.964 5.576-1.91 1.91-4.923 1.995-6.729.188-1.806-1.806-.964-5.575-.901-7.819.073-2.628 4.485-.125 6.666 2.055z"/><path fill="#F4900C" d="M11.203 16.11c2.369 1.052 3.327 3.876 2.139 6.308-1.187 2.434-3.354 2.085-5.723 1.033-2.37-1.052-4.045-2.407-2.857-4.841 1.188-2.432 4.071-3.551 6.441-2.5z"/><path fill="#FFCC4D" d="M10.486 17.578c2.368 1.052 4.043 2.408 2.855 4.84-1.187 2.434-4.071 3.553-6.439 2.501-2.37-1.051-2.857-4.84-3.57-6.943-.836-2.463 4.294-1.666 7.154-.398z"/><path fill="#F4900C" d="M24.93 7.012c1.143 2.447.082 5.359-2.365 6.5-2.446 1.14-3.88-.607-5.023-3.056-1.142-2.449-1.56-4.671.887-5.813 2.448-1.141 5.358-.081 6.501 2.369z"/><path fill="#FFCC4D" d="M23.453 7.7c1.141 2.449 1.559 4.671-.889 5.812-2.446 1.14-5.359.081-6.501-2.368-1.141-2.448.889-5.812 1.676-7.977.925-2.54 4.334 1.578 5.714 4.533z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4a1.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4a1.svg new file mode 100644 index 0000000000000000000000000000000000000000..88b62e387aea1c0928fea0227ab3820c4f7b4bc5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4a1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFD983" d="M29 11.06c0 6.439-5 7.439-5 13.44 0 3.098-3.123 3.359-5.5 3.359-2.053 0-6.586-.779-6.586-3.361C11.914 18.5 7 17.5 7 11.06 7 5.029 12.285.14 18.083.14 23.883.14 29 5.029 29 11.06z"/><path fill="#CCD6DD" d="M22.167 32.5c0 .828-2.234 2.5-4.167 2.5-1.933 0-4.167-1.672-4.167-2.5 0-.828 2.233-.5 4.167-.5 1.933 0 4.167-.328 4.167.5z"/><path fill="#FFCC4D" d="M22.707 10.293c-.391-.391-1.023-.391-1.414 0L18 13.586l-3.293-3.293c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414L17 15.414V26c0 .553.448 1 1 1s1-.447 1-1V15.414l3.707-3.707c.391-.391.391-1.023 0-1.414z"/><path fill="#99AAB5" d="M24 31c0 1.104-.896 2-2 2h-8c-1.104 0-2-.896-2-2v-6h12v6z"/><path fill="#CCD6DD" d="M11.999 32c-.48 0-.904-.347-.985-.836-.091-.544.277-1.06.822-1.15l12-2c.544-.098 1.06.277 1.15.822.091.544-.277 1.06-.822 1.15l-12 2c-.055.01-.111.014-.165.014zm0-4c-.48 0-.904-.347-.985-.836-.091-.544.277-1.06.822-1.15l12-2c.544-.097 1.06.277 1.15.822.091.544-.277 1.06-.822 1.15l-12 2c-.055.01-.111.014-.165.014z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4a7.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4a7.svg new file mode 100644 index 0000000000000000000000000000000000000000..3116ec31793c1fcb15914550a23b0fc3f33a3d1b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4a7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5DADEC" d="M28.344 17.768L18.148 1.09 8.7 17.654c-2.2 3.51-2.392 8.074-.081 11.854 3.285 5.373 10.363 7.098 15.811 3.857 5.446-3.24 7.199-10.22 3.914-15.597z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4b3.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4b3.svg new file mode 100644 index 0000000000000000000000000000000000000000..97641af46a3e9a7d843b1fa8d45f61250e66418c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4b3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9s0-4-4-4H4z"/><path fill="#292F33" d="M0 10h36v5H0z"/><path fill="#F4F7F9" d="M4 19h28v6H4z"/><path fill="#8899A6" d="M19 24c-1.703 0-2.341-1.21-2.469-1.801-.547.041-1.08.303-1.805.764C13.961 23.449 13.094 24 12 24c-1.197 0-1.924-.675-2-2-.003-.056.038-.188.021-.188-1.858 0-3.202 1.761-3.215 1.779-.195.267-.499.409-.806.409-.206 0-.413-.063-.591-.194-.445-.327-.542-.953-.215-1.398C5.271 22.303 7.11 20 10 20c1.937 0 2.048 1.375 2.078 1.888l.007.109c.486-.034.991-.354 1.57-.723.961-.61 2.153-1.371 3.75-.962.871.223 1.007 1.031 1.059 1.336.013.076.032.19.049.226.007 0 .146.091.577.13.82.075 1.721-.279 2.675-.653.988-.388 2.01-.788 3.111-.788 3.389 0 4.767 1.635 4.913 1.821.34.435.264 1.063-.171 1.403-.175.137-.381.207-.587.213-.307.009-.613-.123-.817-.384-.024-.027-.93-1.054-3.337-1.054-.723 0-1.528.315-2.381.649-1.009.396-2.434.789-3.496.789z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4bf.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4bf.svg new file mode 100644 index 0000000000000000000000000000000000000000..6824a06417d6f3ff609f1cac234b08554818155e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4bf.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8899A6" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18zm-18-3c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><path fill="#CCD6DD" d="M13.288 17.476c.122-1.104.598-2.101 1.343-2.846L6.686 6.686C4.182 9.19 2.51 12.521 2.102 16.233l11.186 1.243zm9.425 1.048c-.122 1.104-.598 2.101-1.343 2.846l7.944 7.944c2.504-2.504 4.176-5.835 4.584-9.547l-11.185-1.243z"/><path fill="#F5F8FA" d="M18.527 22.712l1.251 11.183c3.707-.41 7.034-2.081 9.536-4.582l-7.944-7.944c-.745.744-1.741 1.22-2.843 1.343zm-1.023-9.427L16.325 2.089c-3.749.39-7.114 2.073-9.639 4.598l7.944 7.944c.752-.751 1.759-1.229 2.874-1.346z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4cc.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4cc.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ab6da3e1472963b5864c2f25ea61e5ef1fccb4c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4cc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M23.651 23.297L12.702 12.348l9.386-7.821 9.385 9.385z"/><path fill="#DD2E44" d="M34.6 13.912c-1.727 1.729-4.528 1.729-6.255 0l-6.257-6.256c-1.729-1.727-1.729-4.53 0-6.258 1.726-1.727 4.528-1.727 6.257 0L34.6 7.656c1.728 1.727 1.728 4.529 0 6.256z"/><path fill="#99AAB5" d="M14 17.823S-.593 35.029.188 35.813C.97 36.596 18.177 22 18.177 22L14 17.823z"/><path fill="#DD2E44" d="M25.215 27.991c-1.726 1.729-4.528 1.729-6.258 0L8.009 17.041c-1.727-1.728-1.727-4.528 0-6.256 1.728-1.729 4.53-1.729 6.258 0l10.948 10.949c1.728 1.729 1.728 4.528 0 6.257z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4ce.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4ce.svg new file mode 100644 index 0000000000000000000000000000000000000000..284cf6674b65435f29233b2cf18084cb3347cd40 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4ce.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M35.354 25.254c.217-2.391-.513-4.558-2.057-6.102L17.033 2.89c-.391-.391-1.024-.391-1.414 0-.391.391-.391 1.024 0 1.414l16.264 16.263c1.116 1.117 1.642 2.717 1.479 4.506-.159 1.748-.957 3.456-2.188 4.686-1.23 1.23-2.938 2.027-4.685 2.187-1.781.161-3.39-.362-4.506-1.479L3.598 12.082c-.98-.98-1.059-2.204-.953-3.058.15-1.196.755-2.401 1.66-3.307 1.7-1.7 4.616-2.453 6.364-.707l14.85 14.849c1.119 1.12.026 2.803-.708 3.536-.733.735-2.417 1.826-3.535.707L9.962 12.789c-.391-.391-1.024-.39-1.414 0-.391.391-.391 1.023 0 1.414l11.313 11.314c1.859 1.858 4.608 1.05 6.363-.707 1.758-1.757 2.565-4.507.708-6.364L12.083 3.597c-2.62-2.62-6.812-1.673-9.192.706C1.677 5.517.864 7.147.661 8.775c-.229 1.833.312 3.509 1.523 4.721l18.384 18.385c1.365 1.365 3.218 2.094 5.281 2.094.27 0 .544-.013.82-.037 2.206-.201 4.362-1.209 5.918-2.765 1.558-1.556 2.565-3.713 2.767-5.919z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4d5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4d5.svg new file mode 100644 index 0000000000000000000000000000000000000000..701ff017c504978a35d0285a978cf449761175e2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4d5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A0041E" d="M35 26c0 2.209-1.791 4-4 4H5c-2.209 0-4-1.791-4-4V6.313C1 4.104 6.791 0 9 0h20.625C32.719 0 35 2.312 35 5.375V26z"/><path fill="#CCD6DD" d="M33 30c0 2.209-1.791 4-4 4H7c-2.209 0-4-1.791-4-4V6c0-4.119-.021-4 5-4h21c2.209 0 4 1.791 4 4v24z"/><path fill="#E1E8ED" d="M31 31c0 1.657-1.343 3-3 3H4c-1.657 0-3-1.343-3-3V7c0-1.657 1.343-3 3-3h24c1.657 0 3 1.343 3 3v24z"/><path fill="#BE1931" d="M31 32c0 2.209-1.791 4-4 4H6c-2.209 0-4-1.791-4-4V10c0-2.209 1.791-4 4-4h21c2.209 0 4 1.791 4 4v22z"/><path fill="#DD2E44" d="M29 32c0 2.209-1.791 4-4 4H6c-2.209 0-4-1.791-4-4V12c0-2.209 1.791-4 4-4h19.335C27.544 8 29 9.456 29 11.665V32z"/><path fill="#A0041E" d="M6 6C4.312 6 4.269 4.078 5 3.25 5.832 2.309 7.125 2 9.438 2H11V0H8.281C4.312 0 1 2.5 1 5.375V32c0 2.209 1.791 4 4 4h2V6H6z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4e1.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4e1.svg new file mode 100644 index 0000000000000000000000000000000000000000..dcb02946d303e46942cd50a86cd535ab83195e9c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4e1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M10.746 21.521c1.668 0 7.43 4.345 7.427 9.701.003 5.358-14.853 5.358-14.854-.001.001-5.356 5.759-9.7 7.427-9.7z"/><path fill="#CCD6DD" d="M8.541 25.182c8.839 8.84 17.337 5.163 20.033 2.469 2.695-2.696-.158-9.916-6.371-16.129C15.988 5.308 8.767 2.455 6.072 5.15 3.377 7.845-.299 16.343 8.541 25.182z"/><path fill="#66757F" d="M12.443 21.278c6.214 6.214 13.434 9.066 16.13 6.372 2.695-2.696-.158-9.916-6.371-16.129C15.988 5.308 8.767 2.455 6.072 5.15c-2.695 2.695.158 9.916 6.371 16.128z"/><path fill="#CCD6DD" d="M22.202 11.521c.443.444.443 1.163 0 1.607l-7.233 7.231c-.444.444-1.163.444-1.607 0-.444-.443-.444-1.163 0-1.607l7.232-7.231c.445-.444 1.163-.444 1.608 0z"/><path fill="#CCD6DD" d="M23.809 9.915c.887.887.887 2.327 0 3.214-.888.888-2.327.888-3.215 0-.887-.887-.887-2.327 0-3.214.887-.889 2.327-.889 3.215 0z"/><path fill="#FFAC33" d="M28.287 13.078l-.051-.001c-.552-.027-.976-.497-.949-1.048.001-.016.063-2.157-1.58-3.8-1.638-1.637-3.772-1.579-3.801-1.58-.55.033-1.021-.398-1.049-.948-.027-.552.397-1.022.949-1.049.122-.012 3.028-.123 5.314 2.163 2.287 2.288 2.17 5.191 2.164 5.314-.026.533-.468.949-.997.949z"/><path fill="#FFAC33" d="M31.846 12.522c-.109 0-.221-.019-.33-.057-.521-.183-.796-.753-.613-1.274.034-.107.893-2.876-2.195-5.963-3.126-3.127-6.126-2.414-6.252-2.382-.529.137-1.077-.184-1.216-.715-.14-.531.172-1.074.701-1.217.17-.046 4.205-1.077 8.181 2.901 4.016 4.014 2.726 7.876 2.668 8.039-.144.41-.531.668-.944.668z"/><path fill="#66757F" d="M10.914 32.521c-2.9 0-5.543-.658-7.566-1.737-.008.146-.029.29-.029.438.001 5.359 14.857 5.359 14.854.001 0-.09-.015-.177-.018-.266-1.977.976-4.496 1.564-7.241 1.564z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4e2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4e2.svg new file mode 100644 index 0000000000000000000000000000000000000000..8bd0c94fb602ab913bfaf0322e99b9c6194a4128 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4e2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M12.908 30.75c-.276 2.209-2.291 3-4.5 3s-3.776-1.791-3.5-4l1-9c.276-2.209 2.291-4 4.5-4s6.468 0 3.5 4-1 10-1 10z"/><path fill="#CCD6DD" d="M35.825 14.75c0 6.902-1.544 12.5-3.45 12.5-1.905 0-20.45-5.598-20.45-12.5 0-6.903 18.545-12.5 20.45-12.5 1.906 0 3.45 5.597 3.45 12.5z"/><ellipse fill="#66757F" cx="32.375" cy="14.75" rx="3.45" ry="12.5"/><path fill="#DD2E44" d="M17.925 21.75l-14-1c-5 0-5-12 0-12l14-1c-3 3-3 11 0 14z"/><ellipse fill="#99AAB5" cx="31.325" cy="14.75" rx="1.5" ry="4.348"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f4fb.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f4fb.svg new file mode 100644 index 0000000000000000000000000000000000000000..33808ad72ba8f52b69e95972e07e0d9fcf527762 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f4fb.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M2.697 12.389c-.391.391-.391 1.023 0 1.414s1.023.391 1.414 0l9.192-9.192c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0l-9.192 9.192z"/><path fill="#99AAB5" d="M36 32c0 4-4 4-4 4H4s-4 0-4-4V14s0-4 4-4h28c4 0 4 4 4 4v18z"/><path fill="#292F33" d="M15.561 3.061c-.391.391-1.023.391-1.414 0l-.707-.707c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l.707.707c.39.39.39 1.023 0 1.414z"/><circle fill="#292F33" cx="27.5" cy="18.5" r="5.5"/><circle fill="#292F33" cx="27.5" cy="29.5" r="3.5"/><circle fill="#66757F" cx="27.5" cy="18.5" r="3.5"/><circle fill="#66757F" cx="27.5" cy="29.5" r="1.5"/><g fill="#292F33"><circle cx="10.5" cy="25.5" r="1.5"/><circle cx="5.5" cy="25.5" r="1.5"/><circle cx="10.5" cy="20.5" r="1.5"/><circle cx="15.5" cy="20.5" r="1.5"/><circle cx="15.5" cy="25.5" r="1.5"/><circle cx="15.5" cy="30.5" r="1.5"/><circle cx="5.5" cy="30.5" r="1.5"/><circle cx="5.5" cy="20.5" r="1.5"/><circle cx="10.5" cy="15.5" r="1.5"/><circle cx="15.5" cy="15.5" r="1.5"/><circle cx="5.5" cy="15.5" r="1.5"/><circle cx="10.5" cy="30.5" r="1.5"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f50b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f50b.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd0913c63d8f51d0d6c81f82da92cf752eda54b5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f50b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#77B255" d="M30 32.7c0 1.657-5.373 3.3-12 3.3S6 34.357 6 32.7c0-1.657 5.373-2.7 12-2.7s12 1.043 12 2.7z"/><path fill="#77B255" d="M6 3h24v29.7H6z"/><ellipse fill="#5C913B" cx="18" cy="3" rx="12" ry="3"/><path fill="#FFF" d="M21.956 12.788c.091.544-.321 1.066-.922 1.136-.676.079-1.355.121-2.035.147V16a1 1 0 0 1-2 0v-1.93a26.188 26.188 0 0 1-2.035-.147c-.601-.07-1.012-.591-.922-1.136a1.042 1.042 0 0 1 1.152-.851c.6.07 1.202.109 1.804.133V10a1 1 0 0 1 2 0v2.07a24.781 24.781 0 0 0 1.804-.133 1.042 1.042 0 0 1 1.154.851zm-1.652 17.746a21.119 21.119 0 0 1-4.607 0 1.048 1.048 0 0 0-1.153.854c-.091.544.326 1.067.934 1.134 1.676.184 3.368.184 5.044 0 .609-.067 1.026-.59.934-1.134a1.047 1.047 0 0 0-1.152-.854z"/><ellipse fill="#CCD6DD" cx="18" cy="3" rx="10" ry="2"/><path fill="#99AAB5" d="M14 1v1.5c0 .552 1.791 1 4 1s4-.448 4-1V1h-8z"/><ellipse fill="#CCD6DD" cx="18" cy="1" rx="4" ry="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f511.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f511.svg new file mode 100644 index 0000000000000000000000000000000000000000..7b4dc2a73dc757743787fcbd9aacfb9710d8df3e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f511.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M32.614 3.414C28.31-.89 21.332-.89 17.027 3.414c-3.391 3.392-4.098 8.439-2.144 12.535l-3.916 3.915c-.64.641-.841 1.543-.625 2.359l-1.973 1.972c-.479-.48-1.252-.48-1.731 0l-1.731 1.732c-.479.479-.479 1.253 0 1.732l-.867.864c-.479-.478-1.253-.478-1.731 0l-.866.867c-.479.479-.479 1.253 0 1.732.015.016.036.02.051.033-.794 1.189-.668 2.812.382 3.863 1.195 1.195 3.134 1.195 4.329 0L20.08 21.144c4.097 1.955 9.144 1.247 12.535-2.146 4.302-4.302 4.302-11.28-.001-15.584zm-1.731 5.195c-.957.956-2.509.956-3.464 0-.956-.956-.956-2.507 0-3.464.955-.956 2.507-.956 3.464 0 .956.957.956 2.508 0 3.464z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f525.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f525.svg new file mode 100644 index 0000000000000000000000000000000000000000..e7dee6dd270bec54e4803ffa319162c3b8dd53b0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f525.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M35 19c0-2.062-.367-4.039-1.04-5.868-.46 5.389-3.333 8.157-6.335 6.868-2.812-1.208-.917-5.917-.777-8.164.236-3.809-.012-8.169-6.931-11.794 2.875 5.5.333 8.917-2.333 9.125-2.958.231-5.667-2.542-4.667-7.042-3.238 2.386-3.332 6.402-2.333 9 1.042 2.708-.042 4.958-2.583 5.208-2.84.28-4.418-3.041-2.963-8.333C2.52 10.965 1 14.805 1 19c0 9.389 7.611 17 17 17s17-7.611 17-17z"/><path fill="#FFCC4D" d="M28.394 23.999c.148 3.084-2.561 4.293-4.019 3.709-2.106-.843-1.541-2.291-2.083-5.291s-2.625-5.083-5.708-6c2.25 6.333-1.247 8.667-3.08 9.084-1.872.426-3.753-.001-3.968-4.007C7.352 23.668 6 26.676 6 30c0 .368.023.73.055 1.09C9.125 34.124 13.342 36 18 36s8.875-1.876 11.945-4.91c.032-.36.055-.722.055-1.09 0-2.187-.584-4.236-1.606-6.001z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f526.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f526.svg new file mode 100644 index 0000000000000000000000000000000000000000..1aff8ae2c0d7f4aad2fa9c566124011116723fcb --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f526.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M23 17l1-1s1-1 2 0l2 2s1 1 0 2l-1 1-4-4z"/><path fill="#8899A6" d="M34.879 27.879c1.166 1.166 1.166 3.076 0 4.242l-2.758 2.758c-1.166 1.166-3.076 1.166-4.242 0L9.121 16.121c-1.167-1.166-1.167-3.076 0-4.242l2.758-2.758c1.167-1.167 3.076-1.167 4.242 0l18.758 18.758z"/><path fill="#66757F" d="M20.879 10.879c1.166 1.167 1.166 3.076 0 4.242l-5.758 5.758c-1.167 1.166-3.076 1.166-4.242 0L6 16s-1-1 0-2l8-8c1-1 2 0 2 0l4.879 4.879z"/><path fill="#8899A6" d="M7 17L17 7l2 2L9 19z"/><path d="M11.001 6c-.367 0-.72-.202-.896-.553l-2-4C7.858.953 8.059.353 8.553.105c.495-.248 1.095-.047 1.342.447l2 4c.247.494.047 1.095-.447 1.342-.144.072-.297.106-.447.106zm-6.002 6c-.15 0-.303-.034-.446-.106l-4-2c-.494-.247-.695-.847-.448-1.341.247-.494.847-.695 1.342-.447l4 2c.494.247.694.848.447 1.342-.175.35-.528.552-.895.552zM8 9c-.256 0-.512-.098-.707-.293l-4-4c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l4 4c.391.391.391 1.023 0 1.414C8.512 8.902 8.256 9 8 9z" fill="#FFCC4D"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f52c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f52c.svg new file mode 100644 index 0000000000000000000000000000000000000000..e910ee894e4a8f20ba9fca1cb91eed5446a921fd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f52c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><g fill="#66757F"><path d="M19.78 21.345l-6.341-6.342-.389 4.38 2.35 2.351z"/><path d="M15.4 22.233c-.132 0-.259-.053-.354-.146l-2.351-2.351c-.104-.104-.158-.25-.145-.397l.389-4.38c.017-.193.145-.359.327-.425.182-.067.388-.021.524.116l6.341 6.342c.138.138.183.342.116.524s-.232.31-.426.327l-4.379.389-.042.001zm-1.832-3.039l2.021 2.021 3.081-.273-4.828-4.828-.274 3.08z"/></g><path fill="#8899A6" d="M31 32h-3c0-3.314-2.63-6-5.875-6-3.244 0-5.875 2.686-5.875 6H8.73c0-1.104-.895-2-2-2-1.104 0-2 .896-2 2-1.104 0-2 .896-2 2s.896 2 2 2H31c1.104 0 2-.896 2-2s-.896-2-2-2z"/><path fill="#8899A6" d="M20 10v4c3.866 0 7 3.134 7 7s-3.134 7-7 7h-8.485c2.018 2.443 5.069 4 8.485 4 6.075 0 11-4.925 11-11s-4.925-11-11-11z"/><path fill="#67757F" d="M16.414 30.414c-.781.781-2.047.781-2.828 0l-9.899-9.9c-.781-.781-.781-2.047 0-2.828.781-.781 2.047-.781 2.829 0l9.899 9.9c.78.781.78 2.047-.001 2.828zm-7.225-1.786c.547-.077 1.052.304 1.129.851.077.547-.305 1.053-.851 1.129l-5.942.834c-.547.077-1.052-.305-1.129-.851-.077-.547.305-1.053.852-1.13l5.941-.833z"/><path fill="#66757F" d="M27.341 2.98l4.461 4.461-3.806 3.807-4.461-4.461z"/><path fill="#AAB8C2" d="M34.037 7.083c-.827.827-2.17.827-2.997 0l-3.339-3.34c-.827-.826-.827-2.169 0-2.996.827-.826 2.17-.826 2.995 0l3.342 3.34c.826.827.826 2.168-.001 2.996zm-14.56 15.026l-6.802-6.803c-.389-.389-.389-1.025 0-1.414l9.858-9.858c.389-.389 1.025-.389 1.414 0l6.801 6.803c.389.389.389 1.025 0 1.414l-9.858 9.858c-.388.389-1.024.389-1.413 0z"/><path fill="#E1E8ED" d="M13.766 12.8l1.638-1.637 8.216 8.216-1.638 1.637z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f52d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f52d.svg new file mode 100644 index 0000000000000000000000000000000000000000..113c0330a8f3e26a7854fbb500ebba069906b5a8 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f52d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#9AAAB4" cx="17" cy="20" r="3"/><path fill="#DA2F47" d="M19.235 17.059c-.259.485-.868.671-1.353.412L5.529 10.883c-.485-.259-.67-.868-.412-1.353L7.94 4.235c.259-.485.868-.67 1.353-.412l12.353 6.588c.485.259.671.868.412 1.353l-2.823 5.295z"/><path fill="#DA2F47" d="M31.177 22.293c-.259.485-.868.671-1.354.412l-9.705-5.176c-.485-.259-.671-.868-.412-1.354l1.882-3.529c.259-.485.868-.67 1.354-.412l9.705 5.176c.485.259.671.868.412 1.354l-1.882 3.529z"/><path fill="#BB1A34" d="M19.235 17.058l2.824-5.293 1.765.941L20.999 18z"/><path fill="#9D0522" d="M28.942 22.235l2.823-5.294 3.53 1.882-2.824 5.294z"/><path fill="#292F33" d="M8.294 7.824l1.882-3.53-.881-.47v-.001L4.882 1.471c-.485-.259-1.094-.074-1.353.411L.706 7.177c-.259.486-.074 1.094.412 1.353l3.529 1.882 1.766.941.47-.882 1.411-2.647zM23 25c0 1.104-.896 2-2 2h-8c-1.104 0-2-.896-2-2s.896-2 2-2h8c1.104 0 2 .896 2 2z"/><path d="M9.467 36l3.344-7.152c.468-1 .036-2.191-.965-2.658-1-.469-2.191-.037-2.658.965L5.052 36h4.415zm15.065 0h4.416l-4.137-8.846c-.467-1.002-1.658-1.434-2.658-.965-1.001.467-1.433 1.658-.965 2.658L24.532 36zM19 36v-8c0-1.104-.896-2-2-2s-2 .896-2 2v8h4z" fill="#9AAAB4"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f52e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f52e.svg new file mode 100644 index 0000000000000000000000000000000000000000..d7e09232d7e87443795207ff14d3e6e37c568b92 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f52e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BF6952" d="M28.736 28.767l-21.458.076-1.649 4.835c-.062.187-.101.387-.073.582.145.984.993 1.74 2.017 1.74h20.894c1.024 0 1.872-.756 2.017-1.74.029-.195-.01-.395-.073-.582l-1.675-4.911z"/><path fill="#854836" d="M28.736 28.767l-.19-.556c-.199-.598-.759-1.001-1.389-1.001H8.883c-.63 0-1.19.403-1.389 1.001l-.216.632c2.928 2.344 6.636 3.754 10.678 3.754 4.088 0 7.837-1.438 10.78-3.83z"/><circle fill="#AA8DD8" cx="17.956" cy="15.488" r="15.288"/><circle fill="#744EAA" cx="23.266" cy="12.37" r="4.195"/><circle fill="#744EAA" cx="14.875" cy="18.662" r="3.146"/><circle fill="#744EAA" cx="15.924" cy="5.028" r="2.098"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f54a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f54a.svg new file mode 100644 index 0000000000000000000000000000000000000000..613e4956d71d0d051302b5e59ced067fcdfa816a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f54a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M.794 16.112c1 0 5.875 1.344 6.5 2.312L6.013 18.3s-3.906-1.25-4.906-1.25c-1.001 0-.313-.938-.313-.938z"/><path fill="#99AAB5" d="M11 2c1 1 3 7 3 10s-2 6 2 8 5.001-1 5.001-5S20 7 19 5s-2 0-2 0-1-4-2-4-1 2-1 2-2-2-3-2 0 1 0 1z"/><path fill="#CCD6DD" d="M10 15c3 0 4 4 6 4s1-3 3-3 10-5 10-11 3-3 3-1c1 0 2 1.586 2 3 0 1 0 2-1 3 1 0 2 2 1 3 1 3-1 6-3 7 0 1-2 3-4 2 0 0-1 3-3 2 0 0 3.052 1.684 4 2 3 1 7 1 7 1s0 1-2 2c0 0 1 1 0 2s-2 1-2 1 1 2-2 1-6-4-6-4-5 1-9-1-6-6-6-8-3-1-4-1 2-2 3-2c0 0 0-2 3-2z"/><path fill="#5C913B" d="M6.95 18.019s5.438 2.625 7.938 6.656c1.9 3.064 2.782 8.656 2.782 8.656s.043.564-.907-2.281c-1-3-2.217-6.288-4.312-8.188-3.344-3.031-4.75-3.5-6.062-4.25-.332-.189.217-.687.561-.593z"/><path fill="#5C913B" d="M16.198 28.54s2.038.103 3.107 2.139c1.068 2.036-.053 4.914-.053 4.914s-2.75-1.268-3.462-2.947c-.712-1.68.408-4.106.408-4.106zm-2.133-4.778s1.274 1.437 3.558 1.705c2.284.269 4.121-1.379 4.121-1.379s-2.144-1.97-3.968-2.033c-1.823-.065-3.711 1.707-3.711 1.707zm-4.047-3.148s-2.015.329-2.85 2.472.425 4.01.425 4.01 2.534-.848 3.055-2.597c.521-1.747-.63-3.885-.63-3.885z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f58c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f58c.svg new file mode 100644 index 0000000000000000000000000000000000000000..b39bcbc9dd7e641ddaa4cb39137aab9ce227842c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f58c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3B88C3" d="M14.57 27.673c2.814-1.692 6.635-3.807 9.899-7.071 7.03-7.029 12.729-16.97 11.314-18.385C34.369.803 24.428 6.502 17.398 13.531c-3.265 3.265-5.379 7.085-7.071 9.899l4.243 4.243z"/><path fill="#C1694F" d="M.428 34.744s7.071 1.414 12.021-3.536c2.121-2.121 2.121-4.949 2.121-4.949l-2.829-2.829s-3.535.708-4.95 2.122c-1.414 1.414-2.518 4.232-2.888 5.598-.676 2.502-3.475 3.594-3.475 3.594z"/><path fill="#CCD6DD" d="M17.882 25.328l-5.168-5.168c-.391-.391-.958-.326-1.27.145l-1.123 1.705c-.311.471-.271 1.142.087 1.501l4.122 4.123c.358.358 1.03.397 1.501.087l1.705-1.124c.472-.311.536-.878.146-1.269z"/><path fill="#A0041E" d="M11.229 32.26c-1.191.769-1.826.128-1.609-.609.221-.751-.12-1.648-1.237-1.414-1.117.233-1.856-.354-1.503-1.767.348-1.393-1.085-1.863-1.754-.435-.582 1.16-1.017 2.359-1.222 3.115-.677 2.503-3.476 3.595-3.476 3.595s5.988 1.184 10.801-2.485z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f58d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f58d.svg new file mode 100644 index 0000000000000000000000000000000000000000..5a4cbe8e1a8c340ea21d68ebbbb08b8098d408bd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f58d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M35.702 7.477L28.522.298c-.396-.397-1.038-.397-1.436 0L3.395 23.989c-.397.397-.397 1.038 0 1.437.72.719-3.14 7.959-3.395 8.496L2.068 36c.536-.255 7.785-4.115 8.506-3.395.397.397 1.039.397 1.436 0L35.702 8.913c.397-.396.397-1.039 0-1.436z"/><path fill="#EA596E" d="M4.139 23.24L26.407.972l8.62 8.62L12.759 31.86z"/><path fill="#292F33" d="M23.534 3.846l1.437-1.436 8.62 8.62-1.437 1.436zM5.576 21.803l1.436-1.437 8.62 8.62-1.437 1.437z"/><path fill="#BE1931" d="M26.886 9.353c-1.521-1.521-5.982.476-9.967 4.459-3.983 3.984-5.979 8.446-4.459 9.967 1.52 1.521 5.983-.476 9.967-4.459 3.983-3.984 5.979-8.447 4.459-9.967z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f5ff.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f5ff.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ba18be1f93401c3e694f86302c9beb166d617df --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f5ff.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M8 27s-2 4-2 6 4 3 12 3 12-1 12-3-2-6-2-6H8zM9 6C6 6 6 7 5 16c-.994 8.945 0 10 4 10 2 0 2-20 0-20zm18 0c3 0 3 1 4 10 .994 8.945 0 10-4 10-2 0-2-20 0-20z"/><path fill="#CCD6DD" d="M8 3s1-3 10-3 10 3 10 3 1 6 1 14-1 14-1 14-1 2-10 2-10-2-10-2-1-3-1-14S8 3 8 3z"/><path fill="#66757F" d="M28 8c0-1-3-4-10-4S8 7 8 8c0 .807 4.548 1.612 6.311 1.894C14.999 12.548 15 18 15 18c.805-3.218.315-7.079.093-8.467C15.295 8.942 15.941 8 18 8c3 0 3 2 3 2h.002c-.234 1.657-.566 5.089.162 8 0 0 .002-5.491.697-8.134C23.727 9.562 28 8.782 28 8z"/><path fill="#66757F" d="M14 20c0-1 2-3 4-3s4 2 4 3-1 1-4 1-4 0-4-1zm-2 4s2-2 6-2 6 2 6 2-2-1-6-1-6 1-6 1zm0 2c0-1 2-2 6-2s6 1 6 2-1 1-6 1-6 0-6-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f680.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f680.svg new file mode 100644 index 0000000000000000000000000000000000000000..8658d4397b8cb7f1f0b4b6643bd67a04946d3a5a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f680.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A0041E" d="M1 17l8-7 16 1 1 16-7 8s.001-5.999-6-12-12-6-12-6z"/><path fill="#FFAC33" d="M.973 35s-.036-7.979 2.985-11S15 21.187 15 21.187 14.999 29 11.999 32c-3 3-11.026 3-11.026 3z"/><circle fill="#FFCC4D" cx="8.999" cy="27" r="4"/><path fill="#55ACEE" d="M35.999 0s-10 0-22 10c-6 5-6 14-4 16s11 2 16-4c10-12 10-22 10-22z"/><path d="M26.999 5c-1.623 0-3.013.971-3.641 2.36.502-.227 1.055-.36 1.641-.36 2.209 0 4 1.791 4 4 0 .586-.133 1.139-.359 1.64 1.389-.627 2.359-2.017 2.359-3.64 0-2.209-1.791-4-4-4z"/><path fill="#A0041E" d="M8 28s0-4 1-5 13.001-10.999 14-10-9.001 13-10.001 14S8 28 8 28z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f681.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f681.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b7a40320cb3144cc0d8d6586b11bce963145ac4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f681.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M16.26 26h2v5h-2zm-8 0h2v5h-2z"/><ellipse fill="#99AAB5" cx="6.259" cy="3" rx="6" ry="1"/><ellipse fill="#99AAB5" cx="20.259" cy="3" rx="6" ry="1"/><path fill="#99AAB5" d="M12.26 3h2v6h-2z"/><ellipse fill="#66757F" cx="13.259" cy="3" rx="2" ry="1"/><path fill="#FFCC4D" d="M34.259 10c0-3 0-7-1-7s-3 4-4 6 5 1 5 1z"/><path fill="#FFCC4D" d="M34.259 10c0-2.209-8-3-19-3h-2C6.632 7 .509 12.451.509 18.25S4.259 28 13.259 28s12-4.701 12-10.5c0-.881-.138-1.731-.371-2.549C29.259 14 34.259 12.006 34.259 10z"/><path fill="#3B88C3" d="M4.259 13c-2.091 2.918-3.068 7.589 1.213 7.784 4.787.216 6.787.216 7.85-2.372 1.364-3.32.937-7.413-.276-8.195-2.32-1.497-6.695-.135-8.787 2.783zm16.841-.465C23.259 16 23.17 18.696 19.259 20c-3 1-4-2-3.841-5.535.112-2.483.206-4.195 1.841-4.465 1.447-.24 2.526.426 3.841 2.535z"/><path fill="#99AAB5" d="M31.441 7.114c.903 1.273 1.271 2.564.82 2.884-.45.32-1.548-.454-2.451-1.726-.903-1.273-1.271-2.564-.82-2.884.45-.321 1.547.453 2.451 1.726z"/><path fill="#99AAB5" d="M34.72 11.735c.909 1.279 1.28 2.575.83 2.894-.45.32-1.553-.458-2.46-1.737-.909-1.279-1.279-2.576-.829-2.896.45-.318 1.551.46 2.459 1.739z"/><path fill="#66757F" d="M33.076 9.419c.319.45.214 1.074-.236 1.394-.45.32-1.074.214-1.395-.236-.319-.45-.214-1.074.237-1.394.451-.321 1.075-.214 1.394.236z"/><path fill="#99AAB5" d="M25.26 32c0 1.104-.896 2-2 2h-20c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f686.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f686.svg new file mode 100644 index 0000000000000000000000000000000000000000..3f5f5b85617cca19a3cdc659aa4b19a45519c882 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f686.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A7A9AC" d="M2 36h32L23 19H13z"/><path fill="#58595B" d="M5 36h26L21 19h-6z"/><path fill="#808285" d="M8 36h20l-9-17h-2z"/><path fill="#A7A9AC" d="M28 35c0 .553-.447 1-1 1H9c-.552 0-1-.447-1-1 0-.553.448-1 1-1h18c.553 0 1 .447 1 1zm-2-4c0 .553-.447 1-1 1H11c-.552 0-1-.447-1-1 0-.553.448-1 1-1h14c.553 0 1 .447 1 1z"/><path fill="#58595B" d="M27.076 25.3L23 19H13l-4.076 6.3c1.889 2.517 4.798 4.699 9.076 4.699 4.277 0 7.188-2.183 9.076-4.699z"/><path fill="#A7A9AC" d="M18 0C9 0 6 3 6 9v8c0 1.999 3 11 12 11s12-9.001 12-11V9c0-6-3-9-12-9z"/><path fill="#E6E7E8" d="M8 11C8 2 12.477 1 18 1s10 1 10 10c0 6-4.477 11-10 11-5.523-.001-10-5-10-11z"/><path fill="#FFAC33" d="M18 21.999c1.642 0 3.185-.45 4.553-1.228C21.77 19.729 20.03 19 18 19s-3.769.729-4.552 1.772c1.366.777 2.911 1.227 4.552 1.227z"/><path d="M19 4.997v4.965c3.488-.232 6-1.621 6-2.463V5.833c0-.791-3.692-.838-6-.836zm-2 0c-2.308-.002-6 .044-6 .836V7.5c0 .842 2.512 2.231 6 2.463V4.997z" fill="#55ACEE"/><path fill="#269" d="M6 10s0 3 4 9c0 0-4-2-4-6v-3zm24 0s0 3-4 9c0 0 4-2 4-6v-3z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f68b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f68b.svg new file mode 100644 index 0000000000000000000000000000000000000000..da204b81a3b0904773dfad616f35ac606c168485 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f68b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#939598" d="M0 34h36v2H0z"/><path fill="#58595B" d="M10 32c0-1.657-1.344-3-3-3s-3 1.343-3 3 1.343 3 3 3 3-1.343 3-3z"/><path fill="#292F33" d="M9 32c0-1.105-.896-2-2-2s-2 .895-2 2 .896 2 2 2 2-.895 2-2z"/><circle fill="#58595B" cx="29" cy="32" r="3"/><circle fill="#292F33" cx="29" cy="32" r="2"/><path fill="#E6E7E8" d="M34 2H2c-.552 0-1-.448-1-1s.448-1 1-1h32c.553 0 1 .448 1 1s-.447 1-1 1z"/><path fill="#66757F" d="M22.998 4.944c-.016-.284-.151-.548-.373-.726l-3.683-2.945c.087-.302.049-.635-.162-.898-.314-.394-.859-.468-1.281-.221-.42-.248-.966-.174-1.281.221-.211.264-.25.597-.162.898l-3.682 2.945c-.222.178-.358.441-.374.726-.016.284.09.561.291.762l3.835 3.834c-.198.377-.152.848.165 1.165.197.197.453.295.709.295.176 0 .344-.063.5-.155.156.091.324.155.5.155.256 0 .512-.098.707-.293.317-.317.363-.788.165-1.165l3.835-3.835c.201-.202.308-.479.291-.763zM17.5 8.085l-3.003-3.003L17.5 2.68l3.003 2.403L17.5 8.085z"/><path fill="#BCBEC0" d="M30 10c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2z"/><path fill="#E6E7E8" d="M36 22c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-8c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v8zM0 28h36v4H0z"/><path fill="#BE1931" d="M0 14h36v14H0z"/><path fill="#DD2E44" d="M36 14H0v10h6v6h7v-6h10v6h7v-6h6z"/><path fill="#55ACEE" d="M2 16H0v10h2c1.104 0 2-.896 2-2v-6c0-1.104-.896-2-2-2zm34 0h-2c-1.104 0-2 .896-2 2v6c0 1.104.896 2 2 2h2V16zm-15 6c0 .553-.448 1-1 1h-4c-.553 0-1-.447-1-1v-4c0-.553.448-1 1-1h4c.552 0 1 .447 1 1v4zm-9 1c0 .553-.448 1-1 1H8c-.552 0-1-.447-1-1v-5c0-.552.448-1 1-1h3c.552 0 1 .448 1 1v5zm17 0c0 .553-.447 1-1 1h-3c-.553 0-1-.447-1-1v-5c0-.552.447-1 1-1h3c.553 0 1 .448 1 1v5z"/><path fill="#A0041E" d="M0 28h36v2H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f68d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f68d.svg new file mode 100644 index 0000000000000000000000000000000000000000..68ca65faa0734112506a2f79b3fb6a1a4c2eff52 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f68d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M11 34c0 1.104-.896 2-2 2H7c-1.104 0-2-.896-2-2v-7c0-1.104.896-2 2-2h2c1.104 0 2 .896 2 2v7zm20 0c0 1.104-.896 2-2 2h-2c-1.104 0-2-.896-2-2v-7c0-1.104.896-2 2-2h2c1.104 0 2 .896 2 2v7z"/><path fill="#99AAB5" d="M3 17c0 .553-.448 1-1 1H1c-.552 0-1-.447-1-1v-7c0-.552.448-1 1-1h1c.552 0 1 .448 1 1v7zm33 0c0 .553-.447 1-1 1h-1c-.553 0-1-.447-1-1v-7c0-.552.447-1 1-1h1c.553 0 1 .448 1 1v7z"/><path fill="#99AAB5" d="M35 11c0 .552-.447 1-1 1H2c-.552 0-1-.448-1-1s.448-1 1-1h32c.553 0 1 .448 1 1zm0 4c0 .553-.447 1-1 1H2c-.552 0-1-.447-1-1 0-.553.448-1 1-1h32c.553 0 1 .447 1 1z"/><path fill="#CCD6DD" d="M24 2c0 1.104-.896 2-2 2h-8c-1.104 0-2-.896-2-2s.896-2 2-2h8c1.104 0 2 .896 2 2z"/><path fill="#CCD6DD" d="M28 2H8C5.791 2 4 3.791 4 6v26h28V6c0-2.209-1.791-4-4-4z"/><path fill="#FFCC4D" d="M4 16h28v16H4z"/><path fill="#66757F" d="M33 32c0 .553-.447 1-1 1H4c-.552 0-1-.447-1-1v-1c0-.553.448-1 1-1h28c.553 0 1 .447 1 1v1zm-1-15c0 1.657-1.343 3-3 3H7c-1.657 0-3-1.343-3-3v-7c0-1.657 1.343-3 3-3h22c1.657 0 3 1.343 3 3v7z"/><path fill="#88C9F9" d="M30 16c0 1.104-.896 2-2 2H8c-1.104 0-2-.895-2-2v-5c0-1.104.896-2 2-2h20c1.104 0 2 .895 2 2v5z"/><path fill="#FFAC33" d="M4 25h28v5H4z"/><path fill="#FFF" d="M6 25h6v3H6zm18 0h6v3h-6z"/><path fill="#DD2E44" d="M4 25h2v3H4zm26 0h2v3h-2z"/><path fill="#66757F" d="M14 25h8v3h-8z"/><path fill="#292F33" d="M22 3.5c0 .829-.672 1.5-1.5 1.5h-5c-.829 0-1.5-.671-1.5-1.5S14.671 2 15.5 2h5c.828 0 1.5.671 1.5 1.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f695.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f695.svg new file mode 100644 index 0000000000000000000000000000000000000000..5446414a25448c516d38a51ef4d24c030b7c4d88 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f695.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M21.377 15.449c.089.816-.83 1.495-2.053 1.515-1.223.02-2.095-.635-1.947-1.463l.356-2c.147-.829.938-1.5 1.767-1.5.828 0 1.572.662 1.661 1.478l.216 1.97z"/><path fill="#FFCC4D" d="M32.246 21h-.135l-.444-3c-.327-2.209-1.864-4-3.433-4H16.162c-1.569 0-3.574 1.791-4.478 4l-1.228 3H6.911c-2.073 0-4.104 1.791-4.538 4l-.588 3c-.001.008 0 .015-.002.021C.782 28.132 0 28.97 0 30c0 1.104.896 2 2 2h30c2.209 0 4-1.791 4-4v-3c0-2.209-1.681-4-3.754-4z"/><circle fill="#292F33" cx="10" cy="31" r="4"/><circle fill="#CCD6DD" cx="10" cy="31" r="2"/><circle fill="#292F33" cx="27" cy="31" r="4"/><circle fill="#CCD6DD" cx="27" cy="31" r="2"/><path fill="#F4900C" d="M2.373 25l-.196 1H36v-1c0-.348-.055-.679-.133-1H2.702c-.141.321-.261.652-.329 1z"/><path d="M24 21h5.92c-.014-.416-.064-.908-.156-1.5-.395-2.5-.552-3.5-3.437-3.5H24v5zm-2-5h-5c-1.594 0-3.236 1.567-3.847 3.5-.194.599-.353 1.088-.472 1.5H22v-5z" fill="#55ACEE"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f697.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f697.svg new file mode 100644 index 0000000000000000000000000000000000000000..97b5f10d4c5a03f11f60a7352e030ec5b2749936 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f697.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M13 32h20s3 0 3-4c0-2 0-6-1-7s-8-7-11-7h-6c-3 0-10 7-10 7l-4 1s-3 1-3 3v3s-1 .338-1 1.957C0 32 2 32 2 32h11z"/><path fill="#BBDDF5" d="M20 16h-2c-2 0-8 6-8 6s4.997-.263 10-.519V16zm10 3c-1-1-5-3-7-3h-1v5.379c4.011-.204 7.582-.379 8-.379 1 0 1-1 0-2z"/><circle fill="#292F33" cx="10" cy="31" r="4"/><circle fill="#CCD6DD" cx="10" cy="31" r="2"/><circle fill="#292F33" cx="27" cy="31" r="4"/><circle fill="#CCD6DD" cx="27" cy="31" r="2"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f69a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f69a.svg new file mode 100644 index 0000000000000000000000000000000000000000..7441d1bba8047ab7841d8bb412f05eb54688677d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f69a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4v-3c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v3z"/><path fill="#FFCC4D" d="M19 13l-.979-1H7.146C4 12 3 14 3 14l-3 5.959V25h19V13z"/><path fill="#55ACEE" d="M9 20H2l2-4s1-2 3-2h2v6z"/><circle fill="#292F33" cx="9" cy="31" r="4"/><circle fill="#CCD6DD" cx="9" cy="31" r="2"/><circle fill="#292F33" cx="27" cy="31" r="4"/><circle fill="#CCD6DD" cx="27" cy="31" r="2"/><path fill="#CCD6DD" d="M32 8H17c-2.209 0-4 1.791-4 4v13h23V12c0-2.209-1.791-4-4-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f69c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f69c.svg new file mode 100644 index 0000000000000000000000000000000000000000..014ca11d340ab3f52e4133118591e361062f352a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f69c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M11 11h3v9h-3z"/><path fill="#77B255" d="M24 26.157C24 28.832 22.354 31 20.325 31H4.709c-2.029 0-3.488-1.565-3.258-3.494l.625-5.241c.23-1.93 1.992-3.808 3.928-4.199l14.628-3.21C22.496 14.413 24 16.219 24 18.893v7.264z"/><path fill="#292F33" d="M16.535 24.167C16.239 26.283 17.791 28 20 28h9c2.209 0 4-1.717 4-3.833V8.833C33 6.716 31.547 5 29.755 5h-7.303c-1.792 0-3.484 1.716-3.78 3.833l-2.137 15.334z"/><path fill="#BBDDF5" d="M18.245 25c-.135 1.104.65 2 1.755 2h9c1.104 0 2-.896 2-2V11c0-1.104-.743-2-1.66-2h-7.473c-.917 0-1.771.896-1.906 2l-1.716 14z"/><path fill="#77B255" d="M15 21h18v10H15z"/><path fill="#FFCC4D" d="M33 23H2l1-2h30z"/><circle fill="#292F33" cx="8" cy="31" r="4"/><circle fill="#FFCC4D" cx="8" cy="31" r="2"/><path fill="#77B255" d="M33 16v4l-10 9-7-1 3-10 3-2z"/><path fill="#292F33" d="M18.222 26.111c0-4.91 3.979-8.889 8.889-8.889 4.91 0 8.889 3.979 8.889 8.889C36 31.021 32.021 35 27.111 35c-4.91 0-8.889-3.979-8.889-8.889z"/><path fill="#FFCC4D" d="M32.667 26.111c0 3.068-2.487 5.556-5.556 5.556-3.068 0-5.556-2.487-5.556-5.556 0-3.068 2.487-5.556 5.556-5.556 3.069.001 5.556 2.488 5.556 5.556z"/><path fill="#FFE8B6" d="M30.444 26.111c0 1.841-1.492 3.333-3.333 3.333-1.842 0-3.334-1.492-3.334-3.333 0-1.842 1.492-3.334 3.334-3.334 1.841 0 3.333 1.493 3.333 3.334z"/><path fill="#77B255" d="M32.588 7c-.552-1.187-1.606-2-2.833-2h-7.303c-1.227 0-2.395.813-3.112 2h13.248z"/><path fill="#F4900C" d="M29.333 26.111c0 1.227-.995 2.222-2.222 2.222-1.227 0-2.223-.995-2.223-2.222 0-1.227.995-2.223 2.223-2.223 1.227.001 2.222.996 2.222 2.223z"/><circle fill="#F4900C" cx="8" cy="31" r="1"/><path fill="#66757F" d="M11 13h3v2h-3z"/><path fill="#5C913B" d="M16 28.75c-.094 0-.19-.013-.285-.041-.529-.157-.832-.714-.675-1.243l2-6.75C17.421 18.796 19.188 15 23 15h10c.553 0 1 .448 1 1s-.447 1-1 1H23c-3.144 0-4.011 4.154-4.02 4.196l-2.021 6.838c-.129.435-.527.716-.959.716z"/><path fill="#3E721D" d="M2.001 29c-.042 0-.083-.003-.125-.008-.548-.068-.937-.568-.868-1.116l1-8c.068-.549.569-.936 1.116-.868.548.068.937.568.868 1.116l-1 8c-.063.506-.494.876-.991.876z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6a0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a0.svg new file mode 100644 index 0000000000000000000000000000000000000000..8510956dc2af6d3a3b7b1e2ebe46170cc634781b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#58595B" d="M19 12V5h-2v7h-5v5h12v-5z"/><path fill="#FFD983" d="M34 28V18c0-2.209-1.791-4-4-4H6c-2.209 0-4 1.791-4 4v10h32z"/><path fill="#269" d="M2 22v6c0 4.418 3.582 8 8 8h16c4.418 0 8-3.582 8-8v-6H2z"/><path fill="#88C9F9" d="M2 18h6v9H2zm8 0h7v9h-7zm9 0h7v9h-7zm9 0h6v9h-6z"/><path fill="#6D6E71" d="M33.213 10.977L3.27 2.954c-.533-.144-.85-.691-.707-1.226.143-.533.691-.85 1.225-.707L33.73 9.045c.534.144.851.691.707 1.225-.142.534-.69.851-1.224.707z"/><path fill="#A7A9AC" d="M23.348 4.361l-1.933-.518.259-.965-5.795-1.553-.259.966-1.932-.518c-1.067-.285-2.164.348-2.45 1.415-.286 1.066.348 2.163 1.414 2.449l9.66 2.588c1.066.286 2.163-.348 2.449-1.414.286-1.066-.347-2.164-1.413-2.45z"/><path fill="#808285" d="M13.877 4.931c-.286 1.066-1.383 1.7-2.45 1.414-1.066-.286-1.7-1.383-1.414-2.449.286-1.067 1.383-1.7 2.449-1.415 1.068.286 1.701 1.382 1.415 2.45zm11.592 3.105c-.286 1.067-1.383 1.7-2.449 1.414-1.067-.286-1.7-1.382-1.414-2.449.285-1.067 1.382-1.7 2.449-1.414 1.066.286 1.7 1.383 1.414 2.449z"/><path fill="#55ACEE" d="M2 18h6v2H2zm8 0h7v2h-7zm9 0h7v2h-7zm9 0h6v2h-6z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6a2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a2.svg new file mode 100644 index 0000000000000000000000000000000000000000..79077f00a46c9e6204450bc2ffefc79aaadea8fe --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M16 0h4v5h-4z"/><path fill="#D1D3D4" d="M16 2h4v4h-4z"/><path fill="#A7A9AC" d="M18 2h2v4h-2z"/><path fill="#66757F" d="M18 19H5s1.355 8 4.875 14C13.394 39 18 33 18 33s4.606 6 8.125 0C29.645 27 31 19 31 19H18z"/><path fill="#99AAB5" d="M18 19H5s1.355 8 4.875 14C13.394 39 18 33 18 33V19z"/><path fill="#55ACEE" d="M0 30h36v6H0z"/><path fill="#E6E7E8" d="M30 9h-2.45l-.242-4H8.692l-.241 4H6v6h2.088l-.242 4h20.308l-.242-4H30z"/><path fill="#D1D3D4" d="M10 15h16v4H10z"/><path fill="#6D6E71" d="M8 11h20v2H8z"/><path fill="#BCBEC0" d="M10 7h16v2H10z"/><path fill="#BE1931" d="M5.913 23h24.174c.201-.747.368-1.427.5-2H5.413c.132.573.299 1.253.5 2z"/><path fill="#A0041E" d="M18 23h12.087c.201-.747.368-1.427.5-2H18v2z"/><path fill="#BCBEC0" d="M12 17h12v2H12z"/><path fill="#58595B" d="M16 0h2v2h-2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6a4.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a4.svg new file mode 100644 index 0000000000000000000000000000000000000000..7dfe5a6b81b24e4aa2bf98f7d650444340ebaf37 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6a4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M33 27h-2l1-8h2z"/><path fill="#DD2E44" d="M1 14c9.055.053 11 1 17 2 2.959.493 7 1 11 1 2 0 4 1 4 4 0 2 .534 3.187-5.433 3.815C23.59 25.233 13 23 9 21c-6-3-9-7.005-8-7z"/><path fill="#55ACEE" d="M0 24h36v12H0z"/><path fill="#FFCC4D" d="M5 13c4 0 11 0 18 1s10 1 10 3v3c0 1.414-6.869.447-10 0-7-1-14-3-18-4-4.047-1.011-7-3 0-3z"/><path fill="#A0041E" d="M30.592 24.322c2.122-.539 2.403-1.307 2.418-2.361-1.263.619-3.699.32-5.886.047-7.96-.995-16.481-2.935-24.722-5.608 1.043 1.04 2.584 2.29 4.568 3.483 6.706 1.901 13.484 3.307 19.905 4.109 1.259.157 2.53.312 3.717.33z"/><path fill="#55ACEE" d="M12 24c3-2 7-5 6-3s-1.001 3 1 2c2-1 5-2 4 0s2 1 3 0 4 0 3 1-9 2-12 2-5-2-5-2z"/><path fill="#5C913B" d="M34 16h-1c-1.104 0-2 .896-2 2h1c.553 0 1 .447 1 1v1h1c1.104 0 2 .104 2-1s-.896-3-2-3z"/><path fill="#C1694F" d="M30 16c.97.243 0 2-1 3s-10-1-10-1l2-3s5 0 9 1z"/><path fill="#A0041E" d="M29 19c.328-.328.645-.737.899-1.147-1.475-.764-3.63-1.385-6.079-1.664-1.249-.142-2.441-.178-3.527-.128L19 18s9 2 10 1z"/><path fill="#55ACEE" d="M21 15v-1l-4 1-2 2 4 1z"/><path fill="#292F33" d="M23 14c-.553 0-1 1.343-1 3 0 .612.062 1.181.167 1.656.502.127 1.035.221 1.592.278.148-.524.241-1.193.241-1.934 0-1.656-.447-3-1-3z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..6d9bb3d2eaf154fc30ed1f4a67b2f6dc47686550 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M8.514 19.828L19.122 9.223l2.121 2.121L10.635 21.95z"/><path fill="#55ACEE" d="M8.515 29.728c-.781.781-2.047.781-2.828 0l-4.95-4.949c-.781-.781-.781-2.048 0-2.828L5.687 17c.781-.781 2.047-.781 2.828 0l4.95 4.95c.781.78.781 2.047 0 2.828l-4.95 4.95zm16.262-16.263c-.78.781-2.047.781-2.827 0L17 8.515c-.781-.781-.781-2.047 0-2.828l4.951-4.95c.781-.781 2.047-.781 2.828 0l4.949 4.95c.781.781.781 2.047.001 2.828l-4.952 4.95z"/><path fill="#99AAB5" d="M12.404 10.283L10.99 6.04c-.448-1.342-1.415-1.415-2.122-.708L6.04 8.161c-.708.707-.635 1.674.707 2.122l4.243 1.414 1.414-1.414z"/><path fill="#CCD6DD" d="M17.708 21.949c-.782.781-2.048.781-2.829.001l-7.071-7.071c-.781-.781-.781-2.048 0-2.829l4.242-4.242c.781-.781 2.048-.781 2.829 0l7.071 7.071c.78.781.78 2.047-.001 2.829l-4.241 4.241z"/><path fill="#CCD6DD" d="M21.016 21.055c-1.952 1.953-4.802 2.269-6.364.708-1.562-1.562.876-2.29 2.829-4.243 1.953-1.953 2.681-4.39 4.243-2.829 1.561 1.562 1.245 4.411-.708 6.364z"/><path fill="#99AAB5" d="M27.96 20.182c-2.12-2.122-5.118-1.951-7.071 0-1.952 1.954-2.121 4.95 0 7.071l7.071-7.071zm-2.828 2.829l2.121 3.535-3.535-2.121z"/><path fill="#99AAB5" d="M27.813 27.106c-.391.391-1.023.391-1.414 0s-.391-1.023 0-1.414 1.023-.391 1.414 0 .391 1.024 0 1.414z"/><path fill="#88C9F9" d="M4.27 18.416L5.686 17l7.779 7.777-1.414 1.415zM17 5.686l1.414-1.414 7.778 7.778-1.414 1.414zM.735 21.952l1.414-1.415 7.78 7.776-1.414 1.414zm19.798-19.8L21.946.737l7.781 7.775-1.413 1.414z"/><path fill="#99AAB5" d="M8.307 7.601c-.39.39-1.023.39-1.414 0-.391-.391-.39-1.024 0-1.415.391-.39 1.023-.39 1.414 0 .391.391.391 1.024 0 1.415z"/><path fill="#FFAC33" d="M23.682 30.431l.002-.051c.027-.552.497-.977 1.049-.949.016.001 2.156.063 3.8-1.58 1.637-1.638 1.578-3.772 1.58-3.801-.033-.55.397-1.021.948-1.049.552-.027 1.022.397 1.049.949.012.122.123 3.028-2.163 5.314-2.288 2.287-5.191 2.17-5.314 2.164-.535-.027-.951-.468-.951-.997z"/><path fill="#FFAC33" d="M24.238 33.989c0-.109.018-.221.057-.33.182-.521.752-.796 1.273-.613.107.034 2.877.893 5.964-2.195 3.127-3.126 2.414-6.126 2.382-6.252-.137-.529.184-1.077.716-1.216.53-.14 1.073.172 1.217.701.046.17 1.077 4.205-2.9 8.181-4.014 4.016-7.876 2.726-8.038 2.668-.413-.144-.671-.531-.671-.944z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f4.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f4.svg new file mode 100644 index 0000000000000000000000000000000000000000..e217dc436402c97400ff804d32d4c2eeef4729ad --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#292F33" cx="4.5" cy="31.5" r="4.5"/><circle fill="#DD2E44" cx="4.5" cy="31.5" r="3"/><circle fill="#292F33" cx="31.5" cy="31.5" r="4.5"/><circle fill="#DD2E44" cx="31.5" cy="31.5" r="3"/><path fill="#55ACEE" d="M31.5 33h-20c-.825 0-1.5-.675-1.5-1.5s.675-1.5 1.5-1.5h20c.825 0 1.5.675 1.5 1.5s-.675 1.5-1.5 1.5z"/><path fill="#55ACEE" d="M26.012 31.746c-.003-.082-.012-.163-.012-.246 0-3.038 2.462-5.5 5.5-5.5 1.21 0 2.326.396 3.234 1.058l.89-1.205c-1.158-.847-2.58-1.353-4.125-1.353-3.866 0-7 3.134-7 7 0 .102.011.201.015.302l1.498-.056zM5.629 26.117c2.495.52 4.369 2.73 4.371 5.378l3.5.003c-.001-4.34-3.074-7.962-7.163-8.81-.232 1.13-.476 2.31-.708 3.429z"/><path fill="#99AAB5" d="M4.395 31.998c-.269-.057-.442-.324-.385-.593l6.002-28.238c.057-.269.324-.442.593-.385.269.057.442.324.385.593L4.988 31.613c-.057.269-.324.442-.593.385z"/><path fill="#55ACEE" d="M6.123 26.261l-.978-.208c-.538-.114-.885-.648-.77-1.186l1.247-5.869c.114-.538.648-.885 1.186-.77l.978.208c.538.114.885.648.77 1.186L7.31 25.49c-.115.538-.649.885-1.187.771z"/><path fill="#DD2E44" d="M9.3 4.324l-1.957-.416c-.807-.172-1.327-.972-1.155-1.779.171-.807.972-1.327 1.779-1.156l1.956.416c.807.172 1.327.972 1.155 1.779-.171.807-.972 1.327-1.778 1.156z"/><path fill="#55ACEE" d="M10.84 1.675c-.807-.172-1.608.348-1.779 1.155L7.71 9.188c-.114.538.232 1.072.77 1.186l.978.208c.538.114 1.072-.232 1.186-.77l1.351-6.358c.172-.807-.348-1.607-1.155-1.779z"/><path fill="#DD2E44" d="M14.105 5.345l-2.934-.624c-.807-.172-1.327-.972-1.155-1.779.172-.807.972-1.327 1.779-1.155l2.934.624c.807.172 1.327.972 1.155 1.779-.171.807-.972 1.327-1.779 1.155z"/><path fill="#EA596E" d="M15.903 4.194c-.172.81-.969 1.328-1.779 1.155-.81-.172-1.328-.969-1.155-1.779.172-.81.969-1.328 1.779-1.155s1.328.968 1.155 1.779z"/><circle fill="#55ACEE" cx="35.19" cy="26.46" r=".74"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..a1e0f4b99e20be2902a6533e2fded04509f55e1f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M32 24h-1c-.55 0-1-.45-1-1s.45-1 1-1h1c.55 0 1 .45 1 1s-.45 1-1 1"/><path fill="#292F33" d="M10 31.5c0 2.485-2.015 4.5-4.5 4.5S1 33.985 1 31.5 3.015 27 5.5 27s4.5 2.015 4.5 4.5m24 0c0 2.485-2.015 4.5-4.5 4.5S25 33.985 25 31.5s2.015-4.5 4.5-4.5 4.5 2.015 4.5 4.5"/><path fill="#99AAB5" d="M8 31.5C8 32.881 6.881 34 5.5 34S3 32.881 3 31.5 4.119 29 5.5 29 8 30.119 8 31.5m24 0c0 1.381-1.119 2.5-2.5 2.5S27 32.881 27 31.5s1.119-2.5 2.5-2.5 2.5 1.119 2.5 2.5"/><path fill="#DD2E44" d="M5.854 24.082l2.615-6.989L8 16s-.916.008-1-1c-.083-1.007 2.408-3.079 3-3 .593.08 0 2 0 2s2.32.557 2 2c-.319 1.444-2.375 8.688-2.375 8.688S11.375 25.563 12 27c.449 1.032 1.681 1.018 3 1 1.319-.016 4.393-.007 5-2 .606-1.991 1-3 1-3l-1-1 10-2s-.891 1.982 1 3c2.168 1.169 2.86 2.669 4 5 .749 1.534.448 1.897-1 2-1.941.14-4.44.386-5.79.535-1.197.134-2.284 1.65-4.164 1.65s-10.052.049-12.046-.186c-3.496-.409-4.758-3-10-3-2.072 0-1.06-1.563.028-2.665 1.209-1.226 3.801-2.4 3.826-2.252"/><path fill="#BE1931" d="M22 33h-3c-1.1 0-2-.9-2-2s.9-2 2-2h3c1.1 0 2 .9 2 2s-.9 2-2 2"/><path fill="#BE1931" d="M19 33h-5c-.55 0-1-.45-1-1s.45-1 1-1h5c.55 0 1 .45 1 1s-.45 1-1 1"/><path fill="#292F33" d="M22 22c-1.618 0-2.431.306-3-1s-.02-2 1-2 5.728-.181 8-1c2.272-.819 3.053-.831 3 0s-1 2-1 2-1.254 2-8 2m-8-6h-3.251c-.55 0-1-.45-1-1s.45-1 1-1H14c.55 0 1 .45 1 1s-.45 1-1 1"/><path fill="#F4900C" d="M7.5 16c-.275 0-.5-.225-.5-.5v-1c0-.275.225-.5.5-.5s.5.225.5.5v1c0 .275-.225.5-.5.5"/><path fill="#292F33" d="M13.062 13h-.125c-.516 0-.937-.422-.937-.937V9.937c0-.515.421-.937.938-.937h.125c.516 0 .937.422.937.937v2.126c0 .515-.421.937-.938.937"/><path fill="#292F33" d="M9.982 15.066l-.022-.022c-.188-.188-.188-.497 0-.685l2.85-2.851c.189-.188.497-.188.685 0l.023.022c.188.189.188.497 0 .685l-2.851 2.851c-.188.188-.497.188-.685 0"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f6.svg new file mode 100644 index 0000000000000000000000000000000000000000..b6a2165254a33999293e31fc81d576d07cccec0c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M33.793 17S32.476 20 18 20C3.523 20 1.973 17 1.973 17S-1 22.117 4.802 25c4.238 2.105 10.916-.131 12.723-.814 1.991.683 9.274 2.824 13.557.814 5.862-2.751 2.711-8 2.711-8z"/><path fill="#55ACEE" d="M0 24h36v12H0z"/><path fill="#FFAC33" d="M27.005 25.389c.206 0 .412-.079.569-.236.315-.315.315-.824 0-1.139l-8.861-8.86c-.315-.315-.824-.315-1.139 0-.315.315-.315.824 0 1.139l8.861 8.86c.158.157.364.236.57.236z"/><path fill="#FFCC4D" d="M29.316 28.505c.412 0 .825-.157 1.139-.472.629-.629.629-1.649 0-2.278l-2.416-2.416c-.629-.629-1.65-.629-2.278 0-.629.629-.629 1.649 0 2.278l2.416 2.416c.314.315.727.472 1.139.472z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f8.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f8.svg new file mode 100644 index 0000000000000000000000000000000000000000..5f015fe792bb0de2e806a94f4418de9bca19345a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f8.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFD983" d="M32.831 20.425c-.689 3.241-9.21 6.221-17.314 4.499S.841 17.013 1.53 13.772s8.587-3.287 16.69-1.564 15.3 4.976 14.611 8.217z"/><path fill="#FFD983" d="M27 36l-2-14-17-5-8 19z"/><ellipse transform="rotate(-78 17.482 15.686)" fill="#67757F" cx="17.481" cy="15.685" rx="7.556" ry="17"/><path fill="#67757F" d="M.414 10.977l.414 2.315 32.866 6.986 1.412-2.126z"/><ellipse transform="rotate(-78 18.013 13.186)" fill="#9AAAB4" cx="18.012" cy="13.186" rx="8" ry="18"/><ellipse transform="rotate(-78 18.43 11.23)" fill="#CCD6DD" cx="18.428" cy="11.229" rx="6" ry="15"/><ellipse transform="rotate(-78 18.845 9.274)" fill="#E1E8ED" cx="18.844" cy="9.273" rx="3" ry="9"/><path fill="#5DADEC" d="M10.041 7.402c.344-1.621 2.996-4.475 9.843-3.02s8.108 5.141 7.764 6.762c-.344 1.621-4.565 2.097-9.427 1.063s-8.525-3.184-8.18-4.805z"/><circle fill="#8CCAF7" cx="16.765" cy="19.055" r="1"/><circle fill="#8CCAF7" cx="24.798" cy="19.74" r="1"/><circle fill="#8CCAF7" cx="32.269" cy="18.261" r="1"/><ellipse transform="rotate(-50.811 34.182 14.066)" fill="#8CCAF7" cx="34.183" cy="14.067" rx=".5" ry="1"/><ellipse transform="rotate(-15.188 2.802 7.396)" fill="#8CCAF7" cx="2.802" cy="7.397" rx="1" ry=".5"/><circle fill="#8CCAF7" cx="2.924" cy="12.023" r="1"/><circle fill="#8CCAF7" cx="9.148" cy="16.413" r="1"/><ellipse transform="rotate(-78 19.573 5.85)" fill="#8CCAF7" cx="19.572" cy="5.85" rx="1.5" ry="5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6f9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..1ee4bfec4ac72f00685987418803bb10b0062862 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A0041E" d="M32.436 2.821c1.801 1.799 3.779 2.737 0 6.517L12.884 28.889c-4.594 4.595-5.463 7.571-11.405 1.63-3.258-3.258.284-3.543 4.888-8.148l19.552-19.55c1.8-1.8 4.718-1.8 6.517 0z"/><path fill="#DD2E44" d="M33.936 4.321c1.801 1.799 1.801 4.717 0 6.517L14.385 30.389c-4.073 4.073-8.342 4.693-11.405 1.63-3.258-3.258.284-3.543 4.888-8.148L27.42 4.321c1.799-1.8 4.717-1.8 6.516 0z"/><path fill="#3B88C3" d="M15.301 33.18c.927.929 2.687.673 3.932-.572 1.244-1.244 1.501-3.004.572-3.932-.927-.928-2.688-.672-3.932.572-1.245 1.245-1.501 3.005-.572 3.932z"/><path fill="#3B88C3" d="M19.068 27.937l-4.506 4.506.739.737 4.504-4.504z"/><path fill="#88C9F9" d="M14.613 32.493c.928.928 2.688.672 3.932-.573 1.245-1.244 1.501-3.004.573-3.932-.928-.928-2.688-.672-3.932.572-1.245 1.246-1.501 3.005-.573 3.933z"/><path fill="#808285" d="M17.651 29.396c.302.367.243.973-.207 1.423-.45.45-1.032.477-1.422.207-3.468-2.396-3.067-3.798-2.617-4.248.449-.45 1.148-1.148 4.246 2.618z"/><path fill="#A7A9AC" d="M16.243 29.83c-1.103 1.237-2.763.609-3.935-.562-1.172-1.171-1.302-2.466-.13-3.638 1.171-1.172 2.36-.703 3.531.469 1.172 1.171 1.756 2.359.534 3.731z"/><path fill="#3B88C3" d="M9.139 27.4c1.006 1.008 2.916.729 4.265-.621 1.351-1.35 1.628-3.259.622-4.266-1.006-1.007-2.916-.729-4.266.621-1.351 1.351-1.629 3.261-.621 4.266z"/><path fill="#3B88C3" d="M13.226 21.712l-4.888 4.89.801.798 4.886-4.886z"/><path fill="#88C9F9" d="M8.393 26.655c1.007 1.007 2.917.729 4.266-.622 1.351-1.35 1.628-3.259.622-4.266-1.006-1.007-2.916-.728-4.266.621-1.351 1.351-1.629 3.26-.622 4.267z"/><path fill="#3B88C3" d="M11.651 23.396c.336.335.243.973-.207 1.423-.45.45-1.086.542-1.422.207-.335-.336-.243-.973.208-1.423.449-.45 1.085-.541 1.421-.207zm17.651-4.216c.927.929 2.687.673 3.931-.572 1.244-1.244 1.5-3.004.572-3.932-.928-.928-2.687-.672-3.931.572-1.245 1.246-1.502 3.005-.572 3.932z"/><path fill="#3B88C3" d="M33.068 13.937l-4.505 4.507.739.736 4.503-4.504z"/><path fill="#88C9F9" d="M28.614 18.494c.928.927 2.687.671 3.931-.573 1.244-1.244 1.5-3.004.572-3.932-.928-.928-2.686-.672-3.931.572-1.244 1.245-1.501 3.005-.572 3.933z"/><path fill="#808285" d="M31.65 15.397c.303.367.244.973-.207 1.423-.449.45-1.03.477-1.421.207-3.469-2.396-3.068-3.798-2.617-4.248.449-.45 1.149-1.149 4.245 2.618z"/><path fill="#A7A9AC" d="M30.243 15.831c-1.103 1.237-2.764.609-3.935-.562-1.172-1.171-1.302-2.466-.13-3.638 1.172-1.172 2.359-.703 3.531.469 1.173 1.17 1.756 2.358.534 3.731z"/><path fill="#3B88C3" d="M23.14 13.401c1.006 1.008 2.915.729 4.265-.621 1.351-1.35 1.628-3.259.622-4.266-1.007-1.007-2.916-.729-4.266.621-1.352 1.351-1.629 3.26-.621 4.266z"/><path fill="#3B88C3" d="M22.341 12.601l4.887-4.889.8.8-4.886 4.89z"/><path fill="#88C9F9" d="M22.394 12.656c1.006 1.007 2.916.729 4.266-.622 1.35-1.35 1.628-3.259.621-4.266-1.006-1.007-2.916-.729-4.266.621-1.351 1.351-1.629 3.26-.621 4.267z"/><path fill="#3B88C3" d="M25.651 9.397c.336.335.243.973-.207 1.423-.45.45-1.086.542-1.422.207-.336-.336-.243-.973.207-1.423.451-.45 1.086-.542 1.422-.207z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6fa.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6fa.svg new file mode 100644 index 0000000000000000000000000000000000000000..aae4e94ac5a0f49fce6e8ceba2022f2ef8a57819 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6fa.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M19 9h2v11h-2z"/><path fill="#55ACEE" d="M10 9c-2 2-4 5-4 7 0 4 5 1 5 1V9h-1z"/><circle fill="#292F33" cx="5" cy="32" r="4"/><circle fill="#99AAB5" cx="5" cy="32" r="2"/><path fill="#1E5200" d="M29 23h-2c-1.105 0-2 .895-2 2v5c0 1.105.895 2 2 2h2c1.105 0 2-.895 2-2v-5c0-1.105-.895-2-2-2zm-10 0h-2c-1.105 0-2 .895-2 2v5c0 1.105.895 2 2 2h2c1.105 0 2-.895 2-2v-5c0-1.105-.895-2-2-2z"/><path fill="#5C913B" d="M2 28.377c-1.387.225-2.581-1.152-1-2.435 2-1.623 7-2.435 9-1.623S12 33 11 33s-4-5.435-9-4.623z"/><path fill="#3E721D" d="M11 33h13c1 0 2 0 2-2 0-1 1-4 3-4s5 3 5 4 0 2 1 2 1-1 1-2V19h-8c0 3-1 8-1 8s-1-1-1 1c0 .606-1 2-2 2h-1c-1 0-2-.666-2-1.672V19c0-1-2-1-2 0v9.328C19 29.334 18.262 30 17.341 30h-3.33C13 30 12 29 12 28v-9H5c0 6 5 14 6 14z"/><path fill="#5C913B" d="M34 32c0 1 1 0 1-2 0-3-.833-5-5-5s-5 3-5 5c0 1 1 3 1 2s.667-2 4-2 4 1 4 2z"/><path fill="#FFAC33" d="M12 19H5c0-1 1-3 1-3h4c.552 0 1-.448 1-1v-4s-2 0-2-2c0-.326.106-.652.25-.944C9.573 7.4 10.258 7 10.99 7H33c2 0 3 5 3 12h-8s0-8-3-8H12v8z"/><circle fill="#292F33" cx="30" cy="32" r="4"/><circle fill="#99AAB5" cx="30" cy="32" r="2"/><path fill="#F4900C" d="M9 18.5v-1c0-.276-.224-.5-.5-.5H5.552C5.286 17.648 5 18.464 5 19h3.5c.276 0 .5-.224.5-.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f6fc.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f6fc.svg new file mode 100644 index 0000000000000000000000000000000000000000..091d51ef63eb87af07d6b7ce2cac60cdf21b211f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f6fc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M10 27.5c0 1.381-2.567 3.5-4.5 3.5S1 28.881 1 27.5 3.567 26 5.5 26s4.5.119 4.5 1.5zm19 0c0 1.381-2.567 3.5-4.5 3.5S20 28.881 20 27.5s2.567-1.5 4.5-1.5 4.5.119 4.5 1.5zm0-.5c0 1 0 2 2 3s2-3 2-3h-4z"/><path fill="#F4900C" d="M34.787 28.795c1.332 1.332.729 1.683-.603 3.016-1.332 1.332-1.683 1.935-3.016.603-1.332-1.332-1.935-2.889-.603-4.222 1.332-1.333 2.889-.73 4.222.603z"/><path fill="#662113" d="M33.299 24.074s.595-.073.595.929c0 1.004-.462.996-1.466.996H19.146c-4.037 0-8.513-2.889-10.439-2.889L8.137 26h-6.17c0-1.368-.843-3.084-.848-3.993-.011-2.007.647-4.231.647-4.231l15.607 5.335 15.926.963z"/><path fill="#88C9F9" d="M26.472 16.478c-2.218-1.018-6.023-4.326-6.21-4.536C15.591 3.987 18.336.964 18.336.964S17.043.019 16.41.048l-.963.916-.963-.788C11.226.454 2.93 4.816 2.93 4.816s.963 2.889.963 4.814-.696 4.238-.696 4.238-1.383 2.338-1.631 3.426c-.276 1.213.212 2.035 1.044 2.236 2.923.704 5.578.623 11.525 3.254 2.307 1.02 3.852 1.29 6.127 1.29h13.037s1.214-1.518.173-4.26c-.37-.975-4.725-2.292-7-3.336z"/><path fill="#EA596E" d="M26.258 16.371c-2.24-1.119-5.815-4.225-5.995-4.429C15.592 3.987 18.337.964 18.337.964S17.044.019 16.411.048l-.963.916-.963-.788c-.022.002-.051.008-.073.011-.057.5-.145 1.318-.28 2.633-.52 5.078 2.136 8.698 4.792 11.558 2.656 2.86 5.39 3.491 6.698 3.794s2.974-.768 2.974-.768l-2.338-1.033z"/><path fill="#99AAB5" d="M34 28H2c-.55 0-1-.45-1-1s.45-1 1-1h32c.55 0 1 .45 1 1s-.45 1-1 1z"/><circle fill="#F4900C" cx="5.5" cy="31.5" r="4.5"/><circle fill="#662113" cx="5.5" cy="31.5" r="2.25"/><circle fill="#F4900C" cx="24.5" cy="31.5" r="4.5"/><circle fill="#662113" cx="24.5" cy="31.5" r="2.25"/><path fill="#269" d="M15.448.965c-1.891 1.9-1.107 8.629 1.825 11.354C11.41 7.24 14.485.177 14.485.177l.963.788z"/><path fill="#BE1931" d="M15.775 13.513c-.299-.462-.166-1.084.296-1.383l2.772-1.817c.462-.299 1.084-.166 1.383.296.299.462.166 1.084-.296 1.383l-2.772 1.817c-.462.299-1.084.166-1.383-.296zm4.616 3.755c-.444-.325-.541-.954-.215-1.398l1.595-2.176c.325-.444.954-.541 1.398-.215.444.325.541.954.215 1.398l-1.595 2.176c-.325.443-.954.54-1.398.215zm4.777 1.903c-.519-.183-.794-.757-.611-1.276l.613-1.739c.183-.519.757-.794 1.276-.611.519.183.794.757.611 1.276l-.613 1.739c-.183.519-.757.794-1.276.611zM12.487 2.449c.047-.548.534-.958 1.082-.91l3.985.345c.548.047.958.534.91 1.082-.047.548-.534.958-1.082.91l-3.985-.345c-.548-.047-.957-.534-.91-1.082zm.584 5.538c-.104-.54.253-1.067.793-1.171l3.723-.687c.54-.104 1.067.253 1.171.793.104.54-.253 1.067-.793 1.171l-3.723.687c-.54.104-1.067-.253-1.171-.793z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f916.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f916.svg new file mode 100644 index 0000000000000000000000000000000000000000..1dbe6d68de79c6714e4e64056235c7e9b51820c0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f916.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#F4900C" cx="33.5" cy="14.5" rx="2.5" ry="3.5"/><ellipse fill="#F4900C" cx="2.5" cy="14.5" rx="2.5" ry="3.5"/><path fill="#FFAC33" d="M34 19c0 .553-.447 1-1 1h-3c-.553 0-1-.447-1-1v-9c0-.552.447-1 1-1h3c.553 0 1 .448 1 1v9zM7 19c0 .553-.448 1-1 1H3c-.552 0-1-.447-1-1v-9c0-.552.448-1 1-1h3c.552 0 1 .448 1 1v9z"/><path fill="#FFCC4D" d="M28 5c0 2.761-4.478 4-10 4C12.477 9 8 7.761 8 5s4.477-5 10-5c5.522 0 10 2.239 10 5z"/><path fill="#F4900C" d="M25 4.083C25 5.694 21.865 7 18 7c-3.866 0-7-1.306-7-2.917 0-1.611 3.134-2.917 7-2.917 3.865 0 7 1.306 7 2.917z"/><path fill="#269" d="M30 5.5C30 6.881 28.881 7 27.5 7h-19C7.119 7 6 6.881 6 5.5S7.119 3 8.5 3h19C28.881 3 30 4.119 30 5.5z"/><path fill="#55ACEE" d="M30 6H6c-1.104 0-2 .896-2 2v26h28V8c0-1.104-.896-2-2-2z"/><path fill="#3B88C3" d="M35 33v-1c0-1.104-.896-2-2-2H22.071l-3.364 3.364c-.391.391-1.023.391-1.414 0L13.929 30H3c-1.104 0-2 .896-2 2v1c0 1.104-.104 2 1 2h32c1.104 0 1-.896 1-2z"/><circle fill="#FFF" cx="24.5" cy="14.5" r="4.5"/><circle fill="#DD2E44" cx="24.5" cy="14.5" r="2.721"/><circle fill="#FFF" cx="11.5" cy="14.5" r="4.5"/><path fill="#F5F8FA" d="M29 25.5c0 1.381-1.119 2.5-2.5 2.5h-17C8.119 28 7 26.881 7 25.5S8.119 23 9.5 23h17c1.381 0 2.5 1.119 2.5 2.5z"/><path fill="#CCD6DD" d="M17 23h2v5h-2zm-5 0h2v5h-2zm10 0h2v5h-2zM7 25.5c0 1.21.859 2.218 2 2.45v-4.9c-1.141.232-2 1.24-2 2.45zm20-2.45v4.899c1.141-.232 2-1.24 2-2.45s-.859-2.217-2-2.449z"/><circle fill="#DD2E44" cx="11.5" cy="14.5" r="2.721"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f93f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f93f.svg new file mode 100644 index 0000000000000000000000000000000000000000..01239db8784638856158b1120994ab01157a87f1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f93f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M21 25c-2.556 0-4.062-3.128-5.161-4.676-.412-.58-1.266-.58-1.677 0C13.062 21.872 11.557 25 9 25c-4.551 0-7.923-3.033-8.784-7.619C-.804 11.955 3.589 7 9.11 7h11.78c5.521 0 9.914 4.955 8.894 10.381C28.923 21.967 25.551 25 21 25z"/><path fill="#292F33" d="M18 22l-3-3-3 3-2 2c2 0 3 3 5 3s3-3 5-3l-2-2z"/><path fill="#4E9322" d="M21 25c-2.556 0-4.062-3.128-5.161-4.676-.412-.58-1.266-.58-1.677 0C13.062 21.872 11.557 25 9 25c-4.551 0-7.923-3.033-8.784-7.619C-.804 11.955 3.589 7 9.11 7h11.78c5.521 0 9.914 4.955 8.894 10.381C28.923 21.967 25.551 25 21 25z"/><path fill="#88C9F9" d="M21 23c-1.041 0-2.113-1.664-2.896-2.88-.226-.35-.437-.676-.635-.954-.568-.8-1.491-1.277-2.469-1.277-.979 0-1.901.477-2.469 1.275-.199.281-.41.606-.635.957C11.113 21.336 10.042 23 9 23c-3.512 0-6.125-2.295-6.819-5.988-.365-1.941.147-3.87 1.442-5.431C4.984 9.941 6.984 9 9.11 9h11.78c2.126 0 4.126.941 5.486 2.581 1.295 1.561 1.808 3.49 1.442 5.431C27.125 20.706 24.512 23 21 23z"/><path fill="#292F33" d="M26.761 11.262C25.305 9.507 23.165 8.5 20.89 8.5H9.11c-2.275 0-4.415 1.007-5.871 2.762-1.392 1.678-1.942 3.752-1.549 5.842C2.431 21.049 5.232 23.5 9 23.5c1.314 0 2.424-1.723 3.316-3.108.221-.344.428-.663.622-.938.475-.667 1.245-1.065 2.062-1.065s1.587.398 2.062 1.067c.194.272.401.593.622.935.892 1.385 2.002 3.109 3.316 3.109 3.769 0 6.569-2.45 7.31-6.396.393-2.089-.158-4.164-1.549-5.842zm.566 5.658c-.646 3.442-3.07 5.58-6.327 5.58-.769 0-1.837-1.659-2.476-2.651-.23-.356-.445-.688-.647-.972-.662-.931-1.737-1.487-2.877-1.487-1.14 0-2.215.555-2.877 1.486-.203.287-.417.618-.648.976-.639.99-1.706 2.648-2.475 2.648-3.256 0-5.681-2.139-6.328-5.581-.336-1.792.138-3.574 1.336-5.019 1.266-1.525 3.125-2.4 5.102-2.4h11.78c1.977 0 3.836.875 5.102 2.4 1.197 1.445 1.672 3.228 1.335 5.02z"/><path fill="#BBDDF5" d="M12.495 9.505l-8.977 8.977c.436 1.29 1.091 2.313 1.996 3.004L17.495 9.505h-5z"/><path fill="#3C96CE" d="M15 15c-1.837 0-3.674 4.215-5.511 7.227.827-.557 1.732-1.831 2.286-2.692.209-.325.405-.627.589-.888.527-.741 1.515-1.277 2.635-1.277 1.315 0 2.352.719 2.879 1.461.184.258.38.561.589.885.561.871 1.127 2.044 2.058 2.537C18.685 19.24 16.842 15 15 15z"/><path fill="#F4900C" d="M26 36c-3.557 0-6.874-1.914-8.659-4.995-.553-.956-.227-2.179.729-2.732.958-.554 2.18-.228 2.733.729C21.874 30.851 23.865 32 26 32c3.309 0 6-2.691 6-6V2c0-1.104.896-2 2-2s2 .896 2 2v24c0 5.514-4.486 10-10 10z"/><path fill="#292F33" d="M21.586 30.146l-3.732 1.44c-1.026.396-2.19-.12-2.586-1.146-.396-1.026.12-2.19 1.146-2.586l3.732-1.44c1.026-.396 2.19.12 2.586 1.146.396 1.027-.12 2.19-1.146 2.586z"/><path fill="#FFCC4D" d="M32 5h4v4h-4zm0 7h4v4h-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f941.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f941.svg new file mode 100644 index 0000000000000000000000000000000000000000..e197d16c3e09207185734dc27005d023edc589a0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f941.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F18F26" d="M0 18h36v9H0z"/><ellipse fill="#F18F26" cx="18" cy="26" rx="18" ry="9"/><ellipse fill="#F18F26" cx="18" cy="27" rx="18" ry="9"/><path fill="#9D0522" d="M0 10v16h.117c.996 4.499 8.619 8 17.883 8s16.887-3.501 17.883-8H36V10H0z"/><ellipse fill="#F18F26" cx="18" cy="11" rx="18" ry="9"/><ellipse fill="#F18F26" cx="18" cy="12" rx="18" ry="9"/><path fill="#F18F26" d="M0 10h1v2H0zm35 0h1v2h-1z"/><ellipse fill="#FCAB40" cx="18" cy="10" rx="18" ry="9"/><ellipse fill="#F5F8FA" cx="18" cy="10" rx="17" ry="8"/><path fill="#FDD888" d="M18 3c9.03 0 16.395 3.316 16.946 7.5.022-.166.054-.331.054-.5 0-4.418-7.611-8-17-8S1 5.582 1 10c0 .169.032.334.054.5C1.605 6.316 8.97 3 18 3z"/><path d="M28.601 2.599c.44-.33.53-.96.2-1.4l-.6-.8c-.33-.44-.96-.53-1.4-.2L14.157 10.243c-.774-.167-1.785.083-2.673.749-1.326.994-1.863 2.516-1.2 3.4s2.275.794 3.6-.2c.835-.626 1.355-1.461 1.462-2.215l13.255-9.378zm5.868 2.919l-.509-.861c-.28-.474-.896-.632-1.37-.352l-13.913 8.751c-.719-.141-1.626.023-2.472.524-1.426.843-2.127 2.297-1.565 3.248.562.951 2.174 1.039 3.6.196 1.005-.594 1.638-1.49 1.735-2.301l14.142-7.835c.474-.281.632-.897.352-1.37z" fill="#AA695B"/><path fill="#DA2F47" d="M2 28c-.55 0-1-.45-1-1v-9c0-.55.45-1 1-1s1 .45 1 1v9c0 .55-.45 1-1 1zm9 4c-.55 0-1-.45-1-1v-9c0-.55.45-1 1-1s1 .45 1 1v9c0 .55-.45 1-1 1zm12 0c-.55 0-1-.45-1-1v-9c0-.55.45-1 1-1s1 .45 1 1v9c0 .55-.45 1-1 1zm11-4c-.55 0-1-.45-1-1v-9c0-.55.45-1 1-1s1 .45 1 1v9c0 .55-.45 1-1 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f94c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f94c.svg new file mode 100644 index 0000000000000000000000000000000000000000..9bc8f8a58d42126be83ece2d9bd1c4d3290745ac --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f94c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M28 12H13V8c0-.552.448-1 1-1h11c1.104 0 2-.896 2-2s-.896-2-2-2H14c-2.761 0-5 2.239-5 5v4H8c-1.104 0-2 .896-2 2s.896 2 2 2h20c1.104 0 2-.896 2-2s-.896-2-2-2z"/><path fill="#66757F" d="M36 25c0 3.313-2.687 6-6 6H6c-3.313 0-6-2.687-6-6v-5c0-3.313 2.687-6 6-6h24c3.313 0 6 2.687 6 6v5z"/><path fill="#99AAB5" d="M0 20h36v5H0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f94f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f94f.svg new file mode 100644 index 0000000000000000000000000000000000000000..84fdba474f0ab3b3866ba1ed70fc82499401bcdc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f94f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M35 21.526C35 26.758 27.389 31 18 31S1 26.758 1 21.526 7.625 11 18 11s17 5.294 17 10.526z"/><ellipse fill="#FFAC33" cx="18" cy="19.502" rx="16" ry="8.5"/><path fill="#FFD983" d="M18 11.331c-6.449 0-11.5 2.491-11.5 5.672 0 3.18 5.051 5.671 11.5 5.671 6.448 0 11.5-2.491 11.5-5.671 0-3.181-5.052-5.672-11.5-5.672z"/><ellipse fill="#FFAC33" cx="18" cy="18.002" rx="12" ry="6"/><path fill="#F4900C" d="M29 18.002c-1.81 3.118-7 4-11 4s-9.19-.882-11-4c-.75-1.292-1.5 1.083.5 3.083S14 24.402 18 24.402s8.5-1.317 10.5-3.317 1.25-4.374.5-3.083z"/><path fill="#E1E8ED" d="M35 1S24.497-.538 15.958 3C6.77 6.807 4 13 4 13c1.541-1.541 5.463-3.079 10.383-3.705 1.777-3.182 6.97-7.391 12.271-7.351 0 0-7.222 1.493-9.759 7.121C17.586 9.026 18.286 9 19 9c1.319 0 2.551.118 3.702.303.68-2.914 3.791-6.264 7.226-6.829 0 0-3.562 1.707-4.845 7.338C29.418 10.981 32 13 32 13c-4-8 3-12 3-12z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f950.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f950.svg new file mode 100644 index 0000000000000000000000000000000000000000..eef4358d88ee42923fcb07b58abaa333aeca8c20 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f950.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M11.569 35.41c-2.223-.63-5.362-4.11-6.86-7.331-.183-.391-1.101-.673-1.265-1.084C.953 20.775.637 12.54 6.342 6.834 12.751.425 20.537-.295 26.817 1.757c.45.147.837 1.114 1.286 1.199 5.917 1.115 8.322 7.549 5.759 6.816-1.199-.342-2.657-.557-3.814-.428-.437.049-1.051.892-1.544.962-.767.11-2.64.212-3.564.305-9.159.916-12.395 6.971-12.811 14.256-.046.808-.617.623-.73 1.283-.344 1.992 1.089 4.884 1.772 6.939.594 1.794.619 2.951-1.602 2.321z"/><path fill="#DB7803" d="M4.128 9.652c-1.439 2.333-2.158 4.906-2.333 7.505 2.615-1.499 6.334-2.652 12.393-.18.779-1.397 1.806-2.623 3.124-3.624-.992-.932-1.992-1.645-2.742-1.822-2.481-.588-7.17-2.213-10.442-1.879zm-.251 17.769c.324.215.719.416.832.658.032.069.069.139.103.209 1.92-1.11 4.42-1.707 6.553-1.642.006-.167.005-.339.032-.496.095-.552.506-.52.667-.965-4.887-1.059-6.75.812-8.187 2.236zM28.899 3.157c-.26-.074-.52-.148-.796-.2-.169-.032-.33-.19-.489-.382.918 2.123 1.899 5.032 1.024 7.689.467-.178 1.011-.875 1.409-.919.067-.007.143-.003.211-.008.206-1.704-.284-4.207-1.359-6.18z"/><path fill="#FFAC33" d="M2.038 14.915C1.084 11.663 2.419 2.294 14.659 0c2.133 0 10.133 1.272 6.527 16.257-.559 2.325-1.797 2.739-3.562 1.605-4.126-2.648-11.602-7.099-15.586-2.947z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f951.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f951.svg new file mode 100644 index 0000000000000000000000000000000000000000..ed1d9f9f633cb860772aaafc781599163274b877 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f951.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M35 5.904c2.394 6.042-1.438 20.543-10.5 26.5-9.06 5.957-20.395 3.573-23.097-6.443-1.669-6.186 2.79-10.721 11.851-16.677C22.315 3.327 32.64-.053 35 5.904z"/><path fill="#3E721D" d="M20.605 26.03c-6.523 4.546-15.287 5.15-18.469.582-3.183-4.566.418-12.578 6.943-17.124 6.522-4.545 21.951-9.796 25.134-5.23 3.183 4.57-7.085 17.226-13.608 21.772"/><path fill="#A6D388" d="M19.815 26.578c-5.757 4.013-13.482 3.097-16.29-.934C.718 21.613 4 14.474 9.757 10.463c5.755-4.011 20.258-9.264 23.068-5.234 2.807 4.03-4.825 16.175-13.01 21.349"/><path fill="#C6E5B3" d="M18.169 23.926c-4.506 3.14-9.939 3.127-12.136-.027-2.2-3.154-.33-8.255 4.176-11.395 4.507-3.141 15.835-7.238 18.035-4.084 2.199 3.154-5.567 12.366-10.075 15.506z"/><path fill="#662113" d="M11.162 12.488c3.48-2.332 7.382-1.495 9.798.995 1.433 1.477-.88 5.382-4.359 7.714-3.478 2.33-7.769 1.763-8.239.731-1.44-3.157-.677-7.109 2.8-9.44z"/><path fill="#7C3225" d="M13.071 13.106c1.51-1.013 3.414-.819 4.254.431.837 1.251.294 3.087-1.217 4.1-1.51 1.01-3.414.817-4.253-.433-.839-1.252-.294-3.086 1.216-4.098z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f955.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f955.svg new file mode 100644 index 0000000000000000000000000000000000000000..b949554ff7a1c68c0883be256aa3f2450d6801cf --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f955.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M31.096 8.933c3.535-2.122 4.408-8.32 3.701-7.613.707-.707-5.657 0-7.778 3.536 0-1.414-1.414-7.071-3.535-2.121-2.122 4.95-1.415 5.657-1.415 7.071 0 1.414 2.829 1.414 2.829 1.414s-.125 2.704 1.29 2.704c1.414 0 1.997.583 6.946-1.538 4.95-2.122-.624-3.453-2.038-3.453z"/><path fill="#F4900C" d="M22.422 23.594C14.807 31.209 2.27 36.675.502 34.907c-1.768-1.768 3.699-14.305 11.313-21.92 7.615-7.615 11.53-7.562 14.85-4.243 3.319 3.32 3.372 7.235-4.243 14.85z"/><path d="M21.875 14.56c-.972-.972-2.77-2.785-4.692-6.106-.753.492-1.554 1.091-2.409 1.808 2.803 3.613 8.121 5.317 7.101 4.298zm-7.485 8.072c-1.041-1.041-3.03-3.05-5.105-6.846-.687.832-1.349 1.693-1.98 2.57 2.807 3.597 8.101 5.292 7.085 4.276zm9.301-.351c-3.581-2.008-5.49-3.91-6.502-4.921-1.02-1.022.692 4.315 4.317 7.114.311-.29 1.786-1.767 2.185-2.193zm-12.183 9.324c.895-.492 1.804-1.025 2.715-1.597-3.273-1.905-5.069-3.683-6.034-4.648-.922-.923.386 3.347 3.319 6.245z" fill="#D67503"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f956.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f956.svg new file mode 100644 index 0000000000000000000000000000000000000000..8da10427ff0f0de9d16eab50c8fc4ec67bbaa2b9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f956.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EDB980" d="M12.697 31.165c-3.785 3.785-8.273 3.838-9.841 2.271-1.568-1.568-1.514-6.056 2.271-9.841L24.052 4.67c3.785-3.784 8.271-3.838 9.84-2.271 1.567 1.568 1.515 6.056-2.271 9.841L12.697 31.165z"/><path d="M24.322 7.969c1.568 1.568 2.758 2.917 3.595 2.082.152-.152.241-.349.301-.565-.018-.043-.036-.087-.041-.136-.128-1.148-2.41-3.641-4.08-4.721l-.045.042-1.474 1.474c.438.539 1.064 1.144 1.744 1.824zm-4.543 4.542c1.568 1.568 2.76 2.917 3.597 2.082.152-.152.241-.35.301-.567-.018-.043-.036-.086-.041-.135-.127-1.148-2.411-3.643-4.083-4.722l-1.517 1.517c.437.54 1.063 1.145 1.743 1.825zm-4.54 4.542c1.567 1.568 2.759 2.918 3.595 2.081.152-.152.241-.349.301-.565-.018-.043-.036-.087-.042-.136-.128-1.148-2.412-3.642-4.083-4.721l-1.517 1.517c.439.539 1.065 1.144 1.746 1.824zm-4.542 4.542c1.567 1.567 2.759 2.919 3.596 2.082.152-.152.241-.35.301-.566-.018-.043-.036-.087-.042-.136-.127-1.148-2.411-3.643-4.082-4.722L8.953 19.77c.437.54 1.063 1.145 1.744 1.825zm-4.542 4.541c1.567 1.568 2.759 2.919 3.596 2.082.152-.152.241-.35.301-.566-.018-.043-.036-.086-.042-.135-.128-1.148-2.412-3.643-4.083-4.722l-.801.801c-.246.246-.475.496-.691.747.437.532 1.053 1.126 1.72 1.793z" fill="#E5A157"/><path d="M24.859 3.932c-.126.106-.634.569-.762.696 1.67 1.08 3.952 3.574 4.08 4.721.005.049.023.093.042.136.077.182.252.309.455.309l.057-.003c.274-.031.472-.278.441-.553-.164-1.452-2.382-4-4.313-5.306zm-4.583 4.514l-.724.724c1.671 1.079 3.956 3.574 4.083 4.722.005.049.023.092.041.135.076.183.252.31.455.31l.057-.003c.274-.031.472-.278.441-.552-.162-1.464-2.411-4.04-4.353-5.336zm-4.541 4.541l-.724.724c1.671 1.079 3.955 3.574 4.083 4.721.005.049.023.093.042.136.077.182.252.309.454.309l.057-.003c.274-.031.472-.278.441-.552-.163-1.463-2.412-4.038-4.353-5.335zm-4.542 4.541l-.724.724c1.671 1.079 3.955 3.574 4.082 4.722.005.049.023.093.042.136.077.183.252.309.455.309l.056-.003c.274-.03.472-.277.442-.552-.163-1.463-2.411-4.039-4.353-5.336zm-4.542 4.543l-.724.724c1.671 1.079 3.955 3.574 4.083 4.722.005.049.023.092.042.135.077.182.252.309.455.309.019 0 .037-.001.056-.003.274-.03.472-.278.442-.553-.164-1.462-2.413-4.038-4.354-5.334z" fill="#FFD983"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f95c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f95c.svg new file mode 100644 index 0000000000000000000000000000000000000000..c809689a053651f255bbc530a1b900b337bae3d3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f95c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M17.256 31.519c-4.754 4.754-11.207 5.573-14.683 2.097C-.902 30.141.056 23.55 4.672 18.934c3.355-3.356 6.711-3.356 9.228-5.873 2.517-2.516 1.678-5.033 5.454-8.809C23.968-.361 29.84-1.201 33.616 2.574c3.774 3.776 2.832 9.754-1.678 14.263-3.775 3.775-6.292 2.936-8.809 5.452-2.518 2.518-2.518 5.873-5.873 9.23z"/><path fill="#C1694F" d="M8.211 21.397c-.324 0-.643-.157-.835-.448-.305-.46-.179-1.081.282-1.386.682-.451 1.438-.853 2.245-1.193 3.938-1.516 6.902-4.208 7.765-7.037.161-.529.721-.829 1.248-.665.529.161.826.72.666 1.248-1.039 3.406-4.46 6.589-8.931 8.309-.665.28-1.31.623-1.889 1.006-.17.113-.361.166-.551.166zm-5.044 8.937h-.022c-.552-.012-.99-.47-.979-1.021.047-2.164.385-4.916 2.601-7.002.403-.377 1.036-.358 1.414.043.379.402.359 1.035-.042 1.414-1.666 1.567-1.932 3.704-1.972 5.588-.012.544-.458.978-1 .978zm4.125-.709c-.082 0-.166-.01-.249-.031-.535-.137-.858-.682-.721-1.217.562-2.191 1.782-5.277 5.875-6.774.517-.188 1.093.077 1.282.596.19.519-.077 1.093-.596 1.283-3.171 1.159-4.137 3.49-4.625 5.392-.113.451-.52.751-.966.751zm17.667-11.041c-.412 0-.798-.257-.943-.667-.184-.521.09-1.092.61-1.276 4.279-1.51 6.849-4.449 7.856-8.982.12-.54.657-.874 1.193-.759.539.12.879.654.76 1.193-1.154 5.19-4.23 8.701-9.144 10.435-.109.037-.222.056-.332.056z"/><path fill="#C1694F" d="M24.459 14.875c-.397 0-.774-.24-.93-.632-.203-.514.048-1.095.562-1.298 1.722-.682 3.378-2.263 4.12-3.935.225-.502.813-.732 1.32-.508.505.225.731.815.508 1.32-.956 2.151-3.002 4.107-5.212 4.982-.121.049-.245.071-.368.071zm-8.709 7.209c-.395 0-.768-.234-.926-.622-.209-.512.037-1.095.548-1.304.955-.39 1.979-1.345 2.266-1.832.28-.476.895-.635 1.369-.354.477.28.635.893.354 1.369-.513.873-1.864 2.11-3.233 2.669-.124.051-.252.074-.378.074zm4-12.667c-.108 0-.22-.018-.328-.056-.522-.181-.798-.751-.617-1.272.4-1.152 1.234-2.255 2.124-2.812.469-.293 1.086-.15 1.378.318.293.468.15 1.085-.317 1.378-.421.263-1.017.973-1.295 1.772-.144.413-.531.672-.945.672zM6.457 33.915c-.49 0-.917-.358-.988-.857-.064-.451 0-1.253.098-1.691.12-.539.659-.87 1.193-.759.539.12.879.655.759 1.194-.064.286-.09.824-.069.975.076.546-.305 1.053-.852 1.129-.048.006-.095.009-.141.009z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f95d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f95d.svg new file mode 100644 index 0000000000000000000000000000000000000000..4007a720a28036d05ecb6bebf66b0fbfaf0bebb1 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f95d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M25.94 15.188c2.045 8.239-1.642 16.246-8.235 17.881-6.592 1.636-13.593-3.719-15.638-11.958-2.044-8.24 1.642-16.246 8.236-17.882 6.59-1.636 13.593 3.718 15.637 11.959z"/><path fill="#C1694F" d="M34.146 13.151c2.391 9.635-6.295 17.402-14.948 19.548-8.653 2.146-14.34-3.532-16.385-11.773-2.044-8.24.328-15.92 8.98-18.066 8.652-2.148 19.801.005 22.353 10.291z"/><path fill="#77B255" d="M24.448 15.558c1.789 7.211-1.438 14.215-7.205 15.646-5.768 1.434-11.895-3.253-13.685-10.463-1.788-7.21 1.438-14.215 7.207-15.647 5.766-1.43 11.893 3.254 13.683 10.464z"/><path fill="#A6D388" d="M12.871 5.837c4.713 0 9.174 4.19 10.607 9.962.811 3.267.56 6.581-.707 9.331-1.231 2.674-3.28 4.486-5.768 5.103-.61.152-1.238.228-1.868.228-4.712 0-9.172-4.19-10.605-9.962-1.654-6.662 1.252-13.138 6.476-14.434.609-.151 1.236-.228 1.865-.228m0-1c-.702 0-1.406.084-2.106.257-5.769 1.432-8.995 8.437-7.206 15.647 1.572 6.335 6.492 10.721 11.575 10.721.702 0 1.409-.084 2.109-.258 5.766-1.431 8.994-8.435 7.205-15.646-1.573-6.335-6.494-10.721-11.577-10.721z"/><g fill="#A6D388"><path d="M18.974 18.518l-2.799 1.311 1.656 4.152-2.955-2.326-.697 4.171-1.378-4.098-2.651 1.745 1.006-3.976-3.043-1.701 2.8-1.315-1.657-4.149 2.957 2.115.697-4.172 1.379 4.31 2.645-1.745-1.001 3.973z"/><path d="M14.178 26.826c-.426 0-.81-.271-.947-.682l-.964-2.868-1.567 1.032c-.343.228-.792.221-1.129-.021-.336-.238-.491-.66-.39-1.06l.817-3.232-2.373-1.326c-.328-.184-.525-.534-.512-.908.013-.375.235-.71.574-.87l1.947-.914-1.308-3.274c-.165-.413-.038-.884.312-1.158.35-.273.838-.284 1.199-.026l1.653 1.183.432-2.59c.076-.456.454-.8.914-.833.472-.022.885.253 1.025.693l.977 3.053 1.544-1.019c.344-.227.794-.22 1.129.019.336.239.492.66.391 1.06l-.813 3.231 2.373 1.33c.326.184.523.535.51.909-.014.375-.235.71-.574.869l-1.945.912 1.307 3.276c.168.42.032.9-.33 1.171-.363.271-.862.265-1.217-.015l-1.628-1.282-.419 2.506c-.076.452-.45.796-.907.832l-.081.002zm-1.377-6.098c.11 0 .22.018.326.055.293.102.523.333.622.627l.103.306.038-.225c.058-.349.296-.64.625-.768.329-.126.701-.071.979.146l.027.021-.275-.691c-.196-.491.025-1.051.504-1.275l1.036-.485-1.342-.752c-.394-.221-.591-.679-.481-1.117l.372-1.477-.496.327c-.261.172-.588.213-.883.109-.295-.104-.524-.34-.62-.639l-.12-.375-.016.097c-.057.34-.285.627-.604.759-.318.133-.683.09-.964-.11l-.181-.129.391.979c.196.492-.024 1.051-.503 1.276l-1.038.487 1.343.75c.395.221.593.68.481 1.118l-.374 1.479.5-.329c.166-.109.357-.164.55-.164z"/></g><g fill="#C6E5B3"><path d="M16.788 18.019l-1.709.812 1.076 2.538-1.846-1.288-.378 2.556-.91-2.634-1.606 1.077.566-2.437-1.902-1.034 1.706-.813-1.078-2.539 1.852 1.286.373-2.556.911 2.637 1.61-1.079-.567 2.438z"/><path d="M13.931 23.137c-.211 0-.402-.134-.472-.337l-.698-2.021-1.066.716c-.17.114-.394.114-.563-.004-.169-.116-.25-.324-.203-.524l.48-2.066-1.569-.852c-.165-.09-.266-.265-.261-.453s.115-.357.285-.438l1.274-.607-.891-2.099c-.087-.205-.028-.443.145-.583.173-.141.417-.149.601-.022l1.188.826.256-1.757c.033-.228.218-.404.448-.425.228-.028.444.116.52.334l.7 2.024 1.071-.718c.171-.114.394-.112.562.004.169.117.25.325.203.525l-.48 2.067 1.568.854c.165.09.266.265.261.453-.005.188-.116.357-.285.438l-1.277.607.89 2.097c.087.205.028.443-.146.584-.173.141-.418.147-.601.021l-1.184-.826-.26 1.757c-.034.228-.219.403-.448.425h-.048zm-.91-3.634c.053 0 .107.009.159.026.147.049.263.164.313.311l.243.701.079-.533c.025-.171.138-.317.296-.386.159-.067.341-.051.484.049l.421.294-.398-.938c-.104-.247.004-.532.246-.646l.823-.392-1.04-.566c-.197-.107-.299-.333-.248-.552l.28-1.205-.558.374c-.129.086-.292.106-.438.059-.147-.049-.263-.164-.313-.311l-.241-.697-.077.525c-.025.171-.137.317-.295.386-.16.069-.342.051-.484-.048l-.429-.298.401.945c.104.246-.003.531-.245.646l-.821.391 1.041.565c.197.107.299.334.248.553l-.279 1.203.553-.371c.083-.056.18-.085.279-.085z"/></g><path fill="#292F33" d="M9.306 14.957c.229.497.147 1.024-.185 1.178-.332.153-.786-.127-1.016-.624-.229-.497-.147-1.024.185-1.177.331-.154.786.126 1.016.623zm6.698-2.936c-.129.532-.521.894-.876.809-.356-.087-.538-.589-.409-1.121.129-.532.521-.894.877-.807.354.085.537.586.408 1.119zm-2.644 9.914c-.129.532-.52.894-.875.809-.357-.087-.539-.588-.41-1.12.129-.531.521-.895.877-.808.354.086.537.587.408 1.119zm3.216 2.178c.229.497.147 1.023-.185 1.179-.331.151-.786-.128-1.016-.625-.228-.496-.148-1.023.185-1.178.332-.152.787.127 1.016.624zm1.121-7.683c-.304.292-.68.391-.843.225-.161-.17-.045-.542.258-.835.303-.292.681-.393.843-.224.162.169.047.542-.258.834zm-5.274-2.365c.181.38.158.768-.053.871-.212.098-.53-.129-.71-.509-.18-.38-.156-.77.056-.871.21-.101.528.128.707.509zm-3.98 7.094c-.304.292-.679.392-.843.225-.16-.169-.045-.542.258-.834.303-.291.68-.393.843-.225.162.169.047.542-.258.834zm10.622-.928c.329.356.382.842.116 1.093-.267.246-.752.159-1.082-.195-.33-.356-.384-.843-.116-1.094.267-.248.751-.16 1.082.196z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f95e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f95e.svg new file mode 100644 index 0000000000000000000000000000000000000000..795fb134113d3a6d462a6041e915b261e163cfd2 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f95e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#929497" cx="18" cy="23.949" rx="18" ry="10"/><ellipse fill="#CCD6DC" cx="18" cy="22.199" rx="18" ry="10"/><path fill="#F19020" d="M32 20.393c0 4.295-6.268 7.778-14 7.778S4 24.688 4 20.393s6.268-7.778 14-7.778 14 3.483 14 7.778z"/><path fill="#FAAA35" d="M32 18.239c0 4.295-6.268 7.778-14 7.778S4 22.534 4 18.239s6.268-7.778 14-7.778 14 3.483 14 7.778z"/><path fill="#F19020" d="M32 16.085c0 4.295-6.268 7.778-14 7.778S4 20.381 4 16.085s6.268-7.778 14-7.778 14 3.483 14 7.778z"/><path fill="#FAAA35" d="M32 13.932c0 4.295-6.268 7.778-14 7.778S4 18.227 4 13.932s6.268-7.778 14-7.778 14 3.482 14 7.778z"/><path fill="#F19020" d="M32 11.778c0 4.295-6.268 7.778-14 7.778S4 16.073 4 11.778 10.268 4 18 4s14 3.483 14 7.778z"/><path fill="#E18524" d="M28.316 23.498c-.726.439-1.542.832-2.431 1.17.119.557.468.846.87.846.601 0 1.32-.647 1.561-2.016"/><path fill="#E5922E" d="M28.401 21.292c-.765.471-1.632.89-2.583 1.247.013.708.024 1.262.024 1.691 0 .161.015.307.043.438.889-.337 1.705-.73 2.431-1.17.053-.304.083-.643.083-1.018l.002-1.188"/><path fill="#E18524" d="M28.41 19.132c-.776.479-1.658.905-2.625 1.265.009.834.021 1.543.032 2.142.95-.356 1.818-.775 2.583-1.247.003-.829.006-1.553.01-2.16"/><path fill="#E5922E" d="M28.433 16.955l-2.658 1.284c0 .799.005 1.516.011 2.158.967-.36 1.849-.786 2.625-1.265.009-1.401.022-2.177.022-2.177"/><path fill="#D17A28" d="M15.341 6.359c-3.971-1.211-5.645-.6-5.384 2.524.067.808-1.043 2.154-2.154 2.928-2.583 1.8-1.473 4.809 2.962 2.591 2.221-1.11 5.46-1.035 9.389.168 3.298 1.01 5.351 2.187 5.62 3.668.875-.296 1.942-.759 2.659-1.284-.271-.614-1.481-2.418-3.399-3.259-3.628-1.591-.124-3.884 2.591-4.442 2.457-.505.034-2.356-3.702-2.288-3.735.068-2.796 1.16-8.582-.606z"/><path fill="#FAAA35" d="M22.122 8.571s.107 1.247-.315 1.487l-3.046 1.736c-.421.24-1.102.24-1.523 0l-3.046-1.736c-.421-.24-.316-1.511-.316-1.511l8.246.024z"/><path fill="#FFD882" d="M21.807 8.113c.221.126.326.293.315.458-.01.149-.115.296-.315.41l-3.046 1.736c-.421.24-1.102.24-1.523 0l-3.046-1.736c-.21-.12-.316-.277-.316-.434 0-.157.105-.314.316-.434l3.046-1.736c.421-.24 1.102-.24 1.523 0l3.046 1.736z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f965.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f965.svg new file mode 100644 index 0000000000000000000000000000000000000000..7f1692794b5e506cb4111dedfa8c340f73004897 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f965.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8B5E3C" d="M5.506 30.167c-7.03-7.029-6.397-19.059 1.414-26.87l25.456 25.456c-7.811 7.811-19.841 8.443-26.87 1.414z"/><path fill="#603913" d="M6.92 3.297c-3.905 3.905-1.373 12.77 5.656 19.8 7.031 7.029 15.895 9.561 19.799 5.656 3.905-3.904 1.374-12.769-5.657-19.799C19.69 1.924 10.825-.607 6.92 3.297z"/><path fill="#F5F8FA" d="M31.591 24.217c.229.229.56.336.887.276.387-.071.696-.362.79-.745.067-.269 1.575-6.67-3.013-11.258-1.12-1.12-2.783-3.774-3.256-4.544-.4-.415-.733-.27-1.498-1.035-.35-.35-1.405-2.248-4.439.629-.35.332-.39.878-.116 1.275l10.528 15.263c.036.05.075.097.117.139z"/><path fill="#603913" d="M24.271 7.562c.707.707 1.458 1.417 1.458 1.417s2.404 2.804 3.819 4.218c4.242 4.243 2.75 10.313 2.75 10.313L20.646 7.833s2.792-1.042 3.625-.271zm1.271-1.354c-1.833-1.438-4.777-.315-5.5.396-.683.683-.467 1.984.081 2.778l10.528 15.263c.07.101.147.193.232.278.46.46 1.121.673 1.775.553.774-.142 1.393-.725 1.581-1.489.072-.293 1.705-7.223-3.277-12.205-.892-.892-1.938-1.738-2.909-2.913-.329-.423-1.186-1.441-2.074-2.328l-.437-.333z"/><path fill="#F5F8FA" d="M8.334 4.711c-3.124 3.124-.592 10.722 5.657 16.97 6.247 6.248 13.846 8.781 16.97 5.657 3.124-3.124.591-10.723-5.657-16.971-6.248-6.247-13.846-8.78-16.97-5.656z"/><path fill="#99AAB5" d="M10.411 6.877c-2.318 2.318-.083 8.314 4.994 13.391 5.078 5.078 11.072 7.312 13.391 4.994 2.318-2.318.083-8.313-4.994-13.391-5.076-5.078-11.072-7.313-13.391-4.994z"/><path fill="#99AAB5" d="M20.199 9.939l1.176-.335c.562-.312 1.354-.333 1.896.167l1.211 1.273c.573.69 1.919 2.137 2.995 3.213 3.807 3.807 2.319 8.722 2.253 8.93-.057.182-.213.315-.401.344-.159.024-.318-.029-.429-.141-.021-.021-.04-.043-.058-.068l-8.797-12.669c-.079-.114-.108-.254-.078-.39.029-.135.113-.252.232-.324z"/><path fill="#F5F8FA" d="M23.76 26.056s-3.209-2.085-3.771-3.771c-.628-1.885-4.662-2.252-5.29-4.138-.627-1.885-1.676-4.765-2.253-5.918-.576-1.153-1.258-.001-1.886-1.886-.628-1.887-1.885-3.144-1.885-3.144s0 8.801 1.885 10.686c1.886 1.886 9.429 9.429 10.058 8.799.628-.628 3.142-.628 3.142-.628z"/><path fill="#603913" d="M22.838 27.73s-3.73-2.537-4.316-4.294c-.655-1.964-5.29-2.619-5.944-4.583-.655-1.964-1.596-5.486-1.913-5.892-.916-1.18-1.309-.001-1.964-1.964-.655-1.965-1.964-3.274-1.964-3.274s0 9.166 1.964 11.13c1.964 1.965 9.82 9.821 10.476 9.166.655-.654 3.661-.289 3.661-.289z"/><path fill="#8B5E3C" d="M21.769 29.46s-3.61-2.345-4.242-4.242c-.707-2.121-6.365-3.536-7.072-5.657-.707-2.122-.707-4.95-1.414-5.657-.707-.708-1.414 0-2.121-2.122-.707-2.121-2.121-3.535-2.121-3.535s0 9.9 2.121 12.021 10.606 10.606 11.313 9.899c.708-.707 3.536-.707 3.536-.707z"/><path fill="#A97C50" d="M10.811 32.853c.091-.285.836-.061 1.113.001 6.934 1.526 11.66-1.385 11.712-1.409.272-.136.579-.034.685.224.106.258-.026.577-.296.712-.225.112-4.808 2.55-12.125.939-.091-.021-.721-.131-.781-.191-.123-.123-.37-.084-.308-.276zm-8.364-9.968c.115.114.108.212.29.165.288-.073.299-.517.255-.798-.492-3.192.36-6.504 1.841-10.352.107-.281-.027-.575-.294-.652-.272-.08-.579.084-.687.364-1.555 4.034-2.057 7.636-1.536 11.013.017.104.064.192.131.26zm10.357 9.178c.07.071.167.118.279.132 3.769.426 6.893-1.137 7.024-1.204.269-.137.4-.456.291-.714-.108-.259-.417-.356-.688-.218-.029.015-2.743 1.843-6.181 1.453-.285-.032-.826-.016-.889.275-.036.177.053.166.164.276z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f966.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f966.svg new file mode 100644 index 0000000000000000000000000000000000000000..ee2bc1cb1092e98a7c9eff728c50ae033a7267b4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f966.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M23.013 24.322l-5.546-5.546-5.547-5.546S12.375 24.413.737 27.323c0 0 1.032 2.487 3.364 4.819s4.819 3.364 4.819 3.364c2.91-11.639 14.093-11.184 14.093-11.184z"/><path fill="#5C913B" d="M13.83 16.594c-.727 3.637-5.092 9.456-5.092 9.456l8.728-8.728c2.909-2.909-3.636-.728-3.636-.728zm12.365 6.546s-10.91.727-17.457 5.819c8.001-8.001 11.638-8.728 11.638-8.728l5.819 2.909z"/><path fill="#3E721D" d="M30.156 28.192c.667.045 1.348-.178 1.858-.688.937-.937.937-2.457 0-3.394-.085-.085-.18-.154-.274-.224.411-.101.802-.304 1.123-.625.311-.311.509-.688.613-1.084.396-.105.773-.302 1.084-.613.937-.937.937-2.457 0-3.394.937-.937.937-2.457 0-3.394-.352-.352-.786-.572-1.241-.659.43-.893.284-1.994-.456-2.735-.321-.321-.712-.524-1.123-.625.094-.07.189-.139.274-.224.937-.937.937-2.457 0-3.394-.741-.741-1.842-.887-2.735-.456-.088-.455-.307-.889-.659-1.241-.51-.51-1.191-.732-1.858-.688.045-.667-.178-1.348-.688-1.858-.937-.937-2.457-.937-3.394 0-.741-.741-1.842-.887-2.735-.456-.088-.455-.307-.889-.659-1.241-.937-.937-2.457-.937-3.394 0-.352.352-.572.786-.659 1.241-.893-.43-1.994-.284-2.735.456-.321.321-.524.712-.625 1.123-.07-.094-.139-.189-.224-.274-.937-.937-2.457-.937-3.394 0-.742.739-.888 1.84-.458 2.734-.455.087-.889.307-1.241.659-.937.937-.937 2.457 0 3.394.321.321.712.524 1.123.625-.094.07-.189.139-.274.224-.937.937-.937 2.457 0 3.394.352.352.786.572 1.241.659-.43.893-.284 1.994.456 2.735.741.741 1.842.887 2.735.456.088.455.307.889.659 1.241.321.321.712.524 1.123.625-.094.07-.189.139-.274.224-.937.937-.937 2.457 0 3.394.741.741 1.842.887 2.735.456.088.455.307.889.659 1.241.636.636 1.537.83 2.345.603.064.084.124.169.201.246.51.51 1.191.732 1.858.688-.045.667.178 1.348.688 1.858.937.937 2.457.937 3.394 0 .085-.085.154-.18.224-.274.101.411.304.802.625 1.123.937.937 2.457.937 3.394 0 .51-.51.732-1.191.688-1.858z"/><circle fill="#5C913B" cx="10.92" cy="5.683" r="1.543"/><circle fill="#5C913B" cx="15.285" cy="5.683" r="1.543"/><circle fill="#5C913B" cx="18.194" cy="2.774" r="1.543"/><circle fill="#5C913B" cx="21.831" cy="4.956" r="1.543"/><circle fill="#5C913B" cx="24.74" cy="4.956" r="1.543"/><circle fill="#5C913B" cx="25.468" cy="7.138" r="1.543"/><circle fill="#5C913B" cx="27.65" cy="7.865" r="1.543"/><circle fill="#5C913B" cx="30.559" cy="9.32" r="1.543"/><circle fill="#5C913B" cx="29.832" cy="11.502" r="1.543"/><circle fill="#5C913B" cx="32.014" cy="15.139" r="1.543"/><circle fill="#5C913B" cx="32.741" cy="18.776" r="1.543"/><circle fill="#5C913B" cx="26.922" cy="11.502" r="1.543"/><circle fill="#5C913B" cx="24.013" cy="8.593" r="1.543"/><circle fill="#5C913B" cx="20.376" cy="6.411" r="1.543"/><circle fill="#5C913B" cx="16.012" cy="7.865" r="1.543"/><circle fill="#5C913B" cx="17.467" cy="6.411" r="1.543"/><circle fill="#5C913B" cx="13.102" cy="9.32" r="1.543"/><circle fill="#5C913B" cx="20.376" cy="10.775" r="1.543"/><circle fill="#5C913B" cx="25.468" cy="15.866" r="1.543"/><circle fill="#5C913B" cx="26.922" cy="20.231" r="1.543"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f968.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f968.svg new file mode 100644 index 0000000000000000000000000000000000000000..10bd682b6834cd71a5de16c5224809e189ecbf7a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f968.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M35 16c0-8-6-11-12-11-1.738 0-3.472.371-5 1.097C16.472 5.371 14.738 5 13 5 7 5 1 8 1 16c0 3 1.314 5.662 3 8 .434.602.903 1.146 1.4 1.647-.357.603-.616 1.091-.779 1.353C4 28 5 29 6 29c.69 0 1.205-.617 1.745-1.482C10.552 29.273 14.023 30 18 30s7.448-.727 10.255-2.482C28.795 28.383 29.31 29 30 29c1 0 2-1 1.379-2-.163-.262-.422-.75-.779-1.353.497-.501.967-1.046 1.4-1.647 1.686-2.338 3-5 3-8zm-17 1.207C16.578 15.736 17 14 17 14c0-.708.381-1.414 1-2.034.619.62 1 1.326 1 2.034 0 0 .422 1.736-1 3.207zM8.215 19.94C6.59 17.687 6.204 15.388 7 13c1.053-3.158 4.85-3 6-3 .288 0 .576.024.861.059C13.314 11.185 13 12.498 13 14c0 1.476.578 3.273 1.951 4.799-.298.075-.61.144-.951.201-1.907.318-3.471 1.122-4.745 2.107-.375-.355-.73-.736-1.04-1.167zM18 24c-2.296 0-4.476-.394-6.324-1.266.657-.372 1.415-.642 2.324-.734 1.565-.157 2.885-.524 4-1.024 1.115.5 2.435.867 4 1.024.909.092 1.667.362 2.324.734C22.476 23.606 20.296 24 18 24zm9.785-4.06c-.311.431-.665.812-1.04 1.167C25.471 20.122 23.906 19.318 22 19c-.341-.057-.653-.126-.95-.201C22.422 17.273 23 15.476 23 14c0-1.502-.313-2.815-.861-3.941.285-.035.573-.059.861-.059 1.15 0 4.947-.158 6 3 .796 2.388.41 4.687-1.215 6.94z"/><path fill="#AD5810" d="M11.751 22.764c-.794.448-1.78 1.172-2.376 2.236-.688 1.229-1.218 2.033-1.584 2.544.335.207.679.402 1.032.581.353-.692.878-1.653 1.552-2.688.768-1.179 1.902-1.912 2.489-2.238-.381-.131-.756-.269-1.113-.435zm11.692-.434l-.005.002c.314.114.611.247.886.402-.19.09-.399.153-.597.233.564.415 1.348 1.092 1.96 2.032.74 1.136 1.377 2.218 1.797 2.952.26-.14.521-.278.771-.435.188.3.372.567.562.792 0 0-.562-.792-2.004-3.31s-3.37-2.668-3.37-2.668zm-2.393-3.531c.05-.055.09-.112.138-.168-.568.444-1.34 1.055-2.023 1.622-.358.297-.763.531-1.161.724.401.18.839.335 1.296.477.524-.293 1.157-.698 1.701-1.204.56-.521.892-.92 1.081-1.23-.029-.005-.054-.015-.082-.02-.341-.057-.653-.126-.95-.201zm-2.467-6.088c.732-.612 2.127-1.524 3.951-1.669-.109-.324-.233-.637-.376-.935-.583.091-1.385.249-2.158.518-.877.305-1.58.914-1.998 1.344.235.236.423.486.581.742z"/><g fill="#FFE8B6"><circle cx="7" cy="22" r="1"/><circle cx="3" cy="14" r="1"/><circle cx="6" cy="11" r="1"/><circle cx="12" cy="7" r="1"/><circle cx="14" cy="27" r="1"/><circle cx="21" cy="26" r="1"/><circle cx="25" cy="27" r="1"/><circle cx="31" cy="17" r="1"/><circle cx="31" cy="9" r="1"/><circle cx="22" cy="8" r="1"/><circle cx="19" cy="9" r="1"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f96c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f96c.svg new file mode 100644 index 0000000000000000000000000000000000000000..6ef36cb221f1a41977927ff6006fd78d68e8d7c0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f96c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M29.866 24.625c2.522-.841 5.884-4.203 5.884-5.884s-2.522-.841-1.681-3.362 1.681-5.043 0-6.724-3.362 0-5.043-1.681 0-3.362-1.681-5.043-4.203-.841-6.724 0S18.939.25 17.258.25s-5.043 3.362-5.884 5.884-2.521.84-3.361 3.362c-.78 2.341.177 4.823-1.972 9.748-1.026 1.621-1.995 3.178-2.899 4.543C-.836 29.792.449 35.552.449 35.552s5.76 1.285 11.765-2.693c1.365-.904 2.922-1.873 4.543-2.899 4.925-2.15 7.407-1.192 9.748-1.972 2.521-.841.84-2.522 3.361-3.363z"/><path fill="#679E44" d="M34.253 19.017c-.103-.312-.438-.483-.75-.379-3.21 1.054-5.749.677-7.001.349 2.811-2.865 5.337-5.842 7.222-8.589.186-.271.116-.641-.154-.827-.271-.187-.641-.116-.826.154-1.082 1.576-2.403 3.251-3.878 4.944.082-1.765-.065-4.516-1.327-7.238-.139-.298-.492-.427-.789-.289-.298.138-.428.491-.289.789 1.679 3.623 1.194 7.416 1.062 8.235-1.369 1.489-2.837 2.973-4.356 4.402.156-1.873.084-4.922-1.559-7.337-.183-.271-.552-.343-.825-.158-.271.185-.342.554-.157.826 1.957 2.879 1.347 7.003 1.178 7.925-2.44 2.2-4.953 4.211-7.33 5.836 1.535-2.474 3.146-6.37 2-10.845-.082-.318-.406-.511-.723-.428-.318.082-.51.405-.428.723 1.679 6.557-3.33 11.987-3.778 12.456-5.407 3.356-8.373 4.368-8.407 4.379-.311.104-.479.439-.375.751.083.249.314.407.563.407.062 0 .125-.01.187-.03.16-.054 3.996-1.354 11.056-6.036 1.365-.905 2.768-1.936 4.176-3.05.695.426 2.288 1.141 5.162 1.141.804 0 1.706-.057 2.717-.19.325-.043.554-.342.511-.667-.042-.325-.349-.555-.667-.511-3.704.492-5.777-.136-6.717-.581 1.974-1.619 3.937-3.396 5.799-5.235.617.218 1.922.586 3.735.586 1.299 0 2.854-.189 4.592-.761.309-.105.478-.441.376-.752z"/><path fill="#3E721D" d="M12.753 24.327c.456-.09 1.009-.182 1.61-.281 3.811-.633 7.752-1.288 7.752-3.729 0-1.241-.664-1.982-1.101-2.436.25-.076.59-.147.825-.198 1.07-.227 2.402-.51 2.983-1.69.359-.729.313-1.608-.143-2.635.416-.307 1.58-.678 2.308-.909 1.796-.572 3.493-1.113 3.959-2.504.163-.484.223-1.25-.409-2.144-.008-.011-.02-.035-.028-.05-.495-.084-.989-.284-1.484-.778-.313-.313-.509-.626-.632-.939.234.645.845 2.094 1.123 2.486 2.031 2.872-7.321 2.534-6.024 5.247 1.541 3.222-2.907 2.206-3.747 3.467-.841 1.261 1.121 1.401 1.121 3.082s-5.746 2.271-8.354 2.783C7.243 24.136.448 35.552.448 35.552s.508.11 1.363.165c2.052-3.324 7.257-10.666 10.942-11.39z"/><path fill="#77B255" d="M12.512 23.101c2.608-.512 8.354-1.102 8.354-2.783s-1.961-1.821-1.121-3.082c.841-1.261 5.288-.245 3.747-3.467-1.298-2.713 8.055-2.375 6.024-5.247-.322-.455-1.094-2.335-1.205-2.729-.363-1.287.321-2.574-.967-3.861-1.681-1.681-4.203-.841-6.724 0S18.939.25 17.258.25s-5.043 3.362-5.884 5.884-2.521.84-3.361 3.362c-.78 2.341.177 4.823-1.972 9.748-1.026 1.621-1.995 3.178-2.899 4.543C-.836 29.792.449 35.552.449 35.552s6.794-11.416 12.063-12.451z"/><path fill="#A6D388" d="M28.4 8.292c-2.723-1.262-5.475-1.409-7.24-1.326 1.693-1.476 3.367-2.797 4.944-3.878.271-.186.34-.556.154-.827-.186-.27-.556-.339-.826-.154-2.747 1.884-5.724 4.411-8.589 7.222-.329-1.253-.706-3.791.349-7.001.103-.312-.067-.648-.379-.75-.31-.103-.647.067-.75.379-1.366 4.158-.55 7.265-.176 8.328-1.839 1.862-3.616 3.824-5.235 5.799-.445-.94-1.071-3.013-.58-6.719.043-.325-.186-.624-.511-.667-.32-.043-.623.184-.667.51-.613 4.63.407 6.991.951 7.879-1.115 1.408-2.145 2.811-3.05 4.176C2.112 28.323.812 32.159.759 32.318c-.104.312.065.647.376.751.062.021.125.03.188.03.249 0 .481-.157.564-.406.011-.034 1.023-2.999 4.378-8.406.463-.446 5.882-5.465 12.456-3.778.314.079.642-.111.723-.429.081-.318-.11-.642-.429-.724-4.475-1.144-8.373.468-10.848 2.003 1.625-2.378 3.637-4.893 5.838-7.334.923-.169 5.047-.777 7.925 1.18.103.069.219.103.333.103.19 0 .378-.091.492-.26.185-.271.114-.641-.157-.826-2.416-1.642-5.465-1.714-7.338-1.558 1.428-1.518 2.912-2.986 4.401-4.355.814-.134 4.598-.625 8.236 1.061.081.038.166.056.25.056.224 0 .438-.128.539-.345.142-.298.012-.652-.286-.789z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f96d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f96d.svg new file mode 100644 index 0000000000000000000000000000000000000000..b5607c107cc4d30384cfb95c1add70e69dbef304 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f96d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M26.38 3.539c.483-.039 1.259-.655 1.664-.595.405.06 1.573 1.078 1.67 1.283.097.205-.637 1.178-.746 1.48-.109.302-.64.239-1.51-.543-.869-.782-1.078-1.625-1.078-1.625z"/><path fill="#EA564B" d="M12.3 3.139c4.545-2.66 11.267-2.611 13.685-.58 1.617 1.358 2.942 2.401 4.474 3.011 2.022.804 3.692 3.154 4.415 5.384.981 3.023 1.68 12.579-8.029 18.516-6.233 3.812-17.656 5.363-18.961 4.723-.984-.483-4.621-2.09-6.675-6.453S-1.324 11.111 12.3 3.139z"/><path fill="#F97253" d="M17.329 2.607C22.578 1.125 26.5 4.743 24.078 5c-4.359.463-9.015 4.969-12.625 8.375-6.625 6.25-8.125 13.75-9 12.5-1.424-2.034-1.468-9.148 3.561-15.386 5.029-6.238 9.104-7.257 11.315-7.882z"/><path fill="#77B255" d="M28.271 4.278c2.174.697 4.987 4.564 4.944 7.811-.114 8.655-4.132 11.992-4.132 11.992s-2.551-9.325-2.171-12.719c.278-2.478 1.646-3.166 1.891-4.569.229-1.305-.532-2.515-.532-2.515z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f96f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f96f.svg new file mode 100644 index 0000000000000000000000000000000000000000..6a65f4c19330d6a9aa0558c9cd9ae8042dd1070a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f96f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M18.09 9.295C7.847 9.295.573 13.188.573 18.053c0 7.569 5.839 15.57 17.517 15.57 11.678 0 17.517-8.001 17.517-15.57 0-4.865-7.274-8.758-17.517-8.758z"/><path fill="#D99E82" d="M18.09 8.322C7.847 8.322.573 11.961.573 17.927c0 5.966 7.273 9.858 17.517 9.858 10.243 0 17.517-4.146 17.517-9.858S28.333 8.322 18.09 8.322z"/><path fill="#CCD6DD" d="M2.519 20.973c-.973.973 4.866 6.812 7.785 3.893 2.919-2.919 5.942 1.511 6.812 1.946 1.946.973 6.754-4.408 11.678-1.946 1.947.973 4.866-1.946 4.866-4.866 0-2.919-30.167 0-31.141.973z"/><path fill="#FFF" d="M2.422 19.462s-.181.378-.169.496c.217 2.144 5.132 6.854 8.052 3.935 2.919-2.919 5.942 1.511 6.812 1.946 1.946.973 6.754-4.408 11.678-1.946 1.608.804 4.848-2.228 5.258-4.811-2.136 0-31.631.38-31.631.38z"/><path fill="#C1694F" d="M18.733 2.583C14.568 2.34.805 4.52.307 16.595c.01.608.592 1.741 2.114 2.867 2.556 1.891 7.765 3.764 17.378 3.103 8.374-.576 12.357-2.1 14.253-3.483 1.577-1.15 1.711-2.203 1.711-2.532.001-3.89-3.541-13.164-17.03-13.967z"/><path fill="#FFF" d="M14.468 10.228c1.188.461 2.637.578 3.799.622 1.54.058 3.13-.13 4.572-.699 0-.963 0-2.838-4.186-2.838s-4.185 1.771-4.185 2.915z"/><path fill="#8A4B38" d="M18.811 6.302c-3.959-.262-7.406 2.073-5.272 3.453.279.191.596.344.93.473.897-.78 2.572-1.596 4.285-1.521 2.026.089 3.393.727 4.086 1.444.312-.123.62-.258.917-.419 1.489-1.108-.056-3.106-4.946-3.43z"/><g fill="#D99E82"><path d="M9.226 9.736c-.535.226-2.352.483-2.578-.052s1.225-1.659 1.76-1.885c.535-.226 1.152.024 1.378.559.225.535-.025 1.152-.56 1.378zm22.199-.506c.311.349.977 1.667.628 1.978-.349.311-1.581-.503-1.892-.852-.311-.349-.28-.884.069-1.194.349-.312.884-.281 1.195.068zm-6.578 8.119c-.442.152-1.915.258-2.067-.184-.152-.442 1.075-1.264 1.517-1.416.442-.152.923.083 1.075.525.152.442-.083.923-.525 1.075zm-16.86-3.013c-.393.428-1.839 1.308-2.267.915-.428-.393.325-1.909.718-2.337.393-.428 1.058-.456 1.485-.064.429.393.457 1.058.064 1.486z"/><ellipse transform="matrix(1 -.0076 .0076 1 -.031 .133)" cx="17.539" cy="4.159" rx="1.216" ry=".566"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f980.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f980.svg new file mode 100644 index 0000000000000000000000000000000000000000..8f45b53dd4f910f984267831ee0839bcd1d1a3cc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f980.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A0041E" d="M6.96 20.637c.068.639-.543 1.228-1.368 1.315-.824.089-1.547-.357-1.615-.995-.068-.639.544-1.227 1.368-1.314.824-.089 1.547.356 1.615.994zm2.087 2.717c.125.818-1.756 2.544-2.576 2.669-.819.125-1.584-.438-1.708-1.257-.125-.818.58-1.14 1.398-1.265.819-.124 2.761-.965 2.886-.147zm1.783 2.104c.173.81-1.628 3.927-2.438 4.1-.811.173-1.645.146-1.817-.665-.173-.81.306-1.688 1.116-1.861.81-.174 2.966-2.384 3.139-1.574zm3.853.858c.165.811-1.338 4.354-2.15 4.519-.812.165-1.439.451-1.604-.36-.165-.812.261-1.975 1.006-2.58.644-.523 2.584-2.39 2.748-1.579z"/><path fill="#A0041E" d="M3.925 18.869c.607.715 1.18 1.23.464 1.835-.716.606-1.747.162-2.354-.554-.605-.715-2.239-3.42-1.524-4.025.717-.606 2.809 2.029 3.414 2.744zm.33 4.88c.892.295 1.857.801 1.563 1.691-.294.891-1.328.991-2.219.698-.889-.295-3.772-1.691-3.478-2.581.295-.89 3.244-.102 4.134.192zm1.214 4.532c.905-.253 1.907-.283 2.159.619.252.903-.282 1.535-1.186 1.787-.902.251-4.342.727-4.594-.176-.251-.905 2.718-1.98 3.621-2.23zm4.348 3.188c.084-.937.644-1.669 1.577-1.585.934.085 1.258 1.025 1.173 1.96-.085.934.147 3.562-1.715 4.016-.912.221-1.121-3.46-1.035-4.391zM29.04 20.637c-.068.639.543 1.228 1.367 1.315.824.089 1.547-.357 1.615-.995.068-.639-.544-1.227-1.367-1.314-.824-.089-1.547.356-1.615.994zm-2.087 2.717c-.125.818 1.757 2.544 2.575 2.669.819.125 1.584-.438 1.709-1.257s-.58-1.14-1.398-1.265c-.819-.124-2.761-.965-2.886-.147zm-1.783 2.104c-.173.81 1.628 3.927 2.438 4.1.81.173 1.644.146 1.816-.665.174-.81-.305-1.688-1.115-1.861-.81-.174-2.966-2.384-3.139-1.574zm-3.853.858c-.166.811 1.338 4.354 2.149 4.519.812.165 1.438.451 1.604-.36.164-.812-.262-1.975-1.007-2.58-.642-.523-2.582-2.39-2.746-1.579z"/><path fill="#A0041E" d="M32.075 18.869c-.607.715-1.18 1.23-.465 1.835.716.606 1.747.162 2.354-.554.605-.715 2.239-3.42 1.523-4.025-.715-.606-2.807 2.029-3.412 2.744zm-.33 4.88c-.892.295-1.857.801-1.562 1.691.293.891 1.328.991 2.219.698.889-.295 3.771-1.691 3.477-2.581-.294-.89-3.244-.102-4.134.192zm-1.215 4.532c-.904-.253-1.906-.283-2.158.619-.252.903.282 1.535 1.185 1.787.902.251 4.343.727 4.594-.177.252-.904-2.717-1.979-3.621-2.229zm-4.347 3.188c-.084-.937-.645-1.669-1.577-1.585-.935.085-1.258 1.025-1.173 1.96.084.934-.147 3.562 1.715 4.016.912.221 1.121-3.46 1.035-4.391zM3.148 13.878c-.383-.856.001-1.86.857-2.242.856-.383 1.86.002 2.243.858.381.855 2.651 5.612 1.795 5.994-.855.382-4.513-3.755-4.895-4.61z"/><path fill="#A0041E" d="M3.994 12.034c1.221 2.956 8.341-3.341 8.803-6.281.462-2.939-.308-4.201-.694-4.5-.386-.299.144 1.435-1.187 3.306-1.053 1.482-7.766 5.434-6.922 7.475zm28.858 1.844c.384-.856-.001-1.86-.857-2.242-.857-.383-1.861.002-2.244.858-.381.855-2.65 5.612-1.794 5.994.855.382 4.513-3.755 4.895-4.61z"/><path fill="#A0041E" d="M32.007 12.034c-1.222 2.956-8.341-3.341-8.804-6.281-.461-2.939.309-4.201.694-4.5.386-.299-.144 1.435 1.187 3.306 1.054 1.482 7.766 5.434 6.923 7.475z"/><path fill="#BE1931" d="M6 22c0-2 2-10 12-10s12 8 12 10c-5 3-5.373 7-12 7s-6-4-12-7zm-1.677-9.777c-3.153.543-.358-8.141 1.883-10.099C8.446.166 10.863.207 11.321.374s-1.174 2.595-1.75 4.178c-.293.803-3.072 7.296-5.248 7.671zm27.354 0c3.152.543.358-8.141-1.882-10.099C27.555.166 25.139.207 24.68.374c-.459.167 1.174 2.595 1.75 4.178.293.803 3.071 7.296 5.247 7.671z"/><path fill="#A0041E" d="M17.032 12.136c.335 1.339-.045 1.588-.849 1.789-.804.201-1.727.278-2.061-1.061-.335-1.339.045-2.588.849-2.789.803-.201 1.726.721 2.061 2.061zm4.846.728c-.335 1.34-1.258 1.262-2.061 1.061-.804-.201-1.184-.45-.849-1.789.335-1.34 1.258-2.262 2.062-2.061.803.2 1.183 1.449.848 2.789z"/><circle fill="#292F33" cx="14.5" cy="9.5" r="1.5"/><circle fill="#292F33" cx="21.5" cy="9.5" r="1.5"/><path fill="#DD2E44" d="M9.053 21.529c-.14.236-3.053.732-2.303-.731s2.443.497 2.303.731z"/><path fill="#DD2E44" d="M9.891 20.124c-.218.225-3.188.391-1.922-1.404 1.265-1.793 2.234 1.082 1.922 1.404z"/><path fill="#DD2E44" d="M11.657 18.66c-.378.231-3.471-.501-1.407-1.932 1.872-1.296 1.906 1.626 1.407 1.932z"/><path fill="#DD2E44" d="M14.102 17.427c-1.008.299-3.378-1.302-.881-2.141 2.498-.839 1.889 1.842.881 2.141zm12.754 4.102c.141.235 3.053.731 2.303-.731-.75-1.463-2.443.497-2.303.731z"/><path fill="#DD2E44" d="M26.019 20.124c.218.225 3.188.391 1.922-1.404-1.266-1.793-2.235 1.082-1.922 1.404z"/><path fill="#DD2E44" d="M24.253 18.66c.378.231 3.471-.501 1.406-1.932-1.872-1.296-1.906 1.626-1.406 1.932z"/><path fill="#DD2E44" d="M21.808 17.427c1.008.299 3.378-1.302.881-2.141-2.499-.839-1.89 1.842-.881 2.141z"/><path fill="#A0041E" d="M26.849 16.25c0 .414-2.189-2.25-8.849-2.25-6.661 0-8.848 2.664-8.848 2.25 0-.414 2.754-3.75 8.848-3.75 6.094 0 8.849 3.336 8.849 3.75z"/><path fill="#DD2E44" d="M10.793 24.433c0-.414 1.782 2.25 7.207 2.25s7.208-2.664 7.208-2.25c0 .414-2.244 3.75-7.208 3.75s-7.207-3.336-7.207-3.75z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f981.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f981.svg new file mode 100644 index 0000000000000000000000000000000000000000..674ff24e628ae477ebc72ca4dc1a99bb06a1e90a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f981.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M32.325 10.958s2.315.024 3.511 1.177c-.336-4.971-2.104-8.249-5.944-10.13-3.141-1.119-6.066 1.453-6.066 1.453s.862-1.99 2.19-2.746C23.789.236 21.146 0 18 0c-3.136 0-5.785.227-8.006.701 1.341.745 2.215 2.758 2.215 2.758S9.194.803 6 2.053C2.221 3.949.481 7.223.158 12.174c1.183-1.19 3.55-1.215 3.55-1.215S-.105 13.267.282 16.614c.387 2.947 1.394 5.967 2.879 8.722C3.039 22.15 5.917 20 5.917 20s-2.492 5.96-.581 8.738c1.935 2.542 4.313 4.641 6.976 5.916-.955-1.645-.136-3.044-.103-2.945.042.125.459 3.112 2.137 3.743 1.178.356 2.4.548 3.654.548 1.292 0 2.55-.207 3.761-.583 1.614-.691 2.024-3.585 2.064-3.708.032-.098.843 1.287-.09 2.921 2.706-1.309 5.118-3.463 7.064-6.073 1.699-2.846-.683-8.557-.683-8.557s2.85 2.13 2.757 5.288c1.556-2.906 2.585-6.104 2.911-9.2-.035-3.061-3.459-5.13-3.459-5.13z"/><path fill="#FFCC4D" d="M13.859 9.495c.596 2.392.16 4.422-2.231 5.017-2.392.596-6.363.087-6.958-2.304-.596-2.392.469-5.39 1.81-5.724 1.341-.334 6.784.62 7.379 3.011zm9.104 18.432c0 2.74-2.222 4.963-4.963 4.963s-4.963-2.223-4.963-4.963c0-2.741 2.223-4.964 4.963-4.964 2.741 0 4.963 2.222 4.963 4.964z"/><path fill="#DD2E44" d="M21.309 27.927c0 1.827-1.481 3.309-3.309 3.309s-3.309-1.481-3.309-3.309c0-1.827 1.481-3.31 3.309-3.31s3.309 1.483 3.309 3.31z"/><path fill="#E6AAAA" d="M11.052 8.997c.871 1.393.447 3.229-.946 4.1-1.394.871-2.608.797-3.479-.596-.871-1.394-.186-4.131.324-4.45.51-.319 3.23-.448 4.101.946z"/><path fill="#FFCC4D" d="M22.141 9.495c-.596 2.392-.159 4.422 2.232 5.017 2.392.596 6.363.087 6.959-2.304.596-2.392-.47-5.39-1.811-5.724-1.342-.334-6.786.62-7.38 3.011z"/><path fill="#E6AAAA" d="M24.948 8.997c-.871 1.393-.447 3.229.945 4.1 1.394.871 2.608.797 3.479-.596.871-1.394.185-4.131-.324-4.45-.51-.319-3.229-.448-4.1.946z"/><path fill="#FFCC4D" d="M18 7.125h-.002C5.167 7.126 7.125 12.083 8.5 18.667 9.875 25.25 10.384 27 10.384 27h15.228s.51-1.75 1.885-8.333C28.872 12.083 30.829 7.126 18 7.125z"/><path fill="#272B2B" d="M12 16s0-1.5 1.5-1.5S15 16 15 16v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V16zm9 0s0-1.5 1.5-1.5S24 16 24 16v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V16z"/><path fill="#FFE8B6" d="M20.168 21.521c-1.598 0-1.385.848-2.168 2.113-.783-1.266-.571-2.113-2.168-2.113-6.865 0-6.837.375-6.865 2.828-.058 4.986 2.802 6.132 5.257 6.06 1.597-.048 2.994-.88 3.777-2.131.783 1.251 2.179 2.083 3.776 2.131 2.455.072 5.315-1.073 5.257-6.06-.029-2.453-.001-2.828-6.866-2.828z"/><path fill="#272B2B" d="M14.582 21.411c-1.14.233 2.279 4.431 3.418 4.431s4.559-4.198 3.419-4.431c-1.14-.232-5.698-.232-6.837 0z"/><circle fill="#D99E82" cx="11.5" cy="24.5" r=".5"/><circle fill="#D99E82" cx="10.5" cy="26.5" r=".5"/><circle fill="#D99E82" cx="12.5" cy="27.5" r=".5"/><circle fill="#D99E82" cx="24.5" cy="24.5" r=".5"/><circle fill="#D99E82" cx="25.5" cy="26.5" r=".5"/><circle fill="#D99E82" cx="23.5" cy="27.5" r=".5"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f984.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f984.svg new file mode 100644 index 0000000000000000000000000000000000000000..19d9ff1613d2bcc8afac81374d86db2318ec967d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f984.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1CDD5" d="M36 19.854C33.518 9.923 25.006 1.909 16.031 6.832c0 0-4.522-1.496-5.174-1.948-.635-.44-1.635-.904-.912.436.423.782.875 1.672 2.403 3.317C8 12.958 9.279 18.262 7.743 21.75c-1.304 2.962-2.577 4.733-1.31 6.976 1.317 2.33 4.729 3.462 7.018 1.06 1.244-1.307.471-1.937 3.132-4.202 2.723-.543 4.394-1.791 4.394-4.375 0 0 .795-.382 1.826 6.009.456 2.818-.157 5.632-.039 8.783H36V19.854z"/><path fill="#60379A" d="M31.906 6.062c.531 1.312.848 3.71.595 5.318-.15-3.923-3.188-6.581-4.376-7.193-2.202-1.137-4.372-.979-6.799-.772.111.168.403.814.32 1.547-.479-.875-1.604-1.42-2.333-1.271-1.36.277-2.561.677-3.475 1.156-.504.102-1.249.413-2.372 1.101-1.911 1.171-4.175 4.338-6.737 3.511 1.042 2.5 3.631 1.845 3.631 1.845 1.207-1.95 4.067-3.779 6.168-4.452 7.619-1.745 12.614 3.439 15.431 9.398.768 1.625 2.611 7.132 4.041 10.292V10.956c-.749-1.038-1.281-3.018-4.094-4.894z"/><path fill="#C1CDD5" d="M13.789 3.662c.573.788 3.236.794 4.596 3.82 1.359 3.026-1.943 2.63-3.14 1.23-1.334-1.561-1.931-2.863-2.165-3.992-.124-.596-.451-2.649.709-1.058z"/><path fill="#758795" d="M14.209 4.962c.956.573 2.164 1.515 2.517 2.596.351 1.081-.707.891-1.349-.042-.641-.934-.94-1.975-1.285-2.263-.346-.289.117-.291.117-.291z"/><circle fill="#292F33" cx="15.255" cy="14.565" r=".946"/><path fill="#53626C" d="M8.63 26.877c.119.658-.181 1.263-.67 1.351-.49.089-.984-.372-1.104-1.03-.119-.659.182-1.265.671-1.354.49-.088.984.373 1.103 1.033z"/><path fill="#EE7C0E" d="M13.844 8.124l.003-.002-.005-.007-.016-.014c-.008-.007-.011-.019-.019-.025-.009-.007-.021-.011-.031-.018C12.621 7.078.933-.495.219.219-.51.948 10.443 9.742 11.149 10.28l.011.006.541.439c.008.007.01.018.018.024.013.01.028.015.042.024l.047.038-.009-.016c.565.361 1.427.114 1.979-.592.559-.715.577-1.625.066-2.079z"/><path fill="#C43512" d="M4.677 2.25l.009-.025c-.301-.174-.594-.341-.878-.5-.016.038-.022.069-.041.11-.112.243-.256.484-.429.716-.166.224-.349.424-.541.595-.02.018-.036.026-.056.043.238.22.489.446.745.676.234-.21.456-.449.654-.717.214-.287.395-.589.537-.898zm2.275 2.945c.306-.41.521-.822.66-1.212-.292-.181-.584-.36-.876-.538-.076.298-.247.699-.586 1.152-.31.417-.613.681-.864.845.259.223.52.445.779.665.314-.244.619-.552.887-.912zM9.87 7.32c.365-.49.609-.983.734-1.437l-.906-.586c-.023.296-.172.81-.631 1.425-.412.554-.821.847-1.1.978l.814.671c.381-.256.761-.611 1.089-1.051z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f986.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f986.svg new file mode 100644 index 0000000000000000000000000000000000000000..085c9006346839f4f04d9be09852a0136a39c0de --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f986.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M12.75 17.75c1.226 2.195 1.856-1.361 9.312-2.625s13.729 4.454 13.859 5.413c.132.958-4.447 9.462-9.462 9.462H10.75c-4.143 0-7.022-7.224-4-11.438 0 0 4.5-3.5 6-.812z"/><path fill="#C1694F" d="M13.008 18.136C8.02 25.073 6.969 30 10.75 30c-4.143 0-6.578-6.188-4.468-11.031.463-1.064 1.758-2.492 1.758-2.492l4.179-.008c.162.32.599 1.365.789 1.667z"/><path fill="#E1E8ED" d="M20.062 22.75c6.672-2.682 15.729-3.171 15.859-2.212.132.958-4.447 9.462-9.462 9.462H11.813c-4.143 0 1.232-4.429 8.249-7.25z"/><path fill="#292F33" d="M25.359 21.125c6-1.312 10.468-1.282 10.563-.587.079.578-1.559 3.907-3.973 6.454 2.204-2.804 1.42-6.113-6.59-5.867z"/><path fill="#3E721D" d="M7.125 6.125c1.562-4.938 10.44-4.143 10.062.688-.378 4.829-6.453 7.859-4.179 11.323-1.586 1.38-5.016.913-6.727.833.702-1.351 1.381-2.631 1.812-3.406 2.916-5.235-2.131-5.764-.968-9.438z"/><path fill="#FFCC4D" d="M1.893 9.045c.568-1.1.549.106 3.352.142 1.554.021 1.463-.56 1.664-1.621.041-.223.776 1.616 2.061 1.807 3.554.531 1.879 1.94 0 2.261-.901.154-2.01.318-3.938.155-2.519-.212-3.768-1.528-3.139-2.744z"/><path fill="#F5F8FA" d="M12.502 16.625c.044.625.506 1.511.506 1.511-1.016 1.474-5.643 3.017-7.354 2.93.096-.628.283-1.362.627-2.097 1.844-.471 4.661-1.071 6.221-2.344z"/><path fill="#292F33" d="M11.708 6.151c0 .716-.58 1.296-1.296 1.296s-1.295-.58-1.295-1.296c0-.716.579-1.295 1.295-1.295s1.296.58 1.296 1.295z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f987.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f987.svg new file mode 100644 index 0000000000000000000000000000000000000000..4ebb5ad4c15f5917ed3e0dc94f71025066894ec9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f987.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M23 21c0 6.352-3 10-5 10s-5-3.648-5-10 2.239-7 5-7c2.762 0 5 .648 5 7z"/><circle fill="#66757F" cx="18" cy="11" r="4"/><path fill="#66757F" d="M14 11c-2-5 1-7 1-7s2 1 2 4-3 3-3 3z"/><path fill="#546066" d="M14.668 9.904c-.776-2.457-.119-3.896.403-4.58C15.486 5.773 16 6.608 16 8c0 1.268-.739 1.734-1.332 1.904z"/><path fill="#66757F" d="M22 11c2-5-1-7-1-7s-2 1-2 4 3 3 3 3zm-5.984 3c-1.62 1.157-10 2-9-5 .142-.99-1-1-2 0-3 3-6 7.834-4 20 3-5 6-4 7 1 3-4 6-2 8 0 3-3 0-16 0-16zm3.937 0c1.62 1.157 10 2 9-5-.142-.99 1-1 2 0 3 3 6 7.834 4 20-3-5-6-4-7 1-3-4-6-2-8 0-3-3 0-16 0-16z"/><circle fill="#292F33" cx="16" cy="11" r="1"/><circle fill="#292F33" cx="20" cy="11" r="1"/><path fill="#546066" d="M21.332 9.904c.775-2.457.118-3.896-.403-4.58C20.514 5.773 20 6.608 20 8c0 1.268.739 1.734 1.332 1.904z"/><path fill="#99AAB5" d="M7.996 26.91c.892-2.691.573-5.988-.996-9.91-1.487-3.719-1.315-6.329-1.129-7.423-.049.041-.096.078-.148.13C3.017 12.414.477 16.531 1.66 26.436c1.276-1.379 2.412-1.723 3.228-1.723 1.265 0 2.333.783 3.108 2.197z"/><path fill="#99AAB5" d="M6.832 13.25c-.019-.03-.041-.058-.06-.087C7 16 8.4 17.001 9 20c.588 2.94.476 5.519.088 7.564.839-.571 1.726-.874 2.656-.874 1.264 0 2.548.538 3.895 1.627C14 19 9 17 6.832 13.25zm21.172 13.66c-.893-2.691-.572-5.988.996-9.91 1.487-3.719 1.315-6.329 1.129-7.423.049.041.097.078.148.13 2.706 2.707 5.246 6.824 4.063 16.729-1.275-1.379-2.412-1.723-3.227-1.723-1.266 0-2.334.783-3.109 2.197z"/><path fill="#99AAB5" d="M29.168 13.25l.061-.087C29 16 27.6 17.001 27 20c-.588 2.94-.477 5.519-.088 7.564-.84-.571-1.726-.874-2.656-.874-1.264 0-2.548.538-3.895 1.627C22 19 27 17 29.168 13.25zm-10.48-.144c-.378.378-.998.378-1.375 0l-.57-.571c-.378-.378-.25-.688.285-.688h1.945c.535 0 .664.309.285.688l-.57.571z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f988.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f988.svg new file mode 100644 index 0000000000000000000000000000000000000000..f6381c521eaf5c875153ee7f83ff0ce4d17e671e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f988.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M36 21c0 5-3 9-11 11-7.062 1.766-21-.934-21-2 0-1.129 2.503-1.371 6.812-1.125 10.938.625 13.75-3.857 12-5.25-3.062-2.437-6.437.375-12.062-.125C3.782 22.881 0 17.472 0 16c0-2 11.716-8 20-8s16 4.25 16 13z"/><path fill="#292F33" d="M15 12.5c0 .829-.671 1.5-1.5 1.5s-1.5-.671-1.5-1.5.671-.5 1.5-.5 1.5-.329 1.5.5z"/><path fill="#66757F" d="M14 9c2-5 5.291-9 7.958-9S21 2 26 10 14 9 14 9zM3 30c0-4-1.04-6 .146-6s6.011 4.031 6.011 6.24c0 2.209-4.826 5.76-6.011 5.76C1.96 36 3 34 3 30z"/><path fill="#292F33" d="M26.921 22.5l7.996 7.5s-3.242 1.833-7.996-7.5z"/><path fill="#66757F" d="M26.921 22.5l5.537-3.833S36.333 28.584 34.917 30c-2.583-1-7.996-7.5-7.996-7.5z"/><path fill="#FFF" d="M9 20.307c0 .493-.508 2.673-1 2.673s-1-2.18-1-2.673v-1.779c0-.493.508.889 1 .889s1-1.382 1-.889v1.779zm3 0c0 .493-.508 2.673-1 2.673s-1-2.18-1-2.673v-1.779c0-.493.508.889 1 .889s1-1.382 1-.889v1.779zm3-1c0 .493-.508 2.673-1 2.673s-1-2.18-1-2.673v-1.779c0-.493.508.889 1 .889s1-1.382 1-.889v1.779zm3 0c0 .493-.508 2.673-1 2.673s-1-2.18-1-2.673v-1.779c0-.493.508.889 1 .889s1-1.382 1-.889v1.779z"/><path fill="#66757F" d="M6 20l7-1h6v-2H6z"/><path fill="#292F33" d="M18.417 19.167c-4-2.083-13.385-.011-14.917 1.513.469.36.988.707 1.547 1.028 6.109-3.281 14.082-2.169 13.37-2.541z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f989.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f989.svg new file mode 100644 index 0000000000000000000000000000000000000000..bb0d461ab47a7663615da4e10f1cdef481c88b8b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f989.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M7.317 11c-5.723 9.083.958 18 .958 18s2.874-.442 6.875-5.2c4-4.758-7.833-12.8-7.833-12.8zm21.342 0c5.723 9.083-.958 18-.958 18s-2.874-.442-6.875-5.2C16.825 19.042 28.659 11 28.659 11z"/><path fill="#FFAC33" d="M15.203 31.557c-.123-.229-.317-.384-.531-.496-2.032-2.172-.589-4.717-.589-4.717 0-.703 1.271-2.544 0-2.544l-1.272 1.272c-1.272 1.271-1.272 5.089-1.272 5.089H8.995c-.703 0-1.272.568-1.272 1.272 0 .701.569 1.271 1.272 1.271h1.408l-.282.153c-.618.334-.848 1.105-.514 1.726.334.616 1.106.848 1.724.514l3.357-1.816c.619-.334.846-1.105.515-1.724zm5.596 0c.123-.229.317-.384.53-.496 2.033-2.172.589-4.717.589-4.717 0-.703-1.271-2.544 0-2.544l1.272 1.272c1.273 1.271 1.273 5.089 1.273 5.089h2.544c.704 0 1.271.568 1.271 1.272 0 .701-.566 1.271-1.271 1.271h-1.408l.281.153c.62.334.848 1.105.515 1.726-.336.616-1.105.848-1.726.514l-3.356-1.816c-.619-.334-.847-1.105-.514-1.724z"/><path fill="#662113" d="M28.278 11.292c2.891-6.092 0-10.542 0-10.542s-5.781.959-6.744 2.875c-1.219 2.424 6.744 7.667 6.744 7.667z"/><path fill="#662113" d="M29.562 12.738c0 10.297-3.152 20.595-11.562 20.595-8.409 0-11.563-10.298-11.563-20.595C6.437 2.44 11.614 2.083 18 2.083c6.387 0 11.562.357 11.562 10.655z"/><path fill="#C1694F" d="M27.666 17.738c0 10.297-7.774 14.595-9.666 14.595s-9.666-4.298-9.666-14.595c0-10.298 19.332-10.298 19.332 0z"/><path fill="#662113" d="M7.722 11.292C4.831 5.2 7.722.75 7.722.75s5.782.959 6.746 2.875c1.218 2.424-6.746 7.667-6.746 7.667z"/><path fill="#C1694F" d="M14.929 4.373C10.702 2.789 7.722.75 7.722.75s-2.076 3.221-.928 7.926c.446 2.137 1.94 4.195 3.904 4.662 2.637.627 7.302-.049 7.302-3.963 0-2.695-1.074-4.252-3.071-5.002zm6.142 0C25.298 2.789 28.277.75 28.277.75s2.076 3.221.928 7.926c-.445 2.137-1.939 4.195-3.902 4.662-2.638.627-7.303-.049-7.303-3.963 0-2.695 1.074-4.252 3.071-5.002z"/><path fill="#FFD983" d="M16.083 8.417c0 2.117-1.716 3.833-3.833 3.833s-3.833-1.716-3.833-3.833 1.717-3.833 3.833-3.833c2.117-.001 3.833 1.716 3.833 3.833zm11.5 0c0 2.117-1.716 3.833-3.833 3.833s-3.833-1.716-3.833-3.833 1.716-3.833 3.833-3.833 3.833 1.716 3.833 3.833z"/><path fill="#292F33" d="M14.167 8.417c0 1.059-.858 1.917-1.917 1.917s-1.917-.858-1.917-1.917c0-1.058.858-1.917 1.917-1.917s1.917.858 1.917 1.917zm11.5 0c0 1.059-.858 1.917-1.917 1.917s-1.917-.858-1.917-1.917c0-1.058.858-1.917 1.917-1.917s1.917.858 1.917 1.917z"/><path fill="#FFCC4D" d="M20.875 12.729c0 2.382-2.875 3.354-2.875 3.354s-2.875-.973-2.875-3.354S18 9.375 18 9.375s2.875.972 2.875 3.354z"/><path fill="#F4900C" d="M20.875 12.729c0 2.382-2.875 3.354-2.875 3.354s-2.875-.973-2.875-3.354C16.323 13.927 18 14.167 18 14.167s1.677-.24 2.875-1.438z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f98a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f98a.svg new file mode 100644 index 0000000000000000000000000000000000000000..2cb2f986dfa21715732614fd07afbd27caf0479f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f98a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M13.431 9.802c.658 2.638-8.673 10.489-11.244 4.098C.696 10.197-.606 2.434.874 2.065c1.48-.368 11.9 5.098 12.557 7.737z"/><path fill="#A0041E" d="M11.437 10.355c.96 1.538-1.831 4.561-3.368 5.522-1.538.961-2.899-.552-4.414-4.414-.662-1.689-1.666-6.27-1.103-6.622.562-.351 7.924 3.976 8.885 5.514z"/><path fill="#F4900C" d="M22.557 9.802C21.9 12.441 31.23 20.291 33.802 13.9c1.49-3.703 2.792-11.466 1.312-11.835-1.48-.368-11.899 5.098-12.557 7.737z"/><path fill="#A0041E" d="M24.552 10.355c-.96 1.538 1.831 4.561 3.368 5.522 1.537.961 2.898-.552 4.413-4.414.662-1.688 1.666-6.269 1.104-6.621-.563-.352-7.924 3.975-8.885 5.513z"/><path fill="#F18F26" d="M32.347 26.912c0-.454-.188-1.091-.407-1.687.585.028 1.519.191 2.77.817-.008-.536-.118-.984-.273-1.393.041.02.075.034.116.055-1.103-3.31-3.309-5.517-3.309-5.517h2.206c-2.331-4.663-4.965-8.015-8.075-9.559-1.39-.873-3.688-1.338-7.373-1.339h-.003c-3.695 0-5.996.468-7.385 1.346-3.104 1.547-5.734 4.896-8.061 9.552H4.76s-2.207 2.206-3.311 5.517c.03-.015.055-.025.084-.04-.201.392-.307.847-.282 1.377 1.263-.632 2.217-.792 2.813-.818-.189.513-.343 1.044-.386 1.475-.123.371-.191.812-.135 1.343C6.75 26.584 8.25 26.792 10 27.667 11.213 31.29 14.206 34 18.001 34c3.793 0 6.746-2.794 7.958-6.416 1.458-1.25 3.708-.875 6.416.416.066-.414.036-.773-.036-1.093l.008.005z"/><path fill="#FFD983" d="M31.243 23.601c.006 0 1.108.003 3.309 1.103-1.249-2.839-7.525-4.07-9.931-3.291-1.171 1.954-1.281 5.003-3.383 6.622-1.741 1.431-4.713 1.458-6.479 0-2.345-1.924-2.559-5.813-3.382-6.622-2.407-.781-8.681.454-9.931 3.291 2.201-1.101 3.304-1.103 3.309-1.103 0 .001-1.103 2.208-1.103 3.311l.001-.001v.001c2.398-1.573 5.116-2.271 7.429-.452 1.666 7.921 12.293 7.545 13.833 0 2.314-1.818 5.03-1.122 7.429.452v-.001l.001.001c.002-1.103-1.101-3.311-1.102-3.311z"/><path fill="#272B2B" d="M11 17s0-1.5 1.5-1.5S14 17 14 17v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V17zm11 0s0-1.5 1.5-1.5S25 17 25 17v1.5s0 1.5-1.5 1.5-1.5-1.5-1.5-1.5V17zm-7.061 10.808c-1.021.208 2.041 3.968 3.062 3.968 1.02 0 4.082-3.76 3.062-3.968-1.021-.208-5.103-.208-6.124 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f98b.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f98b.svg new file mode 100644 index 0000000000000000000000000000000000000000..22c6ead8ffcf699eb11c15dfacab1af42802ed64 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f98b.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#1C6399" d="M20.004 20.243c-.426 0-.858.01-1.294.031-.436 1.268-.468 2.747 0 5.097.328 1.646 2.659 6.299 4.584 7.933.683.58 1.638.884 2.69.884 2.144 0 4.691-1.265 6.157-4.034 3.001-5.671-3.474-9.911-12.137-9.911z"/><path fill="#1C6399" d="M33.666 1.973c-.204 0-.425.021-.663.066-3.182.601-9.302 5.126-14.287 11.771 0 0-.789 5.16-.789 6.194 0 .336 1.264.5 3.058.5 3.717 0 9.709-.705 11.424-2.041 1.898-1.479 3.65-9.804 3.488-14.079-.046-1.175-.662-2.411-2.231-2.411z"/><path fill="#55ACEE" d="M27.098 13.936l6.629-.436s-1.055 3.619-3.102 4.656-7.719 1.5-7.719 1.5 2.33-4.261 3.286-5.29c.237-.256.559-.408.906-.43zm.52-1.952l7.526-8.151s.002 5.365-1.206 8.635c0 0-5.383.379-5.914.391-.703.016-.969-.265-.406-.875zm-6.068 7.672l5.5-8.547c.188-.22.253-.52.171-.798l-.968-3.233-6.722 6.609-.844 6.031 2.863-.062zM27.862 8.88c.172.406.516.5.938.125s6.074-6.094 6-6.218c0 0-2.832-1.194-7.8 3.463 0 0 .69 2.224.862 2.63zm-8.925 12.099l5.373 5.228c.203.178.255.473.125.709L22.06 31.25s-4.187-5.479-3.123-10.271zm7.282 6.301l5.549.741s-1.058 3.845-3.394 4.854c-3.906 1.688-5.312-.625-5.312-.625l2.352-4.562c.151-.298.477-.463.805-.408zm-5.95-6.426l5.375 4.958c.077.066.169.11.269.129l6.119.903s-1.219-3.031-4.429-4.531c-3.71-1.733-7.334-1.459-7.334-1.459z"/><path fill="#292F33" d="M20.004 20.243c-.426 0-.858.01-1.294.031-.436 1.268-.468 2.747 0 5.097.328 1.646 2.659 6.299 4.584 7.933.683.58 1.638.884 2.69.884 2.144 0 4.691-1.265 6.157-4.034 3.001-5.671-3.474-9.911-12.137-9.911zm10.537 9.326c-1.316 2.486-3.05 3.473-4.558 3.473-.767 0-1.704-.313-2.15-.691-1.695-1.439-3.437-4.58-4.25-7.224-.465-1.513-.354-4.022-.354-4.022l.667-.021c5.168 0 9.249 2.058 10.726 4.512.714 1.186.687 2.523-.081 3.973z"/><path fill="#292F33" d="M33.666 3.223c.231 0 .935 0 .981 1.208.102 2.681-.594 6.061-1.397 8.882-.541 1.901-1.586 3.292-2.094 3.687-.56.436-1.863 1.238-3.719 1.563-2.03.355-4.207.833-6.456.833-.827 0-1.433.019-1.794-.021.131-1.218.489-3.551.717-5.064 3.768-4.94 9.711-10.361 13.331-11.044.155-.029.3-.044.431-.044m0-1.25c-.204 0-.425.021-.663.066-3.182.601-9.302 5.126-14.287 11.771 0 0-.789 5.16-.789 6.194 0 .336 1.264.5 3.058.5 3.717 0 9.709-.705 11.424-2.041 1.898-1.479 3.65-9.804 3.488-14.079-.046-1.175-.662-2.411-2.231-2.411z"/><path fill="#1C6399" d="M3.902 30.154c1.466 2.769 4.012 4.034 6.157 4.034 1.052 0 2.007-.304 2.69-.884 1.925-1.633 4.256-6.286 4.584-7.933.468-2.35.436-3.828 0-5.097-.436-.021-.868-.031-1.294-.031-8.665 0-15.139 4.24-12.137 9.911z"/><path fill="#1C6399" d="M2.376 1.973C.807 1.973.19 3.209.146 4.383c-.162 4.275 1.59 12.601 3.488 14.079 1.715 1.336 7.706 2.041 11.424 2.041 1.794 0 3.058-.164 3.058-.5 0-1.033-.789-6.194-.789-6.194C12.341 7.165 6.22 2.64 3.039 2.039c-.238-.045-.459-.066-.663-.066z"/><path fill="#55ACEE" d="M8.943 13.936L2.315 13.5s1.055 3.619 3.102 4.656 7.719 1.5 7.719 1.5-2.33-4.261-3.286-5.29c-.237-.256-.559-.408-.907-.43zm-.519-1.952L.898 3.833s-.002 5.365 1.206 8.635c0 0 5.383.379 5.914.391.703.016.969-.265.406-.875zm6.068 7.672l-5.5-8.547c-.188-.22-.253-.52-.171-.798l.968-3.233 6.722 6.609.844 6.031-2.863-.062zM8.179 8.88c-.172.406-.516.5-.938.125s-6.074-6.094-6-6.218c0 0 2.832-1.194 7.8 3.463.001 0-.69 2.224-.862 2.63zm8.926 12.099l-5.373 5.228c-.203.178-.255.473-.125.709l2.375 4.333c-.001.001 4.187-5.478 3.123-10.27zM9.822 27.28l-5.549.741s1.058 3.845 3.394 4.854c3.906 1.688 5.312-.625 5.312-.625l-2.352-4.562c-.15-.298-.476-.463-.805-.408zm5.951-6.426l-5.375 4.958c-.077.066-.169.11-.269.129l-6.119.903s1.219-3.031 4.429-4.531c3.709-1.733 7.334-1.459 7.334-1.459z"/><path fill="#292F33" d="M3.902 30.154c1.466 2.769 4.012 4.034 6.157 4.034 1.052 0 2.007-.304 2.69-.884 1.925-1.633 4.256-6.286 4.584-7.933.468-2.35.436-3.828 0-5.097-.436-.021-.868-.031-1.294-.031-8.665 0-15.139 4.24-12.137 9.911zm1.518-4.559c1.477-2.454 5.558-4.512 10.726-4.512l.667.021s.111 2.51-.354 4.022c-.813 2.644-2.555 5.785-4.25 7.224-.446.379-1.383.691-2.15.691-1.508 0-3.242-.986-4.558-3.473-.768-1.449-.795-2.786-.081-3.973z"/><path fill="#292F33" d="M2.376 3.223c.131 0 .276.015.431.044 3.619.683 9.563 6.104 13.331 11.044.228 1.513.586 3.846.717 5.064-.361.04-.967.021-1.794.021-2.249 0-4.426-.478-6.456-.833-1.856-.325-3.159-1.127-3.719-1.563-.508-.396-1.553-1.786-2.094-3.687-.803-2.821-1.499-6.201-1.397-8.882.046-1.208.749-1.208.981-1.208m0-1.25C.807 1.973.19 3.209.146 4.383c-.162 4.275 1.59 12.601 3.488 14.079 1.715 1.336 7.706 2.041 11.424 2.041 1.794 0 3.058-.164 3.058-.5 0-1.033-.789-6.194-.789-6.194C12.341 7.165 6.22 2.64 3.039 2.039c-.238-.045-.459-.066-.663-.066z"/><path fill="#292F33" d="M21.887 4.762c-.25-.138-.563-.047-.701.203l-2.74 4.98c-.018.033-.022.068-.032.102-.127-.007-.244-.018-.393-.018-.148 0-.266.01-.392.018-.01-.034-.014-.069-.032-.102l-2.74-4.98c-.138-.25-.452-.341-.702-.203-.25.137-.341.451-.203.701l2.655 4.826c-1.179.784 1.15 3.438.381 9.204-1.033 7.75 1.033 9.817 1.033 9.817s2.067-2.067 1.033-9.817c-.769-5.766 1.56-8.42.381-9.204l2.656-4.826c.137-.25.046-.564-.204-.701z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f98c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f98c.svg new file mode 100644 index 0000000000000000000000000000000000000000..86623680c24320678a99e0fbe4cc093a72b70186 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f98c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M15.971 15.083c-1.458-2.333-.667-7.708 0-8.958s-.542-2.458-1.5-.458-.996 3-3.162 2.458-1.088-3.292-.379-5.625c.729-2.4-.917-1.959-1.667-.458-.75 1.5-1.254 5.693-2.901 5.984-1.647.291-6.099.599-2.851-5.651C4.818-.139 2.773-.656 1.68 1.459.361 4.007-.404 7.25.221 8.625c1.113 2.448 3.483 2.95 6.983 2.284s6.101-.634 6.101 1.133c0 1.872.208 3.458 1.042 3.625s1.624-.584 1.624-.584zm4.057 0c1.458-2.333.667-7.708 0-8.958s.542-2.458 1.5-.458.996 3 3.162 2.458 1.088-3.292.379-5.625c-.729-2.4.917-1.959 1.667-.458s1.254 5.693 2.901 5.984c1.647.292 6.099.599 2.851-5.651-1.307-2.514.737-3.031 1.831-.916 1.318 2.549 2.084 5.792 1.459 7.167-1.113 2.448-3.482 2.95-6.982 2.284s-6.102-.634-6.102 1.133c0 1.872-.208 3.458-1.041 3.625s-1.625-.585-1.625-.585z"/><path fill="#C1694F" d="M13.859 15.495c.596 2.392.16 4.422-2.231 5.017-2.392.596-6.344.559-7.958-1.303-2.294-2.646-2.531-6.391-1.189-6.725 1.34-.334 10.783.62 11.378 3.011zm8.283 0c-.596 2.392-.16 4.422 2.231 5.017 2.392.596 6.345.559 7.958-1.303 2.295-2.646 2.531-6.391 1.189-6.725-1.34-.334-10.783.62-11.378 3.011z"/><path fill="#272B2B" d="M2.48 12.484c-.943.235-1.102 2.157-.317 4.198l3.374-4.134c-1.457-.146-2.643-.167-3.057-.064zm31.041 0c-.419-.104-1.632-.083-3.118.069l3.445 4.106c.774-2.032.613-3.941-.327-4.175z"/><path fill="#E6AAAA" d="M12.052 15.997c.871 1.393-.553 2.229-1.946 3.099-1.394.871-4.608-.203-5.479-1.596-.871-1.394-1.186-3.131-.676-3.45.51-.318 7.23.553 8.101 1.947zm11.896 0c-.871 1.393.553 2.229 1.945 3.099 1.394.871 4.608-.203 5.479-1.596.871-1.394 1.185-3.131.676-3.45-.51-.318-7.229.553-8.1 1.947z"/><path fill="#C1694F" d="M18 14.125h-.002c-10.271.001-8.703 3.959-7.603 10.541 1.1 6.584 2.401 11.256 7.605 11.256 5.203 0 6.502-4.672 7.604-11.256 1.099-6.582 2.666-10.54-7.604-10.541z"/><path fill="#272B2B" d="M11.826 22.851s-.75-1.299.549-2.049 2.049.549 2.049.549l.75 1.299s.75 1.299-.549 2.049-2.049-.549-2.049-.549l-.75-1.299zm9.75-1.5s.75-1.299 2.049-.549.549 2.049.549 2.049l-.75 1.299s-.75 1.299-2.049.549-.549-2.049-.549-2.049l.75-1.299zm-6.35 12.915c-.925-.188 1.85-3.596 2.774-3.596s3.699 3.407 2.774 3.596c-.924.188-4.624.188-5.548 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f98e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f98e.svg new file mode 100644 index 0000000000000000000000000000000000000000..1164a73b64f12a20e92aaa4198009ac0fbf9032b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f98e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M15.66 6.844c.485-2.03.384-3.139-.553-3.677-.936-.537.337-2.666 1.977-.793 1.641 1.873 1.428 3.618.662 4.853-.767 1.234-2.336.66-2.086-.383zm-.48 2.951c-.916 1.877-1.699 2.668-2.764 2.487-1.064-.18-1.435 2.272 1.023 1.869 2.457-.403 3.401-1.886 3.595-3.326.193-1.44-1.383-1.994-1.854-1.03zm11.336 6.261c-2.072-1.377-5.382 1.43-5.699 2.28-.317.85 1.721 3.461 1.146 4.94-.577 1.477 1.142 1.768 1.92.491.778-1.278.304-3.612.156-4.169-.148-.557 2.189-1.219 3.671-.037 1.481 1.18-.323-2.925-1.194-3.505zm1.068-.818c-1.546-1.949.975-5.482 1.794-5.87.821-.387 2.572.402 3.997-.295 1.424-.697 1.745.854.65 1.874-1.227 1.142-2.241 1.335-3.119 1.526-.563.122-.032 2.033-.009 3.97.023 1.799-2.663-.385-3.313-1.205z"/><path fill="#3E721D" d="M15.319 3.167c0 .4-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.399.324-.724.724-.724.4 0 .724.325.724.724zm-2.999 8.897c0 .399-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.399.324-.724.724-.724.4 0 .724.324.724.724zm-.298 1.677c0 .4-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.399.324-.724.724-.724.4 0 .724.324.724.724zm1.447.724c0 .399-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.4.324-.724.724-.724.4 0 .724.324.724.724zm8.575 8.848c.128.378-.073.791-.452.92-.377.129-.789-.075-.918-.453s.072-.79.45-.919c.379-.129.791.074.92.452zm.772 1.268c.128.378-.073.79-.452.919-.377.128-.789-.074-.918-.452-.129-.377.073-.79.451-.918.379-.13.791.073.919.451zm1.627-.24c.13.377-.073.79-.452.919-.376.129-.788-.074-.917-.451-.129-.378.073-.791.45-.919.379-.13.791.073.919.451zm9.803-15.752c0 .399-.325.724-.725.724s-.724-.325-.724-.724c0-.399.324-.725.724-.725s.725.326.725.725zm1.504.725c0 .399-.324.724-.725.724-.398 0-.723-.325-.723-.724s.324-.724.723-.724c.401-.001.725.325.725.724zm-.346 1.716c0 .399-.324.724-.725.724-.399 0-.724-.325-.724-.724 0-.399.324-.724.724-.724.401 0 .725.325.725.724zM15.512 1.618c0 .399-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.4.324-.724.724-.724.4 0 .724.324.724.724zm1.571-.469c0 .4-.324.724-.724.724-.399 0-.724-.324-.724-.724 0-.399.324-.724.724-.724.4.001.724.325.724.724z"/><path fill="#3E721D" d="M.208 5.652C.472 4.599 4.865.929 8.85 1.618c2.024.351 2.942 3.354 5.102 3.428 11.289.389 22.272 11.138 18.847 21.391-1.506 4.507-5.618 8.798-15.461 5.001-1.956-.754-3.97-1.985-7.824-1.227-2.852.563-3.149 3.159-2.803 4.497.272 1.048-.161 1.582-.701.759-1.226-1.867-1.317-4.347.643-5.955 3.912-3.211 9.248-1.284 13.137-.059 6.481 2.044 9.917-3.651 6.346-10.315-3.503-6.54-9.812-8.324-14.005-8.816-1.168-.137-3.639 2.048-5.367 1.742C3.143 11.421.018 6.416.208 5.652z"/><path fill="#77B255" d="M.208 5.652C.472 4.599 4.865.929 8.85 1.618c2.024.351 2.942 3.354 5.102 3.428 11.289.389 22.272 11.138 18.847 21.391-1.506 4.507-5.618 8.798-15.461 5.001-1.956-.754-3.97-1.985-7.824-1.227-2.852.563-3.149 3.159-2.803 4.497.134.516.097.906-.039 1.073-.922-1.281-1.362-4.339.661-5.864 3.539-2.667 8.568-.131 13.301 1.042 10.251 2.541 12.183-7.995 7.907-14.875C23.355 7.736 7 5.75.208 5.652z"/><circle fill="#292F33" cx="7" cy="3" r="1"/><circle fill="#292F33" cx="6" cy="10" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f98f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f98f.svg new file mode 100644 index 0000000000000000000000000000000000000000..0d07017ab4fdc1b6b73e6e65ed2abe78e36d22b6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f98f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M27.295 7.526c-1.152-3.054-2.65-6.8-8.299-6.915-1.759-.036-1.52.539-.347 1.02 2.248.922-2.474 5.438 4.759 7.4 5.648 1.531 5.039 1.549 3.887-1.505z"/><path fill="#99AAB5" d="M36.004 3.903c-7.737 0-14.411 2.514-18.105 5.757-4.875 4.28-5.38 10.306-14.034 15.66-2.847 1.761-.423 7.517 1.153 9.618 1.908 2.544 28.617.238 30.987-8.777l-.001-22.258z"/><path fill="#66757F" d="M8.676 29.652c1.011.507 1.787 1.051 1.318 1.986-.469.936-1.173.25-2.185-.257-1.012-.508-2.285-.018-1.816-.954.47-.935 1.672-1.281 2.683-.775zM34.202 6.326c.238-2.563-2.178-4.999-5.95-5.906-1.685-.406-3.281-.35-2.345.478 1.793 1.585-.082 4.006 1.274 7.124.728 1.674 3.238 3.753 4.719 3.82 1.056.048 2.054-2.847 2.302-5.516z"/><path fill="#99AAB5" d="M33.247 6.326c.238-2.563-2.272-5.445-6.17-6.007-1.715-.247-2.287.087-1.351.914 1.793 1.585-.638 3.627.718 6.745.728 1.674 3.393 3.84 4.875 3.907 1.055.049 1.68-2.89 1.928-5.559z"/><path fill="#CCD6DD" d="M2.639 26.898C.087 22.915-.988 14.927 1.147 9.301c.321-.845 1.083-1.071 1.179.13.181 2.282 2.417 6.833 7.966 10.968 1.241.924-5.713 9.527-7.653 6.499z"/><path fill="#CCD6DD" d="M13.248 15.387c-2.048-.852-3.609-3.189-4.092-4.661-.577-1.758-2.152 3.927.852 8.892 1.207 1.993 4.653-3.644 3.24-4.231z"/><circle fill="#292F33" cx="16.789" cy="21.006" r="2"/><path fill="#E6AAAA" d="M30.293 9.41c1.331.105 1.954-1.737 1.216-4.69-.644-2.576-4.252-3.248-4.227-3.069.025.179 1.057 1.549.014 2.939-1.014 1.352 1.347 4.69 2.997 4.82z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f992.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f992.svg new file mode 100644 index 0000000000000000000000000000000000000000..233e3c989dc0e524d76d2aa113d1ff178042b80a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f992.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path d="M22.217 35.615h-.002c-.804-.142-1.34-.908-1.198-1.712l.59-3.344s.68-3.165-1.076-5.449c1.259-1.171 5.024.085 5.024.085l-1.626 9.221c-.142.804-.908 1.34-1.712 1.199zm-12.692-.021h-.002c-.804-.142-1.34-.908-1.198-1.712l1.312-7.025s.503-2.419.503-4.439c1.142-.439 2.723 2.757 2.723 2.757l-1.626 9.221c-.143.803-.909 1.339-1.712 1.198zm21.277-9.823c-.537 0-.977-.431-.985-.969-.012-.723-.304-4.326-4.925-4.326-.545 0-.985-.441-.985-.985s.441-.985.985-.985c5.363 0 6.858 3.938 6.896 6.264.009.545-.425.993-.969 1.002l-.017-.001z" fill="#F4900C"/><g fill="#754C29"><path d="M15.226 17.252l-3.46-11.98 1.687-1.02c.369.61.628 1.722 1.054 3.633.569 2.558 1.349 6.06 2.657 7.876.318.442.218 1.058-.224 1.376-.175.126-1.714.115-1.714.115zM7.615 2.71V.739c0-.408.331-.739.739-.739s.739.331.739.739V2.71H7.615zm2.332 0V.739c0-.408.331-.739.739-.739s.739.331.739.739V2.71H9.947z"/><ellipse cx="30.802" cy="26.263" rx="1.971" ry="2.464"/></g><path fill="#FFCC4D" d="M28.935 34.094s-.647-2.515-.998-4.154c-.332-1.549-1.025-3.981-1.171-8.225-.01-.145-.039-.512-.138-.779-.122-.33-.567-.933-.766-1.203-.777-1.052-2.012-1.691-3.526-1.847-1.283-.132-2.573-.185-3.854-.339-.59-.071-1.1-.156-1.422-.272-1.636-.589-1.962-2.502-2.414-3.965-.8-2.59-1.508-5.225-1.961-7.9l-.036.009.036-.009-.027-.165V4.84c1.567-.714 2.79-2.888 1.971-3.706-1.416-.708-2.827.11-3.513.992-.02-.001-.039-.006-.059-.006H8.459c-.655 0-1.304.16-1.872.51-.584.359-.986.907-1.633 1.19-.786.344-1.721.093-2.417.64-1.189.933-.625 2.525.854 2.578.201.577.745.993 1.39.993h2.106c.055.011.108.021.173.029.604.071 1.088.525 1.477 1.215 1.047 1.856 1.244 4.244 1.415 6.324.119 1.448.177 2.906.158 4.36-.293 1.566-.12 3.377-.12 3.377.044.419.186.777.394 1.095l-.01.011c1.99 2.81 2.449 5.97 2.449 5.97l.784 4.193c.142.804.908 1.341 1.713 1.199.804-.142 1.341-.908 1.199-1.712l-1.262-7.159c1.977.534 4.609.932 6.449.852 0 .006-.003.014-.002.02 2.371-.146 3.26 1.73 3.454 2.576.194.846.868 4.228.868 4.228.142.804.909 1.341 1.712 1.199.802-.143 1.339-.91 1.197-1.714z"/><path fill="#F4900C" d="M11.975 22.1c-.985.985-1.16 2.408-.391 3.178.77.77 2.193.595 3.178-.391s1.16-2.408.391-3.178c-.77-.77-2.193-.595-3.178.391zm1.088-6.185c0 1.633 1.324 2.956 2.956 2.956 1.029 0 1.933-.526 2.462-1.323-.59-.071-1.1-.156-1.422-.272-1.564-.563-1.872-2.237-2.253-3.441-.057-.179-.108-.349-.162-.523-.935.496-1.581 1.469-1.581 2.603zm-.986-4.434c0-1.361-1.103-2.464-2.464-2.464-.388 0-.75.098-1.077.257.635 1.126 1.015 2.885 1.242 4.653 1.282-.086 2.299-1.142 2.299-2.446zm-1.093-4.079c0 1.118.906 2.023 2.023 2.023.182 0 .355-.032.523-.077-.449-1.787-.709-3.122-.847-3.937-.961.156-1.699.985-1.699 1.991zm8.977 12.456c0 1.633 1.324 2.956 2.956 2.956 1.633 0 2.956-1.324 2.956-2.956 0-.043-.011-.082-.013-.124-.777-1.052-2.012-1.691-3.526-1.847-.457-.047-.972-.088-1.499-.128-.538.536-.874 1.277-.874 2.099zM11.598 2.613c.505-.483 1.317-1.089 1.778-.856.461.233.258 1.273-1.166 2.151.113-.439.551-1.215-.612-1.295z"/><circle fill="#292F33" cx="8.772" cy="4.09" r=".985"/><path d="M21.047 33.545s-1.142 1.351-.985 1.781 2.741.491 3.249.022-1.951-1.842-2.264-1.803zm-12.623 0s-1.142 1.351-.985 1.781c.156.43 2.741.491 3.249.022s-1.951-1.842-2.264-1.803zm4.547 2.22c.136.391 2.766.329 3.205-.461.439-.79-2.678-1.317-2.678-1.317s-.703 1.273-.527 1.778zm12.404 0c.136.391 2.766.329 3.205-.461.439-.79-2.678-1.317-2.678-1.317s-.703 1.273-.527 1.778z" fill="#754C29"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f993.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f993.svg new file mode 100644 index 0000000000000000000000000000000000000000..2cb4b9eb2e8bc4f516b002854d43dfa756046ae5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f993.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M23.283 23.275s1.374 1.635 2.733 10.047c.143.883.201 1.775.217 2.678H36V7.448C31.613 3.975 25.601 3.259 18.322 5.69c0 0-5.408-3-6.147-3.739-.719-.72-1.857-1.556-1.235.35.364 1.112.764 2.373 2.358 4.862-3.436 2.036-4.513 4.68-8.558 13.341C1.652 27.12.08 29.269.937 31.797c1.13 3.337 5.316 5.595 8.844 3.021 1.919-1.4 2.246-3.913 6.225-6.223 3.653-.065 7.277-1.604 7.277-5.32z"/><path fill="#292F33" d="M36 6.012C27.665.301 14.354 1.473 15.909 6.19 25.51 4.328 31.77 7.731 36 13.358V6.012z"/><path fill="#292F33" d="M19.663 5.763c-2.878.233-7.28 1.765-9.42 4.137 0 0-.005-5.317 3.689-5.784 6.172-.779 5.809.363 5.809.363l-.078 1.284z"/><path fill="#E1E8ED" d="M16.357 1.056c.558 1.155 4.006 1.79 5.056 6.029 1.051 4.24-3.134 2.951-4.356.855-1.361-2.334-1.828-4.162-1.867-5.679-.021-.801.039-3.538 1.167-1.205z"/><path fill="#66757F" d="M16.596 2.838c1.103.968 2.448 2.472 2.65 3.955.202 1.483-1.125.988-1.736-.372-.612-1.359-.753-2.779-1.134-3.233-.38-.454.22-.35.22-.35z"/><path fill="#292F33" d="M16.94 15.525c0 .687-.557 1.244-1.245 1.244-.687 0-1.244-.557-1.244-1.244 0-.688.557-1.245 1.244-1.245.688.001 1.245.558 1.245 1.245z"/><path fill="#E1E8ED" d="M10.354 9.924c-.033-.017-.075-.014-.111-.024-1.543 2.033-2.92 5.102-5.49 10.604-1.356 2.903-2.42 4.946-3.116 6.538 1.628.226 3.285-1.442 3.945-3.271.673-1.866 3.215-5.652 4.927-7.778 1.712-2.127 1.561-5.144-.155-6.069z"/><path fill="#292F33" d="M28.188 6.312s-2.296 6.947-2.302 8.947c-.011 3.803-2.687 7.801-2.687 7.801l1.342 3.422s3.25-3.04 3.938-10.228c.571-5.973 2.566-7.667 2.566-7.667l-2.857-2.275zm5.874 3.126S31.056 13.073 30 19c-1.438 8.062-4.857 9.746-4.857 9.746l.482 2.441s5.281-3.056 6.632-9.115C33.875 14.812 36 13.358 36 13.358l-1.938-3.92zm-30.812 14c.688-.714 3.017 3.808 4.53 4.884 1.589 1.13 5.469.935 5.701 2.162-1.668 1.704-2.763 4.273-4.84 4.988-2.078.716-5.71.677-7.238-2.647-1.528-3.325-.403-4.7.222-6.137s1.458-2.938 1.625-3.25z"/><path fill="#66757F" d="M4.222 29.917c0 .881-.532 1.594-1.187 1.594s-1.187-.713-1.187-1.594c0-.882.532-1.596 1.187-1.596s1.187.714 1.187 1.596z"/><path fill="#292F33" d="M25.954 32.945s4.608-1.57 6.108-3.383S36 24 36 24v6.375S34.812 32 32.312 33.313c-1.586.832-6.092 2.251-6.092 2.251l-.266-2.619zM25.01 6.08S24.063 9 23.813 12s-1.125 4.875-1.938 6.188c.312-4.25-.688-5.875-.125-8.125s.87-4.32.87-4.32.63-.368 1.255-.305 1.135.642 1.135.642zM4.753 20.504s3.934-.379 5.747.871 5.332 7.323 5.332 7.323l-1.134.753s-1.697-4.639-4.76-6.076-6-1.188-6-1.188l.815-1.683z"/><path fill="#292F33" d="M5.605 18.678s5.516-.358 6.958 1.509c2.75 3.562 3.831 5.01 4.447 8.349l1.785-.307c-.794-2.917-2.607-8.104-5.919-10.292s-6.25-1.688-6.25-1.688l-1.021 2.429zm12.27-5.99c-.625.688 2 3.312 1.125 5.5s-.375 5.25.125 6.625 1.26 2.839 1.26 2.839l1.622-1.146S21.75 25 21 22.813s-.688-2.25-.375-4.438S18.5 12 17.875 12.688zm-2.83-5.859s1.142 2.046 1.08 3.046-.062 2.688-.625 3.062-.812-2-1.188-3.062-1.064-2.258-1.064-2.258 1.469-1.428 1.797-.788zm-3.544 1.79s1.793 1.398 1.73 2.398 1.144 2.607.581 2.982-1.938-1.25-2.312-2.312S10.243 9.9 10.243 9.9s.929-1.921 1.258-1.281zm-2.563 3.193s1.522.981 1.938 1.75c.415.768 2.11 1.387 1.938 1.875-.173.488-1.977-.098-2.688-.75-.711-.652-2.345-.579-2.345-.579l1.157-2.296z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f994.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f994.svg new file mode 100644 index 0000000000000000000000000000000000000000..ebbfc2ad25cd8a381282ca695daeabca1e9ebaad --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f994.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#6D6E71" d="M28.688 20.312C28.688 26.217 23.904 31 18 31c-5.903 0-10.688-4.783-10.688-10.688 0-5.903 4.786-10.689 10.688-10.689 5.904.001 10.688 4.786 10.688 10.689z"/><path fill="#662113" d="M26 33.5H10c-1.665 0-2.479-1.339-2.763-2.31l-2.664-.056c-.153-.003-.297-.077-.389-.2-.092-.122-.123-.281-.083-.43l.594-2.216-2.446-.651c-.152-.041-.276-.15-.335-.296s-.046-.311.035-.445l1.199-1.993-2.156-1.192c-.139-.077-.233-.216-.254-.374-.02-.157.036-.315.151-.426l1.729-1.647-1.729-1.646c-.115-.11-.171-.268-.151-.426.021-.158.115-.297.254-.374l2.156-1.194-1.2-1.994c-.081-.135-.094-.3-.035-.445.059-.146.183-.255.335-.296l2.446-.65-.594-2.218c-.04-.148-.009-.307.083-.43s.236-.196.39-.2l2.575-.053.058-2.302c.004-.149.074-.289.192-.381.118-.092.271-.127.416-.094l2.521.561.717-2.234c.045-.139.148-.251.282-.308.136-.056.288-.051.417.014l2.284 1.139 1.341-2.009c.08-.119.208-.199.35-.218.145-.019.287.024.394.119L18 7.258l1.88-1.636c.109-.094.251-.137.395-.118.143.019.269.099.35.218l1.34 2.009 2.286-1.139c.13-.065.283-.069.417-.014.135.057.237.169.282.308l.716 2.234 2.521-.561c.146-.032.298.002.416.094s.188.232.192.381l.058 2.302 2.574.053c.153.003.297.077.389.2.093.123.123.282.083.43l-.595 2.217 2.449.65c.152.04.276.15.336.296.059.146.046.311-.035.445l-1.201 1.994 2.155 1.194c.14.077.233.216.254.374s-.036.316-.151.426l-1.729 1.646 1.729 1.647c.115.11.172.269.151.426-.021.158-.114.297-.254.374L32.854 24.9l1.2 1.993c.081.135.094.3.035.445-.06.146-.184.255-.335.296l-2.45.651.595 2.216c.04.148.01.307-.082.43-.093.123-.236.197-.39.2l-2.663.056c-.285.974-1.099 2.313-2.764 2.313z"/><path fill="#8A4B38" d="M16.188 28.824c-.022 0-.044-.001-.066-.004-.143-.019-.27-.099-.35-.219l-1.058-1.585-1.805.899c-.131.064-.283.07-.418.014-.134-.057-.237-.169-.282-.309l-.564-1.757-1.99.442c-.148.031-.299-.003-.417-.095s-.188-.231-.192-.381l-.045-1.804-2.029-.043c-.153-.003-.297-.077-.389-.2-.092-.122-.123-.281-.083-.43l.464-1.732-1.92-.51c-.152-.041-.276-.15-.335-.296s-.046-.311.035-.445l.937-1.557-1.688-.934c-.14-.077-.234-.216-.254-.374-.02-.158.036-.316.151-.426l1.352-1.289-1.352-1.287c-.115-.11-.171-.268-.151-.426.021-.158.115-.297.254-.374l1.689-.935-.937-1.558c-.081-.135-.094-.3-.035-.445.059-.146.183-.255.335-.296l1.922-.511-.466-1.732c-.04-.148-.009-.307.083-.43s.236-.196.39-.2l2.029-.042.045-1.805c.004-.149.074-.289.192-.381.117-.092.27-.127.416-.094l1.99.442.564-1.756c.045-.139.148-.251.282-.308.136-.055.287-.051.418.014l1.805.899 1.058-1.584c.08-.119.207-.199.35-.218.144-.021.287.024.395.119L18 4.172l1.484-1.291c.109-.095.253-.138.395-.119.143.019.269.099.35.218l1.057 1.583 1.807-.9c.13-.064.283-.069.417-.013.135.057.237.169.282.308l.562 1.756 1.991-.442c.146-.033.3.002.416.094.118.092.188.232.192.382l.045 1.804 2.028.042c.153.003.297.077.389.2.093.123.123.282.083.43l-.465 1.734 1.924.511c.152.041.276.15.336.296.059.146.046.311-.035.445l-.938 1.558 1.689.935c.14.077.233.216.254.374.021.158-.036.316-.151.426l-1.353 1.287 1.353 1.289c.115.11.172.268.151.426-.021.158-.115.296-.254.374l-1.688.934.938 1.557c.081.135.094.3.035.445-.06.145-.184.255-.335.296l-1.925.512.465 1.732c.04.148.01.307-.082.43-.093.123-.236.197-.39.2l-2.028.043-.045 1.804c-.004.149-.074.289-.192.381-.117.092-.271.126-.416.095l-1.991-.442-.562 1.757c-.045.139-.147.252-.282.309-.134.058-.284.053-.417-.014l-1.806-.899-1.058 1.585c-.08.12-.207.199-.35.219-.142.018-.286-.024-.395-.119L18 27.407l-1.483 1.294c-.092.08-.209.123-.329.123z"/><path fill="#8A4B38" d="M13.5 27.052h9c3.521 0 6.5 2.575 6.5 4.5 0 1.65-1.35 2-3 2H10c-1.65 0-3-.35-3-2 0-1.925 2.99-4.5 6.5-4.5z"/><path fill="#D99E82" d="M26.222 22.779c0 4.088-3.68 7.398-8.222 7.398s-8.222-3.31-8.222-7.398c0-4.087 3.68-7.4 8.222-7.4s8.222 3.313 8.222 7.4z"/><path fill="#E6E7E8" d="M21.289 26.479c0 2.043-1.473 3.699-3.289 3.699s-3.289-1.656-3.289-3.699S16.183 22.78 18 22.78s3.289 1.655 3.289 3.699z"/><path fill="#231F20" d="M19.645 27.711c0 .908-.736 1.645-1.645 1.645s-1.645-.736-1.645-1.645c0-.908.736-1.642 1.645-1.642s1.645.734 1.645 1.642zm-4.934-6.166c0 .682-.552 1.234-1.233 1.234s-1.233-.553-1.233-1.234c0-.68.552-1.232 1.233-1.232.681-.001 1.233.552 1.233 1.232zm9.044 0c0 .682-.552 1.234-1.232 1.234-.682 0-1.233-.553-1.233-1.234 0-.68.552-1.232 1.233-1.232.68-.001 1.232.552 1.232 1.232z"/><path fill="#C1694F" d="M11.422 17.846s4.111-1.644 4.933 0C17.178 19.49 18 19.49 18 19.49v-4.934c0 .001-6.578.001-6.578 3.29zm13.155 0s-4.11-1.644-4.933 0C18.822 19.49 18 19.49 18 19.49v-4.934c0 .001 6.577.001 6.577 3.29z"/><path fill="#D99E82" d="M12.245 18.256c0 1.136-.92 2.056-2.055 2.056-1.136 0-2.056-.92-2.056-2.056 0-1.135.92-2.055 2.056-2.055 1.135 0 2.055.92 2.055 2.055zm15.621 0c0 1.136-.92 2.056-2.056 2.056-1.135 0-2.056-.92-2.056-2.056 0-1.135.921-2.055 2.056-2.055 1.136 0 2.056.92 2.056 2.055zM11 35c-2 0-2-4 2-4s4.062 4 2 4h-4zm10 0c-2 0-2-4 2-4s4.062 4 2 4h-4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f995.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f995.svg new file mode 100644 index 0000000000000000000000000000000000000000..fb046c69c7bc84940ed3952e810783935691de0d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f995.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#3E721D" d="M17.68 22s1.937 7.873 1.187 9.373c-2.373 4.746-1.187 4.627 0 4.627h2.373c2.373 0-1.187-14-1.187-14H17.68zM5.255 19.387s-.436 7.993-1.187 9.493C1.695 33.626 1.695 36 2.882 36h2.373c1.186 0 1.187-4.154 1.187-5.34 0-1.187 1.187-8.603 1.187-8.603l-2.374-2.67z"/><path fill="#77B255" d="M12.374 5.251c-2.068.017-4.209-.435-5.523 2.099-1.404 2.709-2.065 8.579.776 9.664 2.479.947 7.933-1.187 13.866 1.187 5.933 2.373 8.306 16.612 13.015 16.63 1.224.005 1.206 1.123.001 1.132-5.914.045-8.509-5.897-9.509-5.897 0 0 1 5.934 0 5.934h-4c-1 0 0-3.081 0-4.268v-1.667s-1.593 1.218-5.936 1.218C11.781 31.284 9 30.066 9 30.066S10 36 9 36H5.255c-1.678 0 .166-4.013 0-5.934-.102-1.182-.51-4.757-1.224-5.933-1.726-2.847-2.763-11.521-1.929-15.285.781-3.526 3.122-6.633 4.675-7.51C8.296.479 9.64-.162 12.968.373c1.775.285 3.591 2.922 2.89 4.274-.421.81-1.94.591-3.484.604z"/><path d="M12.967 2.181c0 .328-.265.593-.593.593-.328 0-.593-.265-.593-.593s.265-.593.593-.593c.328 0 .593.266.593.593z"/><path d="M10.218 18.485c.094.304-.076.626-.38.72-.304.094-.626-.076-.72-.38-.094-.304.076-.626.38-.72.304-.094.626.076.72.38zm3.874 1.248c.134.433-.108.892-.54 1.025-.432.134-.892-.108-1.026-.541-.134-.432.108-.892.541-1.025.432-.133.891.109 1.025.541zm-1.625-1.426c.071.23-.057.474-.288.545-.23.071-.474-.058-.545-.288-.071-.23.058-.474.288-.545.23-.071.474.058.545.288zm2.458-.331c.067.218-.054.448-.272.516-.217.067-.448-.054-.516-.272-.067-.218.054-.448.272-.516.218-.067.449.055.516.272zm2.843.35c.125.402-.101.829-.503.954s-.829-.1-.954-.503c-.125-.402.101-.829.503-.954.403-.125.83.101.954.503zm4.753 1.979c.08.258-.064.531-.322.61-.257.08-.531-.064-.61-.322-.08-.257.064-.531.322-.61.258-.08.531.065.61.322zm-5.854 0c.08.258-.064.531-.322.61-.257.08-.531-.064-.61-.322-.08-.257.064-.531.322-.61.257-.08.531.065.61.322zm4.218-1.306c.08.257-.064.531-.322.61-.257.08-.531-.064-.61-.322s.064-.531.322-.61c.257-.08.531.065.61.322zm-1.501.199c.118.381-.095.785-.476.903s-.785-.095-.903-.476.095-.785.476-.903.785.095.903.476z" fill="#5C913B"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f998.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f998.svg new file mode 100644 index 0000000000000000000000000000000000000000..8a72b40a7af2011e720d936d69a33fa01eecd456 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f998.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BF6952" d="M6.513.886c0 .984.649 3.926 1.153 5.047s-.505.35-1.442-.771-1.657-2.244-1.225-3.435S6.513-.446 6.513.886z"/><path fill="#D99E82" d="M.314 10.699c-.004.961 1.22 2.097 2.883 1.682 1.333-.332 3.234-1.359 3.316-.561.082.798-1.179 3.471-.629 6.276.93 4.74 2.379 8.873 7.201 10.095 0 0 .723 2.775 1.479 3.986.694 1.111 1.029 2.022.45 2.215-.579.193-3.472.386-4.694.579C9.099 35.164 8.906 36 10.256 36H17.2c.707 0 .643-.643.193-1.607s.805-2.643.598-5.332c.414.14 1.395.067 1.974.838.579.772 3.729 5.976 8.809 5.976s6.43-3.826 6.815-4.855c.386-1.029-.45-1.029-1.093-.193s-2.761 1.931-5.722 1.508c-3.151-.45-3.822-4.465-4.658-6.909-.836-2.443-2.74-6.968-7.044-9.487-3.177-1.859-5.483-1.31-5.363-3.356.178-3.033.325-5.21-1.099-6.892-1.15-1.357-3.851-1.264-5.418-.319-.697.42-1.117 1.595-1.778 2.103C1.428 8.998.317 9.848.314 10.699z"/><path fill="#D79E84" d="M6.042 22.625c-.259.531-.006 1.019-.158 1.355-.225.497-1.254.804-1.35-.032-.097-.836-.021-1.948.45-2.572.322-.427 3.279-2.797 3.408-2.893.129-.096-.354-2.893-.354-2.893s.096-1.125 1.447-.868c1.35.257 1.318 1.415 1.318 2.636s.225 2.443-.386 2.733-4.117 2.003-4.375 2.534z"/><path fill="#292F33" d="M6.657 7.405c0 .465-.387.841-.865.841s-.865-.377-.865-.841.387-.561.865-.561.865.096.865.561z"/><path fill="#D99E82" d="M9.973.255c.912-.665 1.009 1.963.793 2.804S8.891 6.073 8.891 6.073s-1.297.631-1.297-.911S9.108.886 9.973.255z"/><path fill="#BF6952" d="M10.062 2.09c.58.346-1.307 3.303-1.766 3.055-.459-.247.988-3.519 1.766-3.055z"/><path fill="#292F33" d="M.314 10.139c.869-.528 1.081.911.793 1.402-.289.49-1.37-1.052-.793-1.402z"/><path fill="#BF6952" d="M7.274 22.34c-.125 0-.244-.073-.297-.195-.071-.164.004-.354.168-.426 1.066-.464 1.99-1.182 2.367-1.533.15-.182.523-1.447.777-2.511.042-.174.219-.278.39-.24.174.042.281.216.24.39-.223.931-.645 2.536-.966 2.835-.546.508-1.546 1.216-2.55 1.652-.042.019-.086.028-.129.028z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f999.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f999.svg new file mode 100644 index 0000000000000000000000000000000000000000..b505faf82d7a76f6e8615e08f0e3abcc38daffed --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f999.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M6.755 2.246c-.443-.368-1.05-.976-1.629-1.299-.497-.277-.247.918.173 1.391.421.473 1.824 1.342 2.455 1.815.631.473.936.398.315-.473-.649-.911-1.314-1.434-1.314-1.434z"/><path fill="#D99E82" d="M8.191.736c.328.339.735 2.394.735 2.394s1.282.092 2.407.786c4.5 2.776 2.542 9.542 3.944 11.102.432.48 9.681-1.643 14.222.544 3.844 1.852 3.083 4.646 4.083 5.271.758.474-2 1.25-2.578-2.313-.506 11.147-1.072 13.867-1.672 16.354-.339 1.406-1.979 1.601-1.792-.333.1-1.027.463-7.223-.583-8.792-.75-1.125-4.708 2.417-11.707 1.773-.485 4.276-1.097 7.136-1.272 7.519-.562 1.229-1.863 1.218-1.676-.009.187-1.228.447-4.949-.884-9.01-5.626-3.98-1.626-14.189-3.253-16.146-.362-.435-2.647-.981-3.314-1.048-.666-.067-1.265-.172-1.664-.239-.4-.067-.994-1.776-.927-2.242s.394-.623 1.26-.956.988-.222.942-.728c-.097-1.052 2.183-1.774 3.481-1.645-.133-.133-1.08-1.786-1.354-2.393-.35-.774 1.068-.442 1.602.111z"/><path fill="#C1694F" d="M2.901 6.241c.068.342-.394.394-.315.69.079.296.536 1.256.95 1.157.414-.099.909-.07.224.259-.522.25-.847.012-.847.012s-.772-1.473-.693-1.894c.08-.419.661-.322.681-.224z"/><path fill="#292F33" d="M7.58 4.805c0 .405-.328.733-.733.733s-.732-.328-.732-.733c0-.405.367-.31.772-.31s.693-.095.693.31zM2.22 6.146c.062-.462 1.54-.335 1.005.138-.335.296-1.104.591-1.005-.138z"/><path fill="#C1694F" d="M7.473.846c.497.129 1.105 2.281.909 2.311-.256.04-1.517-2.468-.909-2.311zm2.472 5.846s1.009 1.324.252 2.269c-.756.946-2.333.63-2.333.63s1.513-.441 1.891-1.198c.379-.755.19-1.701.19-1.701z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f99a.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f99a.svg new file mode 100644 index 0000000000000000000000000000000000000000..7606d382ac63ed6757c822dad909a08216171427 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f99a.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M14.5 36c-.128 0-.256-.049-.354-.146-.195-.195-.195-.512 0-.707L16 33.293V31.5c0-.276.224-.5.5-.5s.5.224.5.5v2.207l-2.146 2.146c-.098.098-.226.147-.354.147z"/><path fill="#292F33" d="M16.5 34h-3c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h3c.276 0 .5.224.5.5s-.224.5-.5.5zm5 2c-.128 0-.256-.049-.354-.146L19 33.707V31.5c0-.276.224-.5.5-.5s.5.224.5.5v1.793l1.854 1.854c.195.195.195.512 0 .707-.098.097-.226.146-.354.146z"/><path fill="#292F33" d="M22.5 34h-3c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h3c.276 0 .5.224.5.5s-.224.5-.5.5z"/><path fill="#A6D388" d="M36 25.909C36 29.727 34.001 31 18 31S0 29.727 0 25.909C0 13.257 8.059 4 18 4s18 9.257 18 21.909z"/><path fill="#77B255" d="M18 29c-.209 0-.404-.133-.474-.342-.087-.262.054-.545.316-.633l16.5-5.5c.263-.086.545.055.633.316.087.262-.055.545-.316.633l-16.5 5.5c-.054.018-.107.026-.159.026zm0-3c-.155 0-.308-.071-.405-.207-.162-.224-.112-.536.111-.698l14.5-10.5c.222-.163.536-.112.698.111s.111.537-.112.698l-14.5 10.5c-.087.065-.19.096-.292.096zm0-4c-.091 0-.183-.024-.266-.077-.233-.146-.304-.456-.157-.689l8.5-13.5c.147-.234.458-.301.689-.157.234.147.304.456.157.69l-8.5 13.5c-.095.15-.257.233-.423.233z"/><circle fill="#55ACEE" cx="32.5" cy="27" r="2"/><circle fill="#55ACEE" cx="32.5" cy="20" r="2"/><circle fill="#55ACEE" cx="28.5" cy="13" r="2"/><circle fill="#55ACEE" cx="21.5" cy="8" r="2"/><circle fill="#55ACEE" cx="28" cy="28.5" r="1.5"/><circle fill="#55ACEE" cx="28" cy="22.5" r="1.5"/><circle fill="#55ACEE" cx="25" cy="16.5" r="1.5"/><circle fill="#55ACEE" cx="24.5" cy="29" r="1"/><circle fill="#55ACEE" cx="24.5" cy="24" r="1"/><circle fill="#55ACEE" cx="21.5" cy="20" r="1"/><path fill="#77B255" d="M17.5 29c-.052 0-.105-.008-.158-.025l-16.5-5.5c-.262-.088-.403-.371-.316-.633s.369-.405.632-.316l16.5 5.5c.262.088.403.371.316.633-.07.208-.265.341-.474.341zm0-3c-.102 0-.204-.031-.293-.095l-14.5-10.5c-.224-.162-.273-.475-.111-.698.161-.224.474-.274.698-.111l14.5 10.5c.224.162.273.475.111.698-.098.135-.251.206-.405.206zm0-4c-.166 0-.329-.083-.424-.233l-8.5-13.5c-.146-.234-.076-.543.157-.69.236-.146.543-.077.69.156l8.5 13.5c.147.233.077.543-.157.689-.082.054-.175.078-.266.078z"/><path fill="#77B255" d="M17.5 24c-.276 0-.5-.224-.5-.5v-18c0-.276.224-.5.5-.5s.5.224.5.5v18c0 .276-.224.5-.5.5z"/><path fill="#269" d="M15 16c-1-2 0-4 0-4s0 1 1 2c0-3 1-3 1-3s0 2 1 3-3 2-3 2zm7.997 13c-.433-2-1.725-3.061-2.559-4.5-.671-1.156-2.134-3.75-.132-6.618.532-.762-1.885-1.831-2.305-1.877v-.004l-.015.002-.015-.002v.004c-.42.046-2.837 1.115-2.305 1.877 2.002 2.868.538 5.462-.132 6.618-.834 1.439-2.126 2.5-2.559 4.5-.362 1.668 2.247 3.981 4.997 3.998v.001h.015L18 33v-.002c2.75-.017 5.358-2.33 4.997-3.998z"/><path fill="#292F33" d="M19 16c3 0 6 2 6 2s-3 1-6 0 0-2 0-2"/><circle fill="#269" cx="18" cy="16" r="3"/><circle fill="#292F33" cx="19" cy="16" r="1"/><circle fill="#55ACEE" cx="3" cy="27" r="2"/><circle fill="#55ACEE" cx="3" cy="20" r="2"/><circle fill="#55ACEE" cx="7" cy="13" r="2"/><circle fill="#55ACEE" cx="14" cy="8" r="2"/><circle fill="#55ACEE" cx="7.5" cy="28.5" r="1.5"/><circle fill="#55ACEE" cx="7.5" cy="22.5" r="1.5"/><circle fill="#55ACEE" cx="10.5" cy="16.5" r="1.5"/><circle fill="#55ACEE" cx="11" cy="29" r="1"/><circle fill="#55ACEE" cx="11" cy="24" r="1"/><circle fill="#55ACEE" cx="14" cy="20" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f99c.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f99c.svg new file mode 100644 index 0000000000000000000000000000000000000000..f7f743c52258ffc7ca3c8c2891789b3a18fa0cbd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f99c.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M17.5 35c-.128 0-.256-.049-.354-.146-.195-.195-.195-.512 0-.707L19 32.293V29.5c0-.276.224-.5.5-.5s.5.224.5.5v3.207l-2.146 2.146c-.098.098-.226.147-.354.147z"/><path fill="#66757F" d="M19.5 33h-3c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h3c.276 0 .5.224.5.5s-.224.5-.5.5zm3 2c-.128 0-.256-.049-.354-.146-.195-.195-.195-.512 0-.707L24 32.293V29.5c0-.276.224-.5.5-.5s.5.224.5.5v3.207l-2.146 2.146c-.098.098-.226.147-.354.147z"/><path fill="#66757F" d="M24.5 33h-3c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h3c.276 0 .5.224.5.5s-.224.5-.5.5z"/><path fill="#F4900C" d="M3.53 13.798c.845.452 3.813-1.411 4.36-3.308S6.869 8.374 5.008 9.25 2.8 13.407 3.53 13.798z"/><path fill="#FFAC33" d="M6.325 4C3.77 5 2.047 7.378 2.031 10.088c-.016 2.699 1.219 4.423 2.594 4.047.376-.103-.303-1.922.85-4.371.57-1.207 1.303-1.35 1.675-1.313.373.036.443-4.947-.825-4.451z"/><path fill="#77B255" d="M34.525 31.384c-.014.499-1.916.822-5.592-3.599-2.927 3.09-7.374 3.182-11.821 1.422-4.999-1.979-8.383-6.924-7.701-13.976.382-3.954-5.228-3.587-5.081-8.899C4.441 2.337 7.843.797 10.704.876c4.74.131 6.82 5.293 8.052 6.561 6.494 6.688 15.81 22.47 15.769 23.947z"/><path fill="#EA596E" d="M28.932 27.785c-2.927 3.09-7.374 3.182-11.821 1.422-4.999-1.979-8.383-6.924-7.701-13.976.036 4.343 1.559 7.582 2.94 8.416-.58-2.79.117-7.062.784-7.779 1.591 9.402 10.022 14.78 15.798 11.917z"/><path fill="#3B88C3" d="M13.135 15.867s1.737 5.788 7.33 9.387 8.468 2.53 8.468 2.53-2.939 3.363-7.647 2.084-9.321-5.997-8.151-14.001z"/><path fill="#5C913B" d="M16.938 9.417c-2.504-.588-6.666 7.123-1.009 13.392 7.436 8.241 13.004 4.976 13.004 4.976S24.785 11.259 16.938 9.417z"/><circle fill="#292F33" cx="8" cy="6" r="1"/><path fill="#5C913B" d="M10.724 13.259c-.79 0-1.509-.189-1.976-.45-.248-.139-.336-.453-.198-.701.14-.248.454-.336.701-.198.665.373 2.406.63 3.614-.423.213-.187.539-.165.726.05.187.214.164.54-.05.726-.836.729-1.877.996-2.817.996z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f99d.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f99d.svg new file mode 100644 index 0000000000000000000000000000000000000000..30c88720fb80085217e67d8ab36d7181128201bc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f99d.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M10.668 5.616C9.032 2.479 4.439 1.005 3.584 2.298s.707 10.152 1.757 9.967c1.051-.185 5.327-6.649 5.327-6.649z"/><path fill="#292F33" d="M9.841 7.674c-1.27-2.68-4.696-4.82-5.304-3.745-.435.771.122 5.263.757 7.696l4.547-3.951z"/><path fill="#99AAB5" d="M25.284 5.616c1.636-3.137 6.228-4.611 7.084-3.318s-.708 10.152-1.758 9.967c-1.051-.185-5.326-6.649-5.326-6.649z"/><path fill="#292F33" d="M26.36 7.674c1.231-2.686 4.501-4.854 5.07-3.786.416.78-.178 5.425-.815 7.825L26.36 7.674z"/><path fill="#99AAB5" d="M33.13 13.316c-2.583-3.164-9.048-11.601-15.155-11.601S5.404 10.152 2.821 13.316C-.317 17.16-.23 21.613.573 24.193c.805 2.587 3.155 5.038 9.261 7.431 2.065.809 5.705 2.393 8.142 2.393s6.076-1.583 8.142-2.393c6.106-2.393 8.457-4.843 9.261-7.431.802-2.58.89-7.033-2.249-10.877z"/><path fill="#E1E8ED" d="M17.976 14.408c0-4.913-4.078-4.855-6.542-4.572C6.922 10.353.076 16.597.076 20.569c0 1.39.16 2.631.496 3.624.584 1.726 1.875 3.015 5.034 5.266 3.49-8.351 12.37-11.246 12.37-15.051z"/><path fill="#292F33" d="M17.976 15.777c0-2.399-4.389-3.04-6.649-2.678C6.443 13.882.587 20.633.572 24.07v.013c.002.006.001.111.001.111s.384 1.401 1.623 2.815c.867.991 2.346 2.068 3.333 2.584l.01-.011c2.952-3.861 6.877-6.416 10.022-7.617 1.763-.673 2.415-3.5 2.415-6.188z"/><circle fill="#99AAB5" cx="13.396" cy="17.489" r="1.527"/><path fill="#E1E8ED" d="M17.976 14.408c0-4.913 4.078-4.855 6.542-4.572 4.511.518 11.357 6.762 11.357 10.734 0 1.39-.16 2.631-.496 3.624-.584 1.726-1.875 3.015-5.034 5.266-3.489-8.352-12.369-11.247-12.369-15.052z"/><path fill="#292F33" d="M17.976 15.777c0-2.399 4.389-3.04 6.649-2.678 4.884.783 10.74 7.534 10.755 10.971v.013c-.002.006-.001.111-.001.111s-.384 1.401-1.623 2.815c-.868.991-2.347 2.068-3.333 2.584l-.01-.011c-2.952-3.861-6.877-6.416-10.022-7.617-1.763-.673-2.415-3.5-2.415-6.188z"/><circle fill="#99AAB5" cx="22.555" cy="17.489" r="1.527"/><path fill="#66757F" d="M20.746 22.102c-.923-1.073-1.75-19.035-2.77-19.035s-1.847 17.962-2.77 19.035h5.54z"/><path fill="#E1E8ED" d="M24.915 24.184c-1.636-2.06-4.164-3.705-6.94-3.705s-5.304 1.646-6.94 3.705c-1.388 1.748-1.388 3.061-.925 4.226.482 1.214 1.388 2.821 4.164 3.986.939.394 2.594 1.165 3.701 1.165 1.108 0 2.762-.771 3.701-1.165 2.776-1.165 3.682-2.772 4.164-3.986.463-1.165.463-2.478-.925-4.226z"/><path fill="#292F33" d="M21.614 28.372c-.689-.562-1.629.184-3.639.184s-2.95-.746-3.639-.184c-.689.562.585 2.308 3.639 2.308s4.328-1.746 3.639-2.308z"/><path fill="#66757F" d="M13.165 24.769c-.133 0-.268-.035-.391-.107-3.002-1.792-8.357-.913-9.664-.286-.378.184-.835.023-1.019-.357-.182-.381-.022-.837.358-1.019 1.744-.838 7.624-1.725 11.107.35.362.217.481.685.264 1.047-.142.239-.395.372-.655.372z"/><path fill="#66757F" d="M2.141 29.702c-.168 0-.337-.056-.478-.169-.328-.264-.38-.744-.116-1.073 1.455-1.807 4.896-4.888 11.581-5.216.419-.035.779.304.8.725.021.421-.304.779-.725.8-6.089.299-9.171 3.041-10.467 4.649-.151.187-.372.284-.595.284zm31.669 0c-.223 0-.443-.097-.594-.284-1.295-1.608-4.377-4.35-10.467-4.649-.42-.021-.745-.379-.725-.8.021-.42.383-.763.8-.725 6.685.328 10.124 3.409 11.58 5.216.264.329.213.809-.115 1.073-.141.113-.31.169-.479.169z"/><path fill="#66757F" d="M22.787 24.769c-.26 0-.514-.133-.657-.373-.216-.362-.097-.83.264-1.047 3.482-2.076 9.366-1.188 11.107-.35.381.182.541.638.358 1.018-.182.381-.636.544-1.018.358-1.31-.628-6.664-1.505-9.664.286-.123.074-.257.108-.39.108z"/><path fill="#292F33" d="M21.614 22.244c0 1.765-2.539 3.223-3.639 3.223-1.1 0-3.639-1.458-3.639-3.223s1.629-1.81 3.639-1.81 3.639.045 3.639 1.81z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f99e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f99e.svg new file mode 100644 index 0000000000000000000000000000000000000000..8df2a7467606b11621ed366ae19e556b00eae6fd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f99e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><g fill="#BE1931"><path d="M14.847 22.402h-.064c-2.117-.069-4.919-1.006-6.246-5.077-.135-.413.089-.864.503-.999.414-.135.857.085.992.499l.003.011c.312.959 1.263 3.876 4.8 3.991.435.015.776.378.762.812-.014.415-.344.743-.75.763zm-5.348 5.637c.151-.221.411-.359.698-.342 3.034.181 4.578-1.938 5.086-2.634.256-.352.749-.429 1.1-.173.352.256.414.747.173 1.1-1.698 2.33-3.869 3.434-6.453 3.28-.434-.026-.766-.399-.74-.834.01-.148.059-.284.136-.397z"/><path d="M14.362 23.967c.421-.064.767-.141 1.022-.2l.179-.04c.426-.092.695-.511.603-.937-.092-.425-.515-.698-.937-.603l-.193.043c-1.087.245-3.635.824-6.463-1.149-.357-.248-.849-.161-1.096.195-.249.357-.161.848.195 1.096 2.665 1.86 5.165 1.826 6.69 1.595z"/><path d="M15.403 25.298c.376-.199 1.053-.624 1.053-.624.371-.228.487-.712.259-1.084-.227-.37-.718-.488-1.084-.259l-.168.105c-.944.591-3.156 1.981-6.479 1.057-.419-.116-.854.129-.97.548-.117.419.129.854.548.97 3.131.87 5.479.009 6.841-.713z"/></g><g fill="#BE1931"><path d="M21.833 22.402h.064c2.117-.069 4.919-1.006 6.246-5.077.135-.413-.089-.864-.503-.999-.414-.135-.857.085-.992.499l-.003.011c-.312.959-1.263 3.876-4.8 3.991-.435.015-.776.378-.762.812.015.415.344.743.75.763zm5.348 5.637c-.151-.221-.411-.359-.698-.342-3.034.181-4.578-1.938-5.086-2.634-.256-.352-.749-.429-1.1-.173-.352.256-.414.747-.173 1.1 1.698 2.33 3.869 3.434 6.453 3.28.434-.026.766-.399.74-.834-.009-.148-.058-.284-.136-.397z"/><path d="M22.318 23.967c-.421-.064-.767-.141-1.022-.2l-.179-.04c-.426-.092-.695-.511-.603-.937.092-.425.515-.698.937-.603l.193.043c1.087.245 3.635.824 6.463-1.149.357-.248.849-.161 1.096.195.249.357.161.848-.195 1.096-2.664 1.86-5.165 1.826-6.69 1.595z"/><path d="M21.277 25.298c-.376-.199-1.053-.624-1.053-.624-.371-.228-.487-.712-.259-1.084.227-.37.718-.488 1.084-.259l.168.105c.944.591 3.156 1.981 6.479 1.057.419-.116.854.129.97.548.117.419-.129.854-.548.97-3.131.87-5.479.009-6.841-.713z"/></g><path fill="#BE1931" d="M8.983 6.922c.752-.779 2.316-2.461 1.59-3.954.949.077 6.757 6.159-.06 9.073-1.072-.137-1.53-5.119-1.53-5.119zm8.772 23.394c-.726.329-4.25 2.171-4.354 5.46.069.789 2.73-1.25 5.01-1.25v-3.454l-.656-.756z"/><path fill="#BE1931" d="M19.035 30.316c.726.329 4.25 2.171 4.354 5.46-.069.789-2.73-1.25-5.01-1.25v-3.454l.656-.756zm-11.4-18.303c.133 1.429 2.975 2.889 5.023 3.227.262-.57-1.354-2.237-2.227-3.246-.488-.564-.701-1.904-2.185-1.321s-.611 1.34-.611 1.34z"/><path fill="#BE1931" d="M11.742 13.793c-.655 0-.83 1.754 2.489 2.544s1.56-.878 1.048-1.667c-.656-1.009-3.537-.877-3.537-.877z"/><path fill="#89021F" d="M15.465 25.382c-.187.987-.075 6.217 2.961 6.612v-7.006l-2.961.394z"/><path fill="#BE1931" d="M27.629 6.922c-.752-.779-2.316-2.461-1.59-3.954-.949.077-6.757 6.159.06 9.073 1.072-.137 1.53-5.119 1.53-5.119z"/><path fill="#BE1931" d="M28.976 12.013c-.133 1.429-2.975 2.889-5.023 3.227-.262-.57 1.354-2.237 2.227-3.246.488-.564.701-1.904 2.185-1.321s.611 1.34.611 1.34z"/><path fill="#BE1931" d="M24.87 13.793c.655 0 .83 1.754-2.489 2.544s-1.56-.878-1.048-1.667c.655-1.009 3.537-.877 3.537-.877z"/><path fill="#DD2E44" d="M28.391.042c2.633.67 4.675 5.092 4.174 7.847-.782 4.302-2.992 5.787-5.428 6.164-.748-.058-3.293-3.474-.576-6.272s2.505-5.856 1.83-7.739z"/><path fill="#BE1931" d="M17.541 12.5c-.258 0-.478-.199-.498-.461-.498-6.35-2.635-10.064-6.018-10.459-.274-.032-.471-.28-.438-.555.032-.273.274-.468.555-.438 2.264.264 6.17 2.093 6.898 11.374.021.275-.184.516-.459.538l-.04.001zm1.418 0l-.04-.001c-.275-.021-.481-.262-.459-.538C19.188 2.68 23.095.851 25.359.587c.27-.038.522.164.555.438.031.274-.165.523-.439.555-3.383.395-5.52 4.109-6.018 10.459-.02.262-.239.461-.498.461z"/><path fill="#A0041E" d="M18.381 23.04c0 1 .019 3.326.019 4.876-.576 0-1.491-.016-2.438-.3-1.497-.45-1.113-3.901-.614-4.701l3.033.125z"/><path fill="#BE1931" d="M18.335 19.239c0 1.113.022 3.702.022 5.428-.655 0-1.696-.017-2.773-.334-1.703-.501-1.266-4.342-.699-5.233l3.45.139z"/><path fill="#DD2E44" d="M18.335 11.731c0 2.169.279 8.822.279 9.497-1.397 0-5.301.337-5.082-3.134.218-3.47 2.358-6.363 4.803-6.363z"/><path fill="#89021F" d="M21.152 25.382c.187.987.075 6.217-2.961 6.612v-7.006l2.961.394z"/><path fill="#A0041E" d="M18.235 23.04c0 1-.152 3.326-.152 4.876.576 0 1.624-.016 2.57-.3 1.497-.45 1.113-3.901.614-4.701l-3.032.125z"/><path fill="#BE1931" d="M18.282 19.239c0 1.113-.165 3.702-.165 5.428.655 0 1.84-.017 2.916-.334 1.703-.501 1.266-4.342.699-5.233l-3.45.139z"/><path fill="#DD2E44" d="M18.282 11.731c0 2.169-.21 8.822-.21 9.497 1.397 0 5.231.337 5.013-3.134s-2.358-6.363-4.803-6.363zM8.22.042c-2.633.67-4.675 5.092-4.174 7.847.782 4.302 2.992 5.787 5.428 6.164.748-.058 3.293-3.474.576-6.272S7.546 1.925 8.22.042z"/><ellipse transform="rotate(-10.068 16.574 12.941)" fill="#BE1931" cx="16.578" cy="12.94" rx="1.015" ry="1.435"/><ellipse transform="rotate(-79.939 19.875 12.896)" fill="#BE1931" cx="19.875" cy="12.896" rx="1.435" ry="1.015"/><ellipse transform="rotate(-10.068 16.45 12.233)" fill="#292F33" cx="16.453" cy="12.232" rx="1.015" ry="1.435"/><ellipse transform="rotate(-79.939 19.99 12.232)" fill="#292F33" cx="19.99" cy="12.232" rx="1.435" ry="1.015"/><path fill="#EA596E" d="M14.375 18.906c.281.844.844 1.75 3.844 1.75 2.094 0 4.156-.375 4.094-1.906-.781.656-1.75.938-4.094.938-2.5 0-3.844-.782-3.844-.782z"/><path fill="#DD2E44" d="M15.272 22.923c.218.595.653 1.234 2.975 1.234 1.62 0 3.217-.264 3.168-1.344-.605.463-1.354.661-3.168.661-1.935-.001-2.975-.551-2.975-.551z"/><path fill="#BE1931" d="M15.376 26.089c.205.595.615 1.234 2.803 1.234 1.527 0 3.031-.264 2.986-1.344-.57.463-1.276.661-2.986.661-1.823 0-2.803-.551-2.803-.551z"/><path fill="#EA596E" d="M8.812 12.781c-.106 0-.214-.022-.316-.07-2.026-.944-3.157-2.62-3.361-4.98-.036-.412.265-.812.677-.848.413-.036.773.231.81.643l.006.076c.064.737.233 2.693 2.501 3.75.375.175.538.621.363.997-.127.272-.397.432-.68.432zm18.938 0c-.282 0-.553-.16-.68-.433-.175-.375-.013-.822.363-.997 2.268-1.057 2.437-3.013 2.5-3.75l.754-.008.741.137c-.205 2.36-1.336 4.036-3.362 4.98-.102.049-.21.071-.316.071z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a3.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a3.svg new file mode 100644 index 0000000000000000000000000000000000000000..1aa87190b9ea1bb3e48c1c801ae7087f9b975815 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M9.396 20.496s2.053 6.29 2.053 8.144.023 3.271-.374 4.463c-.397 1.192-.066 1.523 1.523 1.589 1.589.066 3.774 0 3.973-1.192.199-1.192-.156-1.55-.089-2.742.066-1.192.331-4.37.53-4.701.199-.331 3.906.662 4.635.927s3.046.265 3.112 1.059c.066.795.487 4.86.288 5.655-.199.795.397.993 2.251.927 1.986-.071 3.112-.463 2.979-1.324-.132-.861-.222-2.146.043-3.139s1.258-3.84 1.324-4.767c0 0 .927-2.053.861-3.575-.066-1.523-.651-3.477-2.522-5.575-1.28-1.435-3.196-1.466-5.579-2.194s-4.461-1.581-5.454-2.508c-.993-.927-3.694-1.065-5.078-.439-1.362.616-6.059 10.788-4.476 9.392z"/><path fill="#C1694F" d="M35.627 28.281c-.53-1.523-.993-3.906-1.059-5.429-.029-.661-.076-1.581-.263-2.576l.619.435c-.104-1.144-1.069-2.108-1.069-2.108l1.126-.118c-.28-.504-1.854-1.338-1.854-1.338l1.283-.318c-.56-.84-2.03-.98-2.03-.98l.318-.504c-.402-.281-1.209-.247-2.149-.532-1.02-.603-2.203-1.096-3.576-1.515-1.12-.342-2.124-.907-2.984-1.504l1.289-.444s-1.157-.459-1.628-.619c-.378-.129-.988-.154-1.217-.16l-.026-.023 1.32-.401c-.413-.558-2.555-.759-2.555-.759s.988-.197 1.139-.287c-.755-.574-2.112-.319-2.112-.319l.995-.859c-.583-.077-2.719.602-2.719.602l.582-.999c-.734.013-1.586 1.026-2.27 1.061-.051.003-.097.011-.147.016-.489-.106-.982-.292-1.425-.68-.497-.435-1.054-.86-1.638-1.183-.757-.419-1.558-.666-2.326-.539-1.195.199-1.565 1.223-2.53 1.674-.113.053-.214.115-.304.184-.828.376-1.435.846-1.641 1.093l.802.059s-1.661.726-2.02 1.188l1.042-.031s-.926.655-1.131 1.22l.772.012s-1.279 1.13-1.485 1.592l.971-.258-.704 1.654.543-.055c-.073.341-.135.678-.187 1.012-.039.12-.067.266-.074.455-.031.811-1.09 1.688-1.09 1.688l.541.609s-.565 1.302-.883 1.674c0 0 .931-.215 1.09-.481 0 0-.297 1.16-.52 2.022l.777-.481c.164 2.254.028 5.167-.987 6.98-1.031 1.843-2.782 2.646-3.715 3.193-.933.547.109 3.102.733 3.012.624-.09 2.429-.561 4.762-2.374.442-.344.808-.679 1.14-1.01l.201.67c.445-.683.799-1.769.799-1.769l.799.4v-1.598l.799.285s-.483-1.41-.24-2.181c.39-1.353 1.351-2.888 2.309-3.965.588 1.9 1.691 5.641 1.691 7.001 0 1.854.023 3.271-.374 4.463s-.066 1.523 1.523 1.589 3.774 0 3.973-1.192c.199-1.192-.156-1.55-.089-2.742.065-1.168.2-3.8.392-4.216l.403.587.645-.751.02.001.479 2.204.529-1.925.498.897.692-.957.449 2.156.562-1.64.693 1.069.601-.935.564 1.634.481-1.388c.06.025.118.049.175.075l.522.995c.035-.012.215-.165.422-.405.129.133.225.27.237.417.066.795.398 4.328.199 5.123-.199.795.397.993 2.251.927 1.986-.071 3.112-.463 2.979-1.324-.132-.861-.222-2.146.043-3.139.265-.993 1.258-3.84 1.324-4.767 0 0 .07 1.396.596 2.185 1.195 1.784 1.857 1.188 1.327-.335z"/><path fill="#DA9E82" d="M9.808 21.064s-1.305 3.179-2.829 3.704c-1.857.64-4.21.573-4.917-.904-.748-1.564-.534-3.186.46-4.254.412-.443-.03-.645-.567-.31-1.484.926-2 2.417-1.777 4.256.188 1.544 1.681 3.207 3.59 3.465s4.308.127 6.011-1.73c1.283-1.399 1.78-2.374 2.118-2.947.316-.539-1.879-1.763-2.089-1.28z"/><path fill="#FFE9B7" d="M9.808 21.064s-1.45 3.394-2.973 3.92c-1.857.64-4.283.497-4.99-.98-.749-1.564-.727-3.209.267-4.277.412-.443.2-.542-.297-.149C.538 20.588.136 21.69.36 23.528c.188 1.544 1.596 3.069 3.505 3.327 1.909.258 4.119.283 5.822-1.574 1.283-1.399 1.872-2.364 2.209-2.937.317-.539-1.878-1.763-2.088-1.28z"/><circle fill="#292F33" cx="11" cy="14" r="1"/><path fill="#662113" d="M15.552 10.936c.068.616.89 1.848 1.369 2.258.479.411.616 1.574-.205 2.532s-1.095 2.532-1.848 3.148-1.779.137-1.984-.342c0 0-.411.958.753 1.232 1.163.274 1.848.068 2.463-1.095.616-1.163 1.437-2.326 2.053-3.148.616-.821.479-2.395-.274-2.874-.754-.48-2.327-1.711-2.327-1.711z"/><path opacity=".6" fill="#662113" d="M30.355 17.471c.175.738.01 1.891-.319 1.115s-.49-2.059-.49-2.059.634.205.809.944zm1.691 1.199s.119 1.173.43 2.049.395-.374.215-1.196c-.179-.822-.645-.853-.645-.853zm.581 4.422s.013.997.228 2.011c.215 1.013.472.175.398-.76s-.626-1.251-.626-1.251zm-3.314 1.979s.024 1.299.227 2.122.535-.031.475-.792c-.06-.761-.702-1.33-.702-1.33zm1.971 2.413s-.233 1.278-.197 2.125c.036.846.531.076.622-.682.091-.758-.425-1.443-.425-1.443zm-3.123-8.993s.009 1.086.223 2.099c.215 1.013.567.018.493-.917-.074-.935-.716-1.182-.716-1.182zm-.371 4.332s-.327.753-.255 1.787c.072 1.033.56.096.616-.84.057-.936-.361-.947-.361-.947zm2.948-1.222s-.055.874.305 1.845.578.202.369-.712c-.21-.914-.674-1.133-.674-1.133zm-4.319-6.013s-.066.762.268 1.742.498-.137.336-1.057c-.162-.92-.604-.685-.604-.685zm-4.664-2.692s.533.878 1.09 1.545.402-.278.012-.955c-.389-.678-1.102-.59-1.102-.59zm1.136 3.228s.029.94.325 1.757.473-.125.337-.894c-.135-.769-.662-.863-.662-.863zm-.872 4.083s-.16.921-.006 1.776.568.425.564-.356-.558-1.42-.558-1.42zm3.283 4.984s-.056.822.098 1.678c.154.855.487-.043.484-.824s-.582-.854-.582-.854zm-5.278-1.775s-.294.818-.229 1.684c.065.866.428.51.505-.267.077-.777-.276-1.417-.276-1.417zm-1.474 1.519s-.294.818-.229 1.684c.065.866.428.51.505-.267.077-.778-.276-1.417-.276-1.417zm5.181.848s-.294.818-.229 1.684c.065.866.428.51.505-.267.077-.777-.276-1.417-.276-1.417zm-6.063-5.633s-.205 1.204-.14 2.071c.065.866.398.391.475-.386.077-.778-.335-1.685-.335-1.685zm-3.681 4.336c.132.77.548 1.608.522.745s-.283-1.826-.283-1.826-.371.31-.239 1.081zm1.713 2.67c.132.77.548 1.608.522.745s-.323-1.807-.323-1.807-.331.292-.199 1.062zm-1.295 3.171c.132.77.548 1.608.522.745s-.273-1.673-.273-1.673-.381.158-.249.928zm5.334-18.798s.49 1.29.926 2.041.443-.207.173-.94c-.27-.732-1.099-1.101-1.099-1.101zm-.063 6.407s.08 1.378.27 2.226c.191.848.485-.064.447-.844s-.717-1.382-.717-1.382zm5.426.772s.253 1.357.549 2.174c.296.817.473-.125.337-.894-.135-.77-.886-1.28-.886-1.28zm-1.42 2.546s-.09 1.071.096 1.92.485-.061.452-.842c-.032-.78-.548-1.078-.548-1.078zM7.259 14.74s-.67.491-.938 1.027c-.268.536-.089 1.072.223.536.313-.536.715-1.563.715-1.563zm1.161-4.422s-.715.134-1.117.491-.313.849.134.491c.447-.357.983-.982.983-.982zm-1.563 2.769c.402-.447 1.921-1.608 1.206-1.429-.715.179-1.295.938-1.295.938-.269.312-.313.938.089.491zm2.769-4.154c.536-.402 1.34-.804 1.34-.804s-.448.061-1.206.313c-.536.179-.67.893-.134.491zm-2.412 8.084s-.581.223-.938 1.027c-.357.804-.179 1.251.134.625.313-.624.804-1.652.804-1.652zm.536 2.323s-.581.402-.804 1.027c-.223.625-.089 1.251.134.625.223-.625.67-1.652.67-1.652zm1.697-1.653s-.402.759-.447 1.295c-.045.536.268.983.313.357.045-.624.134-1.652.134-1.652zm-2.456 4.69s-.581.313-.938.804c-.357.491-.223 1.251.089.67.313-.581.849-1.474.849-1.474zm.178 7.191c-.045.67.536.134.536-.447s-.178-1.251-.178-1.251-.313 1.028-.358 1.698zm-2.724 0s-.491.134-.983.313c-.491.179-1.072 1.027-.491.759s1.474-1.072 1.474-1.072zm-.313 2.322s-.536.402-1.117.581c-.581.179-.357.67.357.313.716-.358.76-.894.76-.894zM14.449 8.576c.804.536.759.223.491-.223-.268-.447-1.519-.625-1.519-.625s.224.312 1.028.848zm-.808 2.433c.466.549.513-.414.028-.823s-1.122-.654-1.122-.654.628.928 1.094 1.477zm-.666 5.964c.22.686.559.028.268-.536s-.687-.837-.687-.837.2.687.419 1.373zm1.564-2.546c.22.686.559.028.268-.536s-.687-.837-.687-.837.199.687.419 1.373zm13.264 1.474c.22.686.559.028.268-.536s-.687-.837-.687-.837.2.687.419 1.373zm.626 15.41c.102.713.547.121.354-.484-.193-.605-.537-.94-.537-.94s.081.711.183 1.424zm-11.16 1.26c-.081.716.499.255.464-.379-.034-.634-.284-1.045-.284-1.045s-.1.708-.18 1.424zM11.055 10.05s-.983.357-1.251.759-.089.938.179.491c.268-.446 1.072-1.25 1.072-1.25z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a4.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a4.svg new file mode 100644 index 0000000000000000000000000000000000000000..1dbac1e3177b33a2fe8bbd3288da2a9d3acc55b4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E08110" d="M17.338 26.109c0 1.515-.032 2.456-.771 2.813-.739.357-3.354.065-3.805.339-.45.274-.845.792-.42.78.425-.012 1.004.13 1.004.13s-.821.222-1.127.531-.464.961-.148.923c.316-.038 1.869-.427 2.177-.429 0 0-.386.482-.429.816-.043.335.229.478.229.478s1.118-.495 1.551-.697c.433-.202 1.161-.83 1.504-.977.343-.147.768-.158 2.126.249 0 0 .016-.655-.51-.859-.526-.205-.915-.058-.802-.847.134-.936.436-2.834.713-3.342.278-.505-1.292-1.027-1.292.092z"/><path fill="#66757F" d="M13.427 21.831c1.303 1.002 2.871 2.423 3.206 3.132.336.708.186 1.864 1.118 1.901.932.037 1.454-.746 1.827-1.901.373-1.156 1.007-3.02.634-4.175s-5.48-.746-6.263-.41c-.783.334-1.492.707-.522 1.453z"/><path fill="#CCD6DD" d="M10.009 1.94c0 .801-.651 1.352-1.552 1.602s-2.403.2-3.204 1.001-1.201 2.803 1.452 4.806c0 0-.401-.701-.25-1.202 0 0 .801.2 1.352-.1.551-.3.801-.951 1.302-1.302.501-.35 1.652-.651 1.852.751s2.186-.419 2.47-.834c.434-.634 1.619-2.553 1.168-3.104S13.33 2.59 12.93 2.09c-.401-.501-2.921-.15-2.921-.15z"/><path fill="#E1E8ED" d="M10.009 1.94c0 .801-.651 1.352-1.552 1.602s-2.403.2-3.204 1.001-1.201 2.803 1.452 4.806c0 0-.401-.701-.25-1.202 0 0 .801.2 1.352-.1.551-.3.801-.951 1.302-1.302.501-.35 1.652-.651 1.852.751s1.952-.1 2.003-.601c.05-.501.25-1.101-.2-1.652s-1.902-.601-2.303-1.101c-.402-.5-.452-2.202-.452-2.202z"/><path fill="#FFAC33" d="M6.289 7.708c.167-.5.458-.749.874-.985.405-.886.534-2.102.456-3.021-.825.125-1.781.257-2.366.841-.773.773-1.164 2.667 1.197 4.599-.279-.447-.323-.948-.161-1.434z"/><path fill="#FFAC33" d="M8.31 6.423l-.087.073c-.533.433-1.267.511-1.7 1.312-.05.093-.064.213-.064.34.018.004.804.196 1.349-.101.082-.045.148-.109.218-.168.294-.364.304-1.073.284-1.456z"/><path fill="#C1694F" d="M9.859 4.927c-.867.167-1.402 1.134-2.136 1.502-.21.105-.393.199-.56.294-.416.236-.707.485-.874.985-.162.486-.118.987.161 1.434.084.069.164.138.255.207 0 0-.4-.701-.25-1.201l.003.001c0-.127.014-.247.064-.34.434-.802 1.168-.88 1.702-1.314l.086-.072c.532-.444 1.283-1.164 1.916-1.196.667-.033 2.003.167 2.003.167s-1.502-.634-2.37-.467z"/><path fill="#99AAB5" d="M10.026 2.323c-.255-.074-.425-.467-.3-.801.142-.38 1.135-1.168 2.87-1.068s4.139 1.335 4.205 4.606c.067 3.271-1.569 4.239-2.203 5.006-.634.768-.634 1.769.868 1.836 1.502.067-.2 3.605-1.368 5.04s-4.339 3.304-5.607 1.535c-1.268-1.769-1.902-2.637-1.969-4.606s.935-3.638 2.069-4.606 2.169-1.135 2.336-2.069c0 0 .567.067.901-.434.334-.501.768-.501 1.202-.567s1.202-.968 1.168-1.635c-.033-.655-.38-1.646-.884-2.069-1.035-.868-2.644.019-3.288-.168z"/><circle fill="#292F33" cx="12.097" cy="3.601" r=".75"/><path fill="#99AAB5" d="M13.998 11.523c.668.374 2.011.257 2.61.086s2.61-.599 3.893-.428 3.166 1.112 4.192 1.711c1.027.599 1.754.856 2.396.471s2.011 2.909 2.182 4.62c.171 1.711.299 3.251-1.283 4.492-1.583 1.241-4.306 2.644-8.513 2.396-4.286-.253-11.147-2.432-11.389-7.234-.28-5.557.48-4.402 1.977-5.557s2.866-1.156 3.935-.557z"/><path fill="#FFAC33" d="M20.457 27.401c-.039 1.158-.045 2.673-.802 3.297-.757.624-3.876 1.025-4.322 1.47-.446.446-.757 1.158-.267 1.025s1.203-.134 1.203-.134-.891.49-1.158.936c-.267.446-.267 1.248.089 1.114s2.05-1.025 2.406-1.114c0 0-.312.668-.267 1.069.045.401.401.49.401.49s1.158-.891 1.604-1.248 1.114-1.292 1.47-1.559c.356-.267.847-.401 2.54-.312 0 0-.223-.624-.891-.713-.668-.089-1.515.089-1.337-.847s.713-3.208.891-3.876c.178-.667-1.515-.935-1.56.402z"/><path fill="#99AAB5" d="M15.957 22.366c1.557 1.198 3.431 2.896 3.832 3.743s.223 2.228 1.337 2.272c1.114.045 1.738-.891 2.183-2.272.446-1.381 1.203-3.609.757-4.99s-6.549-.891-7.485-.49c-.936.401-1.782.846-.624 1.737z"/><path fill="#66757F" d="M13.614 15.306c-.325.812-.3 3.254.3 3.755.601.501 1.445 1.202 1.502 1.802.1 1.051 1.302 2.703 2.553 3.354 1.252.651 3.004.651 3.755.551.751-.1 1.252-.951 1.001-2.353-.25-1.402-.951-3.004-2.003-3.304 0 0 1.252-.951 1.252-1.802 0-.851-1.202-2.854-1.952-3.454-.751-.601-5.707-.301-6.408 1.451z"/><path fill="#99AAB5" d="M13.452 15.013c-.325.812.112 3.197.712 3.697.601.501 1.602 1.402 1.652 2.003.05.601.901 2.303 2.153 2.954 1.252.651 2.603.851 3.354.751.751-.1 1.352-.651 1.101-2.053-.25-1.402-.701-3.154-2.253-3.404 0 0 1.502-.851 1.502-1.702s-.893-3.097-1.644-3.698c-.75-.601-5.876-.3-6.577 1.452z"/><path fill="#CCD6DD" d="M25.999 13.524c.23-1.11 1.477-2.227 2.903-2.135.921.059 1.842.446 2.243 1.188.421.78-.059 1.515-.059 1.515s.356.52.238 1.396c-.105.771-.743.802-.743.802s-.305 1.343-.802 1.871c-1.426 1.515-1.693 1.411-1.693 1.411s.297-.876.431-1.678c0 0-.475-.074-.475-.876s-.016-1.369-.327-2.347c-.298-.935-1.716-1.147-1.716-1.147zm-7.623 5.727s1.211-.081 1.776.081c.565.161 1.897 1.09 1.17 1.13-.727.04-2.946-1.211-2.946-1.211zm-.081.807s1.574.242 2.139.404c.565.161 1.897 1.164 1.17 1.13-1.735-.081-3.309-1.534-3.309-1.534zm.363 1.009s1.574.525 2.139.686 1.897.881 1.17.847c-1.735-.081-3.309-1.533-3.309-1.533zm0 .968s1.574.525 2.139.686 1.897.881 1.17.847c-1.735-.08-3.309-1.533-3.309-1.533zm-1.077-4.89s1.659.033 2.246.02c.587-.014 2.073.278 1.369.462-1.68.438-3.615-.482-3.615-.482zm.835-.638s.986-.176 1.573-.189c.587-.014 1.795.331 1.09.512-1.251.322-2.663-.323-2.663-.323zm.202-.727s.906-.107 1.493-.121 1.592.181.888.363c-1.251.323-2.381-.242-2.381-.242zm-.242 7.264s1.13.282 1.695.444c.565.161 1.897.881 1.17.847-1.736-.08-2.865-1.291-2.865-1.291zm-.808-4.923s.987-.237 1.572-.188c.586.049 2.032.498 1.312.605-1.718.256-2.884-.417-2.884-.417z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a5.svg new file mode 100644 index 0000000000000000000000000000000000000000..7371a8ed19f1c4c2be9463a3e51e58b7a98255c6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#7A5C44" d="M6 21c-1.105 0-2-.895-2-2V4c0-1.105.895-1 2-1s2-.105 2 1c0 0-.606 6.424 0 11.997C8.54 20.971 12 22 12 22c0 1.105-4.895-1-6-1zm14 4.999c-1.105 0-2-.895-2-2v-21c0-1.105.895-1 2-1s2-.105 2 1c0 0-.446 5.108-.125 9.297.32 4.187.125 11.703.125 11.703 0 1.104-.895 2-2 2z"/><path fill="#662113" d="M36 4L0 8V4l36-2z"/><path fill="#A78E81" d="M22.644 18.406c-.633 1.126-1.363 1.809-2.16 2.193-.402.041-1.132-.085-1.417-1.443-.332-1.587-.668-3.833-.668-6.594 0-4.144.601-8.742.601-8.742 0-.929 1.412-.936 2.086-.991-.156-.832-1.749-.83-3.684-.83-1.453 0-2.256 1.074-2.402 2.301-.147 1.228-.789 6.347-.744 10 .024 1.984.154 4.161.315 6.016-.792-.201-1.585-.393-2.364-.491-2.807-.356-6.505-.535-7.129-5.881C4.584 9.712 5 4.82 5 4.82c0-.929 1.412-1.158 2.086-1.213-.156-.832-1.678-.911-3.61-.783C2.026 2.92 1.235 3.668 1 5.3.622 7.929.578 13.988.8 18.176c.124 2.338.49 10.76 4.099 14.035C7.007 34.123 10.587 35.253 15 35c4.185-.24 7.623-1.796 9.548-3.413 3.342-2.807 4.09-4.837 4.229-7.035C29 21 24.02 15.959 22.644 18.406z"/><path fill="#A78E81" d="M35.025 22.671c-2.101 3.201-6.277 4.173-10.759 1.232s-5.253-7.159-3.152-10.36 7.488-2.584 10.384-.624 5.628 6.551 3.527 9.752z"/><path fill="#E2D2C7" d="M33.271 23.178c-1.5 2.287-5.164 2.984-9.005.464s-4.419-6.001-2.918-8.288c1.5-2.287 4.294-1.921 8.135.6s5.288 4.938 3.788 7.224z"/><path fill="#292F33" d="M20.565 14.564c-.499 1.126-.677 2.336-.491 3.55 1.498.439 3.637.97 4.65.759 1.646-.342 2.198-1.817 1.956-2.981-.335-1.616-3.191-2.544-6.115-1.328z"/><circle fill="#F5F8FA" cx="23.389" cy="16.576" r="1.188"/><path fill="#292F33" d="M34.307 23.581c-.834.906-1.873 1.551-3.061 1.864-.999-1.199-2.337-2.951-2.548-3.964-.342-1.646.792-2.739 1.956-2.981 1.617-.335 3.605 1.915 3.653 5.081z"/><circle fill="#F5F8FA" cx="31.338" cy="21.792" r="1.188"/><path fill="#292F33" d="M28.047 22.475c-.72 1.098-2.194 1.403-3.291.683-1.098-.72-1.403-2.194-.683-3.291.72-1.098 1.542-.41 2.639.31 1.097.72 2.055 1.2 1.335 2.298z"/><path fill="#292F33" d="M27.979 25.122c-.024 0-.049-.002-.073-.005-4.479-.654-6.297-4.07-6.372-4.216-.126-.244-.031-.545.214-.672.246-.13.546-.031.674.211.017.031 1.673 3.109 5.629 3.687.273.04.462.294.423.567-.037.249-.25.428-.495.428z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a6.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ea0173a5008bcfa231ecbc333f53bf70b0f96b6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A78E81" d="M2.381 8.671c-1.573 0-2.359.786-1.573 1.573 1.573 1.573 3.145 1.573 3.931.786L2.381 8.671zm6.29-6.29c0-1.573.786-2.359 1.573-1.573 1.573 1.573 1.573 3.145.786 3.931L8.671 2.381zm-4.717 9.435s8.547 14.433 14.939 16.512c3.344 1.087 5.692.599 7.863-1.573s2.406-4.447 1.573-7.863C26.937 13.188 11.816 3.954 11.816 3.954l-7.862 7.862z"/><path fill="#A78E81" d="M16.129 26.852c4.231 5.36 8.793 7.807 10.465 6.519 1.624-1.25-.324-2.578-2.174-6.954-1.936-4.58-10.526-2.397-8.291.435zM26.85 16.07c5.36 4.231 7.803 8.858 6.516 10.53-1.25 1.624-2.578-.324-6.954-2.174-4.581-1.936-2.394-10.591.438-8.356z"/><path fill="#846659" d="M17.008 21.564c.699-1.287-.914-3.363-2.504-3.314-1.172.036-3.617 1.934-5.883-.746-.209.209-.304.496-.311.829 1.158 1.577 2.472 3.242 3.848 4.765 1.656.479 3.913.192 4.85-1.534zm1.242-7.06c-.049 1.589 2.028 3.203 3.314 2.504 1.712-.93 2.007-3.159 1.544-4.81-1.545-1.372-3.246-2.703-4.851-3.882-.3.02-.56.113-.753.306 2.679 2.265.782 4.71.746 5.882z"/><path fill="#CAB8AC" d="M13.341 16.895c1.589-.049 3.203 2.028 2.504 3.314-1.12 2.061-4.135 2.086-5.74 1.183-1.79-1.007-3.732-4.157-2.646-5.243 2.265 2.68 4.709.783 5.882.746zm3.553-3.553c-.049 1.589 2.028 3.203 3.314 2.504 2.061-1.12 2.086-4.135 1.183-5.74-1.007-1.79-4.157-3.732-5.243-2.646 2.679 2.265.782 4.71.746 5.882z"/><path fill="#A78E81" d="M27.542 24.397c3.474 3.474 8.731 10.139 7.863 11.008-.868.868-7.534-4.389-11.008-7.863s-4.014-5.422-3.145-6.29c.868-.869 2.816-.329 6.29 3.145zM12.603 3.167c2.171 2.171 1.554 4.736-1.573 7.863s-5.692 3.744-7.863 1.573-2.34-5.523.787-8.649 6.477-2.958 8.649-.787z"/><path fill="#CAB8AC" d="M13.738 4.303c1.223 1.223 1.991 5.173-1.136 8.3s-7.076 2.359-8.3 1.136c-1.93-1.93 1.223-5.067 2.796-6.64s4.71-4.726 6.64-2.796z"/><path fill="#292F33" d="M9.457 6.312c.868.868.868 2.277 0 3.145s-2.277.868-3.145 0-.082-1.49.787-2.358 1.49-1.655 2.358-.787z"/><circle fill="#292F33" cx="4.74" cy="9.457" r="1.112"/><circle fill="#292F33" cx="9.457" cy="4.74" r="1.112"/><path fill="#A78E81" d="M10.655 10.401c-.426 0-.82-.101-1.132-.308-.189-.125-.241-.38-.116-.57.125-.19.38-.242.57-.116.452.299 1.339.188 2.019-.253.276-.179.906-.674.785-1.399-.037-.224.114-.436.338-.473.225-.036.436.114.473.338.139.836-.291 1.668-1.15 2.224-.565.368-1.205.557-1.787.557z"/><path fill="#A78E81" d="M7.931 13.619c-.103 0-.207-.009-.31-.026-.224-.038-.376-.249-.338-.473.038-.224.251-.375.473-.338.722.121 1.22-.509 1.399-.786.441-.681.553-1.568.253-2.019-.125-.189-.074-.444.116-.57.189-.126.445-.074.57.116.489.739.387 1.939-.249 2.92-.488.753-1.187 1.176-1.914 1.176z"/><path fill="#846659" d="M25.635 28.904c-1.021-1.634-1.501-3.563-.898-4.166.613-.613 2.073-.745 4.186.878-1.348-1.286-3.757-2.695-4.186-5.044.123 2.164-.419 4.625-4.125 4.043 2.082.614 5.023 4.289 5.023 4.289z"/><g fill="#67757F"><path d="M2.928 15.73c-.028 0-.057-.002-.086-.008-.264-.047-.44-.3-.393-.564.407-2.269 1.793-3.891 3.707-4.338.261-.06.523.102.584.363.061.262-.101.523-.363.584-1.524.356-2.634 1.689-2.971 3.564-.042.233-.246.399-.478.399z"/><path d="M5.072 15.974c-.253 0-.466-.195-.484-.451-.079-1.078.493-2.498 1.586-3.008.244-.113.533-.009.646.235.113.243.009.533-.235.646-.671.313-1.08 1.335-1.028 2.056.02.268-.181.501-.449.52-.013.002-.024.002-.036.002zm6.208-9.209c-.037 0-.074-.004-.111-.013-.262-.061-.424-.323-.363-.584.448-1.914 2.07-3.299 4.338-3.707.264-.047.517.129.564.393.047.264-.128.517-.393.564-1.875.337-3.207 1.447-3.564 2.971-.05.225-.25.376-.471.376z"/><path d="M12.944 6.877c-.069 0-.139-.015-.205-.046-.244-.113-.348-.403-.235-.646.51-1.093 1.919-1.664 3.008-1.586.268.019.469.253.449.52-.019.267-.248.468-.52.449-.712-.048-1.742.357-2.056 1.028-.083.177-.258.281-.441.281z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a7.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a7.svg new file mode 100644 index 0000000000000000000000000000000000000000..0382845585341d0bd4a284223729ea7adfacbc06 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E26000" d="M36 32c0-12-2-28-18-28S0 20 0 32h8v-5c0-1 1-1 1 0 0 7 4 6 4 6l2 2 1-1c0-.552 1.448-1 2-1s2 .448 2 1l1 1 2-2s4 1 4-6c0-1 1-1 1 0v5h8z"/><circle fill="#E26000" cx="18" cy="13.5" r="11.5"/><path fill="#D9B981" d="M32 31c-3 0-4 1-4 1v1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1v-1s-1-1-4-1zM4 31c-3 0-4 1-4 1v1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1c0 .552.448 1 1 1s1-.448 1-1v-1s-1-1-4-1z"/><path fill="#C45400" d="M6.5 19.607C6.5 25.051 14.167 27 18 27s11.5-1.949 11.5-7.393c0-2.366-.974-4.536-2.595-6.235.023-.244.04-.491.04-.747C26.944 7.862 24.9 4 18 4s-8.944 3.862-8.944 8.625c0 .256.017.503.04.747C7.474 15.071 6.5 17.241 6.5 19.607z"/><path fill="#D9B981" d="M8 17.571C8 22.305 14.667 24 18 24s10-1.695 10-6.429c0-2.057-.847-3.944-2.257-5.422.02-.212.035-.427.035-.65C25.778 7.358 24 4 18 4s-7.778 3.358-7.778 7.5c0 .223.015.438.035.65C8.847 13.627 8 15.514 8 17.571z"/><circle fill="#292F33" cx="16" cy="11" r="1"/><circle fill="#292F33" cx="20" cy="11" r="1"/><path fill="#FFE8B6" d="M12.67 11.073c-.042 0-.084-.005-.127-.016-.267-.07-.427-.343-.357-.61.488-1.867 2.405-2.988 4.271-2.503.267.07.427.343.357.61-.07.267-.343.424-.61.357-1.332-.347-2.702.455-3.05 1.788-.059.225-.262.374-.484.374zm10.66 0c-.223 0-.425-.149-.483-.374-.169-.646-.579-1.188-1.155-1.525-.576-.339-1.249-.432-1.896-.262-.269.069-.54-.091-.609-.357-.07-.268.09-.541.357-.61.901-.236 1.846-.106 2.653.367.807.473 1.381 1.231 1.616 2.136.07.267-.09.54-.357.61-.042.009-.085.015-.126.015z"/><path fill="#C09154" d="M13 5l2 3 1-1 2 3 2-3 1 1 2-3s-2-1-5-1-5 1-5 1z"/><path fill="#E26000" d="M13 5l2 2 1-2 2 3 2-3 1 2 2-2s-2-2-5-2-5 2-5 2z"/><circle fill="#C09154" cx="17.5" cy="13.5" r=".5"/><circle fill="#C09154" cx="18.5" cy="13.5" r=".5"/><path fill="#292F33" d="M18 21c-3.665 0-5.286-1.579-5.354-1.646-.195-.195-.195-.512 0-.707.195-.194.51-.195.705-.002C13.365 18.658 14.783 20 18 20c3.218 0 4.635-1.342 4.648-1.356.197-.191.514-.189.706.006.193.195.193.509-.001.703C23.286 19.421 21.665 21 18 21z"/><path fill="#D9B981" d="M17.295 33c-.235 2.224-5 4-6 2-.247-.494-2.341-4.936-2.535-5.453-.194-.517.068-1.094.586-1.287s1.094.068 1.287.586c-.194-.517.068-1.094.586-1.287.517-.194 1.094.068 1.287.586-.194-.517.068-1.094.586-1.287.517-.194 1.094.068 1.287.586-.194-.517.068-1.094.586-1.287s1.094.068 1.287.586c.193.514 1.148 5.263 1.043 6.257zm1.41 0c.235 2.224 5 4 6 2 .247-.494 2.341-4.936 2.535-5.453.194-.517-.068-1.094-.586-1.287s-1.094.068-1.287.586c.194-.517-.068-1.094-.586-1.287-.517-.194-1.094.068-1.287.586.194-.517-.068-1.094-.586-1.287-.517-.194-1.094.068-1.287.586.194-.517-.068-1.094-.586-1.287s-1.094.068-1.287.586c-.193.514-1.148 5.263-1.043 6.257z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9a9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a9.svg new file mode 100644 index 0000000000000000000000000000000000000000..aaa5cfa26d3860612165cda03c8a39afd2e3c487 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9a9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA596E" d="M22.903 27.55c1.218-.812 2.232-.783 3.073-.058-.435-1.131-2.348-3.624-2.348-3.624l-.725 3.682z"/><path fill="#F4ABBA" d="M22.949 27.679c-.03 0-.06-.002-.091-.006-.401-.05-.686-.415-.637-.816l.426-3.448c.023-.188.117-.358.264-.478l4.448-3.624-7.108-3.833c-.356-.192-.488-.636-.296-.992.193-.356.636-.489.992-.297l8.072 4.353c.214.116.357.332.381.575.023.244-.077.482-.267.636l-5.07 4.13-.39 3.156c-.044.373-.36.644-.724.644z"/><path fill="#E1E8ED" d="M5.38 3.523L1.476 7.427C.5 8.403.5 11.331.5 13.283s1.952 1.952 1.952 0 3.904-4.88 6.832-5.856S5.38 3.523 5.38 3.523z"/><path fill="#292F33" d="M1.476 7.427C.5 8.403.5 11.331.5 13.283s1.952 1.952 1.952 0c0-.671.461-1.456 1.184-2.238 1.383-1.495-2.16-.69-2.16-3.618z"/><path fill="#EA596E" d="M16.598 31.913c.522.87.478 2.283.283 3.087.957-.457 2.435-2.827 2.435-2.827l-2.718-.26z"/><path fill="#EA596E" d="M17.366 35.203c.928-.616 2.595-.573 3.58-.138.986.435-.681-2.529-.681-2.529l-2.435 1.507-.464 1.16z"/><path fill="#F4ABBA" d="M25.877 27.679c-.236 0-.469-.114-.61-.326l-1.952-2.928c-.224-.336-.133-.791.203-1.015.337-.224.791-.133 1.015.203l1.952 2.928c.224.336.133.791-.203 1.015-.125.083-.266.123-.405.123zm-5.857 4.88h-2.928c-.404 0-.732-.328-.732-.732s.328-.732.732-.732h2.196V16.211c0-.404.328-.732.732-.732s.732.328.732.732v15.616c0 .404-.328.732-.732.732z"/><path fill="#F4ABBA" d="M20.996 35.487c-.307 0-.592-.193-.695-.5l-.601-1.804-2.09 2.09c-.286.286-.749.286-1.035 0-.286-.286-.286-.749 0-1.035l2.928-2.928c.18-.18.443-.252.685-.194.247.058.446.24.527.48l.976 2.928c.128.384-.08.798-.463.926-.077.025-.156.037-.232.037z"/><circle fill="#EA596E" cx="8.308" cy="4.499" r="3.904"/><path fill="#EA596E" d="M12.579 20.716c-.573 0-1.14-.098-1.688-.3-2.025-.748-3.217-2.756-3.036-5.115.223-2.908 1.853-4.853 3.164-6.415 1.175-1.402 1.833-2.241 1.696-3.203-.163-1.143-.848-1.673-1.393-1.917-1.068-.477-2.506-.286-3.666.488L6.032 1.817C8.039.479 10.524.201 12.517 1.092c1.697.759 2.826 2.281 3.096 4.176.329 2.303-1.034 3.928-2.351 5.499-1.201 1.433-2.337 2.786-2.488 4.758-.081 1.051.342 1.852 1.131 2.144.858.315 2.341.04 3.68-1.792l2.364 1.727c-1.461 1.997-3.442 3.112-5.37 3.112z"/><path fill="#EA596E" d="M15.14 17.187c-2.166-3.248 0-7.808 2.928-9.76s10.736-2.928 15.616 4.88c5.401 8.641-2.763 4.433-4.88 3.904-7.808-1.952-11.712 3.904-13.664.976z"/><circle fill="#292F33" cx="6.356" cy="4.499" r=".976"/><path fill="#EA596E" d="M9.284 6.451c1.952-.976 4.255-.997 1.327 2.907-1.171 1.562 5.282-4.671 1.957-8.175-.536-.565-4.407-1.087-5.943-.174-.982.584 2.659 5.442 2.659 5.442z"/><circle fill="#EA596E" cx="28.804" cy="19.139" r=".976"/><circle fill="#EA596E" cx="20.02" cy="24.995" r=".976"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9ad.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ad.svg new file mode 100644 index 0000000000000000000000000000000000000000..6904e81a57331f971a8c497a5bcc1ec546706b91 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ad.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><g fill="#99AAB5"><path d="M3.016 5.201c-.062 0-.116-.043-.128-.105-.105-.555-.092-1.586.168-1.875.047-.053.129-.058.184-.01.053.048.058.13.01.184-.159.176-.216 1.072-.106 1.652.013.071-.033.139-.104.152-.008.002-.016.002-.024.002zm.517.9c-.057 0-.109-.038-.125-.096-.203-.74-.075-1.858-.008-2.097.019-.068.093-.107.16-.09.069.019.109.091.09.16-.069.246-.172 1.299.008 1.959.019.069-.022.141-.091.16-.011.003-.023.004-.034.004z"/><path d="M4.17 7.035c-.054 0-.105-.035-.123-.089-.45-1.338-.336-2.578-.331-2.63.007-.07.066-.121.142-.116.071.007.124.07.117.142-.001.012-.113 1.238.318 2.521.023.068-.014.142-.082.165-.013.005-.027.007-.041.007zm.87.931c-.05 0-.098-.029-.12-.079-.779-1.808-.767-3.11-.766-3.164.001-.071.059-.128.13-.128h.002c.072.001.129.06.128.132 0 .013-.011 1.305.745 3.059.028.066-.002.142-.068.171-.017.006-.034.009-.051.009z"/></g><path fill="#292F33" d="M7.708 16.15c-.002 2.273.264 7.198.191 7.812-.074.614-.588 1.462-1.51 1.562s-4.156.409-4.99.453-.651.443.198.538 4.364.221 5.254.265 1.967-.352 2.424-.868 1.872-2.953 2.367-3.985-.37-4.296-1.56-5.379-2.372-2.543-2.374-.398z"/><path fill="#66757F" d="M8.11 19.867c-.153-1.414-.339-5.618.171-4.463s1.666 4.203 1.097 7.238c-.115.613-.422 1.719-.684 2.352-.262.633-.751.882-1.518.91s-.575-.294.012-.467.967-.54 1.052-2.122c.07-1.295-.13-3.448-.13-3.448z"/><path fill="#99AAB5" d="M8.375 20.025c-.008.362.047 1.3.042 1.829s-.154 2.317-.353 2.773c-.199.457.334.213.458-.36.125-.573.516-2.418.528-2.885.012-.468-.654-2.323-.675-1.357z"/><path fill="#66757F" d="M2.85 1.802c.708-.674 1.726-.02 2.38.023.939.062 1.79-.263 3.018-.116s3.479.487 4.434 2.202c.787 1.415 1.852 3.802 2.682 4.979 1.019 1.445 2.753 3.657 3.875 4.803 1.206 1.232 4.908 2.917 6.094 3.118 2.351.399 6.989 1.903 8.042 5.612s1.328 5.824.563 6.513c-.765.689-1.571-.297-2.595-1.585-1.025-1.288-4.498-1.939-7.478-1.897s-8.146 1.437-11.177-.752c-3.034-2.19-4.614-6.029-5.104-9.706s-.205-4.92-.574-6.185C6.6 7.406 5.704 5.782 4.375 5.133S2.131 2.486 2.85 1.802z"/><path fill="#99AAB5" d="M2.85 1.802c.708-.674 1.726-.02 2.38.023.939.062 1.79-.263 3.018-.116s3.479.487 4.434 2.202c.787 1.415 1.852 3.802 2.682 4.979 1.019 1.445 2.753 3.657 3.875 4.803 1.206 1.232 4.908 2.917 6.094 3.118 2.351.399 6.989 1.903 8.042 5.612s1.328 5.824.563 6.513c-.765.689-1.158-.539-2.183-1.827-1.025-1.288-4.751-2.343-7.73-2.301s-8.188 1.199-11.22-.989c-3.034-2.19-4.73-5.144-5.22-8.821s-.205-4.92-.574-6.185c-.41-1.405-1.306-3.029-2.635-3.678S2.131 2.486 2.85 1.802z"/><path fill="#292F33" d="M15.746 19.496c-.933 1.551-1.064 3.557-1.218 4.784s-.098 2.076.517 2.618 1.714.754 2.466.816c.752.063 5.063.575 6.082.517s.714-.306-.047-.461-3.053-.967-3.58-1.566-.27-3.185-.324-4.158-.696-3.519-1.228-4.163c-.532-.643-1.951.422-2.668 1.613z"/><path fill="#66757F" d="M16.148 19.095c-.924 1.556-1.073 3.877-1.221 5.105-.147 1.228-.048 1.855.569 2.394s1.608.79 2.519.878c.751.073 3.179.372 4.367.43 1.02.05.436-.28-.326-.431-.762-.151-1.831-.548-2.361-1.144-.53-.595-.134-3.979-.193-4.952s-.473-3.228-1.008-3.869-1.636.394-2.346 1.589z"/><path fill="#99AAB5" d="M15.817 19.193c-.924 1.556-.411 2.811-.643 4.7-.15 1.228.116 2.225.586 2.548.676.464 1.421.779 2.331.867.751.073 2.026.341 3.213.399 1.02.05.603-.174-.159-.325-.762-.151-1.264-.485-1.795-1.081s.263-4.248.528-5.185c.562-1.988-.677-3.392-1.212-4.034s-2.139.916-2.849 2.111z"/><path fill="#292F33" d="M2.932 1.7c.567-.453 1.162-.032.464.416s-.936-.038-.464-.416zm.3 2.346s-.177-.773.274-.915c.451-.142 2.077.242 2.929 1.222 0 0-2.116-1.03-2.659-.878s-.544.571-.544.571z"/><path fill="#66757F" d="M11.228 3.835c.614.074 1.113.812.397.656-.716-.155-.397-.656-.397-.656z"/><path fill="#292F33" d="M7.584 2.037c.616.048.535.642.059.553-.475-.088-.812-.611-.059-.553zm25.477 25.458c1.51-.349 2.406 3.478 1.786 5.029-.63 1.575-2.047 1.961-3.222 2.137-.587.088-1.068.122-1.475-.043-.397-.161-.362-.509.09-.589.384-.067 1.006-.244 1.309-.356.35-.13.523-.437.523-.437s-1.84.665-3.083.379c-1.278-.293-.694-.811.417-.884.802-.053 1.698-.253 2.426-.845 0 0-.93.38-1.975.493-1.045.113-2.13.04-1.423-.662.144-.143 1.235-.286 1.906-.485.797-.238 1.448-.623 1.448-.623s-1.43.331-2.018.311c-.697-.023-.758-.423-.502-.552.531-.267 1.41-.367 1.929-.558.957-.352.348-1.965 1.864-2.315z"/><path d="M5.216 4.637c-.06 0-.113-.041-.127-.102-.213-.949-.958-1.66-.965-1.667-.052-.049-.055-.131-.005-.183s.131-.055.183-.006c.033.031.81.771 1.041 1.8.016.07-.028.14-.099.155-.009.002-.018.003-.028.003zm1.249.775c-.056 0-.107-.036-.124-.091-.377-1.214-1.404-2.154-1.415-2.164-.053-.048-.057-.13-.009-.184.049-.053.131-.056.184-.009.044.041 1.09.997 1.488 2.279.021.068-.017.142-.085.163-.013.004-.026.006-.039.006zm1.057.724c-.054 0-.104-.034-.123-.087-.524-1.521-1.584-2.511-1.595-2.521-.053-.049-.055-.131-.007-.184.05-.053.131-.056.184-.008.045.042 1.118 1.042 1.665 2.627.023.068-.013.142-.081.166-.014.005-.028.007-.043.007zm1.194 1.34c-.057 0-.109-.038-.125-.095-.521-1.892-1.608-3.114-1.62-3.126-.048-.053-.044-.135.01-.184.053-.048.134-.044.184.01.045.05 1.138 1.276 1.677 3.231.019.069-.021.141-.091.16-.012.003-.023.004-.035.004z" fill="#CCD6DD"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9c1.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c1.svg new file mode 100644 index 0000000000000000000000000000000000000000..1f966c363b0f5f3a87a64c48ef00991af86a8f6b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BBDDF5" d="M5 21.875s1.589 5.727 2 8.482c.464 3.111 3.571 5.571 11 5.571s10.536-2.461 11-5.571c.411-2.755 2-8.482 2-8.482H5z"/><path fill="#662113" d="M5.094 21.969c.25 1.219.694 1.994 1.344 1.594.65-.4 1.65-.193 1.344.625-.281.75.969 1.094 1.5.656.509-.419 1.555-.881 1.656.062.094.875 1.168 1.11 1.656.469.5-.656 1.875-.394 2.125.406s1.594.688 1.969.125c.355-.533.713-.885 1.312-.885V25c.6 0 .957.373 1.312.906.375.562 1.719.675 1.969-.125s1.625-1.062 2.125-.406c.489.641 1.562.406 1.656-.469.101-.943 1.147-.482 1.656-.062.531.438 1.781.094 1.5-.656-.307-.818.694-1.025 1.344-.625.65.4 1.094-.375 1.344-1.594H5.094z"/><path fill="#C1694F" d="M33 18.969c0-4.919-6.731-8.906-15.033-8.906-8.303 0-15.033 3.987-15.033 8.906 0 3.969 9 6.031 15.033 6.031S33 23 33 18.969z"/><path d="M18 35.5c-.276 0-.5-.224-.5-.5v-8.646c0-.276.224-.5.5-.5s.5.224.5.5V35c0 .276-.224.5-.5.5zm-6.699-1.268c-.248 0-.463-.184-.496-.436l-1.031-7.982c-.035-.274.158-.525.432-.561.272-.041.524.158.56.432l1.031 7.982c.035.274-.158.525-.432.561-.021.003-.043.004-.064.004zm3.179.976c-.257 0-.476-.197-.498-.459l-.708-8.521c-.023-.274.182-.517.457-.539.283-.022.517.182.54.457l.708 8.521c.023.274-.182.517-.457.539l-.042.002zm-5.959-3.041c-.175 0-.331-.123-.367-.301l-1.5-7.438c-.041-.203.09-.4.293-.441.198-.048.4.09.442.293l1.5 7.438c.041.203-.09.4-.293.441-.026.006-.051.008-.075.008zm16.1 1.952c-.024 0-.048-.002-.072-.005-.273-.039-.463-.293-.424-.566l1.13-7.869c.039-.274.296-.456.566-.424.273.039.463.293.424.566l-1.13 7.869c-.036.249-.25.429-.494.429zm-3.042 1.089l-.042-.002c-.275-.022-.48-.265-.457-.539l.708-8.521c.022-.276.292-.474.539-.457.275.022.48.265.457.539l-.708 8.521c-.021.262-.24.459-.497.459zm5.983-3c-.023 0-.047-.002-.07-.007-.204-.039-.337-.235-.298-.438l1.438-7.479c.039-.203.241-.337.438-.298.204.039.337.235.298.438l-1.438 7.479c-.034.18-.191.305-.368.305z" fill="#88C9F9"/><path fill="#FFE8B6" d="M16.912-.011s1.087 1.144 2.175 1.167c2.268.049 4.355 1.315 4.355 3.506 0 0 5.261 0 5.443 4.674 0 0 2.655.045 3.263 4.672.454 3.456-3.038 8.227-14.148 8.178-9.795-.043-14.806-3.524-14.148-8.176.634-4.48 4.354-4.673 4.354-4.673s-.636-5.843 6.529-5.842c0 0 .726-2.337 2.177-3.506z"/><path fill="#FFCC4D" d="M17.91 10.504c2.936-1.108 5.623-3.115 5.533-5.841 0-.858-.327-1.568-.852-2.125.643 2.808-3.651 6-8.399 6.506-5.941.633-5.261-2.872-5.261-2.872l-.007.007c-.883 1.536-.717 3.159-.717 3.159.905 2.383 5.576 2.724 9.703 1.166z"/><path fill="#FFCC4D" d="M28.885 9.337c-.006-.143-.03-.268-.045-.402-.116-.677-.453-1.506-.774-2.138-.19-.265-.4-.499-.63-.702 1.109 4.426-5.563 9.749-11.93 10.982-8.299 1.606-11.654-3.065-11.654-3.065-.342 2.415.858 4.509 3.449 5.976 10.227 4.169 21.673-6.095 21.584-10.651z"/><path fill="#DD2E44" d="M8.689 14.201l-1.181 1.614c-.325.444-.954.541-1.398.216-.444-.325-.541-.954-.216-1.398l1.181-1.614c.325-.444.954-.541 1.398-.216.444.325.541.954.216 1.398z"/><path fill="#55ACEE" d="M14.935 8.187l-1.956-.419c-.538-.115-.884-.65-.768-1.187.115-.538.65-.884 1.187-.768l1.956.419c.538.115.884.65.768 1.187-.115.538-.649.884-1.187.768z"/><path fill="#77B255" d="M16.431 14.173l1.313 1.509c.361.415.317 1.05-.098 1.411-.415.361-1.05.317-1.411-.098l-1.313-1.509c-.361-.415-.317-1.05.098-1.411.415-.361 1.05-.317 1.411.098z"/><path fill="#F4900C" d="M24.372 11.499l-1.871.707c-.515.194-1.095-.068-1.289-.582-.194-.515.068-1.095.582-1.289l1.871-.707c.515-.194 1.095.068 1.289.582.195.514-.067 1.094-.582 1.289z"/><path fill="#AA8DD8" d="M30.366 14.051l-1 1.732c-.275.476-.89.641-1.366.366-.476-.275-.641-.89-.366-1.366l1-1.732c.275-.476.89-.641 1.366-.366.476.275.641.889.366 1.366z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9c3.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c3.svg new file mode 100644 index 0000000000000000000000000000000000000000..51a3f26d4d9d55445ff207a41e7cc33684191cb6 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E3A919" d="M28.337 32.563l-2.579 3.082c-.552.553-1.758.007-1.758-.545V12.001c0-.552 2.372-4.501 5-4.501l-.028 23.007c0 1.134-.093 1.308-.635 2.056z"/><path fill="#FFD983" d="M26 10.454H9l.194-.348L12.74 7.5c.486-.379.831-.5 1.383-.5h14.363c.188 0 .514.277.344.47L26 10.454z"/><path fill="#FFCC4D" d="M25 36H10c-.552 0-1-.448-1-1V10.454S9.448 10 10 10h15c.552 0 1 .454 1 .454V35c0 .552-.448 1-1 1z"/><circle fill="#F4900C" cx="15" cy="27" r="3"/><circle fill="#EA596E" cx="15" cy="21" r="4"/><circle fill="#FFE8B6" cx="19.5" cy="23.5" r="4.5"/><circle fill="#FFCC4D" cx="19.5" cy="23.5" r="2.5"/><path fill="#CCD6DD" d="M22.999 8.464s-.21.431-.967.431-1.033-.431-1.033-.431V4.342c0-1.993.532-3.309 1.582-3.911 1.005-.576 2.326-.398 3.922.535 1.274.743 4.421 2.972 4.496 3.034 0 0 .165.565-.303 1.1-.468.535-.965.447-.965.447-.018-.014-3.101-2.191-4.236-2.855-.881-.515-1.584-.623-1.904-.436-.279.16-.592.726-.592 2.086v4.122z"/><path fill="#99AAB5" d="M25.434.44c-1.124-.446-2.082-.451-2.853-.01-.791.454-1.287 1.314-1.484 2.562l1.975.367c.108-.664.322-.989.52-1.103.22-.129.63-.105 1.146.082L25.434.44z"/><path fill="#FFE8B6" d="M25.931 11H9.5c-.275 0-.5-.225-.5-.5s.225-.5.5-.5h16.431c.275 0 .5.225.5.5s-.225.5-.5.5z"/><path fill="#FFE8B6" d="M28.908 7.796l-2.536 3.036c-.163.201-.471.223-.684.05-.214-.173-.255-.479-.093-.68l2.536-3.036c.163-.201.471-.223.684-.05.214.174.255.479.093.68z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9c5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c5.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab68cb1d6c1974807854ef97830ea12dc3318b90 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D39954" d="M26.617 32.441c-.02-.039-.373-.678-1.025-1.172.103-.421.056-.835-.307-1.103-.9-.662-8.82.226-9.386 3.057-.234 1.171.588 1.171 1.038.809-.137.499-.212 1.011-.169 1.49.024.269.261.467.531.444.029-.002.057-.007.084-.015.225-.06.381-.275.36-.516-.03-.334.022-.694.111-1.051.201.18.424.327.686.269.312-.07.51-.378.64-.712.015.212.046.348.05.363.069.259.333.411.593.345l.006-.002c.257-.069.411-.333.348-.591-.004-.017-.051-.229-.019-.565.442.267 1 .509 1.457.398.581-.142.859-.631.997-1.113.439.412.698.895.958 1.454.101.219.344.327.569.267.028-.007.054-.016.08-.029.246-.113.352-.405.238-.65-.185-.399-.414-.88-.793-1.348.346.231.711.393.95.253.166-.097.364-.302.545-.553.377.336.589.721.592.727.11.204.344.3.559.242.035-.009.069-.023.103-.04.239-.126.33-.419.204-.658z"/><path fill="#EDD6A6" d="M21.708 6.32c-2.741-.932-5.978-3.134-6.754-6.03-.273-1.02-.952 1.29-1.891 1.541-.939.252-2.682-1.409-2.408-.389.776 2.896-.926 6.422-2.834 8.599-3.575 4.08-6.287 8.95-4.89 14.165 2 7.465 10.1 10.746 18.41 8.519s13.684-9.118 11.684-16.582c-1.398-5.215-6.182-8.077-11.317-9.823z"/><path fill="#E2A759" d="M13.66 32.585c-3.296-1.993-7.838-5.273-8.227-11.23-.425-6.519 4.936-10.098 5.304-13.826.444 4.428-3.559 7.236-3.214 12.866.313 5.101 2.429 8.841 6.137 12.19z"/><path fill="#E2A759" d="M19.764 32.885c-3.097-1.934-6.932-5.916-7.944-11.203-1.457-7.611 1.103-12.145.203-17.89 1.897 6.644 1.034 9.757 2.302 16.336.825 4.282 2.9 10.213 5.439 12.757zm8.158-4.121c1.858-3.374 4.302-8.526 1.66-13.88-2.891-5.858-9.474-6.237-11.657-9.281 1.829 4.057 6.85 4.447 9.367 9.495 2.28 4.574 2.166 8.912.63 13.666z"/><path fill="#E2A759" d="M22.786 32.076c1.715-3.223 3.045-8.589 1.278-13.674-2.543-7.32-7.027-9.966-9.121-15.392 1.679 6.703 3.983 8.966 6.174 15.298 1.427 4.12 2.596 10.295 1.669 13.768z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9c7.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c7.svg new file mode 100644 index 0000000000000000000000000000000000000000..cc92a9d18792e401ac27f8024a4c5f8a6e292f16 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c7.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#939598" cx="18" cy="26" rx="18" ry="10"/><ellipse fill="#CCD6DD" cx="18" cy="24" rx="18" ry="10"/><path fill="#F4900C" d="M15.714 32.54L2.575 24.857c-1.262-.738-.929-3.558-.929-4.785l14.069-6.657c1.262-.738 3.308-.738 4.57 0L34.37 20.26c0 1.689.316 3.859-.947 4.597L20.285 32.54c-1.262.738-3.309.738-4.571 0z"/><path fill="#FFAC33" d="M15.714 29.279L2.575 21.596c-1.262-.738-1.262-1.934 0-2.672l13.139-7.683c1.262-.738 3.308-.738 4.57 0l13.139 7.683c1.262.738 1.262 1.934 0 2.672l-13.139 7.683c-1.261.738-3.308.738-4.57 0z"/><path d="M17.463 14.416l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.778.174-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.777.174-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.777.174-1.074 0zm3.758 2.198l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.778.173-1.074 0zm-15.03-4.395l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.777.174-1.074 0zm3.758 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.778.174-1.074 0zm3.757 2.198l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.777.173-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.777.173-1.074 0zM9.948 18.81l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.174-.778.174-1.074 0zm3.757 2.198l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.777.173-1.074 0zm3.758 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.778.173-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.777.173-1.074 0zM6.191 21.008l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.778.173-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.778.173-1.074 0zm3.757 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.777.173-1.074 0zm3.758 2.197l-1.61-.942c-.296-.173-.296-.454 0-.628l1.61-.942c.296-.173.777-.173 1.074 0l1.61.942c.296.173.296.454 0 .628l-1.61.942c-.297.173-.778.173-1.074 0z" fill="#F4900C"/><path fill="#D3790D" d="M15.72 16.354c-3.406-1.039-4.841-.515-4.618 2.165.058.693-.895 1.847-1.847 2.511-2.215 1.544-1.263 4.124 2.54 2.222 1.905-.952 4.682-.887 8.052.144 2.828.866 4.589 2.05 4.82 3.32 1.122-.367 1.732-.847 2.28-1.309-.233-.526-1.27-2.04-2.915-2.761-3.112-1.365-.106-3.331 2.222-3.81 2.107-.433.029-2.02-3.175-1.963-3.202.058-2.397.995-7.359-.519z"/><path opacity=".5" fill="#D3790D" d="M24.668 26.542c0 .456.058.468.058 1.387 0 1.789 2.194 1.472 2.194-1.501 0-.346.029-1.021.029-1.021l-2.281 1.135z"/><path fill="#FFAC33" d="M22.16 17.651c.46.262.461 1.863 0 2.125l-3.328 1.897c-.46.262-1.204.262-1.664 0l-3.329-1.897c-.46-.262-.46-1.863 0-2.125l3.329-.721c.46-.262 1.204-.262 1.664 0l3.328.721z"/><path fill="#FFD983" d="M22.16 17.651c.46.262.461.686 0 .948l-3.328 1.897c-.46.262-1.204.262-1.664 0l-3.329-1.897c-.46-.262-.46-.686 0-.948l3.329-1.897c.46-.262 1.204-.262 1.664 0l3.328 1.897z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9c9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c9.svg new file mode 100644 index 0000000000000000000000000000000000000000..16b0db823d27a90e50bce77d099b018abbafce8c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9c9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#8A4B38" d="M26.875 14.6C25.1 12.778 21.55 12.778 18 12.778s-7.1 0-8.875 1.822c-2.663 2.733-5.325 9.72-3.55 15.186C7.35 35.252 15.132 35.814 18 35.814s10.65-.562 12.425-6.028c1.775-5.465-.887-12.453-3.55-15.186z"/><path fill="#A5503C" d="M25.58 14.412c-1.516-1.556-4.548-1.556-7.58-1.556s-6.064 0-7.58 1.556c-2.274 2.334-4.548 8.302-3.032 12.969C8.904 32.049 15.55 32.529 18 32.529s9.096-.48 10.611-5.148c1.516-4.668-.757-10.635-3.031-12.969z"/><path fill="#CCD6DD" d="M27.453 13.025c-.383-1.616-2.263-3.17-9.437-3.17h-.032c-7.175 0-9.055 1.554-9.437 3.17-.733 3.093 2.263 4.278 9.437 4.278h.032c7.174-.001 10.17-1.185 9.437-4.278z"/><path fill="#66757F" d="M25.622 12.355c.293.72-1.832 1.658-7.64 1.658s-7.938-.941-7.64-1.658c.323-.779 3.869-1.55 7.64-1.55 3.771 0 7.324.771 7.64 1.55z"/><path fill="#77B255" d="M10.993 13.144c1.015.473 3.226.869 6.99.869 3.767 0 5.976-.395 6.99-.869-.734-.635-2.76-1.27-6.99-1.27-4.23.001-6.256.635-6.99 1.27z"/><path fill="#FFF" d="M25 14.231c-.156-.424-.429-.393-.814-.276-1.779.537-4.36.641-6.211.652-1.851-.011-4.676-.162-6.211-.652-.384-.122-.701-.172-.862.276-.156.436.306.852.697.947 2.366.576 4.313.746 6.376.759 2.062-.013 3.765-.159 6.131-.735.392-.096 1.075-.476.894-.971z"/><path fill="#CCD6DD" d="M22.894 13.686l5.315-7.93 5.296-3.743s.141-.297-.78-1.01C31.804.29 31.388.587 31.388.587L26.84 4.204 20.348 13.9c.994-.051 1.839-.124 2.546-.214z"/><path fill="#99AAB5" d="M22.894 13.686l5.315-7.93 5.296-3.743-.067-.089-5.792 3.208-5.8 8.674c.431-.034.635-.06 1.048-.12z"/><circle fill="#99AAB5" cx="27.617" cy="4.945" r="1.668"/><path fill="#CCD6DD" d="M26.213 4.639c0-.697.565-1.262 1.262-1.262s1.262.565 1.262 1.262-.565 1.262-1.262 1.262-1.262-.565-1.262-1.262z"/><path fill="#E1E8ED" d="M11.459 10.865c1.604-.639 4.544-.802 5.569-.757 1.025.045.571.757-.015.757-1.693 0-3.787.401-5.228.772-.851.219-1.143-.447-.326-.772z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9d9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9d9.svg new file mode 100644 index 0000000000000000000000000000000000000000..553708315577b9c93cbd987046a6f0fdeb1be70b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9d9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#C63900" cx="18" cy="19.024" rx="15" ry="3.529"/><path fill="#FA743E" d="M26.276 28.276h-16c-2.486 0-4.774 1.443-5.762 3.449-.368-.415-.907-.619-1.514-.619-1.1 0-2 .935-2 1.998V36h31v-1.931c0-3.199-2.411-5.793-5.724-5.793z"/><path fill="#FFDC5D" d="M14 25v3.234c0 .004.011.007.015.011.132.237 3.737 6.739 3.989 6.739.253 0 3.854-6.502 3.985-6.739.004-.004.01-.007.01-.011V25H14z"/><path fill="#F9CA55" d="M14 27.598c1.115 1.259 2.497 1.6 4 1.6 1.502 0 2.884-.342 4-1.6v-3.2h-8v3.2z"/><path fill="#D1D3D4" d="M17.982 13.557c-2.61 0-5.654 3.198-9.115 3.885.143 1.499.597 2.619.802 4.127.337 2.477 1.73 3.27 2.843 3.601 1.602 2.116 3.305 2.026 6.164 2.026 5.483 0 8.14-3.609 8.457-9.747-3.476-.692-6.532-3.892-9.151-3.892z"/><path fill="#FFDC5D" d="M24.315 17.386c-.54-.748-1.232-1.35-2.748-1.564.569.261 1.114 1.161 1.185 1.658.071.498.142.9-.308.403-1.803-1.993-3.767-1.208-5.714-2.426-1.359-.851-1.773-1.791-1.773-1.791s-.166 1.256-2.227 2.535c-.598.371-1.31 1.197-1.706 2.417-.284.877-.196 1.659-.196 2.995 0 3.9 3.214 7.179 7.179 7.179s7.179-3.308 7.179-7.179c-.001-2.426-.255-3.374-.871-4.227z"/><path fill="#C1694F" d="M18.798 23.607h-1.595c-.22 0-.399-.178-.399-.399 0-.22.178-.399.399-.399h1.595c.22 0 .399.178.399.399-.001.221-.179.399-.399.399z"/><path fill="#662113" d="M14.809 20.815c-.441 0-.798-.357-.798-.798v-.797c0-.44.357-.798.798-.798.44 0 .798.357.798.798v.798c0 .44-.357.797-.798.797zm6.382 0c-.44 0-.798-.357-.798-.798v-.797c0-.44.357-.798.798-.798.44 0 .798.357.798.798v.798c-.001.44-.358.797-.798.797z"/><path fill="#C1694F" d="M17.997 26.465c-2.359 0-3.084-.604-3.204-.726-.22-.219-.22-.575 0-.794.212-.212.552-.218.773-.02.044.032.617.417 2.431.417 1.886 0 2.429-.416 2.435-.42.219-.218.564-.208.783.013.219.219.207.585-.012.804-.123.122-.847.726-3.206.726"/><path fill="#FA743E" d="M25.765 15.157C24.537 12.47 18.793 0 18 0s-6.537 12.47-7.765 15.157C5.415 16.001 3 17.595 3 19c6-2 11-2.443 15-2.443S27 17 33 19c0-1.405-2.415-2.999-7.235-3.843z"/><path fill="#D99E82" d="M5 36H3V11.862L2 8h4l-1 3.862z"/><circle fill="#55ACEE" cx="4" cy="6" r="3"/><circle fill="#B0F0FF" cx="3.5" cy="5.5" r="1.5"/><path fill="#FFDC5D" d="M7 30.5C7 32.433 5.657 34 4 34s-3-1.567-3-3.5S2.343 28 4 28s3 .567 3 2.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9da.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9da.svg new file mode 100644 index 0000000000000000000000000000000000000000..5c9ea3625c0a9656c0e985dfb2228e6af7f16de9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9da.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ABDFFF" d="M20.769 20.273c-4.558 6.089-5.676 12.675-2.497 14.71 3.179 2.035 9.451-1.252 14.008-7.341 4.558-6.089 2.752-17.029 2.497-16.631-1.777 2.774-9.45 3.173-14.008 9.262z"/><path fill="#ABDFFF" d="M15.255 20.273c4.558 6.089 5.676 12.675 2.498 14.71-3.179 2.035-9.451-1.252-14.009-7.341S.904 10.673 1.247 11.011C5 14.71 10.698 14.184 15.255 20.273z"/><path fill="#55ACEE" d="M4.598 17.829c-.484-.808-1.158-1.652-.776-.211.542 2.047 2.184 5.253 4.848 7.268 1.12.847 1.209-.427.179-1.398-2.665-2.512-3.291-4.055-4.251-5.659zm26.804 0c-.96 1.604-1.586 3.147-4.251 5.659-1.03.971-.941 2.245.179 1.398 2.664-2.015 4.306-5.221 4.848-7.268.382-1.441-.292-.597-.776.211z"/><path fill="#FFDC5D" d="M31 36v-3.5c0-3.314-3.685-5.5-7-5.5H12c-3.313 0-7 2.186-7 5.5V36h26z"/><path fill="#FFDC5D" d="M14 20.059v8c0 2.209 1.791 4 4 4s4-1.791 4-4v-8h-8z"/><path fill="#F9CA55" d="M14 24.971c1.115 1.26 2.497 1.6 3.999 1.6 1.503 0 2.886-.341 4.001-1.6V21.77h-8v3.201z"/><path fill="#FA743E" d="M25 27h-3s-.938 6-4 6-4-6-4-6h-3c-3 0-4 1-4 1s2 2 2 5v3h18v-3c0-2.983 2-5 2-5s-1-1-4-1z"/><path fill="#FFAC33" d="M21.532 2.731c-1.893-.613-6.348-.445-7.461 1.002-2.895.056-6.292 2.673-6.737 6.125-.441 3.417.541 5.003.891 7.573.396 2.911 2.032 3.842 3.341 4.232 1.882 2.487 3.883 2.38 7.243 2.38 6.561 0 9.686-4.39 9.962-11.846.167-4.51-2.479-7.926-7.239-9.466z"/><path fill="#FFDC5D" d="M25.421 12.515c-.635-.879-1.448-1.587-3.229-1.837.668.306 1.308 1.364 1.392 1.949.084.585.167 1.058-.362.473-2.119-2.342-4.427-1.42-6.714-2.851-1.597-.999-2.084-2.105-2.084-2.105s-.195 1.475-2.617 2.979c-.702.436-1.54 1.406-2.005 2.84-.334 1.03-.23 1.949-.23 3.519 0 4.583 3.777 8.436 8.436 8.436s8.436-3.887 8.436-8.436c-.001-2.851-.299-3.964-1.023-4.967z"/><path fill="#C1694F" d="M21.749 22.168h-7.498s.937 1.875 3.749 1.875 3.749-1.875 3.749-1.875zm-2.812-2.343h-1.875c-.259 0-.469-.21-.469-.469s.21-.469.469-.469h1.875c.259 0 .469.21.469.469 0 .26-.21.469-.469.469z"/><path fill="#662113" d="M14.251 16.545c-.518 0-.937-.42-.937-.937v-.938c0-.518.42-.937.937-.937.518 0 .937.42.937.937v.937c0 .518-.42.938-.937.938zm7.498 0c-.518 0-.937-.42-.937-.937v-.938c0-.518.42-.937.937-.937.518 0 .937.42.937.937v.937c0 .518-.419.938-.937.938z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9dc.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9dc.svg new file mode 100644 index 0000000000000000000000000000000000000000..52f120c41f499f2bd737ae864a76947a9b48ce21 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9dc.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFDC5D" d="M7.399 17.278c-1.878 1.035-3.24 2.455-3.336 2.617-.239.404-.437 1.592-.276 2.415.145.741.177 2.238.66 2.915.198.277.107.759-.032 1.208-.419 1.353.306 3.199-.145 2.882-.918-.644-1.074-1.83-1.047-2.528.015-.393-.166-.884-.257-1.138-.059-.16-1.245-3.203-1.518-4.54-.148-.722-.333-1.302.275-2.155.903-1.266 2.094-2.996 3.311-3.885 2.012-1.471 3.936-1.687 3.936-1.687s-.911 3.532-1.571 3.896zm23-6.626c-.084.009-.143.102-.203.238-.023-.164-.074-.276-.184-.264-.129.013-.201.22-.304.492-.027-.047-.062-.079-.117-.078-.261.009-.349.811-.909 1.334-.081.036-.154.078-.248.104-.059.016-.098.041-.146.061.005-.255.171-.405.271-.474.239-.166.089-.586-.314-.331-.289.183-.41.365-.501.55-.255.519-.354 1.058-.333 1.487l-.119.215c-.139.242-1.626 1.17-2.696 1.967-1.066.793-1.846 1.694-2.415 1.132-.396-.391-1.591-1.706-3.322-2.833-1.093-.712-2.733-.866-2.733-.866-.807.662.166 3.109.894 3.566.938.589 4.26 2.925 5.306 3.391s1.704-.161 2.196-.609c.403-.366 3.434-4.072 3.703-4.326.365-.344 1.063-.797 1.457-1.491.338-.596.543-1.079.667-1.855.071-.456.402-1.447.05-1.41z"/><path fill="#FFDC5D" d="M16.125 13.384s-2.26-.137-3.764-.137-2.959.1-3.392.137l-1.963 3.619.526.283s1.209 4.354 1.209 5.202c0 .848-1.209 5.202-1.209 5.202h9.674s-1.209-4.075-1.209-5.202 1.209-5.202 1.209-5.202l.495-.266-1.576-3.636z"/><path fill="#FF5540" d="M8.969 13.384l-1.437 3.902.983 6.288 7.697.327.994-6.615-1.081-3.902s-.857-.176-3.562-.176-3.594.176-3.594.176z"/><path fill="#316116" d="M28.744 25.545c1.738-2.783-.967-7.196-.967-7.196-.067.534-.348 1.714-.348 1.714-.163.998-.678 2.566-2.219 4.469-1.049 1.294 4.467 5.504 5.708 4.687 1.937-1.276 1.587-3.432 3.655-5.726.367-.407.8-.817 1.346-1.228-3.575-.319-7.175 3.28-7.175 3.28zm-3.123 3.078c-4.478 3.618-9.355 2.292-10.385 1.38l-7.644-5.978c-5.516 0-4.48 7.846 1.132 10.349 9.576 4.271 17.103-1.423 18.399-4.18l-1.502-1.571z"/><path fill="#66A644" d="M27.814 26.878c1.408-2.155.357-5.346-.385-6.815-.163.998-.843 2.383-2.384 4.286-1.049 1.294-.483 3.302-.021 4.199l.001.001c-3.596 2.842-7.065 2.264-8.825 1.464 1.17-.542 1.986-1.7 1.986-3.053 0-1.87-1.547-3.385-3.454-3.385h-7.14c-5.516 0-4.48 7.39 1.132 9.843 9.165 4.007 17-.67 18.793-3.448.863.096 2.363.056 3.573-.741 1.937-1.276 1.414-3.441 3.482-5.734-3.483.249-6.758 3.383-6.758 3.383z"/><path fill="#316116" d="M16.212 30.014c-2.309-.46-6.994-2.625-7.193-2.717-.194-.09-.278-.319-.188-.512.09-.195.321-.28.513-.188.048.022 5.488 2.428 7.707 2.869 0 0-.158.133-.336.267-.179.132-.503.281-.503.281z"/><path fill="#FFDC5D" d="M10.63 9.387v3.714c0 1.026.831 3.61 1.857 3.61s1.857-2.584 1.857-3.61V9.387H10.63z"/><path fill="#F9CA55" d="M10.63 12.825c.517.585 1.159.743 1.857.743.697 0 1.339-.159 1.857-.743v-1.486H10.63v1.486z"/><path fill="#744EAA" d="M14.509.429c-1.043-.338-3.498-.246-4.112.552-1.596.031-3.467 1.473-3.713 3.376-.243 1.883.298 2.757.491 4.173.218 1.604 1.12 2.117 1.841 2.332 1.037 1.371 2.14 1.312 3.992 1.312 3.616 0 5.338-2.419 5.49-6.529.093-2.485-1.366-4.367-3.989-5.216z"/><path fill="#FFDC5D" d="M16.577 5.821c-.35-.484-.798-.875-1.78-1.013.368.169.721.752.767 1.074.046.322.092.583-.199.261-1.168-1.291-2.44-.783-3.7-1.571-.88-.551-1.148-1.16-1.148-1.16s-.107.813-1.442 1.642c-.387.24-.849.775-1.105 1.565-.185.568-.128 1.074-.128 1.939 0 2.526 2.081 4.649 4.649 4.649s4.649-2.142 4.649-4.649c.001-1.571-.164-2.184-.563-2.737z"/><path fill="#C1694F" d="M14.558 11.141h-4.132s.517 1.033 2.066 1.033 2.066-1.033 2.066-1.033zm-1.55-1.291h-1.033c-.143 0-.258-.116-.258-.258s.116-.258.258-.258h1.033c.143 0 .258.116.258.258s-.115.258-.258.258z"/><path fill="#662113" d="M10.425 8.042c-.285 0-.517-.231-.517-.517v-.516c0-.285.231-.517.517-.517.285 0 .517.231.517.517v.517c0 .285-.231.516-.517.516zm4.133 0c-.285 0-.517-.231-.517-.517v-.516c0-.285.231-.517.517-.517s.517.231.517.517v.517c-.001.285-.232.516-.517.516z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9e0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e0.svg new file mode 100644 index 0000000000000000000000000000000000000000..653427da92a853e135c5830d3e0596a731c349d9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EA596E" d="M29.896 26.667c.003.283-.07.653-.146.958-.531 2.145-2.889 4.552-6.208 4.333-3.008-.198-5.458-1.642-5.458-3.667s2.444-3.667 5.458-3.667 6.335.018 6.354 2.043z"/><path fill="#DD2E44" d="M23.542 24.964c-1.619 0-5.314.448-6.162.448-1.498 0-2.713.94-2.713 2.1 0 .558.286 1.062.744 1.438 0 0 1.006 1.009 2.818.525.793-.212 2.083-1.786 4.354-2.036 1.131-.125 3.25.75 6.974.771.16-.344.193-.583.193-.583 0-2.027-3.194-2.663-6.208-2.663z"/><path fill="#F4ABBA" d="M29.75 27.625s2.184-.443 3.542-2.229c1.583-2.083 1.375-4.312 1.375-4.312 1.604-3-.5-5.813-.5-5.813C33.958 12.104 32 10.792 32 10.792c-1.271-3.021-4.083-3.833-4.083-3.833-2.208-2.583-6.125-2.5-6.125-2.5s-3.67-1.345-8.708.167c-.833.25-3.625.833-5.667 2.083C.981 10.649.494 16.793.584 17.792 1.083 23.375 5 24.375 7.5 24.958c.583 1.583 2.729 4.5 6.583 3.417 4.75-.833 6.75-2.25 7.917-2.25s4.417 1.25 7.75 1.5z"/><g fill="#EA596E"><path d="M17.737 18.648c2.328-1.255 3.59-1.138 4.704-1.037.354.032.689.057 1.028.055 1.984-.045 3.591-.881 4.302-1.69.182-.208.161-.523-.046-.706-.206-.182-.521-.163-.706.045-.548.624-1.899 1.313-3.573 1.351-.3.009-.601-.021-.913-.05-1.195-.111-2.679-.247-5.271 1.152-.665.359-1.577.492-2.565.592-2.197-3.171-.875-5.933-.497-6.591.037.002.073.014.111.014.4 0 .802-.098 1.166-.304.24-.136.325-.441.189-.681s-.441-.325-.681-.189c-.64.362-1.482.153-1.88-.467-.149-.233-.458-.301-.69-.151-.232.149-.3.458-.151.69.237.371.571.65.948.837-.521 1.058-1.51 3.84.372 6.951-1.324.13-2.65.317-3.688.986-.67.432-1.355 1.064-1.878 1.791-.629-.108-2.932-.675-3.334-3.231.25-.194.452-.45.577-.766.102-.257-.024-.547-.281-.649s-.547.024-.649.281c-.089.225-.25.389-.454.461-.202.072-.431.048-.643-.07-.243-.135-.546-.046-.68.194-.134.241-.047.546.194.68.284.158.588.238.89.238.037 0 .072-.017.109-.019.476 2.413 2.383 3.473 3.732 3.794-.176.388-.295.788-.331 1.192-.024.274.179.518.454.542l.045.002c.256 0 .475-.195.498-.456.108-1.213 1.265-2.48 2.293-3.145.964-.621 2.375-.752 3.741-.879 1.325-.121 2.577-.237 3.558-.767zm12.866-1.504c-.131.242-.041.546.2.677.076.042.159.062.24.062.176 0 .347-.093.438-.259.019-.034 1.842-3.449-1.571-5.744-.228-.152-.539-.093-.694.136-.154.229-.093.54.136.694 2.644 1.778 1.309 4.326 1.251 4.434zM9.876 9.07c.156 0 .309-.072.406-.208 1.45-2.017 3.458-1.327 3.543-1.295.259.094.544-.038.64-.296.096-.259-.036-.546-.295-.642-.96-.356-3.177-.468-4.7 1.65-.161.223-.11.536.114.697.089.064.191.094.292.094zm13.072-1.888c2.225-.181 3.237 1.432 3.283 1.508.094.158.26.246.431.246.086 0 .174-.022.253-.069.238-.14.318-.446.179-.684-.054-.091-1.34-2.218-4.224-1.998-.275.021-.48.262-.459.538.022.275.271.484.537.459zm9.15 14.611c-.246-.014-.517.181-.539.457-.002.018-.161 1.719-1.91 2.294-.262.086-.405.368-.318.631.068.21.265.344.475.344.052 0 .104-.008.156-.025 2.372-.778 2.586-3.064 2.594-3.161.021-.276-.183-.518-.458-.54z"/><path d="M7.347 16.934c-.072.267.086.541.353.613.043.012.087.017.13.017.221 0 .422-.147.482-.37.19-.711.927-1.167 1.652-1.014.271.055.535-.116.592-.387.057-.27-.116-.535-.387-.592-.426-.09-.854-.048-1.248.086-1.166-1.994-.939-3.96-.936-3.981.036-.273-.156-.524-.429-.562-.272-.033-.524.154-.562.427-.013.097-.28 2.316 1.063 4.614-.334.301-.588.694-.71 1.149zm11.179-2.47c.407-.377 1.06-.37 1.455.015.098.094.223.141.349.141.131 0 .261-.051.358-.152.192-.198.188-.515-.01-.707-.23-.223-.505-.372-.797-.465.296-1.016.179-1.467-.096-2.312-.048-.147-.101-.311-.157-.498l-.03-.1c-.364-1.208-.605-2.005.087-3.13.145-.235.071-.543-.164-.688-.231-.144-.542-.073-.688.164-.928 1.508-.587 2.637-.192 3.944l.03.1c.059.194.113.364.163.517.247.761.322 1.016.02 1.936-.369.069-.722.236-1.01.504-.202.188-.213.505-.025.707.189.202.506.212.707.024zm6.365-2.985c.291 0 .585-.061.859-.191.25-.118.357-.416.239-.666-.117-.25-.419-.354-.665-.239-.502.236-1.121.031-1.384-.457-.131-.244-.436-.333-.677-.205-.243.13-.335.434-.204.677.18.336.448.601.76.785-.537 1.305-.232 2.691.017 3.426.07.209.265.34.474.34.053 0 .106-.008.16-.026.262-.088.402-.372.313-.633-.168-.498-.494-1.756-.002-2.826.038.002.073.015.11.015zm4.797 9.429c-.019-.275-.257-.492-.531-.467-1.014.072-1.878-.697-1.947-1.703-.02-.275-.265-.48-.533-.465-.275.019-.483.258-.465.533.041.59.266 1.122.608 1.555-.804.946-1.857 1.215-2.444 1.284-.519.062-.973.009-1.498-.053-.481-.055-1.025-.118-1.698-.098l-.005.001c-.02-.286-.088-.703-.305-1.05-.146-.233-.455-.304-.689-.158-.233.146-.305.455-.158.689.134.215.159.558.159.725-.504.181-.94.447-1.334.704-.704.458-1.259.82-2.094.632-.756-.173-1.513-.208-2.155-.118-.1-.251-.258-.551-.502-.782-.201-.19-.517-.182-.707.02-.189.2-.181.517.02.707.086.081.154.199.209.317-1.103.454-1.656 1.213-1.682 1.25-.16.224-.107.533.115.694.088.063.19.094.292.094.155 0 .308-.071.406-.205.005-.008.554-.743 1.637-1.04.56-.154 1.363-.141 2.146.037.219.05.422.067.619.07.093.218.129.477.134.573.016.266.236.472.499.472l.027-.001c.275-.015.486-.248.473-.523-.003-.05-.023-.346-.13-.686.461-.167.862-.428 1.239-.673.572-.373 1.113-.726 1.82-.749.592-.021 1.08.036 1.551.091.474.055.94.091 1.454.061.091.253.084.591.07.704-.033.273.16.523.434.559.021.003.042.004.063.004.247 0 .462-.183.495-.435.008-.062.059-.512-.059-.981.718-.193 1.608-.612 2.345-1.471.431.264.934.419 1.469.419.062 0 .125-.002.187-.006.275-.018.483-.255.465-.531z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9e2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e2.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2dd6c6f2f1e695dc0088d95a89966c19cdc6647 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse transform="rotate(-87.495 21.25 5.018)" fill="#2B7BB9" cx="21.249" cy="5.018" rx=".944" ry="1.565"/><path fill="#292F33" d="M29.831 27.74s3.523 1.385 5.185.088c.125-1.17-3.311-2.035-3.311-2.035l-1.874 1.947zM7.527 25.549S2.271 33.375.77 32.031c0 0-.425-1.397 1.23-4.218 1.656-2.822 5.527-2.264 5.527-2.264z"/><path fill="#1C6399" d="M19.766 4.82s-8.537.43-13.735 16.348c7.494 0 16.785.555 16.785.555s7.799 3.982 8.889 4.469c1.089.487 3.311 1.637 3.311 1.637s1.089-5.531.305-9.69S30.79 4.997 19.766 4.82z"/><path fill="#1C6399" d="M3.354 25.167C1.521 28.209.138 30.988.77 32.031c0 0-.203-.761.775-1.633.892-.795 2.805-1.522 6.461-1.522 5.534 0 13.006 4.498 16.119 5.562 2.375.812 2.875.188 4.188-1.25 1.4-1.534 3.716-6.904 3.716-6.904s-7.47-4.107-11.871-5.726-5.358-1.427-6.752-1.401c-3.056.057-5.314.671-7.375 2.011 0 0-1.494 2.036-2.677 3.999z"/><path fill="#50A5E6" d="M30.588 11.339c-.61-3.443-4.011-5.076-4.011-5.076-1.895-.883-4.158-1.448-6.864-1.491 0 0-12.192-.105-13.681 16.395 0 0 2.541-1.115 7.92-.793 7.299.438 14.414 4.117 15.986 4.812.83-2.779 1.367-9.798.65-13.847z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9e6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e6.svg new file mode 100644 index 0000000000000000000000000000000000000000..44fc31080aaa6a771c98f8960c07a4a34a7e23e9 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M27 19.276c-.983 0-1.893.294-2.667.784v4.549h-2.3c.175 2.603 2.319 4.667 4.966 4.667 2.761 0 5-2.239 5-5v-5H27z"/><path fill="#1C6399" d="M22.995 22.999l.005-16 9 .003-.005 16z"/><path fill="#1C6399" d="M24.202 21.451l6.354 6.354-6.878 6.878-6.354-6.354z"/><path fill="#55ACEE" d="M30 4h-5c-1.1 0-2 .9-2 2v2h9V6c0-1.1-.9-2-2-2zM15 15.276c-.983 0-1.893.294-2.667.784v4.549h-2.3c.175 2.603 2.319 4.667 4.966 4.667 2.761 0 5-2.239 5-5v-5H15z"/><path fill="#1C6399" d="M10.994 18.999l.006-16 9 .003-.006 16z"/><path fill="#55ACEE" d="M23.676 34.682c-1.757 1.757-4.607 1.757-6.364 0s-1.757-4.607 0-6.364c0 0 1.149.133 3.69 2.674s2.674 3.69 2.674 3.69zM18 0h-5c-1.1 0-2 .9-2 2v2h9V2c0-1.1-.9-2-2-2z"/><path fill="#1C6399" d="M12.202 17.451l6.354 6.354-6.878 6.878-6.354-6.354z"/><path fill="#55ACEE" d="M11.676 30.682c-1.757 1.757-4.607 1.757-6.364 0s-1.757-4.607 0-6.364c0 0 1.149.133 3.69 2.674s2.674 3.69 2.674 3.69z"/><path fill="#FFCC4D" d="M22.994 10.067h9v2h-9zm0 4h9v2h-9zm-12-8h9v2h-9zm0 4h9v2h-9z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9e9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e9.svg new file mode 100644 index 0000000000000000000000000000000000000000..ae4bf566814b61cfd3f052dfcad2d362970dee5e --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9e9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#78B159" d="M26.093 4.612c-.498.498-.629.839-.728 1.029-.66 1.266-1.455 1.676-2.78.351-.13-.13-4.087-4.267-4.741-5.017-.427-.49-1.081-.64-1.584-.262-.38.286-4.035 3.273-5.035 4.507-.774.955-.8 2.134-.079 2.856.326.326.727.449 1.151.578.552.169 1.763.068 2.47.775 1.133 1.133.54 2.924-.917 4.421-1.497 1.457-3.288 2.05-4.421.917-.708-.708-.606-1.918-.775-2.47-.129-.424-.252-.824-.578-1.151-.721-.721-1.9-.694-2.856.079-1.235 1-4.221 4.655-4.507 5.035-.379.503-.228 1.156.262 1.584.75.654 4.887 4.611 5.017 4.741 1.324 1.324.915 2.12-.351 2.78-.19.099-.53.229-1.029.728-1.462 1.462-1.462 3.833 0 5.295 1.462 1.462 3.833 1.462 5.295 0 .498-.498.629-.839.728-1.029.66-1.266 1.455-1.676 2.78-.351.13.13 4.087 4.267 4.741 5.017.427.49 1.081.64 1.584.262.38-.286 4.035-3.273 5.035-4.507.774-.955.8-2.134.079-2.856-.326-.326-.727-.449-1.151-.578-.552-.169-1.763-.068-2.47-.775-1.133-1.133-.54-2.924.917-4.421 1.497-1.457 3.288-2.05 4.421-.917.708.708.606 1.918.775 2.47.129.424.252.824.578 1.151.721.721 1.9.694 2.856-.079 1.235-1 4.221-4.655 4.507-5.035.379-.503.228-1.156-.262-1.584-.75-.654-4.887-4.611-5.017-4.741-1.324-1.324-.915-2.12.351-2.78.19-.099.53-.229 1.029-.728 1.462-1.462 1.462-3.833 0-5.295-1.462-1.463-3.833-1.463-5.295 0z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9ea.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ea.svg new file mode 100644 index 0000000000000000000000000000000000000000..8116cfa1ca017d11708052456e625507e5d4e2f4 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ea.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M14.563 14.414L25.47 3.505l6.961 6.962-10.908 10.908z"/><path fill="#68E090" d="M8.103 34.399C2.5 34 1.5 30.062 1.635 27.932c.322-5.07 15.601-16.551 15.601-16.551l12.517 1.93c.001 0-17.389 21.392-21.65 21.088z"/><path fill="#8899A6" d="M32.326 3.708C29.405.787 26.104-.649 24.954.502c-.013.013-.022.031-.034.044-.006.006-.015.008-.021.014L2.295 23.164c-1.412 1.412-2.19 3.29-2.19 5.288 0 1.997.778 3.875 2.19 5.287 1.413 1.413 3.291 2.19 5.288 2.19 1.998 0 3.875-.777 5.287-2.189l22.604-22.604c.007-.007.009-.016.015-.023.013-.012.03-.02.043-.033 1.151-1.15-.285-4.451-3.206-7.372zM10.75 31.619c-.846.846-1.97 1.311-3.166 1.311s-2.321-.466-3.167-1.312c-.846-.846-1.312-1.97-1.312-3.167 0-1.196.466-2.32 1.311-3.166L25.412 4.29c.622 1.144 1.56 2.394 2.749 3.584 1.189 1.189 2.44 2.127 3.584 2.749L10.75 31.619z"/><path fill="#17BF63" d="M29.196 13.144c-.058.379-2.627.751-5.691.343-3.063-.408-5.482-1.223-5.403-1.82.08-.597 2.627-.751 5.691-.343s5.495 1.224 5.403 1.82zM10.84 23.247c-.31.31-.813.31-1.123 0-.31-.31-.31-.813 0-1.123.31-.31.813-.31 1.123 0 .31.31.31.813 0 1.123zm3.317 2.615c-.507.507-1.328.506-1.835 0-.506-.506-.506-1.328 0-1.834.507-.507 1.328-.506 1.834 0 .507.506.508 1.327.001 1.834zm1.677-5.324c-.476.476-1.25.476-1.726 0s-.476-1.249 0-1.726c.476-.476 1.249-.477 1.725 0 .478.477.478 1.25.001 1.726zm-6.868 8.858c-.581.581-1.524.581-2.105 0-.582-.582-.581-1.524 0-2.105s1.523-.581 2.105 0c.581.581.582 1.523 0 2.105zm11.396-9.158c-.413.413-1.083.413-1.496 0-.413-.413-.412-1.083.001-1.496.414-.414 1.083-.414 1.496-.001.413.414.413 1.083-.001 1.497zm-1.207-4.288c-.27.27-.708.27-.979 0-.27-.27-.27-.708 0-.979.27-.27.708-.271.979 0 .27.271.27.709 0 .979z"/><ellipse transform="rotate(-45.001 30.817 5.223)" fill="#CCD6DD" cx="30.817" cy="5.223" rx="1.184" ry="4.847"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9ec.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ec.svg new file mode 100644 index 0000000000000000000000000000000000000000..689cc3e440fad43b90113c903dbbfa8c769f908b --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ec.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M3.019 26.246l3.432 3.432-.923.922-3.432-3.431z"/><path fill="#FFD983" d="M6.362 29.587l3.431 3.432-.923.923-3.43-3.432z"/><path fill="#FFAC33" d="M6.273 24.237l3.432 3.432-.923.923L5.35 25.16z"/><path fill="#EA596E" d="M8.998 26.962l3.432 3.432-.923.923-3.431-3.432zm3.909-9.359l3.431 3.432-.923.923-3.431-3.432z"/><path fill="#FFAC33" d="M15.631 20.329l3.432 3.431-.923.923-3.432-3.431z"/><path fill="#77B255" d="M14.97 14.377l3.432 3.432-.922.923-3.432-3.432z"/><path fill="#FFD983" d="M18.277 17.683l3.432 3.432-.923.923-3.432-3.432z"/><path fill="#FFAC33" d="M17.616 11.731l3.432 3.432-.923.922-3.432-3.431z"/><path fill="#EA596E" d="M20.923 15.038l3.432 3.431-.923.923-3.431-3.432zM24.387 4.96l3.432 3.432-.923.922-3.432-3.431z"/><path fill="#FFAC33" d="M27.694 8.267l3.432 3.431-.923.923-3.432-3.432z"/><path fill="#77B255" d="M27.013 2.252l3.432 3.432-.923.923-3.432-3.432z"/><path fill="#FFD983" d="M30.36 5.6l3.432 3.431-.923.923-3.432-3.431z"/><path fill="#9266CC" d="M24.922.812c-2.52 2.52-2.601 6.145-2.396 9.806.501.028 1.002.061 1.502.094.39.026.775.051 1.159.074-.198-3.286-.199-6.299 1.606-8.104.727-.703.955-1.653.447-2.166-.535-.54-1.542-.497-2.318.296z"/><path fill="#3B88C3" d="M13.146 25.65l-.153-2.66c-.026-.445-.058-.899-.074-1.332-.296-.296-2.466-.349-2.653-.162.013.44.047.884.071 1.327.028.502.126 2.275.149 2.66.054.91.096 1.806.086 2.656.259.259 2.371.437 2.645.162.015-.872-.022-1.761-.071-2.651z"/><path fill="#55ACEE" d="M13.22 28.3l-2.649-.162c-.026 2.209-.384 4.145-1.687 5.448-.517.517-.517 1.354 0 1.871.258.258.597.388.935.388.338 0 .677-.129.935-.388 2.423-2.422 2.467-7.174 2.466-7.157z"/><path fill="#9266CC" d="M25.354 13.447c-.501-.028-1.003-.061-1.503-.094-.389-.026-.775-.051-1.158-.074.198 3.285.199 6.299-1.607 8.104-1.804 1.804-4.813 1.805-8.094 1.607-.386-.023-2.159-.14-2.656-.168-3.667-.206-7.297-.126-9.82 2.397-.516.516-.516 1.353.001 1.87.258.258.597.388.935.388.338 0 .677-.129.935-.388 1.805-1.804 4.815-1.806 8.098-1.608.385.023 2.161.14 2.66.168 3.662.205 7.289.125 9.811-2.396 2.521-2.52 2.603-6.145 2.398-9.806z"/><path fill="#744EAA" d="M25.354 13.447c-.028-.501-.145-2.277-.168-2.66-.027-.45-.049-.894-.064-1.332-.336-.021-2.1-.133-2.653-.163.013.44.032.883.056 1.326.028.501.145 2.277.168 2.661.055.914.091 1.804.081 2.656.333.021 2.094.132 2.645.162.015-.872-.015-1.759-.065-2.65z"/><path fill="#55ACEE" d="M35.581 8.827c-.42-.436-1.385-.601-2.291.353-1.805 1.805-4.817 1.806-8.104 1.607-.384-.023-2.16-.141-2.661-.169-3.66-.205-7.286-.123-9.806 2.397-2.215 2.215-2.545 5.284-2.453 8.48.553.03 2.319.142 2.653.162-.098-2.755.113-5.214 1.671-6.772 1.805-1.805 4.818-1.805 8.104-1.607.383.023 2.16.14 2.661.168 3.661.205 7.286.124 9.806-2.396.886-.869.84-1.787.42-2.223z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9ed.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ed.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd3d583e58a9682ea5209d50a6b7d10cc8663735 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F4900C" cx="18" cy="18" r="18"/><circle fill="#FFD983" cx="18" cy="18" r="14.5"/><circle fill="#F5F8FA" cx="18" cy="18" r="13"/><path fill="#CCD6DD" d="M18 8l1.531 6.304 5.54-3.375-3.375 5.54L28 18l-6.304 1.531 3.375 5.54-5.54-3.375L18 28l-1.531-6.304-5.54 3.375 3.375-5.54L8 18l6.304-1.531-3.375-5.54 5.54 3.375z"/><path fill="#292F33" d="M17.343 20.748l8.777 5.381-5.379-8.778z"/><path fill="#DD2E44" d="M18.657 15.267L9.879 9.886l5.38 8.779z"/><circle fill="#8899A6" cx="18" cy="18.008" r="3.055"/><circle fill="#F5F8FA" cx="18" cy="18.008" r="1.648"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9ee.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ee.svg new file mode 100644 index 0000000000000000000000000000000000000000..c619bb0eb5e789fcb2773d36be37b639c6ed80d0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9ee.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M3 16v-2h30v2zm0 7v-2h30v2zm0 7v-2h30v2zM3 9V7h30v2z"/><path fill="#D5AB88" d="M35 33V1c0-.552-.448-1-1-1h-1c-.552 0-1 .448-1 1H4c0-.552-.448-1-1-1H2c-.552 0-1 .448-1 1v32h34zM4 4h28v29H4V4z"/><path fill="#3B94D9" d="M19 5.5c-.829 0-1.5.671-1.5 1.5 0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5c0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5c0-.829-.671-1.5-1.5-1.5S8.5 6.171 8.5 7c0-.829-.671-1.5-1.5-1.5S5.5 6.171 5.5 7v2c0 .829.671 1.5 1.5 1.5S8.5 9.829 8.5 9c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5.828 0 1.5-.671 1.5-1.5V7c0-.829-.672-1.5-1.5-1.5z"/><path fill="#BE1931" d="M19 12.5c-.829 0-1.5.671-1.5 1.5 0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5c0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5c0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5c0-.829-.671-1.5-1.5-1.5s-1.5.671-1.5 1.5v2c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5s1.5-.671 1.5-1.5c0 .829.671 1.5 1.5 1.5.828 0 1.5-.671 1.5-1.5v-2c0-.829-.672-1.5-1.5-1.5z"/><path fill="#5C913B" d="M19 19.5c-.829 0-1.5.672-1.5 1.5 0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5v2c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5.828 0 1.5-.672 1.5-1.5v-2c0-.828-.672-1.5-1.5-1.5z"/><path fill="#FFAC33" d="M19 26.5c-.829 0-1.5.672-1.5 1.5 0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5c0-.828-.671-1.5-1.5-1.5s-1.5.672-1.5 1.5v2c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5s1.5-.672 1.5-1.5c0 .828.671 1.5 1.5 1.5.828 0 1.5-.672 1.5-1.5v-2c0-.828-.672-1.5-1.5-1.5z"/><path fill="#3B94D9" d="M29 10.5c-.828 0-1.5-.671-1.5-1.5V7c0-.829.672-1.5 1.5-1.5s1.5.671 1.5 1.5v2c0 .829-.672 1.5-1.5 1.5z"/><path fill="#BE1931" d="M29 17.5c-.828 0-1.5-.671-1.5-1.5v-2c0-.829.672-1.5 1.5-1.5s1.5.671 1.5 1.5v2c0 .829-.672 1.5-1.5 1.5z"/><path fill="#5C913B" d="M29 24.5c-.828 0-1.5-.672-1.5-1.5v-2c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5v2c0 .828-.672 1.5-1.5 1.5z"/><path fill="#FFAC33" d="M29 31.5c-.828 0-1.5-.672-1.5-1.5v-2c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5v2c0 .828-.672 1.5-1.5 1.5z"/><path fill="#BF6952" d="M35 33H1c-.552 0-1 .448-1 1v1c0 .552.448 1 1 1h34c.552 0 1-.448 1-1v-1c0-.552-.448-1-1-1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9f2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..e81b4644e2930dfc811ba8e6b6875f4b2f3cc218 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M19.469 8.319l-3.854-4.671c-.355-.43-.991-.491-1.421-.136l-3.376 2.785 5.138 6.228 3.376-2.785c.431-.355.492-.991.137-1.421z"/><path fill="#BE1931" d="M29.543 25.021l-6.228-5.138s-2.395 3.132-5.006 6.152c-1.986 2.298-6.093 2.215-8.406-.098s-2.395-6.42-.098-8.406c3.02-2.611 6.152-5.006 6.152-5.006l-5.138-6.228s-5.122 3.928-6.613 5.43c-5.468 5.508-5.487 14.418.001 19.906s14.398 5.468 19.906.001c1.502-1.491 5.43-6.613 5.43-6.613z"/><path fill="#CCD6DD" d="M27.521 16.371l4.671 3.854c.43.355.491.991.136 1.421l-2.785 3.376-6.228-5.138 2.785-3.376c.355-.431.992-.492 1.421-.137z"/><path fill="#FFAC33" d="M23.717 4.223L21.96 2.43 23.896.535c.006-.006.004-.015.009-.021.016-.019.021-.039.027-.063.007-.024.013-.044.01-.068-.001-.008.005-.015.004-.023-.004-.017-.02-.024-.028-.038-.008-.016-.005-.035-.018-.048-.006-.006-.015-.004-.022-.009-.02-.016-.042-.021-.067-.028-.022-.006-.041-.012-.063-.01-.008.001-.016-.006-.024-.004L18.588 1.48c-.064.016-.115.065-.134.129-.018.064 0 .133.046.18l1.757 1.794-1.935 1.896c-.006.006-.004.015-.009.021-.016.019-.021.04-.028.064-.007.024-.013.043-.01.067.001.008-.006.015-.004.024.006.025.023.043.038.062.005.007.003.016.009.023l.011.011c.042.036.095.044.147.036.007-.001.011.006.018.004l5.134-1.257c.064-.016.115-.065.134-.129.018-.066 0-.135-.045-.182zm-2.155-1.661l.005-.005-.005.005zm14.266 12.543l-2.055-1.443 1.557-2.217c.005-.007.001-.015.005-.022.012-.022.013-.042.015-.067s.005-.045-.002-.069c-.002-.008.003-.015-.001-.023-.007-.016-.024-.02-.034-.033-.011-.014-.012-.032-.027-.043-.007-.005-.016-.001-.023-.005-.023-.012-.045-.013-.071-.015-.023-.002-.043-.004-.064.002-.008.002-.016-.003-.024.001l-4.819 2.173c-.06.027-.101.085-.108.151-.006.066.025.131.078.169l2.055 1.443-1.556 2.217c-.005.007-.001.015-.005.022-.012.022-.013.043-.015.068-.002.024-.005.045.002.068.002.008-.003.016.001.024.011.023.031.038.049.054.006.006.006.015.013.02l.013.008c.048.028.102.026.151.008.006-.002.012.004.018.001l4.818-2.174c.06-.027.101-.085.108-.151.004-.064-.026-.129-.079-.167zm-2.422-1.24l.004-.006-.004.006z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9f5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..3210fbeb543ab08506f10752c3e23c97b98126ee --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#553788" d="M35 36c-.419 0-.809-.265-.948-.684C33.388 33.326 31.595 32 25 32c-.553 0-1-.447-1-1s.447-1 1-1c5.635 0 9.653.797 10.948 4.684.175.524-.108 1.091-.632 1.265-.105.034-.212.051-.316.051z"/><path fill="#553788" d="M3 3h22v30H3z"/><path fill="#C1694F" d="M26 4H2c-.55 0-2-3-2-3 0-.55.45-1 1-1h26c.55 0 1 .45 1 1 0 0-1.45 3-2 3zm0 28H2c-.55 0-2 3-2 3 0 .55.45 1 1 1h26c.55 0 1-.45 1-1 0 0-1.45-3-2-3z"/><path fill="#744EAA" d="M23 7H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1zm0 4H5c-.55 0-1-.45-1-1s.45-1 1-1h18c.55 0 1 .45 1 1s-.45 1-1 1z"/><path fill="#9266CC" d="M17.261 7H7.739C7.332 7 7 6.668 7 6.261v-.522C7 5.332 7.332 5 7.739 5h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 11 7 10.668 7 10.261v-.522C7 9.332 7.332 9 7.739 9h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 15 7 14.668 7 14.261v-.523c0-.406.332-.738.739-.738h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 19 7 18.668 7 18.261v-.523c0-.406.332-.738.739-.738h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 23 7 22.668 7 22.261v-.523c0-.406.332-.738.739-.738h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 27 7 26.668 7 26.261v-.523c0-.406.332-.738.739-.738h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738zm0 4H7.739C7.332 31 7 30.668 7 30.261v-.523c0-.406.332-.738.739-.738h9.523c.406 0 .738.332.738.739v.523c0 .406-.332.738-.739.738z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1f9f9.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f9.svg new file mode 100644 index 0000000000000000000000000000000000000000..2bcbda87e3e868439c318d1db4efb1ccf8bdc1c5 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1f9f9.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M19.175 16.825c-.706-.706-.706-1.861 0-2.567L32.433 1C33.139.294 34.294.294 35 1c.706.706.706 1.861 0 2.567L21.742 16.825c-.706.706-1.861.706-2.567 0z"/><path fill="#66757F" d="M8.839 27.365l-.204-.204c-.941-.941-.941-2.48 0-3.42l8.35-8.35c.941-.941 2.48-.941 3.42 0l.204.204c.941.941.941 2.48 0 3.42l-8.35 8.35c-.94.941-2.48.941-3.42 0z"/><path fill="#FFCC4D" d="M19.389 26.341c1.688-1.688.671-5.441-1.809-7.921s-6.233-3.497-7.921-1.809L0 26.16 9.84 36l9.549-9.659z"/><path fill="#FFAC33" d="M2.02 28.18l8.66-8.658.58.58L2.6 28.76zm1.74 1.74l8.66-8.659.58.58-8.66 8.66zm1.74 1.74L14.158 23l.58.58-8.66 8.66zm1.74 1.74l8.659-8.66.58.58-8.66 8.659z"/><path fill="#55ACEE" d="M9.875 16.43c-.073.059-.149.114-.216.181L7.46 18.779l9.761 9.761 2.167-2.199c.067-.067.123-.143.181-.216L9.875 16.43z"/><path fill="#269" d="M8.882 18.221l.235-.568 9.225 9.224-.572.232z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa73.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa73.svg new file mode 100644 index 0000000000000000000000000000000000000000..03e70ca89e718cff4568c7b6ba9e1c8834071b51 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa73.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#78B159" d="M31 6V1.955c0-.527-.428-.955-.955-.955H5.955C5.428 1 5 1.428 5 1.955V6L0 31l14 4 4-10.545L22 35l14-4-5-25z"/><g fill="#5D9040"><path d="M5 4h26v2H5zm8.782 2h-2.074c-1.378 4.107-5.46 5.399-7.87 5.807l-.421 2.107c3.606-.408 8.9-2.403 10.365-7.914z"/><path d="M32.583 13.914l-.421-2.107c-2.41-.408-6.491-1.701-7.87-5.807h-2.074c1.464 5.511 6.759 7.506 10.365 7.914zM17 6v21.091l1-2.636 1 2.636V6z"/><path d="M18.149 23H18v-2h.149C19.722 21 21 19.722 21 18.149V5h2v13.149C23 20.824 20.824 23 18.149 23z"/></g></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa80.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa80.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc9af9be9d2d8913c521758e5f148846283990c0 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa80.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#BE1931" cx="17.722" cy="21.507" rx="12.917" ry="13.993"/><ellipse fill="#A0041E" cx="15.569" cy="21.507" rx="12.917" ry="13.993"/><path fill="#99AAB5" d="M28.298 13.741c-1.643 0-3.457-.825-5.227-1.629-2.124-.966-4.322-1.966-5.46-1.113l-1.167-1.555c2.06-1.544 4.79-.303 7.431.898 2.023.92 4.117 1.868 5.327 1.263.664-.331 1.155-1.195 1.459-2.566l1.899.422c-.444 2-1.259 3.27-2.49 3.885-.558.278-1.153.395-1.772.395z"/><ellipse fill="#DD2E44" cx="13.417" cy="21.507" rx="12.917" ry="13.993"/><ellipse fill="#EA596E" cx="12.878" cy="21.507" rx="9.149" ry="10.433"/><path fill="#99AAB5" d="M31.611 10.222c-2.41 0-3.889-3.398-3.889-5.833S29.176.5 31.611.5 35.5 1.954 35.5 4.389c0 2.436-1.479 5.833-3.889 5.833zm0-7.778c-1.344 0-1.944.6-1.944 1.944 0 1.878 1.141 3.889 1.944 3.889s1.944-2.011 1.944-3.889c.001-1.344-.599-1.944-1.944-1.944z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa81.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa81.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd8605e468471119640e562102e7942e4d98a3f3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa81.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#55ACEE" d="M22.45 32.289L.592 18.752 6.55.711l18.042 5.958z"/><path fill="#269" d="M20.543 29.5c-.366 0-.719-.201-.895-.551L6.929 3.687c-.249-.493-.05-1.095.443-1.343.494-.249 1.095-.05 1.343.443l12.72 25.264c.248.493.05 1.094-.444 1.343-.143.072-.297.106-.448.106z"/><path fill="#269" d="M3.12 18.48c-.366 0-.718-.201-.894-.55-.249-.493-.05-1.095.443-1.343l18.947-9.54c.49-.25 1.094-.05 1.343.443.248.493.05 1.095-.443 1.343l-18.947 9.54c-.145.073-.298.107-.449.107z"/><path fill="#3B88C3" d="M27.367 35.339c-2.44 0-4.521-1.268-6.199-3.784-.307-.459-.183-1.08.277-1.387.458-.307 1.079-.183 1.387.277 1.564 2.343 3.359 3.228 5.644 2.781.945-.184 1.793-.98 2.27-2.132.701-1.693.47-3.668-.62-5.282-2.006-2.971-2.777-6.787-2.063-10.21.615-2.956 2.24-5.344 4.698-6.905.466-.295 1.084-.158 1.38.308.297.466.158 1.084-.308 1.38-2.516 1.598-3.462 3.941-3.813 5.625-.604 2.905.055 6.151 1.765 8.683 1.466 2.172 1.769 4.851.811 7.167-.734 1.772-2.131 3.018-3.736 3.329-.513.1-1.009.15-1.493.15z"/><path d="M31.532 30.992c-.781-2.485-2.807-4.482-4.157-2.075-1.342 2.392 1.04 3.456 3.717 2.74.781 2.485 2.807 4.482 4.157 2.075 1.342-2.392-1.039-3.456-3.717-2.74zm-1.425-7.039c2.377 1.066 5.215.876 4.311-1.731-.898-2.592-3.275-1.517-4.517.961-2.377-1.066-5.215-.876-4.311 1.731.898 2.592 3.275 1.517 4.517-.961zm-1.261-6.597c1.355 2.225 3.802 3.676 4.534 1.015.727-2.645-1.84-3.105-4.267-1.766-1.355-2.224-3.802-3.676-4.534-1.015-.728 2.645 1.84 3.105 4.267 1.766zm2.897-6.557c-.132 2.602 1.074 5.178 3.177 3.39 2.089-1.777.226-3.602-2.534-3.861.132-2.602-1.074-5.178-3.177-3.39-2.089 1.777-.225 3.602 2.534 3.861z" fill="#9266CC"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa83.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa83.svg new file mode 100644 index 0000000000000000000000000000000000000000..3de58a8f2cc510ae81f3fdc4ee6a03e9412debce --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa83.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M31.497 6.06s.244-4.293-6.702-3.83c-8.617.574-18.599 9.155-18.95 17.159-.267 6.089 8.109 1.203 11.139-1.96-.045-.045 3.282 1.426 4.752 4.545-3.267 2.733-8.047 4.803-11.644 5.109-6.282.535-8.546-2.727-7.557-9.15C3.758 10 13.588.858 24.604.795c8.377-.048 6.893 5.265 6.893 5.265z"/><path fill="#662113" d="M32.19 32.317c.351-1.768-.27-19.086-4.411-22.615S5.541 7.73 3.881 8.435c-2.24.95-1.352 3.835.184 3.93 5.43.339 16.02.786 18.774 3.133s4.875 12.732 6.07 18.04c.337 1.501 2.643 1.99 3.281-1.221z"/><path fill="#C1694F" d="M32.19 32.317c.432-1.75-.057-20.063-4.197-23.592s-22.3-1.109-23.96-.405c-2.24.95-1.291 2.972.245 3.068 5.43.339 16.02.786 18.774 3.133s4.875 12.732 6.07 18.04c.338 1.501 2.484 2.118 3.068-.244z"/><path fill="#FFCC4D" d="M6.747 11.537c1.459.089 3.08.196 4.731.339l-.013-4.686c-1.373.125-2.649.274-3.749.426l-.969 3.921zm21.836 18.61c-.319-1.426-.682-3.01-1.084-4.618l4.629-.73c.094 1.376.149 2.659.174 3.769l-3.719 1.579z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa90.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa90.svg new file mode 100644 index 0000000000000000000000000000000000000000..46a0c53cea531d63a7aa4483666a74149fc67f88 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa90.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCC4D" cx="18" cy="18" r="10.694"/><path fill="#F4900C" d="M10.229 22.751c-.985.067-1.689-.308-2.203-.917.214.557.487 1.081.788 1.588.771.289 1.591.41 2.54-.272-.463-.227-.88-.415-1.125-.399zM23.086 8.608c.045.328-.187.5-.75.363-.955-.232-1.793.776-2.274 1.619-.947 1.657-4.854 3.524-4.857 2.087-.001-.679-3.452.843-3.893.161-.417-.644-1.663-.396-1.921-1.168-1.135 1.544-1.869 3.402-2.04 5.422.377.718.864 1.282 1.352 1.526.66.33 3.726 1.528 4.174.763.747-1.276 5.229-.373 5.122-1.044-.205-1.285 2.427-.23 3.373-1.886.482-.843 1.533-1.49 2.489-1.258 1.116.271 2.493-1.643 2.389-3.996-.871-1.057-1.951-1.931-3.164-2.589zm3.181 16.175c-.338.166-.671.293-.975.326-2.248.243-2.734 2.005-4.242 1.703-.777-.156-1.837 1.214-3.05 1.297-.611.042-1.489.141-2.386.308.768.175 1.565.277 2.386.277 3.331 0 6.305-1.523 8.267-3.911z"/><path fill="#E85E00" d="M23.225 8.674c.953.535 1.811 1.213 2.554 2.003 2.491-.157 4.01.429 3.883 1.777-.066.705-.585 1.542-1.431 2.435-2.108 2.221-6.309 4.796-11.07 6.602-3.309 1.255-6.258 1.9-8.366 1.934-2.145.035-3.418-.563-3.302-1.803.076-.815.752-1.806 1.852-2.857-.019-.255-.039-.507-.039-.765 0-.848.109-1.669.296-2.461C3.3 18.522.5 21.807.5 24.369c0 3.487 5.162 4.558 12.275 2.957 1.65-.371 3.405-.886 5.225-1.549 3.9-1.419 7.489-3.3 10.399-5.317 4.301-2.983 7.101-6.268 7.101-8.83 0-3.486-5.162-4.558-12.275-2.956z"/><path fill="#F4900C" d="M6.356 18.051c-.742.711-1.369 1.524-1.88 2.382-.49.852-.907 1.811-.844 2.671.035.856.682 1.366 1.558 1.602.874.227 1.845.287 2.834.229 1.962-.089 3.93-.415 5.841-.965 1.924-.505 3.791-1.225 5.615-2.036 3.648-1.628 7.068-3.789 10.132-6.382.368-.333.771-.649 1.124-.986.333-.337.647-.713.91-1.097.522-.768.826-1.667.335-2.352-.49-.696-1.495-1.075-2.453-1.271-.981-.187-2.01-.23-3.03-.111.992-.265 2.037-.395 3.088-.316 1.03.092 2.172.3 3.008 1.221.41.457.599 1.145.524 1.746-.057.611-.293 1.15-.563 1.635-.278.485-.59.925-.945 1.348-.352.404-.709.777-1.072 1.163-2.932 2.994-6.44 5.414-10.261 7.159-3.816 1.72-7.974 2.911-12.261 2.754-1.056-.04-2.157-.133-3.236-.548-.534-.209-1.082-.517-1.5-1.016-.429-.49-.635-1.171-.589-1.774.098-1.213.704-2.152 1.349-2.976.664-.819 1.447-1.525 2.316-2.08z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa91.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa91.svg new file mode 100644 index 0000000000000000000000000000000000000000..8db580193f88211532b9a0ebe5bab679ed32575d --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa91.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A4523A" d="M12 20c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2s2-.9 2-2V22c0-1.1-.9-2-2-2zm18 0c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2s2-.9 2-2V22c0-1.1-.9-2-2-2z"/><path fill="#C1694F" d="M13 2h16v8H13z"/><path fill="#C1694F" d="M16 9h2v13h-2zm4 0h2v13h-2zm4 0h2v13h-2zM7 23c-1.1 0-2 .9-2 2v9c0 1.1.9 2 2 2s2-.9 2-2v-9c0-1.1-.9-2-2-2z"/><path fill="#C1694F" d="M25 21c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2s2-.9 2-2V23c0-1.1-.9-2-2-2zM12 0c-1.1 0-2 .9-2 2v20h4V2c0-1.1-.9-2-2-2zm18 0c-1.1 0-2 .9-2 2v20h4V2c0-1.1-.9-2-2-2z"/><path fill="#A4523A" d="M14 2h1v8h-1zm14 8h-1V2h1z"/><path fill="#D99E82" d="M30.769 20H10.341c-.223 0-.442.061-.633.175l-5.954 3.041s22.726 2.418 24.726 2.418l3.029-2.265c.309-.232.491-.597.491-.985v-1.153c0-.68-.551-1.231-1.231-1.231z"/><path fill="#A4523A" d="M16 10h2v1h-2zM5 26h4v1H5zm18 0h4v1h-4zm-3-16h2v1h-2zm4 0h2v1h-2z"/><path fill="#C1694F" d="M27.44 26H4.56C3.698 26 3 25.328 3 24.5S3.698 23 4.56 23h22.88c.862 0 1.56.672 1.56 1.5s-.698 1.5-1.56 1.5z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa95.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa95.svg new file mode 100644 index 0000000000000000000000000000000000000000..da6e25d06b84f7f2d4991e48d951a9b3a0e7d119 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa95.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#67757F" cx="10.047" cy="16.953" r="1"/><circle fill="#67757F" cx="1.047" cy="25.953" r="1"/><circle fill="#67757F" cx="19.047" cy="25.953" r="1"/><circle fill="#67757F" cx="10.047" cy="34.953" r="1"/><circle fill="#67757F" cx="3.547" cy="19.828" r="1"/><circle fill="#67757F" cx="16.214" cy="32.495" r="1"/><path fill="#292F33" d="M32.339 5.338l-15.45 17.334-3.561-3.56L30.66 3.66z"/><ellipse transform="rotate(-52.019 10.047 25.953)" fill="#F18F26" cx="10.047" cy="25.953" rx="9" ry="9"/><ellipse transform="rotate(-52.019 10.047 25.953)" fill="#F5F8FA" cx="10.047" cy="25.953" rx="7" ry="7"/><path fill="#CCD6DD" d="M4.628 29.934L28.8 5.807l.53.531L5.16 30.466zm.869.87L29.67 6.676l.531.531L6.028 31.335z"/><path fill="#292F33" d="M2.047 31.953l2-3s1 0 2 1 1 2 1 2l-3 2-2-2z"/><path fill="#67757F" d="M9.097 30.903c-.256 0-.512-.098-.707-.293l-3-3c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l3 3c.391.391.391 1.023 0 1.414-.196.196-.452.293-.707.293z"/><path fill="#F18F26" d="M34.704 2.685c.438.438.438 1.155-.001 1.592l-3.186 3.186c-.438.438-1.155.438-1.593-.001l-1.39-1.389c-.438-.438-.438-1.155.001-1.592l3.187-3.186c.438-.438 1.155-.438 1.593 0l1.389 1.39z"/><circle fill="#642116" cx="33" cy="8" r="1"/><circle fill="#642116" cx="35" cy="6" r="1"/><circle fill="#642116" cx="28" cy="3" r="1"/><circle fill="#642116" cx="30" cy="1" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fa97.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fa97.svg new file mode 100644 index 0000000000000000000000000000000000000000..c9c21ca2a2965c84786a3ebaf096fca70e2aead7 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fa97.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFE8B6" d="M17.483 30.971c-.574.051-1.099-.36-1.168-.93L13.427 5.136c-.069-.57.676-1.133 1.657-1.22.981-.087 1.811.336 1.844.909l1.541 25.024c.031.574-.412 1.07-.986 1.122zm4.199-.146c-.574-.011-1.051-.476-1.058-1.051l-.192-25.071c-.007-.574.791-1.054 1.773-1.034.982.019 1.76.528 1.731 1.102l-1.157 25.045c-.029.574-.522 1.02-1.097 1.009zm4.185.306c-.57-.073-.993-.586-.939-1.158l2.501-24.947c.054-.572.899-.963 1.873-.838.974.124 1.694.714 1.603 1.281l-3.839 24.776c-.091.568-.629.959-1.199.886z"/><path fill="#D99E82" d="M19.582 30.841c-.575.02-1.076-.419-1.114-.992L16.927 4.825c-.038-.573.734-1.095 1.717-1.128.983-.034 1.788.433 1.789 1.007l.192 25.071c.001.574-.468 1.046-1.043 1.066zm4.197.081c-.573-.042-1.023-.532-.999-1.106l1.157-25.045c.024-.574.846-1.01 1.825-.938.979.071 1.729.622 1.669 1.193L24.93 29.973c-.062.572-.579.991-1.151.949z"/><path fill="#BE1931" d="M29.781 31.803l-1.033-.159c-1.136-.175-1.922-1.247-1.747-2.383l3.495-22.715c.175-1.136 1.247-1.922 2.383-1.747l1.033.159c1.136.175 1.922 1.247 1.747 2.383l-3.495 22.715c-.175 1.136-1.248 1.922-2.383 1.747z"/><circle fill="#F5F8FA" cx="33.276" cy="9.088" r="1.045"/><circle fill="#F5F8FA" cx="33.276" cy="9.088" r="1.045"/><circle fill="#F5F8FA" cx="32.799" cy="12.186" r="1.045"/><circle fill="#F5F8FA" cx="32.322" cy="15.283" r="1.045"/><circle fill="#F5F8FA" cx="31.846" cy="18.381" r="1.045"/><circle fill="#F5F8FA" cx="31.369" cy="21.478" r="1.045"/><circle fill="#F5F8FA" cx="30.893" cy="24.576" r="1.045"/><circle fill="#F5F8FA" cx="30.416" cy="27.673" r="1.045"/><path fill="#BE1931" d="M14.591 31.252L5.25 32.318c-1.142.13-2.182-.697-2.313-1.839L.331 7.645c-.13-1.142.697-2.183 1.839-2.313l9.341-1.066c1.142-.13 2.182.697 2.313 1.839l2.606 22.834c.13 1.142-.697 2.183-1.839 2.313z"/><path fill="#F5F8FA" d="M7.891 7.833l-5.542.633c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.473-.289.905-.763.959zm.355 3.114l-5.541.633c-.474.054-.906-.29-.96-.764l-.04-.352c-.055-.474.289-.906.763-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.055.473-.289.905-.763.959zm.355 3.114l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.474-.289.906-.764.96zm.356 3.114l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.473-.29.906-.764.96zm.355 3.113l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.474-.29.906-.764.96zm.355 3.114l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.474-.289.906-.764.96zm.356 3.114l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.474-.29.906-.764.96zm.355 3.114l-5.541.632c-.474.054-.906-.29-.96-.764l-.04-.352c-.054-.474.29-.906.764-.96l5.541-.632c.474-.054.906.29.96.764l.04.352c.054.473-.29.906-.764.96z"/><path fill="#292F33" d="M5.582 9.148l2.427-.277c.474-.054.818-.486.764-.96l-.04-.352c-.054-.474-.486-.818-.96-.764l-2.428.277c-.474.054-.818.486-.764.96l.04.352c.054.475.486.818.961.764zm.355 3.114l2.427-.277c.474-.054.818-.486.764-.96l-.04-.352c-.054-.474-.486-.818-.96-.764l-2.428.277c-.474.054-.818.486-.764.96l.04.352c.055.475.487.818.961.764zm.711 6.228l2.427-.277c.474-.054.818-.486.764-.96l-.04-.353c-.054-.474-.486-.818-.96-.764l-2.427.277c-.474.054-.818.486-.764.96l.04.352c.053.475.486.819.96.765zm.355 3.113l2.427-.277c.474-.054.818-.486.764-.96l-.04-.352c-.054-.474-.486-.818-.96-.764l-2.427.277c-.474.054-.818.486-.764.96l.04.352c.054.475.486.818.96.764zm.355 3.114l2.427-.277c.474-.054.818-.486.764-.96l-.04-.352c-.054-.474-.486-.818-.96-.764l-2.427.277c-.474.054-.818.486-.764.96l.04.352c.054.475.486.818.96.764zm.711 6.228l2.427-.277c.474-.054.818-.486.764-.96l-.04-.352c-.054-.474-.486-.818-.96-.764l-2.427.277c-.474.054-.818.486-.764.96l.04.352c.054.474.486.818.96.764z"/><path fill="#A0041E" d="M10.103 6.529l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.258c-.237.027-.409.243-.382.48l.02.176c.027.237.243.408.48.381zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.244-.382.481l.02.176c.027.236.243.408.48.381zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.075l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.026.238.243.41.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.026.238.242.409.48.382zm.236 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382zm.237 2.076l2.252-.257c.237-.027.409-.243.382-.48l-.02-.176c-.027-.237-.243-.409-.48-.382l-2.252.257c-.237.027-.409.243-.382.48l.02.176c.027.237.243.409.48.382z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fab6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fab6.svg new file mode 100644 index 0000000000000000000000000000000000000000..8e70d6cd5c39b603fe3b9e269e65fd8837c38d62 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fab6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#C1694F" d="M4.048 29.644c-.811-.558-1.541-4.073-.936-4.404.738-.402.686.835 2.255 2.362 1.569 1.528 6.47.913 7.708 1.326 1.363.455-6.385 2.533-9.027.716z"/><path fill="#D99E82" d="M5.367 27.603C4 22 4.655 18.919 5.433 16.861 6.8 13.24 16.699 5.169 23.8 2.637 25.678 1.967 31.62 1 35 1c.589 2.332-1.174 6.717-1.62 7.518-1.009 1.81-3.564 4.273-8.646 9.482-.252.258-5.119-.46-5.376-.191-.283.296 4.044 1.579 3.755 1.889-.738.79-1.495 1.624-2.268 2.507-.172.196-8.311-.923-8.484-.722-.232.27 7.501 1.862 7.266 2.14-.645.765-1.299 1.564-1.959 2.397-1.725 2.178-12.301 1.583-12.301 1.583z"/><path fill="#C1694F" d="M19.15 12.787c1.588.966 5.331 1.943 8.316 2.422 1.898-1.937 3.299-3.378 4.302-4.529-2.259-.49-5.742-1.3-7.487-2.087l-.816-.403-4.872 4.17.557.427z"/><path fill="#662113" d="M35.088 1.514c-.02-.179-.047-.352-.088-.514-.378 0-.792.014-1.225.036-3.438.178-8.307 1.006-9.975 1.601-.345.123-.702.27-1.059.418-.478.198-.964.416-1.459.654.356 1.481 1.126 3.144 1.807 4.013-1.703 1.323-3.317 2.704-4.836 4.115-5.655 5.248-10.021 10.872-13.005 15.242.04.174.076.344.12.524 0 0 .219.012.589.026 1.482-2.288 5.703-8.239 13.194-14.841 1.565-1.379 3.276-2.786 5.13-4.195 1.745.787 5.228 1.597 7.487 2.087.322-.369.606-.712.849-1.028.316-.412.569-.785.763-1.134.415-.746 1.969-4.594 1.708-7.004z"/><path fill="#C1694F" d="M35 1c-.369 0-.751-.003-1.138-.008-3.915 1.874-7.509 4.194-10.772 6.73-.68-.87-1.451-2.532-1.807-4.013-1.467.708-2.987 1.575-4.484 2.539.309 1.911.852 4.377 1.455 5.589C6.827 22.441.638 34.605.553 34.776c-.124.247-.023.547.224.671.071.036.147.053.223.053.184 0 .36-.102.448-.276.119-.238 12.144-23.883 33.659-33.72-.032-.174-.066-.343-.107-.504z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fad0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fad0.svg new file mode 100644 index 0000000000000000000000000000000000000000..34e68d6b49b17f697d74a7f3f5a39cb972b5b351 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fad0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M8.089 1s5.858.616 8.54 4.06c3.206 4.117.891 7.962.891 7.962s-4.825-.425-7.03-3.157C7.287 5.896 8.089 1 8.089 1z"/><path fill="#77B255" d="M21.901 1s.913 4.617-1.006 7.47c-2.293 3.41-5.676 2.54-5.676 2.54s-.813-3.784.691-6.106C18.096 1.53 21.901 1 21.901 1z"/><ellipse fill="#5864B7" cx="23.737" cy="11.536" rx="6.916" ry="6.027"/><path fill="#334372" d="M19.34 16.996c0-.851-.124-1.64-.34-2.373 1.231-.409 2.569-.641 3.983-.641 2.263 0 4.355.55 6.073 1.562C27.818 17.147 25.7 18 23.292 18c-1.476 0-2.834-.331-3.955-.949 0-.019.003-.036.003-.055z"/><path fill="#334372" d="M21.761 16.558c0 .27-.017.531-.04.789-2.836-.632-4.901-2.641-4.901-5.811 0-.778.129-1.483.359-2.119 2.732 1.246 4.582 3.739 4.582 7.141z"/><ellipse fill="#5864B7" cx="10.892" cy="16.558" rx="8.892" ry="8.035"/><path fill="#334372" d="M10.892 24.091c0-5.278 3.75-8.713 8.687-9.406.132.589.206 1.213.206 1.872 0 4.984-3.968 8.024-8.867 8.034-.008-.166-.026-.329-.026-.5z"/><ellipse transform="rotate(-60 17.507 21.52)" fill="#AA8DD8" cx="17.507" cy="21.519" rx="2.525" ry="2.5"/><ellipse fill="#5864B7" cx="22.44" cy="25.095" rx="10.56" ry="9.542"/><path fill="#334372" d="M17.043 19.746c.702-1.228 1.699-.59 2.881-1.366.95-.624 1.079-1.574 2.079-1.574s1.604.832 2.168 1.04c1.327.489 2.119-.228 3.119.772s-.772 1.901-.921 2.673c-.189.982 1.04 1.693.178 2.168-1.237.683-1.549-.556-3.547-.459-1.502.073-2.096 1.528-3.403 1.082-1.339-.456.475-1.752-.327-2.584-.981-1.018-2.702-.92-2.227-1.752zm-10.871-7.99c.445-1.036 1.065-.439 1.932-1.161.696-.581.712-1.345 1.504-1.436.792-.091 1.346.514 1.812.627 1.096.267 1.88-.08 2.541.329.959.594-.138 1.312-.186 1.937-.061.795.676 1.511.036 1.966-.919.654-1.492-.174-3.066.083-1.183.194-1.271 1.037-2.347.802-1.102-.24-.151-1.315-.861-1.901-.869-.716-1.667-.544-1.365-1.246zM24.39 6.679c.831-.296.818.377 1.693.49.703.091 1.15-.307 1.624.1.473.406.421 1.045.604 1.373.429.77 1.046 1.036 1.162 1.632.17.866-.826.618-1.21.924-.488.388-.508 1.191-1.108 1.066-.864-.18-.693-.948-1.678-1.714-.74-.576-1.27-.177-1.708-.919-.448-.76.674-.785.632-1.505-.051-.881-.573-1.247-.011-1.447z"/><ellipse fill="#253356" cx="22.667" cy="20.182" rx="3.758" ry="2.387"/><ellipse fill="#253356" cx="10.455" cy="11.945" rx="2.818" ry="1.791"/><ellipse transform="rotate(-40.137 26.699 9.278)" fill="#253356" cx="26.7" cy="9.278" rx="1.293" ry="2.035"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fad2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fad2.svg new file mode 100644 index 0000000000000000000000000000000000000000..b84ce6a1f480065c71723df23fe7f53014dfb3ef --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fad2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#909B50" d="M13.241 23.993c1.274-1.617 4.455-.891 6.416.535s3.089 4.337 1.901 5.941-4.158 1.96-6.416.416c-2.258-1.545-3.446-4.931-1.901-6.892zm4.455-20.792c2.802.342 3.208 2.97 2.792 5.703-.416 2.733-2.436 5.347-4.693 5.228-2.257-.119-3.149-3.446-2.792-6.238s2.258-4.99 4.693-4.693z"/><path fill="#C1694F" d="M1.3 32.876c-.08 0-.161-.016-.239-.048-.319-.133-.47-.498-.337-.817 2.393-5.756 6.062-8.645 8.72-10.055 1.57-.833 2.938-2.249 4.036-3.387.663-.687 1.236-1.28 1.767-1.672 1.357-1.003 6.335-4.495 6.547-4.643.282-.199.672-.129.87.153.198.283.13.672-.153.871-.051.036-5.177 3.631-6.521 4.625-.447.331-.986.889-1.61 1.536-1.16 1.201-2.604 2.696-4.35 3.622-2.476 1.314-5.9 4.018-8.151 9.432-.102.238-.334.383-.579.383z"/><path fill="#C1694F" d="M7.538 24.5c-.321 0-.594-.245-.622-.571-.01-.113-.241-2.802-.12-4.437.025-.345.316-.602.669-.578.344.026.603.326.578.669-.114 1.536.116 4.21.118 4.237.03.344-.225.646-.568.677l-.055.003zm6 .356c-.117 0-.234-.032-.339-.101l-.231-.15c-.837-.545-2.399-1.55-3.163-1.477-.345.042-.652-.209-.69-.553-.038-.343.209-.651.552-.689 1.129-.117 2.525.721 3.983 1.672l.228.148c.29.188.373.574.185.864-.12.186-.321.286-.525.286zm2.051-6.85c-.211 0-.411-.106-.521-.307-.534-.979.188-4.022.385-4.512.128-.321.493-.477.812-.348.32.128.476.492.348.812-.262.654-.631 3.017-.444 3.456.131.307.009.686-.292.831-.093.046-.192.068-.288.068z"/><path fill="#C1694F" d="M19.774 20.163c-.127 0-.256-.039-.367-.119-1.576-1.148-2.984-1.563-4.306-1.263-.339.075-.671-.136-.748-.472-.076-.337.136-.671.472-.748 1.689-.382 3.431.099 5.317 1.471.278.203.34.595.138.874-.122.168-.312.257-.506.257zm3.625-3.624c-.069 0-.14-.011-.208-.036-1.02-.36-3.124-.883-4.528-.573-.335.073-.67-.138-.746-.475-.075-.337.138-.671.475-.746 2.074-.457 4.901.503 5.215.615.325.115.496.472.382.797-.091.258-.332.418-.59.418z"/><path fill="#3E721D" d="M34.449 2.845c2.5 1.136-1.426 5.406-3.624 6.653-2.198 1.248-10.455 5.406-10.99 5.049s3.089-6.772 6.713-9.148 6.594-3.148 7.901-2.554zM18.944 18.587c1.344-.504 6.772 1.366 9.386 3.149 2.614 1.782 4.04 4.634 2.911 5.584s-5.822.238-8.792-2.436-4.456-5.94-3.505-6.297zM9.617 2.964c2.225-.384 2.851 4.218 2.139 7.782S7.954 21.38 7.419 21.498c-.535.119-2.911-5.822-2.495-10.158.416-4.337 2.97-8.079 4.693-8.376z"/><path fill="#909B50" d="M32.341 19.492c-.8 2.707-3.459 2.674-6.086 1.812s-4.871-3.285-4.381-5.492c.49-2.207 3.918-2.536 6.613-1.724 2.695.813 4.549 3.051 3.854 5.404z"/><path fill="#C7CC62" d="M27.109 14.505c1.928.463 3.149 1.248 3.505 1.842.356.594-.059 1.248-.95.594-.891-.653-3.03-1.485-4.099-1.663-1.07-.179.059-1.13 1.544-.773zM16 4.228c1.399-.646 2.673 0 2.614.416-.059.416-1.842 0-2.673.891s-1.96 1.307-1.723.653 1.01-1.604 1.782-1.96zm1.544 20.019c1.432.102 2.97 2.198 2.436 2.614s-1.663-1.663-2.733-1.901c-1.069-.237-1.366-.831.297-.713z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/1fad6.svg b/browser/components/torpreferences/content/bridgemoji/svgs/1fad6.svg new file mode 100644 index 0000000000000000000000000000000000000000..9e6894dafeee6f1f2b178cd0da79a36c4f27f212 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/1fad6.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#269" cx="17.5" cy="31.5" rx="8" ry="2"/><path fill="#3B88C3" d="M11.173 31.777s3.297.757 6.371.668c2.539-.074 5.614-.356 6.505-.757 0 0-1.069 1.381-6.416 1.381s-6.46-1.292-6.46-1.292z"/><ellipse fill="#269" cx="17.5" cy="15.25" rx="8.5" ry="2.25"/><path fill="#3B88C3" d="M33.582 16.654c3.518-.202 2.185 1.133 1.072 1.712-.505.262-1.515 1.738-2.098 4.234-.455 1.948-.847 5.658-5.213 5.391-2.994-.183-.045-7.084-.045-7.084s1.871 3.119 3.876-1.47c.895-2.049 1.409-2.726 2.408-2.783zM5.829 28.351c-1.112 0-2.138-.351-3.021-1.04C.858 25.789.167 22.812.167 21c0-2.422 1.331-4.875 3.875-4.875 1.546 0 2.209.537 2.911 1.104.394.319.801.648 1.48.988l-.782 1.931c-.849-.424-1.375-.85-1.798-1.192-.607-.491-.884-.715-1.811-.715-1.46 0-2.125 1.254-2.125 2.759 0 1.531.608 3.551 1.967 4.611.822.643 1.815.822 2.945.54l.425 2.017c-.486.122-.963.183-1.425.183z"/><path fill="#3B88C3" d="M29 24.727C29 31.254 22.1 32 17.5 32S6 31.254 6 24.727 10.775 12 17.5 12 29 18.2 29 24.727z"/><path fill="#269" d="M29.485 26.965c-.489.039-1.069-.757-1.069-.757-.847 2.049-3.342 4.589-11.139 4.589-6.995 0-9.579-2.139-10.96-3.965 0 0 .33 1.202-1.782.757-.648-.137-1.926-.768-2.966-1.658.34.524.749.998 1.239 1.38.883.689 1.91 1.04 3.021 1.04.354 0 .718-.047 1.087-.118 2.02 3.3 6.932 3.847 10.521 3.847 3.679 0 8.883-.566 10.798-4.097 3.525-.265 3.898-3.577 4.32-5.382.439-1.88 1.12-3.18 1.645-3.82-.03.013-.051.016-.082.031-1.826.891-1.871 7.93-4.633 8.153zM4.891 17.698c-.64-.362-1.96-.223-2.629.891-.442.736-.471 1.642-.34 2.316.028-1.462.691-2.664 2.12-2.664.926 0 1.204.224 1.811.715.289.234.636.508 1.092.793l.174-.492s-1.203-.98-2.228-1.559zm19.663-3.704c.284.159.446.328.446.506 0 .828-3.358 1.5-7.5 1.5s-7.5-.672-7.5-1.5c0-.178.162-.347.446-.506C9.533 14.353 9 14.785 9 15.25c0 1.243 3.806 2.25 8.5 2.25s8.5-1.007 8.5-2.25c0-.465-.533-.897-1.446-1.256z"/><ellipse fill="#269" cx="17.5" cy="11" rx="2.8" ry="1.5"/><ellipse fill="#269" cx="34.364" cy="17.141" rx="1.047" ry=".334"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/23f0.svg b/browser/components/torpreferences/content/bridgemoji/svgs/23f0.svg new file mode 100644 index 0000000000000000000000000000000000000000..ea9ad143166154b3641081203eb45ea6c4e76497 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/23f0.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M20 6.042c0 1.112-.903 2.014-2 2.014s-2-.902-2-2.014V2.014C16 .901 16.903 0 18 0s2 .901 2 2.014v4.028z"/><path fill="#FFAC33" d="M9.18 36c-.224 0-.452-.052-.666-.159-.736-.374-1.035-1.28-.667-2.027l8.94-18.127c.252-.512.768-.835 1.333-.835s1.081.323 1.333.835l8.941 18.127c.368.747.07 1.653-.666 2.027-.736.372-1.631.07-1.999-.676L18.121 19.74l-7.607 15.425c-.262.529-.788.835-1.334.835z"/><path fill="#58595B" d="M18.121 20.392c-.263 0-.516-.106-.702-.295L3.512 5.998c-.388-.394-.388-1.031 0-1.424s1.017-.393 1.404 0L18.121 17.96 31.324 4.573c.389-.393 1.017-.393 1.405 0 .388.394.388 1.031 0 1.424l-13.905 14.1c-.187.188-.439.295-.703.295z"/><path fill="#DD2E44" d="M34.015 19.385c0 8.898-7.115 16.111-15.894 16.111-8.777 0-15.893-7.213-15.893-16.111 0-8.9 7.116-16.113 15.893-16.113 8.778-.001 15.894 7.213 15.894 16.113z"/><path fill="#E6E7E8" d="M30.041 19.385c0 6.674-5.335 12.084-11.92 12.084-6.583 0-11.919-5.41-11.919-12.084C6.202 12.71 11.538 7.3 18.121 7.3c6.585-.001 11.92 5.41 11.92 12.085z"/><path fill="#FFCC4D" d="M30.04 1.257c-1.646 0-3.135.676-4.214 1.77l8.429 8.544C35.333 10.478 36 8.968 36 7.299c0-3.336-2.669-6.042-5.96-6.042zm-24.08 0c1.645 0 3.135.676 4.214 1.77l-8.429 8.544C.667 10.478 0 8.968 0 7.299c0-3.336 2.668-6.042 5.96-6.042z"/><path fill="#414042" d="M23 20h-5c-.552 0-1-.447-1-1v-9c0-.552.448-1 1-1s1 .448 1 1v8h4c.553 0 1 .448 1 1 0 .553-.447 1-1 1z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2600.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2600.svg new file mode 100644 index 0000000000000000000000000000000000000000..8602baef7e5aa673bcce7e4e3397b70232860c1f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2600.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M16 2s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2V2zm18 14s2 0 2 2-2 2-2 2h-2s-2 0-2-2 2-2 2-2h2zM4 16s2 0 2 2-2 2-2 2H2s-2 0-2-2 2-2 2-2h2zm5.121-8.707s1.414 1.414 0 2.828-2.828 0-2.828 0L4.878 8.708s-1.414-1.414 0-2.829c1.415-1.414 2.829 0 2.829 0l1.414 1.414zm21 21s1.414 1.414 0 2.828-2.828 0-2.828 0l-1.414-1.414s-1.414-1.414 0-2.828 2.828 0 2.828 0l1.414 1.414zm-.413-18.172s-1.414 1.414-2.828 0 0-2.828 0-2.828l1.414-1.414s1.414-1.414 2.828 0 0 2.828 0 2.828l-1.414 1.414zm-21 21s-1.414 1.414-2.828 0 0-2.828 0-2.828l1.414-1.414s1.414-1.414 2.828 0 0 2.828 0 2.828l-1.414 1.414zM16 32s0-2 2-2 2 2 2 2v2s0 2-2 2-2-2-2-2v-2z"/><circle fill="#FFAC33" cx="18" cy="18" r="10"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2602.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2602.svg new file mode 100644 index 0000000000000000000000000000000000000000..7c633302e7e8f58d8e31ca78e596e13d2ad29f7a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2602.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M9 28.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5v.5s0 3 3 3 3-3 3-3V3.5c0-.829.671-1.5 1.5-1.5s1.5.671 1.5 1.5V29s0 6-6 6-6-6-6-6v-.5z"/><path fill="#744EAA" d="M19.5 4C28.612 4 36 9.82 36 17c0 0 0 2-1 2s-3-2-3-2H7s-2 2-3 2-1-2-1-2C3 9.82 10.387 4 19.5 4z"/><path fill="#9266CC" d="M19.5 4C26.403 4 32 9.82 32 17c0 0 0 2-2 2s-5-2-5-2H14s-3 2-5 2-2-2-2-2C7 9.82 12.596 4 19.5 4z"/><path fill="#744EAA" d="M19.5 4C23.09 4 25 9.82 25 17c0 0-3 2-5 2h-1c-2 0-5-2-5-2 0-7.18 1.91-13 5.5-13z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2604.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2604.svg new file mode 100644 index 0000000000000000000000000000000000000000..07df915c4f9b632c4bbac5752f878b70aedacabc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2604.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5DADEC" d="M33.662.049c-1.148-.077-5.869-.75-17.522 6.665C4.488 14.129-1.646 26.609 3.604 33.329c1.104 1.413 5.518 4.283 10.682.53 3.247-2.359 4.242-7.52 7.15-14.434 1.986-4.723 6.444-13.594 12.668-17.611 1.942-.97.22-1.72-.442-1.765z"/><path fill="#8CCAF7" d="M16.625 13.651c-.265-1.059.971-4.281 1.324-5.164-6.437 2.929-12.509 11.616-12.47 13.18.006.227.139.305.42.193 5.398-2.166 8.882 1.07 9.807 3.751.095.274.214.414.339.44.171.036.352-.15.494-.557C18.565 19.675 23.112 9.055 27.835 5c-2.648 1.28-10.106 6.797-11.21 8.651z"/><path fill="#BDDDF4" d="M14.242 12.989c-1.737.827-7.275 6.192-8.762 8.678.006.227.139.305.42.193 5.398-2.166 8.882 1.07 9.807 3.751.095.274.214.414.339.44.057-2.328-.092-7.616 2.213-11.561-4.061 3.707-5.076 3.618-4.017-1.501z"/><path fill="#F5F8FA" d="M8.725 23.663c-2.925 0-5.297 2.371-5.297 5.297 0 2.925 2.372 5.296 5.297 5.296s5.296-2.371 5.296-5.296c0-2.926-2.371-5.297-5.296-5.297z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/260e.svg b/browser/components/torpreferences/content/bridgemoji/svgs/260e.svg new file mode 100644 index 0000000000000000000000000000000000000000..e65124faa5485baec829faa2357544d1607ec366 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/260e.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M36 11.5C36 8.462 33 4 18 4S0 8.462 0 11.5c0 .045.019.076.022.119-.012.196-.022.402-.022.631C0 14.873 2.239 16 5 16s5-1.127 5-3.75c0-.218-.021-.412-.051-.597C12.374 11.302 15.102 11 18 11s5.626.302 8.051.653c-.03.185-.051.379-.051.597 0 2.623 2.238 3.75 5 3.75s5-1.127 5-3.75c0-.225-.009-.429-.024-.621.004-.046.024-.08.024-.129z"/><path fill="#DD2E44" d="M34.934 23c-.482-1.031-2.31-4.19-3.968-7.007C29.408 13.346 27 11 25 11V9c0-1.104-.896-2-2-2s-2 .896-2 2v2h-6V9c0-1.104-.896-2-2-2s-2 .896-2 2v2c-2 0-4.41 2.351-5.97 5-1.657 2.815-3.483 5.97-3.964 7C.488 24.239 0 25 0 27s1.791 5 4 5h28c2.209 0 4-3 4-5s-.448-2.676-1.066-4z"/><path fill="#FFF" d="M20.046 14.818c0 .452-.916.818-2.046.818s-2.045-.366-2.045-.818c0-.452.915-.818 2.045-.818s2.046.366 2.046.818zm-4.91 0c0 .452-.915.818-2.045.818s-2.045-.366-2.045-.818c0-.452.916-.818 2.045-.818s2.045.366 2.045.818zm9.818 0c0 .452-.915.818-2.045.818s-2.046-.366-2.046-.818c0-.452.916-.818 2.046-.818s2.045.366 2.045.818zm-4.5 2.864c0 .679-1.099 1.228-2.454 1.228s-2.455-.549-2.455-1.228c0-.677 1.099-1.227 2.455-1.227s2.454.549 2.454 1.227zm5.728 0c0 .679-1.1 1.228-2.454 1.228-1.355 0-2.455-.549-2.455-1.228 0-.677 1.1-1.227 2.455-1.227 1.354 0 2.454.549 2.454 1.227zm-11.455 0c0 .679-1.099 1.228-2.454 1.228-1.355 0-2.455-.549-2.455-1.228 0-.677 1.099-1.227 2.455-1.227 1.355 0 2.454.549 2.454 1.227zm6.545 3.681C21.272 22.269 19.807 23 18 23c-1.807 0-3.273-.731-3.273-1.637 0-.903 1.466-1.636 3.273-1.636 1.807.001 3.272.733 3.272 1.636zm7.365 0c0 .905-1.467 1.637-3.273 1.637-1.807 0-3.273-.731-3.273-1.637 0-.903 1.466-1.636 3.273-1.636 1.806.001 3.273.733 3.273 1.636zm-14.728 0c0 .905-1.466 1.637-3.273 1.637-1.807 0-3.272-.731-3.272-1.637 0-.903 1.465-1.636 3.272-1.636 1.807.001 3.273.733 3.273 1.636z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2693.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2693.svg new file mode 100644 index 0000000000000000000000000000000000000000..09f3fe4162e129a597ba14f21325fb36b0e4573f --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2693.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#269" d="M30.5 18.572L26 25h2.575c-1.13 3.988-4.445 7.05-8.575 7.81V17h3c1.104 0 2-.896 2-2s-.896-2-2-2h-3v-1.349h-4V13h-3c-1.104 0-2 .896-2 2s.896 2 2 2h3v15.81c-4.13-.76-7.445-3.821-8.575-7.81H10l-4.5-6.428L1 25h3.33C5.705 31.289 11.299 36 18 36s12.295-4.711 13.67-11H35l-4.5-6.428z"/><path fill="#269" d="M18 0c-3.314 0-6 2.686-6 6s2.686 6 6 6 6-2.686 6-6-2.686-6-6-6zm0 9c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2696.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2696.svg new file mode 100644 index 0000000000000000000000000000000000000000..61af8441c5a75b9fc7b4ff353960a71c345a0f83 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2696.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M3.923 22.923c-.212.511-.798.751-1.308.539-.51-.213-.751-.798-.539-1.308L6.693 9.616c.212-.51.798-.751 1.307-.539.51.213.751.798.539 1.308L3.923 22.923z"/><path fill="#66757F" d="M13.923 22.154c.212.51-.029 1.095-.539 1.308-.51.212-1.095-.028-1.308-.539L7.461 10.385c-.212-.51.029-1.095.539-1.308.51-.212 1.095.029 1.308.539l4.615 12.538zm10.001.769c-.213.511-.799.751-1.309.539-.51-.213-.75-.798-.538-1.308l4.616-12.539c.212-.509.797-.75 1.307-.538.51.213.752.798.539 1.308l-4.615 12.538z"/><path fill="#66757F" d="M33.923 22.154c.212.51-.028 1.095-.538 1.308-.51.212-1.096-.028-1.309-.539l-4.615-12.538c-.213-.51.029-1.095.539-1.308.51-.212 1.095.029 1.307.539l4.616 12.538z"/><path fill="#FFAC33" d="M14.857 22H1.143C.512 22 0 22.511 0 23.143c0 2.524 3.582 4.571 8 4.571s8-2.047 8-4.571c0-.632-.512-1.143-1.143-1.143zM24 34H12c-.552 0-1-.447-1-1 0-2.209 3.134-4 7-4s7 1.791 7 4c0 .553-.447 1-1 1zm10.857-12H21.143c-.632 0-1.143.511-1.143 1.143 0 2.524 3.581 4.571 8 4.571s8-2.047 8-4.571c0-.632-.511-1.143-1.143-1.143z"/><path fill="#FFAC33" d="M19 3c0-.552-.447-1-1-1-.552 0-1 .448-1 1v27c0 .553.448 1 1 1 .553 0 1-.447 1-1V3z"/><circle fill="#FFAC33" cx="18" cy="4" r="2"/><circle fill="#FFAC33" cx="8" cy="10" r="2"/><circle fill="#FFAC33" cx="28" cy="10" r="2"/><path fill="#FFAC33" d="M28 10c0 1.104 0 0-10 0S8 11.104 8 10s3-4 10-4 10 2.896 10 4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/26bd.svg b/browser/components/torpreferences/content/bridgemoji/svgs/26bd.svg new file mode 100644 index 0000000000000000000000000000000000000000..f24749cb5eab382f9e40e4dae8e936d8eaae0829 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/26bd.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F5F8FA" cx="18" cy="18" r="18"/><path d="M18 11c-.552 0-1-.448-1-1V3c0-.552.448-1 1-1s1 .448 1 1v7c0 .552-.448 1-1 1zm-6.583 4.5c-.1 0-.202-.015-.302-.047l-8.041-2.542c-.527-.167-.819-.728-.652-1.255.166-.527.73-.818 1.255-.652l8.042 2.542c.527.167.819.729.652 1.255-.136.426-.53.699-.954.699zm13.625-.291c-.434 0-.833-.285-.96-.722-.154-.531.151-1.085.682-1.239l6.75-1.958c.531-.153 1.085.153 1.238.682.154.531-.151 1.085-.682 1.239l-6.75 1.958c-.092.027-.186.04-.278.04zm2.001 14.958c-.306 0-.606-.14-.803-.403l-5.459-7.333c-.33-.442-.238-1.069.205-1.399.442-.331 1.069-.238 1.399.205l5.459 7.333c.33.442.238 1.069-.205 1.399-.179.134-.389.198-.596.198zm-18.294-.083c-.197 0-.395-.058-.57-.179-.454-.316-.565-.938-.25-1.392l5.125-7.375c.315-.454.938-.566 1.392-.251.454.315.565.939.25 1.392l-5.125 7.375c-.194.281-.506.43-.822.43zM3.5 27.062c-.44 0-.844-.293-.965-.738L.347 18.262c-.145-.533.17-1.082.704-1.227.535-.141 1.083.171 1.227.704l2.188 8.062c.145.533-.17 1.082-.704 1.226-.088.025-.176.035-.262.035zM22 34h-9c-.552 0-1-.447-1-1s.448-1 1-1h9c.553 0 1 .447 1 1s-.447 1-1 1zm10.126-6.875c-.079 0-.16-.009-.24-.029-.536-.132-.864-.674-.731-1.21l2.125-8.625c.133-.536.679-.862 1.21-.732.536.132.864.674.731 1.211l-2.125 8.625c-.113.455-.521.76-.97.76zM30.312 7.688c-.17 0-.342-.043-.5-.134L22.25 3.179c-.478-.277-.642-.888-.364-1.367.275-.478.886-.643 1.366-.365l7.562 4.375c.478.277.642.888.364 1.367-.185.32-.521.499-.866.499zm-24.811 0c-.312 0-.618-.145-.813-.417-.322-.45-.22-1.074.229-1.396l6.188-4.438c.449-.322 1.074-.219 1.396.229.322.449.219 1.074-.229 1.396L6.083 7.5c-.177.126-.38.188-.582.188z" fill="#CCD6DD"/><path d="M25.493 13.516l-7.208-5.083c-.348-.245-.814-.243-1.161.006l-7.167 5.167c-.343.248-.494.684-.375 1.091l2.5 8.583c.124.426.515.72.96.72H22c.43 0 .81-.274.948-.681l2.917-8.667c.141-.419-.011-.881-.372-1.136zM1.292 19.542c.058 0 .117-.005.175-.016.294-.052.55-.233.697-.494l3.375-6c.051-.091.087-.188.108-.291L6.98 6.2c.06-.294-.016-.6-.206-.832C6.584 5.135 6.3 5 6 5h-.428C2.145 8.277 0 12.884 0 18c0 .266.028.525.04.788l.602.514c.182.156.413.24.65.24zm9.325-16.547c.106.219.313.373.553.412l6.375 1.042c.04.006.081.01.121.01.04 0 .081-.003.122-.01l6.084-1c.2-.033.38-.146.495-.314.116-.168.158-.375.118-.575l-.292-1.443C22.26.407 20.18 0 18 0c-2.425 0-4.734.486-6.845 1.356l-.521.95c-.117.213-.123.47-.017.689zm20.517 2.724l-1.504-.095c-.228-.013-.455.076-.609.249-.152.173-.218.402-.175.63l1.167 6.198c.017.086.048.148.093.224 1.492 2.504 3.152 5.301 3.381 5.782.024.084.062.079.114.151.14.195.372.142.612.142h.007c.198 0 .323.094 1.768-.753.001-.083.012-.164.012-.247 0-4.753-1.856-9.064-4.866-12.281zM14.541 33.376c.011-.199-.058-.395-.191-.544l-4.5-5c-.06-.066-.131-.122-.211-.163-5.885-3.069-5.994-3.105-6.066-3.13-.078-.025-.161-.039-.242-.039-.537 0-.695.065-1.185 2.024 2.236 4.149 6.053 7.316 10.644 8.703l1.5-1.333c.149-.132.239-.319.251-.518zm17.833-8.567c-.189-.08-.405-.078-.592.005l-6.083 2.667c-.106.046-.2.116-.274.205l-4.25 5.083c-.129.154-.19.352-.172.552.02.2.117.384.272.51.683.559 1.261 1.03 1.767 1.44 4.437-1.294 8.154-4.248 10.454-8.146l-.712-1.889c-.072-.193-.221-.347-.41-.427z" fill="#31373D"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/26f2.svg b/browser/components/torpreferences/content/bridgemoji/svgs/26f2.svg new file mode 100644 index 0000000000000000000000000000000000000000..659c22850c5d374a528dc7ad92e7eb448e52e4cd --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/26f2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#99AAB5" d="M1 22.923v6.538C1 33.073 8.611 36 18 36s17-2.927 17-6.538v-6.538H1z"/><ellipse fill="#E1E8ED" cx="18" cy="22.923" rx="17" ry="6.538"/><path fill="#AAB8C2" d="M18 20.308c6.7 0 12.314 1.668 13.913 3.923.297-.419.472-.855.472-1.308 0-2.889-6.44-5.231-14.385-5.231S3.615 20.034 3.615 22.923c0 .452.175.889.472 1.308C5.686 21.976 11.3 20.308 18 20.308z"/><ellipse fill="#3B88C3" cx="18" cy="24.231" rx="13.913" ry="3.923"/><path fill="#50A5E6" d="M18 22.128c-4.497 0-9.625 1.285-9.625 2.103 0 .818 5.129 2.102 9.625 2.102s9.625-1.284 9.625-2.102c0-.818-5.128-2.103-9.625-2.103z"/><path fill="#E1E8ED" d="M15 22.615V24c0 .553 1.343 1 3 1s3-.447 3-1v-1.385h-6z"/><ellipse fill="#AAB8C2" cx="18" cy="22.615" rx="3" ry="1"/><path fill="#1C6399" d="M9 15.786c-.552 0-1-.448-1-1V13.5C8 10.467 10.467 8 13.5 8s5.5 2.467 5.5 5.5c0 .552-.447 1-1 1-.552 0-1-.448-1-1 0-1.93-1.57-3.5-3.5-3.5S10 11.57 10 13.5v1.286c0 .552-.448 1-1 1z"/><path fill="#88C9F9" d="M26 18c-.553 0-1-.448-1-1v-1.143c0-1.654-1.346-3-3-3s-3 1.346-3 3c0 .552-.447 1-1 1-.552 0-1-.448-1-1 0-2.757 2.243-5 5-5s5 2.243 5 5V17c0 .552-.447 1-1 1z"/><path fill="#1C6399" d="M32 11.125c-.553 0-1-.448-1-1 0-3.309-2.691-6-6-6s-6 2.691-6 6c0 .552-.447 1-1 1-.552 0-1-.448-1-1 0-4.411 3.589-8 8-8s8 3.589 8 8c0 .552-.447 1-1 1z"/><path fill="#3B94D9" d="M17 22.659h2V8c0-4.411-3.589-8-8-8S3 3.589 3 8c0 .552.448 1 1 1s1-.448 1-1c0-3.309 2.691-6 6-6s6 2.691 6 6v14.659z"/><circle fill="#1C6399" cx="32" cy="14" r="1"/><circle fill="#BBDDF5" cx="26" cy="21" r="1"/><circle fill="#BBDDF5" cx="33" cy="2" r="1"/><circle fill="#F2F9FF" cx="14" cy="20" r="1"/><circle fill="#50A5E6" cx="26" cy="9" r="1"/><circle fill="#1C6399" cx="20" cy="1" r="1"/><circle fill="#1C6399" cx="9" cy="18" r="1"/><circle fill="#3B94D9" cx="4" cy="13" r="1"/><circle fill="#88C9F9" cx="11" cy="5" r="1"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/26f5.svg b/browser/components/torpreferences/content/bridgemoji/svgs/26f5.svg new file mode 100644 index 0000000000000000000000000000000000000000..c76c0dedfb1f10f95defbb81eaed47faf8c918b3 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/26f5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A7A9AC" d="M20 26c0 .553-.447 1-1 1-.552 0-1-.447-1-1V1c0-.552.448-1 1-1 .553 0 1 .448 1 1v25z"/><path fill="#D1D3D4" d="M3 24h31v8H12c-6 0-9-8-9-8z"/><path fill="#55ACEE" d="M0 30h36v6H0z"/><path fill="#FFAC33" d="M5 22s2-5 5-9 8-8 8-8-1 11-1 16v1s-3-1-6-1-6 1-6 1z"/><path fill="#F4900C" d="M20 2s6 6 9 11c2.771 4.618 4 9 4 9s-3-1-6-1-6 1-6 1v-1c0-9-1-19-1-19z"/><path fill="#E6E7E8" d="M2 24c-.552 0-1 .447-1 1s.448 1 1 1h33v-2H2z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2708.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2708.svg new file mode 100644 index 0000000000000000000000000000000000000000..ebce3afbc7832ce0880982c0955ac9ea1038f61c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2708.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M30 23.828c-.391.392-1.023.392-1.414 0l-1.414-1.414c-.392-.391-.392-1.024 0-1.414L30 18.172c.391-.391 1.023-.391 1.414 0l1.414 1.414c.392.391.392 1.024 0 1.414L30 23.828zm-15-15c-.391.392-1.023.392-1.414 0l-1.414-1.414c-.392-.391-.392-1.023 0-1.414L15 3.172c.391-.391 1.023-.391 1.414 0l1.414 1.414c.392.391.392 1.023 0 1.414L15 8.828z"/><path fill="#55ACEE" d="M2 22c2 0 11 1 11 1s1 9 1 11-2 2-3 1-4-6-4-6-5-3-6-4-1-3 1-3zM4 6.039C7 6 29 7 29 7s.924 22 .962 25c.038 3-2.763 4.002-3.862.001S21 15 21 15 7.045 10.583 3.995 9.898C0 9 .999 6.077 4 6.039z"/><path fill="#CCD6DD" d="M27 3c2-2 7-3 8-2s0 6-2 8-19 18-19 18-6.5 4.5-8 3 3-8 3-8S25 5 27 3z"/><path fill="#66757F" d="M14 22s.5.5-4 5-5 4-5 4-.5-.5 4-5 5-4 5-4zM29 4c1.657 0 3 1.343 3 3h.805c.114-.315.195-.645.195-1 0-1.657-1.343-3-3-3-.355 0-.685.081-1 .195V4z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/270f.svg b/browser/components/torpreferences/content/bridgemoji/svgs/270f.svg new file mode 100644 index 0000000000000000000000000000000000000000..a9b69e1b29529573191551dee603c949790b2310 --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/270f.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#D99E82" d="M35.222 33.598c-.647-2.101-1.705-6.059-2.325-7.566-.501-1.216-.969-2.438-1.544-3.014-.575-.575-1.553-.53-2.143.058 0 0-2.469 1.675-3.354 2.783-1.108.882-2.785 3.357-2.785 3.357-.59.59-.635 1.567-.06 2.143.576.575 1.798 1.043 3.015 1.544 1.506.62 5.465 1.676 7.566 2.325.359.11 1.74-1.271 1.63-1.63z"/><path fill="#EA596E" d="M13.643 5.308c1.151 1.151 1.151 3.016 0 4.167l-4.167 4.168c-1.151 1.15-3.018 1.15-4.167 0L1.141 9.475c-1.15-1.151-1.15-3.016 0-4.167l4.167-4.167c1.15-1.151 3.016-1.151 4.167 0l4.168 4.167z"/><path fill="#FFCC4D" d="M31.353 23.018l-4.17 4.17-4.163 4.165L7.392 15.726l8.335-8.334 15.626 15.626z"/><path fill="#292F33" d="M32.078 34.763s2.709 1.489 3.441.757c.732-.732-.765-3.435-.765-3.435s-2.566.048-2.676 2.678z"/><path fill="#CCD6DD" d="M2.183 10.517l8.335-8.335 5.208 5.209-8.334 8.335z"/><path fill="#99AAB5" d="M3.225 11.558l8.334-8.334 1.042 1.042L4.267 12.6zm2.083 2.086l8.335-8.335 1.042 1.042-8.335 8.334z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2728.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2728.svg new file mode 100644 index 0000000000000000000000000000000000000000..347ad12abbd7b0699a98696bef0dc92341ae953c --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2728.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFAC33" d="M34.347 16.893l-8.899-3.294-3.323-10.891c-.128-.42-.517-.708-.956-.708-.439 0-.828.288-.956.708l-3.322 10.891-8.9 3.294c-.393.146-.653.519-.653.938 0 .418.26.793.653.938l8.895 3.293 3.324 11.223c.126.424.516.715.959.715.442 0 .833-.291.959-.716l3.324-11.223 8.896-3.293c.391-.144.652-.518.652-.937 0-.418-.261-.792-.653-.938z"/><path fill="#FFCC4D" d="M14.347 27.894l-2.314-.856-.9-3.3c-.118-.436-.513-.738-.964-.738-.451 0-.846.302-.965.737l-.9 3.3-2.313.856c-.393.145-.653.52-.653.938 0 .418.26.793.653.938l2.301.853.907 3.622c.112.444.511.756.97.756.459 0 .858-.312.97-.757l.907-3.622 2.301-.853c.393-.144.653-.519.653-.937 0-.418-.26-.793-.653-.937zM10.009 6.231l-2.364-.875-.876-2.365c-.145-.393-.519-.653-.938-.653-.418 0-.792.26-.938.653l-.875 2.365-2.365.875c-.393.146-.653.52-.653.938 0 .418.26.793.653.938l2.365.875.875 2.365c.146.393.52.653.938.653.418 0 .792-.26.938-.653l.875-2.365 2.365-.875c.393-.146.653-.52.653-.938 0-.418-.26-.792-.653-.938z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/2744.svg b/browser/components/torpreferences/content/bridgemoji/svgs/2744.svg new file mode 100644 index 0000000000000000000000000000000000000000..258c161bb9bb8ab929b87b9905b815aeb941d10a --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/2744.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#88C9F9" d="M19 27.586V8.415l4.828-4.829s.707-.707 0-1.415c-.707-.707-1.414 0-1.414 0L19 5.586V1s0-1-1-1-1 1-1 1v4.586l-3.414-3.415s-.707-.707-1.414 0c-.707.708 0 1.415 0 1.415L17 8.415v19.171l-4.828 4.828s-.707.707 0 1.414 1.414 0 1.414 0L17 30.414V35s0 1 1 1 1-1 1-1v-4.586l3.414 3.414s.707.707 1.414 0 0-1.414 0-1.414L19 27.586z"/><path fill="#88C9F9" d="M34.622 20.866c-.259-.966-1.225-.707-1.225-.707l-6.595 1.767-16.603-9.586-1.767-6.595s-.259-.966-1.225-.707C6.24 5.297 6.5 6.263 6.5 6.263l1.25 4.664-3.972-2.294s-.866-.5-1.366.366c-.5.866.366 1.366.366 1.366l3.971 2.293-4.664 1.249s-.967.259-.707 1.225c.259.967 1.225.708 1.225.708l6.596-1.767 16.603 9.586 1.767 6.596s.259.966 1.225.707c.966-.26.707-1.225.707-1.225l-1.25-4.664 3.972 2.293s.867.5 1.367-.365c.5-.867-.367-1.367-.367-1.367l-3.971-2.293 4.663-1.249c0-.001.966-.26.707-1.226z"/><path fill="#88C9F9" d="M33.915 13.907l-4.664-1.25 3.972-2.293s.867-.501.367-1.367c-.501-.867-1.367-.366-1.367-.366l-3.971 2.292 1.249-4.663s.259-.966-.707-1.225c-.966-.259-1.225.707-1.225.707l-1.767 6.595-16.604 9.589-6.594-1.768s-.966-.259-1.225.707c-.26.967.707 1.225.707 1.225l4.663 1.249-3.971 2.293s-.865.501-.365 1.367c.5.865 1.365.365 1.365.365l3.972-2.293-1.25 4.663s-.259.967.707 1.225c.967.26 1.226-.706 1.226-.706l1.768-6.597 16.604-9.585 6.595 1.768s.966.259 1.225-.707c.255-.967-.71-1.225-.71-1.225z"/></svg> \ No newline at end of file diff --git a/browser/components/torpreferences/content/bridgemoji/svgs/README.txt b/browser/components/torpreferences/content/bridgemoji/svgs/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..08cee867d4c9e991862ba2a0156a5408e5a4f6bc --- /dev/null +++ b/browser/components/torpreferences/content/bridgemoji/svgs/README.txt @@ -0,0 +1 @@ +Generated by tools/torbrowser/update_emojis.py on 2024-08-06 diff --git a/browser/components/torpreferences/content/builtinBridgeDialog.js b/browser/components/torpreferences/content/builtinBridgeDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..ea6b7e1cc98c96c3f552dced54b4e092e19c52f2 --- /dev/null +++ b/browser/components/torpreferences/content/builtinBridgeDialog.js @@ -0,0 +1,139 @@ +"use strict"; + +const { TorSettings, TorBridgeSource } = ChromeUtils.importESModule( + "resource://gre/modules/TorSettings.sys.mjs" +); + +const { TorConnect, TorConnectStage, TorConnectTopics } = + ChromeUtils.importESModule("resource://gre/modules/TorConnect.sys.mjs"); + +const gBuiltinBridgeDialog = { + init() { + this._result = window.arguments[0]; + + this._radioGroup = document.getElementById( + "torPreferences-builtinBridge-typeSelection" + ); + + const currentBuiltinType = + TorSettings.bridges.enabled && + TorSettings.bridges.source == TorBridgeSource.BuiltIn + ? TorSettings.bridges.builtin_type + : null; + + for (const optionEl of this._radioGroup.querySelectorAll( + ".builtin-bridges-option" + )) { + const radio = optionEl.querySelector("radio"); + const type = radio.value; + optionEl.hidden = !TorSettings.builtinBridgeTypes.includes(type); + + const descriptionEl = optionEl.querySelector( + ".builtin-bridges-option-description" + ); + // Set an id to be used for the aria-describedby. + descriptionEl.id = `builtin-bridges-description-${type}`; + const currentBadge = optionEl.querySelector(".bridge-status-badge"); + if (type === currentBuiltinType) { + const currentLabelEl = optionEl.querySelector( + ".torPreferences-current-bridge-label" + ); + currentLabelEl.id = `builtin-bridges-current-${type}`; + // Described by both the current badge and the full description. + // These will be concatenated together in the screen reader output. + radio.setAttribute( + "aria-describedby", + `${currentLabelEl.id} ${descriptionEl.id}` + ); + // Make visible. + currentBadge.classList.add("bridge-status-current-built-in"); + } else { + // No visible badge. + radio.setAttribute("aria-describedby", descriptionEl.id); + currentBadge.classList.remove("bridge-status-current-built-in"); + } + } + + if (currentBuiltinType) { + this._radioGroup.value = currentBuiltinType; + } else { + this._radioGroup.selectedItem = null; + } + + this._radioGroup.addEventListener("select", () => this.onSelectChange()); + + const dialog = document.getElementById( + "torPreferences-builtinBridge-dialog" + ); + dialog.addEventListener("dialogaccept", () => { + this._result.accepted = true; + }); + + // Add styling for tor-button to the dialog shadow root. + const styleLink = document.createElement("link"); + styleLink.rel = "stylesheet"; + styleLink.href = + "chrome://browser/content/torpreferences/torPreferences.css"; + dialog.shadowRoot.append(styleLink); + + this._acceptButton = dialog.getButton("accept"); + + Services.obs.addObserver(this, TorConnectTopics.StageChange); + + this.onSelectChange(); + this.onAcceptStateChange(); + }, + + uninit() { + Services.obs.removeObserver(this, TorConnectTopics.StageChange); + }, + + onSelectChange() { + const value = this._radioGroup.value; + this._acceptButton.disabled = !value; + this._result.type = value; + }, + + onAcceptStateChange() { + const connect = TorConnect.stageName !== TorConnectStage.Bootstrapped; + this._result.connect = connect; + this._acceptButton.setAttribute( + "data-l10n-id", + connect ? "bridge-dialog-button-connect" : "bridge-dialog-button-accept" + ); + this._acceptButton.classList.toggle("tor-button", connect); + }, + + observe(subject, topic) { + switch (topic) { + case TorConnectTopics.StageChange: + this.onAcceptStateChange(); + break; + } + }, +}; + +// Initial focus is not visible, even if opened with a keyboard. We avoid the +// default handler and manage the focus ourselves, which will paint the focus +// ring by default. +// NOTE: A side effect is that the focus ring will show even if the user opened +// with a mouse event. +// TODO: Remove this once bugzilla bug 1708261 is resolved. +document.subDialogSetDefaultFocus = () => { + document.getElementById("torPreferences-builtinBridge-typeSelection").focus(); +}; + +window.addEventListener( + "DOMContentLoaded", + () => { + gBuiltinBridgeDialog.init(); + window.addEventListener( + "unload", + () => { + gBuiltinBridgeDialog.uninit(); + }, + { once: true } + ); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/builtinBridgeDialog.xhtml b/browser/components/torpreferences/content/builtinBridgeDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..cbd074a96ef21d1514dd96506d904bc417146c59 --- /dev/null +++ b/browser/components/torpreferences/content/builtinBridgeDialog.xhtml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="built-in-dialog-title" +> + <dialog id="torPreferences-builtinBridge-dialog" buttons="accept,cancel"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/builtinBridgeDialog.js" /> + + <description data-l10n-id="built-in-dialog-introduction"></description> + <radiogroup id="torPreferences-builtinBridge-typeSelection"> + <vbox class="builtin-bridges-option"> + <hbox> + <!-- The radio option is described by both the "Current bridge" label + - and the full description. If the "Connected" label is hidden, then + - only the latter description should contribute. --> + <radio + value="obfs4" + data-l10n-id="built-in-dialog-obfs4-radio-option" + /> + <html:span class="bridge-status-badge"> + <html:div class="bridge-status-icon"></html:div> + <html:span + class="torPreferences-current-bridge-label" + data-l10n-id="built-in-dialog-current-bridge-label" + > + </html:span> + </html:span> + </hbox> + <html:div + class="indent builtin-bridges-option-description" + data-l10n-id="tor-bridges-built-in-obfs4-description" + > + </html:div> + </vbox> + <vbox class="builtin-bridges-option"> + <hbox> + <radio + value="snowflake" + data-l10n-id="built-in-dialog-snowflake-radio-option" + /> + <html:span class="bridge-status-badge"> + <html:div class="bridge-status-icon"></html:div> + <html:span + class="torPreferences-current-bridge-label" + data-l10n-id="built-in-dialog-current-bridge-label" + > + </html:span> + </html:span> + </hbox> + <html:div + class="indent builtin-bridges-option-description" + data-l10n-id="tor-bridges-built-in-snowflake-description" + > + </html:div> + </vbox> + <vbox class="builtin-bridges-option"> + <hbox> + <radio + value="meek-azure" + data-l10n-id="built-in-dialog-meek-azure-radio-option" + /> + <html:span class="bridge-status-badge"> + <html:div class="bridge-status-icon"></html:div> + <html:span + class="torPreferences-current-bridge-label" + data-l10n-id="built-in-dialog-current-bridge-label" + > + </html:span> + </html:span> + </hbox> + <html:div + class="indent builtin-bridges-option-description" + data-l10n-id="tor-bridges-built-in-meek-azure-description" + > + </html:div> + </vbox> + </radiogroup> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/connectionCategory.inc.xhtml b/browser/components/torpreferences/content/connectionCategory.inc.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..0694d56bab9b7894572e67bd733c911ad479c0ed --- /dev/null +++ b/browser/components/torpreferences/content/connectionCategory.inc.xhtml @@ -0,0 +1,11 @@ +<richlistitem id="category-connection" + class="category" + value="paneConnection" + helpTopic="prefs-connection" + data-l10n-id="tor-connection-settings-category" + data-l10n-attrs="tooltiptext" + align="center" + hidden="true"> + <image class="category-icon"/> + <label class="category-name" flex="1" data-l10n-id="tor-connection-settings-heading"></label> +</richlistitem> diff --git a/browser/components/torpreferences/content/connectionPane.js b/browser/components/torpreferences/content/connectionPane.js new file mode 100644 index 0000000000000000000000000000000000000000..b9b82317f52626ab8ec1f42843e427928305c7c2 --- /dev/null +++ b/browser/components/torpreferences/content/connectionPane.js @@ -0,0 +1,2734 @@ +// Copyright (c) 2022, The Tor Project, Inc. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +"use strict"; + +/* import-globals-from /browser/components/preferences/preferences.js */ +/* import-globals-from /browser/components/preferences/search.js */ + +const { setTimeout, clearTimeout } = ChromeUtils.importESModule( + "resource://gre/modules/Timer.sys.mjs" +); + +const { TorSettings, TorSettingsTopics, TorBridgeSource } = + ChromeUtils.importESModule("resource://gre/modules/TorSettings.sys.mjs"); + +const { TorParsers } = ChromeUtils.importESModule( + "resource://gre/modules/TorParsers.sys.mjs" +); +const { TorProviderBuilder, TorProviderTopics } = ChromeUtils.importESModule( + "resource://gre/modules/TorProviderBuilder.sys.mjs" +); + +const { TorConnect, TorConnectTopics, TorConnectStage, TorCensorshipLevel } = + ChromeUtils.importESModule("resource://gre/modules/TorConnect.sys.mjs"); + +const { MoatRPC } = ChromeUtils.importESModule( + "resource://gre/modules/Moat.sys.mjs" +); + +const { QRCode } = ChromeUtils.importESModule( + "resource://gre/modules/QRCode.sys.mjs" +); + +const { TorStrings } = ChromeUtils.importESModule( + "resource://gre/modules/TorStrings.sys.mjs" +); + +const { Lox, LoxTopics } = ChromeUtils.importESModule( + "resource://gre/modules/Lox.sys.mjs" +); + +const log = console.createInstance({ + maxLogLevel: "Warn", + prefix: "connectionPane", +}); + +/* + * Fake Lox module: + +const Lox = { + levelHistory: [0, 1], + // levelHistory: [1, 2], + // levelHistory: [2, 3], + // levelHistory: [3, 4], + // levelHistory: [0, 1, 2], + // levelHistory: [1, 2, 3], + // levelHistory: [4, 3], + // levelHistory: [4, 1], + // levelHistory: [2, 1], + //levelHistory: [2, 3, 4, 1, 2], + // Gain some invites and then loose them all. Shouldn't show any change. + // levelHistory: [0, 1, 2, 1], + // levelHistory: [1, 2, 3, 1], + getEventData() { + let prevLevel = this.levelHistory[0]; + const events = []; + for (let i = 1; i < this.levelHistory.length; i++) { + const level = this.levelHistory[i]; + events.push({ type: level > prevLevel ? "levelup" : "blockage", newLevel: level }); + prevLevel = level; + } + return events; + }, + clearEventData() { + this.levelHistory = []; + }, + nextUnlock: { date: "2024-01-31T00:00:00Z", nextLevel: 1 }, + //nextUnlock: { date: "2024-01-31T00:00:00Z", nextLevel: 2 }, + //nextUnlock: { date: "2024-01-31T00:00:00Z", nextLevel: 3 }, + //nextUnlock: { date: "2024-01-31T00:00:00Z", nextLevel: 4 }, + getNextUnlock() { + return this.nextUnlock; + }, + remainingInvites: 3, + // remainingInvites: 0, + getRemainingInviteCount() { + return this.remainingInvites; + }, + invites: [], + // invites: ["a", "b"], + getInvites() { + return this.invites; + }, +}; +*/ + +/** + * Get the ID/fingerprint of the bridge used in the most recent Tor circuit. + * + * @returns {string?} - The bridge ID or null if a bridge with an id was not + * used in the last circuit. + */ +async function getConnectedBridgeId() { + // TODO: PieroV: We could make sure TorSettings is in sync by monitoring also + // changes of settings. At that point, we could query it, instead of doing a + // query over the control port. + let bridge = null; + try { + const provider = await TorProviderBuilder.build(); + bridge = provider.currentBridge; + } catch (e) { + console.warn("Could not get current bridge", e); + } + return bridge?.fingerprint ?? null; +} + +/** + * Show the bridge QR to the user. + * + * @param {string} bridgeString - The string to use in the QR. + */ +function showBridgeQr(bridgeString) { + gSubDialog.open( + "chrome://browser/content/torpreferences/bridgeQrDialog.xhtml", + { features: "resizable=yes" }, + bridgeString + ); +} + +// TODO: Instead of aria-live in the DOM, use the proposed ariaNotify +// API if it gets accepted into firefox and works with screen readers. +// See https://github.com/WICG/proposals/issues/112 +/** + * Notification for screen reader users. + */ +const gBridgesNotification = { + /** + * The screen reader area that shows updates. + * + * @type {Element?} + */ + _updateArea: null, + /** + * The text for the screen reader update. + * + * @type {Element?} + */ + _textEl: null, + /** + * A timeout for hiding the update. + * + * @type {integer?} + */ + _hideUpdateTimeout: null, + + /** + * Initialize the area for notifications. + */ + init() { + this._updateArea = document.getElementById("tor-bridges-update-area"); + this._textEl = document.getElementById("tor-bridges-update-area-text"); + }, + + /** + * Post a new notification, replacing any existing one. + * + * @param {string} type - The notification type. + */ + post(type) { + this._updateArea.hidden = false; + // First we clear the update area to reset the text to be empty. + this._textEl.removeAttribute("data-l10n-id"); + this._textEl.textContent = ""; + if (this._hideUpdateTimeout !== null) { + clearTimeout(this._hideUpdateTimeout); + this._hideUpdateTimeout = null; + } + + let updateId; + switch (type) { + case "removed-one": + updateId = "tor-bridges-update-removed-one-bridge"; + break; + case "removed-all": + updateId = "tor-bridges-update-removed-all-bridges"; + break; + case "changed": + default: + // Generic message for when bridges change. + updateId = "tor-bridges-update-changed-bridges"; + break; + } + + // Hide the area after 5 minutes, when the update is not "recent" any + // more. + this._hideUpdateTimeout = setTimeout(() => { + this._updateArea.hidden = true; + }, 300000); + + // Wait a small amount of time to actually set the textContent. Otherwise + // the screen reader (tested with Orca) may not pick up on the change in + // text. + setTimeout(() => { + document.l10n.setAttributes(this._textEl, updateId); + }, 500); + }, +}; + +/** + * Controls the bridge grid. + */ +const gBridgeGrid = { + /** + * The grid element. + * + * @type {Element?} + */ + _grid: null, + /** + * The template for creating new rows. + * + * @type {HTMLTemplateElement?} + */ + _rowTemplate: null, + + /** + * @typedef {object} BridgeGridRow + * + * @property {Element} element - The row element. + * @property {Element} optionsButton - The options button. + * @property {Element} menu - The options menupopup. + * @property {Element} statusEl - The bridge status element. + * @property {Element} statusText - The status text. + * @property {string} bridgeLine - The identifying bridge string for this row. + * @property {string?} bridgeId - The ID/fingerprint for the bridge, or null + * if it doesn't have one. + * @property {integer} index - The index of the row in the grid. + * @property {boolean} connected - Whether we are connected to the bridge + * (recently in use for a Tor circuit). + * @property {BridgeGridCell[]} cells - The cells that belong to the row, + * ordered by their column. + */ + /** + * @typedef {object} BridgeGridCell + * + * @property {Element} element - The cell element. + * @property {Element} focusEl - The element belonging to the cell that should + * receive focus. Should be the cell element itself, or an interactive + * focusable child. + * @property {integer} columnIndex - The index of the column this cell belongs + * to. + * @property {BridgeGridRow} row - The row this cell belongs to. + */ + /** + * The current rows in the grid. + * + * @type {BridgeGridRow[]} + */ + _rows: [], + /** + * The cell that should be the focus target when the user moves focus into the + * grid, or null if the grid itself should be the target. + * + * @type {BridgeGridCell?} + */ + _focusCell: null, + + /** + * Initialize the bridge grid. + */ + init() { + this._grid = document.getElementById("tor-bridges-grid-display"); + // Initially, make only the grid itself part of the keyboard tab cycle. + // matches _focusCell = null. + this._grid.tabIndex = 0; + + this._rowTemplate = document.getElementById( + "tor-bridges-grid-row-template" + ); + + this._grid.addEventListener("keydown", this); + this._grid.addEventListener("mousedown", this); + this._grid.addEventListener("focusin", this); + + Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged); + + // NOTE: Before initializedPromise completes, this area is hidden. + TorSettings.initializedPromise.then(() => { + this._updateRows(true); + }); + }, + + /** + * Uninitialize the bridge grid. + */ + uninit() { + Services.obs.removeObserver(this, TorSettingsTopics.SettingsChanged); + this.deactivate(); + }, + + /** + * Whether the grid is visible and responsive. + * + * @type {boolean} + */ + _active: false, + + /** + * Activate and show the bridge grid. + */ + activate() { + if (this._active) { + return; + } + + this._active = true; + + Services.obs.addObserver(this, TorProviderTopics.BridgeChanged); + + this._grid.hidden = false; + + this._updateConnectedBridge(); + }, + + /** + * Deactivate and hide the bridge grid. + */ + deactivate() { + if (!this._active) { + return; + } + + this._active = false; + + this._forceCloseRowMenus(); + + this._grid.hidden = true; + + Services.obs.removeObserver(this, TorProviderTopics.BridgeChanged); + }, + + observe(subject, topic) { + switch (topic) { + case TorSettingsTopics.SettingsChanged: { + const { changes } = subject.wrappedJSObject; + if ( + changes.includes("bridges.source") || + changes.includes("bridges.bridge_strings") + ) { + this._updateRows(); + } + break; + } + case TorProviderTopics.BridgeChanged: + this._updateConnectedBridge(); + break; + } + }, + + handleEvent(event) { + if (event.type === "keydown") { + if (event.altKey || event.shiftKey || event.metaKey || event.ctrlKey) { + // Don't interfere with these events. + return; + } + + if (this._rows.some(row => row.menu.open)) { + // Have an open menu, let the menu handle the event instead. + return; + } + + let numRows = this._rows.length; + if (!numRows) { + // Nowhere for focus to go. + return; + } + + let moveRow = 0; + let moveColumn = 0; + const isLTR = this._grid.matches(":dir(ltr)"); + switch (event.key) { + case "ArrowDown": + moveRow = 1; + break; + case "ArrowUp": + moveRow = -1; + break; + case "ArrowRight": + moveColumn = isLTR ? 1 : -1; + break; + case "ArrowLeft": + moveColumn = isLTR ? -1 : 1; + break; + default: + return; + } + + // Prevent scrolling the nearest scroll container. + event.preventDefault(); + + const curCell = this._focusCell; + let row = curCell ? curCell.row.index + moveRow : 0; + let column = curCell ? curCell.columnIndex + moveColumn : 0; + + // Clamp in bounds. + if (row < 0) { + row = 0; + } else if (row >= numRows) { + row = numRows - 1; + } + + const numCells = this._rows[row].cells.length; + if (column < 0) { + column = 0; + } else if (column >= numCells) { + column = numCells - 1; + } + + const newCell = this._rows[row].cells[column]; + + if (newCell !== curCell) { + this._setFocus(newCell); + } + } else if (event.type === "mousedown") { + if (event.button !== 0) { + return; + } + // Move focus index to the clicked target. + // NOTE: Since the cells and the grid have "tabindex=-1", they are still + // click-focusable. Therefore, the default mousedown handler will try to + // move focus to it. + // Rather than block this default handler, we instead re-direct the focus + // to the correct cell in the "focusin" listener. + const newCell = this._getCellFromTarget(event.target); + // NOTE: If newCell is null, then we do nothing here, but instead wait for + // the focusin handler to trigger. + if (newCell && newCell !== this._focusCell) { + this._setFocus(newCell); + } + } else if (event.type === "focusin") { + const focusCell = this._getCellFromTarget(event.target); + if (focusCell !== this._focusCell) { + // Focus is not where it is expected. + // E.g. the user has clicked the edge of the grid. + // Restore focus immediately back to the cell we expect. + this._setFocus(this._focusCell); + } + } + }, + + /** + * Return the cell that was the target of an event. + * + * @param {Element} element - The target of an event. + * + * @returns {BridgeGridCell?} - The cell that the element belongs to, or null + * if it doesn't belong to any cell. + */ + _getCellFromTarget(element) { + for (const row of this._rows) { + for (const cell of row.cells) { + if (cell.element.contains(element)) { + return cell; + } + } + } + return null; + }, + + /** + * Determine whether the document's active element (focus) is within the grid + * or not. + * + * @returns {boolean} - Whether focus is within this grid or not. + */ + _focusWithin() { + return this._grid.contains(document.activeElement); + }, + + /** + * Set the cell that should be the focus target of the grid, possibly moving + * the document's focus as well. + * + * @param {BridgeGridCell?} cell - The cell to make the focus target, or null + * if the grid itself should be the target. + * @param {boolean} [focusWithin] - Whether focus should be moved within the + * grid. If undefined, this will move focus if the grid currently contains + * the document's focus. + */ + _setFocus(cell, focusWithin) { + if (focusWithin === undefined) { + focusWithin = this._focusWithin(); + } + const prevFocusElement = this._focusCell + ? this._focusCell.focusEl + : this._grid; + const newFocusElement = cell ? cell.focusEl : this._grid; + + if (prevFocusElement !== newFocusElement) { + prevFocusElement.tabIndex = -1; + newFocusElement.tabIndex = 0; + } + // Set _focusCell now, before we potentially call "focus", which can trigger + // the "focusin" handler. + this._focusCell = cell; + + if (focusWithin) { + // Focus was within the grid, so we need to actively move it to the new + // element. + newFocusElement.focus({ preventScroll: true }); + // Scroll to the whole cell into view, rather than just the focus element. + (cell?.element ?? newFocusElement).scrollIntoView({ + block: "nearest", + inline: "nearest", + }); + } + }, + + /** + * Reset the grids focus to be the first row's first cell, if any. + * + * @param {boolean} [focusWithin] - Whether focus should be moved within the + * grid. If undefined, this will move focus if the grid currently contains + * the document's focus. + */ + _resetFocus(focusWithin) { + this._setFocus( + this._rows.length ? this._rows[0].cells[0] : null, + focusWithin + ); + }, + + /** + * The bridge ID/fingerprint of the most recently used bridge (appearing in + * the latest Tor circuit). Roughly corresponds to the bridge we are currently + * connected to. + * + * null if there are no such bridges. + * + * @type {string?} + */ + _connectedBridgeId: null, + /** + * Update _connectedBridgeId. + */ + async _updateConnectedBridge() { + const bridgeId = await getConnectedBridgeId(); + if (bridgeId === this._connectedBridgeId) { + return; + } + this._connectedBridgeId = bridgeId; + for (const row of this._rows) { + this._updateRowStatus(row); + } + }, + + /** + * Update the status of a row. + * + * @param {BridgeGridRow} row - The row to update. + */ + _updateRowStatus(row) { + const connected = row.bridgeId && this._connectedBridgeId === row.bridgeId; + // NOTE: row.connected is initially undefined, so won't match `connected`. + if (connected === row.connected) { + return; + } + + row.connected = connected; + + const noStatus = !connected; + + row.element.classList.toggle("hide-status", noStatus); + row.statusEl.classList.toggle("bridge-status-none", noStatus); + row.statusEl.classList.toggle("bridge-status-connected", connected); + + if (connected) { + document.l10n.setAttributes( + row.statusText, + "tor-bridges-status-connected" + ); + } else { + document.l10n.setAttributes(row.statusText, "tor-bridges-status-none"); + } + }, + + /** + * Create a new row for the grid. + * + * @param {string} bridgeLine - The bridge line for this row, which also acts + * as its ID. + * + * @returns {BridgeGridRow} - A new row, with then "index" unset and the + * "element" without a parent. + */ + _createRow(bridgeLine) { + let details; + try { + details = TorParsers.parseBridgeLine(bridgeLine); + } catch (e) { + console.error(`Detected invalid bridge line: ${bridgeLine}`, e); + } + const row = { + element: this._rowTemplate.content.children[0].cloneNode(true), + bridgeLine, + bridgeId: details?.id ?? null, + cells: [], + }; + + const emojiBlock = row.element.querySelector(".tor-bridges-emojis-block"); + const BridgeEmoji = customElements.get("tor-bridge-emoji"); + for (const cell of BridgeEmoji.createForAddress(bridgeLine)) { + // Each emoji is its own cell, we rely on the fact that createForAddress + // always returns four elements. + cell.setAttribute("role", "gridcell"); + cell.classList.add("tor-bridges-grid-cell", "tor-bridges-emoji-cell"); + emojiBlock.append(cell); + } + + for (const [columnIndex, element] of row.element + .querySelectorAll(".tor-bridges-grid-cell") + .entries()) { + const focusEl = + element.querySelector(".tor-bridges-grid-focus") ?? element; + // Set a negative tabIndex, this makes the element click-focusable but not + // part of the tab navigation sequence. + focusEl.tabIndex = -1; + row.cells.push({ element, focusEl, columnIndex, row }); + } + + const transport = details?.transport ?? "vanilla"; + const typeCell = row.element.querySelector(".tor-bridges-type-cell"); + if (transport === "vanilla") { + document.l10n.setAttributes(typeCell, "tor-bridges-type-prefix-generic"); + } else { + document.l10n.setAttributes(typeCell, "tor-bridges-type-prefix", { + type: transport, + }); + } + + row.element.querySelector(".tor-bridges-address-cell-text").textContent = + bridgeLine; + + row.statusEl = row.element.querySelector( + ".tor-bridges-status-cell .bridge-status-badge" + ); + row.statusText = row.element.querySelector(".tor-bridges-status-cell-text"); + + this._initRowMenu(row); + + this._updateRowStatus(row); + return row; + }, + + /** + * The row menu index used for generating new ids. + * + * @type {integer} + */ + _rowMenuIndex: 0, + /** + * Generate a new id for the options menu. + * + * @returns {string} - The new id. + */ + _generateRowMenuId() { + const id = `tor-bridges-individual-options-menu-${this._rowMenuIndex}`; + // Assume we won't run out of ids. + this._rowMenuIndex++; + return id; + }, + + /** + * Initialize the shared menu for a row. + * + * @param {BridgeGridRow} row - The row to initialize the menu of. + */ + _initRowMenu(row) { + row.menu = row.element.querySelector( + ".tor-bridges-individual-options-menu" + ); + row.optionsButton = row.element.querySelector( + ".tor-bridges-options-cell-button" + ); + + row.menu.id = this._generateRowMenuId(); + row.optionsButton.setAttribute("aria-controls", row.menu.id); + + row.optionsButton.addEventListener("click", event => { + row.menu.toggle(event); + }); + + row.menu.addEventListener("hidden", () => { + // Make sure the button receives focus again when the menu is hidden. + // Currently, panel-list.js only does this when the menu is opened with a + // keyboard, but this causes focus to be lost from the page if the user + // uses a mixture of keyboard and mouse. + row.optionsButton.focus(); + }); + + const qrItem = row.menu.querySelector( + ".tor-bridges-options-qr-one-menu-item" + ); + const removeItem = row.menu.querySelector( + ".tor-bridges-options-remove-one-menu-item" + ); + row.menu.addEventListener("showing", () => { + const show = + this._bridgeSource === TorBridgeSource.UserProvided || + this._bridgeSource === TorBridgeSource.BridgeDB; + qrItem.hidden = !show; + removeItem.hidden = !show; + }); + + qrItem.addEventListener("click", () => { + const bridgeLine = row.bridgeLine; + if (!bridgeLine) { + return; + } + showBridgeQr(bridgeLine); + }); + row.menu + .querySelector(".tor-bridges-options-copy-one-menu-item") + .addEventListener("click", () => { + const clipboard = Cc[ + "@mozilla.org/widget/clipboardhelper;1" + ].getService(Ci.nsIClipboardHelper); + clipboard.copyString(row.bridgeLine); + }); + removeItem.addEventListener("click", () => { + const bridgeLine = row.bridgeLine; + const source = TorSettings.bridges.source; + const strings = TorSettings.bridges.bridge_strings; + const index = strings.indexOf(bridgeLine); + if (index === -1) { + return; + } + strings.splice(index, 1); + + TorSettings.changeSettings({ + bridges: { source, bridge_strings: strings }, + }); + }); + }, + + /** + * Force the row menu to close. + */ + _forceCloseRowMenus() { + for (const row of this._rows) { + row.menu.hide(null, { force: true }); + } + }, + + /** + * The known bridge source. + * + * Initially null to indicate that it is unset. + * + * @type {integer?} + */ + _bridgeSource: null, + /** + * The bridge sources this is shown for. + * + * @type {string[]} + */ + _supportedSources: [ + TorBridgeSource.BridgeDB, + TorBridgeSource.UserProvided, + TorBridgeSource.Lox, + ], + + /** + * Update the grid to show the latest bridge strings. + * + * @param {boolean} [initializing=false] - Whether this is being called as + * part of initialization. + */ + _updateRows(initializing = false) { + // Store whether we have focus within the grid, before removing or hiding + // DOM elements. + const focusWithin = this._focusWithin(); + + let lostAllBridges = false; + let newSource = false; + const bridgeSource = TorSettings.bridges.source; + if (bridgeSource !== this._bridgeSource) { + newSource = true; + + this._bridgeSource = bridgeSource; + + if (this._supportedSources.includes(bridgeSource)) { + this.activate(); + } else { + if (this._active && bridgeSource === TorBridgeSource.Invalid) { + lostAllBridges = true; + } + this.deactivate(); + } + } + + const ordered = this._active + ? TorSettings.bridges.bridge_strings.map(bridgeLine => { + const row = this._rows.find(r => r.bridgeLine === bridgeLine); + if (row) { + return row; + } + return this._createRow(bridgeLine); + }) + : []; + + // Whether we should reset the grid's focus. + // We always reset when we have a new bridge source. + // We reset the focus if no current Cell has focus. I.e. when adding a row + // to an empty grid, we want the focus to move to the first item. + // We also reset the focus if the current Cell is in a row that will be + // removed (including if all rows are removed). + // NOTE: In principle, if a row is removed, we could move the focus to the + // next or previous row (in the same cell column). However, most likely if + // the grid has the user focus, they are removing a single row using its + // options button. In this case, returning the user to some other row's + // options button might be more disorienting since it would not be simple + // for them to know *which* bridge they have landed on. + // NOTE: We do not reset the focus in other cases because we do not want the + // user to loose their place in the grid unnecessarily. + let resetFocus = + newSource || !this._focusCell || !ordered.includes(this._focusCell.row); + + // Remove rows no longer needed from the DOM. + let numRowsRemoved = 0; + let rowAddedOrMoved = false; + + for (const row of this._rows) { + if (!ordered.includes(row)) { + numRowsRemoved++; + // If the row menu was open, it will also be deleted. + // NOTE: Since the row menu is part of the row, focusWithin will be true + // if the menu had focus, so focus should be re-assigned. + row.element.remove(); + } + } + + // Go through all the rows to set their ".index" property and to ensure they + // are in the correct position in the DOM. + // NOTE: We could use replaceChildren to get the correct DOM structure, but + // we want to avoid rebuilding the entire tree when a single row is added or + // removed. + for (const [index, row] of ordered.entries()) { + row.index = index; + const element = row.element; + // Get the expected previous element, that should already be in the DOM + // from the previous loop. + const prevEl = index ? ordered[index - 1].element : null; + + if ( + element.parentElement === this._grid && + prevEl === element.previousElementSibling + ) { + // Already in the correct position in the DOM. + continue; + } + + rowAddedOrMoved = true; + // NOTE: Any elements already in the DOM, but not in the correct position + // will be removed and re-added by the below command. + // NOTE: if the row has document focus, then it should remain there. + if (prevEl) { + prevEl.after(element); + } else { + this._grid.prepend(element); + } + } + this._rows = ordered; + + // Restore any lost focus. + if (resetFocus) { + // If we are not active (and therefore hidden), we will not try and move + // focus (activeElement), but may still change the *focusable* element for + // when we are shown again. + this._resetFocus(this._active && focusWithin); + } + if (!this._active && focusWithin) { + // Move focus out of this element, which has been hidden. + gBridgeSettings.takeFocus(); + } + + // Notify the user if there was some change to the DOM. + // If we are initializing, we generate no notification since there has been + // no change in the setting. + if (!initializing) { + let notificationType; + if (lostAllBridges) { + // Just lost all bridges, and became de-active. + notificationType = "removed-all"; + } else if (this._rows.length) { + // Otherwise, only generate a notification if we are still active, with + // at least one bridge. + // I.e. do not generate a message if the new source is "builtin". + if (newSource) { + // A change in source. + notificationType = "changed"; + } else if (numRowsRemoved === 1 && !rowAddedOrMoved) { + // Only one bridge was removed. This is most likely in response to them + // manually removing a single bridge or using the bridge row's options + // menu. + notificationType = "removed-one"; + } else if (numRowsRemoved || rowAddedOrMoved) { + // Some other change. This is most likely in response to a manual edit + // of the existing bridges. + notificationType = "changed"; + } + // Else, there was no change. + } + + if (notificationType) { + gBridgesNotification.post(notificationType); + } + } + }, +}; + +/** + * Controls the built-in bridges area. + */ +const gBuiltinBridgesArea = { + /** + * The display area. + * + * @type {Element?} + */ + _area: null, + /** + * The type name element. + * + * @type {Element?} + */ + _nameEl: null, + /** + * The bridge type description element. + * + * @type {Element?} + */ + _descriptionEl: null, + /** + * The connection status. + * + * @type {Element?} + */ + _connectionStatusEl: null, + + /** + * Initialize the built-in bridges area. + */ + init() { + this._area = document.getElementById("tor-bridges-built-in-display"); + this._nameEl = document.getElementById("tor-bridges-built-in-type-name"); + this._descriptionEl = document.getElementById( + "tor-bridges-built-in-description" + ); + this._connectionStatusEl = document.getElementById( + "tor-bridges-built-in-connected" + ); + + Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged); + + // NOTE: Before initializedPromise completes, this area is hidden. + TorSettings.initializedPromise.then(() => { + this._updateBridgeType(true); + }); + }, + + /** + * Uninitialize the built-in bridges area. + */ + uninit() { + Services.obs.removeObserver(this, TorSettingsTopics.SettingsChanged); + this.deactivate(); + }, + + /** + * Whether the built-in area is visible and responsive. + * + * @type {boolean} + */ + _active: false, + + /** + * Activate and show the built-in bridge area. + */ + activate() { + if (this._active) { + return; + } + this._active = true; + + Services.obs.addObserver(this, TorProviderTopics.BridgeChanged); + + this._area.hidden = false; + + this._updateBridgeIds(); + this._updateConnectedBridge(); + }, + + /** + * Deactivate and hide built-in bridge area. + */ + deactivate() { + if (!this._active) { + return; + } + this._active = false; + + this._area.hidden = true; + + Services.obs.removeObserver(this, TorProviderTopics.BridgeChanged); + }, + + observe(subject, topic) { + switch (topic) { + case TorSettingsTopics.SettingsChanged: { + const { changes } = subject.wrappedJSObject; + if ( + changes.includes("bridges.source") || + changes.includes("bridges.builtin_type") + ) { + this._updateBridgeType(); + } + if (changes.includes("bridges.bridge_strings")) { + this._updateBridgeIds(); + } + break; + } + case TorProviderTopics.BridgeChanged: + this._updateConnectedBridge(); + break; + } + }, + + /** + * Updates the shown connected state. + */ + _updateConnectedState() { + this._connectionStatusEl.classList.toggle( + "bridge-status-connected", + this._bridgeType && + this._connectedBridgeId && + this._bridgeIds.includes(this._connectedBridgeId) + ); + }, + + /** + * The currently shown bridge type. Empty if deactivated, and null if + * uninitialized. + * + * @type {string?} + */ + _bridgeType: null, + /** + * The strings for each known bridge type. + * + * @type {{[key: string]: {[key: string]: string}}} + */ + _bridgeTypeStrings: { + obfs4: { + name: "tor-bridges-built-in-obfs4-name", + description: "tor-bridges-built-in-obfs4-description", + }, + snowflake: { + name: "tor-bridges-built-in-snowflake-name", + description: "tor-bridges-built-in-snowflake-description", + }, + "meek-azure": { + name: "tor-bridges-built-in-meek-azure-name", + description: "tor-bridges-built-in-meek-azure-description", + }, + }, + + /** + * The known bridge source. + * + * Initially null to indicate that it is unset. + * + * @type {integer?} + */ + _bridgeSource: null, + + /** + * Update the shown bridge type. + * + * @param {boolean} [initializing=false] - Whether this is being called as + * part of initialization. + */ + async _updateBridgeType(initializing = false) { + let lostAllBridges = false; + let newSource = false; + const bridgeSource = TorSettings.bridges.source; + if (bridgeSource !== this._bridgeSource) { + newSource = true; + + this._bridgeSource = bridgeSource; + + if (bridgeSource === TorBridgeSource.BuiltIn) { + this.activate(); + } else { + if (this._active && bridgeSource === TorBridgeSource.Invalid) { + lostAllBridges = true; + } + const hadFocus = this._area.contains(document.activeElement); + this.deactivate(); + if (hadFocus) { + gBridgeSettings.takeFocus(); + } + } + } + + const bridgeType = this._active ? TorSettings.bridges.builtin_type : ""; + + let newType = false; + if (bridgeType !== this._bridgeType) { + newType = true; + + this._bridgeType = bridgeType; + + const bridgeStrings = this._bridgeTypeStrings[bridgeType]; + if (bridgeStrings) { + document.l10n.setAttributes(this._nameEl, bridgeStrings.name); + document.l10n.setAttributes( + this._descriptionEl, + bridgeStrings.description + ); + } else { + // Unknown type, or no type. + this._nameEl.removeAttribute("data-l10n-id"); + this._nameEl.textContent = bridgeType; + this._descriptionEl.removeAttribute("data-l10n-id"); + this._descriptionEl.textContent = ""; + } + + this._updateConnectedState(); + } + + // Notify the user if there was some change to the type. + // If we are initializing, we generate no notification since there has been + // no change in the setting. + if (!initializing) { + let notificationType; + if (lostAllBridges) { + // Just lost all bridges, and became de-active. + notificationType = "removed-all"; + } else if (this._active && (newSource || newType)) { + // Otherwise, only generate a notification if we are still active, with + // a bridge type. + // I.e. do not generate a message if the new source is not "builtin". + notificationType = "changed"; + } + + if (notificationType) { + gBridgesNotification.post(notificationType); + } + } + }, + + /** + * The bridge IDs/fingerprints for the built-in bridges. + * + * @type {Array<string>} + */ + _bridgeIds: [], + /** + * Update _bridgeIds + */ + _updateBridgeIds() { + this._bridgeIds = []; + for (const bridgeLine of TorSettings.bridges.bridge_strings) { + try { + this._bridgeIds.push(TorParsers.parseBridgeLine(bridgeLine).id); + } catch (e) { + console.error(`Detected invalid bridge line: ${bridgeLine}`, e); + } + } + + this._updateConnectedState(); + }, + + /** + * The bridge ID/fingerprint of the most recently used bridge (appearing in + * the latest Tor circuit). Roughly corresponds to the bridge we are currently + * connected to. + * + * @type {string?} + */ + _connectedBridgeId: null, + /** + * Update _connectedBridgeId. + */ + async _updateConnectedBridge() { + this._connectedBridgeId = await getConnectedBridgeId(); + this._updateConnectedState(); + }, +}; + +/** + * Controls the bridge pass area. + */ +const gLoxStatus = { + /** + * The status area. + * + * @type {Element?} + */ + _area: null, + /** + * The area for showing the next unlock and invites. + * + * @type {Element?} + */ + _detailsArea: null, + /** + * The list items showing the next unlocks. + * + * @type {?{[key: string]: Element}} + */ + _nextUnlockItems: null, + /** + * The day counter headings for the next unlock. + * + * One heading is shown during a search, the other is shown otherwise. + * + * @type {?Element[]} + */ + _nextUnlockCounterEls: null, + /** + * Shows the number of remaining invites. + * + * @type {Element?} + */ + _remainingInvitesEl: null, + /** + * The button to show the invites. + * + * @type {Element?} + */ + _invitesButton: null, + /** + * The alert for new unlocks. + * + * @type {Element?} + */ + _unlockAlert: null, + /** + * The list items showing the unlocks. + * + * @type {?{[key: string]: Element}} + */ + _unlockItems: null, + /** + * The alert title. + * + * @type {Element?} + */ + _unlockAlertTitle: null, + /** + * The alert invites item. + * + * @type {Element?} + */ + _unlockAlertInvitesItem: null, + /** + * Button for the user to dismiss the alert. + * + * @type {Element?} + */ + _unlockAlertButton: null, + + /** + * Initialize the bridge pass area. + */ + init() { + if (!Lox.enabled) { + // Area should remain inactive and hidden. + return; + } + + this._area = document.getElementById("tor-bridges-lox-status"); + this._detailsArea = document.getElementById("tor-bridges-lox-details"); + this._nextUnlockItems = { + gainBridges: document.getElementById( + "tor-bridges-lox-next-unlock-gain-bridges" + ), + firstInvites: document.getElementById( + "tor-bridges-lox-next-unlock-first-invites" + ), + moreInvites: document.getElementById( + "tor-bridges-lox-next-unlock-more-invites" + ), + }; + this._nextUnlockCounterEls = Array.from( + document.querySelectorAll(".tor-bridges-lox-next-unlock-counter") + ); + this._remainingInvitesEl = document.getElementById( + "tor-bridges-lox-remaining-invites" + ); + this._invitesButton = document.getElementById( + "tor-bridges-lox-show-invites-button" + ); + this._unlockAlert = document.getElementById("tor-bridges-lox-unlock-alert"); + this._unlockItems = { + gainBridges: document.getElementById( + "tor-bridges-lox-unlock-alert-gain-bridges" + ), + newBridges: document.getElementById( + "tor-bridges-lox-unlock-alert-new-bridges" + ), + invites: document.getElementById("tor-bridges-lox-unlock-alert-invites"), + }; + this._unlockAlertTitle = document.getElementById( + "tor-bridge-unlock-alert-title" + ); + this._unlockAlertInviteItem = document.getElementById( + "tor-bridges-lox-unlock-alert-invites" + ); + this._unlockAlertButton = document.getElementById( + "tor-bridges-lox-unlock-alert-button" + ); + + this._invitesButton.addEventListener("click", () => { + gSubDialog.open( + "chrome://browser/content/torpreferences/loxInviteDialog.xhtml", + { features: "resizable=yes" } + ); + }); + this._unlockAlertButton.addEventListener("click", () => { + Lox.clearEventData(this._loxId); + }); + + Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged); + Services.obs.addObserver(this, LoxTopics.UpdateActiveLoxId); + Services.obs.addObserver(this, LoxTopics.UpdateEvents); + Services.obs.addObserver(this, LoxTopics.UpdateNextUnlock); + Services.obs.addObserver(this, LoxTopics.UpdateRemainingInvites); + Services.obs.addObserver(this, LoxTopics.NewInvite); + + // NOTE: Before initializedPromise completes, this area is hidden. + TorSettings.initializedPromise.then(() => { + this._updateLoxId(); + }); + }, + + /** + * Uninitialize the built-in bridges area. + */ + uninit() { + if (!Lox.enabled) { + return; + } + + Services.obs.removeObserver(this, TorSettingsTopics.SettingsChanged); + Services.obs.removeObserver(this, LoxTopics.UpdateActiveLoxId); + Services.obs.removeObserver(this, LoxTopics.UpdateEvents); + Services.obs.removeObserver(this, LoxTopics.UpdateNextUnlock); + Services.obs.removeObserver(this, LoxTopics.UpdateRemainingInvites); + Services.obs.removeObserver(this, LoxTopics.NewInvite); + }, + + observe(subject, topic) { + switch (topic) { + case TorSettingsTopics.SettingsChanged: { + const { changes } = subject.wrappedJSObject; + if (changes.includes("bridges.source")) { + this._updateLoxId(); + } + // NOTE: We do not call _updateLoxId when "bridges.lox_id" is in the + // changes. Instead we wait until LoxTopics.UpdateActiveLoxId to ensure + // that the Lox module has responded to the change in ID strictly + // *before* we do. In particular, we want to make sure the invites and + // event data has been cleared. + break; + } + case LoxTopics.UpdateActiveLoxId: + this._updateLoxId(); + break; + case LoxTopics.UpdateNextUnlock: + this._updateNextUnlock(); + break; + case LoxTopics.UpdateEvents: + this._updatePendingEvents(); + break; + case LoxTopics.UpdateRemainingInvites: + this._updateRemainingInvites(); + break; + case LoxTopics.NewInvite: + this._updateHaveExistingInvites(); + break; + } + }, + + /** + * The Lox id currently shown. Empty if deactivated, and null if + * uninitialized. + * + * @type {string?} + */ + _loxId: null, + + /** + * Update the shown bridge pass. + */ + async _updateLoxId() { + let loxId = + TorSettings.bridges.source === TorBridgeSource.Lox ? Lox.activeLoxId : ""; + if (loxId === this._loxId) { + return; + } + this._loxId = loxId; + this._area.hidden = !loxId; + // We unset _nextUnlock to ensure the areas no longer use the old value for + // the new loxId. + this._updateNextUnlock(true); + this._updateRemainingInvites(); + this._updateHaveExistingInvites(); + this._updatePendingEvents(); + }, + + /** + * The remaining invites shown, or null if uninitialized or no loxId. + * + * @type {integer?} + */ + _remainingInvites: null, + /** + * Update the shown value. + */ + _updateRemainingInvites() { + const numInvites = this._loxId + ? Lox.getRemainingInviteCount(this._loxId) + : null; + if (numInvites === this._remainingInvites) { + return; + } + this._remainingInvites = numInvites; + this._updateUnlockArea(); + this._updateInvitesArea(); + }, + /** + * Whether we have existing invites, or null if uninitialized or no loxId. + * + * @type {boolean?} + */ + _haveExistingInvites: null, + /** + * Update the shown value. + */ + _updateHaveExistingInvites() { + const haveInvites = this._loxId ? !!Lox.getInvites().length : null; + if (haveInvites === this._haveExistingInvites) { + return; + } + this._haveExistingInvites = haveInvites; + this._updateInvitesArea(); + }, + /** + * Details about the next unlock, or null if uninitialized or no loxId. + * + * @type {UnlockData?} + */ + _nextUnlock: null, + /** + * Tracker id to ensure that the results from later calls to _updateNextUnlock + * take priority over earlier calls. + * + * @type {integer} + */ + _nextUnlockCallId: 0, + /** + * Update the shown value asynchronously. + * + * @param {boolean} [unset=false] - Whether to set the _nextUnlock value to + * null before waiting for the new value. I.e. ensure that the current value + * will not be used. + */ + async _updateNextUnlock(unset = false) { + // NOTE: We do not expect the integer to exceed the maximum integer. + this._nextUnlockCallId++; + const callId = this._nextUnlockCallId; + if (unset) { + this._nextUnlock = null; + } + const nextUnlock = this._loxId + ? await Lox.getNextUnlock(this._loxId) + : null; + if (callId !== this._nextUnlockCallId) { + // Replaced by another update. + // E.g. if the _loxId changed. Or if getNextUnlock triggered + // LoxTopics.UpdateNextUnlock. + return; + } + // Should be safe to trigger the update, even when the value hasn't changed. + this._nextUnlock = nextUnlock; + this._updateUnlockArea(); + }, + /** + * The list of events the user has not yet cleared, or null if uninitialized + * or no loxId. + * + * @type {EventData[]?} + */ + _pendingEvents: null, + /** + * Update the shown value. + */ + _updatePendingEvents() { + // Should be safe to trigger the update, even when the value hasn't changed. + this._pendingEvents = this._loxId ? Lox.getEventData(this._loxId) : null; + this._updateUnlockArea(); + }, + + /** + * Update the display of the current or next unlock. + */ + _updateUnlockArea() { + if ( + !this._loxId || + this._pendingEvents === null || + this._remainingInvites === null || + this._nextUnlock === null + ) { + // Uninitialized or no Lox source. + // NOTE: This area may already be hidden by the change in Lox source, + // but we clean up for the next non-empty id. + this._unlockAlert.hidden = true; + this._detailsArea.hidden = true; + return; + } + + // Grab focus state before changing visibility. + const alertHadFocus = this._unlockAlert.contains(document.activeElement); + const detailsHadFocus = this._detailsArea.contains(document.activeElement); + + const pendingEvents = this._pendingEvents; + const showAlert = !!pendingEvents.length; + this._unlockAlert.hidden = !showAlert; + this._detailsArea.hidden = showAlert; + + if (showAlert) { + // At level 0 and level 1, we do not have any invites. + // If the user starts and ends on level 0 or 1, then overall they would + // have had no change in their invites. So we do not want to show their + // latest updates. + // NOTE: If the user starts at level > 1 and ends with level 1 (levelling + // down to level 0 should not be possible), then we *do* want to show the + // user that they now have "0" invites. + // NOTE: pendingEvents are time-ordered, with the most recent event + // *last*. + const firstEvent = pendingEvents[0]; + // NOTE: We cannot get a blockage event when the user starts at level 1 or + // 0. + const startingAtLowLevel = + firstEvent.type === "levelup" && firstEvent.newLevel <= 2; + const lastEvent = pendingEvents[pendingEvents.length - 1]; + const endingAtLowLevel = lastEvent.newLevel <= 1; + + const showInvites = !(startingAtLowLevel && endingAtLowLevel); + + let blockage = false; + let levelUp = false; + let bridgeGain = false; + // Go through events, in the order that they occurred. + for (const loxEvent of pendingEvents) { + if (loxEvent.type === "levelup") { + levelUp = true; + if (loxEvent.newLevel === 1) { + // Gain 2 bridges from level 0 to 1. + bridgeGain = true; + } + } else { + blockage = true; + } + } + + let alertTitleId; + if (levelUp && !blockage) { + alertTitleId = "tor-bridges-lox-upgrade"; + } else { + // Show as blocked bridges replaced. + // Even if we have a mixture of level ups as well. + alertTitleId = "tor-bridges-lox-blocked"; + } + document.l10n.setAttributes(this._unlockAlertTitle, alertTitleId); + document.l10n.setAttributes( + this._unlockAlertInviteItem, + "tor-bridges-lox-new-invites", + { numInvites: this._remainingInvites } + ); + this._unlockAlert.classList.toggle( + "lox-unlock-upgrade", + levelUp && !blockage + ); + this._unlockItems.gainBridges.hidden = !bridgeGain; + this._unlockItems.newBridges.hidden = !blockage; + this._unlockItems.invites.hidden = !showInvites; + } else { + // Show next unlock. + // Number of days until the next unlock, rounded up. + const numDays = Math.max( + 1, + Math.ceil( + (new Date(this._nextUnlock.date).getTime() - Date.now()) / + (24 * 60 * 60 * 1000) + ) + ); + for (const counterEl of this._nextUnlockCounterEls) { + document.l10n.setAttributes( + counterEl, + "tor-bridges-lox-days-until-unlock", + { numDays } + ); + } + + // Gain 2 bridges from level 0 to 1. After that gain invites. + this._nextUnlockItems.gainBridges.hidden = + this._nextUnlock.nextLevel !== 1; + this._nextUnlockItems.firstInvites.hidden = + this._nextUnlock.nextLevel !== 2; + this._nextUnlockItems.moreInvites.hidden = + this._nextUnlock.nextLevel <= 2; + } + + if (alertHadFocus && !showAlert) { + // Alert has become hidden, move focus back up to the now revealed details + // area. + // NOTE: We have two headings: one shown during a search and one shown + // otherwise. We focus the heading that is currently visible. + // See tor-browser#43320. + // TODO: It might be better if we could use the # named anchor to + // re-orient the screen reader position instead of using tabIndex=-1, but + // about:preferences currently uses the anchor for showing categories + // only. See bugzilla bug 1799153. + if ( + this._nextUnlockCounterEls[0].checkVisibility({ + visibilityProperty: true, + }) + ) { + this._nextUnlockCounterEls[0].focus(); + } else { + this._nextUnlockCounterEls[1].focus(); + } + } else if (detailsHadFocus && showAlert) { + this._unlockAlertButton.focus(); + } + }, + + /** + * Update the invites area. + */ + _updateInvitesArea() { + let hasInvites; + if ( + !this._loxId || + this._remainingInvites === null || + this._haveExistingInvites === null + ) { + // Not initialized yet. + hasInvites = false; + } else { + hasInvites = this._haveExistingInvites || !!this._remainingInvites; + } + + if ( + !hasInvites && + (this._remainingInvitesEl.contains(document.activeElement) || + this._invitesButton.contains(document.activeElement)) + ) { + // About to loose focus. + // Unexpected for the lox level to loose all invites. + // Move to the top of the details area, which should be visible if we + // just had focus. + this._nextUnlockCounterEl.focus(); + } + // Hide the invite elements if we have no historic invites or a way of + // creating new ones. + this._remainingInvitesEl.hidden = !hasInvites; + this._invitesButton.hidden = !hasInvites; + + if (hasInvites) { + document.l10n.setAttributes( + this._remainingInvitesEl, + "tor-bridges-lox-remaining-invites", + { numInvites: this._remainingInvites } + ); + } + }, +}; + +/** + * Controls the bridge settings. + */ +const gBridgeSettings = { + /** + * The preferences <groupbox> for bridges + * + * @type {Element?} + */ + _groupEl: null, + /** + * The button for controlling whether bridges are enabled. + * + * @type {Element?} + */ + _toggleButton: null, + /** + * The area for showing current bridges. + * + * @type {Element?} + */ + _bridgesEl: null, + /** + * The area for sharing bridge addresses. + * + * @type {Element?} + */ + _shareEl: null, + /** + * The two headings for the bridge settings. + * + * One heading is shown during a search, the other is shown otherwise. + * + * @type {?Element[]} + */ + _bridgesSettingsHeadings: null, + /** + * The two headings for the current bridges, at the start of the area. + * + * One heading is shown during a search, the other is shown otherwise. + * + * @type {Element?} + */ + _currentBridgesHeadings: null, + /** + * The area for showing no bridges. + * + * @type {Element?} + */ + _noBridgesEl: null, + /** + * The heading elements for changing bridges. + * + * One heading is shown during a search, the other is shown otherwise. + * + * @type {?Element[]} + */ + _changeHeadingEls: null, + /** + * The button for user to provide a bridge address or share code. + * + * @type {Element?} + */ + _userProvideButton: null, + /** + * A map from the bridge source to its corresponding label. + * + * @type {?Map<number, Element>} + */ + _sourceLabels: null, + + /** + * Initialize the bridge settings. + */ + init() { + gBridgesNotification.init(); + + this._bridgesSettingsHeadings = Array.from( + document.querySelectorAll(".tor-bridges-subcategory-heading") + ); + this._currentBridgesHeadings = Array.from( + document.querySelectorAll(".tor-bridges-current-heading") + ); + this._bridgesEl = document.getElementById("tor-bridges-current"); + this._noBridgesEl = document.getElementById("tor-bridges-none"); + this._groupEl = document.getElementById("torPreferences-bridges-group"); + + this._sourceLabels = new Map([ + [ + TorBridgeSource.BuiltIn, + document.getElementById("tor-bridges-built-in-label"), + ], + [ + TorBridgeSource.UserProvided, + document.getElementById("tor-bridges-user-label"), + ], + [ + TorBridgeSource.BridgeDB, + document.getElementById("tor-bridges-requested-label"), + ], + [TorBridgeSource.Lox, document.getElementById("tor-bridges-lox-label")], + ]); + this._shareEl = document.getElementById("tor-bridges-share"); + + this._toggleButton = document.getElementById("tor-bridges-enabled-toggle"); + // Initially disabled whilst TorSettings may not be initialized. + this._toggleButton.disabled = true; + + this._toggleButton.addEventListener("toggle", () => { + if (!this._haveBridges) { + return; + } + TorSettings.changeSettings({ + bridges: { enabled: this._toggleButton.pressed }, + }); + }); + + this._changeHeadingEls = Array.from( + document.querySelectorAll(".tor-bridges-change-heading") + ); + this._userProvideButton = document.getElementById( + "tor-bridges-open-user-provide-dialog-button" + ); + + document.l10n.setAttributes( + document.getElementById("tor-bridges-user-provide-description"), + // TODO: Set a different string if we have Lox enabled. + "tor-bridges-add-addresses-description" + ); + + // TODO: Change to GetLoxBridges if Lox enabled, and the account is set up. + const telegramUserName = "GetBridgesBot"; + const telegramInstruction = document.getElementById( + "tor-bridges-provider-instruction-telegram" + ); + telegramInstruction.querySelector( + "a" + ).href = `https://t.me/${telegramUserName}`; + document.l10n.setAttributes( + telegramInstruction, + "tor-bridges-provider-telegram-instruction", + { telegramUserName } + ); + + document + .getElementById("tor-bridges-open-built-in-dialog-button") + .addEventListener("click", () => { + this._openBuiltinDialog(); + }); + this._userProvideButton.addEventListener("click", () => { + this._openUserProvideDialog(this._haveBridges ? "replace" : "add"); + }); + document + .getElementById("tor-bridges-open-request-dialog-button") + .addEventListener("click", () => { + this._openRequestDialog(); + }); + + Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged); + + gBridgeGrid.init(); + gBuiltinBridgesArea.init(); + gLoxStatus.init(); + + this._initBridgesMenu(); + this._initShareArea(); + + // NOTE: Before initializedPromise completes, the current bridges sections + // should be hidden. + // And gBridgeGrid and gBuiltinBridgesArea are not active. + TorSettings.initializedPromise.then(() => { + this._updateEnabled(); + this._updateBridgeStrings(); + this._updateSource(); + }); + }, + + /** + * Un-initialize the bridge settings. + */ + uninit() { + gBridgeGrid.uninit(); + gBuiltinBridgesArea.uninit(); + gLoxStatus.uninit(); + + Services.obs.removeObserver(this, TorSettingsTopics.SettingsChanged); + }, + + observe(subject, topic) { + switch (topic) { + case TorSettingsTopics.SettingsChanged: { + const { changes } = subject.wrappedJSObject; + if (changes.includes("bridges.enabled")) { + this._updateEnabled(); + } + if (changes.includes("bridges.source")) { + this._updateSource(); + } + if (changes.includes("bridges.bridge_strings")) { + this._updateBridgeStrings(); + } + break; + } + } + }, + + /** + * Update whether the bridges should be shown as enabled. + */ + _updateEnabled() { + // Changing the pressed property on moz-toggle should not trigger its + // "toggle" event. + this._toggleButton.pressed = TorSettings.bridges.enabled; + }, + + /** + * The shown bridge source. + * + * Initially null to indicate that it is unset for the first call to + * _updateSource. + * + * @type {integer?} + */ + _bridgeSource: null, + /** + * Whether the user is encouraged to share their bridge addresses. + * + * @type {boolean} + */ + _canShare: false, + + /** + * Update _bridgeSource. + */ + _updateSource() { + // NOTE: This should only ever be called after TorSettings is already + // initialized. + const bridgeSource = TorSettings.bridges.source; + if (bridgeSource === this._bridgeSource) { + // Avoid re-activating an area if the source has not changed. + return; + } + + this._bridgeSource = bridgeSource; + + // Before hiding elements, we determine whether our region contained the + // user focus. + const hadFocus = + this._bridgesEl.contains(document.activeElement) || + this._noBridgesEl.contains(document.activeElement); + + for (const [source, labelEl] of this._sourceLabels.entries()) { + labelEl.hidden = source !== bridgeSource; + } + + this._canShare = + bridgeSource === TorBridgeSource.UserProvided || + bridgeSource === TorBridgeSource.BridgeDB; + + this._shareEl.hidden = !this._canShare; + + // Force the menu to close whenever the source changes. + // NOTE: If the menu had focus then hadFocus will be true, and focus will be + // re-assigned. + this._forceCloseBridgesMenu(); + + // Update whether we have bridges. + this._updateHaveBridges(); + + if (hadFocus) { + // Always reset the focus to the start of the area whenever the source + // changes. + // NOTE: gBuiltinBridges._updateBridgeType and gBridgeGrid._updateRows + // may have already called takeFocus in response to them being + // de-activated. The re-call should be safe. + this.takeFocus(); + } + }, + + /** + * Whether we have bridges or not, or null if it is unknown. + * + * @type {boolean?} + */ + _haveBridges: null, + + /** + * Update the _haveBridges value. + */ + _updateHaveBridges() { + // NOTE: We use the TorSettings.bridges.source value, rather than + // this._bridgeSource because _updateHaveBridges can be called just before + // _updateSource (via takeFocus). + const haveBridges = TorSettings.bridges.source !== TorBridgeSource.Invalid; + + if (haveBridges === this._haveBridges) { + return; + } + + this._haveBridges = haveBridges; + + this._toggleButton.disabled = !haveBridges; + // Add classes to show or hide the "no bridges" and "Your bridges" sections. + // NOTE: Before haveBridges is set, neither class is added, so both sections + // and hidden. + this._groupEl.classList.add("bridges-initialized"); + this._bridgesEl.hidden = !haveBridges; + this._noBridgesEl.hidden = haveBridges; + + for (const headingEl of this._changeHeadingEls) { + document.l10n.setAttributes( + headingEl, + haveBridges + ? "tor-bridges-replace-bridges-heading" + : "tor-bridges-add-bridges-heading" + ); + } + document.l10n.setAttributes( + this._userProvideButton, + haveBridges ? "tor-bridges-replace-button" : "tor-bridges-add-new-button" + ); + }, + + /** + * Force the focus to move to the bridge area. + */ + takeFocus() { + if (this._haveBridges === null) { + // The bridges area has not been initialized yet, which means that + // TorSettings may not be initialized. + // Unexpected to receive a call before then, so just return early. + return; + } + + // Make sure we have the latest value for _haveBridges. + // We also ensure that the _currentBridgesHeadings element is visible before + // we focus it. + this._updateHaveBridges(); + + // Move focus to the start of the relevant section, which is a heading. + // They have tabindex="-1" so should be focusable, even though they are not + // part of the usual tab navigation. + // NOTE: We have two headings: one shown during a search and one shown + // otherwise. We focus the heading that is currently visible. + // See tor-browser#43320. + // TODO: It might be better if we could use the # named anchor to + // re-orient the screen reader position instead of using tabIndex=-1, but + // about:preferences currently uses the anchor for showing categories + // only. See bugzilla bug 1799153. + const focusHeadings = this._haveBridges + ? this._currentBridgesHeadings // The heading above the new bridges. + : this._bridgesSettingsHeadings; // The top of the bridge settings. + if (focusHeadings[0].checkVisibility({ visibilityProperty: true })) { + focusHeadings[0].focus(); + } else { + focusHeadings[1].focus(); + } + }, + + /** + * The bridge strings in a copy-able form. + * + * @type {string} + */ + _bridgeStrings: "", + /** + * Whether the bridge strings should be shown as a QR code. + * + * @type {boolean} + */ + _canQRBridges: false, + + /** + * Update the stored bridge strings. + */ + _updateBridgeStrings() { + const bridges = TorSettings.bridges.bridge_strings; + + this._bridgeStrings = bridges.join("\n"); + // TODO: Determine what logic we want. + this._canQRBridges = bridges.length <= 3; + + this._qrButton.disabled = !this._canQRBridges; + }, + + /** + * Copy all the bridge addresses to the clipboard. + */ + _copyBridges() { + const clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( + Ci.nsIClipboardHelper + ); + clipboard.copyString(this._bridgeStrings); + }, + + /** + * Open the QR code dialog encoding all the bridge addresses. + */ + _openQR() { + if (!this._canQRBridges) { + return; + } + showBridgeQr(this._bridgeStrings); + }, + + /** + * The QR button for copying all QR codes. + * + * @type {Element?} + */ + _qrButton: null, + + _initShareArea() { + document + .getElementById("tor-bridges-copy-addresses-button") + .addEventListener("click", () => { + this._copyBridges(); + }); + + this._qrButton = document.getElementById("tor-bridges-qr-addresses-button"); + this._qrButton.addEventListener("click", () => { + this._openQR(); + }); + }, + + /** + * The menu for all bridges. + * + * @type {Element?} + */ + _bridgesMenu: null, + + /** + * Initialize the menu for all bridges. + */ + _initBridgesMenu() { + this._bridgesMenu = document.getElementById("tor-bridges-all-options-menu"); + + // NOTE: We generally assume that once the bridge menu is opened the + // this._bridgeStrings value will not change. + const qrItem = document.getElementById( + "tor-bridges-options-qr-all-menu-item" + ); + qrItem.addEventListener("click", () => { + this._openQR(); + }); + + const copyItem = document.getElementById( + "tor-bridges-options-copy-all-menu-item" + ); + copyItem.addEventListener("click", () => { + this._copyBridges(); + }); + + const editItem = document.getElementById( + "tor-bridges-options-edit-all-menu-item" + ); + editItem.addEventListener("click", () => { + this._openUserProvideDialog("edit"); + }); + + // TODO: Do we want a different item for built-in bridges, rather than + // "Remove all bridges"? + document + .getElementById("tor-bridges-options-remove-all-menu-item") + .addEventListener("click", async () => { + // TODO: Should we only have a warning when not built-in? + const parentWindow = + Services.wm.getMostRecentWindow("navigator:browser"); + const flags = + Services.prompt.BUTTON_POS_0 * + Services.prompt.BUTTON_TITLE_IS_STRING + + Services.prompt.BUTTON_POS_0_DEFAULT + + Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL; + + const [titleString, bodyString, removeString] = + await document.l10n.formatValues([ + { id: "remove-all-bridges-warning-title" }, + { id: "remove-all-bridges-warning-description" }, + { id: "remove-all-bridges-warning-remove-button" }, + ]); + + // TODO: Update the text, and remove old strings. + const buttonIndex = Services.prompt.confirmEx( + parentWindow, + titleString, + bodyString, + flags, + removeString, + null, + null, + null, + {} + ); + + if (buttonIndex !== 0) { + return; + } + + TorSettings.changeSettings({ + // This should always have the side effect of disabling bridges as + // well. + bridges: { source: TorBridgeSource.Invalid }, + }); + }); + + this._bridgesMenu.addEventListener("showing", () => { + qrItem.hidden = !this._canShare || !this._canQRBridges; + editItem.hidden = this._bridgeSource !== TorBridgeSource.UserProvided; + }); + + const bridgesMenuButton = document.getElementById( + "tor-bridges-all-options-button" + ); + bridgesMenuButton.addEventListener("click", event => { + this._bridgesMenu.toggle(event, bridgesMenuButton); + }); + + this._bridgesMenu.addEventListener("hidden", () => { + // Make sure the button receives focus again when the menu is hidden. + // Currently, panel-list.js only does this when the menu is opened with a + // keyboard, but this causes focus to be lost from the page if the user + // uses a mixture of keyboard and mouse. + bridgesMenuButton.focus(); + }); + }, + + /** + * Force the bridges menu to close. + */ + _forceCloseBridgesMenu() { + this._bridgesMenu.hide(null, { force: true }); + }, + + /** + * Open a bridge dialog that will change the users bridges. + * + * @param {string} url - The url of the dialog to open. + * @param {object?} inputData - The input data to send to the dialog window. + * @param {Function} onAccept - The method to call if the bridge dialog was + * accepted by the user. This will be passed a "result" object containing + * data set by the dialog. This should return a promise that resolves once + * the bridge settings have been set, or null if the settings have not + * been applied. + */ + _openDialog(url, inputData, onAccept) { + const result = { accepted: false, connect: false }; + let savedSettings = null; + gSubDialog.open( + url, + { + features: "resizable=yes", + closingCallback: () => { + if (!result.accepted) { + return; + } + savedSettings = onAccept(result); + if (!savedSettings) { + // No change in settings. + return; + } + if (!result.connect) { + // Do not open about:torconnect. + return; + } + + // Wait until the settings are applied before bootstrapping. + // NOTE: Saving the settings should also cancel any existing bootstrap + // attempt first. See tor-browser#41921. + savedSettings.then(() => { + // The bridge dialog button is "connect" when Tor is not + // bootstrapped, so do the connect. + + // Start Bootstrapping, which should use the configured bridges. + // NOTE: We do this regardless of any previous TorConnect Error. + TorConnect.openTorConnect({ beginBootstrapping: "hard" }); + }); + }, + // closedCallback should be called after gSubDialog has already + // re-assigned focus back to the document. + closedCallback: () => { + if (!savedSettings) { + return; + } + // Wait until the settings have changed, so that the UI could + // respond, then move focus. + savedSettings.then(() => gBridgeSettings.takeFocus()); + }, + }, + result, + inputData + ); + }, + + /** + * Open the built-in bridge dialog. + */ + _openBuiltinDialog() { + this._openDialog( + "chrome://browser/content/torpreferences/builtinBridgeDialog.xhtml", + null, + result => { + if (!result.type) { + return null; + } + return TorSettings.changeSettings({ + bridges: { + enabled: true, + source: TorBridgeSource.BuiltIn, + builtin_type: result.type, + }, + }); + } + ); + }, + + /* + * Open the request bridge dialog. + */ + _openRequestDialog() { + this._openDialog( + "chrome://browser/content/torpreferences/requestBridgeDialog.xhtml", + null, + result => { + if (!result.bridges?.length) { + return null; + } + return TorSettings.changeSettings({ + bridges: { + enabled: true, + source: TorBridgeSource.BridgeDB, + bridge_strings: result.bridges, + }, + }); + } + ); + }, + + /** + * Open the user provide dialog. + * + * @param {string} mode - The mode to open the dialog in: "add", "replace" or + * "edit". + */ + _openUserProvideDialog(mode) { + this._openDialog( + "chrome://browser/content/torpreferences/provideBridgeDialog.xhtml", + { mode }, + result => { + const loxId = result.loxId; + if (!loxId && !result.addresses?.length) { + return null; + } + const bridges = { enabled: true }; + if (loxId) { + bridges.source = TorBridgeSource.Lox; + bridges.lox_id = loxId; + } else { + bridges.source = TorBridgeSource.UserProvided; + bridges.bridge_strings = result.addresses; + } + return TorSettings.changeSettings({ bridges }); + } + ); + }, +}; + +/** + * Area to show the internet and tor network connection status. + */ +const gNetworkStatus = { + /** + * Initialize the area. + */ + init() { + this._internetAreaEl = document.getElementById( + "network-status-internet-area" + ); + this._internetResultEl = this._internetAreaEl.querySelector( + ".network-status-result" + ); + this._internetTestButton = document.getElementById( + "network-status-internet-test-button" + ); + this._internetTestButton.addEventListener("click", () => { + this._startInternetTest(); + }); + + this._torAreaEl = document.getElementById("network-status-tor-area"); + this._torResultEl = this._torAreaEl.querySelector(".network-status-result"); + this._torConnectButton = document.getElementById( + "network-status-tor-connect-button" + ); + this._torConnectButton.addEventListener("click", () => { + TorConnect.openTorConnect({ beginBootstrapping: "soft" }); + }); + + this._updateInternetStatus("unknown"); + this._updateTorConnectionStatus(); + + Services.obs.addObserver(this, TorConnectTopics.StageChange); + }, + + /** + * Un-initialize the area. + */ + uninit() { + Services.obs.removeObserver(this, TorConnectTopics.StageChange); + }, + + observe(subject, topic) { + switch (topic) { + // triggered when tor connect state changes and we may + // need to update the messagebox + case TorConnectTopics.StageChange: { + this._updateTorConnectionStatus(); + break; + } + } + }, + + /** + * Whether the test should be disabled. + * + * @type {boolean} + */ + _internetTestDisabled: false, + /** + * Start the internet test. + */ + async _startInternetTest() { + if (this._internetTestDisabled) { + return; + } + this._internetTestDisabled = true; + // We use "aria-disabled" rather than the "disabled" attribute so that the + // button can remain focusable during the test. + // TODO: Replace with moz-button when it handles this for us. See + // tor-browser#43275. + this._internetTestButton.setAttribute("aria-disabled", "true"); + this._internetTestButton.classList.add("spoof-button-disabled"); + this._internetTestButton.tabIndex = -1; + try { + this._updateInternetStatus("testing"); + const mrpc = new MoatRPC(); + let status = null; + try { + await mrpc.init(); + status = await mrpc.testInternetConnection(); + } catch (err) { + log.error("Error while checking the Internet connection", err); + } finally { + mrpc.uninit(); + } + if (status) { + this._updateInternetStatus(status.successful ? "online" : "offline"); + } else { + this._updateInternetStatus("unknown"); + } + } finally { + this._internetTestButton.removeAttribute("aria-disabled"); + this._internetTestButton.classList.remove("spoof-button-disabled"); + this._internetTestButton.tabIndex = 0; + this._internetTestDisabled = false; + } + }, + + /** + * Update the shown internet status. + * + * @param {string} stateName - The name of the state to show. + */ + _updateInternetStatus(stateName) { + let l10nId; + switch (stateName) { + case "testing": + l10nId = "tor-connection-internet-status-testing"; + break; + case "offline": + l10nId = "tor-connection-internet-status-offline"; + break; + case "online": + l10nId = "tor-connection-internet-status-online"; + break; + } + if (l10nId) { + this._internetResultEl.setAttribute("data-l10n-id", l10nId); + } else { + this._internetResultEl.removeAttribute("data-l10n-id"); + this._internetResultEl.textContent = ""; + } + + this._internetAreaEl.classList.toggle( + "status-loading", + stateName === "testing" + ); + this._internetAreaEl.classList.toggle( + "status-offline", + stateName === "offline" + ); + }, + + /** + * Update the shown Tor connection status. + */ + _updateTorConnectionStatus() { + const buttonHadFocus = this._torConnectButton.contains( + document.activeElement + ); + const isBootstrapped = + TorConnect.stageName === TorConnectStage.Bootstrapped; + const isBlocked = !isBootstrapped && TorConnect.potentiallyBlocked; + let l10nId; + if (isBootstrapped) { + l10nId = "tor-connection-network-status-connected"; + } else if (isBlocked) { + l10nId = "tor-connection-network-status-blocked"; + } else { + l10nId = "tor-connection-network-status-not-connected"; + } + + document.l10n.setAttributes(this._torResultEl, l10nId); + this._torAreaEl.classList.toggle("status-connected", isBootstrapped); + this._torAreaEl.classList.toggle("status-blocked", isBlocked); + if (isBootstrapped && buttonHadFocus) { + // Button has become hidden and will loose focus. Most likely this has + // happened because the user clicked the button to open about:torconnect. + // Since this is near the top of the page, we move focus to the search + // input (for when the user returns). + gSearchResultsPane.searchInput.focus(); + } + }, +}; + +/* + Connection Pane + + Code for populating the XUL in about:preferences#connection, handling input events, interfacing with tor-launcher +*/ +const gConnectionPane = (function () { + /* CSS selectors for all of the Tor Network DOM elements we need to access */ + const selectors = { + bridges: { + locationGroup: "#torPreferences-bridges-locationGroup", + locationLabel: "#torPreferences-bridges-locationLabel", + location: "#torPreferences-bridges-location", + locationEntries: "#torPreferences-bridges-locationEntries", + chooseForMe: "#torPreferences-bridges-buttonChooseBridgeForMe", + }, + }; /* selectors */ + + const retval = { + // cached frequently accessed DOM elements + _enableQuickstartCheckbox: null, + + // populate xul with strings and cache the relevant elements + _populateXUL() { + // Quickstart + this._enableQuickstartCheckbox = document.getElementById( + "torPreferences-quickstart-toggle" + ); + this._enableQuickstartCheckbox.addEventListener("command", () => { + TorConnect.quickstart = this._enableQuickstartCheckbox.checked; + }); + this._enableQuickstartCheckbox.checked = TorConnect.quickstart; + Services.obs.addObserver(this, TorConnectTopics.QuickstartChange); + + // Location + { + const prefpane = document.getElementById("mainPrefPane"); + + const locationGroup = prefpane.querySelector( + selectors.bridges.locationGroup + ); + prefpane.querySelector(selectors.bridges.locationLabel).textContent = + TorStrings.settings.bridgeLocation; + const location = prefpane.querySelector(selectors.bridges.location); + const locationEntries = prefpane.querySelector( + selectors.bridges.locationEntries + ); + const chooseForMe = prefpane.querySelector( + selectors.bridges.chooseForMe + ); + chooseForMe.setAttribute( + "label", + TorStrings.settings.bridgeChooseForMe + ); + chooseForMe.addEventListener("command", () => { + TorConnect.openTorConnect({ + beginBootstrapping: "hard", + regionCode: location.value, + }); + }); + this._populateLocations = () => { + const currentValue = location.value; + locationEntries.textContent = ""; + const createItem = (value, label, disabled) => { + const item = document.createXULElement("menuitem"); + item.setAttribute("value", value); + item.setAttribute("label", label); + if (disabled) { + item.setAttribute("disabled", "true"); + } + return item; + }; + const addLocations = codes => { + const items = []; + for (const code of codes) { + items.push( + createItem( + code, + TorConnect.countryNames[code] + ? TorConnect.countryNames[code] + : code + ) + ); + } + items.sort((left, right) => left.label.localeCompare(right.label)); + locationEntries.append(...items); + }; + locationEntries.append( + createItem("automatic", TorStrings.settings.bridgeLocationAutomatic) + ); + if (TorConnect.countryCodes.length) { + locationEntries.append( + createItem("", TorStrings.settings.bridgeLocationFrequent, true) + ); + addLocations(TorConnect.countryCodes); + locationEntries.append( + createItem("", TorStrings.settings.bridgeLocationOther, true) + ); + } + addLocations(Object.keys(TorConnect.countryNames)); + location.value = currentValue; + }; + this._showAutoconfiguration = () => { + if ( + !TorConnect.canBeginAutoBootstrap || + !TorConnect.potentiallyBlocked + ) { + locationGroup.setAttribute("hidden", "true"); + return; + } + // Populate locations, even though we will show only the automatic + // item for a moment. In my opinion showing the button immediately is + // better then waiting for the Moat query to finish (after a while) + // and showing the controls only after that. + this._populateLocations(); + locationGroup.removeAttribute("hidden"); + if (!TorConnect.countryCodes.length) { + TorConnect.getCountryCodes().then(() => this._populateLocations()); + } + }; + this._showAutoconfiguration(); + } + + // Advanced setup + document + .getElementById("torPreferences-advanced-button") + .addEventListener("click", () => { + this.onAdvancedSettings(); + }); + + // Tor logs + document + .getElementById("torPreferences-buttonTorLogs") + .addEventListener("click", () => { + this.onViewTorLogs(); + }); + + Services.obs.addObserver(this, TorConnectTopics.StageChange); + }, + + init() { + gBridgeSettings.init(); + gNetworkStatus.init(); + + this._populateXUL(); + + const onUnload = () => { + window.removeEventListener("unload", onUnload); + gConnectionPane.uninit(); + }; + window.addEventListener("unload", onUnload); + }, + + uninit() { + gBridgeSettings.uninit(); + gNetworkStatus.uninit(); + + // unregister our observer topics + Services.obs.removeObserver(this, TorConnectTopics.QuickstartChange); + Services.obs.removeObserver(this, TorConnectTopics.StageChange); + }, + + // whether the page should be present in about:preferences + get enabled() { + return TorConnect.enabled; + }, + + // + // Callbacks + // + + observe(subject, topic) { + switch (topic) { + case TorConnectTopics.QuickstartChange: { + this._enableQuickstartCheckbox.checked = TorConnect.quickstart; + break; + } + // triggered when tor connect state changes and we may + // need to update the messagebox + case TorConnectTopics.StageChange: { + this._showAutoconfiguration(); + break; + } + } + }, + + async onAdvancedSettings() { + // Ensure TorSettings is complete before loading the dialog, which reads + // from TorSettings. + await TorSettings.initializedPromise; + gSubDialog.open( + "chrome://browser/content/torpreferences/connectionSettingsDialog.xhtml", + { features: "resizable=yes" } + ); + }, + + onViewTorLogs() { + gSubDialog.open( + "chrome://browser/content/torpreferences/torLogDialog.xhtml", + { features: "resizable=yes" } + ); + }, + }; + return retval; +})(); /* gConnectionPane */ diff --git a/browser/components/torpreferences/content/connectionPane.xhtml b/browser/components/torpreferences/content/connectionPane.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..62a3dc3099583358b5999ec1975dbdc3256dd1d3 --- /dev/null +++ b/browser/components/torpreferences/content/connectionPane.xhtml @@ -0,0 +1,632 @@ +<!-- Tor panel --> + +<script + type="application/javascript" + src="chrome://browser/content/torpreferences/connectionPane.js" +/> +<html:template id="template-paneConnection"> + <vbox + id="torPreferencesCategory" + class="subcategory" + data-category="paneConnection" + hidden="true" + > + <html:h1 data-l10n-id="tor-connection-settings-heading"></html:h1> + <description class="description-deemphasized" flex="1"> + <html:span data-l10n-id="tor-connection-overview"></html:span> + <label + class="learnMore text-link" + is="text-link" + href="about:manual#about" + useoriginprincipal="true" + data-l10n-id="tor-connection-browser-learn-more-link" + /> + </description> + <!-- Keep within #torPreferencesCategory so this won't appear in search + - results. --> + <html:div + id="network-status-internet-area" + class="network-status-area" + role="group" + aria-labelledby="network-status-internet-area-label" + > + <html:img alt="" class="network-status-icon" /> + <!-- Use an aria-live area to announce "Internet: Online" or + - "Internet: Offline". We only expect this to change when triggered by + - the user clicking the "Test" button, so shouldn't occur unexpectedly. + --> + <html:div + class="network-status-live-area" + aria-live="polite" + aria-atomic="true" + > + <html:span + id="network-status-internet-area-label" + class="network-status-label" + data-l10n-id="tor-connection-internet-status-label" + ></html:span> + <img alt="" class="network-status-loading-icon tor-loading-icon" /> + <html:span class="network-status-result"></html:span> + </html:div> + <html:button + id="network-status-internet-test-button" + data-l10n-id="tor-connection-internet-status-test-button" + ></html:button> + </html:div> + <html:div + id="network-status-tor-area" + class="network-status-area" + role="group" + aria-labelledby="network-status-tor-area-label" + > + <html:img alt="" class="network-status-icon" /> + <!-- NOTE: Unlike #network-status-internet-area, we do not wrap the label + - and status ("Tor network: Not connected", etc) in an aria-live area. + - This is not likely to change whilst this page has focus. + - Moreover, the status is already present in the torconnect status bar + - in the window tab bar. --> + <html:span + id="network-status-tor-area-label" + class="network-status-label" + data-l10n-id="tor-connection-network-status-label" + ></html:span> + <html:span class="network-status-result"></html:span> + <html:button + id="network-status-tor-connect-button" + data-l10n-id="tor-connection-network-status-connect-button" + ></html:button> + </html:div> + </vbox> + + <!-- Quickstart --> + <groupbox data-category="paneConnection" hidden="true"> + <label> + <html:h2 data-l10n-id="tor-connection-quickstart-heading"></html:h2> + </label> + <description + class="description-deemphasized" + flex="1" + data-l10n-id="tor-connection-quickstart-description" + /> + <checkbox + id="torPreferences-quickstart-toggle" + data-l10n-id="tor-connection-quickstart-checkbox" + /> + </groupbox> + + <!-- Bridges --> + <hbox class="subcategory" data-category="paneConnection" hidden="true"> + <html:h1 + id="tor-bridges-subcategory-heading-non-search" + class="tor-bridges-subcategory-heading tor-focusable-heading" + tabindex="-1" + data-l10n-id="tor-bridges-heading" + ></html:h1> + </hbox> + <groupbox + id="torPreferences-bridges-group" + data-category="paneConnection" + hidden="true" + aria-labelledby="tor-bridges-subcategory-heading-non-search" + > + <!-- Add a search-header that only appears in search results as a substitute + - for the hidden h1 element. See tor-browser#43320. + - NOTE: Usually the first xul:label will act as the accessible name for + - a xul:groubbox element *if* it is not hidden. Since the search-header + - is sometimes hidden we need an explicit aria-labelledby anyway. + - However, we keep the wrapper xul:label for styling consistency with the + - other settings. --> + <label class="search-header" hidden="true"> + <html:h2 + class="tor-bridges-subcategory-heading tor-focusable-heading" + tabindex="-1" + data-l10n-id="tor-bridges-heading" + ></html:h2> + </label> + <description class="description-deemphasized" flex="1"> + <html:span data-l10n-id="tor-bridges-overview"></html:span> + <label + class="learnMore text-link" + is="text-link" + href="about:manual#bridges" + useoriginprincipal="true" + data-l10n-id="tor-bridges-learn-more-link" + /> + </description> + <hbox + align="center" + id="torPreferences-bridges-locationGroup" + hidden="true" + > + <label + id="torPreferences-bridges-locationLabel" + control="torPreferences-bridges-location" + /> + <spacer flex="1" /> + <menulist id="torPreferences-bridges-location"> + <menupopup id="torPreferences-bridges-locationEntries" /> + </menulist> + <button + id="torPreferences-bridges-buttonChooseBridgeForMe" + class="primary tor-button" + /> + </hbox> + <html:moz-toggle + id="tor-bridges-enabled-toggle" + label-align-after="" + data-l10n-id="tor-bridges-use-bridges" + data-l10n-attrs="label" + /> + <!-- Add an aria-live area where we can post notifications to screen + - reader users about changes to their list of bridges. This is to give + - these users some feedback for when the remove a bridge or change + - their bridges in other ways. I.e. whenever tor-bridges-grid-display + - changes its rows. + - + - If we change the text in #tor-bridges-update-area-text, a screen + - reader should speak out the text to the user, even when this area + - does not have focus. + - + - In fact, we don't really want the user to navigate to this element + - directly. But currently using an aria-live region in the DOM is the + - only way to effectively pass a notification to a screen reader user. + - Since it must be somewhere in the DOM, we logically place it just + - before the grid, where it is hopefully least confusing to stumble + - across. + - + - TODO: Instead of aria-live in the DOM, use the proposed ariaNotify + - API if it gets accepted into firefox and works with screen readers. + - See https://github.com/WICG/proposals/issues/112 + --> + <!-- NOTE: This area is hidden by default, and is only shown temporarily + - when a notification is added. It should never match with search + - queries. --> + <html:div + id="tor-bridges-update-area" + hidden="hidden" + data-hidden-from-search="true" + > + <!-- NOTE: This first span's text content will *not* be read out as part + - of the notification because it does not have an aria-live + - attribute. Instead it is just here to give context to the following + - text in #tor-bridges-update-area-text if the user navigates to + - #tor-bridges-update-area manually whilst it is not hidden. + - I.e. it is just here to make it less confusing if a screen reader + - user stumbles across this. + --> + <html:span data-l10n-id="tor-bridges-update-area-intro"></html:span> + <!-- Whitespace between spans. --> + <!-- This second span is the area to place notification text in. --> + <html:span + id="tor-bridges-update-area-text" + aria-live="polite" + ></html:span> + </html:div> + <html:div id="tor-bridges-none" hidden="hidden"> + <html:img id="tor-bridges-none-icon" alt="" /> + <html:div data-l10n-id="tor-bridges-none-added"></html:div> + </html:div> + <html:div id="tor-bridges-current" hidden="hidden"> + <html:div id="tor-bridges-current-header-bar"> + <html:h2 + id="tor-bridges-current-heading-non-search" + class="tor-bridges-current-heading tor-focusable-heading tor-small-heading tor-non-search-heading" + tabindex="-1" + data-l10n-id="tor-bridges-your-bridges" + ></html:h2> + <!-- Add a duplicate search heading. + - In a search result the heading h1.tor-bridges-subcategory-heading + - will be hidden, and the h2.tor-bridges-subcategory-heading + - will be visible. + - As such, all headings below h2.tor-bridges-subcategory-heading also + - need to shift one lower in heading level to preseve the correct + - hierarchy of - heading levels. + - In this case we hide the <h2> heading and show the duplicate <h3> + - heading instead. + - See tor-browser#43320. --> + <html:h3 + class="tor-bridges-current-heading tor-focusable-heading tor-small-heading tor-search-heading" + tabindex="-1" + data-l10n-id="tor-bridges-your-bridges" + ></html:h3> + <html:span + id="tor-bridges-user-label" + class="tor-bridges-source-label" + data-l10n-id="tor-bridges-source-user" + ></html:span> + <html:span + id="tor-bridges-built-in-label" + class="tor-bridges-source-label" + data-l10n-id="tor-bridges-source-built-in" + ></html:span> + <html:span + id="tor-bridges-requested-label" + class="tor-bridges-source-label" + data-l10n-id="tor-bridges-source-requested" + ></html:span> + <html:span id="tor-bridges-lox-label" class="tor-bridges-source-label"> + <html:img id="tor-bridges-lox-label-icon" alt="" /> + <html:span data-l10n-id="tor-bridges-source-lox"></html:span> + </html:span> + <html:button + id="tor-bridges-all-options-button" + class="tor-bridges-options-button" + aria-haspopup="menu" + aria-expanded="false" + aria-controls="tor-bridges-all-options-menu" + data-l10n-id="tor-bridges-options-button" + ></html:button> + <html:panel-list + id="tor-bridges-all-options-menu" + data-hidden-from-search="true" + > + <html:panel-item + id="tor-bridges-options-qr-all-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-qr-all-bridge-addresses" + ></html:panel-item> + <html:panel-item + id="tor-bridges-options-copy-all-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-copy-all-bridge-addresses" + ></html:panel-item> + <html:panel-item + id="tor-bridges-options-edit-all-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-edit-all-bridges" + ></html:panel-item> + <html:panel-item + id="tor-bridges-options-remove-all-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-remove-all-bridges" + ></html:panel-item> + </html:panel-list> + </html:div> + <html:div id="tor-bridges-built-in-display" hidden="hidden"> + <html:div id="tor-bridges-built-in-type-name"></html:div> + <html:div + id="tor-bridges-built-in-connected" + class="bridge-status-badge" + > + <html:div class="bridge-status-icon"></html:div> + <html:span + data-l10n-id="tor-bridges-built-in-status-connected" + ></html:span> + </html:div> + <html:div id="tor-bridges-built-in-description"></html:div> + </html:div> + <html:div + id="tor-bridges-grid-display" + class="tor-bridges-grid" + role="grid" + aria-labelledby="tor-bridges-current-heading-non-search" + hidden="hidden" + ></html:div> + <html:template id="tor-bridges-grid-row-template"> + <html:div class="tor-bridges-grid-row" role="row"> + <!-- TODO: lox status cell for new bridges? --> + <html:span + class="tor-bridges-type-cell tor-bridges-grid-cell" + role="gridcell" + ></html:span> + <html:span class="tor-bridges-emojis-block" role="none"></html:span> + <html:span class="tor-bridges-grid-end-block" role="none"> + <html:span + class="tor-bridges-address-cell tor-bridges-grid-cell" + role="gridcell" + > + <html:span class="tor-bridges-address-cell-text"></html:span> + </html:span> + <html:span + class="tor-bridges-status-cell tor-bridges-grid-cell" + role="gridcell" + > + <html:div class="bridge-status-badge"> + <html:div class="bridge-status-icon"></html:div> + <html:span class="tor-bridges-status-cell-text"></html:span> + </html:div> + </html:span> + <html:span + class="tor-bridges-options-cell tor-bridges-grid-cell" + role="gridcell" + > + <html:button + class="tor-bridges-options-cell-button tor-bridges-options-button tor-bridges-grid-focus" + aria-haspopup="menu" + aria-expanded="false" + data-l10n-id="tor-bridges-individual-bridge-options-button" + ></html:button> + <html:panel-list + class="tor-bridges-individual-options-menu" + data-hidden-from-search="true" + > + <html:panel-item + class="tor-bridges-options-qr-one-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-qr-address" + ></html:panel-item> + <html:panel-item + class="tor-bridges-options-copy-one-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-copy-address" + ></html:panel-item> + <html:panel-item + class="tor-bridges-options-remove-one-menu-item" + data-l10n-attrs="accesskey" + data-l10n-id="tor-bridges-menu-item-remove-bridge" + ></html:panel-item> + </html:panel-list> + </html:span> + </html:span> + </html:div> + </html:template> + <html:div + id="tor-bridges-share" + class="tor-bridges-details-box" + hidden="hidden" + > + <html:h3 + class="tor-bridges-share-heading tor-small-heading tor-non-search-heading" + data-l10n-id="tor-bridges-share-heading" + ></html:h3> + <!-- Add a duplicate search heading. See tor-browser#43320. --> + <html:h4 + class="tor-bridges-share-heading tor-small-heading tor-search-heading" + data-l10n-id="tor-bridges-share-heading" + ></html:h4> + <html:span + id="tor-bridges-share-description" + data-l10n-id="tor-bridges-share-description" + ></html:span> + <html:button + id="tor-bridges-copy-addresses-button" + data-l10n-id="tor-bridges-copy-addresses-button" + ></html:button> + <html:button + id="tor-bridges-qr-addresses-button" + data-l10n-id="tor-bridges-qr-addresses-button" + ></html:button> + </html:div> + <html:div id="tor-bridges-lox-status" hidden="hidden"> + <html:div data-l10n-id="tor-bridges-lox-description"></html:div> + <html:div + id="tor-bridges-lox-details" + class="tor-bridges-details-box tor-bridges-lox-box" + hidden="hidden" + > + <html:img alt="" class="tor-bridges-lox-image-inner" /> + <html:img alt="" class="tor-bridges-lox-image-outer" /> + <html:h3 + class="tor-bridges-lox-next-unlock-counter tor-small-heading tor-bridges-lox-intro tor-focusable-heading tor-non-search-heading" + tabindex="-1" + ></html:h3> + <!-- Add a duplicate search heading. See tor-browser#43320. --> + <html:h4 + class="tor-bridges-lox-next-unlock-counter tor-small-heading tor-bridges-lox-intro tor-focusable-heading tor-search-heading" + tabindex="-1" + ></html:h4> + <html:ul class="tor-bridges-lox-list"> + <html:li + id="tor-bridges-lox-next-unlock-gain-bridges" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-bridge" + data-l10n-id="tor-bridges-lox-unlock-two-bridges" + hidden="hidden" + ></html:li> + <html:li + id="tor-bridges-lox-next-unlock-first-invites" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-invite" + data-l10n-id="tor-bridges-lox-unlock-first-invites" + hidden="hidden" + ></html:li> + <html:li + id="tor-bridges-lox-next-unlock-more-invites" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-invite" + data-l10n-id="tor-bridges-lox-unlock-more-invites" + hidden="hidden" + ></html:li> + </html:ul> + <html:div + id="tor-bridges-lox-remaining-invites" + hidden="hidden" + ></html:div> + <html:button + id="tor-bridges-lox-show-invites-button" + class="tor-bridges-lox-button" + data-l10n-id="tor-bridges-lox-show-invites-button" + hidden="hidden" + ></html:button> + </html:div> + <html:div + id="tor-bridges-lox-unlock-alert" + role="alert" + class="tor-bridges-details-box tor-bridges-lox-box" + hidden="hidden" + > + <html:img alt="" class="tor-bridges-lox-image-inner" /> + <html:img alt="" class="tor-bridges-lox-image-outer" /> + <html:div + id="tor-bridge-unlock-alert-title" + class="tor-small-heading tor-bridges-lox-intro" + ></html:div> + <html:ul class="tor-bridges-lox-list"> + <html:li + id="tor-bridges-lox-unlock-alert-gain-bridges" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-bridge" + data-l10n-id="tor-bridges-lox-gained-two-bridges" + hidden="hidden" + ></html:li> + <html:li + id="tor-bridges-lox-unlock-alert-new-bridges" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-bridge" + data-l10n-id="tor-bridges-lox-new-bridges" + hidden="hidden" + ></html:li> + <html:li + id="tor-bridges-lox-unlock-alert-invites" + class="tor-bridges-lox-list-item tor-bridges-lox-list-item-invite" + hidden="hidden" + ></html:li> + </html:ul> + <html:button + id="tor-bridges-lox-unlock-alert-button" + class="tor-bridges-lox-button" + data-l10n-id="tor-bridges-lox-got-it-button" + ></html:button> + </html:div> + </html:div> + </html:div> + <html:h2 + class="tor-bridges-change-heading tor-medium-heading tor-non-search-heading" + ></html:h2> + <!-- Add a duplicate search heading. See tor-browser#43320. + - This has the same content, but a smaller font. --> + <html:h3 + class="tor-bridges-change-heading tor-small-heading tor-search-heading" + ></html:h3> + <hbox align="center"> + <description + flex="1" + data-l10n-id="tor-bridges-select-built-in-description" + /> + <html:button + id="tor-bridges-open-built-in-dialog-button" + class="accessory-button" + data-l10n-id="tor-bridges-select-built-in-button" + ></html:button> + </hbox> + <hbox align="center"> + <description id="tor-bridges-user-provide-description" flex="1" /> + <html:button + id="tor-bridges-open-user-provide-dialog-button" + class="accessory-button" + ></html:button> + </hbox> + <html:h3 + class="tor-bridges-provider-heading tor-medium-heading tor-non-search-heading" + data-l10n-id="tor-bridges-find-more-heading" + ></html:h3> + <!-- Add a duplicate search heading. See tor-browser#43320. + - This has the same content, but a smaller font. --> + <html:h4 + class="tor-bridges-provider-heading tor-small-heading tor-search-heading" + data-l10n-id="tor-bridges-find-more-heading" + ></html:h4> + <description + data-l10n-id="tor-bridges-find-more-description" + class="description-deemphasized" + /> + <html:div id="tor-bridges-provider-area"> + <html:ul id="tor-bridges-provider-list"> + <html:li class="tor-bridges-provider-item"> + <html:img + id="tor-bridges-provider-icon-telegram" + class="tor-bridges-provider-icon" + alt="" + /> + <html:div + class="tor-bridges-provider-name" + data-l10n-id="tor-bridges-provider-telegram-name" + ></html:div> + <html:div + id="tor-bridges-provider-instruction-telegram" + class="tor-bridges-provider-instruction" + > + <html:a data-l10n-name="user"></html:a> + </html:div> + </html:li> + <html:li class="tor-bridges-provider-item"> + <html:img + id="tor-bridges-provider-icon-web" + class="tor-bridges-provider-icon" + alt="" + /> + <html:div + class="tor-bridges-provider-name" + data-l10n-id="tor-bridges-provider-web-name" + ></html:div> + <html:div + class="tor-bridges-provider-instruction" + data-l10n-id="tor-bridges-provider-web-instruction" + data-l10n-args='{ "url": "bridges.torproject.org" }' + > + <html:a + href="https://bridges.torproject.org" + data-l10n-name="url" + ></html:a> + </html:div> + </html:li> + <html:li class="tor-bridges-provider-item"> + <html:img + id="tor-bridges-provider-icon-email" + class="tor-bridges-provider-icon" + alt="" + /> + <html:div + class="tor-bridges-provider-name" + data-l10n-id="tor-bridges-provider-email-name" + ></html:div> + <html:div + class="tor-bridges-provider-instruction" + data-l10n-id="tor-bridges-provider-email-instruction" + data-l10n-args='{ "address": "bridges@torproject.org" }' + ></html:div> + </html:li> + </html:ul> + <html:div id="tor-bridges-request-box"> + <html:img + alt="" + src="chrome://browser/content/torpreferences/bridge-bot.svg" + ></html:img> + <html:div + id="tor-bridges-request-description" + data-l10n-id="tor-bridges-request-from-browser" + ></html:div> + <html:button + id="tor-bridges-open-request-dialog-button" + data-l10n-id="tor-bridges-request-button" + ></html:button> + </html:div> + </html:div> + </groupbox> + + <!-- Advanced --> + <hbox class="subcategory" data-category="paneConnection" hidden="true"> + <html:h1 + id="tor-advanced-subcategory-heading-non-search" + data-l10n-id="tor-advanced-settings-heading" + ></html:h1> + </hbox> + <groupbox + id="torPreferences-advanced-group" + data-category="paneConnection" + hidden="true" + aria-labelledby="tor-advanced-subcategory-heading-non-search" + > + <!-- Add a search-header that only appears in search results as a substitute + - for the hidden h1 element. See tor-browser#43320. + - NOTE: Usually the first xul:label will act as the accessible name for + - a xul:groubbox element *if* it is not hidden. Since the search-header + - is sometimes hidden we need an explicit aria-labelledby anyway. + - However, we keep the wrapper xul:label for styling consistency with the + - other settings. --> + <label class="search-header" hidden="true"> + <html:h2 data-l10n-id="tor-advanced-settings-heading"></html:h2> + </label> + <hbox align="center"> + <description data-l10n-id="tor-advanced-settings-description" flex="1" /> + <html:button + id="torPreferences-advanced-button" + class="accessory-button" + data-l10n-id="tor-advanced-settings-button" + ></html:button> + </hbox> + <hbox align="center" data-subcategory="viewlogs"> + <description data-l10n-id="tor-view-log-description" flex="1" /> + <html:button + id="torPreferences-buttonTorLogs" + class="accessory-button" + data-l10n-id="tor-view-log-button" + ></html:button> + </hbox> + </groupbox> +</html:template> diff --git a/browser/components/torpreferences/content/connectionSettingsDialog.js b/browser/components/torpreferences/content/connectionSettingsDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..c8172b993d741efdb9db9bfea9d1cb53c23740b4 --- /dev/null +++ b/browser/components/torpreferences/content/connectionSettingsDialog.js @@ -0,0 +1,336 @@ +"use strict"; + +const { TorSettings, TorProxyType } = ChromeUtils.importESModule( + "resource://gre/modules/TorSettings.sys.mjs" +); + +const gConnectionSettingsDialog = { + _useProxyCheckbox: null, + _proxyTypeLabel: null, + _proxyTypeMenulist: null, + _proxyAddressLabel: null, + _proxyAddressTextbox: null, + _proxyPortLabel: null, + _proxyPortTextbox: null, + _proxyUsernameLabel: null, + _proxyUsernameTextbox: null, + _proxyPasswordLabel: null, + _proxyPasswordTextbox: null, + _useFirewallCheckbox: null, + _allowedPortsLabel: null, + _allowedPortsTextbox: null, + + selectors: { + useProxyCheckbox: "checkbox#torPreferences-connection-toggleProxy", + proxyTypeLabel: "label#torPreferences-localProxy-type", + proxyTypeList: "menulist#torPreferences-localProxy-builtinList", + proxyAddressLabel: "label#torPreferences-localProxy-address", + proxyAddressTextbox: "input#torPreferences-localProxy-textboxAddress", + proxyPortLabel: "label#torPreferences-localProxy-port", + proxyPortTextbox: "input#torPreferences-localProxy-textboxPort", + proxyUsernameLabel: "label#torPreferences-localProxy-username", + proxyUsernameTextbox: "input#torPreferences-localProxy-textboxUsername", + proxyPasswordLabel: "label#torPreferences-localProxy-password", + proxyPasswordTextbox: "input#torPreferences-localProxy-textboxPassword", + useFirewallCheckbox: "checkbox#torPreferences-connection-toggleFirewall", + firewallAllowedPortsLabel: "label#torPreferences-connection-allowedPorts", + firewallAllowedPortsTextbox: + "input#torPreferences-connection-textboxAllowedPorts", + }, + + // disables the provided list of elements + _setElementsDisabled(elements, disabled) { + for (let currentElement of elements) { + currentElement.disabled = disabled; + } + }, + + init() { + const selectors = this.selectors; + + // Local Proxy + this._useProxyCheckbox = document.querySelector(selectors.useProxyCheckbox); + this._useProxyCheckbox.addEventListener("command", () => { + const checked = this._useProxyCheckbox.checked; + this.onToggleProxy(checked); + }); + this._proxyTypeLabel = document.querySelector(selectors.proxyTypeLabel); + + let mockProxies = [ + { + value: TorProxyType.Socks4, + l10nId: "tor-advanced-dialog-proxy-socks4-menuitem", + }, + { + value: TorProxyType.Socks5, + l10nId: "tor-advanced-dialog-proxy-socks5-menuitem", + }, + { + value: TorProxyType.HTTPS, + l10nId: "tor-advanced-dialog-proxy-http-menuitem", + }, + ]; + this._proxyTypeMenulist = document.querySelector(selectors.proxyTypeList); + this._proxyTypeMenulist.addEventListener("command", () => { + const value = this._proxyTypeMenulist.value; + this.onSelectProxyType(value); + }); + for (let currentProxy of mockProxies) { + let menuEntry = window.document.createXULElement("menuitem"); + menuEntry.setAttribute("value", currentProxy.value); + menuEntry.setAttribute("data-l10n-id", currentProxy.l10nId); + this._proxyTypeMenulist.querySelector("menupopup").appendChild(menuEntry); + } + + this._proxyAddressLabel = document.querySelector( + selectors.proxyAddressLabel + ); + this._proxyAddressTextbox = document.querySelector( + selectors.proxyAddressTextbox + ); + this._proxyAddressTextbox.addEventListener("blur", () => { + let value = this._proxyAddressTextbox.value.trim(); + let colon = value.lastIndexOf(":"); + if (colon != -1) { + let maybePort = parseInt(value.substr(colon + 1)); + if (!isNaN(maybePort) && maybePort > 0 && maybePort < 65536) { + this._proxyAddressTextbox.value = value.substr(0, colon); + this._proxyPortTextbox.value = maybePort; + } + } + }); + this._proxyPortLabel = document.querySelector(selectors.proxyPortLabel); + this._proxyPortTextbox = document.querySelector(selectors.proxyPortTextbox); + this._proxyUsernameLabel = document.querySelector( + selectors.proxyUsernameLabel + ); + this._proxyUsernameTextbox = document.querySelector( + selectors.proxyUsernameTextbox + ); + this._proxyPasswordLabel = document.querySelector( + selectors.proxyPasswordLabel + ); + this._proxyPasswordTextbox = document.querySelector( + selectors.proxyPasswordTextbox + ); + + this.onToggleProxy(false); + if (TorSettings.proxy.enabled) { + this.onToggleProxy(true); + this.onSelectProxyType(TorSettings.proxy.type); + this._proxyAddressTextbox.value = TorSettings.proxy.address; + this._proxyPortTextbox.value = TorSettings.proxy.port; + this._proxyUsernameTextbox.value = TorSettings.proxy.username; + this._proxyPasswordTextbox.value = TorSettings.proxy.password; + } + + // Local firewall + this._useFirewallCheckbox = document.querySelector( + selectors.useFirewallCheckbox + ); + this._useFirewallCheckbox.addEventListener("command", () => { + const checked = this._useFirewallCheckbox.checked; + this.onToggleFirewall(checked); + }); + this._allowedPortsLabel = document.querySelector( + selectors.firewallAllowedPortsLabel + ); + this._allowedPortsTextbox = document.querySelector( + selectors.firewallAllowedPortsTextbox + ); + + this.onToggleFirewall(false); + if (TorSettings.firewall.enabled) { + this.onToggleFirewall(true); + this._allowedPortsTextbox.value = + TorSettings.firewall.allowed_ports.join(", "); + } + + const dialog = document.getElementById("torPreferences-connection-dialog"); + dialog.addEventListener("dialogaccept", () => { + this._applySettings(); + }); + }, + + // callback when proxy is toggled + onToggleProxy(enabled) { + this._useProxyCheckbox.checked = enabled; + let disabled = !enabled; + + this._setElementsDisabled( + [ + this._proxyTypeLabel, + this._proxyTypeMenulist, + this._proxyAddressLabel, + this._proxyAddressTextbox, + this._proxyPortLabel, + this._proxyPortTextbox, + this._proxyUsernameLabel, + this._proxyUsernameTextbox, + this._proxyPasswordLabel, + this._proxyPasswordTextbox, + ], + disabled + ); + if (enabled) { + this.onSelectProxyType(this._proxyTypeMenulist.value); + } + }, + + // callback when proxy type is changed + onSelectProxyType(value) { + if (typeof value === "string") { + value = parseInt(value); + } + + this._proxyTypeMenulist.value = value; + switch (value) { + case TorProxyType.Invalid: { + this._setElementsDisabled( + [ + this._proxyAddressLabel, + this._proxyAddressTextbox, + this._proxyPortLabel, + this._proxyPortTextbox, + this._proxyUsernameLabel, + this._proxyUsernameTextbox, + this._proxyPasswordLabel, + this._proxyPasswordTextbox, + ], + true + ); // DISABLE + + this._proxyAddressTextbox.value = ""; + this._proxyPortTextbox.value = ""; + this._proxyUsernameTextbox.value = ""; + this._proxyPasswordTextbox.value = ""; + break; + } + case TorProxyType.Socks4: { + this._setElementsDisabled( + [ + this._proxyAddressLabel, + this._proxyAddressTextbox, + this._proxyPortLabel, + this._proxyPortTextbox, + ], + false + ); // ENABLE + this._setElementsDisabled( + [ + this._proxyUsernameLabel, + this._proxyUsernameTextbox, + this._proxyPasswordLabel, + this._proxyPasswordTextbox, + ], + true + ); // DISABLE + + this._proxyUsernameTextbox.value = ""; + this._proxyPasswordTextbox.value = ""; + break; + } + case TorProxyType.Socks5: + case TorProxyType.HTTPS: { + this._setElementsDisabled( + [ + this._proxyAddressLabel, + this._proxyAddressTextbox, + this._proxyPortLabel, + this._proxyPortTextbox, + this._proxyUsernameLabel, + this._proxyUsernameTextbox, + this._proxyPasswordLabel, + this._proxyPasswordTextbox, + ], + false + ); // ENABLE + break; + } + } + }, + + // callback when firewall proxy is toggled + onToggleFirewall(enabled) { + this._useFirewallCheckbox.checked = enabled; + let disabled = !enabled; + + this._setElementsDisabled( + [this._allowedPortsLabel, this._allowedPortsTextbox], + disabled + ); + }, + + // pushes settings from UI to tor + _applySettings() { + const type = this._useProxyCheckbox.checked + ? parseInt(this._proxyTypeMenulist.value) + : TorProxyType.Invalid; + const address = this._proxyAddressTextbox.value; + const port = this._proxyPortTextbox.value; + const username = this._proxyUsernameTextbox.value; + const password = this._proxyPasswordTextbox.value; + const settings = { proxy: {}, firewall: {} }; + switch (type) { + case TorProxyType.Invalid: + settings.proxy.enabled = false; + break; + case TorProxyType.Socks4: + settings.proxy.enabled = true; + settings.proxy.type = type; + settings.proxy.address = address; + settings.proxy.port = port; + settings.proxy.username = ""; + settings.proxy.password = ""; + break; + case TorProxyType.Socks5: + settings.proxy.enabled = true; + settings.proxy.type = type; + settings.proxy.address = address; + settings.proxy.port = port; + settings.proxy.username = username; + settings.proxy.password = password; + break; + case TorProxyType.HTTPS: + settings.proxy.enabled = true; + settings.proxy.type = type; + settings.proxy.address = address; + settings.proxy.port = port; + settings.proxy.username = username; + settings.proxy.password = password; + break; + } + + let portListString = this._useFirewallCheckbox.checked + ? this._allowedPortsTextbox.value + : ""; + if (portListString) { + settings.firewall.enabled = true; + settings.firewall.allowed_ports = portListString; + } else { + settings.firewall.enabled = false; + } + + // FIXME: What if this fails? Should we prevent the dialog to close and show + // an error? + TorSettings.changeSettings(settings); + }, +}; + +// Initial focus is not visible, even if opened with a keyboard. We avoid the +// default handler and manage the focus ourselves, which will paint the focus +// ring by default. +// NOTE: A side effect is that the focus ring will show even if the user opened +// with a mouse event. +// TODO: Remove this once bugzilla bug 1708261 is resolved. +document.subDialogSetDefaultFocus = () => { + document.getElementById("torPreferences-connection-toggleProxy").focus(); +}; + +window.addEventListener( + "DOMContentLoaded", + () => { + gConnectionSettingsDialog.init(); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/connectionSettingsDialog.xhtml b/browser/components/torpreferences/content/connectionSettingsDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..97e8dc5ae94d7f37ff3565b7616c44b468eda905 --- /dev/null +++ b/browser/components/torpreferences/content/connectionSettingsDialog.xhtml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="tor-advanced-dialog-title" +> + <dialog id="torPreferences-connection-dialog" buttons="accept,cancel"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/connectionSettingsDialog.js" /> + + <description + id="torPreferences-connection-header" + data-l10n-id="tor-advanced-dialog-introduction" + ></description> + <!-- Local Proxy --> + <checkbox + id="torPreferences-connection-toggleProxy" + data-l10n-id="tor-advanced-dialog-proxy-checkbox" + /> + <box id="torPreferences-connection-grid"> + <hbox class="indent" align="center"> + <label + id="torPreferences-localProxy-type" + data-l10n-id="tor-advanced-dialog-proxy-type-selector-label" + control="torPreferences-localProxy-builtinList" + /> + </hbox> + <hbox align="center"> + <spacer flex="1" /> + <menulist + id="torPreferences-localProxy-builtinList" + class="torMarginFix" + > + <menupopup /> + </menulist> + </hbox> + <hbox class="indent" align="center"> + <label + id="torPreferences-localProxy-address" + data-l10n-id="tor-advanced-dialog-proxy-address-input-label" + control="torPreferences-localProxy-textboxAddress" + /> + </hbox> + <hbox align="center"> + <html:input + id="torPreferences-localProxy-textboxAddress" + type="text" + class="torMarginFix" + data-l10n-id="tor-advanced-dialog-proxy-address-input" + /> + <label + id="torPreferences-localProxy-port" + data-l10n-id="tor-advanced-dialog-proxy-port-input-label" + control="torPreferences-localProxy-textboxPort" + /> + <!-- proxy-port-input class style pulled from preferences.css and used in the vanilla proxy setup menu --> + <html:input + id="torPreferences-localProxy-textboxPort" + class="proxy-port-input torMarginFix" + hidespinbuttons="true" + type="number" + min="0" + max="65535" + maxlength="5" + /> + </hbox> + <hbox class="indent" align="center"> + <label + id="torPreferences-localProxy-username" + data-l10n-id="tor-advanced-dialog-proxy-username-input-label" + control="torPreferences-localProxy-textboxUsername" + /> + </hbox> + <hbox align="center"> + <html:input + id="torPreferences-localProxy-textboxUsername" + type="text" + class="torMarginFix" + data-l10n-id="tor-advanced-dialog-proxy-username-input" + /> + <label + id="torPreferences-localProxy-password" + data-l10n-id="tor-advanced-dialog-proxy-password-input-label" + control="torPreferences-localProxy-textboxPassword" + /> + <html:input + id="torPreferences-localProxy-textboxPassword" + class="torMarginFix" + type="password" + data-l10n-id="tor-advanced-dialog-proxy-password-input" + /> + </hbox> + </box> + <!-- Firewall --> + <checkbox + id="torPreferences-connection-toggleFirewall" + data-l10n-id="tor-advanced-dialog-firewall-checkbox" + /> + <box id="torPreferences-connection-firewall"> + <hbox class="indent" align="center"> + <label + id="torPreferences-connection-allowedPorts" + data-l10n-id="tor-advanced-dialog-firewall-ports-input-label" + control="torPreferences-connection-textboxAllowedPorts" + /> + </hbox> + <hbox id="torPreferences-connection-hboxAllowedPorts" align="center"> + <html:input + id="torPreferences-connection-textboxAllowedPorts" + type="text" + class="torMarginFix" + value="80,443" + data-l10n-id="tor-advanced-dialog-firewall-ports-input" + /> + </hbox> + </box> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/lox-bridge-icon.svg b/browser/components/torpreferences/content/lox-bridge-icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..f9971b36273e56370151e40ecff4af0c6f03d4f0 --- /dev/null +++ b/browser/components/torpreferences/content/lox-bridge-icon.svg @@ -0,0 +1,6 @@ +<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="0.5" y="0.5" width="17" height="17" rx="1.5" stroke="context-stroke"/> +<path d="M14.625 11.625C14.625 8.5184 12.1066 6 9 6C5.8934 6 3.375 8.5184 3.375 11.625V12.5596H4.25391V11.625C4.25391 9.0038 6.3788 6.87891 9 6.87891C11.6212 6.87891 13.7461 9.0038 13.7461 11.625V12.5596H14.625V11.625Z" fill="context-fill"/> +<path d="M12.9375 11.625C12.9375 9.45037 11.1746 7.6875 9 7.6875C6.82537 7.6875 5.0625 9.45037 5.0625 11.625L5.06242 12.5596H5.94132L5.9414 11.625C5.9414 9.93578 7.31078 8.5664 9 8.5664C10.6892 8.5664 12.0586 9.93578 12.0586 11.625L12.0587 12.5596H12.9376L12.9375 11.625Z" fill="context-fill"/> +<path d="M9 9.375C10.2426 9.375 11.25 10.3824 11.25 11.625L11.2502 12.5596H10.3713L10.3711 11.625C10.3711 10.8678 9.75724 10.2539 9 10.2539C8.24277 10.2539 7.62891 10.8678 7.62891 11.625L7.62873 12.5596H6.74982V11.625C6.74982 10.3824 7.75736 9.375 9 9.375Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torpreferences/content/lox-bridge-pass.svg b/browser/components/torpreferences/content/lox-bridge-pass.svg new file mode 100644 index 0000000000000000000000000000000000000000..e4a19b8908c1b3fbeb84102fcc4b53ad15d81bdd --- /dev/null +++ b/browser/components/torpreferences/content/lox-bridge-pass.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" clip-rule="evenodd" d="M0.825958 10.1991C0.191356 9.56445 0.191356 8.53556 0.825958 7.90095L7.89702 0.829887C8.53163 0.195285 9.56052 0.195285 10.1951 0.829887L11.3198 1.95455C11.5751 2.2099 11.6412 2.59873 11.4846 2.92409C11.0031 3.9241 12.0507 4.97168 13.0507 4.4902C13.376 4.33354 13.7649 4.39962 14.0202 4.65497L15.1449 5.77963C15.7795 6.41424 15.7795 7.44313 15.1449 8.07773L8.0738 15.1488C7.4392 15.7834 6.41031 15.7834 5.7757 15.1488L4.65104 14.0241C4.39569 13.7688 4.32961 13.38 4.48627 13.0546C4.96775 12.0546 3.92017 11.007 2.92016 11.4885C2.5948 11.6451 2.20597 11.5791 1.95062 11.3237L0.825958 10.1991ZM1.70984 8.78484C1.56339 8.93128 1.56339 9.16872 1.70984 9.31517L2.64555 10.2509C4.53493 9.58573 6.38902 11.4398 5.72388 13.3292L6.65959 14.2649C6.80603 14.4114 7.04347 14.4114 7.18992 14.2649L14.261 7.19385C14.4074 7.0474 14.4074 6.80996 14.261 6.66352L13.3253 5.7278C11.4359 6.39295 9.5818 4.53886 10.247 2.64948L9.31124 1.71377C9.16479 1.56732 8.92735 1.56732 8.78091 1.71377L1.70984 8.78484Z" fill="context-fill"/> + <path d="M8.87637 9.78539L9.76025 8.90151L10.6441 9.78539L9.76025 10.6693L8.87637 9.78539Z" fill="context-fill"/> + <path d="M7.1086 8.01763L7.99249 7.13374L8.87637 8.01763L7.99249 8.90151L7.1086 8.01763Z" fill="context-fill"/> + <path d="M5.34084 6.24986L6.22472 5.36598L7.1086 6.24986L6.22472 7.13374L5.34084 6.24986Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torpreferences/content/lox-complete-ring.svg b/browser/components/torpreferences/content/lox-complete-ring.svg new file mode 100644 index 0000000000000000000000000000000000000000..0d48eb2b09cfd985fb9dc04ac087b88420b0028c --- /dev/null +++ b/browser/components/torpreferences/content/lox-complete-ring.svg @@ -0,0 +1,12 @@ +<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> +<defs> + <filter id="ring-blur" x="0" y="0" width="44" height="44" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feColorMatrix in="SourceGraphic" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0"/> + <feGaussianBlur stdDeviation="2"/> + <feBlend mode="normal" in="SourceGraphic"/> + </filter> +</defs> +<g filter="url(#ring-blur)"> +<path d="M40 22C40 31.9411 31.9411 40 22 40C12.0589 40 4 31.9411 4 22C4 12.0589 12.0589 4 22 4C31.9411 4 40 12.0589 40 22ZM6.25 22C6.25 30.6985 13.3015 37.75 22 37.75C30.6985 37.75 37.75 30.6985 37.75 22C37.75 13.3015 30.6985 6.25 22 6.25C13.3015 6.25 6.25 13.3015 6.25 22Z" fill="context-fill"/> +</g> +</svg> diff --git a/browser/components/torpreferences/content/lox-invite-icon.svg b/browser/components/torpreferences/content/lox-invite-icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..0fd8dde2a5351c3406ca010fd36acd9d5e3abcee --- /dev/null +++ b/browser/components/torpreferences/content/lox-invite-icon.svg @@ -0,0 +1,4 @@ +<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="0.5" y="0.5" width="17" height="17" rx="1.5" stroke="context-stroke"/> +<path d="M9 9C8.45 9 7.97917 8.80417 7.5875 8.4125C7.19583 8.02083 7 7.55 7 7C7 6.45 7.19583 5.97917 7.5875 5.5875C7.97917 5.19583 8.45 5 9 5C9.55 5 10.0208 5.19583 10.4125 5.5875C10.8042 5.97917 11 6.45 11 7C11 7.55 10.8042 8.02083 10.4125 8.4125C10.0208 8.80417 9.55 9 9 9ZM5 12V11.6C5 11.3167 5.07292 11.0563 5.21875 10.8187C5.36458 10.5812 5.55833 10.4 5.8 10.275C6.31667 10.0167 6.84167 9.82292 7.375 9.69375C7.90833 9.56458 8.45 9.5 9 9.5C9.55 9.5 10.0917 9.56458 10.625 9.69375C11.1583 9.82292 11.6833 10.0167 12.2 10.275C12.4417 10.4 12.6354 10.5812 12.7812 10.8187C12.9271 11.0563 13 11.3167 13 11.6V12C13 12.275 12.9021 12.5104 12.7063 12.7063C12.5104 12.9021 12.275 13 12 13H6C5.725 13 5.48958 12.9021 5.29375 12.7063C5.09792 12.5104 5 12.275 5 12ZM6 12H12V11.6C12 11.5083 11.9771 11.425 11.9313 11.35C11.8854 11.275 11.825 11.2167 11.75 11.175C11.3 10.95 10.8458 10.7813 10.3875 10.6688C9.92917 10.5563 9.46667 10.5 9 10.5C8.53333 10.5 8.07083 10.5563 7.6125 10.6688C7.15417 10.7813 6.7 10.95 6.25 11.175C6.175 11.2167 6.11458 11.275 6.06875 11.35C6.02292 11.425 6 11.5083 6 11.6V12ZM9 8C9.275 8 9.51042 7.90208 9.70625 7.70625C9.90208 7.51042 10 7.275 10 7C10 6.725 9.90208 6.48958 9.70625 6.29375C9.51042 6.09792 9.275 6 9 6C8.725 6 8.48958 6.09792 8.29375 6.29375C8.09792 6.48958 8 6.725 8 7C8 7.275 8.09792 7.51042 8.29375 7.70625C8.48958 7.90208 8.725 8 9 8Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torpreferences/content/lox-progress-ring.svg b/browser/components/torpreferences/content/lox-progress-ring.svg new file mode 100644 index 0000000000000000000000000000000000000000..9ab9ff87ad4cedeb8d47498113936ddda153041e --- /dev/null +++ b/browser/components/torpreferences/content/lox-progress-ring.svg @@ -0,0 +1,13 @@ +<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> +<defs> + <filter id="ring-blur" x="0" y="0" width="44" height="44" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feColorMatrix in="SourceGraphic" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0"/> + <feGaussianBlur stdDeviation="2"/> + <feBlend mode="normal" in="SourceGraphic"/> + </filter> +</defs> +<path d="M 40,22 C 40,31.9411 31.9411,40 22,40 12.05887,40 4,31.9411 4,22 4,12.0589 12.05887,4 22,4 31.9411,4 40,12.0589 40,22 Z M 6.25,22 c 0,8.6985 7.05152,15.75 15.75,15.75 8.6985,0 15.75,-7.0515 15.75,-15.75 C 37.75,13.3015 30.6985,6.25 22,6.25 13.30152,6.25 6.25,13.3015 6.25,22 Z" fill="context-stroke"/> +<g filter="url(#ring-blur)"> + <path d="m 22,5.125 c 0,-0.62132 0.5042,-1.12866 1.1243,-1.08986 3.0298,0.18958 5.963,1.14263 8.5256,2.77013 0.5245,0.3331 0.6342,1.03991 0.269,1.54257 C 31.5537,8.8505 30.852,8.95814 30.3246,8.62974 28.1505,7.27609 25.6786,6.47291 23.1241,6.29015 22.5044,6.24582 22,5.74632 22,5.125 Z" fill="context-fill"/> +</g> +</svg> diff --git a/browser/components/torpreferences/content/lox-success.svg b/browser/components/torpreferences/content/lox-success.svg new file mode 100644 index 0000000000000000000000000000000000000000..bd7f5d09c81d49c5f39adc28b060aea4087fa57e --- /dev/null +++ b/browser/components/torpreferences/content/lox-success.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M10 14C9.62059 14.0061 9.25109 13.8787 8.95594 13.6403C8.6608 13.4018 8.45874 13.0672 8.385 12.695L8.028 11.028C7.97202 10.7692 7.84264 10.5321 7.65536 10.345C7.46807 10.1579 7.23081 10.0287 6.972 9.973L5.305 9.616C4.524 9.447 4 8.798 4 8C4 7.202 4.524 6.553 5.305 6.385L6.972 6.028C7.23078 5.97185 7.46794 5.84243 7.65519 5.65519C7.84243 5.46794 7.97185 5.23078 8.028 4.972L8.386 3.305C8.553 2.524 9.202 2 10 2C10.798 2 11.447 2.524 11.615 3.305L11.972 4.972C12.086 5.5 12.5 5.914 13.028 6.027L14.695 6.384C15.476 6.553 16 7.202 16 8C16 8.798 15.476 9.447 14.695 9.615L13.028 9.972C12.769 10.028 12.5316 10.1575 12.3443 10.345C12.157 10.5324 12.0277 10.7699 11.972 11.029L11.614 12.695C11.5407 13.0672 11.3388 13.4019 11.0438 13.6404C10.7488 13.8789 10.3793 14.0062 10 14ZM10 3.25C9.902 3.25 9.669 3.28 9.608 3.566L9.25 5.234C9.14333 5.72828 8.89643 6.18132 8.53888 6.53888C8.18132 6.89643 7.72828 7.14333 7.234 7.25L5.567 7.607C5.281 7.669 5.25 7.902 5.25 8C5.25 8.098 5.281 8.331 5.567 8.393L7.234 8.75C7.72828 8.85667 8.18132 9.10357 8.53888 9.46112C8.89643 9.81868 9.14333 10.2717 9.25 10.766L9.608 12.434C9.669 12.72 9.902 12.75 10 12.75C10.098 12.75 10.331 12.72 10.392 12.434L10.75 10.767C10.8565 10.2725 11.1033 9.81928 11.4609 9.46154C11.8185 9.10379 12.2716 8.85674 12.766 8.75L14.433 8.393C14.719 8.331 14.75 8.098 14.75 8C14.75 7.902 14.719 7.669 14.433 7.607L12.766 7.25C12.2717 7.14333 11.8187 6.89643 11.4611 6.53888C11.1036 6.18132 10.8567 5.72828 10.75 5.234L10.392 3.566C10.331 3.28 10.098 3.25 10 3.25Z" fill="context-fill"/> + <path d="M2.44399 12.151L2.62599 11.302C2.71199 10.9 3.28599 10.9 3.37299 11.302L3.55499 12.151C3.57035 12.2229 3.60618 12.2888 3.65817 12.3408C3.71016 12.3928 3.77609 12.4286 3.84799 12.444L4.69699 12.626C5.09899 12.712 5.09899 13.286 4.69699 13.373L3.84799 13.555C3.77609 13.5704 3.71016 13.6062 3.65817 13.6582C3.60618 13.7102 3.57035 13.7761 3.55499 13.848L3.37299 14.697C3.28699 15.099 2.71299 15.099 2.62599 14.697L2.44399 13.848C2.42863 13.7761 2.39279 13.7102 2.3408 13.6582C2.28881 13.6062 2.22289 13.5704 2.15099 13.555L1.30199 13.373C0.899988 13.287 0.899988 12.713 1.30199 12.626L2.15099 12.444C2.22294 12.4288 2.28893 12.393 2.34094 12.341C2.39295 12.2889 2.42875 12.223 2.44399 12.151Z" fill="context-fill"/> + <path d="M2.44399 2.151L2.62599 1.302C2.71199 0.900004 3.28599 0.900004 3.37299 1.302L3.55499 2.151C3.57035 2.22291 3.60618 2.28883 3.65817 2.34082C3.71016 2.39281 3.77609 2.42864 3.84799 2.444L4.69699 2.626C5.09899 2.712 5.09899 3.286 4.69699 3.373L3.84899 3.556C3.77703 3.57125 3.71105 3.60704 3.65904 3.65905C3.60703 3.71106 3.57123 3.77705 3.55599 3.849L3.37299 4.698C3.28699 5.1 2.71299 5.1 2.62599 4.698L2.44399 3.849C2.42875 3.77705 2.39295 3.71106 2.34094 3.65905C2.28893 3.60704 2.22294 3.57125 2.15099 3.556L1.30199 3.373C0.899988 3.287 0.899988 2.713 1.30199 2.626L2.15099 2.444C2.22294 2.42876 2.28893 2.39296 2.34094 2.34095C2.39295 2.28894 2.42875 2.22296 2.44399 2.151Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torpreferences/content/loxInviteDialog.js b/browser/components/torpreferences/content/loxInviteDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..f5e0c7d5d45903a32f657a210cb4652fc2145850 --- /dev/null +++ b/browser/components/torpreferences/content/loxInviteDialog.js @@ -0,0 +1,366 @@ +"use strict"; + +const { TorSettings, TorSettingsTopics, TorBridgeSource } = + ChromeUtils.importESModule("resource://gre/modules/TorSettings.sys.mjs"); + +const { Lox, LoxError, LoxTopics } = ChromeUtils.importESModule( + "resource://gre/modules/Lox.sys.mjs" +); + +/** + * Fake Lox module + +const LoxError = { + LoxServerUnreachable: "LoxServerUnreachable", + Other: "Other", +}; + +const Lox = { + remainingInvites: 5, + getRemainingInviteCount() { + return this.remainingInvites; + }, + invites: [ + '{"invite": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]}', + '{"invite": [9,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]}', + ], + getInvites() { + return this.invites; + }, + failError: null, + generateInvite() { + return new Promise((res, rej) => { + setTimeout(() => { + if (this.failError) { + rej({ type: this.failError }); + return; + } + if (!this.remainingInvites) { + rej({ type: LoxError.Other }); + return; + } + const invite = JSON.stringify({ + invite: Array.from({ length: 100 }, () => + Math.floor(Math.random() * 265) + ), + }); + this.invites.push(invite); + this.remainingInvites--; + res(invite); + }, 4000); + }); + }, +}; +*/ + +const gLoxInvites = { + /** + * Initialize the dialog. + */ + init() { + this._dialog = document.getElementById("lox-invite-dialog"); + this._remainingInvitesEl = document.getElementById( + "lox-invite-dialog-remaining" + ); + this._generateArea = document.getElementById( + "lox-invite-dialog-generate-area" + ); + this._generateButton = document.getElementById( + "lox-invite-dialog-generate-button" + ); + this._errorEl = document.getElementById("lox-invite-dialog-error-message"); + this._inviteListEl = document.getElementById("lox-invite-dialog-list"); + + this._generateButton.addEventListener("click", () => { + this._generateNewInvite(); + }); + + const menu = document.getElementById("lox-invite-dialog-item-menu"); + this._inviteListEl.addEventListener("contextmenu", event => { + if (!this._inviteListEl.selectedItem) { + return; + } + menu.openPopupAtScreen(event.screenX, event.screenY, true); + }); + menu.addEventListener("popuphidden", () => { + menu.setAttribute("aria-hidden", "true"); + }); + menu.addEventListener("popupshowing", () => { + menu.removeAttribute("aria-hidden"); + }); + document + .getElementById("lox-invite-dialog-copy-menu-item") + .addEventListener("command", () => { + const selected = this._inviteListEl.selectedItem; + if (!selected) { + return; + } + const clipboard = Cc[ + "@mozilla.org/widget/clipboardhelper;1" + ].getService(Ci.nsIClipboardHelper); + clipboard.copyString(selected.textContent); + }); + + // NOTE: TorSettings should already be initialized when this dialog is + // opened. + Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged); + Services.obs.addObserver(this, LoxTopics.UpdateActiveLoxId); + Services.obs.addObserver(this, LoxTopics.UpdateRemainingInvites); + Services.obs.addObserver(this, LoxTopics.NewInvite); + + // Set initial _loxId value. Can close this dialog. + this._updateLoxId(); + + this._updateRemainingInvites(); + this._updateExistingInvites(); + }, + + /** + * Un-initialize the dialog. + */ + uninit() { + Services.obs.removeObserver(this, TorSettingsTopics.SettingsChanged); + Services.obs.removeObserver(this, LoxTopics.UpdateActiveLoxId); + Services.obs.removeObserver(this, LoxTopics.UpdateRemainingInvites); + Services.obs.removeObserver(this, LoxTopics.NewInvite); + }, + + observe(subject, topic) { + switch (topic) { + case TorSettingsTopics.SettingsChanged: + const { changes } = subject.wrappedJSObject; + if (changes.includes("bridges.source")) { + this._updateLoxId(); + } + break; + case LoxTopics.UpdateActiveLoxId: + this._updateLoxId(); + break; + case LoxTopics.UpdateRemainingInvites: + this._updateRemainingInvites(); + break; + case LoxTopics.NewInvite: + this._updateExistingInvites(); + break; + } + }, + + /** + * The loxId this dialog is shown for. null if uninitailized. + * + * @type {string?} + */ + _loxId: null, + /** + * Update the _loxId value. Will close the dialog if it changes after + * initialization. + */ + _updateLoxId() { + const loxId = + TorSettings.bridges.source === TorBridgeSource.Lox ? Lox.activeLoxId : ""; + if (!loxId || (this._loxId !== null && loxId !== this._loxId)) { + // No lox id, or it changed. Close this dialog. + this._dialog.cancelDialog(); + } + this._loxId = loxId; + }, + + /** + * The invites that are already shown. + * + * @type {Set<string>} + */ + _shownInvites: new Set(), + + /** + * Add a new invite at the start of the list. + * + * @param {string} invite - The invite to add. + */ + _addInvite(invite) { + if (this._shownInvites.has(invite)) { + return; + } + const newInvite = document.createXULElement("richlistitem"); + newInvite.classList.add("lox-invite-dialog-list-item"); + newInvite.textContent = invite; + + this._inviteListEl.prepend(newInvite); + this._shownInvites.add(invite); + }, + + /** + * Update the display of the existing invites. + */ + _updateExistingInvites() { + // Add new invites. + + // NOTE: we only expect invites to be appended, so we won't re-order any. + // NOTE: invites are ordered with the oldest first. + for (const invite of Lox.getInvites()) { + this._addInvite(invite); + } + }, + + /** + * The shown number or remaining invites we have. + * + * @type {integer} + */ + _remainingInvites: 0, + + /** + * Update the display of the remaining invites. + */ + _updateRemainingInvites() { + this._remainingInvites = Lox.getRemainingInviteCount(this._loxId); + + document.l10n.setAttributes( + this._remainingInvitesEl, + "tor-bridges-lox-remaining-invites", + { numInvites: this._remainingInvites } + ); + this._updateGenerateButtonState(); + }, + + /** + * Whether we are currently generating an invite. + * + * @type {boolean} + */ + _generating: false, + /** + * Set whether we are generating an invite. + * + * @param {boolean} isGenerating - Whether we are generating. + */ + _setGenerating(isGenerating) { + this._generating = isGenerating; + this._updateGenerateButtonState(); + this._generateArea.classList.toggle("show-connecting", isGenerating); + }, + + /** + * Whether the generate button is disabled. + * + * @type {boolean} + */ + _generateDisabled: false, + /** + * Update the state of the generate button. + */ + _updateGenerateButtonState() { + const disabled = this._generating || !this._remainingInvites; + this._generateDisabled = disabled; + // When generating we use "aria-disabled" rather than the "disabled" + // attribute so that the button can remain focusable whilst we generate + // invites. + // TODO: Replace with moz-button when it handles this for us. See + // tor-browser#43275. + this._generateButton.classList.toggle("spoof-button-disabled", disabled); + this._generateButton.tabIndex = disabled ? -1 : 0; + if (disabled) { + this._generateButton.setAttribute("aria-disabled", "true"); + } else { + this._generateButton.removeAttribute("aria-disabled"); + } + }, + + /** + * Start generating a new invite. + */ + _generateNewInvite() { + if (this._generateDisabled) { + return; + } + if (this._generating) { + console.error("Already generating an invite"); + return; + } + this._setGenerating(true); + // Clear the previous error. + this._updateGenerateError(null); + + let moveFocus = false; + Lox.generateInvite(this._loxId) + .finally(() => { + // Fetch whether the generate button has focus before we potentially + // disable it. + moveFocus = this._generateButton.contains(document.activeElement); + this._setGenerating(false); + }) + .then( + invite => { + this._addInvite(invite); + + if (!this._inviteListEl.contains(document.activeElement)) { + // Does not have focus, change the selected item to be the new + // invite (at index 0). + this._inviteListEl.selectedIndex = 0; + } + + if (moveFocus) { + // Move focus to the new invite before we hide the "Connecting" + // message. + this._inviteListEl.focus(); + } + }, + loxError => { + console.error("Failed to generate an invite", loxError); + switch (loxError instanceof LoxError ? loxError.code : null) { + case LoxError.LoxServerUnreachable: + this._updateGenerateError("no-server"); + break; + default: + this._updateGenerateError("generic"); + break; + } + } + ); + }, + + /** + * Update the shown generation error. + * + * @param {string?} type - The error type, or null if no error should be + * shown. + */ + _updateGenerateError(type) { + // First clear the existing error. + this._errorEl.removeAttribute("data-l10n-id"); + this._errorEl.textContent = ""; + this._generateArea.classList.toggle("show-error", !!type); + + if (!type) { + return; + } + + let errorId; + switch (type) { + case "no-server": + errorId = "lox-invite-dialog-no-server-error"; + break; + case "generic": + // Generic error. + errorId = "lox-invite-dialog-generic-invite-error"; + break; + } + + document.l10n.setAttributes(this._errorEl, errorId); + }, +}; + +window.addEventListener( + "DOMContentLoaded", + () => { + gLoxInvites.init(); + window.addEventListener( + "unload", + () => { + gLoxInvites.uninit(); + }, + { once: true } + ); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/loxInviteDialog.xhtml b/browser/components/torpreferences/content/loxInviteDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..9266eed9a5c8486b566548cdde21b760ef2d139a --- /dev/null +++ b/browser/components/torpreferences/content/loxInviteDialog.xhtml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="lox-invite-dialog-title" +> + <!-- Context menu, aria-hidden whilst not shown so it does not appear in the + - document content. --> + <menupopup id="lox-invite-dialog-item-menu" aria-hidden="true"> + <menuitem + id="lox-invite-dialog-copy-menu-item" + data-l10n-id="lox-invite-dialog-menu-item-copy-invite" + /> + </menupopup> + <dialog id="lox-invite-dialog" buttons="accept"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + <html:link + rel="localization" + href="locales-preview/tor-browser-no-translate.ftl" + /> + </linkset> + + <script src="chrome://browser/content/torpreferences/loxInviteDialog.js" /> + + <description data-l10n-id="lox-invite-dialog-description"></description> + <html:div id="lox-invite-dialog-generate-area"> + <html:span id="lox-invite-dialog-remaining"></html:span> + <html:button + id="lox-invite-dialog-generate-button" + data-l10n-id="lox-invite-dialog-request-button" + ></html:button> + <html:div id="lox-invite-dialog-message-area"> + <html:span + id="lox-invite-dialog-error-message" + role="alert" + ></html:span> + <img + id="lox-invite-dialog-loading-icon" + class="tor-loading-icon" + alt="" + /> + <html:span + id="lox-invite-dialog-connecting" + role="alert" + data-l10n-id="lox-invite-dialog-connecting" + ></html:span> + </html:div> + </html:div> + <html:div + id="lox-invite-dialog-list-label" + data-l10n-id="lox-invite-dialog-invites-label" + ></html:div> + <richlistbox + id="lox-invite-dialog-list" + aria-labelledby="lox-invite-dialog-list-label" + ></richlistbox> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/mail.svg b/browser/components/torpreferences/content/mail.svg new file mode 100644 index 0000000000000000000000000000000000000000..b31e7f4d79c1dd21605ddec877bd44b8d13ece39 --- /dev/null +++ b/browser/components/torpreferences/content/mail.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" d="M13 2.5H3C1.89543 2.5 1 3.39543 1 4.5V11.5C1 12.6046 1.89543 13.5 3 13.5H13C14.1046 13.5 15 12.6046 15 11.5V4.5C15 3.39543 14.1046 2.5 13 2.5ZM12.8023 3.75H3.19766L7.7466 7.91986C7.88997 8.05129 8.11003 8.05129 8.2534 7.91986L12.8023 3.75ZM2.25 4.57702V11.5C2.25 11.9142 2.58579 12.25 3 12.25H13C13.4142 12.25 13.75 11.9142 13.75 11.5V4.57702L9.09805 8.84131C8.47678 9.41081 7.52322 9.41081 6.90195 8.84131L2.25 4.57702Z" fill="context-fill" /> +</svg> diff --git a/browser/components/torpreferences/content/network-broken.svg b/browser/components/torpreferences/content/network-broken.svg new file mode 100644 index 0000000000000000000000000000000000000000..fd04523648c6aeb519293b0ec2587820133ae387 --- /dev/null +++ b/browser/components/torpreferences/content/network-broken.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="18.6565" height="1.22295" rx="0.611475" transform="matrix(-0.707107 -0.707107 -0.707107 0.707107 14.9464 14.1921)" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M3.9498 1.68761C5.14904 0.918177 6.55296 0.5 8 0.5C9.98912 0.5 11.8968 1.29018 13.3033 2.6967C14.7098 4.10322 15.5 6.01088 15.5 8C15.5 9.44704 15.0818 10.851 14.3124 12.0502L13.3945 11.1323C13.8373 10.3656 14.1137 9.51118 14.202 8.625H11.973C11.9515 8.95148 11.9131 9.27556 11.8582 9.596L9.63719 7.375H10.719C10.573 5.44665 9.75105 3.63171 8.398 2.25H7.602C7.08087 2.78217 6.63852 3.37861 6.28323 4.02104L5.37173 3.10954C5.55124 2.81339 5.74752 2.52639 5.96 2.25H5.552C5.31395 2.35224 5.08325 2.46884 4.86107 2.59888L3.9498 1.68761ZM13.0242 4.30006C12.3637 3.39877 11.4738 2.69088 10.447 2.25H10.04C11.1778 3.72922 11.8509 5.51288 11.974 7.375H14.203C14.0918 6.26313 13.6848 5.20135 13.0242 4.30006Z" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M3.08673 2.33343C2.9529 2.44948 2.82278 2.57061 2.6967 2.6967C1.29018 4.10322 0.5 6.01088 0.5 8C0.5 9.98912 1.29018 11.8968 2.6967 13.3033C4.10322 14.7098 6.01088 15.5 8 15.5C9.98912 15.5 11.8968 14.7098 13.3033 13.3033C13.4294 13.1772 13.5505 13.0471 13.6666 12.9133L12.7733 12.02C12.1456 12.7694 11.3496 13.3627 10.448 13.75H10.039C10.7209 12.8639 11.2359 11.8685 11.5656 10.8123L10.5448 9.79147C10.2135 11.2778 9.47326 12.6509 8.397 13.75H7.602C6.24895 12.3683 5.427 10.5534 5.281 8.625H9.37831L8.12831 7.375H5.281C5.34173 6.57283 5.51944 5.79028 5.80369 5.05038L4.8504 4.09709C4.38292 5.12591 4.10162 6.23576 4.026 7.375H1.797C1.90802 6.2632 2.31487 5.20145 2.97523 4.30016C3.26721 3.90165 3.60404 3.54094 3.97771 3.22441L3.08673 2.33343ZM2.97497 11.7C3.63536 12.6014 4.52524 13.3092 5.552 13.75H5.96C4.82222 12.2708 4.14912 10.4871 4.026 8.625H1.797C1.90781 9.73686 2.31458 10.7987 2.97497 11.7Z" fill="context-fill"/> +</svg> diff --git a/browser/components/torpreferences/content/network.svg b/browser/components/torpreferences/content/network.svg new file mode 100644 index 0000000000000000000000000000000000000000..ec0b88af6707d41071c3da6b1d993eeaa67f1cc7 --- /dev/null +++ b/browser/components/torpreferences/content/network.svg @@ -0,0 +1,3 @@ +<svg viewBox="0 0 16 16" width="16" height="16" xmlns="http://www.w3.org/2000/svg"> + <path d="m 8,0.5 a 7.5,7.5 0 1 0 0,15 7.5,7.5 0 0 0 0,-15 z m 2.447,1.75 a 6.255,6.255 0 0 1 3.756,5.125 H 11.974 A 9.426,9.426 0 0 0 10.04,2.25 Z m -2.049,0 a 8.211,8.211 0 0 1 2.321,5.125 H 5.281 A 8.211,8.211 0 0 1 7.602,2.25 Z m -2.846,0 H 5.96 A 9.434,9.434 0 0 0 4.026,7.375 H 1.797 A 6.254,6.254 0 0 1 5.552,2.25 Z m 0,11.5 A 6.252,6.252 0 0 1 1.797,8.625 H 4.026 A 9.426,9.426 0 0 0 5.96,13.75 Z m 2.05,0 A 8.211,8.211 0 0 1 5.281,8.625 h 5.437 A 8.211,8.211 0 0 1 8.397,13.75 Z m 2.846,0 h -0.409 a 9.418,9.418 0 0 0 1.934,-5.125 h 2.229 a 6.253,6.253 0 0 1 -3.754,5.125 z" fill="context-fill" /> +</svg> diff --git a/browser/components/torpreferences/content/provideBridgeDialog.js b/browser/components/torpreferences/content/provideBridgeDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..412b46e3416fd08c05fab7ac3c6cd5bd998877c0 --- /dev/null +++ b/browser/components/torpreferences/content/provideBridgeDialog.js @@ -0,0 +1,542 @@ +"use strict"; + +const { TorSettings, TorBridgeSource, validateBridgeLines } = + ChromeUtils.importESModule("resource://gre/modules/TorSettings.sys.mjs"); + +const { TorConnect, TorConnectStage, TorConnectTopics } = + ChromeUtils.importESModule("resource://gre/modules/TorConnect.sys.mjs"); + +const { TorParsers } = ChromeUtils.importESModule( + "resource://gre/modules/TorParsers.sys.mjs" +); + +const { Lox, LoxError } = ChromeUtils.importESModule( + "resource://gre/modules/Lox.sys.mjs" +); + +/* + * Fake Lox module: + +const LoxError = { + BadInvite: "BadInvite", + LoxServerUnreachable: "LoxServerUnreachable", + Other: "Other", +}; + +const Lox = { + failError: null, + // failError: LoxError.BadInvite, + // failError: LoxError.LoxServerUnreachable, + // failError: LoxError.Other, + redeemInvite(invite) { + return new Promise((res, rej) => { + setTimeout(() => { + if (this.failError) { + rej({ type: this.failError }); + } + res("lox-id-000000"); + }, 4000); + }); + }, + validateInvitation(invite) { + return invite.startsWith("lox-invite"); + }, + getBridges(id) { + return [ + "0:0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "0:1 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + ]; + }, +}; +*/ + +const gProvideBridgeDialog = { + init() { + this._result = window.arguments[0]; + const mode = window.arguments[1].mode; + + let titleId; + switch (mode) { + case "edit": + titleId = "user-provide-bridge-dialog-edit-title"; + break; + case "add": + titleId = "user-provide-bridge-dialog-add-title"; + break; + case "replace": + default: + titleId = "user-provide-bridge-dialog-replace-title"; + break; + } + + document.l10n.setAttributes(document.documentElement, titleId); + + this._allowLoxInvite = mode !== "edit" && Lox.enabled; + + document.l10n.setAttributes( + document.getElementById("user-provide-bridge-textarea-label"), + this._allowLoxInvite + ? "user-provide-bridge-dialog-textarea-addresses-or-invite-label" + : "user-provide-bridge-dialog-textarea-addresses-label" + ); + + this._dialog = document.getElementById("user-provide-bridge-dialog"); + this._acceptButton = this._dialog.getButton("accept"); + + // Inject our stylesheet into the shadow root so that the accept button can + // take the spoof-button-disabled styling and tor-button styling. + const styleLink = document.createElement("link"); + styleLink.rel = "stylesheet"; + styleLink.href = + "chrome://browser/content/torpreferences/torPreferences.css"; + this._dialog.shadowRoot.append(styleLink); + + this._textarea = document.getElementById("user-provide-bridge-textarea"); + this._errorEl = document.getElementById( + "user-provide-bridge-error-message" + ); + this._resultDescription = document.getElementById( + "user-provide-result-description" + ); + this._bridgeGrid = document.getElementById( + "user-provide-bridge-grid-display" + ); + this._rowTemplate = document.getElementById( + "user-provide-bridge-row-template" + ); + + if (mode === "edit") { + // Only expected if the bridge source is UseProvided, but verify to be + // sure. + if (TorSettings.bridges.source == TorBridgeSource.UserProvided) { + this._textarea.value = TorSettings.bridges.bridge_strings.join("\n"); + } + } else { + // Set placeholder if not editing. + document.l10n.setAttributes( + this._textarea, + this._allowLoxInvite + ? "user-provide-bridge-dialog-textarea-addresses-or-invite" + : "user-provide-bridge-dialog-textarea-addresses" + ); + } + + this._textarea.addEventListener("input", () => this.onValueChange()); + + this._dialog.addEventListener("dialogaccept", event => + this.onDialogAccept(event) + ); + + Services.obs.addObserver(this, TorConnectTopics.StageChange); + + this.setPage("entry"); + this.checkValue(); + }, + + uninit() { + Services.obs.removeObserver(this, TorConnectTopics.StageChange); + }, + + /** + * Set the page to display. + * + * @param {string} page - The page to show. + */ + setPage(page) { + this._page = page; + this._dialog.classList.toggle("show-entry-page", page === "entry"); + this._dialog.classList.toggle("show-result-page", page === "result"); + this.takeFocus(); + this.updateResult(); + this.updateAcceptDisabled(); + this.onAcceptStateChange(); + }, + + /** + * Reset focus position in the dialog. + */ + takeFocus() { + switch (this._page) { + case "entry": + this._textarea.focus(); + break; + case "result": + // Move focus to the table. + // In particular, we do not want to keep the focus on the (same) accept + // button (with now different text). + this._bridgeGrid.focus(); + break; + } + }, + + /** + * Callback for whenever the input value changes. + */ + onValueChange() { + this.updateAcceptDisabled(); + // Reset errors whenever the value changes. + this.updateError(null); + }, + + /** + * Callback for whenever the accept button may need to change. + */ + onAcceptStateChange() { + let connect = false; + if (this._page === "entry") { + this._acceptButton.setAttribute( + "data-l10n-id", + "user-provide-bridge-dialog-next-button" + ); + } else { + connect = TorConnect.stageName !== TorConnectStage.Bootstrapped; + this._acceptButton.setAttribute( + "data-l10n-id", + connect ? "bridge-dialog-button-connect" : "bridge-dialog-button-accept" + ); + } + this._result.connect = connect; + this._acceptButton.classList.toggle("tor-button", connect); + }, + + /** + * Whether the dialog accept button is disabled. + * + * @type {boolean} + */ + _acceptDisabled: false, + /** + * Callback for whenever the accept button's might need to be disabled. + */ + updateAcceptDisabled() { + const disabled = + this._page === "entry" && (this.isEmpty() || this._loxLoading); + this._acceptDisabled = disabled; + // Spoof the button to look and act as if it is disabled, but still allow + // keyboard focus so the user can sit on this button whilst we are loading. + // TODO: Replace with moz-button when it handles this for us. See + // tor-browser#43275. + this._acceptButton.classList.toggle("spoof-button-disabled", disabled); + this._acceptButton.tabIndex = disabled ? -1 : 0; + if (disabled) { + this._acceptButton.setAttribute("aria-disabled", "true"); + } else { + this._acceptButton.removeAttribute("aria-disabled"); + } + }, + + /** + * The lox loading state. + * + * @type {boolean} + */ + _loxLoading: false, + + /** + * Set the lox loading state. I.e. whether we are connecting to the lox + * server. + * + * @param {boolean} isLoading - Whether we are loading or not. + */ + setLoxLoading(isLoading) { + this._loxLoading = isLoading; + this._textarea.readOnly = isLoading; + this._dialog.classList.toggle("show-connecting", isLoading); + this.updateAcceptDisabled(); + }, + + /** + * Callback for when the accept button is pressed. + * + * @param {Event} event - The dialogaccept event. + */ + onDialogAccept(event) { + if (this._acceptDisabled) { + // Prevent closing. + event.preventDefault(); + return; + } + + if (this._page === "result") { + this._result.accepted = true; + // Continue to close the dialog. + return; + } + // Prevent closing the dialog. + event.preventDefault(); + + if (this._loxLoading) { + // User can still click Next whilst loading. + console.error("Already have a pending lox invite"); + return; + } + + // Clear the result from any previous attempt. + delete this._result.loxId; + delete this._result.addresses; + // Clear any previous error. + this.updateError(null); + + const value = this.checkValue(); + if (!value) { + // Not valid. + return; + } + if (value.loxInvite) { + this.setLoxLoading(true); + Lox.redeemInvite(value.loxInvite) + .finally(() => { + // Set set the loading to false before setting the errors. + this.setLoxLoading(false); + }) + .then( + loxId => { + this._result.loxId = loxId; + this.setPage("result"); + }, + loxError => { + console.error("Redeeming failed", loxError); + switch (loxError instanceof LoxError ? loxError.code : null) { + case LoxError.BadInvite: + // TODO: distinguish between a bad invite, an invite that has + // expired, and an invite that has already been redeemed. + this.updateError({ type: "bad-invite" }); + break; + case LoxError.LoxServerUnreachable: + this.updateError({ type: "no-server" }); + break; + default: + this.updateError({ type: "invite-error" }); + break; + } + } + ); + return; + } + + if (!value.addresses?.length) { + // Not valid + return; + } + this._result.addresses = value.addresses; + this.setPage("result"); + }, + + /** + * Update the displayed error. + * + * @param {object?} error - The error to show, or null if no error should be + * shown. Should include the "type" property. + */ + updateError(error) { + // First clear the existing error. + this._errorEl.removeAttribute("data-l10n-id"); + this._errorEl.textContent = ""; + if (error) { + this._textarea.setAttribute("aria-invalid", "true"); + } else { + this._textarea.removeAttribute("aria-invalid"); + } + this._textarea.classList.toggle("invalid-input", !!error); + this._dialog.classList.toggle("show-error", !!error); + + if (!error) { + return; + } + + let errorId; + let errorArgs; + switch (error.type) { + case "invalid-address": + errorId = "user-provide-bridge-dialog-address-error"; + errorArgs = { line: error.line }; + break; + case "multiple-invites": + errorId = "user-provide-bridge-dialog-multiple-invites-error"; + break; + case "mixed": + errorId = "user-provide-bridge-dialog-mixed-error"; + break; + case "not-allowed-invite": + errorId = "user-provide-bridge-dialog-invite-not-allowed-error"; + break; + case "bad-invite": + errorId = "user-provide-bridge-dialog-bad-invite-error"; + break; + case "no-server": + errorId = "user-provide-bridge-dialog-no-server-error"; + break; + case "invite-error": + // Generic invite error. + errorId = "user-provide-bridge-dialog-generic-invite-error"; + break; + } + + document.l10n.setAttributes(this._errorEl, errorId, errorArgs); + }, + + /** + * The condition for the value to be empty. + * + * @type {RegExp} + */ + _emptyRegex: /^\s*$/, + /** + * Whether the input is considered empty. + * + * @returns {boolean} true if it is considered empty. + */ + isEmpty() { + return this._emptyRegex.test(this._textarea.value); + }, + + /** + * Check the current value in the textarea. + * + * @returns {object?} - The bridge addresses, or lox invite, or null if no + * valid value. + */ + checkValue() { + if (this.isEmpty()) { + // If empty, we just disable the button, rather than show an error. + this.updateError(null); + return null; + } + + // Only check if this looks like a Lox invite when the Lox module is + // enabled. + if (Lox.enabled) { + let loxInvite = null; + for (let line of this._textarea.value.split(/\r?\n/)) { + line = line.trim(); + if (!line) { + continue; + } + // TODO: Once we have a Lox invite encoding, distinguish between a valid + // invite and something that looks like it should be an invite. + const isLoxInvite = Lox.validateInvitation(line); + if (isLoxInvite) { + if (!this._allowLoxInvite) { + // Lox is enabled, but not allowed invites when editing bridge + // addresses. + this.updateError({ type: "not-allowed-invite" }); + return null; + } + if (loxInvite) { + this.updateError({ type: "multiple-invites" }); + return null; + } + loxInvite = line; + } else if (loxInvite) { + this.updateError({ type: "mixed" }); + return null; + } + } + + if (loxInvite) { + return { loxInvite }; + } + } + + const validation = validateBridgeLines(this._textarea.value); + if (validation.errorLines.length) { + // Report first error. + this.updateError({ + type: "invalid-address", + line: validation.errorLines[0], + }); + return null; + } + + return { addresses: validation.validBridges }; + }, + + /** + * Update the shown result on the last page. + */ + updateResult() { + if (this._page !== "result") { + return; + } + + const loxId = this._result.loxId; + + document.l10n.setAttributes( + this._resultDescription, + loxId + ? "user-provide-bridge-dialog-result-invite" + : "user-provide-bridge-dialog-result-addresses" + ); + + this._bridgeGrid.replaceChildren(); + + const bridgeResult = loxId ? Lox.getBridges(loxId) : this._result.addresses; + + for (const bridgeLine of bridgeResult) { + let details; + try { + details = TorParsers.parseBridgeLine(bridgeLine); + } catch (e) { + console.error(`Detected invalid bridge line: ${bridgeLine}`, e); + } + + const rowEl = this._rowTemplate.content.children[0].cloneNode(true); + + const emojiBlock = rowEl.querySelector(".tor-bridges-emojis-block"); + const BridgeEmoji = customElements.get("tor-bridge-emoji"); + for (const cell of BridgeEmoji.createForAddress(bridgeLine)) { + // Each emoji is its own cell, we rely on the fact that createForAddress + // always returns four elements. + cell.setAttribute("role", "cell"); + cell.classList.add("tor-bridges-grid-cell", "tor-bridges-emoji-cell"); + emojiBlock.append(cell); + } + + const transport = details?.transport ?? "vanilla"; + const typeCell = rowEl.querySelector(".tor-bridges-type-cell"); + if (transport === "vanilla") { + document.l10n.setAttributes( + typeCell, + "tor-bridges-type-prefix-generic" + ); + } else { + document.l10n.setAttributes(typeCell, "tor-bridges-type-prefix", { + type: transport, + }); + } + + rowEl.querySelector(".tor-bridges-address-cell-text").textContent = + bridgeLine; + + this._bridgeGrid.append(rowEl); + } + }, + + observe(subject, topic) { + switch (topic) { + case TorConnectTopics.StageChange: + this.onAcceptStateChange(); + break; + } + }, +}; + +document.subDialogSetDefaultFocus = () => { + // Set the focus to the text area on load. + gProvideBridgeDialog.takeFocus(); +}; + +window.addEventListener( + "DOMContentLoaded", + () => { + gProvideBridgeDialog.init(); + window.addEventListener( + "unload", + () => { + gProvideBridgeDialog.uninit(); + }, + { once: true } + ); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/provideBridgeDialog.xhtml b/browser/components/torpreferences/content/provideBridgeDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..e15a5d6ef6daed97dbba17e7aa8b053df13b5947 --- /dev/null +++ b/browser/components/torpreferences/content/provideBridgeDialog.xhtml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" +> + <dialog + id="user-provide-bridge-dialog" + buttons="accept,cancel" + class="show-entry-page" + > + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/bridgemoji/BridgeEmoji.js" /> + <script src="chrome://browser/content/torpreferences/provideBridgeDialog.js" /> + + <html:div id="user-provide-bridge-entry-page"> + <description id="user-provide-bridge-description"> + <html:span + data-l10n-id="user-provide-bridge-dialog-description" + ></html:span> + <label + is="text-link" + class="learnMore text-link" + href="about:manual#bridges" + useoriginprincipal="true" + data-l10n-id="user-provide-bridge-dialog-learn-more" + /> + </description> + <html:label + id="user-provide-bridge-textarea-label" + for="user-provide-bridge-textarea" + ></html:label> + <html:textarea + id="user-provide-bridge-textarea" + multiline="true" + rows="3" + aria-describedby="user-provide-bridge-description" + aria-errormessage="user-provide-bridge-error-message" + /> + <html:div id="user-provide-bridge-message-area"> + <html:span + id="user-provide-bridge-error-message" + role="alert" + ></html:span> + <img + id="user-provide-bridge-loading-icon" + class="tor-loading-icon" + alt="" + /> + <html:span + id="user-provide-bridge-connecting" + role="alert" + data-l10n-id="user-provide-bridge-dialog-connecting" + ></html:span> + </html:div> + </html:div> + <html:div id="user-provide-bridge-result-page"> + <description id="user-provide-result-description" /> + <!-- NOTE: Unlike #tor-bridge-grid-display, this element is not + - interactive, and not a tab-stop. So we use the "table" role rather + - than "grid". + - NOTE: Using a <html:table> would not allow us the same structural + - freedom, so we use a generic div and add the semantics manually. --> + <html:div + id="user-provide-bridge-grid-display" + class="tor-bridges-grid" + role="table" + tabindex="0" + aria-labelledby="user-provide-result-description" + ></html:div> + <html:template id="user-provide-bridge-row-template"> + <html:div class="tor-bridges-grid-row" role="row"> + <html:span + class="tor-bridges-type-cell tor-bridges-grid-cell" + role="cell" + ></html:span> + <html:span class="tor-bridges-emojis-block" role="none"></html:span> + <html:span class="tor-bridges-grid-end-block" role="none"> + <html:span + class="tor-bridges-address-cell tor-bridges-grid-cell" + role="cell" + > + <html:span class="tor-bridges-address-cell-text"></html:span> + </html:span> + </html:span> + </html:div> + </html:template> + </html:div> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/requestBridgeDialog.js b/browser/components/torpreferences/content/requestBridgeDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..b884d0755b3b6ef64605f9a71cb329a34f26c565 --- /dev/null +++ b/browser/components/torpreferences/content/requestBridgeDialog.js @@ -0,0 +1,212 @@ +"use strict"; + +const { BridgeDB } = ChromeUtils.importESModule( + "resource://gre/modules/BridgeDB.sys.mjs" +); + +const { TorConnect, TorConnectStage, TorConnectTopics } = + ChromeUtils.importESModule("resource://gre/modules/TorConnect.sys.mjs"); + +const log = console.createInstance({ + maxLogLevel: "Warn", + prefix: "requestBridgeDialog", +}); + +const gRequestBridgeDialog = { + selectors: { + dialogHeader: "#torPreferences-requestBridge-header", + captchaImage: "image#torPreferences-requestBridge-captchaImage", + captchaEntryTextbox: "input#torPreferences-requestBridge-captchaTextbox", + refreshCaptchaButton: + "button#torPreferences-requestBridge-refreshCaptchaButton", + incorrectCaptchaHbox: + "hbox#torPreferences-requestBridge-incorrectCaptchaHbox", + }, + + init() { + this._result = window.arguments[0]; + + const selectors = this.selectors; + + this._dialog = document.getElementById( + "torPreferences-requestBridge-dialog" + ); + + // Add styling for tor-button to the dialog shadow root. + const styleLink = document.createElement("link"); + styleLink.rel = "stylesheet"; + styleLink.href = + "chrome://browser/content/torpreferences/torPreferences.css"; + this._dialog.shadowRoot.append(styleLink); + + // user may have opened a Request Bridge dialog in another tab, so update the + // CAPTCHA image or close out the dialog if we have a bridge list + this._dialog.addEventListener("focusin", () => { + const uri = BridgeDB.currentCaptchaImage; + const bridges = BridgeDB.currentBridges; + + // new captcha image + if (uri) { + this._setcaptchaImage(uri); + } else if (bridges) { + this._dialog.cancelDialog(); + } + }); + + this._submitButton = this._dialog.getButton("accept"); + this._submitButton.disabled = true; + this._dialog.addEventListener("dialogaccept", e => { + e.preventDefault(); + this.onSubmitCaptcha(); + }); + + this._dialogHeader = this._dialog.querySelector(selectors.dialogHeader); + + this._captchaImage = this._dialog.querySelector(selectors.captchaImage); + + // request captcha from bridge db + BridgeDB.requestNewCaptchaImage().then(uri => { + this._setcaptchaImage(uri); + }); + + this._captchaEntryTextbox = this._dialog.querySelector( + selectors.captchaEntryTextbox + ); + this._captchaEntryTextbox.disabled = true; + // disable submit if entry textbox is empty + this._captchaEntryTextbox.oninput = () => { + this._submitButton.disabled = this._captchaEntryTextbox.value == ""; + }; + + this._captchaRefreshButton = this._dialog.querySelector( + selectors.refreshCaptchaButton + ); + this._captchaRefreshButton.disabled = true; + this._captchaRefreshButton.addEventListener("command", () => { + this.onRefreshCaptcha(); + }); + + this._incorrectCaptchaHbox = this._dialog.querySelector( + selectors.incorrectCaptchaHbox + ); + + Services.obs.addObserver(this, TorConnectTopics.StageChange); + this.onAcceptStateChange(); + }, + + uninit() { + BridgeDB.close(); + // Unregister our observer topics. + Services.obs.removeObserver(this, TorConnectTopics.StageChange); + }, + + onAcceptStateChange() { + const connect = TorConnect.stageName !== TorConnectStage.Bootstrapped; + this._result.connect = connect; + this._submitButton.setAttribute( + "data-l10n-id", + connect ? "bridge-dialog-button-connect" : "bridge-dialog-button-submit" + ); + this._submitButton.classList.toggle("tor-button", connect); + }, + + observe(subject, topic) { + switch (topic) { + case TorConnectTopics.StageChange: + this.onAcceptStateChange(); + break; + } + }, + + _setcaptchaImage(uri) { + if (!uri) { + return; + } + if (uri != this._captchaImage.src) { + this._captchaImage.src = uri; + this._dialogHeader.setAttribute( + "data-l10n-id", + "request-bridge-dialog-top-solve" + ); + this._setUIDisabled(false); + this._captchaEntryTextbox.focus(); + this._captchaEntryTextbox.select(); + } + }, + + _setUIDisabled(disabled) { + this._submitButton.disabled = this._captchaGuessIsEmpty() || disabled; + this._captchaEntryTextbox.disabled = disabled; + this._captchaRefreshButton.disabled = disabled; + }, + + _captchaGuessIsEmpty() { + return this._captchaEntryTextbox.value == ""; + }, + + /* + Event Handlers + */ + onSubmitCaptcha() { + let captchaText = this._captchaEntryTextbox.value.trim(); + // noop if the field is empty + if (captchaText == "") { + return; + } + + // freeze ui while we make request + this._setUIDisabled(true); + this._incorrectCaptchaHbox.style.visibility = "hidden"; + + BridgeDB.submitCaptchaGuess(captchaText) + .then(aBridges => { + if (aBridges && aBridges.length) { + this._result.accepted = true; + this._result.bridges = aBridges; + this._submitButton.disabled = false; + // This was successful, but use cancelDialog() to close, since + // we intercept the `dialogaccept` event. + this._dialog.cancelDialog(); + } else { + this._setUIDisabled(false); + this._incorrectCaptchaHbox.style.visibility = "visible"; + } + }) + .catch(aError => { + // TODO: handle other errors properly here when we do the bridge settings re-design + this._setUIDisabled(false); + this._incorrectCaptchaHbox.style.visibility = "visible"; + log.error(aError); + }); + }, + + onRefreshCaptcha() { + this._setUIDisabled(true); + this._captchaImage.src = ""; + this._dialogHeader.setAttribute( + "data-l10n-id", + "request-bridge-dialog-top-wait" + ); + this._captchaEntryTextbox.value = ""; + this._incorrectCaptchaHbox.style.visibility = "hidden"; + + BridgeDB.requestNewCaptchaImage().then(uri => { + this._setcaptchaImage(uri); + }); + }, +}; + +window.addEventListener( + "DOMContentLoaded", + () => { + gRequestBridgeDialog.init(); + window.addEventListener( + "unload", + () => { + gRequestBridgeDialog.uninit(); + }, + { once: true } + ); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/requestBridgeDialog.xhtml b/browser/components/torpreferences/content/requestBridgeDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..31ef37b8bdf71ba38186edb517f18414ef249139 --- /dev/null +++ b/browser/components/torpreferences/content/requestBridgeDialog.xhtml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="request-bridge-dialog-title" +> + <dialog id="torPreferences-requestBridge-dialog" buttons="accept,cancel"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/requestBridgeDialog.js" /> + + <description + id="torPreferences-requestBridge-header" + data-l10n-id="request-bridge-dialog-top-solve" + ></description> + <!-- init to transparent 400x125 png --> + <image id="torPreferences-requestBridge-captchaImage" flex="1" /> + <hbox id="torPreferences-requestBridge-inputHbox"> + <html:input + id="torPreferences-requestBridge-captchaTextbox" + type="text" + data-l10n-id="request-bridge-dialog-captcha-input" + /> + <button + id="torPreferences-requestBridge-refreshCaptchaButton" + image="chrome://global/skin/icons/reload.svg" + /> + </hbox> + <hbox id="torPreferences-requestBridge-incorrectCaptchaHbox" align="center"> + <image id="torPreferences-requestBridge-errorIcon" /> + <label data-l10n-id="request-bridge-dialog-captcha-failed" flex="1" /> + </hbox> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/telegram-logo.svg b/browser/components/torpreferences/content/telegram-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..6977ba62544ae5b77e72924ac48a92dcd3bec9dd --- /dev/null +++ b/browser/components/torpreferences/content/telegram-logo.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" clip-rule="evenodd" d="M13.5527 3.74072C13.6057 3.44502 13.3069 3.21007 13.0321 3.33143L2.46222 7.99865L5.04818 8.60316L10.1001 5.29184C10.8373 4.80861 11.6593 5.7727 11.0656 6.42426L7.88895 9.91029L11.9093 12.8968L13.5527 3.74072ZM12.5272 2.18794C13.7181 1.66208 15.013 2.68016 14.783 3.96155L13.104 13.3162C12.9564 14.1382 11.9962 14.5186 11.3258 14.0205L7.03263 10.8313C6.49819 10.4343 6.42353 9.66259 6.87195 9.17049L7.47872 8.50462L5.68862 9.67797C5.4311 9.84676 5.11564 9.90263 4.81582 9.83254L1.81371 9.13075C0.762034 8.8849 0.627375 7.4424 1.61537 7.00614L12.5272 2.18794Z"/> +</svg> diff --git a/browser/components/torpreferences/content/torLogDialog.js b/browser/components/torpreferences/content/torLogDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..ba2da24d9697ee0ec15f7b2b0be41816ccdd43d2 --- /dev/null +++ b/browser/components/torpreferences/content/torLogDialog.js @@ -0,0 +1,59 @@ +"use strict"; + +const { setTimeout, clearTimeout } = ChromeUtils.importESModule( + "resource://gre/modules/Timer.sys.mjs" +); + +const { TorProviderBuilder } = ChromeUtils.importESModule( + "resource://gre/modules/TorProviderBuilder.sys.mjs" +); + +window.addEventListener( + "DOMContentLoaded", + () => { + const dialog = document.getElementById("torPreferences-torLog-dialog"); + const copyLogButton = dialog.getButton("extra1"); + copyLogButton.setAttribute("data-l10n-id", "tor-log-dialog-copy-button"); + + const logText = document.getElementById( + "torPreferences-torDialog-textarea" + ); + + let restoreButtonTimeout = null; + copyLogButton.addEventListener("command", () => { + // Copy tor log messages to the system clipboard. + let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( + Ci.nsIClipboardHelper + ); + clipboard.copyString(logText.value); + + copyLogButton.setAttribute( + "data-l10n-id", + "tor-log-dialog-copy-button-copied" + ); + copyLogButton.classList.add("primary"); + + const RESTORE_TIME = 1200; + if (restoreButtonTimeout !== null) { + clearTimeout(restoreButtonTimeout); + } + restoreButtonTimeout = setTimeout(() => { + copyLogButton.setAttribute( + "data-l10n-id", + "tor-log-dialog-copy-button" + ); + copyLogButton.classList.remove("primary"); + restoreButtonTimeout = null; + }, RESTORE_TIME); + }); + + // A waiting state should not be needed at this point. + // Also, we probably cannot even arrive here if the provider failed to + // initialize, otherwise we could use a try/catch, and write the exception + // text in the logs, instead. + TorProviderBuilder.build().then( + provider => (logText.value = provider.getLog()) + ); + }, + { once: true } +); diff --git a/browser/components/torpreferences/content/torLogDialog.xhtml b/browser/components/torpreferences/content/torLogDialog.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..33acbe1f7f6a1cd109eaf3574cf57bab53cbdfab --- /dev/null +++ b/browser/components/torpreferences/content/torLogDialog.xhtml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<window + type="child" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + data-l10n-id="tor-log-dialog-title" +> + <dialog id="torPreferences-torLog-dialog" buttons="accept,extra1"> + <linkset> + <html:link rel="stylesheet" href="chrome://global/skin/global.css" /> + <html:link + rel="stylesheet" + href="chrome://browser/skin/preferences/preferences.css" + /> + <html:link + rel="stylesheet" + href="chrome://browser/content/torpreferences/torPreferences.css" + /> + + <html:link rel="localization" href="toolkit/global/tor-browser.ftl" /> + </linkset> + + <script src="chrome://browser/content/torpreferences/torLogDialog.js" /> + + <html:textarea + id="torPreferences-torDialog-textarea" + multiline="true" + readonly="true" + /> + </dialog> +</window> diff --git a/browser/components/torpreferences/content/torPreferences.css b/browser/components/torpreferences/content/torPreferences.css new file mode 100644 index 0000000000000000000000000000000000000000..908501ac9631537f4b955abca6288cb30615c49b --- /dev/null +++ b/browser/components/torpreferences/content/torPreferences.css @@ -0,0 +1,1081 @@ +@import url("chrome://global/skin/tor-colors.css"); + + +#category-connection > .category-icon { + list-style-image: url("chrome://global/content/torconnect/tor-connect.svg"); +} + +/* Make a button appear disabled, whilst still allowing it to keep keyboard + * focus. + * TODO: Replace with moz-button when it handles this for us. See + * tor-browser#43275. */ +button.spoof-button-disabled { + /* Borrow the :disabled rule from common-shared.css */ + opacity: 0.4; + /* Also ensure it does not get hover or active styling. */ + pointer-events: none; +} + +.tor-loading-icon { + width: 16px; + height: 16px; + content: image-set( + url("chrome://global/skin/icons/tor-light-loading.png"), + url("chrome://global/skin/icons/tor-light-loading@2x.png") 2x + ); +} + +@media (prefers-color-scheme: dark) { + .tor-loading-icon { + content: image-set( + url("chrome://global/skin/icons/tor-dark-loading.png"), + url("chrome://global/skin/icons/tor-dark-loading@2x.png") 2x + ); + } +} + +/* Status */ + +#network-status-internet-area { + margin-block: 16px; +} + +#network-status-tor-area { + margin-block: 0 32px; +} + +.network-status-area { + display: flex; + align-items: center; + white-space: nowrap; +} + +.network-status-area > * { + flex: 0 0 auto; +} + +.network-status-icon { + width: 18px; + height: 18px; + margin-inline-end: 8px; + -moz-context-properties: fill, stroke; + fill: currentColor; + stroke: currentColor; +} + +#network-status-internet-area .network-status-icon { + content: url("chrome://browser/content/torpreferences/network.svg"); +} + +#network-status-internet-area.status-offline .network-status-icon { + content: url("chrome://browser/content/torpreferences/network-broken.svg"); +} + +#network-status-tor-area .network-status-icon { + content: url("chrome://global/content/torconnect/tor-connect.svg"); +} + +#network-status-tor-area:not(.status-connected) .network-status-icon { + content: url("chrome://global/content/torconnect/tor-connect-broken.svg"); +} + +#network-status-tor-area.status-blocked .network-status-icon { + /* Same as .tor-connect-status-potentially-blocked. */ + stroke: #c50042; +} + +@media (prefers-color-scheme: dark) { + #network-status-tor-area.status-blocked .network-status-icon { + stroke: #ff9aa2; + } +} + +.network-status-live-area { + display: contents; +} + +.network-status-label { + font-weight: bold; + margin-inline-end: 0.75em; +} + +.network-status-loading-icon { + margin-inline-end: 0.5em; +} + +#network-status-internet-area:not(.status-loading) .network-status-loading-icon { + display: none; +} + +.network-status-result:not(:empty) { + margin-inline-end: 0.75em; +} + +#network-status-tor-area.status-connected #network-status-tor-connect-button { + /* Hide button when already connected. */ + display: none; +} + +/* Bridge settings */ + +.tor-medium-heading { + /* Same font size as mozilla preferences h2. */ + font-size: var(--font-size-large); + font-weight: var(--font-weight-bold); + margin: 0; +} + +.tor-small-heading { + font-size: inherit; + font-weight: var(--font-weight-bold); + margin: 0; +} + +/* Hide the tor-search-heading elements when the group's search header is + * hidden. These only appear in search results. + * See tor-browser#43320. + * NOTE: `.search-header[hidden] ~ :is(* .tor-search-heading)` will not match + * (possibly because the `~` selector is unsure how to integrate with the + * non-compound `* .tor-search-heading` selector). So we need to duplicate the + * `.search-header[hidden]` rule. */ +#torPreferences-bridges-group :is( + .search-header[hidden] ~ * .tor-search-heading, + .search-header[hidden] ~ .tor-search-heading +) { + display: none; +} + +/* Hide the tor-non-search-heading elements when the group's search header is + * not hidden. These only appear outside of search results. + * See tor-browser#43320. */ +#torPreferences-bridges-group :is( + .search-header:not([hidden]) ~ * .tor-non-search-heading, + .search-header:not([hidden]) ~ .tor-non-search-heading +) { + display: none; +} + +.tor-focusable-heading { + /* Do not occupy more horizontal space than necessary. */ + width: fit-content; +} + +.tor-focusable-heading:focus-visible { + outline-offset: var(--in-content-focus-outline-offset); +} + +.bridge-status-badge { + display: flex; + min-width: max-content; + align-items: center; + gap: 0.5em; + font-size: 0.85em; +} + +.bridge-status-badge:not( + .bridge-status-connected, + .bridge-status-none, + .bridge-status-current-built-in +) { + display: none; +} + +.bridge-status-badge.bridge-status-connected { + color: var(--tor-accent-color); +} + +.bridge-status-badge.bridge-status-current-built-in { + color: var(--in-content-accent-color); +} + +.bridge-status-badge > * { + flex: 0 0 auto; +} + +.bridge-status-icon { + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center center; + -moz-context-properties: fill; + fill: currentColor; +} + +.bridge-status-badge:is( + .bridge-status-connected, + .bridge-status-current-built-in +) .bridge-status-icon { + background-image: url("chrome://global/skin/icons/check.svg"); +} + +.bridge-status-badge.bridge-status-none .bridge-status-icon { + /* Hide the icon. */ + display: none; +} + +#tor-bridges-enabled-toggle { + margin-block: 16px; + width: max-content; +} + +#tor-bridges-update-area { + /* Still accessible to screen reader, but not visual. */ + position: absolute; + clip-path: inset(50%); +} + +#torPreferences-bridges-group:not(.bridges-initialized) { + /* Hide bridge settings whilst not initialized. */ + display: none; +} + +#tor-bridges-none, +#tor-bridges-current { + margin-inline: 0; + margin-block: 32px; +} + +#tor-bridges-none:not([hidden]) { + display: grid; + justify-items: center; + text-align: center; + padding-block: 64px; + padding-inline: 32px; + gap: 16px; + border-radius: 4px; + color: var(--text-color-deemphasized); + border: 2px dashed color-mix(in srgb, currentColor 20%, transparent); +} + +#tor-bridges-none-icon { + width: 20px; + height: 20px; + content: url("chrome://browser/content/torpreferences/bridge.svg"); + -moz-context-properties: fill; + fill: currentColor; +} + +#tor-bridges-current { + padding: 16px; + border-radius: 4px; + background: var(--in-content-box-info-background); +} + +#tor-bridges-current-header-bar { + display: grid; + min-width: max-content; + grid-template: "heading source button" min-content / max-content 1fr max-content; + align-items: center; + border-block-end: 1px solid var(--in-content-border-color); + padding-block-end: 16px; + margin-block-end: 16px; + white-space: nowrap; +} + +.tor-bridges-current-heading { + grid-area: heading; +} + +.tor-bridges-source-label { + margin-inline-start: 2em; + margin-inline-end: 8px; + grid-area: source; + justify-self: end; +} + +#tor-bridges-all-options-button { + grid-area: button; +} + +#tor-bridges-lox-label:not([hidden]) { + display: flex; + align-items: center; + gap: 6px; +} + +#tor-bridges-lox-label > * { + flex: 0 0 auto; +} + +#tor-bridges-lox-label-icon { + content: url("chrome://browser/content/torpreferences/lox-bridge-pass.svg"); + width: 16px; + height: 16px; + -moz-context-properties: fill; + fill: var(--in-content-icon-color); +} + +.tor-bridges-options-button { + padding: 3px; + margin: 0; + min-height: auto; + min-width: auto; + box-sizing: content-box; + width: 16px; + height: 16px; + background-image: url("chrome://global/skin/icons/more.svg"); + background-repeat: no-repeat; + background-position: center center; + background-origin: content-box; + background-size: contain; + -moz-context-properties: fill; + fill: currentColor; +} + +#tor-bridges-built-in-display:not([hidden]) { + display: grid; + grid-template: + "type status" min-content + "description description" auto + / max-content 1fr; + gap: 12px 1.5em; + margin-block-end: 16px; +} + +#tor-bridges-built-in-type-name { + font-weight: 700; + grid-area: type; +} + +#tor-bridges-built-in-connected { + grid-area: status; + justify-self: end; +} + +#tor-bridges-built-in-description { + grid-area: description; +} + +.tor-bridges-grid:not([hidden]) { + display: grid; + grid-template-columns: max-content repeat(4, max-content) 1fr; + --tor-bridges-grid-column-gap: 8px; + --tor-bridges-grid-column-short-gap: 4px; + /* For #tor-bridges-grid-display we want each grid item to have the same + * height so that their focus outlines match. */ + align-items: stretch; +} + +.tor-bridges-grid-row { + /* We want each row to act as a row of three items in the + * .tor-bridges-grid grid layout. + * We also want a 16px spacing between rows, and 8px spacing between columns, + * which are outside the .tor-bridges-grid-cell's border area. + * + * For #tor-bridges-grid-display this should ensure that clicking these gaps + * will not focus any item, and their focus outlines do not overlap. + * Moreover, we also want each row to show its .tor-bridges-options-cell when + * the .tor-bridges-grid-row has :hover. + * + * We could use "display: contents" on the row and set a "gap: 16px 8px" on + * the parent so that its items fall into the parent layout. However, the gap + * between the items would mean there are places where no row has :hover. So + * if the user glided across the grid, the options button would visibly + * disappear any time the pointer entered a gap, causing the display to feel + * "jumpy". + * + * Instead, we use a "subgrid" layout for each .tor-bridges-grid-row, and + * using padding, rather than a gap, for the vertical spacing. Therefore, + * every part of the grid is covered by a row, so moving the pointer over the + * grid will always have one row with :hover, so one of the options cell will + * always be visible. + */ + display: grid; + grid-column: 1 / -1; + grid-template-columns: subgrid; + /* Add 16px gap between rows, plus 8px at the start and end of the grid. */ + padding-block: 8px; +} + +#tor-bridges-grid-display .tor-bridges-grid-cell:focus-visible { + /* #tor-bridges-grid-display has focus management for its cells. */ + outline: var(--in-content-focus-outline); + outline-offset: var(--in-content-focus-outline-offset); +} + +.tor-bridges-grid-cell { + /* The cell is stretched to the height of the row, so that each focus outline + * shares the same height, but we want to center-align the content within, + * which is either a single Element or a TextNode. */ + display: grid; + align-content: center; +} + +.tor-bridges-type-cell { + margin-inline-end: var(--tor-bridges-grid-column-gap); +} + +.tor-bridges-emojis-block { + /* Emoji block occupies four columns, but with a smaller gap. */ + display: contents; +} + +.tor-bridges-emoji-cell:not(:last-child) { + margin-inline-end: var(--tor-bridges-grid-column-short-gap); +} + +.tor-bridges-emoji-icon { + display: block; + box-sizing: content-box; + width: 16px; + height: 16px; + /* color-light-gray-10, color-dark-gray-60 */ + background: light-dark(#f9f9fb, #2b2a33); + border-radius: 4px; + padding: 8px; +} + +.tor-bridges-grid-end-block { + /* The last three cells all share a single grid item slot in the + * #tor-bridges-grid-display layout. + * This is because we do not want to align its cells between rows. */ + min-width: max-content; + display: flex; + /* Choose "stretch" instead of "center" so that focus outline is a consistent + * height between cells. */ + align-items: stretch; + margin-inline-start: var(--tor-bridges-grid-column-gap); + gap: var(--tor-bridges-grid-column-gap); +} + +.tor-bridges-address-cell { + /* base size */ + width: 10em; + flex: 1 0 auto; +} + +.tor-bridges-address-cell-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: var(--text-color-deemphasized); +} + +.tor-bridges-status-cell, +.tor-bridges-options-cell { + flex: 0 0 auto; +} + +/* Hide the options button if the row does not have hover or focus. */ +.tor-bridges-grid-row:not( + :hover, + :focus-within +) .tor-bridges-options-cell, +/* Hide the status cell when it shows "No status" if the cell does not have + * focus. */ +.tor-bridges-grid-row.hide-status .tor-bridges-status-cell:not(:focus) { + /* Still accessible to screen reader, but not visual and does not contribute + * to the parent flex layout. */ + /* NOTE: We assume that the height of these cell's content is equal to or less + * than the other cells, so there won't be a jump in row height when they + * become visual again and contribute to the layout. */ + position: absolute; + clip-path: inset(50%); +} + +.tor-bridges-details-box { + margin-block-start: 24px; + border-radius: 4px; + border: 1px solid var(--in-content-border-color); + padding: 16px; +} + +#tor-bridges-share:not([hidden]) { + display: grid; + grid-template: + "heading heading heading" min-content + /* If the description spans one line, it will be center-aligned with the + * buttons, otherwise it will start to expand upwards. */ + "description . ." 1fr + "description copy qr" min-content + / 1fr max-content max-content; + gap: 0 8px; + align-items: center; +} + +.tor-bridges-share-heading { + grid-area: heading; + margin-block-end: 4px; +} + +#tor-bridges-share-description { + grid-area: description; +} + +#tor-bridges-copy-addresses-button { + grid-area: copy; + margin: 0; + /* Match the QR height if it is higher than ours. */ + min-height: auto; + align-self: stretch; +} + +#tor-bridges-qr-addresses-button { + grid-area: qr; + padding: 5px; + margin: 0; + min-height: auto; + min-width: auto; + box-sizing: content-box; + width: 24px; + height: 24px; + background-image: url("chrome://browser/content/torpreferences/bridge-qr.svg"); + background-repeat: no-repeat; + background-position: center center; + background-origin: content-box; + background-size: contain; + -moz-context-properties: fill; + fill: currentColor; +} + +#tor-bridges-lox-status { + margin-block-start: 8px; +} + +.tor-bridges-lox-box:not([hidden]) { + display: grid; + grid-template: + "image intro intro" min-content + ". list list" auto + ". invites button" min-content + / min-content 1fr max-content; + align-items: start; + gap: 8px; +} + +.tor-bridges-lox-image-outer { + grid-area: image; + /* The ring is 36px by 36px, but has 4px of padding for a Gaussian blur. */ + width: 44px; + height: 44px; + margin: -4px; + align-self: center; + justify-self: center; + /* fill is the progress, stroke is the empty ring. */ + -moz-context-properties: fill, stroke; + fill: var(--in-content-success-icon-color); + stroke: var(--in-content-border-color); + content: url("chrome://browser/content/torpreferences/lox-progress-ring.svg"); +} + +#tor-bridges-lox-unlock-alert.lox-unlock-upgrade .tor-bridges-lox-image-outer { + content: url("chrome://browser/content/torpreferences/lox-complete-ring.svg"); +} + +.tor-bridges-lox-image-inner { + grid-area: image; + /* Extra 4px space for gaussian blur. */ + width: 16px; + height: 16px; + align-self: center; + justify-self: center; + -moz-context-properties: fill; + fill: var(--in-content-icon-color); +} + +#tor-bridges-lox-details .tor-bridges-lox-image-inner { + content: url("chrome://browser/content/torpreferences/lox-bridge-pass.svg"); +} + +#tor-bridges-lox-unlock-alert .tor-bridges-lox-image-inner { + content: url("chrome://browser/content/torpreferences/bridge.svg"); +} + +#tor-bridges-lox-unlock-alert.lox-unlock-upgrade .tor-bridges-lox-image-inner { + content: url("chrome://browser/content/torpreferences/lox-success.svg"); +} + +.tor-bridges-lox-intro { + grid-area: intro; + align-self: center; + justify-self: start; +} + +.tor-bridges-lox-list { + grid-area: list; + margin: 0; + padding: 0; + display: grid; + /* Align the icons, as if list markers. */ + grid-template-columns: max-content 1fr; + align-items: start; + gap: 8px 0; +} + +.tor-bridges-lox-list-item:not([hidden]) { + display: contents; +} + +.tor-bridges-lox-list-item:not([hidden])::before { + /* We use ::before rather than list-style-image to have more control. */ + box-sizing: content-box; + width: 18px; + height: 18px; + margin-inline: 4px 6px; + /* We want the icons to be center-aligned relative to the *first* line. */ + margin-block-start: calc((1lh - 18px) / 2); + /* We use display: grid rather than display: block. Otherwise the content will + * be offset vertically by the line-height. */ + display: grid; + /* fill is the icon color, stroke is the border color. */ + -moz-context-properties: fill, stroke; + fill: var(--in-content-icon-color); +} + +.tor-bridges-lox-list-item-bridge::before { + content: url("chrome://browser/content/torpreferences/lox-bridge-icon.svg"); +} + +.tor-bridges-lox-list-item-invite::before { + content: url("chrome://browser/content/torpreferences/lox-invite-icon.svg"); +} + +#tor-bridges-lox-details .tor-bridges-lox-list-item::before { + stroke: var(--in-content-border-color); +} + +#tor-bridges-lox-unlock-alert .tor-bridges-lox-list-item::before { + stroke: var(--in-content-success-icon-color); +} + +#tor-bridges-lox-remaining-invites { + grid-area: invites; + justify-self: end; + align-self: center; +} + +.tor-bridges-lox-button { + grid-area: button; + margin: 0; + align-self: center; +} + +.tor-bridges-provider-heading { + margin-block: 48px 8px; +} + +#tor-bridges-provider-area { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + align-items: start; + margin-block-start: 24px; +} + +#tor-bridges-provider-list { + display: grid; + grid-template-columns: max-content max-content; + /* 24px gap between items. */ + gap: 24px 12px; + margin-block: 16px; + padding: 0; +} + +.tor-bridges-provider-item { + grid-column: 1 / -1; + display: grid; + grid-template-columns: subgrid; + align-items: center; + justify-items: start; + /* 8px gap between the name and instruction. */ + gap: 8px 12px; +} + +.tor-bridges-provider-icon { + width: 16px; + height: 16px; + -moz-context-properties: fill; + fill: var(--in-content-icon-color); +} + +#tor-bridges-provider-icon-telegram { + content: url("chrome://browser/content/torpreferences/telegram-logo.svg"); +} + +#tor-bridges-provider-icon-web { + content: url("chrome://browser/content/torpreferences/network.svg"); +} + +#tor-bridges-provider-icon-email { + content: url("chrome://browser/content/torpreferences/mail.svg"); +} + +.tor-bridges-provider-name { + font-weight: 600; + font-size: 0.85em; +} + +.tor-bridges-provider-instruction { + grid-column: 2 / 3; +} + +#tor-bridges-request-box { + /* Take up the full height in the container. */ + align-self: stretch; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + justify-content: center; + padding: 16px; + background: var(--in-content-box-info-background); + border-radius: 4px; +} + +#tor-bridges-request-box > * { + flex: 0 0 auto; +} + +#tor-bridges-request-description { + margin-block: 12px 16px; +} + +#tor-bridges-open-request-dialog-button { + margin: 0; +} + +#torPreferences-bridges-location { + width: 280px; +} + +#torPreferences-bridges-location menuitem[disabled="true"] { + color: var(--in-content-button-text-color, inherit); + font-weight: 700; +} + +/* Request bridges */ + +image#torPreferences-requestBridge-captchaImage { + margin: 16px 0 8px 0; + min-height: 140px; +} + +button#torPreferences-requestBridge-refreshCaptchaButton { + min-width: initial; +} + +#torPreferences-requestBridge-refreshCaptchaButton image { + -moz-context-properties: fill; + fill: currentColor; +} + +#torPreferences-requestBridge-captchaTextbox { + flex: 1 0 auto; +} + +dialog#torPreferences-requestBridge-dialog > hbox { + margin-bottom: 1em; +} + +/* + Various elements that really should be lining up don't because they have inconsistent margins +*/ +.torMarginFix { + margin-left : 4px; + margin-right : 4px; +} + +/* Show bridge QR dialog */ + +#bridgeQr { + flex: 0 0 auto; + align-self: center; + /* Some readers don't recognize QRs with inverted colors, so let's make + the ones are darker than zeroes. See + https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41049 */ + --qr-one: black; + --qr-zero: white; + background: var(--qr-zero); + /* Padding is needed in case the dark theme is used so the bits don't blend + with whatever the default background color is. */ + padding: 10px; + margin-block: 4px 8px; + border-radius: 4px; + display: grid; + align-items: center; + justify-items: center; + grid-template: "qr" max-content / max-content; +} + +#bridgeQr-target { + width: 300px; + height: 300px; + background: var(--qr-zero); + color: var(--qr-one); + grid-area: qr; +} + +#bridgeQr-icon { + /* Share the same grid area as #bridgeQr-target. */ + grid-area: qr; + content: url("chrome://browser/content/torpreferences/bridge.svg"); + padding: 10px; + border-radius: 8px; + box-sizing: content-box; + width: 52px; + height: 52px; + background: var(--qr-zero); + -moz-context-properties: fill; + fill: var(--qr-one); +} + +/* Lox invite dialog */ + +#lox-invite-dialog-generate-area { + flex: 0 0 auto; + display: grid; + grid-template: + ". remaining button" min-content + "message message message" auto + / 1fr max-content max-content; + gap: 8px; + margin-block: 16px 8px; + align-items: center; +} + +#lox-invite-dialog-remaining { + grid-area: remaining; +} + +#lox-invite-dialog-generate-button { + grid-area: button; +} + +#lox-invite-dialog-message-area { + grid-area: message; + justify-self: end; + display: flex; + align-items: center; +} + +#lox-invite-dialog-message-area::after { + /* Zero width space, to ensure we are always one line high. */ + content: "\200B"; +} + +#lox-invite-dialog-error-message { + color: var(--text-color-error); +} + +#lox-invite-dialog-generate-area:not(.show-error) #lox-invite-dialog-error-message { + display: none; +} + +#lox-invite-dialog-connecting { + color: var(--text-color-deemphasized); + /* Gap with #user-provide-bridge-loading-icon. */ + margin-inline-start: 0.5em; +} + +#lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-connecting { + display: none; +} + +#lox-invite-dialog-loading-icon { + flex: 0 0 auto; +} + +#lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-loading-icon { + /* Use width:0 to effectively hide, but still occupy vertical space. */ + width: 0; +} + +#lox-invite-dialog-list-label { + font-weight: 700; +} + +#lox-invite-dialog-list { + flex: 1 1 auto; + /* basis height */ + height: 10em; + margin-block: 8px; +} + +.lox-invite-dialog-list-item { + white-space: nowrap; + overflow-x: hidden; + /* FIXME: ellipsis does not show. */ + text-overflow: ellipsis; + padding-block: 6px; + padding-inline: 8px; +} + +/* Builtin bridge dialog */ +#torPreferences-builtinBridge-header { + margin: 8px 0 10px 0; +} + +#torPreferences-builtinBridge-description { + margin-bottom: 18px; +} + +#torPreferences-builtinBridge-typeSelection { + margin-bottom: 16px; +} + +#torPreferences-builtinBridge-typeSelection radio label { + font-weight: 700; +} + +/* Request bridge dialog */ +/* + This hbox is hidden by css here by default so that the + xul dialog allocates enough screen space for the error message + element, otherwise it gets cut off since dialog's overflow is hidden +*/ +hbox#torPreferences-requestBridge-incorrectCaptchaHbox { + visibility: hidden; +} + +image#torPreferences-requestBridge-errorIcon { + list-style-image: url("chrome://global/skin/icons/warning.svg"); + -moz-context-properties: fill; + fill: var(--in-content-warning-icon-color); +} + +groupbox#torPreferences-bridges-group textarea { + white-space: pre; + overflow: auto; +} + +/* Provide bridge dialog */ + +#user-provide-bridge-dialog:not(.show-entry-page) #user-provide-bridge-entry-page { + display: none; +} + +#user-provide-bridge-dialog:not(.show-result-page) #user-provide-bridge-result-page { + display: none; +} + +#user-provide-bridge-entry-page { + flex: 1 0 auto; + display: flex; + flex-direction: column; +} + +#user-provide-bridge-description { + flex: 0 0 auto; +} + +#user-provide-bridge-textarea-label { + margin-block: 16px 6px; + flex: 0 0 auto; + align-self: start; +} + +#user-provide-bridge-textarea { + flex: 1 0 auto; + align-self: stretch; + /* Only expect ASCII input, so can set a line-height. */ + line-height: 1.3; + margin: 0; +} + +#user-provide-bridge-message-area { + flex: 0 0 auto; + margin-block: 8px 12px; + align-self: end; + display: flex; + align-items: center; +} + +#user-provide-bridge-message-area::after { + /* Zero width space, to ensure we are always one line high. */ + content: "\200B"; +} + +#user-provide-bridge-textarea.invalid-input { + border-color: var(--in-content-danger-button-background); + outline-color: var(--in-content-danger-button-background); +} + +#user-provide-bridge-error-message { + color: var(--text-color-error); +} + +#user-provide-bridge-dialog:not(.show-error) #user-provide-bridge-error-message { + display: none; +} + +#user-provide-bridge-connecting { + color: var(--text-color-deemphasized); + /* Gap with #user-provide-bridge-loading-icon. */ + margin-inline-start: 0.5em; +} + +#user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-connecting { + display: none; +} + +#user-provide-bridge-loading-icon { + flex: 0 0 auto; +} + +#user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-loading-icon { + /* Use width:0 to effectively hide, but still occupy vertical space. */ + width: 0; +} + +#user-provide-bridge-result-page { + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: column; +} + +#user-provide-result-description { + flex: 0 0 auto; +} + +#user-provide-bridge-grid-display { + flex: 0 1 auto; + overflow: auto; + margin-block: 8px; +} + +#user-provide-bridge-grid-display:focus-visible { + outline: var(--in-content-focus-outline); + outline-offset: var(--in-content-focus-outline-offset); +} + +/* Connection settings dialog */ +#torPreferences-connection-dialog label { + /* Do not wrap the labels. */ + white-space: nowrap; +} + +#torPreferences-connection-header { + margin: 4px 0 14px 0; +} + +#torPreferences-connection-grid { + display: grid; + grid-template-columns: auto 1fr; +} + +#torPreferences-localProxy-textboxAddress, +#torPreferences-localProxy-textboxUsername, +#torPreferences-localProxy-textboxPassword, +#torPreferences-connection-textboxAllowedPorts { + flex: 1 0 auto; +} + +#torPreferences-connection-firewall { + display: flex; +} + +#torPreferences-connection-hboxAllowedPorts { + flex: 1; +} + +/* Tor logs dialog */ +textarea#torPreferences-torDialog-textarea { + flex: 1 0 auto; + font-family: monospace; + font-size: 0.8em; + white-space: pre; + overflow: auto; + /* 10 lines */ + min-height: 20em; +} diff --git a/browser/components/torpreferences/jar.mn b/browser/components/torpreferences/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..ee7ce83563b31e379d1124206162a1e03ad13b16 --- /dev/null +++ b/browser/components/torpreferences/jar.mn @@ -0,0 +1,36 @@ +browser.jar: + content/browser/torpreferences/bridge.svg (content/bridge.svg) + content/browser/torpreferences/bridge-qr.svg (content/bridge-qr.svg) + content/browser/torpreferences/telegram-logo.svg (content/telegram-logo.svg) + content/browser/torpreferences/bridge-bot.svg (content/bridge-bot.svg) + content/browser/torpreferences/lox-invite-icon.svg (content/lox-invite-icon.svg) + content/browser/torpreferences/lox-bridge-icon.svg (content/lox-bridge-icon.svg) + content/browser/torpreferences/lox-bridge-pass.svg (content/lox-bridge-pass.svg) + content/browser/torpreferences/lox-success.svg (content/lox-success.svg) + content/browser/torpreferences/lox-complete-ring.svg (content/lox-complete-ring.svg) + content/browser/torpreferences/lox-progress-ring.svg (content/lox-progress-ring.svg) + content/browser/torpreferences/loxInviteDialog.xhtml (content/loxInviteDialog.xhtml) + content/browser/torpreferences/loxInviteDialog.js (content/loxInviteDialog.js) + content/browser/torpreferences/bridgeQrDialog.xhtml (content/bridgeQrDialog.xhtml) + content/browser/torpreferences/bridgeQrDialog.js (content/bridgeQrDialog.js) + content/browser/torpreferences/builtinBridgeDialog.xhtml (content/builtinBridgeDialog.xhtml) + content/browser/torpreferences/builtinBridgeDialog.js (content/builtinBridgeDialog.js) + content/browser/torpreferences/connectionSettingsDialog.xhtml (content/connectionSettingsDialog.xhtml) + content/browser/torpreferences/connectionSettingsDialog.js (content/connectionSettingsDialog.js) + content/browser/torpreferences/network.svg (content/network.svg) + content/browser/torpreferences/network-broken.svg (content/network-broken.svg) + content/browser/torpreferences/mail.svg (content/mail.svg) + content/browser/torpreferences/provideBridgeDialog.xhtml (content/provideBridgeDialog.xhtml) + content/browser/torpreferences/provideBridgeDialog.js (content/provideBridgeDialog.js) + content/browser/torpreferences/requestBridgeDialog.xhtml (content/requestBridgeDialog.xhtml) + content/browser/torpreferences/requestBridgeDialog.js (content/requestBridgeDialog.js) + content/browser/torpreferences/connectionCategory.inc.xhtml (content/connectionCategory.inc.xhtml) + content/browser/torpreferences/torLogDialog.js (content/torLogDialog.js) + content/browser/torpreferences/torLogDialog.xhtml (content/torLogDialog.xhtml) + content/browser/torpreferences/connectionPane.js (content/connectionPane.js) + content/browser/torpreferences/connectionPane.xhtml (content/connectionPane.xhtml) + content/browser/torpreferences/torPreferences.css (content/torPreferences.css) + content/browser/torpreferences/bridgemoji/BridgeEmoji.js (content/bridgemoji/BridgeEmoji.js) + content/browser/torpreferences/bridgemoji/bridge-emojis.json (content/bridgemoji/bridge-emojis.json) + content/browser/torpreferences/bridgemoji/annotations.json (content/bridgemoji/annotations.json) + content/browser/torpreferences/bridgemoji/svgs/ (content/bridgemoji/svgs/*.svg) diff --git a/browser/components/torpreferences/moz.build b/browser/components/torpreferences/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..2661ad7cb9f3df2b3953a6e1e999aee82d29be78 --- /dev/null +++ b/browser/components/torpreferences/moz.build @@ -0,0 +1 @@ +JAR_MANIFESTS += ["jar.mn"] diff --git a/browser/components/urlbar/UrlbarInput.sys.mjs b/browser/components/urlbar/UrlbarInput.sys.mjs index 75e2ca31549e8e2bb6e7d12ba826d1d929105984..36e0f76b4596141c74d67acb12e1f5a71ac75a98 100644 --- a/browser/components/urlbar/UrlbarInput.sys.mjs +++ b/browser/components/urlbar/UrlbarInput.sys.mjs @@ -22,6 +22,7 @@ ChromeUtils.defineESModuleGetters(lazy, { SearchModeSwitcher: "resource:///modules/SearchModeSwitcher.sys.mjs", SearchUIUtils: "resource:///modules/SearchUIUtils.sys.mjs", SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", UrlbarController: "resource:///modules/UrlbarController.sys.mjs", UrlbarEventBufferer: "resource:///modules/UrlbarEventBufferer.sys.mjs", UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs", @@ -291,6 +292,36 @@ export class UrlbarInput { ); } + // in certain scenarios we want user input uris to open in a new tab if they do so from the + // about:torconnect tab + #maybeUpdateOpenLocationForTorConnect( + openUILinkWhere, + currentURI, + destinationURI + ) { + try { + // only open in new tab if: + if ( + // user is navigating away from about:torconnect + currentURI === "about:torconnect" && + // we are trying to open in same tab + openUILinkWhere === "current" && + // only if user still has not bootstrapped + lazy.TorConnect.shouldShowTorConnect && + // and user is not just navigating to about:torconnect + destinationURI !== "about:torconnect" + ) { + return "tab"; + } + } catch (e) { + // swallow exception and fall through returning original so we don't accidentally break + // anything if an exception is thrown + this.logger.error(e?.message ? e.message : e); + } + + return openUILinkWhere; + } + /** * Applies styling to the text in the urlbar input, depending on the text. */ @@ -3197,6 +3228,11 @@ export class UrlbarInput { this.inputField.setSelectionRange(0, 0); } + openUILinkWhere = this.#maybeUpdateOpenLocationForTorConnect( + openUILinkWhere, + this.window.gBrowser.currentURI.asciiSpec, + url + ); if (openUILinkWhere != "current") { this.handleRevert(); } diff --git a/browser/components/urlbar/UrlbarProvidersManager.sys.mjs b/browser/components/urlbar/UrlbarProvidersManager.sys.mjs index 1f6330fb67b6099753003b026cdaef475672e0c1..0e7fd25ff47ecd857e493dd447a9eafa0a855e4a 100644 --- a/browser/components/urlbar/UrlbarProvidersManager.sys.mjs +++ b/browser/components/urlbar/UrlbarProvidersManager.sys.mjs @@ -48,8 +48,9 @@ var localProviderModules = { "resource:///modules/UrlbarProviderHistoryUrlHeuristic.sys.mjs", UrlbarProviderInputHistory: "resource:///modules/UrlbarProviderInputHistory.sys.mjs", - UrlbarProviderInterventions: - "resource:///modules/UrlbarProviderInterventions.sys.mjs", + // disable as part of tor-browser#41327 + // UrlbarProviderInterventions: + // "resource:///modules/UrlbarProviderInterventions.sys.mjs", UrlbarProviderOmnibox: "resource:///modules/UrlbarProviderOmnibox.sys.mjs", UrlbarProviderPlaces: "resource:///modules/UrlbarProviderPlaces.sys.mjs", UrlbarProviderPrivateSearch: diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs index 8810f2670265ed425d9661d05aba0eaaf7e0a114..107207f2e9f28a6284450475c78abcb2192094c2 100644 --- a/browser/components/urlbar/UrlbarUtils.sys.mjs +++ b/browser/components/urlbar/UrlbarUtils.sys.mjs @@ -1519,17 +1519,21 @@ export var UrlbarUtils = { return "tab"; case UrlbarUtils.RESULT_TYPE.TIP: if (result.providerName === "UrlbarProviderInterventions") { + // disable as part of tor-browser#41327 switch (result.payload.type) { case lazy.UrlbarProviderInterventions.TIP_TYPE.CLEAR: - return "intervention_clear"; + // return "intervention_clear"; + // fall-through case lazy.UrlbarProviderInterventions.TIP_TYPE.REFRESH: - return "intervention_refresh"; + // return "intervention_refresh"; + // fall-through case lazy.UrlbarProviderInterventions.TIP_TYPE.UPDATE_ASK: case lazy.UrlbarProviderInterventions.TIP_TYPE.UPDATE_CHECKING: case lazy.UrlbarProviderInterventions.TIP_TYPE.UPDATE_REFRESH: case lazy.UrlbarProviderInterventions.TIP_TYPE.UPDATE_RESTART: case lazy.UrlbarProviderInterventions.TIP_TYPE.UPDATE_WEB: - return "intervention_update"; + // return "intervention_update"; + // fall-through default: return "intervention_unknown"; } diff --git a/browser/components/urlbar/moz.build b/browser/components/urlbar/moz.build index 1bd3ecb279eb760ac1e86781fc4a022d1a9e3169..3e4766307830b4bfd7dc23a426e5cefb4a2b0693 100644 --- a/browser/components/urlbar/moz.build +++ b/browser/components/urlbar/moz.build @@ -34,7 +34,8 @@ EXTRA_JS_MODULES += [ "UrlbarProviderHeuristicFallback.sys.mjs", "UrlbarProviderHistoryUrlHeuristic.sys.mjs", "UrlbarProviderInputHistory.sys.mjs", - "UrlbarProviderInterventions.sys.mjs", + # disable as part of tor-browser#41327 + # "UrlbarProviderInterventions.sys.mjs", "UrlbarProviderOmnibox.sys.mjs", "UrlbarProviderOpenTabs.sys.mjs", "UrlbarProviderPlaces.sys.mjs", diff --git a/browser/config/mozconfigs/base-browser b/browser/config/mozconfigs/base-browser new file mode 100644 index 0000000000000000000000000000000000000000..2bb193333063bb5084e6aa0ff6a82512ae2e8097 --- /dev/null +++ b/browser/config/mozconfigs/base-browser @@ -0,0 +1,49 @@ +# Shared build settings and settings to enhance security and privacy. + +. $topsrcdir/browser/config/mozconfig + +if test -f "$topsrcdir/mozconfig-toolchain"; then + . $topsrcdir/mozconfig-toolchain +fi + +mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-@CONFIG_GUESS@ + +ac_add_options --enable-official-branding +export MOZILLA_OFFICIAL=1 + +ac_add_options --enable-optimize +ac_add_options --enable-rust-simd + +ac_add_options --disable-unverified-updates +ac_add_options --enable-base-browser-update + +ac_add_options --enable-bundled-fonts + +ac_add_options --disable-tests +ac_add_options --disable-debug + +ac_add_options --disable-crashreporter +# Before removing, please notice that WebRTC does not work on mingw (Bug 1393901) +ac_add_options --disable-webrtc +ac_add_options --disable-parental-controls +ac_add_options --enable-proxy-bypass-protection +# See bugs #30575 and #32418: system policies are harmful either because they +# could allow proxy bypass, and override a number of other preferences we set +ac_add_options --disable-system-policies + +# See bug #41131 +ac_add_options --disable-backgroundtasks + +# Disable telemetry +ac_add_options MOZ_TELEMETRY_REPORTING= + +# Disable the creation of a <something>.default that Firefox by default creates +# for old version that could not use dedicated profiles. See tor-browser#41542. +ac_add_options --disable-legacy-profile-creation + +if test -z "$WASI_SYSROOT"; then + ac_add_options --without-wasm-sandboxed-libraries +fi + +# tor-browser#42337 +ac_add_options --enable-geckodriver diff --git a/browser/config/mozconfigs/base-browser-android b/browser/config/mozconfigs/base-browser-android new file mode 100644 index 0000000000000000000000000000000000000000..9a39b00ebfe7fdcfbbb28c7d958917a9acaf8a3e --- /dev/null +++ b/browser/config/mozconfigs/base-browser-android @@ -0,0 +1,50 @@ +# Changes on this file might need to be synchronized with mozconfig-android-all! +# See also tor-browser#43151. + +export MOZILLA_OFFICIAL=1 + +ac_add_options --enable-optimize +ac_add_options --enable-rust-simd +ac_add_options --enable-official-branding + +ac_add_options --enable-application=mobile/android + +CC="clang" +CXX="clang++" +ac_add_options --enable-linker=lld +ac_add_options --with-java-bin-path=$JAVA_HOME/bin +ac_add_options --with-android-sdk=$ANDROID_HOME +ac_add_options --with-android-ndk=$ANDROID_NDK_HOME +ac_add_options --with-android-min-sdk=21 +ac_add_options --with-gradle=$GRADLE_HOME/bin/gradle + +ac_add_options --enable-strip +ac_add_options --enable-install-strip +ac_add_options --disable-tests +ac_add_options --disable-debug +ac_add_options --disable-rust-debug + +ac_add_options --disable-updater +ac_add_options --disable-crashreporter +ac_add_options --disable-webrtc +ac_add_options --disable-parental-controls + +ac_add_options --enable-proxy-bypass-protection +ac_add_options --disable-system-policies + +# See tor-browser#41131 +ac_add_options --disable-backgroundtasks + +# Disable telemetry +ac_add_options MOZ_TELEMETRY_REPORTING= + +if test -n "$LOCAL_DEV_BUILD"; then + # You must use the "default" bogus channel for dev builds + ac_add_options --enable-update-channel=default + ac_add_options --with-base-browser-version=dev-build + ac_add_options --disable-minify +fi + +if test -z "$WASI_SYSROOT"; then + ac_add_options --without-wasm-sandboxed-libraries +fi diff --git a/browser/config/mozconfigs/tor-browser b/browser/config/mozconfigs/tor-browser new file mode 100644 index 0000000000000000000000000000000000000000..9524c0b7b6cc3950313f7e8701a55cf6b02a0573 --- /dev/null +++ b/browser/config/mozconfigs/tor-browser @@ -0,0 +1,18 @@ +. $topsrcdir/browser/config/mozconfigs/base-browser + +# If building outside tor-browser-build, you might want to customize this value. +# On Linux, it influences the WM_CLASS value, which is shown on GNOME's ALT-TAB, +# for example. +# We customize it in tor-browser-build because we include the channel name, just +# like Firefox does. +# export MOZ_APP_REMOTINGNAME="Tor Browser" + +ac_add_options --with-relative-data-dir=TorBrowser/Data/Browser +# This is not needed with the relative data directory, but it is when you +# disable it, otherwise it is "Mozilla" (on Windows and macOS) or ".mozilla" on +# Unix systems. +# It is used, for example, for GetProductDirectory. +# ac_add_options --with-user-appdir=TorProject +# ac_add_options --with-user-appdir=.torproject + +ac_add_options --with-distribution-id=org.torproject diff --git a/browser/config/mozconfigs/tor-browser-android b/browser/config/mozconfigs/tor-browser-android new file mode 100644 index 0000000000000000000000000000000000000000..894465a4f78f91da2f92b6b37a7f84e0de450e30 --- /dev/null +++ b/browser/config/mozconfigs/tor-browser-android @@ -0,0 +1,3 @@ +. $topsrcdir/browser/config/mozconfigs/base-browser-android + +mk_add_options MOZ_APP_DISPLAYNAME="Tor Browser" diff --git a/browser/confvars.sh b/browser/confvars.sh index 6c27951bfaf54a0030b2db7f3fb15be0b653aa6f..f7a5cb55ea16009c52a21475157343279a964d03 100755 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -11,3 +11,18 @@ # For the mozilla-aurora repository, use "aurora". MOZ_BRANDING_DIRECTORY=browser/branding/unofficial MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official + +# ACCEPTED_MAR_CHANNEL_IDS should usually be the same as the value MAR_CHANNEL_ID. +# If more than one ID is needed, then you should use a comma separated list +# of values. +# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " +if test "$MOZ_UPDATE_CHANNEL" = "alpha"; then + ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-alpha + MAR_CHANNEL_ID=torbrowser-torproject-alpha +elif test "$MOZ_UPDATE_CHANNEL" = "nightly"; then + ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-nightly + MAR_CHANNEL_ID=torbrowser-torproject-nightly +else + ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-release + MAR_CHANNEL_ID=torbrowser-torproject-release +fi diff --git a/browser/extensions/moz.build b/browser/extensions/moz.build index 3c6e7eb886892f419ca83d78b1c1a456e473f218..4e5b9bd6d6c8ad6720eb34c5ee47fab912992c38 100644 --- a/browser/extensions/moz.build +++ b/browser/extensions/moz.build @@ -4,11 +4,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -DIRS += [ - "formautofill", - "screenshots", - "webcompat", - "report-site-issue", - "pictureinpicture", - "search-detection", -] +DIRS += [] diff --git a/browser/fonts/fonts.conf b/browser/fonts/fonts.conf new file mode 100644 index 0000000000000000000000000000000000000000..e0b2cda6e49141c433e197493cc2dbb0bc5d4c10 --- /dev/null +++ b/browser/fonts/fonts.conf @@ -0,0 +1,183 @@ +<?xml version="1.0"?> +<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> +<!-- +**DO NOT EDIT THIS FILE!** +This file sets Tor Browser's bundled fonts as the only available system fonts +and standardizes rendering settings. +Any changes might deanonymize you, or expose you to fingerprinting vectors. +--> +<!-- +Derived from fonts.conf.in of Fontconfig. + +Copyright © 2000,2001,2002,2003,2004,2006,2007 Keith Packard +Copyright © 2005 Patrick Lam +Copyright © 2009 Roozbeh Pournader +Copyright © 2008,2009 Red Hat, Inc. +Copyright © 2008 Danilo Šegan +Copyright © 2012 Google, Inc. + + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of the author(s) not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. The authors make no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +--> +<fontconfig> + +<!-- Font directory list --> + + <dir prefix="cwd">fonts</dir> + +<!-- + Accept deprecated 'mono' alias, replacing it with 'monospace' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>mono</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>monospace</string> + </edit> + </match> + +<!-- + Accept alternate 'sans serif' spelling, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans serif</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>sans-serif</string> + </edit> + </match> + +<!-- + Accept deprecated 'sans' alias, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>sans-serif</string> + </edit> + </match> + +<!-- + Set our default generic families. +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans-serif</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Arimo</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>serif</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Tinos</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>monospace</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Cousine</string> + </edit> + </match> + +<!-- + tor-browser#41799, tor-browser-build#41237: Add some aliases for + compatibility. +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>Arial</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Arimo</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Times New Roman</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Tinos</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Courier New</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Cousine</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Helvetica</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Arimo</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Times</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Tinos</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Courier</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>Cousine</string> + </edit> + </match> + +<!-- Font cache directory list --> + + <cachedir prefix="xdg">fontconfig</cachedir> + + <config> +<!-- + Rescan configuration every 30 seconds when FcFontSetList is called + --> + <rescan> + <int>30</int> + </rescan> + </config> + + <!-- Standardize rendering settings. --> + <match target="pattern"> + <edit name="antialias" mode="assign"><bool>true</bool></edit> + <edit name="autohint" mode="assign"><bool>false</bool></edit> + <edit name="hinting" mode="assign"><bool>true</bool></edit> + <edit name="hintstyle" mode="assign"><const>hintfull</const></edit> + <edit name="lcdfilter" mode="assign"><const>lcddefault</const></edit> + <edit name="rgba" mode="assign"><const>none</const></edit> + </match> +</fontconfig> diff --git a/browser/fonts/moz.build b/browser/fonts/moz.build index 7b9cb08f48e6ba977441fe7d4973694e2225b4dd..82d553e854e50629b895958680cc2761c653545e 100644 --- a/browser/fonts/moz.build +++ b/browser/fonts/moz.build @@ -7,3 +7,6 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("windows", "gtk"): DIST_SUBDIR = "" FINAL_TARGET_FILES.fonts += ["TwemojiMozilla.ttf"] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + FINAL_TARGET_FILES.fonts += ["fonts.conf"] diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in index 2e55ed4b83dcd4b9a761e04c57ec56f8e6673b8f..3827c46cefa8efff8181e4b664cda8c347c57758 100644 --- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -76,6 +76,10 @@ endif endif endif +ifdef BASE_BROWSER_UPDATE +DEFINES += -DBASE_BROWSER_UPDATE +endif + ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET))) DEFINES += -DMOZ_SHARED_MOZGLUE=1 endif diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 8aa6bf65634b6b82d448d57b337c3186bc6e5f96..fd2c2096af08a07262f37fb96decdf1fba83ea8c 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -36,8 +36,10 @@ ; Mac bundle stuff @APPNAME@/Contents/Info.plist #ifdef MOZ_UPDATER +#ifndef BASE_BROWSER_UPDATE @APPNAME@/Contents/Library/LaunchServices #endif +#endif @APPNAME@/Contents/Frameworks @APPNAME@/Contents/PkgInfo @RESPATH@/firefox.icns @@ -137,10 +139,10 @@ @BINPATH@/firefox.VisualElementsManifest.xml @BINPATH@/browser/VisualElements/VisualElements_150.png @BINPATH@/browser/VisualElements/VisualElements_70.png -@BINPATH@/private_browsing.exe -@BINPATH@/private_browsing.VisualElementsManifest.xml -@BINPATH@/browser/VisualElements/PrivateBrowsing_150.png -@BINPATH@/browser/VisualElements/PrivateBrowsing_70.png +; @BINPATH@/private_browsing.exe +; @BINPATH@/private_browsing.VisualElementsManifest.xml +; @BINPATH@/browser/VisualElements/PrivateBrowsing_150.png +; @BINPATH@/browser/VisualElements/PrivateBrowsing_70.png #else #ifndef XP_MACOSX @BINPATH@/@MOZ_APP_NAME@-bin @@ -219,13 +221,23 @@ @RESPATH@/chrome/toolkit@JAREXT@ @RESPATH@/chrome/toolkit.manifest #ifdef MOZ_GTK +@RESPATH@/browser/chrome/icons/default/about-logo.svg @RESPATH@/browser/chrome/icons/default/default16.png @RESPATH@/browser/chrome/icons/default/default32.png @RESPATH@/browser/chrome/icons/default/default48.png @RESPATH@/browser/chrome/icons/default/default64.png @RESPATH@/browser/chrome/icons/default/default128.png #endif -@RESPATH@/browser/features/* + +; Base Browser +@RESPATH@/components/SecurityLevel.manifest + +; Tor Browser localization files +@RESPATH@/chrome/torbutton.manifest +@RESPATH@/chrome/torbutton/* + +; Tor integration +@RESPATH@/components/tor-launcher.manifest ; [DevTools Startup Files] @RESPATH@/browser/chrome/devtools-startup@JAREXT@ @@ -260,6 +272,7 @@ @RESPATH@/browser/defaults/permissions ; Remote Settings JSON dumps @RESPATH@/browser/defaults/settings +@RESPATH@/browser/@PREF_DIR@/000-tor-browser.js # channel-prefs.js has been removed on macOS. #ifndef XP_MACOSX @@ -311,6 +324,7 @@ @RESPATH@/res/locale/layout/HtmlForm.properties @RESPATH@/res/locale/layout/MediaDocument.properties @RESPATH@/res/locale/layout/xmlparser.properties +@RESPATH@/res/locale/xslt/xslt.properties @RESPATH@/res/locale/dom/dom.properties #ifdef XP_MACOSX @RESPATH@/res/MainMenu.nib/ @@ -407,10 +421,6 @@ bin/libfreebl_64int_3.so @BINPATH@/minidump-analyzer@BIN_SUFFIX@ #endif -; [ Ping Sender ] -; -@BINPATH@/pingsender@BIN_SUFFIX@ - ; [ Native Messaging Host Proxy ] ; #if defined(XP_WIN) || defined(XP_MACOSX) @@ -435,11 +445,11 @@ bin/libfreebl_64int_3.so #endif ; media -@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@ -@RESPATH@/gmp-clearkey/0.1/manifest.json -#if defined(MOZ_WMF_CDM) && defined(ENABLE_TESTS) -@BINPATH@/@DLL_PREFIX@wmfclearkey@DLL_SUFFIX@ -#endif +;@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@ +;@RESPATH@/gmp-clearkey/0.1/manifest.json +;#if defined(MOZ_WMF_CDM) && defined(ENABLE_TESTS) +;@BINPATH@/@DLL_PREFIX@wmfclearkey@DLL_SUFFIX@ +;#endif #ifdef PKG_LOCALE_MANIFEST #include @PKG_LOCALE_MANIFEST@ diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh index 35e83936e827b7eb0ce5793ed70f92bd9365ff3e..eacbf83c1c5ee3ecd266ed63345cb0a849820f3f 100755 --- a/browser/installer/windows/nsis/shared.nsh +++ b/browser/installer/windows/nsis/shared.nsh @@ -1581,7 +1581,6 @@ ${RemoveDefaultBrowserAgentShortcut} Push "default-browser-agent.exe" Push "minidump-analyzer.exe" Push "nmhproxy.exe" - Push "pingsender.exe" Push "updater.exe" Push "mozwer.dll" Push "${FileMainEXE}" diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in index 1b8f21be1ca64fd493b480d07d0afd2ec08c6aab..d3b76c92e48ab0a302becf0a4e1078f8a850dc2a 100644 --- a/browser/locales/Makefile.in +++ b/browser/locales/Makefile.in @@ -52,10 +52,6 @@ l10n-%: @$(MAKE) -C ../themes/shared/app-marketplace-icons AB_CD=$* XPI_NAME=locale-$* @$(MAKE) -C ../../toolkit/locales l10n-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)' @$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* -ifneq (,$(wildcard ../extensions/formautofill/locales)) - @$(MAKE) -C ../extensions/formautofill/locales AB_CD=$* XPI_NAME=locale-$* -endif - @$(MAKE) -C ../extensions/report-site-issue/locales AB_CD=$* XPI_NAME=locale-$* @$(MAKE) -C ../../devtools/client/locales AB_CD=$* XPI_NAME=locale-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)' @$(MAKE) -C ../../devtools/startup/locales AB_CD=$* XPI_NAME=locale-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)' @$(MAKE) l10n AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) @@ -69,14 +65,10 @@ chrome-%: @$(MAKE) -C ../themes/shared/app-marketplace-icons chrome AB_CD=$* @$(MAKE) -C ../../toolkit/locales chrome-$* @$(MAKE) -C ../../extensions/spellcheck/locales chrome AB_CD=$* -ifneq (,$(wildcard ../extensions/formautofill/locales)) - @$(MAKE) -C ../extensions/formautofill/locales chrome AB_CD=$* -endif @$(MAKE) -C ../../devtools/client/locales chrome AB_CD=$* @$(MAKE) -C ../../devtools/startup/locales chrome AB_CD=$* @$(MAKE) chrome AB_CD=$* @$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales chrome AB_CD=$* - @$(MAKE) -C ../extensions/report-site-issue/locales chrome AB_CD=$* package-win32-installer: $(SUBMAKEFILES) $(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen ZIP_IN='$(ZIP_OUT)' installer diff --git a/browser/locales/en-US/chrome/overrides/appstrings.properties b/browser/locales/en-US/chrome/overrides/appstrings.properties deleted file mode 100644 index d572ac39c65786db3d5cb799bfa1071578ca1d45..0000000000000000000000000000000000000000 --- a/browser/locales/en-US/chrome/overrides/appstrings.properties +++ /dev/null @@ -1,46 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -malformedURI2=Please check that the URL is correct and try again. -fileNotFound=Firefox can’t find the file at %S. -fileAccessDenied=The file at %S is not readable. -# %S is replaced by the uri host -serverError=%S might have a temporary problem or it could have moved. -dnsNotFound2=We can’t connect to the server at %S. -unknownProtocolFound=Firefox doesn’t know how to open this address, because one of the following protocols (%S) isn’t associated with any program or is not allowed in this context. -connectionFailure=Firefox can’t establish a connection to the server at %S. -netInterrupt=The connection to %S was interrupted while the page was loading. -netTimeout=The server at %S is taking too long to respond. -redirectLoop=Firefox has detected that the server is redirecting the request for this address in a way that will never complete. -## LOCALIZATION NOTE (confirmRepostPrompt): In this item, don’t translate "%S" -confirmRepostPrompt=To display this page, %S must send information that will repeat any action (such as a search or order confirmation) that was performed earlier. -resendButton.label=Resend -unknownSocketType=Firefox doesn’t know how to communicate with the server. -netReset=The connection to the server was reset while the page was loading. -notCached=This document is no longer available. -netOffline=Firefox is currently in offline mode and can’t browse the Web. -isprinting=The document cannot change while Printing or in Print Preview. -deniedPortAccess=This address uses a network port which is normally used for purposes other than Web browsing. Firefox has canceled the request for your protection. -proxyResolveFailure=Firefox is configured to use a proxy server that can’t be found. -proxyConnectFailure=Firefox is configured to use a proxy server that is refusing connections. -contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression. -unsafeContentType=The page you are trying to view cannot be shown because it is contained in a file type that may not be safe to open. Please contact the website owners to inform them of this problem. -externalProtocolTitle=External Protocol Request -externalProtocolPrompt=An external application must be launched to handle %1$S: links.\n\n\nRequested link:\n\n%2$S\n\nApplication: %3$S\n\n\nIf you were not expecting this request it may be an attempt to exploit a weakness in that other program. Cancel this request unless you are sure it is not malicious.\n -#LOCALIZATION NOTE (externalProtocolUnknown): The following string is shown if the application name can't be determined -externalProtocolUnknown=<Unknown> -externalProtocolChkMsg=Remember my choice for all links of this type. -externalProtocolLaunchBtn=Launch application -malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences. -harmfulBlocked=The site at %S has been reported as a potentially harmful site and has been blocked based on your security preferences. -unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences. -deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences. -cspBlocked=This page has a content security policy that prevents it from being loaded in this way. -xfoBlocked=This page has an X-Frame-Options policy that prevents it from being loaded in this context. -corruptedContentErrorv2=The site at %S has experienced a network protocol violation that cannot be repaired. -## LOCALIZATION NOTE (sslv3Used) - Do not translate "%S". -sslv3Used=Firefox cannot guarantee the safety of your data on %S because it uses SSLv3, a broken security protocol. -inadequateSecurityError=The website tried to negotiate an inadequate level of security. -blockedByPolicy=Your organization has blocked access to this page or website. -networkProtocolError=Firefox has experienced a network protocol violation that cannot be repaired. diff --git a/browser/locales/jar.mn b/browser/locales/jar.mn index ea3141e0aeda126ae8be7ee3000d1db85e4fb47c..c699ecd8fda16743498cc81ae91ac4cfa78941f2 100644 --- a/browser/locales/jar.mn +++ b/browser/locales/jar.mn @@ -37,12 +37,3 @@ locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties) locale/browser/syncSetup.properties (%chrome/browser/syncSetup.properties) % locale browser-region @AB_CD@ %locale/browser-region/ -# the following files are browser-specific overrides - locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties) - -#ifdef XPI_NAME -# Bug 1240628, restructure how l10n repacks work with feature addons -# This is hacky, but ensures the chrome.manifest chain is complete -[.] chrome.jar: -% manifest features/chrome.manifest -#endif diff --git a/browser/modules/BrowserWindowTracker.sys.mjs b/browser/modules/BrowserWindowTracker.sys.mjs index 987a7b092039c39b73f96f390ecec80ce4481335..e82466a371f29258bf9fbed56e733d4611aa0d6a 100644 --- a/browser/modules/BrowserWindowTracker.sys.mjs +++ b/browser/modules/BrowserWindowTracker.sys.mjs @@ -294,7 +294,10 @@ export const BrowserWindowTracker = { let loadURIString; if (isPrivate && lazy.PrivateBrowsingUtils.enabled) { windowFeatures += ",private"; - if (!args && !lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) { + if ( + (!args && !lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) || + args?.private === "no-home" + ) { // Force the new window to load about:privatebrowsing instead of the // default home page. loadURIString = "about:privatebrowsing"; diff --git a/browser/modules/HomePage.sys.mjs b/browser/modules/HomePage.sys.mjs index f4da51fe754b004e44bfd9db6f8d2ecf0940ea5b..785ed41129a5d41b169193b9e6cc34a8c5c46740 100644 --- a/browser/modules/HomePage.sys.mjs +++ b/browser/modules/HomePage.sys.mjs @@ -14,7 +14,7 @@ ChromeUtils.defineESModuleGetters(lazy, { }); const kPrefName = "browser.startup.homepage"; -const kDefaultHomePage = "about:home"; +const kDefaultHomePage = "about:tor"; const kExtensionControllerPref = "browser.startup.homepage_override.extensionControlled"; const kHomePageIgnoreListId = "homepage-urls"; diff --git a/browser/modules/LaterRun.sys.mjs b/browser/modules/LaterRun.sys.mjs index 505942d617d875053931b05a4639f5587ef30d31..ff1d8013c9c1ac4aec802367f3ee866403a5dc9c 100644 --- a/browser/modules/LaterRun.sys.mjs +++ b/browser/modules/LaterRun.sys.mjs @@ -61,6 +61,20 @@ export let LaterRun = { }, init(reason) { + // Keep disabled in Base Browser. See tor-browser#41568. + // NOTE: This means that users cannot benefit from feature prompts gated + // behind LaterRun. + // In mozilla ESR 128 it is only used in one place, and is gated behind a + // feature recommendation preference that we switch off in Base Browser + // anyway. See tor-browser#42630. + // But this decision should be reviewed. See tor-browser#43093. + Services.prefs.setBoolPref(kEnabledPref, false); + // Clear any preferences that may have been set before LaterRun was + // disabled. + Services.prefs.clearUserPref(kSessionCountPref); + Services.prefs.clearUserPref(kProfileCreationTime); + Services.prefs.clearUserPref(kUpdateAppliedTime); + if (!this.enabled) { return; } @@ -99,11 +113,8 @@ export let LaterRun = { return Services.prefs.getBoolPref(kEnabledPref, false); }, - enable(reason) { - if (!this.enabled) { - Services.prefs.setBoolPref(kEnabledPref, true); - this.init(reason); - } + enable(_reason) { + // Keep disabled in Base Browser. See tor-browser#41568. }, get hoursSinceInstall() { diff --git a/browser/modules/TorUIUtils.sys.mjs b/browser/modules/TorUIUtils.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..aa04fd7cec5708d06c29bbed74237ac5126fea3d --- /dev/null +++ b/browser/modules/TorUIUtils.sys.mjs @@ -0,0 +1,26 @@ +/** + * Common methods for tor UI components. + */ +export const TorUIUtils = { + /** + * Shorten the given address if it is an onion address. + * + * @param {string} address - The address to shorten. + * + * @returns {string} The shortened form of the address, or the address itself + * if it was not shortened. + */ + shortenOnionAddress(address) { + if ( + // Only shorten ".onion" addresses. + !address.endsWith(".onion") || + // That are not "onion" aliases. + address.endsWith(".tor.onion") || + // And are long. + address.length <= 21 + ) { + return address; + } + return `${address.slice(0, 6)}…${address.slice(-12)}`; + }, +}; diff --git a/browser/modules/URILoadingHelper.sys.mjs b/browser/modules/URILoadingHelper.sys.mjs index f85b68dbb719c70d4c3a89a505b549bb78b67466..70f6d37d06bbf9ac64cb0ee84296ea21fbda8014 100644 --- a/browser/modules/URILoadingHelper.sys.mjs +++ b/browser/modules/URILoadingHelper.sys.mjs @@ -11,6 +11,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", }); ChromeUtils.defineLazyGetter(lazy, "ReferrerInfo", () => @@ -426,6 +427,28 @@ export const URILoadingHelper = { return; } + // make sure users are not faced with the scary red 'tor isn't working' screen + // if they navigate to about:tor before bootstrapped + // + // fixes tor-browser#40752 + // new tabs also redirect to about:tor if browser.newtabpage.enabled is true + // otherwise they go to about:blank + if (lazy.TorConnect.shouldShowTorConnect) { + const homeURLs = [ + "about:home", + "about:privatebrowsing", + "about:tor", + "about:welcome", + ]; + if ( + homeURLs.includes(url) || + (url === "about:newtab" && + Services.prefs.getBoolPref("browser.newtabpage.enabled", false)) + ) { + url = lazy.TorConnect.getRedirectURL(url); + } + } + let { allowThirdPartyFixup, postData, diff --git a/browser/modules/moz.build b/browser/modules/moz.build index 97e1c11cca33b5bb61a14d7ca328994551944f73..1c209b1a316dd9fb343611234cae5107e5b18224 100644 --- a/browser/modules/moz.build +++ b/browser/modules/moz.build @@ -135,6 +135,7 @@ EXTRA_JS_MODULES += [ "SelectionChangedMenulist.sys.mjs", "SiteDataManager.sys.mjs", "SitePermissions.sys.mjs", + "TorUIUtils.sys.mjs", "TransientPrefs.sys.mjs", "URILoadingHelper.sys.mjs", "webrtcUI.sys.mjs", diff --git a/browser/moz.build b/browser/moz.build index 81042c95e629aee4fd31cdfc114a7943eb1ba4b8..56191cccaa76107a0cf30c3a54b04306d129a824 100644 --- a/browser/moz.build +++ b/browser/moz.build @@ -54,6 +54,7 @@ if CONFIG["MOZ_ARTIFACT_BUILDS"]: # These files are specified in this moz.build to pick up DIST_SUBDIR as set in # this directory, which is un-set in browser/app. JS_PREFERENCE_PP_FILES += [ + "app/profile/000-tor-browser.js", "app/profile/firefox.js", ] FINAL_TARGET_FILES.defaults += ["app/permissions"] diff --git a/browser/moz.configure b/browser/moz.configure index e605019172ad6ba6e601b520129e7bfe67f452a2..3c82d9f5dfaf0e863839e4d51afd54daf2d36552 100644 --- a/browser/moz.configure +++ b/browser/moz.configure @@ -5,15 +5,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. imply_option("MOZ_PLACES", True) -imply_option("MOZ_SERVICES_HEALTHREPORT", True) +# tor-browser#32493 +imply_option("MOZ_SERVICES_HEALTHREPORT", False) imply_option("MOZ_SERVICES_SYNC", True) -imply_option("MOZ_DEDICATED_PROFILES", True) -imply_option("MOZ_BLOCK_PROFILE_DOWNGRADE", True) -imply_option("MOZ_NORMANDY", True) -imply_option("MOZ_PROFILE_MIGRATOR", True) +imply_option("MOZ_DEDICATED_PROFILES", False) +imply_option("MOZ_BLOCK_PROFILE_DOWNGRADE", False) +# tor-browser#33734 +imply_option("MOZ_NORMANDY", False) +imply_option("MOZ_PROFILE_MIGRATOR", False) -imply_option("MOZ_APP_VENDOR", "Mozilla") +imply_option("MOZ_APP_VENDOR", "Tor Project") imply_option("MOZ_APP_ID", "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}") # Include the DevTools client, not just the server (which is the default) imply_option("MOZ_DEVTOOLS", "all") @@ -47,7 +49,7 @@ def requires_stub_installer( "USE_STUB_INSTALLER is not specified in the environment" ) - return True + return False imply_option("MOZ_STUB_INSTALLER", True, when=requires_stub_installer) diff --git a/browser/themes/shared/addons/unified-extensions.css b/browser/themes/shared/addons/unified-extensions.css index f254bf482d6239d19ea9d5e9166594c0f4504c9a..44eb231b3467f4c3239dee8a743d9987a73094dc 100644 --- a/browser/themes/shared/addons/unified-extensions.css +++ b/browser/themes/shared/addons/unified-extensions.css @@ -255,3 +255,21 @@ unified-extensions-item { } } } + +/* Extra rule for tor-browser. See tor-browser#41581. + * We want to hide the unified-extensions-button when it is empty. + * However, this button is needed as an anchor for addon notifications. E.g. + * when installing another addon and permissions pop up. + * If we simply marked it as "hidden" then it would not be used as an anchor, so + * the popup would fall back to using the identity button as an anchor instead. + * So instead, we use "visibility: collapse" whilst it is empty *and* it is not + * being used as an anchor (the open attribute is missing). */ +#unified-extensions-button.hide-empty:not([open]) { + visibility: collapse; + /* Ensure getBoundingClientRect().width returns 0. + * Even though this button is collapsed, and therefore should not take up any + * layout space, getBoundingClientRect will still measure the padding. + * If this was not zero, OverflowableToolbar#getOverflowInfo would + * over-measure the children width and would always overflow. */ + padding-inline: 0; +} diff --git a/browser/themes/shared/browser-shared.css b/browser/themes/shared/browser-shared.css index 70622633f63091f1754b1122d608f789a650ffa7..5fd67f3d56301f9a6ae4eab6c2f666e72e4f4b71 100644 --- a/browser/themes/shared/browser-shared.css +++ b/browser/themes/shared/browser-shared.css @@ -27,6 +27,10 @@ @import url("chrome://browser/skin/customizableui/customizeMode.css"); @import url("chrome://browser/skin/UITour.css"); @import url("chrome://browser/skin/formautofill-notification.css"); +@import url("chrome://browser/skin/tor-branding.css"); +@import url("chrome://global/skin/tor-colors.css"); +@import url("chrome://browser/skin/tor-urlbar-button.css"); +@import url("chrome://browser/skin/onionlocation.css"); :root, body { diff --git a/browser/themes/shared/controlcenter/panel.css b/browser/themes/shared/controlcenter/panel.css index b1b9e41d8f6546daf1a60b5a9ab820d215320084..5564589089e07a6470f682a3aa70366b7bec89f7 100644 --- a/browser/themes/shared/controlcenter/panel.css +++ b/browser/themes/shared/controlcenter/panel.css @@ -209,7 +209,15 @@ } #identity-popup[connection=chrome] .identity-popup-security-connection { - list-style-image: url(chrome://branding/content/icon48.png); + /* This is rendered at 16px. In upstream mozilla this was icon48.png, which + * for tb-alpha and tb-nightly will include a small "alpha" and "moon" symbol, + * respectively. This do not render well at 16px, so we swap to icon32.png, + * which does not include these symbols. + * This also keeps the icon consistent with the favicon used for some internal + * pages (icon32.png) and the site identity button icon (icon16.png or + * icon32.png). + * See tor-browser#42088 */ + list-style-image: url(chrome://branding/content/icon32.png); } #identity-popup[connection=file] .identity-popup-security-connection { diff --git a/browser/themes/shared/downloads/contentAreaDownloadsView.css b/browser/themes/shared/downloads/contentAreaDownloadsView.css index 22261ac7c332e7dce0b8370c1d89de07ef903ea0..8cc875a4c0f40da8934a58f686cc77c00a41267f 100644 --- a/browser/themes/shared/downloads/contentAreaDownloadsView.css +++ b/browser/themes/shared/downloads/contentAreaDownloadsView.css @@ -25,3 +25,7 @@ text-align: center; color: var(--text-color-deemphasized); } + +#aboutDownloadsTorWarning { + margin-block-end: 8px; +} diff --git a/browser/themes/shared/icons/new_circuit.svg b/browser/themes/shared/icons/new_circuit.svg new file mode 100644 index 0000000000000000000000000000000000000000..18981b517ea8e300b53ec551f7b25f19f42ad58d --- /dev/null +++ b/browser/themes/shared/icons/new_circuit.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5994 2.89744C9.52191 2.34851 8.2983 2.15477 7.10392 2.34398C6.64247 2.41708 6.19453 2.5459 5.76923 2.72578C5.82159 2.91042 5.84961 3.10529 5.84961 3.3067C5.84961 4.48031 4.89821 5.4317 3.72461 5.4317C2.551 5.4317 1.59961 4.48031 1.59961 3.3067C1.59961 2.1331 2.551 1.1817 3.72461 1.1817C4.23757 1.1817 4.70808 1.36346 5.07525 1.66608C5.65429 1.3987 6.27072 1.21038 6.90834 1.10937C8.36342 0.878863 9.85413 1.11489 11.1668 1.78364C12.4795 2.45239 13.5468 3.51953 14.2158 4.83212C14.8848 6.14471 15.121 7.63538 14.8907 9.0905C14.8368 9.43143 14.5167 9.66408 14.1757 9.61013C13.8348 9.55617 13.6022 9.23605 13.6561 8.89511C13.8451 7.70071 13.6512 6.47713 13.1021 5.39971C12.553 4.3223 11.6769 3.44636 10.5994 2.89744ZM4.64961 3.3067C4.64961 3.81756 4.23547 4.2317 3.72461 4.2317C3.21375 4.2317 2.79961 3.81756 2.79961 3.3067C2.79961 2.79584 3.21375 2.3817 3.72461 2.3817C4.23547 2.3817 4.64961 2.79584 4.64961 3.3067Z" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M1.82421 6.38991C2.16514 6.44387 2.39779 6.76399 2.34383 7.10492C2.15482 8.29933 2.34875 9.52291 2.89785 10.6003C3.44695 11.6777 4.32303 12.5537 5.40053 13.1026C6.47803 13.6515 7.70165 13.8453 8.89602 13.6561C9.35628 13.5831 9.8031 13.4548 10.2274 13.2757C10.1734 13.0884 10.1445 12.8906 10.1445 12.686C10.1445 11.5124 11.0959 10.561 12.2695 10.561C13.4431 10.561 14.3945 11.5124 14.3945 12.686C14.3945 13.8596 13.4431 14.811 12.2695 14.811C11.7602 14.811 11.2927 14.6318 10.9267 14.333C10.3471 14.6009 9.72997 14.7895 9.0916 14.8907C7.63652 15.1212 6.14581 14.8851 4.83311 14.2164C3.52042 13.5476 2.45311 12.4805 1.78415 11.1679C1.11519 9.85533 0.878921 8.36466 1.1092 6.90954C1.16315 6.56861 1.48327 6.33596 1.82421 6.38991ZM13.1945 12.686C13.1945 13.1968 12.7804 13.611 12.2695 13.611C11.7587 13.611 11.3445 13.1968 11.3445 12.686C11.3445 12.1751 11.7587 11.761 12.2695 11.761C12.7804 11.761 13.1945 12.1751 13.1945 12.686Z" fill="context-fill"/> +</svg> diff --git a/browser/themes/shared/icons/new_identity.svg b/browser/themes/shared/icons/new_identity.svg new file mode 100644 index 0000000000000000000000000000000000000000..096ff169c02f318c7968e77986743ca1e5086eb8 --- /dev/null +++ b/browser/themes/shared/icons/new_identity.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g fill="context-fill" fill-opacity="context-fill-opacity"> + <path d="m13.5383 14.5627c-.1712-.0053-.3194-.1334-.3505-.3028-.0419-.294-.1441-.5789-.3001-.8369-.2583-.1558-.5436-.2579-.838-.2998-.1694-.0313-.2974-.1793-.3026-.3501-.0053-.1708.1136-.3146.2813-.3402.2944-.0329.5762-.1254.8284-.272.1426-.2476.2313-.5243.2608-.8129.0237-.1679.1662-.2884.3372-.2851.1699.0042.3181.1295.3517.2973.0471.2931.1533.5763.312.8323.2565.1573.5396.263.8326.3109.1682.0345.2929.1836.2958.3536.0028.17-.1171.3116-.2843.3357-.2894.0285-.5669.1172-.8147.2604-.1462.2521-.2386.5335-.2717.8274-.025.167-.1675.2861-.3379.2822z"/> + <path d="m6.49858 2.99992c-.14675-.00459-.27377-.11436-.3004-.25961-.03593-.25196-.12354-.49621-.25729-.71731-.22137-.13358-.46594-.22109-.71822-.25699-.14526-.02682-.25492-.15363-.25945-.30004-.00454-.14641.09737-.26967.24112-.29164.25236-.02817.49393-.10747.71013-.233093.12217-.2123.19825-.449454.22353-.696834.0203-.143878.14242-.24714456.28897-.24434753.14565.00358504.27273.11100153.30149.25484453.0404.251183.13139.493923.2674.713349.21988.134841.46256.225461.71364.266481.14417.02957.25114.15744.25358.30313.00244.1457-.10035.26707-.24368.28774-.2481.02441-.48592.10041-.69835.22319-.1253.2161-.20449.45729-.23284.7092-.0214.14312-.14361.24521-.28963.24193z"/> + <path d="m1.82093 5.3609c-.15279-.00473-.28512-.11875-.31315-.26981-.02739-.18014-.08781-.35525-.1782-.51643-.16152-.09021-.336989-.15052-.517512-.17788-.151437-.02794-.265749-.16003-.270474-.31254-.004724-.15251.101518-.2809.251381-.30378.181146-.02145.355265-.07593.513815-.16075.08209-.15545.13363-.32622.15197-.50355.02095-.15059.14903-.25861.3025-.25512.15164.00368.28404.11525.31428.26484.03021.18029.09338.35503.18632.51538.16048.09192.33508.15452.51517.18469.1503.0308.26181.164.26435.31577.00254.15176-.10462.27819-.25404.29971-.17764.01914-.34855.07141-.50396.15412-.08502.1582-.13963.33194-.16114.5127-.022.14911-.14912.25571-.30131.25265z"/> + <path clip-rule="evenodd" d="m15.3213 1.06694c.2441-.244076.2441-.639804 0-.883882-.2441-.2440775-.6398-.2440774-.8839 0l-5.96506 5.965062h-.50519c-1.996-1.09517-4.49023.42233-6.49079 1.63948-.41545.25277-.80961.49258-1.173597.69335-.16756.10002-.289261.26641-.30145394.48048-.01219156.21407.06079654.41038.21802994.56743l1.243691 1.24224 2.37084-1.02603c.15392-.06661.30331.14022.18601.25753l-1.66213 1.6621 1.46329 1.4616 1.66126-1.6613c.1173-.1173.32413.0321.25752.186l-1.02482 2.3682 1.25462 1.2531c.15724.157.35379.23.56815.2178.19095-.0561.35851-.1561.45869-.3234.20012-.3592.43577-.7455.68321-1.1511 1.22241-2.0039 2.73233-4.47901 1.66484-6.47533v-.49654zm-7.46715 6.55077c1.12692 1.12692.64113 2.69369-.05278 3.70149h-.50137l-3.13-3.1492v-.5c1.00858-.68566 2.56556-1.17088 3.68415-.05229z" fill-rule="evenodd"/> + </g> +</svg> diff --git a/browser/themes/shared/identity-block/identity-block.css b/browser/themes/shared/identity-block/identity-block.css index d7bb48f5bee58938797e4fa887d11ee53a9d1f0f..1c2046ed52aeb35470bac49642f728bbd254bb9a 100644 --- a/browser/themes/shared/identity-block/identity-block.css +++ b/browser/themes/shared/identity-block/identity-block.css @@ -205,6 +205,29 @@ list-style-image: url(chrome://global/skin/icons/security-broken.svg); } +#identity-box[pageproxystate="valid"].onionUnknownIdentity #identity-icon, +#identity-box[pageproxystate="valid"].onionVerifiedDomain #identity-icon, +#identity-box[pageproxystate="valid"].onionMixedActiveBlocked #identity-icon { + list-style-image: url(chrome://global/skin/icons/onion-site.svg); + visibility: visible; +} + +#identity-box[pageproxystate="valid"].onionMixedDisplayContent #identity-icon, +#identity-box[pageproxystate="valid"].onionMixedDisplayContentLoadedActiveBlocked #identity-icon, +#identity-box[pageproxystate="valid"].onionCertUserOverridden #identity-icon { + list-style-image: url(chrome://global/skin/icons/onion-warning.svg); + visibility: visible; + /* onion-warning includes another context-stroke color. Here we want it to + * match the context-fill color, which should be currentColor. */ + -moz-context-properties: fill, fill-opacity, stroke; + stroke: currentColor; +} + +#identity-box[pageproxystate="valid"].onionMixedActiveContent #identity-icon { + list-style-image: url(chrome://global/skin/icons/onion-slash.svg); + visibility: visible; +} + #permissions-granted-icon { list-style-image: url(chrome://browser/skin/permissions.svg); } @@ -249,6 +272,9 @@ /* TRACKING PROTECTION ICON */ #tracking-protection-icon-container { + /* Always hide the tracking toolbar button in Base Browser. + * tor-browser#26345. */ + display: none !important; padding-inline: var(--urlbar-icon-padding); border-radius: var(--urlbar-icon-border-radius); /* This is needed in order to position the blue dot indicator. */ diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn index 5f6bbd50f9235823e10f5dfbe4c757b578f884e7..503b73110609f8bf675a6832d3fc9008d470faf9 100644 --- a/browser/themes/shared/jar.inc.mn +++ b/browser/themes/shared/jar.inc.mn @@ -29,6 +29,8 @@ skin/classic/browser/sidebar.css (../shared/sidebar.css) skin/classic/browser/toolbarbuttons.css (../shared/toolbarbuttons.css) skin/classic/browser/toolbarbutton-icons.css (../shared/toolbarbutton-icons.css) + skin/classic/browser/tor-branding.css (../shared/tor-branding.css) + skin/classic/browser/tor-urlbar-button.css (../shared/tor-urlbar-button.css) skin/classic/browser/urlbar-dynamic-results.css (../shared/urlbar-dynamic-results.css) skin/classic/browser/urlbar-searchbar.css (../shared/urlbar-searchbar.css) skin/classic/browser/urlbarView.css (../shared/urlbarView.css) @@ -286,3 +288,7 @@ skin/classic/browser/weather/night-partly-cloudy-with-showers.svg (../shared/weather/night-partly-cloudy-with-showers.svg) skin/classic/browser/weather/night-partly-cloudy-with-thunderstorms.svg (../shared/weather/night-partly-cloudy-with-thunderstorms.svg) skin/classic/browser/weather/night-mostly-cloudy-with-flurries.svg (../shared/weather/night-mostly-cloudy-with-flurries.svg) + + skin/classic/browser/new_identity.svg (../shared/icons/new_identity.svg) + + skin/classic/browser/new_circuit.svg (../shared/icons/new_circuit.svg) diff --git a/browser/themes/shared/notification-icons.css b/browser/themes/shared/notification-icons.css index f17b7d64f88739c6b7a06764500cf84b23867f65..1e561c37399ee348aee3b0e4e55ca792aae04a6f 100644 --- a/browser/themes/shared/notification-icons.css +++ b/browser/themes/shared/notification-icons.css @@ -121,6 +121,8 @@ list-style-image: url(chrome://browser/skin/notification-icons/persistent-storage.svg); } +.popup-notification-icon[popupid="tor-clientauth"], +.tor-clientauth-icon, #password-notification-icon { list-style-image: url(chrome://browser/skin/login.svg); diff --git a/browser/themes/shared/preferences/preferences.css b/browser/themes/shared/preferences/preferences.css index ddb6ea0e9ec0099f7c9513fe45f8151978137ac5..4c5c92b692cee730a1e7856d4a518a404ab120e4 100644 --- a/browser/themes/shared/preferences/preferences.css +++ b/browser/themes/shared/preferences/preferences.css @@ -599,6 +599,13 @@ html|label[disabled] { margin-inline-start: 0; } +@media (-moz-platform: windows) { + #windows-sso, + #windows-sso-caption { + display: none; + } +} + /** * Dialog */ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css index 24909332163ee96f89c9de13a8a37cdab3cfe152..ba5b7a29477d5336df3ba77999f281fa9d137b72 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -1047,8 +1047,13 @@ tab-group { /* Firefox View button and menu item */ -:root:not([privatebrowsingmode], [firefoxviewhidden]) :is(toolbarbutton, toolbarpaletteitem) ~ #tabbrowser-tabs, -:root[privatebrowsingmode]:not([firefoxviewhidden]) :is( +/* about:firefoxview is disabled in Base Browser. See tor-browser#42037. + * Therefore we always hide #firefox-view-button, regardless of private + * browsing. Here we only want to draw the border if there is a non-hidden + * toolbar item before the tabs. + * NOTE: Expect merge conflict from bugzilla bug 1917595 and bug 1917599. In + * these cases we want to keep our selector as-is. */ +:root :is( toolbarbutton:not(#firefox-view-button), toolbarpaletteitem:not(#wrapper-firefox-view-button) ) ~ #tabbrowser-tabs { @@ -1057,8 +1062,13 @@ tab-group { margin-inline-start: 2px; } -:root[firefoxviewhidden] :is(#firefox-view-button, #wrapper-firefox-view-button), -:root[privatebrowsingmode] :is(#firefox-view-button, #menu_openFirefoxView) { +/* about:firefoxview is disabled in Base Browser. Always hide the toolbar button + * and menu item regardless of private browsing. See tor-browser#42037. + * NOTE: We also hide #wrapper-firefox-view-button, which is used during + * customization. + * NOTE: Expect merge conflict from bugzilla bug 1903812 and bug 1917599. In + * these cases we want to keep our selector as-is. */ +#firefox-view-button, #wrapper-firefox-view-button, #menu_openFirefoxView { display: none; } diff --git a/browser/themes/shared/toolbarbutton-icons.css b/browser/themes/shared/toolbarbutton-icons.css index cdef75c4aed67072271715e055a416c2b8a6f8c9..a07de424c679db226830a2a48c5597126706c896 100644 --- a/browser/themes/shared/toolbarbutton-icons.css +++ b/browser/themes/shared/toolbarbutton-icons.css @@ -100,6 +100,14 @@ list-style-image: url("chrome://browser/skin/new-tab.svg"); } +#new-identity-button { + list-style-image: url("chrome://browser/skin/new_identity.svg"); +} + +#new-circuit-button { + list-style-image: url("chrome://browser/skin/new_circuit.svg"); +} + #privatebrowsing-button { list-style-image: url("chrome://browser/skin/privateBrowsing.svg"); } diff --git a/browser/themes/shared/tor-branding.css b/browser/themes/shared/tor-branding.css new file mode 100644 index 0000000000000000000000000000000000000000..ad5a7b580c0601aebc162d61dbeb099ff9dac7a8 --- /dev/null +++ b/browser/themes/shared/tor-branding.css @@ -0,0 +1,13 @@ +.letterboxing { + --letterboxing-bgcolor: var(--color-grey-light-20, #F0F0F4); + --letterboxing-gradient-color1: rgba(0, 219, 222, 0.02); + --letterboxing-gradient-color2: rgba(252, 0, 255, 0.02); +} + +@media (prefers-color-scheme: dark) { + .letterboxing { + --letterboxing-bgcolor: var(--color-grey-dark-10, #52525E); + --letterboxing-gradient-color1: rgba(0, 219, 222, 0.06); + --letterboxing-gradient-color2: rgba(252, 0, 255, 0.06); + } +} diff --git a/browser/themes/shared/tor-urlbar-button.css b/browser/themes/shared/tor-urlbar-button.css new file mode 100644 index 0000000000000000000000000000000000000000..60d01bc720320fed0534f13e3ab6b03188369756 --- /dev/null +++ b/browser/themes/shared/tor-urlbar-button.css @@ -0,0 +1,78 @@ +.tor-urlbar-button:not([hidden]) { + display: flex; + align-items: center; + gap: 0.5em; + border-radius: var(--urlbar-icon-border-radius); + --tor-urlbar-button-inline-padding: 8px; + padding-inline: var(--tor-urlbar-button-inline-padding); + margin: 0; +} + +.tor-urlbar-button > * { + flex: 0 0 auto; + margin: 0; +} + +.tor-urlbar-button:focus-visible { + /* This button lies within the urlbar, so if the outline extends beyond the + * button's boundary, it will be clipped by the urlbar. + * Most button's in the urlbar get around this by using --focus-outline-inset, + * but our button has a purple background, which does not contrast well with + * the focus outline. + * Therefore, we use an offset outline rather than an inset outline, and + * compensate by shrinking the button's width and height so that the outline + * fits within the non-focused button boundary. Essentially, this has a + * similar effect to using an inset outline that matches the color of the + * urlbar background, but we keep the rounded corners. */ + outline: var(--focus-outline); + outline-offset: var(--focus-outline-offset); + /* Calculate the difference between the button's border area and the outline + * area. */ + --tor-urlbar-focus-outline-difference: calc( + var(--focus-outline-offset) + + var(--focus-outline-width) + ); + /* For the inline direction, we shrink the padding by the difference, and + * increase the margin by the same amount so that the button text remains in + * the same position. + * For the block direction, the height of the button is flexibly sized with + * the urlbar height, so we should only need to increase the margin. */ + padding-inline: calc( + var(--tor-urlbar-button-inline-padding) + - var(--tor-urlbar-focus-outline-difference) + ); + margin: var(--tor-urlbar-focus-outline-difference); +} + +.tor-urlbar-button:focus-visible > * { + /* Negate the margin that would be added on focus to ensure the button does + * not grow in height. + * Ideally, this should not change anything noticeable, otherwise the text + * could be clipped when focused. */ + margin-block: calc(-1 * var(--tor-urlbar-focus-outline-difference)); +} + +#urlbar[usertyping] .tor-urlbar-button { + /* Hide whilst the user is typing in the url bar. */ + display: none; +} + +/* Make the button look plain like the identity #urlbar-label-box. */ +.tor-urlbar-button.tor-urlbar-button-plain { + background-color: var(--urlbar-box-bgcolor); + color: var(--urlbar-box-text-color); +} + +.tor-urlbar-button.tor-urlbar-button-plain:focus-visible { + outline-color: var(--focus-outline-color); +} + +.tor-urlbar-button.tor-urlbar-button-plain:hover { + background-color: var(--urlbar-box-hover-bgcolor); + color: var(--urlbar-box-hover-text-color); +} + +.tor-urlbar-button.tor-urlbar-button-plain:hover:active { + background-color: var(--urlbar-box-active-bgcolor); + color: var(--urlbar-box-hover-text-color); +} diff --git a/build/application.ini.in b/build/application.ini.in index 6df13230a45b2a86356f4e5a7b189c46f53e44cc..aa02201e619ff78286fa2d4f16f1ae3766daa495 100644 --- a/build/application.ini.in +++ b/build/application.ini.in @@ -52,5 +52,5 @@ ServerURL=@MOZ_CRASHREPORTER_URL@/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSIO #if MOZ_UPDATER [AppUpdate] -URL=https://@MOZ_APPUPDATE_HOST@/update/6/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml +URL=@BB_UPDATER_URL@/%CHANNEL%/%BUILD_TARGET%/%VERSION%/ALL #endif diff --git a/build/moz.build b/build/moz.build index 7bf9c501db06d38f924c26372d4243d448af8d81..27f603d2ff1a653d1ae9720a06bfb99b28f3963a 100644 --- a/build/moz.build +++ b/build/moz.build @@ -75,6 +75,7 @@ if CONFIG["MOZ_APP_BASENAME"]: "MAR_CHANNEL_ID", "MOZ_APP_REMOTINGNAME", "MOZ_CRASHREPORTER_URL", + "BB_UPDATER_URL", ): appini_defines[var] = CONFIG[var] diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure index 247fbab96add196737f2187e26b473baffaf8013..6d813ad07bbcac1caba97ba4770432fa9fa9a8f8 100644 --- a/build/moz.configure/init.configure +++ b/build/moz.configure/init.configure @@ -484,12 +484,16 @@ def split_triplet(triplet, allow_wasi=False): canonical_kernel = "kFreeBSD" elif os.startswith("gnu"): canonical_os = canonical_kernel = "GNU" - elif os.startswith("mingw") or os in ("windows-msvc", "windows-gnu"): + elif os.startswith("mingw") or os in ( + "windows-msvc", + "windows-gnu", + "windows-gnullvm", + ): canonical_os = canonical_kernel = "WINNT" if not os.startswith("mingw"): if os == "windows-msvc": abi = "msvc" - elif os == "windows-gnu": + elif os == "windows-gnu" or os == "windows-gnullvm": abi = "mingw" # Many things down the line are looking for the string "mingw32" # until they are all fixed, we pretend that's the raw os we had @@ -1034,10 +1038,10 @@ option( ) -# set RELEASE_OR_BETA and NIGHTLY_BUILD variables depending on the cycle we're in -# The logic works like this: -# - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD) -# - otherwise, we're building Release/Beta (define RELEASE_OR_BETA) +# Firefox looks for "a" or "a1" in the milestone to detect whether nightly +# features should be enabled. We do not want them, because we want our nightly +# builds to be as close as possible to actual releases. +# So we set always is_release_or_beta to True. @depends( build_environment, build_project, @@ -1098,10 +1102,8 @@ def milestone(build_env, build_project, version_path, as_milestone, _): is_nightly = is_release_or_beta = None - if "a1" in milestone: - is_nightly = True - elif "a" not in milestone: - is_release_or_beta = True + # Do not enable extra nightly features + is_release_or_beta = True major_version = milestone.split(".")[0] m = re.search(r"([ab]\d+)", milestone) @@ -1200,6 +1202,17 @@ set_config("MOZ_UPDATE_CHANNEL", update_channel) set_define("MOZ_UPDATE_CHANNEL", update_channel) +# Add a TOR_BROWSER_NIGHTLY_BUILD flag to use when MOZ_UPDATE_CHANNEL cannot be +# used. For example, for the C++ preprocessor. See tor-browser#41340 +@depends("--enable-update-channel") +def tor_browser_nightly_build(channel): + if channel and channel[0] in ["default", "nightly"]: + return True + + +set_define("TOR_BROWSER_NIGHTLY_BUILD", tor_browser_nightly_build) + + option( env="MOZBUILD_STATE_PATH", nargs=1, diff --git a/build/moz.configure/rust.configure b/build/moz.configure/rust.configure index 1872834802f35978f66fe2082c5d0dcdb34323fe..3cd039b19e5ca4aabadb63d1e40484a57407cb8a 100644 --- a/build/moz.configure/rust.configure +++ b/build/moz.configure/rust.configure @@ -310,9 +310,9 @@ def detect_rustc_target( if host_or_target.abi == "msvc": suffix = "windows-msvc" elif host_or_target.abi == "mingw": - suffix = "windows-gnu" + suffix = "windows-gnullvm" elif compiler_info.type in ("gcc", "clang"): - suffix = "windows-gnu" + suffix = "windows-gnullvm" else: suffix = "windows-msvc" narrowed = [ diff --git a/build/moz.configure/update-programs.configure b/build/moz.configure/update-programs.configure index 4f8bec28704c4ebb08f3982c6ae3cfadaf104e00..4dc34a2764362216150d049bb5b68226c04b5a3b 100644 --- a/build/moz.configure/update-programs.configure +++ b/build/moz.configure/update-programs.configure @@ -214,3 +214,28 @@ option( ) set_config("MOZ_NOTIFICATION_SERVER", True, when="--enable-notification-server") + + +# Enable updater customization for Base Browser-based browsers +# ============================================================================== + +option("--enable-base-browser-update", help="Enable Base Browser update") + +set_config("BASE_BROWSER_UPDATE", True, when="--enable-base-browser-update") +set_define("BASE_BROWSER_UPDATE", True, when="--enable-base-browser-update") + + +# Updater URL +# ============================================================== + +option( + "--with-updater-url", + default="https://aus1.torproject.org/torbrowser/update_3/", + nargs=1, + help="Set the updater URL", +) + +set_config( + "BB_UPDATER_URL", + depends("--with-updater-url")(lambda x: x[0].rstrip("/")), +) diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure index 098cf06a667eef05b9b34ebeb98a51a645c7184a..bef465c95b74c82e97b2750c90428d3ff5cbf6d2 100644 --- a/build/moz.configure/windows.configure +++ b/build/moz.configure/windows.configure @@ -624,11 +624,11 @@ with only_when(depends(c_compiler)(lambda c: c.type == "clang-cl")): add_linker_flag("-LARGEADDRESSAWARE") add_linker_flag("-SAFESEH") + # avoid conficts with std::min/max + set_define("NOMINMAX", True) -set_define("WIN32_LEAN_AND_MEAN", True) -# See http://support.microsoft.com/kb/143208 to use STL -set_define("NOMINMAX", True) +set_define("WIN32_LEAN_AND_MEAN", True) with only_when(target_is_windows & depends(c_compiler)(lambda c: c.type != "clang-cl")): diff --git a/build/variables.py b/build/variables.py index 5996269c03af2a66e4c39fc69b5792d60f83e2e8..3c830cf900920cf125a8c833527108fba91b7afc 100644 --- a/build/variables.py +++ b/build/variables.py @@ -104,7 +104,7 @@ def source_repo_header(output): output.write("#define MOZ_SOURCE_STAMP %s\n" % changeset) if repo and buildconfig.substs.get("MOZ_INCLUDE_SOURCE_INFO"): - source = "%s/rev/%s" % (repo, changeset) + source = "%s/-/commit/%s" % (repo, changeset) output.write("#define MOZ_SOURCE_REPO %s\n" % repo) output.write("#define MOZ_SOURCE_URL %s\n" % source) diff --git a/config/createprecomplete.py b/config/createprecomplete.py index f3ac8c67136b38400b292d22c3ccb0d773346ece..0dd505ba2c35c605492876e97eed57ccee42a672 100644 --- a/config/createprecomplete.py +++ b/config/createprecomplete.py @@ -5,14 +5,23 @@ # update instructions which is used to remove files and directories that are no # longer present in a complete update. The current working directory is used for # the location to enumerate and to create the precomplete file. +# For symlinks, remove instructions are always generated. import io import os +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove all lines in this file that contain: +# TorBrowser/Data + def get_build_entries(root_path): """Iterates through the root_path, creating a list for each file and directory. Excludes any file paths ending with channel-prefs.js. + To support Tor Browser updates, excludes: + TorBrowser/Data/Browser/profiles.ini + TorBrowser/Data/Browser/profile.default/bookmarks.html + TorBrowser/Data/Tor/torrc """ rel_file_path_set = set() rel_dir_path_set = set() @@ -29,6 +38,10 @@ def get_build_entries(root_path): or "/UpdateSettings.framework/" in rel_path_file or rel_path_file.startswith("UpdateSettings.framework/") or "distribution/" in rel_path_file + or rel_path_file == "TorBrowser/Data/Browser/profiles.ini" + or rel_path_file + == "TorBrowser/Data/Browser/profile.default/bookmarks.html" + or rel_path_file == "TorBrowser/Data/Tor/torrc" ): rel_file_path_set.add(rel_path_file) @@ -37,7 +50,10 @@ def get_build_entries(root_path): rel_path_dir = os.path.join(parent_dir_rel_path, dir_name) rel_path_dir = rel_path_dir.replace("\\", "/") + "/" if rel_path_dir.find("distribution/") == -1: - rel_dir_path_set.add(rel_path_dir) + if os.path.islink(rel_path_dir[:-1]): + rel_file_path_set.add(rel_path_dir[:-1]) + else: + rel_dir_path_set.add(rel_path_dir) rel_file_path_list = list(rel_file_path_set) rel_file_path_list.sort(reverse=True) diff --git a/devtools/client/aboutdebugging/src/actions/runtimes.js b/devtools/client/aboutdebugging/src/actions/runtimes.js index 52148f80b2803d75f2f1b84f8379389b68e66a65..543c9a7e5c93fec022f9872def3e6585f8c9e307 100644 --- a/devtools/client/aboutdebugging/src/actions/runtimes.js +++ b/devtools/client/aboutdebugging/src/actions/runtimes.js @@ -59,21 +59,8 @@ const { const CONNECTION_TIMING_OUT_DELAY = 3000; const CONNECTION_CANCEL_DELAY = 13000; -async function getRuntimeIcon(runtime, channel) { - if (runtime.isFenix) { - switch (channel) { - case "release": - case "beta": - return "chrome://devtools/skin/images/aboutdebugging-fenix.svg"; - case "aurora": - default: - return "chrome://devtools/skin/images/aboutdebugging-fenix-nightly.svg"; - } - } - - return channel === "release" || channel === "beta" || channel === "aurora" - ? `chrome://devtools/skin/images/aboutdebugging-firefox-${channel}.svg` - : "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg"; +async function getRuntimeIcon(_runtime, _channel) { + return "chrome://branding/content/about-logo.svg"; } function onRemoteDevToolsClientClosed() { diff --git a/devtools/client/netmonitor/src/components/SecurityState.js b/devtools/client/netmonitor/src/components/SecurityState.js index 74e098d29062b5185fa1d48cf159a52b3f23530d..723c6206d09bb526c05edffd66004d230a6bd09e 100644 --- a/devtools/client/netmonitor/src/components/SecurityState.js +++ b/devtools/client/netmonitor/src/components/SecurityState.js @@ -41,7 +41,7 @@ class SecurityState extends Component { const { securityState, - urlDetails: { isLocal }, + urlDetails: { host, isLocal }, } = item; const iconClassList = ["requests-security-state-icon"]; @@ -50,7 +50,11 @@ class SecurityState extends Component { // Locally delivered files such as http://localhost and file:// paths // are considered to have been delivered securely. - if (isLocal) { + if ( + isLocal || + (host?.endsWith(".onion") && + Services.prefs.getBoolPref("dom.securecontext.allowlist_onions", false)) + ) { realSecurityState = "secure"; } diff --git a/devtools/client/themes/images/aboutdebugging-firefox-logo.svg b/devtools/client/themes/images/aboutdebugging-firefox-logo.svg index fe4d116b16609b1862bc810ec500218316dcf04c..ca682e54e98285b4619a24ce95e085286acd1dfb 100644 --- a/devtools/client/themes/images/aboutdebugging-firefox-logo.svg +++ b/devtools/client/themes/images/aboutdebugging-firefox-logo.svg @@ -1,6 +1,3 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> - <path fill="context-fill #20123a" d="M190.368 150.591c0.157 0.009 0.079 0.003 0 0zm-57.874-28.933c0.158 0.008 0.079 0.003 0 0zm346.228 44.674c-10.445-25.123-31.6-52.248-48.211-60.82 13.52 26.5 21.345 53.093 24.335 72.935 0 0.04 0.015 0.136 0.047 0.4-27.175-67.732-73.254-95.047-110.886-154.512-1.9-3.008-3.805-6.022-5.661-9.2a73.237 73.237 0 0 1-2.646-4.972 43.757 43.757 0 0 1-3.585-9.5 0.625 0.625 0 0 0-0.546-0.644 0.8 0.8 0 0 0-0.451 0c-0.033 0.011-0.084 0.051-0.119 0.065-0.053 0.02-0.12 0.069-0.176 0.095 0.026-0.036 0.083-0.117 0.1-0.135-53.437 31.3-75.587 86.093-81.282 120.97a128.057 128.057 0 0 0-47.624 12.153 6.144 6.144 0 0 0-3.041 7.63 6.034 6.034 0 0 0 8.192 3.525 116.175 116.175 0 0 1 41.481-10.826c0.468-0.033 0.937-0.062 1.405-0.1a117.624 117.624 0 0 1 5.932-0.211 120.831 120.831 0 0 1 34.491 4.777c0.654 0.192 1.295 0.414 1.946 0.616a120.15 120.15 0 0 1 5.539 1.842 121.852 121.852 0 0 1 3.992 1.564c1.074 0.434 2.148 0.868 3.206 1.331a118.453 118.453 0 0 1 4.9 2.307c0.743 0.368 1.485 0.735 2.217 1.117a120.535 120.535 0 0 1 4.675 2.587 107.785 107.785 0 0 1 2.952 1.776 123.018 123.018 0 0 1 42.028 43.477c-12.833-9.015-35.81-17.918-57.947-14.068 86.441 43.214 63.234 192.027-56.545 186.408a106.7 106.7 0 0 1-31.271-6.031 132.461 132.461 0 0 1-7.059-2.886c-1.356-0.618-2.711-1.243-4.051-1.935-29.349-15.168-53.583-43.833-56.611-78.643 0 0 11.093-41.335 79.433-41.335 7.388 0 28.508-20.614 28.9-26.593-0.09-1.953-41.917-18.59-58.223-34.656-8.714-8.585-12.851-12.723-16.514-15.829a71.7 71.7 0 0 0-6.225-4.7 111.335 111.335 0 0 1-0.675-58.733c-24.687 11.242-43.89 29.011-57.849 44.7h-0.111c-9.528-12.067-8.855-51.873-8.312-60.184-0.114-0.516-7.107 3.63-8.024 4.254a175.21 175.21 0 0 0-23.486 20.12 210.5 210.5 0 0 0-22.443 26.913c0 0.012-0.007 0.025-0.011 0.037 0-0.012 0.007-0.025 0.011-0.038a202.837 202.837 0 0 0-32.244 72.81c-0.058 0.265-2.29 10.054-3.92 22.147a265.794 265.794 0 0 0-0.769 5.651c-0.558 3.636-0.992 7.6-1.42 13.767-0.019 0.239-0.031 0.474-0.048 0.712a591.152 591.152 0 0 0-0.481 7.995c0 0.411-0.025 0.816-0.025 1.227 0 132.709 107.6 240.29 240.324 240.29 118.865 0 217.559-86.288 236.882-199.63 0.407-3.075 0.732-6.168 1.092-9.27 4.777-41.21-0.53-84.525-15.588-120.747zm-164.068 72.1z" /> +<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M31 16C31 24.2843 24.2843 31 16 31C7.71573 31 1 24.2843 1 16C1 7.71573 7.71573 1 16 1C24.2843 1 31 7.71573 31 16ZM16 3.69531C22.7957 3.69531 28.3047 9.20431 28.3047 16C28.3047 22.7957 22.7957 28.3047 16 28.3047V26.4297C21.7602 26.4297 26.4297 21.7602 26.4297 16C26.4297 10.2398 21.7602 5.57031 16 5.57031V3.69531ZM16 8.29492C20.2554 8.29492 23.7051 11.7446 23.7051 16C23.7051 20.2554 20.2554 23.7051 16 23.7051V21.8301C19.2199 21.8301 21.8301 19.2199 21.8301 16C21.8301 12.7801 19.2199 10.1699 16 10.1699V8.29492ZM19.1934 16C19.1934 14.2364 17.7636 12.8066 16 12.8066V19.1934C17.7636 19.1934 19.1934 17.7636 19.1934 16Z" fill="context-fill"/> </svg> diff --git a/docshell/base/URIFixup.sys.mjs b/docshell/base/URIFixup.sys.mjs index 6fde38a31094054ed0072a1ee10246ad9773fc68..8c860149b19402f94be8b7bbaffe33ebd4b42db1 100644 --- a/docshell/base/URIFixup.sys.mjs +++ b/docshell/base/URIFixup.sys.mjs @@ -934,6 +934,10 @@ function fileURIFixup(uriString) { } else { // UNIX: Check if it starts with "/" or "~". attemptFixup = /^[~/]/.test(uriString); + const originalHome = Services.env.get("BB_ORIGINAL_HOME"); + if (originalHome && (uriString === "~" || uriString.startsWith("~/"))) { + path = originalHome + path.substring(1); + } } if (attemptFixup) { try { diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp index b21078b00b14cdf2b66985e0caabebcf4884f291..985894132698fcb5b8373a1bc570460731ebfe70 100644 --- a/docshell/base/nsAboutRedirector.cpp +++ b/docshell/base/nsAboutRedirector.cpp @@ -139,8 +139,10 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::IS_SECURE_CHROME_UI}, +#ifndef BASE_BROWSER_VERSION {"mozilla", "chrome://global/content/mozilla.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT}, +#endif #if !defined(ANDROID) && !defined(XP_WIN) {"webauthn", "chrome://global/content/aboutWebauthn.html", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, @@ -185,25 +187,36 @@ static const RedirEntry kRedirMap[] = { {"windows-messages", "chrome://global/content/aboutWindowsMessages.html", nsIAboutModule::ALLOW_SCRIPT}, #endif -#ifndef MOZ_GLEAN_ANDROID +#ifdef MOZ_TELEMETRY_REPORTING +# ifndef MOZ_GLEAN_ANDROID {"glean", "chrome://global/content/aboutGlean.html", -# if !defined(NIGHTLY_BUILD) && defined(MOZILLA_OFFICIAL) +# if !defined(NIGHTLY_BUILD) && defined(MOZILLA_OFFICIAL) nsIAboutModule::HIDE_FROM_ABOUTABOUT | -# endif +# endif nsIAboutModule::ALLOW_SCRIPT}, -#endif +# endif {"telemetry", "chrome://global/content/aboutTelemetry.xhtml", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, +#endif + {"torconnect", "chrome://global/content/torconnect/aboutTorConnect.html", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | + nsIAboutModule::HIDE_FROM_ABOUTABOUT | + nsIAboutModule::IS_SECURE_CHROME_UI}, {"translations", "chrome://global/content/translations/translations.html", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, +#ifndef BASE_BROWSER_VERSION {"url-classifier", "chrome://global/content/aboutUrlClassifier.xhtml", nsIAboutModule::ALLOW_SCRIPT}, +#endif +#ifdef MOZ_WEBRTC {"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.html", nsIAboutModule::ALLOW_SCRIPT}, +#endif {"crashparent", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT}, {"crashcontent", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT | @@ -211,7 +224,11 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::URI_MUST_LOAD_IN_CHILD}, {"crashgpu", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT}, - {"crashextensions", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT}}; + {"crashextensions", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT}, + {"tor", "chrome://browser/content/abouttor/aboutTor.html", + nsIAboutModule::URI_MUST_LOAD_IN_CHILD | + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}}; static const int kRedirTotal = mozilla::ArrayLength(kRedirMap); NS_IMETHODIMP diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 9eface9e97e6a4c8397ae5a0a67c84b45453a612..939efb840b4cf94ad32ec259a87c7c57d3d32541 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -3521,6 +3521,8 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, } } else { // Errors requiring simple formatting + bool isOnionAuthError = false; + bool isOnionError = false; switch (aError) { case NS_ERROR_MALFORMED_URI: // URI is malformed @@ -3602,10 +3604,61 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, // HTTP/2 or HTTP/3 stack detected a protocol error error = "networkProtocolError"; break; - + case NS_ERROR_TOR_ONION_SVC_NOT_FOUND: + error = "onionServices.descNotFound"; + isOnionError = true; + break; + case NS_ERROR_TOR_ONION_SVC_IS_INVALID: + error = "onionServices.descInvalid"; + isOnionError = true; + break; + case NS_ERROR_TOR_ONION_SVC_INTRO_FAILED: + error = "onionServices.introFailed"; + isOnionError = true; + break; + case NS_ERROR_TOR_ONION_SVC_REND_FAILED: + error = "onionServices.rendezvousFailed"; + isOnionError = true; + break; + case NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH: + error = "onionServices.clientAuthMissing"; + isOnionError = true; + isOnionAuthError = true; + break; + case NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH: + error = "onionServices.clientAuthIncorrect"; + isOnionError = true; + isOnionAuthError = true; + break; + case NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS: + error = "onionServices.badAddress"; + isOnionError = true; + break; + case NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT: + error = "onionServices.introTimedOut"; + isOnionError = true; + break; default: break; } + + // The presence of aFailedChannel indicates that we arrived here due to a + // failed connection attempt. Note that we will arrive here a second time + // if the user cancels the Tor client auth prompt, but in that case we + // will not have a failed channel and therefore we will not prompt again. + if (isOnionAuthError && aFailedChannel) { + // Display about:neterror with a style emulating about:blank while the + // Tor client auth prompt is open. Do not use about:blank directly: it + // will mess with the failed channel information persistence! + cssClass.AssignLiteral("onionAuthPrompt"); + } + if (isOnionError) { + // DisplayLoadError requires a non-empty messageStr to proceed and call + // LoadErrorPage. We use a blank space. + if (messageStr.IsEmpty()) { + messageStr.AssignLiteral(u" "); + } + } } nsresult delegateErrorCode = aError; @@ -6125,6 +6178,7 @@ nsresult nsDocShell::FilterStatusForErrorPage( aStatus == NS_ERROR_FILE_ACCESS_DENIED || aStatus == NS_ERROR_CORRUPTED_CONTENT || aStatus == NS_ERROR_INVALID_CONTENT_ENCODING || + NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_TOR || NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) { // Errors to be shown for any frame return aStatus; @@ -7826,6 +7880,35 @@ nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType, FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags); } + // Arrange to show a Tor onion service client authentication prompt if + // appropriate. + if ((mLoadType == LOAD_ERROR_PAGE) && failedChannel) { + nsresult status = NS_OK; + if (NS_SUCCEEDED(failedChannel->GetStatus(&status)) && + ((status == NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH) || + (status == NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH))) { + nsAutoCString onionHost; + failedURI->GetHost(onionHost); + const char* topic = (status == NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH) + ? "tor-onion-services-clientauth-missing" + : "tor-onion-services-clientauth-incorrect"; + if (XRE_IsContentProcess()) { + nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); + if (browserChild) { + static_cast<BrowserChild*>(browserChild.get()) + ->SendShowOnionServicesAuthPrompt(onionHost, nsCString(topic)); + } + } else { + nsCOMPtr<nsPIDOMWindowOuter> browserWin = GetWindow(); + nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); + if (browserWin && obsSvc) { + obsSvc->NotifyObservers(browserWin, topic, + NS_ConvertUTF8toUTF16(onionHost).get()); + } + } + } + } + return NS_OK; } diff --git a/docshell/build/components.conf b/docshell/build/components.conf index c8ea67703cdf7b1288f69eda67f63db642f37d15..2dd047845b77eecc02e22f96a4087c250036c076 100644 --- a/docshell/build/components.conf +++ b/docshell/build/components.conf @@ -22,7 +22,7 @@ about_pages = [ 'logging', 'logo', 'memory', - 'mozilla', + # Removed 'mozilla'. tor-browser#42831. 'neterror', 'networking', 'performance', @@ -30,20 +30,24 @@ about_pages = [ 'serviceworkers', 'srcdoc', 'support', - 'telemetry', + 'torconnect', 'translations', - 'url-classifier', - 'webrtc', + 'tor', + # Removed 'url-classifier'. tor-browser#42831. ] if defined('MOZ_CRASHREPORTER'): about_pages.append('crashes') +if defined('MOZ_TELEMETRY_REPORTING'): + about_pages.append('telemetry') +if defined('MOZ_WEBRTC'): + about_pages.append('webrtc') if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android': about_pages.append('profiles') if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] == 'windows': about_pages.append('third-party') about_pages.append('windows-messages') -if not defined('MOZ_GLEAN_ANDROID'): +if defined('MOZ_TELEMETRY_REPORTING') and not defined('MOZ_GLEAN_ANDROID'): about_pages.append('glean') if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android' and buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'windows': about_pages.append('webauthn') diff --git a/dom/base/ContentAreaDropListener.sys.mjs b/dom/base/ContentAreaDropListener.sys.mjs index 9f7bc500a1eadc9062abb91db73788af091d51bd..ff3ffc1c76034acbb8629f58da7f912f7e5d1d8d 100644 --- a/dom/base/ContentAreaDropListener.sys.mjs +++ b/dom/base/ContentAreaDropListener.sys.mjs @@ -2,6 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + OpaqueDrag: "resource://gre/modules/DragDropFilter.sys.mjs", +}); + // This component is used for handling dragover and drop of urls. // // It checks to see whether a drop of a url is allowed. For instance, a url @@ -40,10 +46,15 @@ ContentAreaDropListener.prototype = { } } - type = "text/x-moz-url"; - if (types.contains(type)) { + for (let type of ["text/x-moz-url", "application/x-torbrowser-opaque"]) { + if (!types.contains(type)) { + continue; + } data = dt.mozGetDataAt(type, i); if (data) { + if (type === "application/x-torbrowser-opaque") { + ({ type, value: data = "" } = lazy.OpaqueDrag.retrieve(data)); + } let lines = data.split("\n"); for (let i = 0, length = lines.length; i < length; i += 2) { this._addLink(links, lines[i], lines[i + 1], type); @@ -236,6 +247,7 @@ ContentAreaDropListener.prototype = { if ( !types.includes("application/x-moz-file") && !types.includes("text/x-moz-url") && + !types.includes("application/x-torbrowser-opaque") && !types.includes("text/uri-list") && !types.includes("text/x-moz-text-internal") && !types.includes("text/plain") diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index b460181916b4f4edfc1a56e8b06f6506bd81465b..4f15274d3fb7bc2b1e90b10e8578048d9d356326 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -2992,6 +2992,7 @@ void Document::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup, // mDocumentURI. mDocumentBaseURI = nullptr; mChromeXHRDocBaseURI = nullptr; + mOnionLocationURI = nullptr; if (aLoadGroup) { nsCOMPtr<nsIInterfaceRequestor> callbacks; @@ -7079,6 +7080,57 @@ void Document::GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const { } } +static bool IsValidOnionLocation(nsIURI* aDocumentURI, + nsIURI* aOnionLocationURI) { + if (!aDocumentURI || !aOnionLocationURI) { + return false; + } + + // Current URI + nsAutoCString host; + if (!aDocumentURI->SchemeIs("https")) { + return false; + } + NS_ENSURE_SUCCESS(aDocumentURI->GetAsciiHost(host), false); + if (StringEndsWith(host, ".onion"_ns)) { + // Already in the .onion site + return false; + } + + // Target URI + if (!aOnionLocationURI->SchemeIs("http") && + !aOnionLocationURI->SchemeIs("https")) { + return false; + } + nsCOMPtr<nsIEffectiveTLDService> eTLDService = + do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); + if (!eTLDService) { + NS_ENSURE_SUCCESS(aOnionLocationURI->GetAsciiHost(host), false); + // This should not happen, but in the unlikely case, still check if it is a + // .onion and in case allow it. + return StringEndsWith(host, ".onion"_ns); + } + NS_ENSURE_SUCCESS(eTLDService->GetBaseDomain(aOnionLocationURI, 0, host), + false); + if (!StringEndsWith(host, ".onion"_ns)) { + return false; + } + + // Ignore v2 + if (host.Length() == 22) { + const char* cur = host.BeginWriting(); + // We have already checked that it ends by ".onion" + const char* end = host.EndWriting() - 6; + bool base32 = true; + for (; cur < end && base32; ++cur) { + base32 = isalpha(*cur) || ('2' <= *cur && *cur <= '7'); + } + return !base32; + } + + return true; +} + void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) { if (!aHeaderField) { NS_ERROR("null headerField"); @@ -7169,6 +7221,14 @@ void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) { if (aHeaderField == nsGkAtoms::handheldFriendly) { mViewportType = Unknown; } + + if (aHeaderField == nsGkAtoms::headerOnionLocation && !aData.IsEmpty()) { + nsCOMPtr<nsIURI> onionURI; + if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(onionURI), aData)) && + IsValidOnionLocation(Document::GetDocumentURI(), onionURI)) { + mOnionLocationURI = onionURI; + } + } } void Document::SetEarlyHints( @@ -11392,7 +11452,7 @@ void Document::RetrieveRelevantHeaders(nsIChannel* aChannel) { static const char* const headers[] = { "default-style", "content-style-type", "content-language", "content-disposition", "refresh", "x-dns-prefetch-control", - "x-frame-options", "origin-trial", + "x-frame-options", "origin-trial", "onion-location", // add more http headers if you need // XXXbz don't add content-location support without reading bug // 238654 and its dependencies/dups first. @@ -16737,6 +16797,12 @@ bool Document::RecomputeResistFingerprinting() { } bool Document::ShouldResistFingerprinting(RFPTarget aTarget) const { +#ifdef ANDROID + if (aTarget == RFPTarget::FontVisibilityBaseSystem || + aTarget == RFPTarget::FontVisibilityLangPack) { + return false; + } +#endif return mShouldResistFingerprinting && nsRFPService::IsRFPEnabledFor(this->IsInPrivateBrowsing(), aTarget, mOverriddenFingerprintingSettings); diff --git a/dom/base/Document.h b/dom/base/Document.h index 9b748acbce8e4dd1c1393aa5d26170747ec48228..cec02455319d89ae158290d3017ad173a08f2e65 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -3387,6 +3387,7 @@ class Document : public nsINode, void ReleaseCapture() const; void MozSetImageElement(const nsAString& aImageElementId, Element* aElement); nsIURI* GetDocumentURIObject() const; + nsIURI* GetOnionLocationURI() const { return mOnionLocationURI; } // Not const because all the fullscreen goop is not const const char* GetFullscreenError(CallerType); bool FullscreenEnabled(CallerType aCallerType) { @@ -4517,6 +4518,7 @@ class Document : public nsINode, nsCOMPtr<nsIURI> mChromeXHRDocURI; nsCOMPtr<nsIURI> mDocumentBaseURI; nsCOMPtr<nsIURI> mChromeXHRDocBaseURI; + nsCOMPtr<nsIURI> mOnionLocationURI; // The base domain of the document for third-party checks. nsCString mBaseDomain; diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 80df23b73f132c2b6ec99df1cb219878d6ea8639..d00181060fa49671f6b7956dd9c612ec3ad212af 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -2756,6 +2756,18 @@ void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting( *aOutputHeight = resultHeight; } +bool nsContentUtils::ShouldRoundWindowSizeForResistingFingerprinting() { + return !( + Preferences::GetBool("privacy.resistFingerprinting.letterboxing", + false) && + // We want to round window size at least once in the browser's life time: + // AppWindow::ForceRoundedDimensions() will set this preference to true. + Preferences::GetBool( + "privacy.resistFingerprinting.letterboxing.didForceSize", false) && + Preferences::GetBool( + "privacy.resistFingerprinting.letterboxing.rememberSize", false)); +} + bool nsContentUtils::ThreadsafeIsCallerChrome() { return NS_IsMainThread() ? IsCallerChrome() : IsCurrentThreadRunningChromeWorker(); @@ -10029,6 +10041,25 @@ bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) { return principal->GetIsOriginPotentiallyTrustworthy(); } +/* static */ bool nsContentUtils::DocumentHasOnionURI(Document* aDocument) { + if (!aDocument) { + return false; + } + + nsIURI* uri = aDocument->GetDocumentURI(); + if (!uri) { + return false; + } + + nsAutoCString host; + if (NS_SUCCEEDED(uri->GetHost(host))) { + bool hasOnionURI = StringEndsWith(host, ".onion"_ns); + return hasOnionURI; + } + + return false; +} + /* static */ void nsContentUtils::TryToUpgradeElement(Element* aElement) { NodeInfo* nodeInfo = aElement->NodeInfo(); diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index d9556910b2e27aebd648835353a6843347d6f8ac..001d0386e15fb2b020be23d0718b93e21565ea50 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -409,6 +409,10 @@ class nsContentUtils { bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth, int32_t* aOutputHeight); + // Tell if we actually want to round size of new windows for RFP, + // depending on letterboxing status and user's preference. + static bool ShouldRoundWindowSizeForResistingFingerprinting(); + /** * Returns the parent node of aChild crossing document boundaries, but skips * any cross-process parent frames and continues with the nearest in-process @@ -3115,6 +3119,11 @@ class nsContentUtils { */ static bool HttpsStateIsModern(Document* aDocument); + /** + * Returns true of the document's URI is a .onion + */ + static bool DocumentHasOnionURI(Document* aDocument); + /** * Returns true if the channel is for top-level window and is over secure * context. diff --git a/dom/base/nsCopySupport.cpp b/dom/base/nsCopySupport.cpp index 29451898207983f5635a547a29b0c6ae51529357..581dd617358df167393ef100bf14e912755a8d0a 100644 --- a/dom/base/nsCopySupport.cpp +++ b/dom/base/nsCopySupport.cpp @@ -288,6 +288,7 @@ static nsresult CreateTransferable( NS_ENSURE_SUCCESS(rv, rv); } +#if !defined(BASE_BROWSER_VERSION) // Try and get source URI of the items that are being dragged nsIURI* uri = aDocument.GetDocumentURI(); if (uri) { @@ -308,6 +309,7 @@ static nsresult CreateTransferable( NS_ENSURE_SUCCESS(rv, rv); } } +#endif } else { if (!aEncodedDocumentWithContext.mSerializationForTextUnicode.IsEmpty()) { // Add the unicode DataFlavor to the transferable diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index 8973a1e401670d32808136d47ab8efb0e396a549..b877931f22bdabe0264b0e9849e230df1837820c 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -1885,7 +1885,8 @@ bool nsGlobalWindowOuter::ComputeIsSecureContext(Document* aDocument, return false; } - if (nsContentUtils::HttpsStateIsModern(aDocument)) { + if (nsContentUtils::HttpsStateIsModern(aDocument) || + nsContentUtils::DocumentHasOnionURI(aDocument)) { return true; } @@ -5987,6 +5988,9 @@ void nsGlobalWindowOuter::CloseOuter(bool aTrustedCaller) { NS_ENSURE_SUCCESS_VOID(rv); if (!StringBeginsWith(url, u"about:neterror"_ns) && + // we want about:torconnect pages to be able to close themselves after + // bootstrap + !StringBeginsWith(url, u"about:torconnect"_ns) && !mBrowsingContext->GetTopLevelCreatedByWebContent() && !aTrustedCaller && !IsOnlyTopLevelDocumentInSHistory()) { bool allowClose = diff --git a/dom/base/nsNodeInfoManager.cpp b/dom/base/nsNodeInfoManager.cpp index 47b1636f2a080462b785d13fc93520b7c0a22d75..348416f37259467aa76dead70ffb20759eea2807 100644 --- a/dom/base/nsNodeInfoManager.cpp +++ b/dom/base/nsNodeInfoManager.cpp @@ -344,6 +344,16 @@ void nsNodeInfoManager::RemoveNodeInfo(NodeInfo* aNodeInfo) { } static bool IsSystemOrAddonOrAboutPrincipal(nsIPrincipal* aPrincipal) { +#ifdef ANDROID + if (aPrincipal->SchemeIs("resource")) { + nsAutoCString spec; + aPrincipal->GetAsciiSpec(spec); + if (StringBeginsWith(spec, "resource://android/assets/"_ns)) { + return true; + } + } +#endif + return aPrincipal->IsSystemPrincipal() || BasePrincipal::Cast(aPrincipal)->AddonPolicy() || // NOTE: about:blank and about:srcdoc inherit the principal of their diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp index a1e5c4792d3613ba56a4c50eb88be44ec9d71a04..f9157fb58ed043584e642db98a0d010d21f7586b 100644 --- a/dom/canvas/ClientWebGLContext.cpp +++ b/dom/canvas/ClientWebGLContext.cpp @@ -5230,6 +5230,14 @@ bool ClientWebGLContext::ReadPixels_SharedPrecheck( return false; } + // Security check passed, but don't let content readPixel calls through for + // now, if Resist Fingerprinting Mode is enabled. + if (ShouldResistFingerprinting(RFPTarget::CanvasRandomization)) { + JsWarning("readPixels: Not allowed in Resist Fingerprinting Mode"); + out_error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return false; + } + return true; } diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 6df1a568f3f5364b5172fca5dcc4da41a2b37d2c..6fbd0b5bb0af0bec92e183686cbf1a45a538c099 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -4101,6 +4101,27 @@ mozilla::ipc::IPCResult BrowserParent::RecvShowCanvasPermissionPrompt( return IPC_OK(); } +mozilla::ipc::IPCResult BrowserParent::RecvShowOnionServicesAuthPrompt( + const nsCString& aOnionName, const nsCString& aTopic) { + nsCOMPtr<nsIBrowser> browser = + mFrameElement ? mFrameElement->AsBrowser() : nullptr; + if (!browser) { + // If the tab is being closed, the browser may not be available. + // In this case we can ignore the request. + return IPC_OK(); + } + nsCOMPtr<nsIObserverService> os = services::GetObserverService(); + if (!os) { + return IPC_FAIL_NO_REASON(this); + } + nsresult rv = os->NotifyObservers(browser, aTopic.get(), + NS_ConvertUTF8toUTF16(aOnionName).get()); + if (NS_FAILED(rv)) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + mozilla::ipc::IPCResult BrowserParent::RecvVisitURI( nsIURI* aURI, nsIURI* aLastVisitedURI, const uint32_t& aFlags, const uint64_t& aBrowserId) { diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index 58dee684f4648843e04731820ec6ff6695c33b98..cf6748857c89d3a756a5782eafd32a02ecb1634d 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -747,6 +747,9 @@ class BrowserParent final : public PBrowserParent, mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt( const nsCString& aOrigin, const bool& aHideDoorHanger); + mozilla::ipc::IPCResult RecvShowOnionServicesAuthPrompt( + const nsCString& aOnionName, const nsCString& aTopic); + mozilla::ipc::IPCResult RecvSetSystemFont(const nsCString& aFontName); mozilla::ipc::IPCResult RecvGetSystemFont(nsCString* aFontName); diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 14406ad0a6cc48b55305fca9e727b87313c53feb..cbf13fd6161a6320c74d8714dc8e232f9cdd46a5 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -566,6 +566,15 @@ parent: */ async RequestPointerLock() returns (nsCString error); + /** + * This function is used to notify the parent that it should display a + * onion services client authentication prompt. + * + * @param aOnionHost The hostname of the .onion that needs authentication. + * @param aTopic The reason for the prompt. + */ + async ShowOnionServicesAuthPrompt(nsCString aOnionHost, nsCString aTopic); + both: /** * informs that a pointer lock has released. diff --git a/dom/ipc/WindowGlobalActor.cpp b/dom/ipc/WindowGlobalActor.cpp index 20dd775bad95efc73eafcc21a0456093c93a2578..d5717154abf1075efc2a42d95d07aab2501b91a2 100644 --- a/dom/ipc/WindowGlobalActor.cpp +++ b/dom/ipc/WindowGlobalActor.cpp @@ -21,6 +21,7 @@ #include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowGlobalChild.h" #include "mozilla/dom/WindowGlobalParent.h" +#include "mozilla/dom/nsMixedContentBlocker.h" #include "nsGlobalWindowInner.h" #include "nsNetUtil.h" @@ -145,7 +146,9 @@ WindowGlobalInit WindowGlobalActor::WindowInitializer( // Init Mixed Content Fields nsCOMPtr<nsIURI> innerDocURI = NS_GetInnermostURI(doc->GetDocumentURI()); fields.Get<Indexes::IDX_IsSecure>() = - innerDocURI && innerDocURI->SchemeIs("https"); + innerDocURI && + (innerDocURI->SchemeIs("https") || + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innerDocURI)); nsCOMPtr<nsITransportSecurityInfo> securityInfo; if (nsCOMPtr<nsIChannel> channel = doc->GetChannel()) { diff --git a/dom/ipc/WindowGlobalChild.cpp b/dom/ipc/WindowGlobalChild.cpp index 356f12605e1213e255f84a3eaf884f6cd7c74406..622454ae522fe5aeb36f67e615ec886902e637f3 100644 --- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -45,6 +45,8 @@ #include "nsIURIMutator.h" #include "nsURLHelper.h" +#include "mozilla/dom/nsMixedContentBlocker.h" + using namespace mozilla::ipc; using namespace mozilla::dom::ipc; @@ -235,7 +237,9 @@ void WindowGlobalChild::OnNewDocument(Document* aDocument) { nsCOMPtr<nsIURI> innerDocURI = NS_GetInnermostURI(aDocument->GetDocumentURI()); if (innerDocURI) { - txn.SetIsSecure(innerDocURI->SchemeIs("https")); + txn.SetIsSecure( + innerDocURI->SchemeIs("https") || + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innerDocURI)); } MOZ_DIAGNOSTIC_ASSERT(mDocumentPrincipal->GetIsLocalIpAddress() == diff --git a/dom/locales/moz.build b/dom/locales/moz.build index bf89d214f398444cb7ff78115d22fbf3d353643f..321c14776a47848a44941fdc4241b09dfd9253ff 100644 --- a/dom/locales/moz.build +++ b/dom/locales/moz.build @@ -57,6 +57,10 @@ RESOURCE_FILES.locale.layout += [ "en-US/chrome/layout/xmlparser.properties", ] +RESOURCE_FILES.locale.xslt += [ + "en-US/chrome/xslt/xslt.properties", +] + RESOURCE_FILES.locale.dom += [ "en-US/chrome/dom/dom.properties", ] diff --git a/dom/media/systemservices/video_engine/desktop_device_info.cc b/dom/media/systemservices/video_engine/desktop_device_info.cc index 52d8656c0f246904d58258980cd28bb4b3be9c21..892f8d25cd69b39976a6916cd69f83fb2feb7383 100644 --- a/dom/media/systemservices/video_engine/desktop_device_info.cc +++ b/dom/media/systemservices/video_engine/desktop_device_info.cc @@ -25,7 +25,7 @@ namespace webrtc { void DesktopSource::setScreenId(ScreenId aId) { mScreenId = aId; } void DesktopSource::setName(nsCString&& aName) { mName = std::move(aName); } void DesktopSource::setUniqueId(nsCString&& aId) { mUniqueId = std::move(aId); } -void DesktopSource::setPid(const int aPid) { mPid = aPid; } +void DesktopSource::setPid(const pid_t aPid) { mPid = aPid; } ScreenId DesktopSource::getScreenId() const { return mScreenId; } const nsCString& DesktopSource::getName() const { return mName; } diff --git a/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp b/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp index 19161d4d70b1314238ac1b1c5f9a8a8bb3850ae6..19b6613d7e02fcacc8c5f753729cbbe5d519e800 100644 --- a/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp +++ b/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp @@ -106,8 +106,8 @@ #endif // for ntohs -#ifdef _MSC_VER -# include "Winsock2.h" +#ifdef WIN32 +# include "winsock2.h" #else # include <netinet/in.h> #endif diff --git a/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp b/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp index 0b76757c444b6d0742d9b254410e7cdc63069ab4..ea75ebec5ae87477ba8905e5f298a92a242fc568 100644 --- a/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp +++ b/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp @@ -4,6 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <string> #include "nsCRT.h" #include "sdp/RsdparsaSdpAttributeList.h" diff --git a/dom/media/webrtc/transport/nrinterfaceprioritizer.cpp b/dom/media/webrtc/transport/nrinterfaceprioritizer.cpp index 76e2f00cb0a35e9d62b7511618f34b757c1b3c8c..025b030cd5dbec7b89faf34f4e104fb733ed4b83 100644 --- a/dom/media/webrtc/transport/nrinterfaceprioritizer.cpp +++ b/dom/media/webrtc/transport/nrinterfaceprioritizer.cpp @@ -41,9 +41,9 @@ class LocalAddress { } addr_ = buf; - is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0; - estimated_speed_ = local_addr.interface.estimated_speed; - type_preference_ = GetNetworkTypePreference(local_addr.interface.type); + is_vpn_ = (local_addr.iface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0; + estimated_speed_ = local_addr.iface.estimated_speed; + type_preference_ = GetNetworkTypePreference(local_addr.iface.type); ip_version_ = local_addr.addr.ip_version; return true; } diff --git a/dom/media/webrtc/transport/sigslot.h b/dom/media/webrtc/transport/sigslot.h index 448e8137fec71b6167a884407cb03be9644bdce8..b5a74e94cec8796a39dd27f90c3b474ad3484b3d 100644 --- a/dom/media/webrtc/transport/sigslot.h +++ b/dom/media/webrtc/transport/sigslot.h @@ -114,7 +114,8 @@ # define WIN32_LEAN_AND_MEAN # endif # include "rtc_base/win32.h" -#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) +#elif (defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)) && \ + !defined(__MINGW32__) # define _SIGSLOT_HAS_POSIX_THREADS # include <pthread.h> #else diff --git a/dom/media/webrtc/transport/test/ice_unittest.cpp b/dom/media/webrtc/transport/test/ice_unittest.cpp index 22e99b85b62ebe895bcb89f9edcbc0ee7c2be1a3..93d5fb0e781bc83df54053cf89a182cab021264f 100644 --- a/dom/media/webrtc/transport/test/ice_unittest.cpp +++ b/dom/media/webrtc/transport/test/ice_unittest.cpp @@ -1964,8 +1964,8 @@ class WebRtcIcePrioritizerTest : public StunTest { std::string str_addr = "10.0.0." + num; std::string ifname = "eth" + num; nr_local_addr local_addr; - local_addr.interface.type = type; - local_addr.interface.estimated_speed = estimated_speed; + local_addr.iface.type = type; + local_addr.iface.estimated_speed = estimated_speed; int r = nr_str_port_to_transport_addr(str_addr.c_str(), 0, IPPROTO_UDP, &(local_addr.addr)); @@ -2902,8 +2902,8 @@ TEST_F(WebRtcIceConnectTest, // prepare a fake wifi interface nr_local_addr wifi_addr; - wifi_addr.interface.type = NR_INTERFACE_TYPE_WIFI; - wifi_addr.interface.estimated_speed = 1000; + wifi_addr.iface.type = NR_INTERFACE_TYPE_WIFI; + wifi_addr.iface.estimated_speed = 1000; int r = nr_str_port_to_transport_addr(FAKE_WIFI_ADDR, 0, IPPROTO_UDP, &(wifi_addr.addr)); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.c b/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.c index a0896d5e9d8b1b6a8db49e8d09adf2306292ac2f..3356b1f3a507eca4d497d41f17940e91ba33e46b 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.c @@ -44,7 +44,7 @@ int nr_local_addr_copy(nr_local_addr *to, nr_local_addr *from) if (r=nr_transport_addr_copy(&(to->addr), &(from->addr))) { ABORT(r); } - to->interface = from->interface; + to->iface = from->iface; to->flags = from->flags; _status=0; @@ -54,7 +54,7 @@ int nr_local_addr_copy(nr_local_addr *to, nr_local_addr *from) int nr_local_addr_fmt_info_string(nr_local_addr *addr, char *buf, int len) { - int addr_type = addr->interface.type; + int addr_type = addr->iface.type; const char *vpn = (addr_type & NR_INTERFACE_TYPE_VPN) ? "VPN on " : ""; const char *type = (addr_type & NR_INTERFACE_TYPE_WIRED) ? "wired" : @@ -63,7 +63,7 @@ int nr_local_addr_fmt_info_string(nr_local_addr *addr, char *buf, int len) "unknown"; snprintf(buf, len, "%s%s, estimated speed: %d kbps %s", - vpn, type, addr->interface.estimated_speed, + vpn, type, addr->iface.estimated_speed, (addr->flags & NR_ADDR_FLAG_TEMPORARY ? "temporary" : "")); buf[len - 1] = '\0'; return (0); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.h b/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.h index fb963e1115733b12ebf674ef485415a84cbd4899..5ef40ae4fb47139ed01d7dbe1b32a0f32bc29880 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/local_addr.h @@ -51,7 +51,7 @@ typedef struct nr_interface_ { typedef struct nr_local_addr_ { nr_transport_addr addr; - nr_interface interface; + nr_interface iface; #define NR_ADDR_FLAG_TEMPORARY 0x1 int flags; } nr_local_addr; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c index 8d22e5979ea389d14deb3c6f165d7aa70af3febc..a512917d01c826e53fa1e56b6207f0b10e9c460c 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c @@ -139,7 +139,7 @@ stun_convert_netlink(nr_local_addr *addr, struct ifaddrmsg *address_msg, struct int flags = get_siocgifflags(addr); if (flags & IFF_POINTOPOINT) { - addr->interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; + addr->iface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; /* TODO (Bug 896913): find backend network type of this VPN */ } @@ -162,11 +162,11 @@ stun_convert_netlink(nr_local_addr *addr, struct ifaddrmsg *address_msg, struct { /* For wireless network, we won't get ethtool, it's a wired * connection */ - addr->interface.type = NR_INTERFACE_TYPE_WIRED; + addr->iface.type = NR_INTERFACE_TYPE_WIRED; #ifdef DONT_HAVE_ETHTOOL_SPEED_HI - addr->interface.estimated_speed = ecmd.speed; + addr->iface.estimated_speed = ecmd.speed; #else - addr->interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; + addr->iface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; #endif } @@ -174,15 +174,15 @@ stun_convert_netlink(nr_local_addr *addr, struct ifaddrmsg *address_msg, struct e = ioctl(s, SIOCGIWRATE, &wrq); if (e == 0) { - addr->interface.type = NR_INTERFACE_TYPE_WIFI; - addr->interface.estimated_speed = wrq.u.bitrate.value / 1000; + addr->iface.type = NR_INTERFACE_TYPE_WIFI; + addr->iface.estimated_speed = wrq.u.bitrate.value / 1000; } close(s); #else - addr->interface.type = NR_INTERFACE_TYPE_UNKNOWN; - addr->interface.estimated_speed = 0; + addr->iface.type = NR_INTERFACE_TYPE_UNKNOWN; + addr->iface.estimated_speed = 0; #endif return 0; } diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c index a1b0cd9f0aba2b780d9e3a32238116595e861039..6af7901fddea7d455f66c8efd333e083a3f537f2 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c @@ -174,14 +174,14 @@ stun_getaddrs_filtered(nr_local_addr addrs[], int maxaddrs, int *count) strlcpy(addrs[n].addr.ifname, hex_hashed_ifname, sizeof(addrs[n].addr.ifname)); if (tmpAddress->IfType == IF_TYPE_ETHERNET_CSMACD) { - addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED; + addrs[n].iface.type = NR_INTERFACE_TYPE_WIRED; } else if (tmpAddress->IfType == IF_TYPE_IEEE80211) { /* Note: this only works for >= Win Vista */ - addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI; + addrs[n].iface.type = NR_INTERFACE_TYPE_WIFI; } else { - addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; + addrs[n].iface.type = NR_INTERFACE_TYPE_UNKNOWN; } - addrs[n].interface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000; + addrs[n].iface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000; if (stun_win32_address_temp_v6(u)) { addrs[n].flags |= NR_ADDR_FLAG_TEMPORARY; } diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c index 51f72f4179a629984827166d18afb17dbf1801cb..7472c2db81dc92884c8583838bd005c49e7ba565 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c @@ -92,7 +92,7 @@ nr_stun_filter_addrs_for_ifname(nr_local_addr src[], const int src_begin, const if (src[i].addr.ip_version == NR_IPV6) { if (nr_transport_addr_is_teredo(&src[i].addr)) { - src[i].interface.type |= NR_INTERFACE_TYPE_TEREDO; + src[i].iface.type |= NR_INTERFACE_TYPE_TEREDO; /* Prefer teredo over mac-based address. Probably will never see * both. */ filter_mac_ipv6 = 1; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c index bb47cda879bfaeed9fd75daf68fd53bf29970373..0206302fa23c196f9e2da47db89d75753f7ad206 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c @@ -46,7 +46,7 @@ #include <string.h> #include <errno.h> -#ifndef _MSC_VER +#ifndef WIN32 #include <strings.h> #include <syslog.h> #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c index 3134ad15361987b016bdad9e2c3b58b1dde572a9..ae802903e7c79b317eb0ab982cecc004d1a320b6 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c @@ -44,7 +44,7 @@ #include <assert.h> #include <string.h> -#ifndef _MSC_VER +#ifndef WIN32 #include <strings.h> #include <sys/param.h> #include <netinet/in.h> diff --git a/dom/security/nsContentSecurityUtils.cpp b/dom/security/nsContentSecurityUtils.cpp index 0a88c9584b40294620747e0d9738bf8b8a883600..453bce3ee84205f71d7ff98e0ebdb71a04c8a9e3 100644 --- a/dom/security/nsContentSecurityUtils.cpp +++ b/dom/security/nsContentSecurityUtils.cpp @@ -619,6 +619,9 @@ bool nsContentSecurityUtils::IsEvalAllowed(JSContext* cx, // The Browser Toolbox/Console "debugger"_ns, + + // Tor Browser's Lox wasm integration + "resource://gre/modules/lox_wasm.jsm"_ns, }; // We also permit two specific idioms in eval()-like contexts. We'd like to diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index bcf88d92300a09bec442574d47f48a290fa04ae4..6b17648322d99dbc43a4fc4397d6f0189ea7865b 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -692,8 +692,8 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, return NS_OK; } - // Check the parent scheme. If it is not an HTTPS page then mixed content - // restrictions do not apply. + // Check the parent scheme. If it is not an HTTPS or .onion page then mixed + // content restrictions do not apply. nsCOMPtr<nsIURI> innerRequestingLocation = NS_GetInnermostURI(requestingLocation); if (!innerRequestingLocation) { @@ -708,6 +708,17 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, bool parentIsHttps = innerRequestingLocation->SchemeIs("https"); if (!parentIsHttps) { + bool parentIsOnion = IsPotentiallyTrustworthyOnion(innerRequestingLocation); + if (!parentIsOnion) { + *aDecision = ACCEPT; + return NS_OK; + } + } + + bool isHttpScheme = innerContentLocation->SchemeIs("http"); + // .onion URLs are encrypted and authenticated. Don't treat them as mixed + // content if potentially trustworthy (i.e. whitelisted). + if (isHttpScheme && IsPotentiallyTrustworthyOnion(innerContentLocation)) { *aDecision = ACCEPT; MOZ_LOG(sMCBLog, LogLevel::Verbose, (" -> decision: Request will be allowed because the requesting " @@ -734,7 +745,6 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, return NS_OK; } - bool isHttpScheme = innerContentLocation->SchemeIs("http"); if (isHttpScheme && IsPotentiallyTrustworthyOrigin(innerContentLocation)) { *aDecision = ACCEPT; return NS_OK; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 0b0c01a477d15f85beb4e404d106ebdd88d4984e..53490009e2a9340cdd8610189181ed79b75b1a13 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -759,6 +759,9 @@ partial interface Document { // context which isn't in bfcache. [ChromeOnly] boolean isActive(); + // Allow chrome JS to know whether a document has a valid Onion-Location + // that we could redirect to. + [ChromeOnly] readonly attribute URI? onionLocationURI; }; Document includes NonElementParentNode; diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index f04f5e9673dc66a6ab5306c2c1627cfe87d43e91..2deae06f25baf90c2061f2e8e1a659f6761d0c5a 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -1790,13 +1790,15 @@ nsresult WebSocketImpl::Init(nsIGlobalObject* aWindowGlobal, JSContext* aCx, // Don't allow https:// to open ws:// // Check that we aren't a server side websocket or set to be upgraded to wss // or allowing ws from https or a local websocket - if (!mIsServerSide && !mSecure && + if (!mIsServerSide && !mSecure && aIsSecure && !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS", false) && !nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost( mAsciiHost)) { - // If aIsSecure is true then disallow loading ws - if (aIsSecure) { + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), mURI); + NS_ENSURE_SUCCESS(rv, rv); + if (!nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(uri)) { return NS_ERROR_DOM_SECURITY_ERR; } diff --git a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp index c5231e9221686ce270a1a92e9ef5def2719229bb..30f1a471d17253289f5ca0665214b37efe99a509 100644 --- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp +++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp @@ -940,11 +940,17 @@ void txMozillaXSLTProcessor::reportError(nsresult aResult, mozilla::components::StringBundle::Service(); if (sbs) { nsString errorText; - sbs->FormatStatusMessage(aResult, u"", errorText); + bool spoofLocale = nsContentUtils::SpoofLocaleEnglish(); + if (spoofLocale && mSource) { + Document* sourceDoc = mSource->OwnerDoc(); + spoofLocale = !(sourceDoc && sourceDoc->AllowsL10n()); + } + sbs->FormatStatusMessage(aResult, u"", spoofLocale, errorText); nsAutoString errorMessage; nsCOMPtr<nsIStringBundle> bundle; - sbs->CreateBundle(XSLT_MSGS_URL, getter_AddRefs(bundle)); + sbs->CreateBundle(spoofLocale ? XSLT_MSGS_URL_en_US : XSLT_MSGS_URL, + getter_AddRefs(bundle)); if (bundle) { AutoTArray<nsString, 1> error = {errorText}; diff --git a/dom/xslt/xslt/txXSLTMsgsURL.h b/dom/xslt/xslt/txXSLTMsgsURL.h index 321b59548a16b6a63f16210a9ad28b861a2152d6..8378d25801b0107e4bb3e025f4fff179c47c23ee 100644 --- a/dom/xslt/xslt/txXSLTMsgsURL.h +++ b/dom/xslt/xslt/txXSLTMsgsURL.h @@ -7,5 +7,6 @@ #define DOM_XSLT_XSLT_TXXSLTMSGSURL_H_ #define XSLT_MSGS_URL "chrome://global/locale/xslt/xslt.properties" +#define XSLT_MSGS_URL_en_US "resource://gre/res/locale/xslt/xslt.properties" #endif // DOM_XSLT_XSLT_TXXSLTMSGSURL_H_ diff --git a/extensions/auth/nsHttpNegotiateAuth.cpp b/extensions/auth/nsHttpNegotiateAuth.cpp index a3ec224b59ee4b94b3954db61efdebe6735dd21c..46da4d015f75c71b1e4113b9601b5c8efd79d9a2 100644 --- a/extensions/auth/nsHttpNegotiateAuth.cpp +++ b/extensions/auth/nsHttpNegotiateAuth.cpp @@ -145,6 +145,10 @@ nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel* authChannel, nsIAuthModule* rawModule = (nsIAuthModule*)*continuationState; *identityInvalid = false; + + /* Always fail Negotiate auth for Tor Browser. We don't need it. */ + return NS_ERROR_ABORT; + if (rawModule) { return NS_OK; } diff --git a/gfx/thebes/StandardFonts-linux.inc b/gfx/thebes/StandardFonts-linux-upstream.inc similarity index 100% rename from gfx/thebes/StandardFonts-linux.inc rename to gfx/thebes/StandardFonts-linux-upstream.inc diff --git a/gfx/thebes/StandardFonts-macos-bb.inc b/gfx/thebes/StandardFonts-macos-bb.inc new file mode 100644 index 0000000000000000000000000000000000000000..d2fcb13a51a9169bee3709798945354398b8ab67 --- /dev/null +++ b/gfx/thebes/StandardFonts-macos-bb.inc @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +static const char* kBaseFonts[] = { + "Apple Color Emoji", + "AppleGothic", + "Arial", + "Arial Black", + "Arial Narrow", + "Courier", + "Courier New", + "Geneva", + "Georgia", + "Heiti TC", + "Helvetica", + "Helvetica Neue", + "Hiragino Kaku Gothic ProN", + "Kailasa", + "Lucida Grande", + "Menlo", + "Monaco", + "PingFang HK", + "PingFang SC", + "PingFang TC", + "Songti SC", + "Songti TC", + "Tahoma", + "Thonburi", + "Times", + "Times New Roman", + "Verdana", +}; diff --git a/gfx/thebes/StandardFonts-macos.inc b/gfx/thebes/StandardFonts-macos-upstream.inc similarity index 100% rename from gfx/thebes/StandardFonts-macos.inc rename to gfx/thebes/StandardFonts-macos-upstream.inc diff --git a/gfx/thebes/StandardFonts-win10-bb.inc b/gfx/thebes/StandardFonts-win10-bb.inc new file mode 100644 index 0000000000000000000000000000000000000000..9a0cc575dee7caf74fffeac249d7924d1b84d004 --- /dev/null +++ b/gfx/thebes/StandardFonts-win10-bb.inc @@ -0,0 +1,90 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +static const char* kBaseFonts[] = { + "Arial", + "Cambria Math", + "Consolas", + "Courier New", + "Georgia", + "Lucida Console", + "Malgun Gothic", + "Microsoft Himalaya", + "Microsoft JhengHei", + "Microsoft YaHei", + "MS Gothic", + "MS PGothic", + "MV Boli", + "Segoe UI", + "SimSun", + "Sylfaen", + "Tahoma", + "Times New Roman", + "Verdana", +}; + +struct FontSubstitute { + const char* substituteName; + const char* actualFontName; +}; + +static const FontSubstitute kFontSubstitutes[] = { + // Common substitutions + {"Arabic Transparent", "Arial"}, + {"Arabic Transparent Bold", "Arial Bold"}, + {"Arial Baltic", "Arial"}, + {"Arial CE", "Arial"}, + {"Arial CYR", "Arial"}, + {"Arial Greek", "Arial"}, + {"Arial TUR", "Arial"}, + {"Courier New Baltic", "Courier New"}, + {"Courier New CE", "Courier New"}, + {"Courier New CYR", "Courier New"}, + {"Courier New Greek", "Courier New"}, + {"Courier New TUR", "Courier New"}, + {"Helv", "MS Sans Serif"}, + {"Helvetica", "Arial"}, + {"MS Shell Dlg 2", "Tahoma"}, + {"Tahoma Armenian", "Tahoma"}, + {"Times", "Times New Roman"}, + {"Times New Roman Baltic", "Times New Roman"}, + {"Times New Roman CE", "Times New Roman"}, + {"Times New Roman CYR", "Times New Roman"}, + {"Times New Roman Greek", "Times New Roman"}, + {"Times New Roman TUR", "Times New Roman"}, + {"Tms Rmn", "MS Serif"}, + // Common, except Japanese (which uses MS UI Gothic, instead) + {"MS Shell Dlg", "Microsoft Sans Serif"}, + // Arabic + {"Arial (Arabic)", "Arial"}, + {"Courier New (Arabic)", "Courier New"}, + {"Times New Roman (Arabic)", "Times New Roman"}, + // Cyrillic + Greek + {"Courier", "Courier New"}, + // Greek + {"Fixedsys Greek", "Fixedsys"}, + {"MS Serif Greek", "MS Serif"}, + {"MS Sans Serif Greek", "MS Sans Serif"}, + {"Small Fonts Greek", "Small Fonts"}, + {"System Greek", "System"}, + // Hebrew + {"Arial (Hebrew)", "Arial"}, + {"Courier New (Hebrew)", "Courier New"}, + {"David Transparent", "David"}, + {"Fixed Miriam Transparent", "Miriam Fixed"}, + {"Miriam Transparent", "Miriam"}, + {"Rod Transparent", "Rod"}, + {"Times New Roman (Hebrew)", "Times New Roman"}, + // Japanese + {"標準明朝", "MS 明朝"}, + {"標準ゴシック", "MS ゴシック"}, + {"ゴシック", "MS ゴシック"}, + {"ゴシック", "MS ゴシック"}, + {"クーリエ", "Courier"}, + {"タイムズロマン", "Times New Roman"}, + {"ヘルベチカ", "Arial"}, + // Simplified Chinese + {"FangSong_GB2312", "FangSong"}, + {"KaiTi_GB2312", "KaiTi"}, +}; diff --git a/gfx/thebes/StandardFonts-win10.inc b/gfx/thebes/StandardFonts-win10-upstream.inc similarity index 100% rename from gfx/thebes/StandardFonts-win10.inc rename to gfx/thebes/StandardFonts-win10-upstream.inc diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 6de30f023cccdc8aa930c9ff5a93ed880f1c9691..32cc4bb921932b19e215afb06ef8f93d3fe90763 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -33,7 +33,7 @@ #include "harfbuzz/hb.h" -#include "StandardFonts-win10.inc" +#include "StandardFonts-win10-bb.inc" using namespace mozilla; using namespace mozilla::gfx; @@ -911,7 +911,9 @@ void gfxDWriteFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, gfxDWriteFontList::gfxDWriteFontList() : mForceGDIClassicMaxFontSize(0.0) { CheckFamilyList(kBaseFonts); +#ifndef BASE_BROWSER_VERSION CheckFamilyList(kLangPackFonts); +#endif } // bug 602792 - CJK systems default to large CJK fonts which cause excessive @@ -1152,9 +1154,11 @@ FontVisibility gfxDWriteFontList::GetVisibilityForFamily( if (FamilyInList(aName, kBaseFonts)) { return FontVisibility::Base; } +#ifndef BASE_BROWSER_VERSION if (FamilyInList(aName, kLangPackFonts)) { return FontVisibility::LangPack; } +#endif return FontVisibility::User; } @@ -1163,8 +1167,10 @@ gfxDWriteFontList::GetFilteredPlatformFontLists() { nsTArray<std::pair<const char**, uint32_t>> fontLists; fontLists.AppendElement(std::make_pair(kBaseFonts, ArrayLength(kBaseFonts))); +#ifndef BASE_BROWSER_VERSION fontLists.AppendElement( std::make_pair(kLangPackFonts, ArrayLength(kLangPackFonts))); +#endif return fontLists; } @@ -1952,6 +1958,20 @@ static void RemoveCharsetFromFontSubstitute(nsACString& aName) { #define MAX_VALUE_DATA 512 nsresult gfxDWriteFontList::GetFontSubstitutes() { + if (nsContentUtils::ShouldResistFingerprinting( + "Ignore any fingerprintable user font customization and normalize " + "font substitutes across different Windows SKUs.", + RFPTarget::FontVisibilityLangPack)) { + for (const FontSubstitute& fs : kFontSubstitutes) { + nsAutoCString substituteName(fs.substituteName); + nsAutoCString actualFontName(fs.actualFontName); + BuildKeyNameFromFontName(substituteName); + BuildKeyNameFromFontName(actualFontName); + AddSubstitute(substituteName, actualFontName); + } + return NS_OK; + } + HKEY hKey; DWORD i, rv, lenAlias, lenActual, valueType; WCHAR aliasName[MAX_VALUE_NAME]; @@ -1986,39 +2006,46 @@ nsresult gfxDWriteFontList::GetFontSubstitutes() { BuildKeyNameFromFontName(substituteName); RemoveCharsetFromFontSubstitute(actualFontName); BuildKeyNameFromFontName(actualFontName); - if (SharedFontList()) { - // Skip substitution if the original font is available, unless the option - // to apply substitutions unconditionally is enabled. - if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) { - // Font substitutions are recorded for the canonical family names; we - // don't need FindFamily to consider localized aliases when searching. - if (SharedFontList()->FindFamily(substituteName, - /*aPrimaryNameOnly*/ true)) { - continue; - } - } - if (SharedFontList()->FindFamily(actualFontName, + AddSubstitute(substituteName, actualFontName); + } + + return NS_OK; +} + +void gfxDWriteFontList::AddSubstitute(const nsCString& substituteName, + const nsCString& actualFontName) { + if (SharedFontList()) { + // Skip substitution if the original font is available, unless the + // option to apply substitutions unconditionally is enabled. + if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) { + // Font substitutions are recorded for the canonical family names; + // we don't need FindFamily to consider localized aliases when + // searching. + if (SharedFontList()->FindFamily(substituteName, /*aPrimaryNameOnly*/ true)) { - mSubstitutions.InsertOrUpdate(substituteName, - MakeUnique<nsCString>(actualFontName)); - } else if (mSubstitutions.Get(actualFontName)) { - mSubstitutions.InsertOrUpdate( - substituteName, - MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName))); - } else { - mNonExistingFonts.AppendElement(substituteName); + return; } + } + if (SharedFontList()->FindFamily(actualFontName, + /*aPrimaryNameOnly*/ true)) { + mSubstitutions.InsertOrUpdate(substituteName, + MakeUnique<nsCString>(actualFontName)); + } else if (mSubstitutions.Get(actualFontName)) { + mSubstitutions.InsertOrUpdate( + substituteName, + MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName))); } else { - gfxFontFamily* ff; - if (!actualFontName.IsEmpty() && - (ff = mFontFamilies.GetWeak(actualFontName))) { - mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); - } else { - mNonExistingFonts.AppendElement(substituteName); - } + mNonExistingFonts.AppendElement(substituteName); + } + } else { + gfxFontFamily* ff; + if (!actualFontName.IsEmpty() && + (ff = mFontFamilies.GetWeak(actualFontName))) { + mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); + } else { + mNonExistingFonts.AppendElement(substituteName); } } - return NS_OK; } struct FontSubstitution { diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index 357336a12cc0519391c484ca87c9ae8a149ffdf3..d416c0a8d5349fc5c87fc1250cd8584ca1393232 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -457,6 +457,9 @@ class gfxDWriteFontList final : public gfxPlatformFontList { const nsTArray<nsCString>* aForceClassicFams = nullptr) MOZ_REQUIRES(mLock); + void AddSubstitute(const nsCString& substituteName, + const nsCString& actualFontName); + #ifdef MOZ_BUNDLED_FONTS already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection( IDWriteFactory* aFactory); diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index 30c202d6eea22f7766f08d242ac41fd8cb27b632..415d2ef610c245c9e29cf294eaca9845d089363b 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -32,7 +32,9 @@ #include "nsCharSeparatedTokenizer.h" #include "nsXULAppAPI.h" #include "SharedFontList-impl.h" -#include "StandardFonts-linux.inc" +#ifndef BASE_BROWSER_VERSION +# include "StandardFonts-linux.inc" +#endif #include "mozilla/intl/Locale.h" #include "mozilla/gfx/HelpersCairo.h" @@ -1358,12 +1360,14 @@ gfxFcPlatformFontList::gfxFcPlatformFontList() mFcSubstituteCache(64), mLastConfig(nullptr), mAlwaysUseFontconfigGenerics(true) { +#ifndef BASE_BROWSER_VERSION CheckFamilyList(kBaseFonts_Ubuntu_22_04); CheckFamilyList(kLangFonts_Ubuntu_22_04); CheckFamilyList(kBaseFonts_Ubuntu_20_04); CheckFamilyList(kLangFonts_Ubuntu_20_04); CheckFamilyList(kBaseFonts_Fedora_39); CheckFamilyList(kBaseFonts_Fedora_38); +#endif mLastConfig = FcConfigGetCurrent(); if (XRE_IsParentProcess()) { // if the rescan interval is set, start the timer @@ -1677,11 +1681,14 @@ using Device = nsIGfxInfo::FontVisibilityDeviceDetermination; static Device sFontVisibilityDevice = Device::Unassigned; void AssignFontVisibilityDevice() { + sFontVisibilityDevice = Device::Linux_Unknown; +#ifndef BASE_BROWSER_VERSION if (sFontVisibilityDevice == Device::Unassigned) { nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service(); NS_ENSURE_SUCCESS_VOID( gfxInfo->GetFontVisibilityDetermination(&sFontVisibilityDevice)); } +#endif } // Per family array of faces. @@ -2002,6 +2009,7 @@ FontVisibility gfxFcPlatformFontList::GetVisibilityForFamily( AssignFontVisibilityDevice(); switch (sFontVisibilityDevice) { +#ifndef BASE_BROWSER_VERSION case Device::Linux_Ubuntu_any: case Device::Linux_Ubuntu_22: if (FamilyInList(aName, kBaseFonts_Ubuntu_22_04)) { @@ -2041,7 +2049,7 @@ FontVisibility gfxFcPlatformFontList::GetVisibilityForFamily( return FontVisibility::Base; } return FontVisibility::User; - +#endif default: // We don't know how to categorize fonts on this system return FontVisibility::Unknown; @@ -2054,6 +2062,7 @@ gfxFcPlatformFontList::GetFilteredPlatformFontLists() { nsTArray<std::pair<const char**, uint32_t>> fontLists; +#ifndef BASE_BROWSER_VERSION switch (sFontVisibilityDevice) { case Device::Linux_Ubuntu_any: case Device::Linux_Ubuntu_22: @@ -2087,6 +2096,7 @@ gfxFcPlatformFontList::GetFilteredPlatformFontLists() { // We don't know how to categorize fonts on this system break; } +#endif return fontLists; } @@ -2189,11 +2199,12 @@ void gfxFcPlatformFontList::GetFontList(nsAtom* aLangGroup, FontFamily gfxFcPlatformFontList::GetDefaultFontForPlatform( nsPresContext* aPresContext, const gfxFontStyle* aStyle, nsAtom* aLanguage) { - // Get the default font by using a fake name to retrieve the first - // scalable font that fontconfig suggests for the given language. - PrefFontList* prefFonts = - FindGenericFamilies(aPresContext, "-moz-default"_ns, - aLanguage ? aLanguage : nsGkAtoms::x_western); + // We hardcode Arimo also in preferences, and using the original code that + // tried to resolve a non-existing font did not play well with our fontconfig + // configuration. See + // https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41043 + PrefFontList* prefFonts = FindGenericFamilies( + aPresContext, "Arimo"_ns, aLanguage ? aLanguage : nsGkAtoms::x_western); NS_ASSERTION(prefFonts, "null list of generic fonts"); if (prefFonts && !prefFonts->IsEmpty()) { return (*prefFonts)[0]; diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index 4dca4506c0ac615446149f45ab41cdd08b334e33..d0686a2b339389f264c36bacdbd399016ad74f37 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -31,6 +31,10 @@ #include "mozilla/StaticPrefs_gfx.h" #include "mozilla/Telemetry.h" +#include "nsContentUtils.h" + +#include "StandardFonts-win10-bb.inc" + #include <usp10.h> using namespace mozilla; @@ -50,6 +54,10 @@ static __inline void BuildKeyNameFromFontName(nsAString& aName) { if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1); ToLowerCase(aName); } +static __inline void BuildKeyNameFromFontName(nsACString& aName) { + if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1); + ToLowerCase(aName); +} // Implementation of gfxPlatformFontList for Win32 GDI, // using GDI font enumeration APIs to get the list of fonts @@ -529,6 +537,26 @@ static void RemoveCharsetFromFontSubstitute(nsAString& aName) { #define MAX_VALUE_DATA 512 nsresult gfxGDIFontList::GetFontSubstitutes() { + if (nsContentUtils::ShouldResistFingerprinting( + "Ignore any fingerprintable user font customization and normalize " + "font substitutes across different Windows SKUs.", + RFPTarget::FontVisibilityLangPack)) { + for (const FontSubstitute& fs : kFontSubstitutes) { + nsAutoCString substituteName(fs.substituteName); + nsAutoCString actualFontName(fs.actualFontName); + BuildKeyNameFromFontName(substituteName); + BuildKeyNameFromFontName(actualFontName); + gfxFontFamily* ff; + if (!actualFontName.IsEmpty() && + (ff = mFontFamilies.GetWeak(actualFontName))) { + mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); + } else { + mNonExistingFonts.AppendElement(substituteName); + } + } + return NS_OK; + } + HKEY hKey; DWORD i, rv, lenAlias, lenActual, valueType; WCHAR aliasName[MAX_VALUE_NAME]; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 6d2a6666df10dba76046926ce40ad09d7db29387..0c870eab5ba06362170e4b1b795c580e771a1562 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -45,7 +45,7 @@ #include <time.h> #include <dlfcn.h> -#include "StandardFonts-macos.inc" +#include "StandardFonts-macos-bb.inc" using namespace mozilla; using namespace mozilla::gfx; @@ -152,6 +152,9 @@ void gfxSingleFaceMacFontFamily::ReadOtherFamilyNames( gfxMacPlatformFontList::gfxMacPlatformFontList() : CoreTextFontList() { CheckFamilyList(kBaseFonts); +#ifndef BASE_BROWSER_VERSION + CheckFamilyList(kBaseFonts_13_Higher); +#endif // cache this in a static variable so that gfxMacFontFamily objects // don't have to repeatedly look it up @@ -170,6 +173,12 @@ FontVisibility gfxMacPlatformFontList::GetVisibilityForFamily( if (FamilyInList(aName, kBaseFonts)) { return FontVisibility::Base; } +#ifndef BASE_BROWSER_VERSION + if (GetFontVisibilityDevice() == Device::MacOS_13_plus && + FamilyInList(aName, kBaseFonts_13_Higher)) { + return FontVisibility::Base; + } +#endif #ifdef MOZ_BUNDLED_FONTS if (mBundledFamilies.Contains(aName)) { return FontVisibility::Base; @@ -184,6 +193,13 @@ gfxMacPlatformFontList::GetFilteredPlatformFontLists() { fontLists.AppendElement(std::make_pair(kBaseFonts, ArrayLength(kBaseFonts))); +#ifndef BASE_BROWSER_VERSION + if (GetFontVisibilityDevice() == Device::MacOS_13_plus) { + fontLists.AppendElement( + std::make_pair(kBaseFonts_13_Higher, std::size(kBaseFonts_13_Higher))); + } +#endif + return fontLists; } diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index d81a1a350a9c3ff01f9e17f8c5b76d978a5a99c8..19e666bb00098c30c497e333f8c858c5d77af89f 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -2055,6 +2055,11 @@ static void GetSystemUIFontFamilies(const nsPresContext* aPresContext, #if defined(XP_MACOSX) || defined(MOZ_WIDGET_UIKIT) *aFamilies.AppendElement() = "-apple-system"_ns; return; +#elif defined(MOZ_WIDGET_GTK) + // tor-browser#43141: Hardcode Arimo in case our custom fontconfig is + // missing. + *aFamilies.AppendElement() = "Arimo"_ns; + return; #elif !defined(MOZ_WIDGET_ANDROID) *aFamilies.AppendElement() = "sans-serif"_ns; return; diff --git a/intl/l10n/Localization.h b/intl/l10n/Localization.h index a22802758d4c454b626705c84e0596340e54e486..7c1f85c8943d8631c8e32d4a33e47d9fdb4395c6 100644 --- a/intl/l10n/Localization.h +++ b/intl/l10n/Localization.h @@ -46,7 +46,9 @@ namespace intl { const nsTArray<nsCString>& aErrors, ErrorResult& aRv, nsIGlobalObject* aGlobal) { if (!aErrors.IsEmpty()) { -#if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG) + // See tor-browser#41285 +#if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG) || \ + defined(TOR_BROWSER_NIGHTLY_BUILD) dom::Document* doc = nullptr; if (aGlobal) { nsPIDOMWindowInner* innerWindow = aGlobal->GetAsInnerWindow(); diff --git a/intl/locale/LocaleService.cpp b/intl/locale/LocaleService.cpp index 1527f2791037dfe22f1e1a344cb632b5c7069080..d8e3b6121b0f3bc57f3ed5f2affda116769eb1e6 100644 --- a/intl/locale/LocaleService.cpp +++ b/intl/locale/LocaleService.cpp @@ -14,6 +14,7 @@ #include "mozilla/intl/AppDateTimeFormat.h" #include "mozilla/intl/Locale.h" #include "mozilla/intl/OSPreferences.h" +#include "nsContentUtils.h" #include "nsDirectoryService.h" #include "nsDirectoryServiceDefs.h" #include "nsIObserverService.h" @@ -484,6 +485,16 @@ LocaleService::GetAppLocaleAsBCP47(nsACString& aRetVal) { NS_IMETHODIMP LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal) { + // tor-browser#42349, #42771: We cannot use JSLocale because it is spoof + // English. So, we use another target for now. + if (nsContentUtils::ShouldResistFingerprinting( + "This is probably a patch that should be refined. But to get the " + "build going, we just keep applying this generic check.", + RFPTarget::JSDateTimeUTC)) { + GetAppLocalesAsBCP47(aRetVal); + return NS_OK; + } + bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false); diff --git a/intl/strres/nsIStringBundle.idl b/intl/strres/nsIStringBundle.idl index a548517703a044b3e053d2c5478b77ce23b3a9c5..6ead1b17114c2c8a282005c2b832ac4830d7afe7 100644 --- a/intl/strres/nsIStringBundle.idl +++ b/intl/strres/nsIStringBundle.idl @@ -86,9 +86,13 @@ interface nsIStringBundleService : nsISupports * used in the string lookup process. * @param aStatusArg - The status message argument(s). Multiple arguments * can be separated by newline ('\n') characters. + * @param aSpoofLocale - If true (default is false), forces the en-US + locale on content-accessible messages (XSLT errors so far). * @return the formatted message */ - AString formatStatusMessage(in nsresult aStatus, in wstring aStatusArg); + AString formatStatusMessage(in nsresult aStatus, + in wstring aStatusArg, + [optional] in boolean aSpoofLocale); /** * flushes the string bundle cache - useful when the locale changes or diff --git a/intl/strres/nsStringBundle.cpp b/intl/strres/nsStringBundle.cpp index 31ecbc3d001953b701a8538dcfe4519efd5b752d..972ee83cc1643cd7f07b1826120a1fac231d99e3 100644 --- a/intl/strres/nsStringBundle.cpp +++ b/intl/strres/nsStringBundle.cpp @@ -977,6 +977,7 @@ nsresult nsStringBundleService::FormatWithBundle( NS_IMETHODIMP nsStringBundleService::FormatStatusMessage(nsresult aStatus, const char16_t* aStatusArg, + bool aSpoofLocale, nsAString& result) { uint32_t i, argCount = 0; nsCOMPtr<nsIStringBundle> bundle; @@ -1012,7 +1013,8 @@ nsStringBundleService::FormatStatusMessage(nsresult aStatus, switch (NS_ERROR_GET_MODULE(aStatus)) { case NS_ERROR_MODULE_XSLT: - getStringBundle(XSLT_MSGS_URL, getter_AddRefs(bundle)); + getStringBundle(aSpoofLocale ? XSLT_MSGS_URL_en_US : XSLT_MSGS_URL, + getter_AddRefs(bundle)); break; case NS_ERROR_MODULE_NETWORK: getStringBundle(NECKO_MSGS_URL, getter_AddRefs(bundle)); diff --git a/js/xpconnect/src/xpc.msg b/js/xpconnect/src/xpc.msg index 7a448562f8eff3f2d27aa5d9420bd39e3c7cf1f2..48b67c39083a8cd32037ae76729e8e8179e4c178 100644 --- a/js/xpconnect/src/xpc.msg +++ b/js/xpconnect/src/xpc.msg @@ -249,6 +249,16 @@ XPC_MSG_DEF(NS_ERROR_CRYPTOMINING_URI , "The URI is cryptomining XPC_MSG_DEF(NS_ERROR_SOCIALTRACKING_URI , "The URI is social tracking") XPC_MSG_DEF(NS_ERROR_EMAILTRACKING_URI , "The URI is email tracking") +/* Codes related to Tor */ +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_NOT_FOUND , "Tor onion service descriptor cannot be found") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_IS_INVALID , "Tor onion service descriptor is invalid") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_INTRO_FAILED , "Tor onion service introduction failed") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_REND_FAILED , "Tor onion service rendezvous failed") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH, "Tor onion service missing client authorization") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH , "Tor onion service wrong client authorization") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS , "Tor onion service bad address") +XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT , "Tor onion service introduction timed out") + /* Profile manager error codes */ XPC_MSG_DEF(NS_ERROR_DATABASE_CHANGED , "Flushing the profiles to disk would have overwritten changes made elsewhere.") diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 43d7e5008b352b7deb198ffc81fedf5de3f4b72a..536dcb5ccc5c6846b1051f056f8a21ef8b84809b 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -9571,7 +9571,9 @@ static void GetSpoofedSystemFontForRFP(LookAndFeel::FontID aFontID, // In general, Linux uses some sans-serif, but its size can vary between // 12px and 16px. We chose 15px because it is what Firefox is doing for the // UI font-size. - aName = u"sans-serif"_ns; + // tor-browser#43141: Hardcode Arimo in case our custom fontconfig is + // missing. + aName = u"Arimo"_ns; aStyle.size = 15; #else # error "Unknown platform" diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt index e65f20da3e909c460d2ef6bfb7b080fd783c5a9a..d34375dae25b1a47cbe6acf5fb363842d3f66258 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt @@ -1353,6 +1353,23 @@ class GeckoEngine( override var userCharacteristicPingCurrentVersion: Int get() = runtime.settings.userCharacteristicPingCurrentVersion set(value) { runtime.settings.setUserCharacteristicPingCurrentVersion(value) } + + override var torSecurityLevel: Int + get() = runtime.settings.torSecurityLevel + set(value) { + value.let { + runtime.settings.torSecurityLevel = it + } + } + + override var spoofEnglish: Boolean + get() = runtime.settings.spoofEnglish + set(value) { + value.let { + runtime.settings.spoofEnglish = it + localeUpdater.updateValue() + } + } }.apply { defaultSettings?.let { this.javascriptEnabled = it.javascriptEnabled @@ -1384,6 +1401,8 @@ class GeckoEngine( this.fdlibmMathEnabled = it.fdlibmMathEnabled this.emailTrackerBlockingPrivateBrowsing = it.emailTrackerBlockingPrivateBrowsing this.userCharacteristicPingCurrentVersion = it.userCharacteristicPingCurrentVersion + this.torSecurityLevel = it.torSecurityLevel + this.spoofEnglish = it.spoofEnglish } } @@ -1511,6 +1530,8 @@ class GeckoEngine( installedExtension.registerTabHandler(webExtensionTabHandler, defaultSettings) onSuccess(installedExtension) } + + fun getTorIntegrationController() = runtime.getTorIntegrationController() } internal fun ContentBlockingController.LogEntry.BlockingData.hasBlockedCookies(): Boolean { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt index 507ebe1d9021413131c8bb2298dfa02012a0911b..8d57accbb39fa7326373df4993e894f3872cac9b 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt @@ -1811,6 +1811,10 @@ class GeckoEngineSession( geckoSession.translationsSessionDelegate = GeckoTranslateSessionDelegate(this) } + fun newTorCircuit() { + geckoSession.newTorCircuit() + } + companion object { internal const val PROGRESS_START = 25 internal const val PROGRESS_STOP = 100 diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorage.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorage.kt index d8f4fc4a700aa3e2c2e749154758fbf89856bb79..650a627dbd190119951b4911b54c4f1ece00dbf8 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorage.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorage.kt @@ -21,7 +21,7 @@ import org.mozilla.geckoview.StorageController */ class GeckoCookieBannersStorage( runtime: GeckoRuntime, - private val reportSiteDomainsRepository: ReportSiteDomainsRepository, +// private val reportSiteDomainsRepository: ReportSiteDomainsRepository, ) : CookieBannersStorage { private val geckoStorage: StorageController = runtime.storageController @@ -34,13 +34,13 @@ class GeckoCookieBannersStorage( setGeckoException(uri, DISABLED, privateBrowsing) } - override suspend fun isSiteDomainReported(siteDomain: String): Boolean { - return reportSiteDomainsRepository.isSiteDomainReported(siteDomain) - } - - override suspend fun saveSiteDomain(siteDomain: String) { - reportSiteDomainsRepository.saveSiteDomain(siteDomain) - } +// override suspend fun isSiteDomainReported(siteDomain: String): Boolean { +// return reportSiteDomainsRepository.isSiteDomainReported(siteDomain) +// } +// +// override suspend fun saveSiteDomain(siteDomain: String) { +// reportSiteDomainsRepository.saveSiteDomain(siteDomain) +// } override suspend fun addPersistentExceptionInPrivateMode(uri: String) { setPersistentPrivateGeckoException(uri, DISABLED) diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepository.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepository.kt index 9fbb9b3eda0b8c22d684d471bf79dbe4c8a2fd4d..79c1895bf961ae2a19d83c1fc52d5b17db5bf4e3 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepository.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepository.kt @@ -12,64 +12,64 @@ import androidx.datastore.preferences.core.stringPreferencesKey import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map -import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository.PreferencesKeys.REPORT_SITE_DOMAINS +//import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository.PreferencesKeys.REPORT_SITE_DOMAINS import mozilla.components.support.base.log.logger.Logger import java.io.IOException /** * A repository to save reported site domains with the datastore API. */ -class ReportSiteDomainsRepository( - private val dataStore: DataStore<Preferences>, -) { - - companion object { - const val SEPARATOR = "@<;>@" - const val REPORT_SITE_DOMAINS_REPOSITORY_NAME = "report_site_domains_preferences" - const val PREFERENCE_KEY_NAME = "report_site_domains" - } - - private object PreferencesKeys { - val REPORT_SITE_DOMAINS = stringPreferencesKey(PREFERENCE_KEY_NAME) - } - - /** - * Check if the given site's domain url is saved locally. - * @param siteDomain the [siteDomain] that will be checked. - */ - suspend fun isSiteDomainReported(siteDomain: String): Boolean { - return dataStore.data - .catch { exception -> - if (exception is IOException) { - Logger.error("Error reading preferences.", exception) - emit(emptyPreferences()) - } else { - throw exception - } - }.map { preferences -> - val reportSiteDomainsString = preferences[REPORT_SITE_DOMAINS] ?: "" - val reportSiteDomainsList = - reportSiteDomainsString.split(SEPARATOR).filter { it.isNotEmpty() } - reportSiteDomainsList.contains(siteDomain) - }.first() - } - - /** - * Save the given site's domain url in datastore to keep it persistent locally. - * This method gets called after the site domain was reported with Nimbus. - * @param siteDomain the [siteDomain] that will be saved. - */ - suspend fun saveSiteDomain(siteDomain: String) { - dataStore.edit { preferences -> - val siteDomainsPreferences = preferences[REPORT_SITE_DOMAINS] ?: "" - val siteDomainsList = siteDomainsPreferences.split(SEPARATOR).filter { it.isNotEmpty() } - if (siteDomainsList.contains(siteDomain)) { - return@edit - } - val domains = mutableListOf<String>() - domains.addAll(siteDomainsList) - domains.add(siteDomain) - preferences[REPORT_SITE_DOMAINS] = domains.joinToString(SEPARATOR) - } - } -} +//class ReportSiteDomainsRepository( +// private val dataStore: DataStore<Preferences>, +//) { +// +// companion object { +// const val SEPARATOR = "@<;>@" +// const val REPORT_SITE_DOMAINS_REPOSITORY_NAME = "report_site_domains_preferences" +// const val PREFERENCE_KEY_NAME = "report_site_domains" +// } +// +// private object PreferencesKeys { +// val REPORT_SITE_DOMAINS = stringPreferencesKey(PREFERENCE_KEY_NAME) +// } +// +// /** +// * Check if the given site's domain url is saved locally. +// * @param siteDomain the [siteDomain] that will be checked. +// */ +// suspend fun isSiteDomainReported(siteDomain: String): Boolean { +// return dataStore.data +// .catch { exception -> +// if (exception is IOException) { +// Logger.error("Error reading preferences.", exception) +// emit(emptyPreferences()) +// } else { +// throw exception +// } +// }.map { preferences -> +// val reportSiteDomainsString = preferences[REPORT_SITE_DOMAINS] ?: "" +// val reportSiteDomainsList = +// reportSiteDomainsString.split(SEPARATOR).filter { it.isNotEmpty() } +// reportSiteDomainsList.contains(siteDomain) +// }.first() +// } +// +// /** +// * Save the given site's domain url in datastore to keep it persistent locally. +// * This method gets called after the site domain was reported with Nimbus. +// * @param siteDomain the [siteDomain] that will be saved. +// */ +// suspend fun saveSiteDomain(siteDomain: String) { +// dataStore.edit { preferences -> +// val siteDomainsPreferences = preferences[REPORT_SITE_DOMAINS] ?: "" +// val siteDomainsList = siteDomainsPreferences.split(SEPARATOR).filter { it.isNotEmpty() } +// if (siteDomainsList.contains(siteDomain)) { +// return@edit +// } +// val domains = mutableListOf<String>() +// domains.addAll(siteDomainsList) +// domains.add(siteDomain) +// preferences[REPORT_SITE_DOMAINS] = domains.joinToString(SEPARATOR) +// } +// } +//} diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/fetch/GeckoViewFetchClient.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/fetch/GeckoViewFetchClient.kt index c28989752db966dc2b443effe9e2bb705172c56f..d62abc30e8625a51c9ff6104a51c91a0164d1c1d 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/fetch/GeckoViewFetchClient.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/fetch/GeckoViewFetchClient.kt @@ -89,6 +89,7 @@ private fun Request.toWebRequest(): WebRequest = WebRequest.Builder(url) .referrer(referrerUrl) .cacheMode(if (useCaches) CACHE_MODE_DEFAULT else CACHE_MODE_RELOAD) .beConservative(conservative) + .origin(origin) .build() private fun WebRequest.Builder.addHeadersFrom(request: Request): WebRequest.Builder { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webextension/GeckoWebExtension.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webextension/GeckoWebExtension.kt index f4db93f826c6d8a0757ab4b310d4bafeb032b20b..04430c7ea74c66da543753984ce1d3019f7d635a 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webextension/GeckoWebExtension.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webextension/GeckoWebExtension.kt @@ -393,6 +393,7 @@ class GeckoWebExtension( override fun isAllowedInPrivateBrowsing(): Boolean { return isBuiltIn() || nativeExtension.metaData.allowedInPrivateBrowsing + || isBundled() } override suspend fun loadIcon(size: Int): Bitmap? { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorageTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorageTest.kt index 958553706b23e6df7bc22c284690bc2303258637..c3819ac603fd1eff2f64501a3582d7eb44ad2a93 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorageTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/GeckoCookieBannersStorageTest.kt @@ -26,136 +26,136 @@ import org.mozilla.geckoview.StorageController @ExperimentalCoroutinesApi class GeckoCookieBannersStorageTest { - private lateinit var runtime: GeckoRuntime - private lateinit var geckoStorage: GeckoCookieBannersStorage - private lateinit var storageController: StorageController - private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository - - @Before - fun setup() { - storageController = mock() - runtime = mock() - reportSiteDomainsRepository = mock() - - whenever(runtime.storageController).thenReturn(storageController) - - geckoStorage = spy(GeckoCookieBannersStorage(runtime, reportSiteDomainsRepository)) - } - - @Test - fun `GIVEN a cookie banner mode WHEN adding an exception THEN add an exception for the given uri and browsing mode`() = - runTest { - val uri = "https://www.mozilla.org" - - doNothing().`when`(geckoStorage) - .setGeckoException(uri = uri, mode = DISABLED, privateBrowsing = false) - - geckoStorage.addException(uri = uri, privateBrowsing = false) - - verify(geckoStorage).setGeckoException(uri, DISABLED, false) - } - - @Test - fun `GIVEN uri and browsing mode WHEN removing an exception THEN remove the exception`() = - runTest { - val uri = "https://www.mozilla.org" - - doNothing().`when`(geckoStorage).removeGeckoException(uri, false) - - geckoStorage.removeException(uri = uri, privateBrowsing = false) - - verify(geckoStorage).removeGeckoException(uri, false) - } - - @Test - fun `GIVEN uri and browsing mode WHEN querying an exception THEN return the matching exception`() = - runTest { - val uri = "https://www.mozilla.org" - - doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage) - .queryExceptionInGecko(uri = uri, privateBrowsing = false) - - val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false) - assertEquals(REJECT_OR_ACCEPT_ALL, result) - } - - @Test - fun `GIVEN error WHEN querying an exception THEN return null`() = - runTest { - val uri = "https://www.mozilla.org" - - doReturn(null).`when`(geckoStorage) - .queryExceptionInGecko(uri = uri, privateBrowsing = false) - - val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false) - assertNull(result) - } - - @Test - fun `GIVEN uri and browsing mode WHEN checking for an exception THEN indicate if it has exceptions`() = - runTest { - val uri = "https://www.mozilla.org" - - doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage) - .queryExceptionInGecko(uri = uri, privateBrowsing = false) - - var result = geckoStorage.hasException(uri = uri, privateBrowsing = false) - - assertFalse(result!!) - - Mockito.reset(geckoStorage) - - doReturn(DISABLED).`when`(geckoStorage) - .queryExceptionInGecko(uri = uri, privateBrowsing = false) - - result = geckoStorage.hasException(uri = uri, privateBrowsing = false) - - assertTrue(result!!) - } - - @Test - fun `GIVEN an error WHEN checking for an exception THEN indicate if that an error happened`() = - runTest { - val uri = "https://www.mozilla.org" - - doReturn(null).`when`(geckoStorage) - .queryExceptionInGecko(uri = uri, privateBrowsing = false) - - val result = geckoStorage.hasException(uri = uri, privateBrowsing = false) - - assertNull(result) - } - - @Test - fun `GIVEN a cookie banner mode WHEN adding a persistent exception in private mode THEN add a persistent exception for the given uri in private browsing mode`() = - runTest { - val uri = "https://www.mozilla.org" - - doNothing().`when`(geckoStorage) - .setPersistentPrivateGeckoException(uri = uri, mode = DISABLED) - - geckoStorage.addPersistentExceptionInPrivateMode(uri = uri) - - verify(geckoStorage).setPersistentPrivateGeckoException(uri, DISABLED) - } - - @Test - fun `GIVEN site domain url WHEN checking if site domain is reported THEN the report site domain repository gets called`() = - runTest { - val reportSiteDomainUrl = "mozilla.org" - - geckoStorage.isSiteDomainReported(reportSiteDomainUrl) - - verify(reportSiteDomainsRepository).isSiteDomainReported(reportSiteDomainUrl) - } - - @Test - fun `GIVEN site domain url WHEN saving a site domain THEN the save method from repository should get called`() = - runTest { - val reportSiteDomainUrl = "mozilla.org" - - geckoStorage.saveSiteDomain(reportSiteDomainUrl) - - verify(reportSiteDomainsRepository).saveSiteDomain(reportSiteDomainUrl) - } +// private lateinit var runtime: GeckoRuntime +// private lateinit var geckoStorage: GeckoCookieBannersStorage +// private lateinit var storageController: StorageController +// private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository +// +// @Before +// fun setup() { +// storageController = mock() +// runtime = mock() +// reportSiteDomainsRepository = mock() +// +// whenever(runtime.storageController).thenReturn(storageController) +// +// geckoStorage = spy(GeckoCookieBannersStorage(runtime, reportSiteDomainsRepository)) +// } +// +// @Test +// fun `GIVEN a cookie banner mode WHEN adding an exception THEN add an exception for the given uri and browsing mode`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doNothing().`when`(geckoStorage) +// .setGeckoException(uri = uri, mode = DISABLED, privateBrowsing = false) +// +// geckoStorage.addException(uri = uri, privateBrowsing = false) +// +// verify(geckoStorage).setGeckoException(uri, DISABLED, false) +// } +// +// @Test +// fun `GIVEN uri and browsing mode WHEN removing an exception THEN remove the exception`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doNothing().`when`(geckoStorage).removeGeckoException(uri, false) +// +// geckoStorage.removeException(uri = uri, privateBrowsing = false) +// +// verify(geckoStorage).removeGeckoException(uri, false) +// } +// +// @Test +// fun `GIVEN uri and browsing mode WHEN querying an exception THEN return the matching exception`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage) +// .queryExceptionInGecko(uri = uri, privateBrowsing = false) +// +// val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false) +// assertEquals(REJECT_OR_ACCEPT_ALL, result) +// } +// +// @Test +// fun `GIVEN error WHEN querying an exception THEN return null`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doReturn(null).`when`(geckoStorage) +// .queryExceptionInGecko(uri = uri, privateBrowsing = false) +// +// val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false) +// assertNull(result) +// } +// +// @Test +// fun `GIVEN uri and browsing mode WHEN checking for an exception THEN indicate if it has exceptions`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage) +// .queryExceptionInGecko(uri = uri, privateBrowsing = false) +// +// var result = geckoStorage.hasException(uri = uri, privateBrowsing = false) +// +// assertFalse(result!!) +// +// Mockito.reset(geckoStorage) +// +// doReturn(DISABLED).`when`(geckoStorage) +// .queryExceptionInGecko(uri = uri, privateBrowsing = false) +// +// result = geckoStorage.hasException(uri = uri, privateBrowsing = false) +// +// assertTrue(result!!) +// } +// +// @Test +// fun `GIVEN an error WHEN checking for an exception THEN indicate if that an error happened`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doReturn(null).`when`(geckoStorage) +// .queryExceptionInGecko(uri = uri, privateBrowsing = false) +// +// val result = geckoStorage.hasException(uri = uri, privateBrowsing = false) +// +// assertNull(result) +// } +// +// @Test +// fun `GIVEN a cookie banner mode WHEN adding a persistent exception in private mode THEN add a persistent exception for the given uri in private browsing mode`() = +// runTest { +// val uri = "https://www.mozilla.org" +// +// doNothing().`when`(geckoStorage) +// .setPersistentPrivateGeckoException(uri = uri, mode = DISABLED) +// +// geckoStorage.addPersistentExceptionInPrivateMode(uri = uri) +// +// verify(geckoStorage).setPersistentPrivateGeckoException(uri, DISABLED) +// } +// +// @Test +// fun `GIVEN site domain url WHEN checking if site domain is reported THEN the report site domain repository gets called`() = +// runTest { +// val reportSiteDomainUrl = "mozilla.org" +// +// geckoStorage.isSiteDomainReported(reportSiteDomainUrl) +// +// verify(reportSiteDomainsRepository).isSiteDomainReported(reportSiteDomainUrl) +// } +// +// @Test +// fun `GIVEN site domain url WHEN saving a site domain THEN the save method from repository should get called`() = +// runTest { +// val reportSiteDomainUrl = "mozilla.org" +// +// geckoStorage.saveSiteDomain(reportSiteDomainUrl) +// +// verify(reportSiteDomainsRepository).saveSiteDomain(reportSiteDomainUrl) +// } } diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepositoryTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepositoryTest.kt index dbc809ef2c515baf01424cc5d6bfcf6a807f2a41..0798b17f3a5a549e2211ceed96ed2a7534c3cd9c 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepositoryTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/cookiebanners/ReportSiteDomainsRepositoryTest.kt @@ -23,52 +23,52 @@ import org.junit.runner.RunWith @ExperimentalCoroutinesApi @RunWith(AndroidJUnit4::class) class ReportSiteDomainsRepositoryTest { - - companion object { - const val TEST_DATASTORE_NAME = "test_data_store" - } - - private lateinit var testDataStore: DataStore<Preferences> - - private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository - - @Before - fun setUp() { - testDataStore = PreferenceDataStoreFactory.create( - produceFile = { testContext.preferencesDataStoreFile(TEST_DATASTORE_NAME) }, - ) - reportSiteDomainsRepository = ReportSiteDomainsRepository(testDataStore) - } - - @After - fun cleanUp() = runTest { testDataStore.edit { it.clear() } } - - @Test - fun `GIVEN site domain url WHEN site domain url is not saved THEN is side domain reported return false`() = - runTest { - assertFalse(reportSiteDomainsRepository.isSiteDomainReported("mozilla.org")) - } - - @Test - fun `GIVEN site domain url WHEN site domain url is saved THEN is side domain reported return true`() = - runTest { - val siteDomainReported = "mozilla.org" - - reportSiteDomainsRepository.saveSiteDomain(siteDomainReported) - - assertTrue(reportSiteDomainsRepository.isSiteDomainReported(siteDomainReported)) - } - - @Test - fun `GIVEN site domain urls WHEN site domain urls are saved THEN is side domain reported return true for each one`() = - runTest { - val mozillaSiteDomainReported = "mozilla.org" - val youtubeSiteDomainReported = "youtube.com" - - reportSiteDomainsRepository.saveSiteDomain(mozillaSiteDomainReported) - reportSiteDomainsRepository.saveSiteDomain(youtubeSiteDomainReported) - - assertTrue(reportSiteDomainsRepository.isSiteDomainReported(mozillaSiteDomainReported)) - assertTrue(reportSiteDomainsRepository.isSiteDomainReported(youtubeSiteDomainReported)) - } +// +// companion object { +// const val TEST_DATASTORE_NAME = "test_data_store" +// } +// +// private lateinit var testDataStore: DataStore<Preferences> +// +// private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository +// +// @Before +// fun setUp() { +// testDataStore = PreferenceDataStoreFactory.create( +// produceFile = { testContext.preferencesDataStoreFile(TEST_DATASTORE_NAME) }, +// ) +// reportSiteDomainsRepository = ReportSiteDomainsRepository(testDataStore) +// } +// +// @After +// fun cleanUp() = runTest { testDataStore.edit { it.clear() } } +// +// @Test +// fun `GIVEN site domain url WHEN site domain url is not saved THEN is side domain reported return false`() = +// runTest { +// assertFalse(reportSiteDomainsRepository.isSiteDomainReported("mozilla.org")) +// } +// +// @Test +// fun `GIVEN site domain url WHEN site domain url is saved THEN is side domain reported return true`() = +// runTest { +// val siteDomainReported = "mozilla.org" +// +// reportSiteDomainsRepository.saveSiteDomain(siteDomainReported) +// +// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(siteDomainReported)) +// } +// +// @Test +// fun `GIVEN site domain urls WHEN site domain urls are saved THEN is side domain reported return true for each one`() = +// runTest { +// val mozillaSiteDomainReported = "mozilla.org" +// val youtubeSiteDomainReported = "youtube.com" +// +// reportSiteDomainsRepository.saveSiteDomain(mozillaSiteDomainReported) +// reportSiteDomainsRepository.saveSiteDomain(youtubeSiteDomainReported) +// +// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(mozillaSiteDomainReported)) +// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(youtubeSiteDomainReported)) +// } } diff --git a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt index d3217bc4b28a2fd2d50f66cc13d5660aa1124654..dfa59112bf22090e4d71883f943a24d922afd733 100644 --- a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt +++ b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt @@ -62,6 +62,7 @@ open class HttpIconLoader( redirect = Request.Redirect.FOLLOW, useCaches = true, private = request.isPrivate, + origin = request.url ) return try { diff --git a/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/WebExtensionBrowserMenuBuilder.kt b/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/WebExtensionBrowserMenuBuilder.kt index 494014bf66b5a69340274f832ea7355caf5c6687..3b6cf170e6dbd2c57e21795b2b9455d49ee14e98 100644 --- a/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/WebExtensionBrowserMenuBuilder.kt +++ b/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/WebExtensionBrowserMenuBuilder.kt @@ -9,7 +9,6 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import mozilla.components.browser.menu.item.BackPressMenuItem import mozilla.components.browser.menu.item.BrowserMenuDivider -import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.item.NO_ID import mozilla.components.browser.menu.item.ParentBrowserMenuItem import mozilla.components.browser.menu.item.WebExtensionBrowserMenuItem @@ -97,21 +96,19 @@ class WebExtensionBrowserMenuBuilder( iconTintColorResource = style.webExtIconTintColorResource, ) - val addonsManagerMenuItem = BrowserMenuImageText( - label = context.getString(R.string.mozac_browser_menu_extensions_manager), - imageResource = style.addonsManagerMenuItemDrawableRes, - iconTintColorResource = style.webExtIconTintColorResource, - ) { - onAddonsManagerTapped.invoke() - } +// val addonsManagerMenuItem = BrowserMenuImageText( +// label = context.getString(R.string.mozac_browser_menu_extensions_manager), +// imageResource = style.addonsManagerMenuItemDrawableRes, +// iconTintColorResource = style.webExtIconTintColorResource, +// ) { +// onAddonsManagerTapped.invoke() +// } val webExtSubMenuItems = if (appendExtensionSubMenuAtStart) { listOf(backPressMenuItem) + BrowserMenuDivider() + - filteredExtensionMenuItems + - BrowserMenuDivider() + addonsManagerMenuItem + filteredExtensionMenuItems } else { - listOf(addonsManagerMenuItem) + BrowserMenuDivider() + - filteredExtensionMenuItems + + filteredExtensionMenuItems + BrowserMenuDivider() + backPressMenuItem } @@ -126,25 +123,28 @@ class WebExtensionBrowserMenuBuilder( endOfMenuAlwaysVisible = endOfMenuAlwaysVisible, ) } else { - BrowserMenuImageText( - label = context.getString(R.string.mozac_browser_menu_extensions), - imageResource = style.addonsManagerMenuItemDrawableRes, - iconTintColorResource = style.webExtIconTintColorResource, - ) { - onAddonsManagerTapped.invoke() - } +// BrowserMenuImageText( +// label = context.getString(R.string.mozac_browser_menu_extensions), +// imageResource = style.addonsManagerMenuItemDrawableRes, +// iconTintColorResource = style.webExtIconTintColorResource, +// ) { +// onAddonsManagerTapped.invoke() +// } + null } val mainMenuIndex = items.indexOfFirst { browserMenuItem -> (browserMenuItem as? WebExtensionPlaceholderMenuItem)?.id == WebExtensionPlaceholderMenuItem.MAIN_EXTENSIONS_MENU_ID } - return if (mainMenuIndex != -1) { + return if (mainMenuIndex != -1 && addonsMenuItem != null) { items[mainMenuIndex] = addonsMenuItem items // if we do not have a placeholder we should add the extension submenu at top or bottom } else { - if (appendExtensionSubMenuAtStart) { + if (addonsMenuItem == null) { + items + } else if (appendExtensionSubMenuAtStart) { listOf(addonsMenuItem) + items } else { items + addonsMenuItem diff --git a/mobile/android/android-components/components/browser/thumbnails/src/main/java/mozilla/components/browser/thumbnails/utils/ThumbnailDiskCache.kt b/mobile/android/android-components/components/browser/thumbnails/src/main/java/mozilla/components/browser/thumbnails/utils/ThumbnailDiskCache.kt index d3e53ae334cb9f1e62e5401ad69d8a46517c0823..afcd7818b6830354010811b148cc3f4f8de03f9b 100644 --- a/mobile/android/android-components/components/browser/thumbnails/src/main/java/mozilla/components/browser/thumbnails/utils/ThumbnailDiskCache.kt +++ b/mobile/android/android-components/components/browser/thumbnails/src/main/java/mozilla/components/browser/thumbnails/utils/ThumbnailDiskCache.kt @@ -7,6 +7,7 @@ package mozilla.components.browser.thumbnails.utils import android.content.Context import android.graphics.Bitmap import android.os.Build +import android.os.StrictMode import androidx.annotation.VisibleForTesting import com.jakewharton.disklrucache.DiskLruCache import mozilla.components.concept.base.images.ImageLoadRequest @@ -14,6 +15,7 @@ import mozilla.components.concept.base.images.ImageSaveRequest import mozilla.components.support.base.log.logger.Logger import java.io.File import java.io.IOException +import mozilla.components.support.ktx.android.os.resetAfter private const val MAXIMUM_CACHE_THUMBNAIL_DATA_BYTES: Long = 1024L * 1024L * 100L // 100 MB private const val THUMBNAIL_DISK_CACHE_VERSION = 1 @@ -34,10 +36,12 @@ class ThumbnailDiskCache(private val isPrivate: Boolean = false) { internal fun clear(context: Context) { synchronized(thumbnailCacheWriteLock) { - try { - getThumbnailCache(context).delete() - } catch (e: IOException) { - logger.warn("Thumbnail cache could not be cleared. Perhaps there are none?") + StrictMode.allowThreadDiskWrites().resetAfter { + try { + getThumbnailCache(context).delete() + } catch (e: IOException) { + logger.warn("Thumbnail cache could not be cleared. Perhaps there are none?") + } } thumbnailCache = null } diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt b/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt index 268f903c79ad1bdd867c5c658649b95be3d3eed6..c87f9296c94ef4b7287709eae7d1b8abe1abba81 100644 --- a/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt +++ b/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt @@ -488,6 +488,7 @@ class DisplayToolbar internal constructor( @ColorInt val color = when (siteSecurity) { Toolbar.SiteSecurity.INSECURE -> colors.securityIconInsecure Toolbar.SiteSecurity.SECURE -> colors.securityIconSecure + Toolbar.SiteSecurity.ONION -> colors.securityIconSecure } if (color == Color.TRANSPARENT && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { views.securityIndicator.clearColorFilter() diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt b/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt index 879897bc5668563ce995b649a66ecc944ed14d3a..00ee96bee1826c97f7bd39d1fcbd7072d34931ff 100644 --- a/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt +++ b/mobile/android/android-components/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt @@ -43,6 +43,11 @@ internal class SiteSecurityIconView @JvmOverloads constructor( View.mergeDrawableStates(drawableState, intArrayOf(R.attr.state_site_secure)) drawableState } + SiteSecurity.ONION -> { + val drawableState = super.onCreateDrawableState(extraSpace + 1) + View.mergeDrawableStates(drawableState, intArrayOf(R.attr.state_site_onion)) + drawableState + } } } } diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml b/mobile/android/android-components/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml index ab2b8d0e37f04c211a216620b55bcc78c0a421b6..2db972d288264c5b0cbca43e5276a506efb33b45 100644 --- a/mobile/android/android-components/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml +++ b/mobile/android/android-components/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml @@ -3,6 +3,9 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ac="http://schemas.android.com/apk/res-auto"> + <item + android:drawable="@drawable/mozac_ic_onion" + ac:state_site_onion="true" /> <item android:drawable="@drawable/mozac_ic_lock_24" ac:state_site_secure="true" /> diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml b/mobile/android/android-components/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml index 431bb6b080764098d9b25db68491cddd8adf6703..dd959709ea2cbf70eca5efbaf84be69ba7102cd1 100644 --- a/mobile/android/android-components/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml +++ b/mobile/android/android-components/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml @@ -27,6 +27,10 @@ <attr name="state_site_secure" format="boolean"/> </declare-styleable> + <declare-styleable name="BrowserToolbarSiteOnionState"> + <attr name="state_site_onion" format="boolean"/> + </declare-styleable> + <declare-styleable name="ActionContainer"> <attr name="actionContainerItemSize" format="dimension" /> </declare-styleable> diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt index d479274d94bbd5c3034cb17eb1ecb89b94e0baf7..ef881fb641d5ee77b0e13e91e97b1b0a86844e98 100644 --- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt +++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt @@ -8,6 +8,7 @@ import android.content.Intent import androidx.annotation.CallSuper import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_ALL import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_FIRST_PARTY_AND_ISOLATE_OTHERS +import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_ONLY_FIRST_PARTY import mozilla.components.concept.engine.content.blocking.Tracker import mozilla.components.concept.engine.history.HistoryItem import mozilla.components.concept.engine.manifest.WebAppManifest @@ -549,7 +550,9 @@ abstract class EngineSession( companion object { fun none() = TrackingProtectionPolicy( trackingCategories = arrayOf(TrackingCategory.NONE), - cookiePolicy = ACCEPT_ALL, + useForPrivateSessions = false, + useForRegularSessions = false, + cookiePolicy = ACCEPT_ONLY_FIRST_PARTY, ) /** diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt index 3f7e5dae0086da827de7ce03e293faec27234d48..f16a68f804d95037ab6824a5b5d319409afce13b 100644 --- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt +++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt @@ -278,6 +278,13 @@ abstract class Settings { * Setting to control the user characteristic ping current version. */ open var userCharacteristicPingCurrentVersion: Int by UnsupportedSetting() + + /** + * Setting to control the current security level + */ + open var torSecurityLevel: Int by UnsupportedSetting() + + open var spoofEnglish: Boolean by UnsupportedSetting() } /** @@ -333,6 +340,8 @@ data class DefaultSettings( override var queryParameterStrippingStripList: String = "", override var emailTrackerBlockingPrivateBrowsing: Boolean = false, override var userCharacteristicPingCurrentVersion: Int = 0, + override var torSecurityLevel: Int = 4, + override var spoofEnglish: Boolean = false, ) : Settings() class UnsupportedSetting<T> { diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/cookiehandling/CookieBannersStorage.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/cookiehandling/CookieBannersStorage.kt index 8ccbdc0f65f0cb691e022863c14b64e4417d9d4f..f05412d74ad2e2ab749a6f36a27dbc5a7c6ec9c3 100644 --- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/cookiehandling/CookieBannersStorage.kt +++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/cookiehandling/CookieBannersStorage.kt @@ -24,14 +24,14 @@ interface CookieBannersStorage { * Check if the given site's domain url is saved locally. * @param siteDomain the [siteDomain] that will be checked. */ - suspend fun isSiteDomainReported(siteDomain: String): Boolean +// suspend fun isSiteDomainReported(siteDomain: String): Boolean /** * Save the given site's domain url in datastore to keep it persistent locally. * This method gets called after the site domain was reported with Nimbus. * @param siteDomain the [siteDomain] that will be saved. */ - suspend fun saveSiteDomain(siteDomain: String) +// suspend fun saveSiteDomain(siteDomain: String) /** * Set persistently the [CookieBannerHandlingMode.DISABLED] mode for the given [uri] in diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtension.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtension.kt index 70cace99a43081386b8fbf7079f38edccf29ddb9..016244ce207d0bfd938ba65fc620b7313941c6ec 100644 --- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtension.kt +++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtension.kt @@ -164,6 +164,14 @@ abstract class WebExtension( */ open fun isBuiltIn(): Boolean = Uri.parse(url).scheme == "resource" + /** + * Checks whether or not this extension is bundled with this browser, + * but otherwise behaves as an unprivileged (non built-in) extension, + * except it cannot be disabled or uninstalled from the UI (e.g. + * NoScript in the Tor Browser). + */ + open fun isBundled(): Boolean = id == "{73a6fe31-595d-460b-a920-fcc0f8843232}" + /** * Checks whether or not this extension is enabled. */ diff --git a/mobile/android/android-components/components/concept/engine/src/test/java/mozilla/components/concept/engine/SettingsTest.kt b/mobile/android/android-components/components/concept/engine/src/test/java/mozilla/components/concept/engine/SettingsTest.kt index 80b7b93ac94c52ccb74794d42bb4d5bbf37aa749..9bbd9ea83e0abb05fad17bb7293a02498856e875 100644 --- a/mobile/android/android-components/components/concept/engine/src/test/java/mozilla/components/concept/engine/SettingsTest.kt +++ b/mobile/android/android-components/components/concept/engine/src/test/java/mozilla/components/concept/engine/SettingsTest.kt @@ -180,7 +180,7 @@ class SettingsTest { cookieBannerHandlingDetectOnlyMode = true, cookieBannerHandlingGlobalRules = true, cookieBannerHandlingGlobalRulesSubFrames = true, - emailTrackerBlockingPrivateBrowsing = true, + emailTrackerBlockingPrivateBrowsing = false, ) assertFalse(defaultSettings.domStorageEnabled) diff --git a/mobile/android/android-components/components/concept/fetch/src/main/java/mozilla/components/concept/fetch/Request.kt b/mobile/android/android-components/components/concept/fetch/src/main/java/mozilla/components/concept/fetch/Request.kt index 7ea1a46df30d48e00f81c61a53f2d67d46d17770..a7967ecfc29a5047ad7446a38d4065be3be6a6a4 100644 --- a/mobile/android/android-components/components/concept/fetch/src/main/java/mozilla/components/concept/fetch/Request.kt +++ b/mobile/android/android-components/components/concept/fetch/src/main/java/mozilla/components/concept/fetch/Request.kt @@ -49,6 +49,7 @@ data class Request( val cookiePolicy: CookiePolicy = CookiePolicy.INCLUDE, val useCaches: Boolean = true, val private: Boolean = false, + val origin: String? = null, ) { var referrerUrl: String? = null var conservative: Boolean = false diff --git a/mobile/android/android-components/components/concept/toolbar/src/main/java/mozilla/components/concept/toolbar/Toolbar.kt b/mobile/android/android-components/components/concept/toolbar/src/main/java/mozilla/components/concept/toolbar/Toolbar.kt index 506921d19424d7e6a75ee19522c290ba916598cc..eb7bc3eb513e159c40aef493ffa08d2ffd1d0b03 100644 --- a/mobile/android/android-components/components/concept/toolbar/src/main/java/mozilla/components/concept/toolbar/Toolbar.kt +++ b/mobile/android/android-components/components/concept/toolbar/src/main/java/mozilla/components/concept/toolbar/Toolbar.kt @@ -488,6 +488,7 @@ interface Toolbar : ScrollableToolbar { enum class SiteSecurity { INSECURE, SECURE, + ONION, } /** diff --git a/mobile/android/android-components/components/feature/accounts/build.gradle b/mobile/android/android-components/components/feature/accounts/build.gradle index b508fe6697eaabaaa5f259268f937194bf213985..51e55859ec2a3a6b8a33a60100b0aacf58fd9804 100644 --- a/mobile/android/android-components/components/feature/accounts/build.gradle +++ b/mobile/android/android-components/components/feature/accounts/build.gradle @@ -8,6 +8,10 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { + androidResources { + ignoreAssetsPattern '!<dir>extensions' + } + defaultConfig { minSdkVersion config.minSdkVersion compileSdk config.compileSdkVersion diff --git a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt index 723d3e6eb113896624ac864805c27e11265eb0b6..7c7af07485718f668211ebd82db02e0d086ab4ab 100644 --- a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt +++ b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt @@ -78,7 +78,7 @@ class AddonManager( * the [addonsProvider] or querying web extension state from the engine / store. */ @Throws(AddonManagerException::class) - @Suppress("TooGenericExceptionCaught") + @Suppress("TooGenericExceptionCaught", "UNUSED_PARAMETER") suspend fun getAddons(waitForPendingActions: Boolean = true, allowCache: Boolean = true): List<Addon> { try { // Make sure extension support is initialized, i.e. the state of all installed extensions is known. @@ -92,6 +92,7 @@ class AddonManager( // Get all the featured add-ons not installed from provider. // NB: We're keeping translations only for the default locale. var featuredAddons = emptyList<Addon>() + /* tor-browser#40502: Do not recommend addons on Tor Browser try { val userLanguage = Locale.getDefault().language val locales = listOf(userLanguage) @@ -103,6 +104,7 @@ class AddonManager( // Do not throw when we fail to fetch the featured add-ons since there can be installed add-ons. logger.warn("Failed to get the featured add-ons", throwable) } + */ // Build a list of installed extensions that are not built-in extensions. val installedAddons = installedExtensions @@ -494,6 +496,7 @@ class AddonManager( val installedAddon = Addon.newFromWebExtension(ext, installedState) addonUpdater.registerForFutureUpdates(installedAddon.id) + setAddonAllowedInPrivateBrowsing(installedAddon, true) completePendingAddonAction(pendingAction) onSuccess(installedAddon) } diff --git a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/amo/AMOAddonsProvider.kt b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/amo/AMOAddonsProvider.kt index e5a49d7b8fe782ba1550b42fecc0c46141a2e0cf..61bdb721486d9f6413cb6875a5b5154f2567b1cd 100644 --- a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/amo/AMOAddonsProvider.kt +++ b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/amo/AMOAddonsProvider.kt @@ -63,7 +63,7 @@ internal const val PAGE_SIZE = 50 * should remain valid before a refresh is attempted. Defaults to -1, meaning no cache * is being used by default */ -class AMOAddonsProvider( +open class AMOAddonsProvider( private val context: Context, private val client: Client, private val serverURL: String = DEFAULT_SERVER_URL, @@ -237,7 +237,7 @@ class AMOAddonsProvider( } @VisibleForTesting - internal fun writeToDiskCache(collectionResponse: String, language: String?) { + open fun writeToDiskCache(collectionResponse: String, language: String?) { synchronized(diskCacheLock) { getCacheFile(context, language, useFallbackFile = false).writeString { collectionResponse } } diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/layout/mozac_feature_addons_fragment_dialog_addon_installed.xml b/mobile/android/android-components/components/feature/addons/src/main/res/layout/mozac_feature_addons_fragment_dialog_addon_installed.xml index 3c23c7a8448256018ce4118aea54798e50962f3c..31453a8e0650c630d0ddcc3af5485af2400c2b63 100644 --- a/mobile/android/android-components/components/feature/addons/src/main/res/layout/mozac_feature_addons_fragment_dialog_addon_installed.xml +++ b/mobile/android/android-components/components/feature/addons/src/main/res/layout/mozac_feature_addons_fragment_dialog_addon_installed.xml @@ -53,6 +53,7 @@ tools:text="@string/mozac_feature_addons_installed_dialog_description_2" /> <androidx.appcompat.widget.AppCompatCheckBox + android:visibility="gone" android:id="@+id/allow_in_private_browsing" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/mobile/android/android-components/components/feature/app-links/build.gradle b/mobile/android/android-components/components/feature/app-links/build.gradle index 71f94f3bc80e1be606c24c1246e136e5ae3050ff..47a8314a98706589754056b35ec2da0d7f910244 100644 --- a/mobile/android/android-components/components/feature/app-links/build.gradle +++ b/mobile/android/android-components/components/feature/app-links/build.gradle @@ -46,6 +46,7 @@ dependencies { implementation project(':ui-widgets') implementation ComponentsDependencies.kotlin_coroutines + implementation project(path: ':support-utils') testImplementation project(':support-test') testImplementation project(':support-test-libstate') diff --git a/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksFeature.kt b/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksFeature.kt index 102f8c173d131a95faf153e3768780559228b8e1..fe4b175040a37c5c07096f1da07dd0cec13c24aa 100644 --- a/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksFeature.kt +++ b/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksFeature.kt @@ -108,7 +108,7 @@ class AppLinksFeature( } @Suppress("ComplexCondition") - if (isAuthentication(tab, appIntent) || (!tab.content.private && !shouldPrompt()) || + if (isAuthentication(tab, appIntent) || (true || !tab.content.private && !shouldPrompt()) || fragmentManager == null ) { doOpenApp() diff --git a/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksUseCases.kt b/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksUseCases.kt index 4b00a69fb3d57ea760c0b9cb285d47a19280064b..a1eb0682e042a2131b5493c04a63ae9f5ed96680 100644 --- a/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksUseCases.kt +++ b/mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksUseCases.kt @@ -23,6 +23,7 @@ import mozilla.components.support.utils.BrowsersCache import mozilla.components.support.utils.ext.queryIntentActivitiesCompat import mozilla.components.support.utils.ext.resolveActivityCompat import java.net.URISyntaxException +import mozilla.components.support.utils.TorUtils @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal const val EXTRA_BROWSER_FALLBACK_URL = "browser_fallback_url" @@ -239,7 +240,7 @@ class AppLinksUseCases( if (launchInNewTask) { it.flags = it.flags or Intent.FLAG_ACTIVITY_NEW_TASK } - context.startActivity(it) + TorUtils.startActivityPrompt(context, it) } catch (e: Exception) { when (e) { is ActivityNotFoundException, is SecurityException, is NullPointerException -> { diff --git a/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionAutocompleteProvider.kt b/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionAutocompleteProvider.kt index e044586ac0233ea48344c10536309f98030eda84..2497780583eadda788d233acf2559851234dce42 100644 --- a/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionAutocompleteProvider.kt +++ b/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionAutocompleteProvider.kt @@ -36,7 +36,7 @@ class SessionAutocompleteProvider( val tabUrl = store.state.tabs .firstOrNull { - !it.content.private && doesUrlStartsWithText(it.content.url, query) + /* !it.content.private && */ doesUrlStartsWithText(it.content.url, query) } ?.content?.url ?: return null diff --git a/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionSuggestionProvider.kt b/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionSuggestionProvider.kt index d94e94153ee6570d3a6f45d1e02e0e51e7be21e9..74f149c762307001eff951ad3d83fcf9eb6afc4f 100644 --- a/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionSuggestionProvider.kt +++ b/mobile/android/android-components/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SessionSuggestionProvider.kt @@ -54,7 +54,7 @@ class SessionSuggestionProvider( val suggestions = mutableListOf<AwesomeBar.Suggestion>() val iconRequests: List<Deferred<Icon>?> = distinctTabs.map { - icons?.loadIcon(IconRequest(url = it.content.url, waitOnNetworkLoad = false)) + icons?.loadIcon(IconRequest(url = it.content.url, isPrivate = it.content.private, waitOnNetworkLoad = false)) } val searchWords = searchText.split(" ") @@ -62,7 +62,7 @@ class SessionSuggestionProvider( if ( resultsUriFilter?.invoke(result.content.url.toUri()) != false && searchWords.all { result.contains(it) } && - !result.content.private && + // !result.content.private && shouldIncludeSelectedTab(state, result) ) { suggestions.add( diff --git a/mobile/android/android-components/components/feature/contextmenu/src/main/java/mozilla/components/feature/contextmenu/ContextMenuCandidate.kt b/mobile/android/android-components/components/feature/contextmenu/src/main/java/mozilla/components/feature/contextmenu/ContextMenuCandidate.kt index 9a8f26e942a2c921428bdec799800def3c2170d5..136af70d1564f3200c32c052e248a141f1647318 100644 --- a/mobile/android/android-components/components/feature/contextmenu/src/main/java/mozilla/components/feature/contextmenu/ContextMenuCandidate.kt +++ b/mobile/android/android-components/components/feature/contextmenu/src/main/java/mozilla/components/feature/contextmenu/ContextMenuCandidate.kt @@ -28,6 +28,7 @@ import mozilla.components.support.ktx.kotlin.stripMailToProtocol import mozilla.components.support.ktx.kotlin.takeOrReplace import mozilla.components.ui.widgets.DefaultSnackbarDelegate import mozilla.components.ui.widgets.SnackbarDelegate +import mozilla.components.support.utils.TorUtils /** * A candidate for an item to be displayed in the context menu. @@ -495,7 +496,8 @@ data class ContextMenuCandidate( } try { - context.startActivity( + TorUtils.startActivityPrompt( + context, intent.createChooserExcludingCurrentApp( context, context.getString(R.string.mozac_feature_contextmenu_share_link), diff --git a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/AbstractFetchDownloadService.kt b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/AbstractFetchDownloadService.kt index e3c5acf8052db6ad5766739b67af6917b66bee31..205d1cd7809b74ae50f79d18d19901ff7ce6a95b 100644 --- a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/AbstractFetchDownloadService.kt +++ b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/AbstractFetchDownloadService.kt @@ -77,6 +77,7 @@ import mozilla.components.support.ktx.kotlinx.coroutines.throttleLatest import mozilla.components.support.utils.DownloadUtils import mozilla.components.support.utils.ext.registerReceiverCompat import mozilla.components.support.utils.ext.stopForegroundCompat +import mozilla.components.support.utils.TorUtils import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -1018,7 +1019,7 @@ abstract class AbstractFetchDownloadService : Service() { val newIntent = createOpenFileIntent(applicationContext, download) return try { - applicationContext.startActivity(newIntent) + TorUtils.startActivityPrompt(applicationContext, newIntent) true } catch (error: ActivityNotFoundException) { false diff --git a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadsFeature.kt b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadsFeature.kt index a5b94c0545cc3fd72a0b6e432adb8cb0b3af29db..09ec02b67a7ed9b71e60531274dd3c2fd35a870b 100644 --- a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadsFeature.kt +++ b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadsFeature.kt @@ -28,7 +28,6 @@ import mozilla.components.feature.downloads.dialog.DeniedPermissionDialogFragmen import mozilla.components.feature.downloads.ext.realFilenameOrGuessed import mozilla.components.feature.downloads.facts.emitPromptDismissedFact import mozilla.components.feature.downloads.facts.emitPromptDisplayedFact -import mozilla.components.feature.downloads.manager.AndroidDownloadManager import mozilla.components.feature.downloads.manager.DownloadManager import mozilla.components.feature.downloads.manager.noop import mozilla.components.feature.downloads.manager.onDownloadStopped @@ -112,7 +111,7 @@ class DownloadsFeature( internal val useCases: DownloadsUseCases, override var onNeedToRequestPermissions: OnNeedToRequestPermissions = { }, onDownloadStopped: onDownloadStopped = noop, - private val downloadManager: DownloadManager = AndroidDownloadManager(applicationContext, store), + private val downloadManager: DownloadManager, private val tabId: String? = null, private val fragmentManager: FragmentManager? = null, private val promptsStyling: PromptsStyling? = null, diff --git a/mobile/android/android-components/components/feature/downloads/src/test/java/mozilla/components/feature/downloads/DownloadsFeatureTest.kt b/mobile/android/android-components/components/feature/downloads/src/test/java/mozilla/components/feature/downloads/DownloadsFeatureTest.kt index 58bc71f27698a22fe0e895b625937fc915b7602d..3d84835361addf7049bdc5dfd13d73d5a73372bc 100644 --- a/mobile/android/android-components/components/feature/downloads/src/test/java/mozilla/components/feature/downloads/DownloadsFeatureTest.kt +++ b/mobile/android/android-components/components/feature/downloads/src/test/java/mozilla/components/feature/downloads/DownloadsFeatureTest.kt @@ -78,60 +78,60 @@ class DownloadsFeatureTest { ) } - @Test - fun `Adding a download object will request permissions if needed`() { - val fragmentManager: FragmentManager = mock() - - val download = DownloadState(url = "https://www.mozilla.org", sessionId = "test-tab") - - var requestedPermissions = false - - val feature = DownloadsFeature( - testContext, - store, - useCases = mock(), - onNeedToRequestPermissions = { requestedPermissions = true }, - fragmentManager = mockFragmentManager(), - ) - - feature.start() - - assertFalse(requestedPermissions) - - store.dispatch(ContentAction.UpdateDownloadAction("test-tab", download)) - .joinBlocking() - - dispatcher.scheduler.advanceUntilIdle() - - assertTrue(requestedPermissions) - verify(fragmentManager, never()).beginTransaction() - } - - @Test - fun `Adding a download when permissions are granted will show dialog`() { - val fragmentManager: FragmentManager = mockFragmentManager() - - grantPermissions() - - val feature = DownloadsFeature( - testContext, - store, - useCases = mock(), - fragmentManager = fragmentManager, - ) - - feature.start() - - verify(fragmentManager, never()).beginTransaction() - val download = DownloadState(url = "https://www.mozilla.org", sessionId = "test-tab") - - store.dispatch(ContentAction.UpdateDownloadAction("test-tab", download)) - .joinBlocking() - - dispatcher.scheduler.advanceUntilIdle() - - verify(fragmentManager).beginTransaction() - } +// @Test +// fun `Adding a download object will request permissions if needed`() { +// val fragmentManager: FragmentManager = mock() +// +// val download = DownloadState(url = "https://www.mozilla.org", sessionId = "test-tab") +// +// var requestedPermissions = false +// +// val feature = DownloadsFeature( +// testContext, +// store, +// useCases = mock(), +// onNeedToRequestPermissions = { requestedPermissions = true }, +// fragmentManager = mockFragmentManager(), +// ) +// +// feature.start() +// +// assertFalse(requestedPermissions) +// +// store.dispatch(ContentAction.UpdateDownloadAction("test-tab", download)) +// .joinBlocking() +// +// dispatcher.scheduler.advanceUntilIdle() +// +// assertTrue(requestedPermissions) +// verify(fragmentManager, never()).beginTransaction() +// } + +// @Test +// fun `Adding a download when permissions are granted will show dialog`() { +// val fragmentManager: FragmentManager = mockFragmentManager() +// +// grantPermissions() +// +// val feature = DownloadsFeature( +// testContext, +// store, +// useCases = mock(), +// fragmentManager = fragmentManager, +// ) +// +// feature.start() +// +// verify(fragmentManager, never()).beginTransaction() +// val download = DownloadState(url = "https://www.mozilla.org", sessionId = "test-tab") +// +// store.dispatch(ContentAction.UpdateDownloadAction("test-tab", download)) +// .joinBlocking() +// +// dispatcher.scheduler.advanceUntilIdle() +// +// verify(fragmentManager).beginTransaction() +// } @Test fun `Try again calls download manager`() { @@ -974,136 +974,136 @@ class DownloadsFeatureTest { verify(spyContext, times(0)).startActivity(any()) } - @Test - fun `GIVEN permissions are granted WHEN our app is selected for download THEN perform the download`() { - val spyContext = spy(testContext) - val usecases: DownloadsUseCases = mock() - val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() - doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload - val tab = createTab("https://www.mozilla.org", id = "test-tab") - val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") - val ourApp = DownloaderApp(name = "app", packageName = testContext.packageName, resolver = mock(), activityName = "", url = "", contentType = null) - var wasPermissionsRequested = false - val feature = spy( - DownloadsFeature( - applicationContext = testContext, - store = mock(), - useCases = usecases, - onNeedToRequestPermissions = { wasPermissionsRequested = true }, - ), - ) - doReturn(false).`when`(feature).startDownload(any()) - - grantPermissions() - feature.onDownloaderAppSelected(ourApp, tab, download) - - verify(feature).startDownload(download) - verify(consumeDownloadUseCase).invoke(tab.id, download.id) - assertFalse(wasPermissionsRequested) - verify(spyContext, never()).startActivity(any()) - } - - @Test - fun `GIVEN permissions are not granted WHEN our app is selected for download THEN request the needed permissions`() { - val spyContext = spy(testContext) - val usecases: DownloadsUseCases = mock() - val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() - doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload - val tab = createTab("https://www.mozilla.org", id = "test-tab") - val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") - val ourApp = DownloaderApp(name = "app", packageName = testContext.packageName, resolver = mock(), activityName = "", url = "", contentType = null) - var wasPermissionsRequested = false - val feature = spy( - DownloadsFeature( - applicationContext = testContext, - store = mock(), - useCases = usecases, - onNeedToRequestPermissions = { wasPermissionsRequested = true }, - ), - ) - - feature.onDownloaderAppSelected(ourApp, tab, download) - - verify(feature, never()).startDownload(any()) - verify(consumeDownloadUseCase, never()).invoke(anyString(), anyString()) - assertTrue(wasPermissionsRequested) - verify(spyContext, never()).startActivity(any()) - } - - @Test - fun `GIVEN a download WHEN a 3rd party app is selected THEN delegate download to it`() { - val spyContext = spy(testContext) - val usecases: DownloadsUseCases = mock() - val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() - doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload - val tab = createTab("https://www.mozilla.org", id = "test-tab") - val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") - val anotherApp = DownloaderApp( - name = "app", - packageName = "test", - resolver = mock(), - activityName = "", - url = download.url, - contentType = null, - ) - val feature = spy( - DownloadsFeature( - applicationContext = spyContext, - store = mock(), - useCases = usecases, - ), - ) - val intentArgumentCaptor = argumentCaptor<Intent>() - val expectedIntent = with(feature) { anotherApp.toIntent() } - - feature.onDownloaderAppSelected(anotherApp, tab, download) - - verify(spyContext).startActivity(intentArgumentCaptor.capture()) - assertEquals(expectedIntent.toUri(0), intentArgumentCaptor.value.toUri(0)) - verify(consumeDownloadUseCase).invoke(tab.id, download.id) - verify(feature, never()).startDownload(any()) - assertNull(ShadowToast.getTextOfLatestToast()) - } - - @Test - fun `GIVEN a download WHEN a 3rd party app is selected and the download fails THEN show a warning toast and consume the download`() { - val spyContext = spy(testContext) - val usecases: DownloadsUseCases = mock() - val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() - doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload - val tab = createTab("https://www.mozilla.org", id = "test-tab") - val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") - val anotherApp = DownloaderApp( - name = "app", - packageName = "test", - resolver = mock(), - activityName = "", - url = download.url, - contentType = null, - ) - val feature = spy( - DownloadsFeature( - applicationContext = spyContext, - store = mock(), - useCases = usecases, - ), - ) - val expectedWarningText = testContext.getString( - R.string.mozac_feature_downloads_unable_to_open_third_party_app, - anotherApp.name, - ) - val intentArgumentCaptor = argumentCaptor<Intent>() - val expectedIntent = with(feature) { anotherApp.toIntent() } - doThrow(ActivityNotFoundException()).`when`(spyContext).startActivity(any()) - - feature.onDownloaderAppSelected(anotherApp, tab, download) - - verify(spyContext).startActivity(intentArgumentCaptor.capture()) - assertEquals(expectedIntent.toUri(0), intentArgumentCaptor.value.toUri(0)) - verify(consumeDownloadUseCase).invoke(tab.id, download.id) - verify(feature, never()).startDownload(any()) - assertEquals(expectedWarningText, ShadowToast.getTextOfLatestToast()) - } +// @Test +// fun `GIVEN permissions are granted WHEN our app is selected for download THEN perform the download`() { +// val spyContext = spy(testContext) +// val usecases: DownloadsUseCases = mock() +// val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() +// doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload +// val tab = createTab("https://www.mozilla.org", id = "test-tab") +// val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") +// val ourApp = DownloaderApp(name = "app", packageName = testContext.packageName, resolver = mock(), activityName = "", url = "", contentType = null) +// var wasPermissionsRequested = false +// val feature = spy( +// DownloadsFeature( +// applicationContext = testContext, +// store = mock(), +// useCases = usecases, +// onNeedToRequestPermissions = { wasPermissionsRequested = true }, +// ), +// ) +// doReturn(false).`when`(feature).startDownload(any()) +// +// grantPermissions() +// feature.onDownloaderAppSelected(ourApp, tab, download) +// +// verify(feature).startDownload(download) +// verify(consumeDownloadUseCase).invoke(tab.id, download.id) +// assertFalse(wasPermissionsRequested) +// verify(spyContext, never()).startActivity(any()) +// } + +// @Test +// fun `GIVEN permissions are not granted WHEN our app is selected for download THEN request the needed permissions`() { +// val spyContext = spy(testContext) +// val usecases: DownloadsUseCases = mock() +// val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() +// doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload +// val tab = createTab("https://www.mozilla.org", id = "test-tab") +// val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") +// val ourApp = DownloaderApp(name = "app", packageName = testContext.packageName, resolver = mock(), activityName = "", url = "", contentType = null) +// var wasPermissionsRequested = false +// val feature = spy( +// DownloadsFeature( +// applicationContext = testContext, +// store = mock(), +// useCases = usecases, +// onNeedToRequestPermissions = { wasPermissionsRequested = true }, +// ), +// ) +// +// feature.onDownloaderAppSelected(ourApp, tab, download) +// +// verify(feature, never()).startDownload(any()) +// verify(consumeDownloadUseCase, never()).invoke(anyString(), anyString()) +// assertTrue(wasPermissionsRequested) +// verify(spyContext, never()).startActivity(any()) +// } + +// @Test +// fun `GIVEN a download WHEN a 3rd party app is selected THEN delegate download to it`() { +// val spyContext = spy(testContext) +// val usecases: DownloadsUseCases = mock() +// val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() +// doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload +// val tab = createTab("https://www.mozilla.org", id = "test-tab") +// val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") +// val anotherApp = DownloaderApp( +// name = "app", +// packageName = "test", +// resolver = mock(), +// activityName = "", +// url = download.url, +// contentType = null, +// ) +// val feature = spy( +// DownloadsFeature( +// applicationContext = spyContext, +// store = mock(), +// useCases = usecases, +// ), +// ) +// val intentArgumentCaptor = argumentCaptor<Intent>() +// val expectedIntent = with(feature) { anotherApp.toIntent() } +// +// feature.onDownloaderAppSelected(anotherApp, tab, download) +// +// verify(spyContext).startActivity(intentArgumentCaptor.capture()) +// assertEquals(expectedIntent.toUri(0), intentArgumentCaptor.value.toUri(0)) +// verify(consumeDownloadUseCase).invoke(tab.id, download.id) +// verify(feature, never()).startDownload(any()) +// assertNull(ShadowToast.getTextOfLatestToast()) +// } + +// @Test +// fun `GIVEN a download WHEN a 3rd party app is selected and the download fails THEN show a warning toast and consume the download`() { +// val spyContext = spy(testContext) +// val usecases: DownloadsUseCases = mock() +// val consumeDownloadUseCase: ConsumeDownloadUseCase = mock() +// doReturn(consumeDownloadUseCase).`when`(usecases).consumeDownload +// val tab = createTab("https://www.mozilla.org", id = "test-tab") +// val download = DownloadState(url = "https://www.mozilla.org/file.txt", sessionId = "test-tab", id = "test") +// val anotherApp = DownloaderApp( +// name = "app", +// packageName = "test", +// resolver = mock(), +// activityName = "", +// url = download.url, +// contentType = null, +// ) +// val feature = spy( +// DownloadsFeature( +// applicationContext = spyContext, +// store = mock(), +// useCases = usecases, +// ), +// ) +// val expectedWarningText = testContext.getString( +// R.string.mozac_feature_downloads_unable_to_open_third_party_app, +// anotherApp.name, +// ) +// val intentArgumentCaptor = argumentCaptor<Intent>() +// val expectedIntent = with(feature) { anotherApp.toIntent() } +// doThrow(ActivityNotFoundException()).`when`(spyContext).startActivity(any()) +// +// feature.onDownloaderAppSelected(anotherApp, tab, download) +// +// verify(spyContext).startActivity(intentArgumentCaptor.capture()) +// assertEquals(expectedIntent.toUri(0), intentArgumentCaptor.value.toUri(0)) +// verify(consumeDownloadUseCase).invoke(tab.id, download.id) +// verify(feature, never()).startDownload(any()) +// assertEquals(expectedWarningText, ShadowToast.getTextOfLatestToast()) +// } @Test fun `when an app third party is selected for downloading we MUST forward the download`() { diff --git a/mobile/android/android-components/components/feature/privatemode/src/main/java/mozilla/components/feature/privatemode/notification/PrivateNotificationFeature.kt b/mobile/android/android-components/components/feature/privatemode/src/main/java/mozilla/components/feature/privatemode/notification/PrivateNotificationFeature.kt index 2dc3086fd566cef2643f4845e705c6003e1fb6c7..bd9ea70fafe7069e9f01f1b1bb8da6c9a69b6720 100644 --- a/mobile/android/android-components/components/feature/privatemode/src/main/java/mozilla/components/feature/privatemode/notification/PrivateNotificationFeature.kt +++ b/mobile/android/android-components/components/feature/privatemode/src/main/java/mozilla/components/feature/privatemode/notification/PrivateNotificationFeature.kt @@ -44,6 +44,7 @@ class PrivateNotificationFeature<T : AbstractPrivateNotificationService>( } override fun stop() { + applicationContext.stopService(Intent(applicationContext, notificationServiceClass.java)) scope?.cancel() } } diff --git a/mobile/android/android-components/components/feature/search/build.gradle b/mobile/android/android-components/components/feature/search/build.gradle index da63f030ee4d37a868c82a06eaaef14ad4f777eb..eb4bc822f2720d530434c7fa8184c9e4595d8613 100644 --- a/mobile/android/android-components/components/feature/search/build.gradle +++ b/mobile/android/android-components/components/feature/search/build.gradle @@ -8,6 +8,10 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { + androidResources { + ignoreAssetsPattern '!<dir>extensions:!search_telemetry_v2.json:!amazon*:!azerdict*:!baidu*:!bing*:!ceneje*:!coccoc*:!daum*:!ebay*:!ecosia*:!faclair*:!google*:!gulesider*:!leo*:!mapy*:!mercadolibre*:!odpiralni*:!pazaruvaj*:!prisjakt*:!qwant*:!rakuten*:!salidzinilv*:!seznam*:!vatera*:!wikipedia-*:!wiktionary*:!yahoo*:!yandex*' + } + defaultConfig { minSdkVersion config.minSdkVersion compileSdk config.compileSdkVersion diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json b/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json index 5bd6349fe540545ff49b3c3a1b17a14fa6cb7587..f3fdb39026242c1967abf901f940a04d37025612 100644 --- a/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json +++ b/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json @@ -1,1064 +1,21 @@ { "default": { - "searchDefault": "Google", - "searchOrder": ["Google", "Bing"], - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"] + "searchDefault": "DuckDuckGo", + "searchOrder": [ + "DuckDuckGo", + "DuckDuckGo (.onion)", + "Startpage", + "Startpage (.onion)", + "Wikipedia" + ], + "visibleDefaultEngines": [ + "ddg", + "ddg-onion", + "startpage", + "startpage-onion", + "wikipedia" + ] }, - "regionOverrides": { - "US": { - "google-b-m": "google-b-1-m" - } - }, - "locales": { - "ach": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"] - } - }, - "an": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-es", - "wikipedia-an" - ] - } - }, - "ar": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ar"] - } - }, - "as": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-as"] - } - }, - "ast": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-es", - "wikipedia-ast" - ] - } - }, - "az": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "azerdict", - "wikipedia-az" - ] - } - }, - "be": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-be"] - }, - "BY": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-be" - ] - }, - "KZ": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-be" - ] - }, - "RU": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-be" - ] - }, - "TR": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-be" - ] - } - }, - "bg": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "pazaruvaj", - "wikipedia-bg" - ] - } - }, - "bn": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"] - } - }, - "bn-BD": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"] - } - }, - "bn-IN": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"] - } - }, - "br": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-br"] - } - }, - "bs": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bs"] - } - }, - "ca": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-es", - "wikipedia-ca" - ] - } - }, - "cak": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"] - } - }, - "cs": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "mapy-cz", - "seznam-cz", - "wikipedia-cz" - ] - } - }, - "cy": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-co-uk", - "wikipedia-cy" - ] - } - }, - "da": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-da"] - } - }, - "de": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ecosia", - "qwant", - "wikipedia-de", - "ebay-de" - ] - } - }, - "de-AT": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ecosia", - "qwant", - "wikipedia-de", - "ebay-at" - ] - } - }, - "dsb": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-dsb", - "ebay-de" - ] - } - }, - "el": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-el"] - } - }, - "en-AU": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia", - "ebay-au" - ] - } - }, - "en-CA": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia", - "ebay-ca" - ] - } - }, - "en-IE": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "qwant", - "wikipedia", - "ebay-ie" - ] - } - }, - "en-GB": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "qwant", - "wikipedia", - "ebay-co-uk" - ] - }, - "BY": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "qwant", - "wikipedia" - ] - }, - "KZ": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "qwant", - "wikipedia" - ] - }, - "RU": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "qwant", - "wikipedia" - ] - }, - "TR": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "qwant", - "wikipedia" - ] - } - }, - "en-US": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay", - "wikipedia" - ] - }, - "BY": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia" - ] - }, - "KZ": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia" - ] - }, - "RU": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia" - ] - }, - "TR": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia" - ] - } - }, - "en-ZA": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia"] - } - }, - "eo": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-eo"] - } - }, - "es-AR": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "ddg", - "mercadolibre-ar", - "wikipedia-es" - ] - } - }, - "es-CL": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "mercadolibre-cl", - "wikipedia-es" - ] - } - }, - "es-ES": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-es", - "ebay-es" - ] - } - }, - "es-MX": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "mercadolibre-mx", - "wikipedia-es" - ] - } - }, - "et": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-et"] - } - }, - "eu": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-es", - "wikipedia-eu" - ] - } - }, - "fa": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fa"] - } - }, - "ff": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fr"] - } - }, - "fi": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fi"] - } - }, - "fr-BE": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "qwant", - "wikipedia-fr", - "ebay-befr" - ] - } - }, - "fr-CA": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-fr", - "ebay-ca" - ] - } - }, - "fr-FR": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "qwant", - "wikipedia-fr", - "ebay-fr" - ] - } - }, - "fr": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-fr", - "qwant", - "wikipedia-fr" - ] - } - }, - "fy-NL": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-nl", - "wikipedia-fy-NL" - ] - } - }, - "ga-IE": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "ddg", - "ebay-ie", - "wikipedia-ga-IE" - ] - } - }, - "gd": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-co-uk", - "faclair-beag", - "wikipedia-gd" - ] - } - }, - "gl": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-es", - "wikipedia-gl" - ] - } - }, - "gn": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-gn"] - } - }, - "gu-IN": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-gu"] - } - }, - "he": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-he"] - } - }, - "hi-IN": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hi"] - } - }, - "hr": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hr"] - } - }, - "hsb": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-hsb", - "ebay-de" - ] - } - }, - "hu": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "vatera", "wikipedia-hu"] - } - }, - "hy-AM": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-hy-AM" - ] - } - }, - "ia": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ia"] - } - }, - "id": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-id"] - } - }, - "is": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-is"] - } - }, - "it": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-it", - "ebay-it" - ] - } - }, - "ja": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "amazon-jp", - "bing", - "ddg", - "rakuten", - "wikipedia-ja", - "yahoo-jp", - "yahoo-jp-auctions" - ] - } - }, - "ka": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ka"] - } - }, - "kab": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-kab"] - } - }, - "kk": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-kk"] - }, - "KZ": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-kk" - ] - }, - "BY": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-kk" - ] - }, - "RU": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-kk" - ] - }, - "TR": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "bing", - "ddg", - "wikipedia-kk" - ] - } - }, - "km": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-km"] - } - }, - "kn": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-kn", - "wiktionary-kn" - ] - } - }, - "ko": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "daum-kr"] - } - }, - "lij": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-lij", - "ebay-it" - ] - } - }, - "lo": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-lo"] - } - }, - "lt": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-lt"] - } - }, - "ltg": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "wikipedia-ltg"] - } - }, - "lv": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "ddg", - "salidzinilv", - "wikipedia-lv" - ] - } - }, - "mai": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hi"] - } - }, - "meh": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"] - } - }, - "mix": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"] - } - }, - "ml": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ml"] - } - }, - "mr": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-mr"] - } - }, - "ms": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ms"] - } - }, - "my": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-my"] - } - }, - "nb-NO": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "gulesider-mobile-NO", - "wikipedia-NO" - ] - } - }, - "ne-NP": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ne"] - } - }, - "nl-NL": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-nl", - "ebay-nl" - ] - } - }, - "nl": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-nl", - "wikipedia-nl" - ] - } - }, - "nn-NO": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "gulesider-mobile-NO", - "wikipedia-NN" - ] - } - }, - "oc": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-oc", - "wiktionary-oc" - ] - } - }, - "or": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-or", - "wiktionary-or" - ] - } - }, - "pa-IN": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-pa"] - } - }, - "pl": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-pl", - "ebay-pl" - ] - } - }, - "pt-BR": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-pt"] - } - }, - "pt-PT": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-pt"] - } - }, - "rm": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-ch", - "leo_ende_de", - "wikipedia-rm" - ] - } - }, - "ro": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ro"] - } - }, - "ru": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-ru"] - }, - "RU": { - "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"] - }, - "BY": { - "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"] - }, - "KZ": { - "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"] - }, - "TR": { - "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"] - } - }, - "sk": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-sk"] - } - }, - "sl": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "ddg", - "ceneje", - "odpiralni", - "wikipedia-sl" - ] - } - }, - "son": { - "default": { - "visibleDefaultEngines": ["google-b-m", "ddg", "bing", "wikipedia-fr"] - } - }, - "sq": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-sq"] - } - }, - "sr": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-sr"] - } - }, - "sv-SE": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "prisjakt-sv-SE", - "ddg", - "wikipedia-sv-SE", - "ebay-ch" - ] - } - }, - "ta": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-ta", - "wiktionary-ta" - ] - } - }, - "te": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-te", - "wiktionary-te" - ] - } - }, - "th": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-th"] - } - }, - "tl": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg"] - } - }, - "tr": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-tr"] - }, - "TR": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "ddg", - "bing", - "wikipedia-tr" - ] - }, - "BY": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "ddg", - "bing", - "wikipedia-tr" - ] - }, - "KZ": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "ddg", - "bing", - "wikipedia-tr" - ] - }, - "RU": { - "visibleDefaultEngines": [ - "google-com-nocodes", - "ddg", - "bing", - "wikipedia-tr" - ] - } - }, - "trs": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"] - } - }, - "uk": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-uk"] - } - }, - "ur": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ur"] - } - }, - "uz": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-uz"] - } - }, - "vi": { - "default": { - "visibleDefaultEngines": ["google-b-m", "coccoc", "ddg", "wikipedia-vi"] - } - }, - "wo": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "ebay-fr", - "wikipedia-wo" - ] - } - }, - "xh": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"] - } - }, - "zam": { - "default": { - "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"] - } - }, - "zh-CN": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "baidu", - "bing", - "ddg", - "wikipedia-zh-CN" - ] - }, - "CN": { - "searchDefault": "百度" - } - }, - "zh-TW": { - "default": { - "visibleDefaultEngines": [ - "google-b-m", - "bing", - "ddg", - "wikipedia-zh-TW" - ] - } - } - } + "regionOverrides": {}, + "locales": {} } diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg-onion.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg-onion.xml new file mode 100644 index 0000000000000000000000000000000000000000..998592291cc95e72d905480cb60cd09cba8f5a7f --- /dev/null +++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg-onion.xml @@ -0,0 +1,10 @@ +<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> +<ShortName>DuckDuckGo (.onion)</ShortName> +<Description>Duck Duck Go Onion</Description> +<InputEncoding>UTF-8</InputEncoding> +<Image width="32" height="32">data:image/png;base64,AAABAAIAEBAAAAEAIAB5AwAAJgAAACAgAAABACAAUAcAAJ8DAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAANASURBVDiNpZNNTFsFAMd/76t9rx+UsZYCGTNsIytVsXGGA5qNmAjG0Ok+OsXNuIMas4MnT4o6g4bTYnYw7jCnS/QAZHMmbBlKluzCphlK5mAbAcamlKyUQt+jtH19Hx6MZpz93f6X3+n/g/+J8OiYTe0KObLysikqRz3F9WeVcsVTUr1rjs9z04vTr66YVxqGx4sCuBsELgj39rW1CtWevkDjzqT60mHU5icRbBvbKmOvrmKODrF669qIvZr/aFvLjXHhU5z/BHOH2p6SNkdGwq8cjUqxXVTSM6xfGcYYHESMBAkeeofgiylYnGPpu5O5tfRMsuXc5BiAeG/PHlUO+ftq33gvaksa6SMdWOlZNn1wkoYz55DDtegDp/irpx3TWCOServGH6k/PptsigKIVqPdEYi3JcXGGJkP30Lt7kHb/y4KoD3dTrj/NJ5YHEJBMn3HsMNbCTXFXyAQTg6mkMQKbq+3qwdjZACpfivSa8e4PZ1leaWA48KkZwfLWiOyK+NKGsblAZTnDyAGQnvjk3FJpGgm5Ooa9KGvkULViKEwur5OJmciCpDOLFNqqMX/hA81plL+5WeUphZESdpdVaVLslYu+SVfACuTRaxrxLOWIxGvQ7H+xJkfYq9gU9zxALPawV1SyN+YBcdFFgkthm1Briieius6indnM1ZBpzh5nWjnQTDuYM+8T26sFtv1IdYoFCZcxFAEx1yn4rJgZiVXNP3qWOnuTdTnunBWsli3fvvnIb527HA/eANomoKdFnBWdYIH3oRCAWxnKpxVHVFx7W/Kl76nqqsHwTCwp+9iAkib8FTtQ/gjwsV1l/lFG3G5SLDzINbV8wjF0pfNMzOmLD+sXDCU6WHt/lR39PMz5E8c5/dfB/lKuYSl51lOZpmvdei/bZD4+BTkFliauDaa0x9cfQxccfvoeN61jN7sD6cfSppM3bcX8W/egmWVEVSN1+V2DrsdxE6cR/BB5uwXufLC4ieJH+/nN7ZwJNEqaDWfVcef6RY6X6UYDhGoieIt2RhT49iXByjM3fnJ0fXeba0TG1v4l7HUFq1Ord9dcb29brGc0MqlgKl4zYpPvS5jnzXN/IXHh6ZWHq3xb489Z7RfaFfAAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHF0lEQVRYhZ2XX2xT9xXHP7/r6z+x48Qhc1lCWWzKopFOqluHDW0SCZuElmpIqaASoRXwMCL2MNE1PGyTNog6qXsoLbBpMHgBNAqVyBaaqbDugaSaSlXwlq4hrNkgzhgOYEJMnFw7zvX97eHa13bsFLrzZJ/7+53v95x7/l3BY8p4Z7sv65rptCHapCSEQgCJDwBBAoOoFAxL5JAtXdMf7B9MPI5d8UjgresCSH2PVOROC/AxRMIJBXtv8OxH0f+LwHhnu4+qmX1SilfyOteaMO617VS1hFH9DShuLwCGliQTHWN+YgztyiDp65ECESEOKim9N9g/XDEiFQmMb10XkCxcAgIA1es3UbdlF6q/8fOcsUSPx5g+d5zZDwbyqqjAvqFSNMoIjG9bG5KG8UcgoPobWd7zBo6mZsvThxfOkB6NoMcn0eMxABSPF0dTM+7WdjytbRZRPR5j8rXd+XNRoSgvBN++MrwkgWLPves3sWzHqyhuL3o8xtztKE6HE0NLMndlCC0yiDGXrBiB6rZN1G02I2ZoSeJHetGuDlaMRAmBm1vD40DA3drO8p43AHh44Qwzl87je/nHiIYmHLXLcDgc6PEYU6fezBsuE8Xtxbelm9qOLgDuH+0lOTRgkkhnn83nhM3yvuu5t0B8T/U38uWfHkbYnUz3HWP6zG8wZh6g/fU9tEvnma+px/nkKhw1dVR/ayN2fyOZiTEMrTQaciFD6pPLIKCqJYyrJczc5b9gaEmftNtch0dif7YikAv9OMDKw++i+ht5eOEMD04dsAw6NnRS/+IPcdXVV/S4yMMyWba9h9qOLjITY9z+ybZc6O3B4NmPogqAwcI+MLNd9Teix2Mk+o4VwDteouEHP1sS3AR5dckqSZw7hh6P4Whqpnr9JgAMufAKgDK+M+QTsBOgbssuAKb7jhcSrO4Jlm/7EZ/+8w7vf/AZs9p8GcC/J6a4PDrFQkd3RQKGliR+tJdiDKGwY7wz5FOzaaVTwWwyee9ni0Jp+8Z3UVUVj8fJxpbKHq5uqmd1Uz2GVs+tPm/F6kiPRjC0JKq/EVdLmPRoxJd12TsVgWgDcK9tB2Du6lDJRfvK1RbIrDbPnXjl0vvtqQ+5PHof15pwxecAD987A4C71cSyYbSpQhBCgjPXbMrKyuWxfvb8coDqKie9PRupdjtLjn0YiQLwNX/DkgTyLbqqxSQphQip5NqtI2ASyEyMlVxayHU7gG+HAwBl4AC/P2Rm9/S5EQAUF1Q/DVUrIX4RjDTo8UkAVIukDKj5CWcNlkXvT0/OWL+3b24tPMgmYepPoJUS9j75Gd5uUGtyXt8ywYFC685hIfGpZa4sljtRMpkMDoejVD/6EmRiZcdVOxiGCZwcgdlrn29eRZBA4jO0JIrba1VCXsTkBKlUqpRAaswCT92Ce+dNL9UaMDIFjxdL8fg2jZNQgCiAfm/x+8nJ5DjzD6dLdY4GsJnGbC5QcimhzywNDlhTNRPNvzYRVZF8AoRS1yM4As241oRJj0ZKLmo3rsFXAgWFzQvNv4Obe3H4Y6zcBZl4KbhaC5l7cLe/oMuX+nwu0YWUw4qBHIRC+dU+31XG3Bj5GF3XS5XuZvj6u+iebpLXAGmCqrUmkeSImf3F4mltoxgL5JBqcxn9ct72Vno04tPjseJOZV0Uk1Hm5uaora0tI5ccgcSFMnWZFM8Zy3ba6FeCJ4YTEk6COQMA/Lv3oXi8hdvj10gnpioati8aQP9qsPHfeqVEp3i8JXMGQMCJYP9wQgFQZPYgwOzQAJnoGKq/kbrNpYMldfM6ALMLST598Hfm9FkAXC3PMeVV0JyCP3zTzq87HFwMlVZ33ebuCnMm2wugAgTPDkdvdIUPCcmeu2/uZcWvTlPT0YUxl2Q6N5aNkY9JrfsOF28PcHL8CABP1z7DvfQd4i86MbIGQhEIKIlA3eZu05aWZPK13QBIyaFV7wxHAayTijO7H4jmVy0A35Zu6rf3oHi8iMko6XRpjf1j6m/c0XI9Q0BWzwLwoFqgeLzUb+/Bt8WMZPxIr7WcPvVOxFr1LQLBE8MJQXYDEJ0dGuDugb0YWpKaji5WvH6a6pWrSE1P8VTNV5FSmlExDOy6HbtuJ/CfecLX01TfT7HM/iVWvH7a8jx+tHgpzW4oduKRa3nDz48W1mxdJy1TvPz+9/HYa9gb+gXPPrEWMLcegJrnu6yOl5kY4+6BvUVrefaF4NvDS6/lFomtoYDEVvgwKVqzwUzEaru30lWTaDzGdN/x4sUmKshuCJ413/sjCeTlRlf4oJDsyf93tYRxt7bjbGrGEWgu6e36vUlS1yNoVwdLeoiUHFLms/u/0KdZseSisR/Y8aizRVYT0uCkIrIHK3n9hQhYRDpDvqxL6VQQ7QjxDMjSz3NEVEgxnCU7ZEsb/Ut5vFj+B4mSK5j/ya9iAAAAAElFTkSuQmCC</Image> +<Url type="text/html" method="GET" template="https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/"> + <Param name="q" value="{searchTerms}"/> +</Url> +<SearchForm>https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion</SearchForm> +</SearchPlugin> diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml index 21364b08aaea37e76d43baa3a98e5043261950ae..5166d9c5243bd05234daea4bba9a1b287e404c96 100644 --- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml +++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml @@ -6,18 +6,8 @@ <ShortName>DuckDuckGo</ShortName> <InputEncoding>UTF-8</InputEncoding> <Image width="32" height="32">data:image/png;base64,AAABAAIAEBAAAAEAIAB5AwAAJgAAACAgAAABACAAUAcAAJ8DAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAANASURBVDiNpZNNTFsFAMd/76t9rx+UsZYCGTNsIytVsXGGA5qNmAjG0Ok+OsXNuIMas4MnT4o6g4bTYnYw7jCnS/QAZHMmbBlKluzCphlK5mAbAcamlKyUQt+jtH19Hx6MZpz93f6X3+n/g/+J8OiYTe0KObLysikqRz3F9WeVcsVTUr1rjs9z04vTr66YVxqGx4sCuBsELgj39rW1CtWevkDjzqT60mHU5icRbBvbKmOvrmKODrF669qIvZr/aFvLjXHhU5z/BHOH2p6SNkdGwq8cjUqxXVTSM6xfGcYYHESMBAkeeofgiylYnGPpu5O5tfRMsuXc5BiAeG/PHlUO+ftq33gvaksa6SMdWOlZNn1wkoYz55DDtegDp/irpx3TWCOServGH6k/PptsigKIVqPdEYi3JcXGGJkP30Lt7kHb/y4KoD3dTrj/NJ5YHEJBMn3HsMNbCTXFXyAQTg6mkMQKbq+3qwdjZACpfivSa8e4PZ1leaWA48KkZwfLWiOyK+NKGsblAZTnDyAGQnvjk3FJpGgm5Ooa9KGvkULViKEwur5OJmciCpDOLFNqqMX/hA81plL+5WeUphZESdpdVaVLslYu+SVfACuTRaxrxLOWIxGvQ7H+xJkfYq9gU9zxALPawV1SyN+YBcdFFgkthm1Briieius6indnM1ZBpzh5nWjnQTDuYM+8T26sFtv1IdYoFCZcxFAEx1yn4rJgZiVXNP3qWOnuTdTnunBWsli3fvvnIb527HA/eANomoKdFnBWdYIH3oRCAWxnKpxVHVFx7W/Kl76nqqsHwTCwp+9iAkib8FTtQ/gjwsV1l/lFG3G5SLDzINbV8wjF0pfNMzOmLD+sXDCU6WHt/lR39PMz5E8c5/dfB/lKuYSl51lOZpmvdei/bZD4+BTkFliauDaa0x9cfQxccfvoeN61jN7sD6cfSppM3bcX8W/egmWVEVSN1+V2DrsdxE6cR/BB5uwXufLC4ieJH+/nN7ZwJNEqaDWfVcef6RY6X6UYDhGoieIt2RhT49iXByjM3fnJ0fXeba0TG1v4l7HUFq1Ord9dcb29brGc0MqlgKl4zYpPvS5jnzXN/IXHh6ZWHq3xb489Z7RfaFfAAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHF0lEQVRYhZ2XX2xT9xXHP7/r6z+x48Qhc1lCWWzKopFOqluHDW0SCZuElmpIqaASoRXwMCL2MNE1PGyTNog6qXsoLbBpMHgBNAqVyBaaqbDugaSaSlXwlq4hrNkgzhgOYEJMnFw7zvX97eHa13bsFLrzZJ/7+53v95x7/l3BY8p4Z7sv65rptCHapCSEQgCJDwBBAoOoFAxL5JAtXdMf7B9MPI5d8UjgresCSH2PVOROC/AxRMIJBXtv8OxH0f+LwHhnu4+qmX1SilfyOteaMO617VS1hFH9DShuLwCGliQTHWN+YgztyiDp65ECESEOKim9N9g/XDEiFQmMb10XkCxcAgIA1es3UbdlF6q/8fOcsUSPx5g+d5zZDwbyqqjAvqFSNMoIjG9bG5KG8UcgoPobWd7zBo6mZsvThxfOkB6NoMcn0eMxABSPF0dTM+7WdjytbRZRPR5j8rXd+XNRoSgvBN++MrwkgWLPves3sWzHqyhuL3o8xtztKE6HE0NLMndlCC0yiDGXrBiB6rZN1G02I2ZoSeJHetGuDlaMRAmBm1vD40DA3drO8p43AHh44Qwzl87je/nHiIYmHLXLcDgc6PEYU6fezBsuE8Xtxbelm9qOLgDuH+0lOTRgkkhnn83nhM3yvuu5t0B8T/U38uWfHkbYnUz3HWP6zG8wZh6g/fU9tEvnma+px/nkKhw1dVR/ayN2fyOZiTEMrTQaciFD6pPLIKCqJYyrJczc5b9gaEmftNtch0dif7YikAv9OMDKw++i+ht5eOEMD04dsAw6NnRS/+IPcdXVV/S4yMMyWba9h9qOLjITY9z+ybZc6O3B4NmPogqAwcI+MLNd9Teix2Mk+o4VwDteouEHP1sS3AR5dckqSZw7hh6P4Whqpnr9JgAMufAKgDK+M+QTsBOgbssuAKb7jhcSrO4Jlm/7EZ/+8w7vf/AZs9p8GcC/J6a4PDrFQkd3RQKGliR+tJdiDKGwY7wz5FOzaaVTwWwyee9ni0Jp+8Z3UVUVj8fJxpbKHq5uqmd1Uz2GVs+tPm/F6kiPRjC0JKq/EVdLmPRoxJd12TsVgWgDcK9tB2Du6lDJRfvK1RbIrDbPnXjl0vvtqQ+5PHof15pwxecAD987A4C71cSyYbSpQhBCgjPXbMrKyuWxfvb8coDqKie9PRupdjtLjn0YiQLwNX/DkgTyLbqqxSQphQip5NqtI2ASyEyMlVxayHU7gG+HAwBl4AC/P2Rm9/S5EQAUF1Q/DVUrIX4RjDTo8UkAVIukDKj5CWcNlkXvT0/OWL+3b24tPMgmYepPoJUS9j75Gd5uUGtyXt8ywYFC685hIfGpZa4sljtRMpkMDoejVD/6EmRiZcdVOxiGCZwcgdlrn29eRZBA4jO0JIrba1VCXsTkBKlUqpRAaswCT92Ce+dNL9UaMDIFjxdL8fg2jZNQgCiAfm/x+8nJ5DjzD6dLdY4GsJnGbC5QcimhzywNDlhTNRPNvzYRVZF8AoRS1yM4As241oRJj0ZKLmo3rsFXAgWFzQvNv4Obe3H4Y6zcBZl4KbhaC5l7cLe/oMuX+nwu0YWUw4qBHIRC+dU+31XG3Bj5GF3XS5XuZvj6u+iebpLXAGmCqrUmkeSImf3F4mltoxgL5JBqcxn9ct72Vno04tPjseJOZV0Uk1Hm5uaora0tI5ccgcSFMnWZFM8Zy3ba6FeCJ4YTEk6COQMA/Lv3oXi8hdvj10gnpioati8aQP9qsPHfeqVEp3i8JXMGQMCJYP9wQgFQZPYgwOzQAJnoGKq/kbrNpYMldfM6ALMLST598Hfm9FkAXC3PMeVV0JyCP3zTzq87HFwMlVZ33ebuCnMm2wugAgTPDkdvdIUPCcmeu2/uZcWvTlPT0YUxl2Q6N5aNkY9JrfsOF28PcHL8CABP1z7DvfQd4i86MbIGQhEIKIlA3eZu05aWZPK13QBIyaFV7wxHAayTijO7H4jmVy0A35Zu6rf3oHi8iMko6XRpjf1j6m/c0XI9Q0BWzwLwoFqgeLzUb+/Bt8WMZPxIr7WcPvVOxFr1LQLBE8MJQXYDEJ0dGuDugb0YWpKaji5WvH6a6pWrSE1P8VTNV5FSmlExDOy6HbtuJ/CfecLX01TfT7HM/iVWvH7a8jx+tHgpzW4oduKRa3nDz48W1mxdJy1TvPz+9/HYa9gb+gXPPrEWMLcegJrnu6yOl5kY4+6BvUVrefaF4NvDS6/lFomtoYDEVvgwKVqzwUzEaru30lWTaDzGdN/x4sUmKshuCJ413/sjCeTlRlf4oJDsyf93tYRxt7bjbGrGEWgu6e36vUlS1yNoVwdLeoiUHFLms/u/0KdZseSisR/Y8aizRVYT0uCkIrIHK3n9hQhYRDpDvqxL6VQQ7QjxDMjSz3NEVEgxnCU7ZEsb/Ut5vFj+B4mSK5j/ya9iAAAAAElFTkSuQmCC</Image> -<Url type="application/x-suggestions+json" method="GET" template="https://ac.duckduckgo.com/ac/"> - <Param name="q" value="{searchTerms}"/> - <Param name="type" value="list"/> -</Url> -<!-- this is effectively x-moz-phonesearch, but search service expects a text/html entry --> <Url type="text/html" method="GET" template="https://duckduckgo.com/"> - <Param name="q" value="{searchTerms}" /> - <Param name="t" value="fpas" /> -</Url> -<Url type="application/x-moz-tabletsearch" method="GET" template="https://duckduckgo.com/"> - <Param name="q" value="{searchTerms}" /> - <Param name="t" value="fpas" /> + <Param name="q" value="{searchTerms}"/> </Url> <SearchForm>https://duckduckgo.com</SearchForm> </SearchPlugin> diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage-onion.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage-onion.xml new file mode 100644 index 0000000000000000000000000000000000000000..21542704a769a17ba08f1a3e8019a3c1d560642d --- /dev/null +++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage-onion.xml @@ -0,0 +1,11 @@ +<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> +<ShortName>Startpage (.onion)</ShortName> +<Description>Start Page Onion</Description> +<InputEncoding>UTF-8</InputEncoding> +<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAASsUlEQVR42qSXXWoCQRCElzxKTiOeSMBLhuAZgscQAR/dXU2aBfnggykaIpTTU9aU3fO3OtXro7C1y/LcFY7zvH4Xbsuy/lZ/wzwTgxWIG2rpqxXy+L4u51+89G2soe/vft6rPRdO6/r6fM/3hndQHx5K+IORk9yM3sUoebSMYTLQo8EPrvoFPODXOIH4AHjGhlg52ROu4AUd1EMsr0thzyLUqwT7Iq8qhsJVcNgNWhgVKA06ChfgKdq8NZ4QeBYZvTSatKQJ34V24HMtHLYFeDxen/XBxRP+HlwIhVmjogQKt6fjcVs69RlPzoAxWUMtLDy8a8BLebj+MHa7bXZTdU7hDvUJsMY8eiF4tjR4DxEW2SfMnj6VQHXJX2jw8jxO9XYOiScT0DqSGXnX+JnSf3ZYj681juUvfS//AYfn11TB3XeWJ9JHzn34NRz3yNPCA1090vmaCt72NWfPkW94FihP8Z7n2+RdTCuT/NNS0A7KC5fAjst5mnfuLt65CT1PanHN8PYyPw0mV6tMrCNtTXpgd+KwCI77z5LC6GpreMKHuttXkjFx/FKy8P04JIPGY80L0sJ3Y+Mf9dlTdcf/EGzwqXNcQG/HEftEdTzQ3/94NQsey2EYCPfHHjMzMzMzMzMzMzMzM1HsOyvqKoo+PW+PJFnPTbPJBjyZcfou6JNnQe89DHrzzi+7HfT+Qyuzd9ReIIZDRmKsIpup0T+zLqxbgAJ0pDxQu5yj88GEB3xa/+6DoDv2BZ2+QLT3cNF2vUWbdRZt2F60gVk7860svus1TNTq7tof9N4D3OEwaT+A1QSqD9HnQo/7Po+mAk5+EmPOhAL7gPYofJ+/DLphW9Dew0SbdLJJjlZOesP4HBcg95OFsb/tO0J04/agL16FPNQdRsT/Mws8H9o4QpgZFbUPM/8g4br+e9ux0xaUO1zrrIH9/olZhHQRnbNU9MGjAJTQ27EY3b4+YshyWVXBGJ51Ds/McHy28uZt0KVr4iQ1bFc3+eWONj+Wt4tl+bsYBeSr5uUtuor1ZX3CjgQm5pIDWKg/PMwLDp28w6wcfumUz9s7fzlojyEZlJRw0y61EnrA2gMEpX8Hz10Hip67mOM/CsMMSsj3oYi1D58thRNClK10cuKsBdZtDdrU4KadDyMMSXFn+3W5vvW9ZnPQr19rwoVzsFKmt0LikSGIGmfOy8KkrM/Zws+fg85eInFnlvCSQA1ObgYl7GvFOuaLTpoj+ukzirT6wocjQtnnqEhoKHcCUIP2A2Hn06egMxfahLjwYZPO5clzUk7PXB/aHTdD9MNHTE/TJGZ1kOl5rNGMUuiQimCYYeNbsLjzvwSdu1Q8ePgPxsxq8hzRj59C1WtRj/H5Io2FGB2edP3IORHKpm7aEcrBI7yk0FBCk/1GS+qY385ftNiG+Va/9MmkDgaXrBE+E6LhbvYXgJgVlpcLkIUgYppPzdL3F6+GUlT9qSWUlNkRl2tZhvXLhWzUQfTw8aB8fuFuBtjxoKt8Zis4xPyQ4nvgmKMx2ldBWGU7Pv4ahx88TnTBCtEtu4LuPRR03+Ggm3cGnb9cdMBo0eZd0ogQiBAf5lr3EH36HFiKn1rwYco3oqGcH/EvpqO/dK3HcJLJycptRw4cI7rnUEwn5JGZ+0+f2YKYtoC+KvgTZwv3xT7Dj79gWF5kDaO48G/6Y/nDx0FbdkvDXDn8gf10HiB65GSwwxvZCV/GR3v3Pi5Eq+65MmaxZpZS3cYdRC9c9oQk53KYFdX71i5NR3up55Tzkx907jJh9tGuNiuZOEv05eua4W/mvIvZ1J5Ds2hz/Vjf4O7rV0wdcyqG56nSTZtZ4Sk4Fh15hxEODLdzAcQwJBoXQWzRTKxB+Hqsg9+9fhPsfLBJTvqGhW9nJnV+446il6/57TNT+n2/AMWbVCIRxtCwYXsAeGH2UtLF6Qts8pN2mNK6H0Tl59TLV8HuE0DUKfrlppg+XxzqmZW7F/e+cC2q5UX42bh0v5HiCqDU+gwXw273do3f+f6tu3YmVBN7bXqKRRDMh8cQ/4gFBWVhFQj3acXt8DUG47AOKf1fdVWvXPcv25l1oGbBOhujGIyRaL8JNKZ+Ckknz1K/3L4v0DwDCHJui9JFKMvsSjANdVcEjZ8pGI7R5wVhsZjVy8Lckm49BmcCDZhYujlMd/gQYv0hbFY/A/zP6PikT/3pC6qF+oUr3F/1jwJ8ArH7YHD/nzQS7ACP6QnOhrJeqgRXeSqCuS03wrdkvYaWOyoNccrViHYbFJNgHMKQWUU4oPcYHXbOGDvjSU9yTZEwmDKOmVL6+jrf/f5OT/6GP3nML+V/eFicQ5OxGEsJ2GCcmy57VouWfJKIWSEL4sHVVqpmk2aX8JOkPtLUdZa+KFMTDD98PvlwxYtWMLTQd/gMSc+eB+PQJY56Zoq1FuxAH39u2/eGShB57eaf5Hf81H46pwVdMnNalS9rbt+LDCiKK/tlAVaWHz6RsS341DHzcedxOde3BOGVG/W3SI/99pmRVRdimFb2GUn8u+u34gKkjMIwt1M/UdMGY6eLzlosumiV6Ir1P5s7B5hLliyOdzbevNh+tm3btm3btm3btm1LY+OzdCe1de5MZTv5Tf1zUuPkbJ+tru66X3fX/wivniqSSOTlYE1PyjeuwXheiykoCsH9wMu8pEoYYC4aEQ0e8yY+9+q08NnX01MIp0ydZoLWYcSR95OEsrJrdT0arhHz3GtXdCJxIrcXHHSZr1DXDNCVkKsdA2E9PQ7eoSryA9GZgCIzW3hYkRmX9f1wu6qCC5BOZxTrymv1uK4VK78n749cV/d4hcRcfAWebamznI10bZa37pc8DbAMD2I6DpHAVx+n19K/IUEQ3A0+oZItzMgE8LXxxPmMzOn8HdYv9/cPhocffznc99DzLvrks+/d9+ccV+DKCAUa+GKFcaS2OBYQBpfY5i4DR8JhOn7z3W9hwSU3/T8ttVk8GtX+f42/6bZHZfql1mzgtJSyz6gSW0uVn2KcQovnBwaG4hc5ZEeupbWlIrI1Tz/nOnuwbnrz7U+dmd/ZsldVvI5rKiaqqtLMhswM7unpD1OmtIU//xoR3nzns3D/wy+ES668Mxx3ymVhrwNPC9vtekzYfLtDw/GnXj7jJeisPPKqfIrz/x0+Jiy54jbp4aavPcsvscLWYeSo8bi/r8CwUcRXOf96Im4dZkm8Eb+avQ88PWy01UFhmVW3T9u89scl2rR5XGSZLcIPP/3JFwCVUkGTjel8nBNOuyLBS1ofVP+tW+14RPRtDQAedUW+zv3RcoJpKQ4PKOHmsy9+dGzv2tcWae+DTrdd4NCusAsSyTov24GLLrdldv36eDp3xbX3qixoVahd2DkAFTIiDCh8LT29/fHrP5B/bOKXrPPTzy209Gbh3gefUxnFAo40/++wMWG19fYA1Ch+kWW3DN/98EfhuuV8lSu71BXsNN5uu+sJbPMZfyQgKG37JSI+v/Xu5zLVUfth+PLGjp0UNtv20Pp6aU1AkfGJdtj92LQjeX+qoq48KkKkESDImwGtgyITJ7WEldfeNVDgaThaZpXtw2tvfCyEWm6c5v8//46OQv4wrOehx596TbhecohgBNvJrVEmLYg3oBvaVRt1wy0PA1cJSaTFltsqXHPDA6GjozvdU6m3GLcv99U3PgprbLBn0cNfd5N9Q2dnj1cbEy0PRF8j3AdaEOFFGxEMuU2OKui6m+6XtnWiuvED7ah+tK/3hZffM03E7Sf6/Y9h4egTL4kYvsXMNBwX/+CjL2r4peVv5PNr6TFHgQZ4Pefl1z4IC0c1068VcXesE7/Ii6+4M3z48TfRtd0eY7R9sdpmIPTGF9Pd3dfU1Z9+7q1w4OHnmPDE9Xo9rtXV1ev4u43g/3Jfk3P5VMq6TbzOXKPFe9LpV+XwX42Dt6O9TNNoNtrywKadsdJau8w4J65z8kZPPvNGifYieuGBpMOxypRrQtDQ7503OFpaOurCMEEPtCBqJ+DTXEAH5lPzktfacdtdjrYdBYjw18NhTLZ8I8+AjMiIloYGzv3598iw6nq7Kwjg+Owntaa5Rkzwy0igf5y8vo6GGIuYyatSTfBffPVTWGGNnYofuh9SyiHonAtvgkUu3PCe5n1FlfJYIOukI58rRDCylwDcNoKfSGJ68+iHsaU4x4jzzSLfPDz74jsCKlRigoJoldOEgIzcWunmaivJ63/7fVjYYIsDhDD2jGP3SM2K44l4zbKr7RB+/f1fqQkRkksiYezMWClJrRtw4GVIN+74CVPCwUeeaz4gPDDBzzXacocjwtSWDpEOqcbLqRLuUxXxSnPFeW7R3ui0e+jRl0wu5CJU1GyW0scmUdvCXMynhhVOOuMqC2ESZgkxSivU7ZV1qwIjfv0MNfKYiPUGXHjU6Anh5DOvNheEgJG5TwtFeuCRFx2FIcXBevBITcw06cBXLnpEO9PyGuHnX/4OZ553fdwRO88WLWj51XdsWtBX33C/CdfcLpHjS628ncWRXUaZTl/UXSKpBdFVSmjSEt9hzBG6knx49MlXw0FHnGMaE2AEcFTj7YHtvNcJ4a77ngmjx0y0+zV9SSeefmWaU6ckzDFWW8sUBvNrAT5EwoKI0tGDUB+vdDWkL/9Fa0j+fv/JirYv0FJJLrv6rhg/vqIpvPc95MxwyFHnxfjy5eGiy28P9zzwbPjgo6/DxIkthtv4LS2tHdHQOrrYCDziuAvjixwU8V+k9Od6XUvNsYJ7OePnAP5jYeNL++eoOeX8sOFjw6rr7lYCZwZhFmTyuKYBv+R1UJ7SWTfqED4RGmNaZcs7+HROjj/V0Tyqiy+/FbQtusrJW8Tuo0++FXBcUiNmvxVBeboZSMiMwLgPhijg+VKyaY8Y5xg9liYf6vYHKckVGnRrb7yPyRZHdjXX5zh/byXaxIu8HPq3Ne47Glxwjib/fBPKpuMXq6f7HnyGxSPU+p4SWxWU123jncaa7p/DOSKQzW1NaOQHoRyLbW1dFnifadSMWhENtmtufAAQ44BDPAcVlHcGxlU3cu4m3WNI3F82T2XuDs/z9w8fOc7ixgUu8k0t8mYZHFifMezcruZvNb6iDeDpuY86L4dA4rieXwo7es7Hn34XFl9ha48qijkWmbOcIynj/BVA6QXMVL8FEZ5YcOB/4JxDyJKalS6Q0AaUJYTBhV2DIuE23zTsus9JseivB+s7C0EAs5Wjr40YU5oOrhUE2CCv0wKFLUIIMMPt1LOvhbvaa6hdeNntdj+t6fh7RyOoLoUaH65uAa9lhCPcV0wajtrau8Iue51Q5rSzIM4L78yu1ERZjCAgiEV1frVMQIvISypIB5S5TiOiUF5ro73toaqEACOMr7jmzpYyI7S4hlML0lADnpR7AfpFcA7y8OXa2gDzw6qVJC250rYlLnFLy+ffR/iRNRYVBB21IglPumM4eKTtOQS00/gp15osM441DTo0anTnvU/L6hz+Nn6oFaFE14SRz5UrqRqwEkNGV63r++sIlmVFnHHu9ZmcosQz7+jaGx8ocEcrCNK8hgU97pzbKLi3V/PS45YfZComv/ichpTqG8QajvHK0ZI3TRaYjmt1hTphhu3RtJMP17pc3BoqLOfUckUJP9wRzeqbP/4cAYPV7YpOL0D4LIQhJoPzYq4ytvBScOR53T+O62Mc8z/74ocklKU8OOv8G+EJSCQgHOOV16ynAC3QOvQc/zh3jfY16XvCs/vamx+HpVfZvp7oVU/2ssicQZa7pZtu1qG3rTMArb9I8mK+XsvbxxpqL8bltVZnNjqcFmuMLR5giVvmBzrmpEvDl1//LFzw0AJVR10644x02zDhHqafSLqu6W4WvEoP1B+FKHvFHKyZqm9a2zpDX/8g1hJQU9IvqMz092swLqGkzpH3+2Kc/1lDrCnWKno+oEpbr9qq1V3FBa+/fCGDClRl37Ug/bJ1VxnhX8Muq0QQvGDbN9yQItb19CzSc8rHC3jRrAP//TGOVwUuaDWuoUT3IHUeRTQO6xWOk/BVS9jTBS9oXdzi8Pkrw0s9GKG9ZHNQFSarB6ITx7QM0vP9YVPhmsF8O3bYC3gv0y8IhPPC8ICsUBBDEvgpHYRcQ8ooDaVaNdYRQ8I15tp9PrAXcHBBt0RvDpBf8PnTGP3ndUazKrSQvHhenKv5w80X9N/4Rn4CbMgsOUCJ2w2tx3lfrdU452i+/P4U5qKdDhLPfmk0pi1Q2b84edVIU7C1RNW4q5EHYU3BE+fwmtnEGznm6Plunw+P9qwbK1f1f3Fw5Ui/iC0+G6kxr++pr/HbCCXX/WQffFVV/2lS+h/7F/vmLxBPHh7pg0gdiOpo3ki4kItly3zL+w3NRkukd+ILONgg3551eu7/AxK2F7WQPNQ+AAAAAElFTkSuQmCC</Image> + +<Url type="text/html" method="POST" template="http://startpagel6srwcjlue4zgq3zevrujfaow726kjytqbbjyrswwmjzcqd.onion/sp/search"> + <Param name="q" value="{searchTerms}"/> +</Url> +<SearchForm>http://startpagel6srwcjlue4zgq3zevrujfaow726kjytqbbjyrswwmjzcqd.onion/sp/search/</SearchForm> +</SearchPlugin> diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage.xml new file mode 100644 index 0000000000000000000000000000000000000000..b34094cd4f96f0db37d5e8787076bd40881cddc1 --- /dev/null +++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/startpage.xml @@ -0,0 +1,11 @@ +<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> +<ShortName>Startpage</ShortName> +<Description>Start Page</Description> +<InputEncoding>UTF-8</InputEncoding> +<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAASsUlEQVR42qSXXWoCQRCElzxKTiOeSMBLhuAZgscQAR/dXU2aBfnggykaIpTTU9aU3fO3OtXro7C1y/LcFY7zvH4Xbsuy/lZ/wzwTgxWIG2rpqxXy+L4u51+89G2soe/vft6rPRdO6/r6fM/3hndQHx5K+IORk9yM3sUoebSMYTLQo8EPrvoFPODXOIH4AHjGhlg52ROu4AUd1EMsr0thzyLUqwT7Iq8qhsJVcNgNWhgVKA06ChfgKdq8NZ4QeBYZvTSatKQJ34V24HMtHLYFeDxen/XBxRP+HlwIhVmjogQKt6fjcVs69RlPzoAxWUMtLDy8a8BLebj+MHa7bXZTdU7hDvUJsMY8eiF4tjR4DxEW2SfMnj6VQHXJX2jw8jxO9XYOiScT0DqSGXnX+JnSf3ZYj681juUvfS//AYfn11TB3XeWJ9JHzn34NRz3yNPCA1090vmaCt72NWfPkW94FihP8Z7n2+RdTCuT/NNS0A7KC5fAjst5mnfuLt65CT1PanHN8PYyPw0mV6tMrCNtTXpgd+KwCI77z5LC6GpreMKHuttXkjFx/FKy8P04JIPGY80L0sJ3Y+Mf9dlTdcf/EGzwqXNcQG/HEftEdTzQ3/94NQsey2EYCPfHHjMzMzMzMzMzMzMzM1HsOyvqKoo+PW+PJFnPTbPJBjyZcfou6JNnQe89DHrzzi+7HfT+Qyuzd9ReIIZDRmKsIpup0T+zLqxbgAJ0pDxQu5yj88GEB3xa/+6DoDv2BZ2+QLT3cNF2vUWbdRZt2F60gVk7860svus1TNTq7tof9N4D3OEwaT+A1QSqD9HnQo/7Po+mAk5+EmPOhAL7gPYofJ+/DLphW9Dew0SbdLJJjlZOesP4HBcg95OFsb/tO0J04/agL16FPNQdRsT/Mws8H9o4QpgZFbUPM/8g4br+e9ux0xaUO1zrrIH9/olZhHQRnbNU9MGjAJTQ27EY3b4+YshyWVXBGJ51Ds/McHy28uZt0KVr4iQ1bFc3+eWONj+Wt4tl+bsYBeSr5uUtuor1ZX3CjgQm5pIDWKg/PMwLDp28w6wcfumUz9s7fzlojyEZlJRw0y61EnrA2gMEpX8Hz10Hip67mOM/CsMMSsj3oYi1D58thRNClK10cuKsBdZtDdrU4KadDyMMSXFn+3W5vvW9ZnPQr19rwoVzsFKmt0LikSGIGmfOy8KkrM/Zws+fg85eInFnlvCSQA1ObgYl7GvFOuaLTpoj+ukzirT6wocjQtnnqEhoKHcCUIP2A2Hn06egMxfahLjwYZPO5clzUk7PXB/aHTdD9MNHTE/TJGZ1kOl5rNGMUuiQimCYYeNbsLjzvwSdu1Q8ePgPxsxq8hzRj59C1WtRj/H5Io2FGB2edP3IORHKpm7aEcrBI7yk0FBCk/1GS+qY385ftNiG+Va/9MmkDgaXrBE+E6LhbvYXgJgVlpcLkIUgYppPzdL3F6+GUlT9qSWUlNkRl2tZhvXLhWzUQfTw8aB8fuFuBtjxoKt8Zis4xPyQ4nvgmKMx2ldBWGU7Pv4ahx88TnTBCtEtu4LuPRR03+Ggm3cGnb9cdMBo0eZd0ogQiBAf5lr3EH36HFiKn1rwYco3oqGcH/EvpqO/dK3HcJLJycptRw4cI7rnUEwn5JGZ+0+f2YKYtoC+KvgTZwv3xT7Dj79gWF5kDaO48G/6Y/nDx0FbdkvDXDn8gf10HiB65GSwwxvZCV/GR3v3Pi5Eq+65MmaxZpZS3cYdRC9c9oQk53KYFdX71i5NR3up55Tzkx907jJh9tGuNiuZOEv05eua4W/mvIvZ1J5Ds2hz/Vjf4O7rV0wdcyqG56nSTZtZ4Sk4Fh15hxEODLdzAcQwJBoXQWzRTKxB+Hqsg9+9fhPsfLBJTvqGhW9nJnV+446il6/57TNT+n2/AMWbVCIRxtCwYXsAeGH2UtLF6Qts8pN2mNK6H0Tl59TLV8HuE0DUKfrlppg+XxzqmZW7F/e+cC2q5UX42bh0v5HiCqDU+gwXw273do3f+f6tu3YmVBN7bXqKRRDMh8cQ/4gFBWVhFQj3acXt8DUG47AOKf1fdVWvXPcv25l1oGbBOhujGIyRaL8JNKZ+Ckknz1K/3L4v0DwDCHJui9JFKMvsSjANdVcEjZ8pGI7R5wVhsZjVy8Lckm49BmcCDZhYujlMd/gQYv0hbFY/A/zP6PikT/3pC6qF+oUr3F/1jwJ8ArH7YHD/nzQS7ACP6QnOhrJeqgRXeSqCuS03wrdkvYaWOyoNccrViHYbFJNgHMKQWUU4oPcYHXbOGDvjSU9yTZEwmDKOmVL6+jrf/f5OT/6GP3nML+V/eFicQ5OxGEsJ2GCcmy57VouWfJKIWSEL4sHVVqpmk2aX8JOkPtLUdZa+KFMTDD98PvlwxYtWMLTQd/gMSc+eB+PQJY56Zoq1FuxAH39u2/eGShB57eaf5Hf81H46pwVdMnNalS9rbt+LDCiKK/tlAVaWHz6RsS341DHzcedxOde3BOGVG/W3SI/99pmRVRdimFb2GUn8u+u34gKkjMIwt1M/UdMGY6eLzlosumiV6Ir1P5s7B5hLliyOdzbevNh+tm3btm3btm3btm1LY+OzdCe1de5MZTv5Tf1zUuPkbJ+tru66X3fX/wivniqSSOTlYE1PyjeuwXheiykoCsH9wMu8pEoYYC4aEQ0e8yY+9+q08NnX01MIp0ydZoLWYcSR95OEsrJrdT0arhHz3GtXdCJxIrcXHHSZr1DXDNCVkKsdA2E9PQ7eoSryA9GZgCIzW3hYkRmX9f1wu6qCC5BOZxTrymv1uK4VK78n749cV/d4hcRcfAWebamznI10bZa37pc8DbAMD2I6DpHAVx+n19K/IUEQ3A0+oZItzMgE8LXxxPmMzOn8HdYv9/cPhocffznc99DzLvrks+/d9+ccV+DKCAUa+GKFcaS2OBYQBpfY5i4DR8JhOn7z3W9hwSU3/T8ttVk8GtX+f42/6bZHZfql1mzgtJSyz6gSW0uVn2KcQovnBwaG4hc5ZEeupbWlIrI1Tz/nOnuwbnrz7U+dmd/ZsldVvI5rKiaqqtLMhswM7unpD1OmtIU//xoR3nzns3D/wy+ES668Mxx3ymVhrwNPC9vtekzYfLtDw/GnXj7jJeisPPKqfIrz/x0+Jiy54jbp4aavPcsvscLWYeSo8bi/r8CwUcRXOf96Im4dZkm8Eb+avQ88PWy01UFhmVW3T9u89scl2rR5XGSZLcIPP/3JFwCVUkGTjel8nBNOuyLBS1ofVP+tW+14RPRtDQAedUW+zv3RcoJpKQ4PKOHmsy9+dGzv2tcWae+DTrdd4NCusAsSyTov24GLLrdldv36eDp3xbX3qixoVahd2DkAFTIiDCh8LT29/fHrP5B/bOKXrPPTzy209Gbh3gefUxnFAo40/++wMWG19fYA1Ch+kWW3DN/98EfhuuV8lSu71BXsNN5uu+sJbPMZfyQgKG37JSI+v/Xu5zLVUfth+PLGjp0UNtv20Pp6aU1AkfGJdtj92LQjeX+qoq48KkKkESDImwGtgyITJ7WEldfeNVDgaThaZpXtw2tvfCyEWm6c5v8//46OQv4wrOehx596TbhecohgBNvJrVEmLYg3oBvaVRt1wy0PA1cJSaTFltsqXHPDA6GjozvdU6m3GLcv99U3PgprbLBn0cNfd5N9Q2dnj1cbEy0PRF8j3AdaEOFFGxEMuU2OKui6m+6XtnWiuvED7ah+tK/3hZffM03E7Sf6/Y9h4egTL4kYvsXMNBwX/+CjL2r4peVv5PNr6TFHgQZ4Pefl1z4IC0c1068VcXesE7/Ii6+4M3z48TfRtd0eY7R9sdpmIPTGF9Pd3dfU1Z9+7q1w4OHnmPDE9Xo9rtXV1ev4u43g/3Jfk3P5VMq6TbzOXKPFe9LpV+XwX42Dt6O9TNNoNtrywKadsdJau8w4J65z8kZPPvNGifYieuGBpMOxypRrQtDQ7503OFpaOurCMEEPtCBqJ+DTXEAH5lPzktfacdtdjrYdBYjw18NhTLZ8I8+AjMiIloYGzv3598iw6nq7Kwjg+Owntaa5Rkzwy0igf5y8vo6GGIuYyatSTfBffPVTWGGNnYofuh9SyiHonAtvgkUu3PCe5n1FlfJYIOukI58rRDCylwDcNoKfSGJ68+iHsaU4x4jzzSLfPDz74jsCKlRigoJoldOEgIzcWunmaivJ63/7fVjYYIsDhDD2jGP3SM2K44l4zbKr7RB+/f1fqQkRkksiYezMWClJrRtw4GVIN+74CVPCwUeeaz4gPDDBzzXacocjwtSWDpEOqcbLqRLuUxXxSnPFeW7R3ui0e+jRl0wu5CJU1GyW0scmUdvCXMynhhVOOuMqC2ESZgkxSivU7ZV1qwIjfv0MNfKYiPUGXHjU6Anh5DOvNheEgJG5TwtFeuCRFx2FIcXBevBITcw06cBXLnpEO9PyGuHnX/4OZ553fdwRO88WLWj51XdsWtBX33C/CdfcLpHjS628ncWRXUaZTl/UXSKpBdFVSmjSEt9hzBG6knx49MlXw0FHnGMaE2AEcFTj7YHtvNcJ4a77ngmjx0y0+zV9SSeefmWaU6ckzDFWW8sUBvNrAT5EwoKI0tGDUB+vdDWkL/9Fa0j+fv/JirYv0FJJLrv6rhg/vqIpvPc95MxwyFHnxfjy5eGiy28P9zzwbPjgo6/DxIkthtv4LS2tHdHQOrrYCDziuAvjixwU8V+k9Od6XUvNsYJ7OePnAP5jYeNL++eoOeX8sOFjw6rr7lYCZwZhFmTyuKYBv+R1UJ7SWTfqED4RGmNaZcs7+HROjj/V0Tyqiy+/FbQtusrJW8Tuo0++FXBcUiNmvxVBeboZSMiMwLgPhijg+VKyaY8Y5xg9liYf6vYHKckVGnRrb7yPyRZHdjXX5zh/byXaxIu8HPq3Ne47Glxwjib/fBPKpuMXq6f7HnyGxSPU+p4SWxWU123jncaa7p/DOSKQzW1NaOQHoRyLbW1dFnifadSMWhENtmtufAAQ44BDPAcVlHcGxlU3cu4m3WNI3F82T2XuDs/z9w8fOc7ixgUu8k0t8mYZHFifMezcruZvNb6iDeDpuY86L4dA4rieXwo7es7Hn34XFl9ha48qijkWmbOcIynj/BVA6QXMVL8FEZ5YcOB/4JxDyJKalS6Q0AaUJYTBhV2DIuE23zTsus9JseivB+s7C0EAs5Wjr40YU5oOrhUE2CCv0wKFLUIIMMPt1LOvhbvaa6hdeNntdj+t6fh7RyOoLoUaH65uAa9lhCPcV0wajtrau8Iue51Q5rSzIM4L78yu1ERZjCAgiEV1frVMQIvISypIB5S5TiOiUF5ro73toaqEACOMr7jmzpYyI7S4hlML0lADnpR7AfpFcA7y8OXa2gDzw6qVJC250rYlLnFLy+ffR/iRNRYVBB21IglPumM4eKTtOQS00/gp15osM441DTo0anTnvU/L6hz+Nn6oFaFE14SRz5UrqRqwEkNGV63r++sIlmVFnHHu9ZmcosQz7+jaGx8ocEcrCNK8hgU97pzbKLi3V/PS45YfZComv/ichpTqG8QajvHK0ZI3TRaYjmt1hTphhu3RtJMP17pc3BoqLOfUckUJP9wRzeqbP/4cAYPV7YpOL0D4LIQhJoPzYq4ytvBScOR53T+O62Mc8z/74ocklKU8OOv8G+EJSCQgHOOV16ynAC3QOvQc/zh3jfY16XvCs/vamx+HpVfZvp7oVU/2ssicQZa7pZtu1qG3rTMArb9I8mK+XsvbxxpqL8bltVZnNjqcFmuMLR5giVvmBzrmpEvDl1//LFzw0AJVR10644x02zDhHqafSLqu6W4WvEoP1B+FKHvFHKyZqm9a2zpDX/8g1hJQU9IvqMz092swLqGkzpH3+2Kc/1lDrCnWKno+oEpbr9qq1V3FBa+/fCGDClRl37Ug/bJ1VxnhX8Muq0QQvGDbN9yQItb19CzSc8rHC3jRrAP//TGOVwUuaDWuoUT3IHUeRTQO6xWOk/BVS9jTBS9oXdzi8Pkrw0s9GKG9ZHNQFSarB6ITx7QM0vP9YVPhmsF8O3bYC3gv0y8IhPPC8ICsUBBDEvgpHYRcQ8ooDaVaNdYRQ8I15tp9PrAXcHBBt0RvDpBf8PnTGP3ndUazKrSQvHhenKv5w80X9N/4Rn4CbMgsOUCJ2w2tx3lfrdU452i+/P4U5qKdDhLPfmk0pi1Q2b84edVIU7C1RNW4q5EHYU3BE+fwmtnEGznm6Plunw+P9qwbK1f1f3Fw5Ui/iC0+G6kxr++pr/HbCCXX/WQffFVV/2lS+h/7F/vmLxBPHh7pg0gdiOpo3ki4kItly3zL+w3NRkukd+ILONgg3551eu7/AxK2F7WQPNQ+AAAAAElFTkSuQmCC</Image> + +<Url type="text/html" method="POST" template="https://startpage.com/sp/search"> + <Param name="q" value="{searchTerms}"/> +</Url> +<SearchForm>https://startpage.com/sp/search/</SearchForm> +</SearchPlugin> diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt index b3e8a1763b5c8947ae406607cd0de5804fcd862e..9aa5313396186ca47b42c6cdc25a46999dc56db3 100644 --- a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt +++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt @@ -13,6 +13,8 @@ import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession +import mozilla.components.concept.engine.Settings +import mozilla.components.concept.engine.UnsupportedSettingException import mozilla.components.feature.search.ext.buildSearchUrl import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.tabs.TabsUseCases @@ -25,6 +27,7 @@ class SearchUseCases( store: BrowserStore, tabsUseCases: TabsUseCases, sessionUseCases: SessionUseCases, + settings: Settings? = null, ) { interface SearchUseCase { /** @@ -41,6 +44,7 @@ class SearchUseCases( private val store: BrowserStore, private val tabsUseCases: TabsUseCases, private val sessionUseCases: SessionUseCases, + private val settings: Settings? = null, ) : SearchUseCase { private val logger = Logger("DefaultSearchUseCase") @@ -72,9 +76,15 @@ class SearchUseCases( flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), additionalHeaders: Map<String, String>? = null, ) { + var securityLevel: Int + try { + securityLevel = settings?.torSecurityLevel ?: 0 + } catch (e: UnsupportedSettingException) { + securityLevel = 0 + } val searchUrl = searchEngine?.let { - searchEngine.buildSearchUrl(searchTerms) - } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms) + searchEngine.buildSearchUrl(searchTerms, securityLevel) + } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms, securityLevel) if (searchUrl == null) { logger.warn("No default search engine available to perform search") @@ -124,6 +134,7 @@ class SearchUseCases( private val store: BrowserStore, private val tabsUseCases: TabsUseCases, private val isPrivate: Boolean, + private val settings: Settings? = null, ) : SearchUseCase { private val logger = Logger("NewTabSearchUseCase") @@ -161,9 +172,15 @@ class SearchUseCases( flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), additionalHeaders: Map<String, String>? = null, ) { + var securityLevel: Int + try { + securityLevel = settings?.torSecurityLevel ?: 0 + } catch (e: UnsupportedSettingException) { + securityLevel = 0 + } val searchUrl = searchEngine?.let { - searchEngine.buildSearchUrl(searchTerms) - } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms) + searchEngine.buildSearchUrl(searchTerms, securityLevel) + } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms, securityLevel) if (searchUrl == null) { logger.warn("No default search engine available to perform search") @@ -310,15 +327,15 @@ class SearchUseCases( } val defaultSearch: DefaultSearchUseCase by lazy { - DefaultSearchUseCase(store, tabsUseCases, sessionUseCases) + DefaultSearchUseCase(store, tabsUseCases, sessionUseCases, settings) } val newTabSearch: NewTabSearchUseCase by lazy { - NewTabSearchUseCase(store, tabsUseCases, false) + NewTabSearchUseCase(store, tabsUseCases, false, settings) } val newPrivateTabSearch: NewTabSearchUseCase by lazy { - NewTabSearchUseCase(store, tabsUseCases, true) + NewTabSearchUseCase(store, tabsUseCases, true, settings) } val addSearchEngine: AddNewSearchEngineUseCase by lazy { diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt index 08615935f46bbf43e5ed1d7ada9638f114182a84..71433f1ac5ceb7c515976911e1f7eca0970b31ec 100644 --- a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt +++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt @@ -85,9 +85,9 @@ fun SearchEngine.buildSuggestionsURL(query: String): String? { /** * Builds a URL to search for the given search terms with this search engine. */ -fun SearchEngine.buildSearchUrl(searchTerm: String): String { +fun SearchEngine.buildSearchUrl(searchTerm: String, securityLevel: Int = 0): String { val builder = SearchUrlBuilder(this) - return builder.buildSearchUrl(searchTerm) + return builder.buildSearchUrl(searchTerm, securityLevel) } /** diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt index 8eec7a15b5f7b51de54c03aa1bfec0d91c4b07f2..2193121419c05ccb4998d4960a630b2d3d52d41e 100644 --- a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt +++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt @@ -28,9 +28,12 @@ private const val OS_PARAM_OPTIONAL = "\\{" + "(?:\\w+:)?\\w+?" + "\\}" internal class SearchUrlBuilder( private val searchEngine: SearchEngine, ) { - fun buildSearchUrl(searchTerms: String): String { + fun buildSearchUrl(searchTerms: String, securityLevel: Int): String { // The parser should have put the best URL for this device at the beginning of the list. - val template = searchEngine.resultUrls[0] + var template = searchEngine.resultUrls[0] + if (securityLevel == 1 && (searchEngine.id == "ddg" || searchEngine.id == "ddg-onion")) { + template = template.replaceFirst("/?", "/html/?") + } return buildUrl(template, searchTerms) } diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt index 51d2ccec52ed398bb9051e29f1d01f899adebdc0..b96cf01384038569585e736d08e37caa81a31ee9 100644 --- a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt +++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt @@ -30,6 +30,9 @@ internal const val GOOGLE_ID = "google" internal val GENERAL_SEARCH_ENGINE_IDS = setOf( GOOGLE_ID, "ddg", + "ddg-onion", + "startpage", + "startpage-onion", "bing", "baidu", "ecosia", diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt index 436b0e22db2d5cbad4db06646e22834bce139cba..35c59790bdd0478829bb04bebdafe395db321500 100644 --- a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt +++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt @@ -8,7 +8,7 @@ import mozilla.appservices.remotesettings.RemoteSettingsResponse import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.ktx.android.org.json.asSequence import mozilla.components.support.ktx.android.org.json.toList -import mozilla.components.support.remotesettings.RemoteSettingsClient +//import mozilla.components.support.remotesettings.RemoteSettingsClient import mozilla.components.support.remotesettings.RemoteSettingsResult import org.jetbrains.annotations.VisibleForTesting import org.json.JSONArray @@ -23,22 +23,22 @@ internal const val REMOTE_ENDPOINT_BUCKET_NAME = "main" * Parse SERP Telemetry json from remote config. */ class SerpTelemetryRepository( - rootStorageDirectory: File, +// rootStorageDirectory: File, private val readJson: () -> JSONObject, - collectionName: String, - serverUrl: String = REMOTE_PROD_ENDPOINT_URL, - bucketName: String = REMOTE_ENDPOINT_BUCKET_NAME, +// collectionName: String, +// serverUrl: String = REMOTE_PROD_ENDPOINT_URL, +// bucketName: String = REMOTE_ENDPOINT_BUCKET_NAME, ) { val logger = Logger("SerpTelemetryRepository") private var providerList: List<SearchProviderModel> = emptyList() - @VisibleForTesting - internal var remoteSettingsClient = RemoteSettingsClient( - serverUrl = serverUrl, - bucketName = bucketName, - collectionName = collectionName, - storageRootDirectory = rootStorageDirectory, - ) +// @VisibleForTesting +// internal var remoteSettingsClient = RemoteSettingsClient( +// serverUrl = serverUrl, +// bucketName = bucketName, +// collectionName = collectionName, +// storageRootDirectory = rootStorageDirectory, +// ) /** * Provides list of search providers from cache or dump and fetches from remotes server . @@ -65,7 +65,7 @@ class SerpTelemetryRepository( val remoteResponse = fetchRemoteResponse() if (remoteResponse.lastModified > cacheLastModified) { providerList = parseRemoteResponse(remoteResponse) - writeToCache(remoteResponse) + //writeToCache(remoteResponse) } } @@ -73,8 +73,9 @@ class SerpTelemetryRepository( * Writes data to local cache. */ @VisibleForTesting - internal suspend fun writeToCache(records: RemoteSettingsResponse): RemoteSettingsResult { - return remoteSettingsClient.write(records) + internal suspend fun writeToCache(/*records: RemoteSettingsResponse*/): RemoteSettingsResult { + return RemoteSettingsResult.NetworkFailure(Exception("Bug-43113: no remote fetching")) +// return remoteSettingsClient.write(records) } /** @@ -104,12 +105,12 @@ class SerpTelemetryRepository( */ @VisibleForTesting internal suspend fun fetchRemoteResponse(): RemoteSettingsResponse { - val result = remoteSettingsClient.fetch() - return if (result is RemoteSettingsResult.Success) { - result.response - } else { - RemoteSettingsResponse(emptyList(), 0u) - } +// val result = remoteSettingsClient.fetch() +// return if (result is RemoteSettingsResult.Success) { +// result.response +// } else { + return RemoteSettingsResponse(emptyList(), 0u) +// } } /** @@ -117,16 +118,16 @@ class SerpTelemetryRepository( */ @VisibleForTesting internal suspend fun loadProvidersFromCache(): Pair<ULong, List<SearchProviderModel>> { - val result = remoteSettingsClient.read() - return if (result is RemoteSettingsResult.Success) { - val response = result.response.records.mapNotNull { - it.fields.toSearchProviderModel() - } - val lastModified = result.response.lastModified - Pair(lastModified, response) - } else { - Pair(0u, emptyList()) - } +// val result = remoteSettingsClient.read() +// return if (result is RemoteSettingsResult.Success) { +// val response = result.response.records.mapNotNull { +// it.fields.toSearchProviderModel() +// } +// val lastModified = result.response.lastModified +// Pair(lastModified, response) +// } else { + return Pair(0u, emptyList()) +// } } } diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt index 90024bbb5689f7b69248a6e770ff9f1b84f56e4f..0060f65b693d3c91ab00bdf58a7723cf3b4d0db9 100644 --- a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt +++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt @@ -27,161 +27,161 @@ import java.io.File @RunWith(AndroidJUnit4::class) class BaseSearchTelemetryTest { - private lateinit var baseTelemetry: BaseSearchTelemetry - private lateinit var handler: BaseSearchTelemetry.SearchTelemetryMessageHandler - - @Mock - private lateinit var mockRepo: SerpTelemetryRepository - - private val mockReadJson: () -> JSONObject = mock() - private val mockRootStorageDirectory: File = mock() - - private fun createMockProviderList(): List<SearchProviderModel> = listOf( - SearchProviderModel( - schema = 1698656464939, - taggedCodes = listOf("monline_7_dg"), - telemetryId = "baidu", - organicCodes = emptyList(), - codeParamName = "tn", - queryParamNames = listOf("wd"), - searchPageRegexp = "^https://(?:m|www)\\\\.baidu\\\\.com/(?:s|baidu)", - followOnParamNames = listOf("oq"), - extraAdServersRegexps = listOf("^https?://www\\\\.baidu\\\\.com/baidu\\\\.php?"), - expectedOrganicCodes = emptyList(), - ), - ) - - private val rawJson = """ - { - "data": [ - { - "schema": 1698656464939, - "taggedCodes": [ - "monline_7_dg" - ], - "telemetryId": "baidu", - "organicCodes": [], - "codeParamName": "tn", - "queryParamNames": [ - "wd" - ], - "searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)", - "followOnParamNames": [ - "oq" - ], - "extraAdServersRegexps": [ - "^https?://www\\.baidu\\.com/baidu\\.php?" - ], - "id": "19c434a3-d173-4871-9743-290ac92a3f6a", - "last_modified": 1698666532326 - }], - "timestamp": 16 -} - """.trimIndent() - - @Before - fun setup() { - baseTelemetry = spy( - object : BaseSearchTelemetry() { - override suspend fun install( - engine: Engine, - store: BrowserStore, - providerList: List<SearchProviderModel>, - ) { - // mock, do nothing - } - - override fun processMessage(message: JSONObject) { - // mock, do nothing - } - }, - ) - handler = baseTelemetry.SearchTelemetryMessageHandler() - mockRepo = spy(SerpTelemetryRepository(mockRootStorageDirectory, mockReadJson, "test")) - } - - @Test - fun `GIVEN an engine WHEN installWebExtension is called THEN the provided extension is installed in engine`() { - val engine: Engine = mock() - val store: BrowserStore = mock() - val id = "id" - val resourceUrl = "resourceUrl" - val messageId = "messageId" - val extensionInfo = ExtensionInfo(id, resourceUrl, messageId) - - baseTelemetry.installWebExtension(engine, store, extensionInfo) - - verify(engine).installBuiltInWebExtension( - id = eq(id), - url = eq(resourceUrl), - onSuccess = any(), - onError = any(), - ) - } - - @Test - fun `GIVEN a search provider does not exist for the url WHEN getProviderForUrl is called THEN return null`() { - val url = "https://www.mozilla.com/search?q=firefox" - baseTelemetry.providerList = createMockProviderList() - - assertEquals(null, baseTelemetry.getProviderForUrl(url)) - } - - @Test(expected = IllegalStateException::class) - fun `GIVEN an extension message WHEN that cannot be processed THEN throw IllegalStateException`() { - val message = "message" - - handler.onMessage(message, mock()) - } - - @Test - fun `GIVEN an extension message WHEN received THEN pass it to processMessage`() { - val message = JSONObject() - - handler.onMessage(message, mock()) - - verify(baseTelemetry).processMessage(message) - } - - @Test - fun `GIVEN empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit = - runBlocking { - val localResponse = JSONObject(rawJson) - val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(0u, emptyList()) - - `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse) - doAnswer { - localResponse - }.`when`(mockReadJson)() - - `when`(mockRepo.parseLocalPreinstalledData(localResponse)).thenReturn(createMockProviderList()) - doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any()) - - baseTelemetry.setProviderList(mockRepo.updateProviderList()) - - assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString()) - } - - @Test - fun `GIVEN non-empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit = - runBlocking { - val localResponse = JSONObject(rawJson) - val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(123u, createMockProviderList()) - - `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse) - doAnswer { - localResponse - }.`when`(mockReadJson)() - doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any()) - - baseTelemetry.setProviderList(mockRepo.updateProviderList()) - - assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString()) - } - - fun getProviderForUrl(url: String): SearchProviderModel? { - return createMockProviderList().find { provider -> - provider.searchPageRegexp.pattern.toRegex().containsMatchIn(url) - } - } +// private lateinit var baseTelemetry: BaseSearchTelemetry +// private lateinit var handler: BaseSearchTelemetry.SearchTelemetryMessageHandler +// +// @Mock +// private lateinit var mockRepo: SerpTelemetryRepository +// +// private val mockReadJson: () -> JSONObject = mock() +// private val mockRootStorageDirectory: File = mock() +// +// private fun createMockProviderList(): List<SearchProviderModel> = listOf( +// SearchProviderModel( +// schema = 1698656464939, +// taggedCodes = listOf("monline_7_dg"), +// telemetryId = "baidu", +// organicCodes = emptyList(), +// codeParamName = "tn", +// queryParamNames = listOf("wd"), +// searchPageRegexp = "^https://(?:m|www)\\\\.baidu\\\\.com/(?:s|baidu)", +// followOnParamNames = listOf("oq"), +// extraAdServersRegexps = listOf("^https?://www\\\\.baidu\\\\.com/baidu\\\\.php?"), +// expectedOrganicCodes = emptyList(), +// ), +// ) +// +// private val rawJson = """ +// { +// "data": [ +// { +// "schema": 1698656464939, +// "taggedCodes": [ +// "monline_7_dg" +// ], +// "telemetryId": "baidu", +// "organicCodes": [], +// "codeParamName": "tn", +// "queryParamNames": [ +// "wd" +// ], +// "searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)", +// "followOnParamNames": [ +// "oq" +// ], +// "extraAdServersRegexps": [ +// "^https?://www\\.baidu\\.com/baidu\\.php?" +// ], +// "id": "19c434a3-d173-4871-9743-290ac92a3f6a", +// "last_modified": 1698666532326 +// }], +// "timestamp": 16 +//} +// """.trimIndent() +// +// @Before +// fun setup() { +// baseTelemetry = spy( +// object : BaseSearchTelemetry() { +// override suspend fun install( +// engine: Engine, +// store: BrowserStore, +// providerList: List<SearchProviderModel>, +// ) { +// // mock, do nothing +// } +// +// override fun processMessage(message: JSONObject) { +// // mock, do nothing +// } +// }, +// ) +// handler = baseTelemetry.SearchTelemetryMessageHandler() +// mockRepo = spy(SerpTelemetryRepository(mockRootStorageDirectory, mockReadJson, "test")) +// } +// +// @Test +// fun `GIVEN an engine WHEN installWebExtension is called THEN the provided extension is installed in engine`() { +// val engine: Engine = mock() +// val store: BrowserStore = mock() +// val id = "id" +// val resourceUrl = "resourceUrl" +// val messageId = "messageId" +// val extensionInfo = ExtensionInfo(id, resourceUrl, messageId) +// +// baseTelemetry.installWebExtension(engine, store, extensionInfo) +// +// verify(engine).installBuiltInWebExtension( +// id = eq(id), +// url = eq(resourceUrl), +// onSuccess = any(), +// onError = any(), +// ) +// } +// +// @Test +// fun `GIVEN a search provider does not exist for the url WHEN getProviderForUrl is called THEN return null`() { +// val url = "https://www.mozilla.com/search?q=firefox" +// baseTelemetry.providerList = createMockProviderList() +// +// assertEquals(null, baseTelemetry.getProviderForUrl(url)) +// } +// +// @Test(expected = IllegalStateException::class) +// fun `GIVEN an extension message WHEN that cannot be processed THEN throw IllegalStateException`() { +// val message = "message" +// +// handler.onMessage(message, mock()) +// } +// +// @Test +// fun `GIVEN an extension message WHEN received THEN pass it to processMessage`() { +// val message = JSONObject() +// +// handler.onMessage(message, mock()) +// +// verify(baseTelemetry).processMessage(message) +// } +// +// @Test +// fun `GIVEN empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit = +// runBlocking { +// val localResponse = JSONObject(rawJson) +// val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(0u, emptyList()) +// +// `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse) +// doAnswer { +// localResponse +// }.`when`(mockReadJson)() +// +// `when`(mockRepo.parseLocalPreinstalledData(localResponse)).thenReturn(createMockProviderList()) +// doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any()) +// +// baseTelemetry.setProviderList(mockRepo.updateProviderList()) +// +// assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString()) +// } +// +// @Test +// fun `GIVEN non-empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit = +// runBlocking { +// val localResponse = JSONObject(rawJson) +// val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(123u, createMockProviderList()) +// +// `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse) +// doAnswer { +// localResponse +// }.`when`(mockReadJson)() +// doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any()) +// +// baseTelemetry.setProviderList(mockRepo.updateProviderList()) +// +// assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString()) +// } +// +// fun getProviderForUrl(url: String): SearchProviderModel? { +// return createMockProviderList().find { provider -> +// provider.searchPageRegexp.pattern.toRegex().containsMatchIn(url) +// } +// } } diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt index 50ae3c6aee85e38c6a5143db116d1fcd589b8343..934a1a83b3b85b6bf0c8e95742a7b15fd7032f40 100644 --- a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt +++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt @@ -23,70 +23,70 @@ import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class SerpTelemetryRepositoryTest { - @Mock - private lateinit var mockRemoteSettingsClient: RemoteSettingsClient - - private lateinit var serpTelemetryRepository: SerpTelemetryRepository - - @Before - fun setup() { - MockitoAnnotations.openMocks(this) - serpTelemetryRepository = SerpTelemetryRepository( - rootStorageDirectory = mock(), - readJson = mock(), - collectionName = "", - serverUrl = "https://test.server", - bucketName = "", - ) - - serpTelemetryRepository.remoteSettingsClient = mockRemoteSettingsClient - } - - @Test - fun `GIVEN non-empty response WHEN writeToCache is called THEN the result is a success`() = runBlocking { - val records = listOf( - RemoteSettingsRecord("1", 123u, false, null, JSONObject()), - RemoteSettingsRecord("2", 456u, true, null, JSONObject()), - ) - val response = RemoteSettingsResponse(records, 125614567U) - - `when`(mockRemoteSettingsClient.write(response)) - .thenReturn(RemoteSettingsResult.Success(response)) - - val result = serpTelemetryRepository.writeToCache(response) - - assertTrue(result is RemoteSettingsResult.Success) - assertEquals(response, (result as RemoteSettingsResult.Success).response) - } - - @Test - fun `GIVEN non-empty response WHEN fetchRemoteResponse is called THEN the result is equal to the response`() = runBlocking { - val records = listOf( - RemoteSettingsRecord("1", 123u, false, null, JSONObject()), - RemoteSettingsRecord("2", 456u, true, null, JSONObject()), - ) - val response = RemoteSettingsResponse(records, 125614567U) - `when`(mockRemoteSettingsClient.fetch()) - .thenReturn(RemoteSettingsResult.Success(response)) - - val result = serpTelemetryRepository.fetchRemoteResponse() - - assertEquals(response, result) - } - - @Test - fun `GIVEN non-empty response WHEN loadProvidersFromCache is called THEN the result is equal to the response`() = runBlocking { - val records = listOf( - RemoteSettingsRecord("1", 123u, false, null, JSONObject()), - RemoteSettingsRecord("2", 456u, true, null, JSONObject()), - ) - val response = RemoteSettingsResponse(records, 125614567U) - `when`(mockRemoteSettingsClient.read()) - .thenReturn(RemoteSettingsResult.Success(response)) - - val result = serpTelemetryRepository.loadProvidersFromCache() - - assertEquals(response.lastModified, result.first) - assertEquals(response.records.mapNotNull { it.fields.toSearchProviderModel() }, result.second) - } +// @Mock +// private lateinit var mockRemoteSettingsClient: RemoteSettingsClient +// +// private lateinit var serpTelemetryRepository: SerpTelemetryRepository +// +// @Before +// fun setup() { +// MockitoAnnotations.openMocks(this) +// serpTelemetryRepository = SerpTelemetryRepository( +// rootStorageDirectory = mock(), +// readJson = mock(), +// collectionName = "", +// serverUrl = "https://test.server", +// bucketName = "", +// ) +// +// serpTelemetryRepository.remoteSettingsClient = mockRemoteSettingsClient +// } +// +// @Test +// fun `GIVEN non-empty response WHEN writeToCache is called THEN the result is a success`() = runBlocking { +// val records = listOf( +// RemoteSettingsRecord("1", 123u, false, null, JSONObject()), +// RemoteSettingsRecord("2", 456u, true, null, JSONObject()), +// ) +// val response = RemoteSettingsResponse(records, 125614567U) +// +// `when`(mockRemoteSettingsClient.write(response)) +// .thenReturn(RemoteSettingsResult.Success(response)) +// +// val result = serpTelemetryRepository.writeToCache(response) +// +// assertTrue(result is RemoteSettingsResult.Success) +// assertEquals(response, (result as RemoteSettingsResult.Success).response) +// } +// +// @Test +// fun `GIVEN non-empty response WHEN fetchRemoteResponse is called THEN the result is equal to the response`() = runBlocking { +// val records = listOf( +// RemoteSettingsRecord("1", 123u, false, null, JSONObject()), +// RemoteSettingsRecord("2", 456u, true, null, JSONObject()), +// ) +// val response = RemoteSettingsResponse(records, 125614567U) +// `when`(mockRemoteSettingsClient.fetch()) +// .thenReturn(RemoteSettingsResult.Success(response)) +// +// val result = serpTelemetryRepository.fetchRemoteResponse() +// +// assertEquals(response, result) +// } +// +// @Test +// fun `GIVEN non-empty response WHEN loadProvidersFromCache is called THEN the result is equal to the response`() = runBlocking { +// val records = listOf( +// RemoteSettingsRecord("1", 123u, false, null, JSONObject()), +// RemoteSettingsRecord("2", 456u, true, null, JSONObject()), +// ) +// val response = RemoteSettingsResponse(records, 125614567U) +// `when`(mockRemoteSettingsClient.read()) +// .thenReturn(RemoteSettingsResult.Success(response)) +// +// val result = serpTelemetryRepository.loadProvidersFromCache() +// +// assertEquals(response.lastModified, result.first) +// assertEquals(response.records.mapNotNull { it.fields.toSearchProviderModel() }, result.second) +// } } diff --git a/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt b/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt index d8951a1417351ceb357af7ea928b1fd645ef08e1..6fe5c5a2f4daac880a91dce45b4bac6d852ee4a7 100644 --- a/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt +++ b/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt @@ -18,6 +18,7 @@ import mozilla.components.concept.toolbar.Toolbar.Highlight import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection import mozilla.components.feature.toolbar.internal.URLRenderer import mozilla.components.lib.state.ext.flowScoped +import mozilla.components.support.ktx.kotlin.isOnionUrl /** * Presenter implementation for a toolbar implementation in order to update the toolbar whenever @@ -69,7 +70,11 @@ class ToolbarPresenter( toolbar.displayProgress(tab.content.progress) toolbar.siteSecure = if (tab.content.securityInfo.secure) { - Toolbar.SiteSecurity.SECURE + if (tab.content.url.isOnionUrl()) { + Toolbar.SiteSecurity.ONION + } else { + Toolbar.SiteSecurity.SECURE + } } else { Toolbar.SiteSecurity.INSECURE } diff --git a/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingController.kt b/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingController.kt index 7bb7ba2696432e3ed7139d0f5f330beb79c7f12b..584fb87eb511de0c1cff12bd68389b56ec808938 100644 --- a/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingController.kt +++ b/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingController.kt @@ -96,32 +96,32 @@ open class NimbusMessagingController( * creates a URI string for the message action. */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun processMessageActionToUri(message: Message): Uri { + open fun processMessageActionToUri(message: Message): Uri { val (uuid, action) = messagingStorage.generateUuidAndFormatMessage(message) sendClickedMessageTelemetry(message.id, uuid) return convertActionIntoDeepLinkSchemeUri(action) } - private fun sendDismissedMessageTelemetry(messageId: String) { + open fun sendDismissedMessageTelemetry(messageId: String) { GleanMessaging.messageDismissed.record(GleanMessaging.MessageDismissedExtra(messageId)) } - private fun sendShownMessageTelemetry(messageId: String) { + open fun sendShownMessageTelemetry(messageId: String) { GleanMessaging.messageShown.record(GleanMessaging.MessageShownExtra(messageId)) } - private fun sendExpiredMessageTelemetry(messageId: String) { + open fun sendExpiredMessageTelemetry(messageId: String) { GleanMessaging.messageExpired.record(GleanMessaging.MessageExpiredExtra(messageId)) } - private fun sendClickedMessageTelemetry(messageId: String, uuid: String?) { + open fun sendClickedMessageTelemetry(messageId: String, uuid: String?) { GleanMessaging.messageClicked.record( GleanMessaging.MessageClickedExtra(messageKey = messageId, actionUuid = uuid), ) } - private fun sendMicrosurveyCompletedTelemetry(messageId: String, answer: String) { + open fun sendMicrosurveyCompletedTelemetry(messageId: String, answer: String) { Microsurvey.submitButtonTapped.record( Microsurvey.SubmitButtonTappedExtra( surveyId = messageId, @@ -130,7 +130,7 @@ open class NimbusMessagingController( ) } - private fun convertActionIntoDeepLinkSchemeUri(action: String): Uri = + open fun convertActionIntoDeepLinkSchemeUri(action: String): Uri = if (action.startsWith("://")) { "$deepLinkScheme$action".toUri() } else { diff --git a/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingStorage.kt b/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingStorage.kt index 9828883337eb7965fb68f47855d92967699aaf51..f389d9a714158c5c4dd4f64028ba477e49263534 100644 --- a/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingStorage.kt +++ b/mobile/android/android-components/components/service/nimbus/src/main/java/mozilla/components/service/nimbus/messaging/NimbusMessagingStorage.kt @@ -33,7 +33,7 @@ const val MESSAGING_FEATURE_ID = "messaging" /** * Provides messages from [messagingFeature] and combine with the metadata store on [metadataStorage]. */ -class NimbusMessagingStorage( +open class NimbusMessagingStorage( private val context: Context, private val metadataStorage: MessageMetadataStorage, private val onMalformedMessage: (String) -> Unit = { diff --git a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/content/Context.kt b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/content/Context.kt index d83a2c7b400379fb75cc413ab5490c349d8cc5a6..ec9056be13af1f94af1a95fef4b0f89796cea600 100644 --- a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/content/Context.kt +++ b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/content/Context.kt @@ -42,6 +42,7 @@ import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.ktx.R import mozilla.components.support.ktx.android.content.res.resolveAttribute import mozilla.components.support.utils.ext.getPackageInfoCompat +import mozilla.components.support.utils.TorUtils import java.io.File /** @@ -110,12 +111,11 @@ fun Context.share(text: String, subject: String = getString(R.string.mozac_suppo flags = FLAG_ACTIVITY_NEW_TASK } - startActivity( - intent.createChooserExcludingCurrentApp( - this, - getString(R.string.mozac_support_ktx_menu_share_with), - ), - ) + val shareIntent = intent.createChooserExcludingCurrentApp(this, getString(R.string.mozac_support_ktx_menu_share_with)).apply { + flags = FLAG_ACTIVITY_NEW_TASK + } + + TorUtils.startActivityPrompt(this, shareIntent) true } catch (e: ActivityNotFoundException) { Log.log(Log.Priority.WARN, message = "No activity to share to found", throwable = e, tag = "share") @@ -222,7 +222,7 @@ fun Context.email( flags = FLAG_ACTIVITY_NEW_TASK } - startActivity(emailIntent) + TorUtils.startActivityPrompt(this, emailIntent) true } catch (e: ActivityNotFoundException) { Logger.warn("No activity found to handle email intent", throwable = e) @@ -253,7 +253,7 @@ fun Context.call( flags = FLAG_ACTIVITY_NEW_TASK } - startActivity(callIntent) + TorUtils.startActivityPrompt(this, callIntent) true } catch (e: ActivityNotFoundException) { Logger.warn("No activity found to handle dial intent", throwable = e) @@ -281,7 +281,7 @@ fun Context.addContact( addFlags(FLAG_ACTIVITY_NEW_TASK) } - startActivity(intent) + TorUtils.startActivityPrompt(this, intent) true } catch (e: ActivityNotFoundException) { Logger.warn("No activity found to handle dial intent", throwable = e) diff --git a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt index b3aed2a5afccda0f94436ddfeb975315c1588b93..a1042d76fc64ef01006454081ef259d5e567bbd6 100644 --- a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt +++ b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt @@ -245,6 +245,15 @@ fun String.urlContainsQueryParameters(searchParameters: String): Boolean = try { false } +/** + * Returns whether the string is an .onion URL. + */ +fun String.isOnionUrl(): Boolean = try { + URL(this).host.endsWith(".onion") +} catch (e: MalformedURLException) { + false +} + /** * Compares 2 URLs and returns true if they have the same origin, * which means: same protocol, same host, same port. diff --git a/mobile/android/android-components/components/support/remotesettings/src/main/java/mozilla/components/support/remotesettings/RemoteSettingsClient.kt b/mobile/android/android-components/components/support/remotesettings/src/main/java/mozilla/components/support/remotesettings/RemoteSettingsClient.kt index c9e448e8a2d643f947e80f48d88f11b8e388573a..76ca2a5d85a4a079b00f411d5d47de9681c978b3 100644 --- a/mobile/android/android-components/components/support/remotesettings/src/main/java/mozilla/components/support/remotesettings/RemoteSettingsClient.kt +++ b/mobile/android/android-components/components/support/remotesettings/src/main/java/mozilla/components/support/remotesettings/RemoteSettingsClient.kt @@ -64,18 +64,20 @@ class RemoteSettingsClient( */ @Suppress("TooGenericExceptionCaught") suspend fun fetch(): RemoteSettingsResult = withContext(Dispatchers.IO) { - try { - val serverRecords = RemoteSettings(config).use { - it.getRecords() - } - RemoteSettingsResult.Success(serverRecords) - } catch (e: RemoteSettingsException) { - Logger.error(e.message.toString()) - RemoteSettingsResult.NetworkFailure(e) - } catch (e: NullPointerException) { - Logger.error(e.message.toString()) - RemoteSettingsResult.NetworkFailure(e) - } +// try { +// val serverRecords = RemoteSettings(config).use { +// it.getRecords() +// } +// RemoteSettingsResult.Success(serverRecords) +// } catch (e: RemoteSettingsException) { +// Logger.error(e.message.toString()) +// RemoteSettingsResult.NetworkFailure(e) +// } catch (e: NullPointerException) { +// Logger.error(e.message.toString()) +// RemoteSettingsResult.NetworkFailure(e) +// } + RemoteSettingsResult.NetworkFailure(Exception("tb-43113: no remote fetching")) + } /** @@ -123,7 +125,8 @@ class RemoteSettingsClient( suspend fun RemoteSettingsClient.readOrFetch(): RemoteSettingsResult { val readResult = read() return if (readResult is RemoteSettingsResult.DiskFailure) { - fetch() + //fetch() + RemoteSettingsResult.NetworkFailure(Exception("tb-43113: no remote fetching")) } else { readResult } diff --git a/mobile/android/android-components/components/support/utils/src/main/java/mozilla/components/support/utils/TorUtils.kt b/mobile/android/android-components/components/support/utils/src/main/java/mozilla/components/support/utils/TorUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..edc552326788022240d33af7f30c6046bb405490 --- /dev/null +++ b/mobile/android/android-components/components/support/utils/src/main/java/mozilla/components/support/utils/TorUtils.kt @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.support.utils + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import mozilla.components.support.utils.PendingIntentUtils + +object TorUtils { + const val TORBROWSER_START_ACTIVITY_PROMPT = "torbrowser_start_activity_prompt" + + // Delegates showing prompt and possibly starting the activity to the main app activity. + // Highly dependant on Fenix/Tor Browser for Android. + // One downside of this implementation is that it does not throw exceptions like the + // direct context.startActivity, so the UI will behave as if the startActivity call was + // done successfully, which may not always be the case. + fun startActivityPrompt(context: Context, intent: Intent) { + val intentContainer = Intent() + intentContainer.setPackage(context.applicationContext.packageName) + intentContainer.putExtra(TORBROWSER_START_ACTIVITY_PROMPT, PendingIntent.getActivity(context, 0, intent, PendingIntentUtils.defaultFlags)) + intentContainer.flags = Intent.FLAG_ACTIVITY_NEW_TASK + context.startActivity(intentContainer) + } +} diff --git a/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt b/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt index 522944dffa1fdb98a281cc4d0b95d9e37b238546..852e9c6cdf7763faf9c126ed10ec8a459f1316f1 100644 --- a/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt +++ b/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt @@ -234,6 +234,7 @@ object WebExtensionSupport { // when the add-on has already been installed, we don't need to show anything // either. val shouldDispatchAction = !installedExtensions.containsKey(extension.id) && !extension.isBuiltIn() + && !extension.isBundled() registerInstalledExtension(store, extension) if (shouldDispatchAction) { store.dispatch( diff --git a/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_onion.xml b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_onion.xml new file mode 100644 index 0000000000000000000000000000000000000000..d904fa7165e63036274f4741314575bc5defa6b0 --- /dev/null +++ b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_onion.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="@color/mozac_ui_icons_fill" + android:fillType="evenOdd" + android:pathData="M12 18.25c2.0711 0 3.75-1.6789 3.75-3.75s-1.6789-3.75-3.75-3.75c-2.0711 0-3.75 1.6789-3.75 3.75s1.6789 3.75 3.75 3.75zm0 1.25c2.7614 0 5-2.2386 5-5s-2.2386-5-5-5c-2.7614 0-5 2.2386-5 5s2.2386 5 5 5z" /> + <path + android:fillColor="@color/mozac_ui_icons_fill" + android:fillType="evenOdd" + android:pathData="M12 15.75c0.6903 0 1.25-0.5596 1.25-1.25 0-0.6903-0.5597-1.25-1.25-1.25s-1.25 0.5597-1.25 1.25c0 0.6904 0.5597 1.25 1.25 1.25zm0 1.25c1.3807 0 2.5-1.1193 2.5-2.5s-1.1193-2.5-2.5-2.5-2.5 1.1193-2.5 2.5 1.1193 2.5 2.5 2.5z" /> + <path + android:fillColor="@color/mozac_ui_icons_fill" + android:fillType="evenOdd" + android:pathData="M17 8.9097c1.5344 1.3733 2.5 3.3691 2.5 5.5903 0 4.1421-3.3579 7.5-7.5 7.5-4.1421 0-7.5-3.3579-7.5-7.5 0-2.2212 0.96563-4.217 2.5-5.5903v-1.9097c0-2.7614 2.2386-5 5-5 2.7614 0 5 2.2386 5 5zm-8.4375-1.0774c1.0298-0.53198 2.1985-0.83239 3.4375-0.83239s2.4078 0.30041 3.4375 0.83239v-0.83239c0-1.8985-1.539-3.4375-3.4375-3.4375s-3.4375 1.539-3.4375 3.4375zm9.6875 6.6676c0 3.4518-2.7982 6.25-6.25 6.25-3.4518 0-6.25-2.7982-6.25-6.25s2.7982-6.25 6.25-6.25c3.4518 0 6.25 2.7982 6.25 6.25z" /> +</vector> diff --git a/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt b/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt index 3fe3ee11a6d7dcce482a04d1ecc0f3fa718687dc..4fe233ed2af56114ee984ed8314d14c905076522 100644 --- a/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt +++ b/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt @@ -23,7 +23,12 @@ object Config { @JvmStatic private fun generateDebugVersionName(): String { - val today = Date() + val today = if (System.getenv("MOZ_BUILD_DATE") != null) { + val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US) + format.parse(System.getenv("MOZ_BUILD_DATE")) + } else { + Date() + } // Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and // identify ancient versions when debugging issues. However this will still keep the same version number during // the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the @@ -68,13 +73,20 @@ object Config { */ @JvmStatic fun generateBuildDate(): String { - return LocalDateTime.now().toString() + return if (System.getenv("MOZ_BUILD_DATE") != null) { + // Converting our MOZ_BUILD_DATE to LocalDateTime + val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US) + val date = format.parse(System.getenv("MOZ_BUILD_DATE")) + java.sql.Timestamp(date.getTime()).toLocalDateTime().toString() + } else { + LocalDateTime.now().toString() + } } private val fennecBaseVersionCode by lazy { val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US) val cutoff = format.parse("20141228000000") - val build = Date() + val build = if (System.getenv("MOZ_BUILD_DATE") != null) format.parse(System.getenv("MOZ_BUILD_DATE")) else Date() Math.floor((build.time - cutoff.time) / (1000.0 * 60.0 * 60.0)).toInt() } diff --git a/mobile/android/android-components/samples/browser/src/main/res/layout/activity_installed_add_on_details.xml b/mobile/android/android-components/samples/browser/src/main/res/layout/activity_installed_add_on_details.xml index 1c713c13b307d33849a45c9869f97ecaa887f2a9..10e5410fe476d458d54bafa8f2e2b99e5baa3f72 100644 --- a/mobile/android/android-components/samples/browser/src/main/res/layout/activity_installed_add_on_details.xml +++ b/mobile/android/android-components/samples/browser/src/main/res/layout/activity_installed_add_on_details.xml @@ -70,6 +70,7 @@ app:drawableStartCompat="@drawable/mozac_ic_permissions" /> <androidx.appcompat.widget.SwitchCompat + android:visibility="gone" android:id="@+id/allow_in_private_browsing_switch" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/mobile/android/app/000-tor-browser-android.js b/mobile/android/app/000-tor-browser-android.js new file mode 100644 index 0000000000000000000000000000000000000000..381a85a667768f4b0ac00d70e67a18aad70e178a --- /dev/null +++ b/mobile/android/app/000-tor-browser-android.js @@ -0,0 +1,34 @@ +// Import all prefs from the canonical file +// We override mobile-specific prefs below +// Tor Browser for Android +// Do not edit this file. + +#include ../../../browser/app/profile/000-tor-browser.js + +// Disable browser auto updaters +pref("app.update.auto", false); +pref("browser.startup.homepage_override.mstone", "ignore"); + +// Clear data on quit +pref("privacy.clearOnShutdown.cache", true); +pref("privacy.clearOnShutdown.cookies", true); +pref("privacy.clearOnShutdown.downloads", true); +pref("privacy.clearOnShutdown.formdata", true); +pref("privacy.clearOnShutdown.history", true); +pref("privacy.clearOnShutdown.offlineApps", true); +pref("privacy.clearOnShutdown.passwords", true); +pref("privacy.clearOnShutdown.sessions", true); +pref("privacy.clearOnShutdown.siteSettings", true); + +// controls if we want camera support +pref("media.realtime_decoder.enabled", false); + +// Enable touch events on Android (highlighting text, etc) +pref("dom.w3c_touch_events.enabled", 2); + +// No HLS support for now due to browser freezing, see: #29859. +pref("media.hls.enabled", false); + +// Disable WebAuthn. It requires Google Play Services, so it isn't +// available, but avoid any potential problems. +pref("security.webauth.webauthn_enable_android_fido2", false); diff --git a/mobile/android/app/geckoview-prefs.js b/mobile/android/app/geckoview-prefs.js index 60d31242b350fa595c2010b195e07ffea7cd3644..91b48e2cabeaa78d5833e3b202dfbd70f1804e60 100644 --- a/mobile/android/app/geckoview-prefs.js +++ b/mobile/android/app/geckoview-prefs.js @@ -408,3 +408,5 @@ pref("xpinstall.signatures.required", true); pref("xpinstall.whitelist.add", "https://addons.mozilla.org"); pref("xpinstall.whitelist.fileRequest", false); + +#include 000-tor-browser-android.js diff --git a/mobile/android/app/moz.build b/mobile/android/app/moz.build index 631f18939af055d3b478bf42a1023c7e9fa32285..f2dc5a7d9acc05599e9fb81773911050eaff7c03 100644 --- a/mobile/android/app/moz.build +++ b/mobile/android/app/moz.build @@ -16,6 +16,10 @@ for var in ("MOZ_UPDATER", "MOZ_APP_UA_NAME", "ANDROID_PACKAGE_NAME", "TARGET_CP if CONFIG["MOZ_PKG_SPECIAL"]: DEFINES["MOZ_PKG_SPECIAL"] = CONFIG["MOZ_PKG_SPECIAL"] +JS_PREFERENCE_PP_FILES += [ + "000-tor-browser-android.js", +] + if not CONFIG["MOZ_ANDROID_FAT_AAR_ARCHITECTURES"]: # Equivalent to JS_PREFERENCE_PP_FILES[CONFIG['ANDROID_CPU_ARCH']], # which isn't supported out of the box. diff --git a/mobile/android/basebrowser.configure b/mobile/android/basebrowser.configure new file mode 100644 index 0000000000000000000000000000000000000000..2d546d39f5d53dc362a98a1cd29881661a824dfa --- /dev/null +++ b/mobile/android/basebrowser.configure @@ -0,0 +1,33 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Set Base Browser default config +# See tor-browser#25741 and tor-browser#41584. + +imply_option("MOZ_ANDROID_EXCLUDE_FONTS", False) + +# Disable uploading crash reports and dump files to an external server +# This is still configured in old-configure. Uncomment when this moves +# to the python config +# imply_option("MOZ_CRASHREPORTER", False) + +# Disable uploading information about the browser configuration and +# performance to an external server. See tor-browser#32493. +imply_option("MOZ_SERVICES_HEALTHREPORT", False) + +# Disable creating telemetry and data reports that are uploaded to an +# external server +# These aren't actually configure options. These are disabled in +# confvars.sh, but they look like configure options so we'll document +# them here, as well. +# XXX: no confvars.sh here +# imply_option("MOZ_TELEMETRY_REPORTING", False) +# imply_option("MOZ_DATA_REPORTING", False) + +# tor-browser#24796: This controls some permissions in GeckoView's +# AndroidManifest.xml +imply_option("MOZ_ANDROID_NETWORK_STATE", False) +imply_option("MOZ_ANDROID_LOCATION", False) diff --git a/mobile/android/branding/beta/locales/jar.mn b/mobile/android/branding/beta/locales/jar.mn index 51780cce930f4b02f530df36e7929d8b2566822f..dce4a921fde79ff5143085308f28a886403dd61c 100644 --- a/mobile/android/branding/beta/locales/jar.mn +++ b/mobile/android/branding/beta/locales/jar.mn @@ -3,10 +3,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -[localization] @AB_CD@.jar: - branding (en-US/**/*.ftl) - -@AB_CD@.jar: -% locale branding @AB_CD@ %locale/branding/ -# Branding only exists in en-US - locale/branding/brand.properties (en-US/brand.properties) +# We provide all brand files in torbutton diff --git a/mobile/android/branding/nightly/locales/jar.mn b/mobile/android/branding/nightly/locales/jar.mn index dbab39423691e4e2bc07970f134d388a7735dea3..dce4a921fde79ff5143085308f28a886403dd61c 100644 --- a/mobile/android/branding/nightly/locales/jar.mn +++ b/mobile/android/branding/nightly/locales/jar.mn @@ -3,10 +3,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -[localization] @AB_CD@.jar: - branding (en-US/**/*.ftl) - -@AB_CD@.jar: -% locale branding @AB_CD@ %locale/branding/ -# Nightly branding only exists in en-US - locale/branding/brand.properties (en-US/brand.properties) +# We provide all brand files in torbutton diff --git a/mobile/android/branding/official/locales/jar.mn b/mobile/android/branding/official/locales/jar.mn index 51780cce930f4b02f530df36e7929d8b2566822f..dce4a921fde79ff5143085308f28a886403dd61c 100644 --- a/mobile/android/branding/official/locales/jar.mn +++ b/mobile/android/branding/official/locales/jar.mn @@ -3,10 +3,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -[localization] @AB_CD@.jar: - branding (en-US/**/*.ftl) - -@AB_CD@.jar: -% locale branding @AB_CD@ %locale/branding/ -# Branding only exists in en-US - locale/branding/brand.properties (en-US/brand.properties) +# We provide all brand files in torbutton diff --git a/mobile/android/branding/unofficial/locales/jar.mn b/mobile/android/branding/unofficial/locales/jar.mn index dbab39423691e4e2bc07970f134d388a7735dea3..dce4a921fde79ff5143085308f28a886403dd61c 100644 --- a/mobile/android/branding/unofficial/locales/jar.mn +++ b/mobile/android/branding/unofficial/locales/jar.mn @@ -3,10 +3,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -[localization] @AB_CD@.jar: - branding (en-US/**/*.ftl) - -@AB_CD@.jar: -% locale branding @AB_CD@ %locale/branding/ -# Nightly branding only exists in en-US - locale/branding/brand.properties (en-US/brand.properties) +# We provide all brand files in torbutton diff --git a/mobile/android/confvars.sh b/mobile/android/confvars.sh index c0e5ed66e5167180da59fe59e34d0614f892ea29..39d2d2a3ed2549aa7a9c554f598255790293f9cc 100644 --- a/mobile/android/confvars.sh +++ b/mobile/android/confvars.sh @@ -5,3 +5,9 @@ MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/android/branding/official # MOZ_APP_DISPLAYNAME is set by branding/configure.sh + +# Disable telemetry at compile-time +unset MOZ_TELEMETRY_REPORTING + +# Disable data reporting at compile-time +unset MOZ_DATA_REPORTING diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java index c0e8e23bfe2797223b64745f20d495cbd2bd7988..3df3c39e1db6cc328a433430ba1f6d7c60752e9e 100644 --- a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java +++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java @@ -531,50 +531,8 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou boolean followRedirects, Map<String, String> requestParameters) throws IOException, URISyntaxException { - /** - * Tor Project modified the way the connection object was created. For the sake of - * simplicity, instead of duplicating the whole file we changed the connection object - * to use the ProxySelector. - */ - HttpURLConnection connection = (HttpURLConnection) openConnectionWithProxy(url.toURI()); - - connection.setConnectTimeout(connectTimeoutMillis); - connection.setReadTimeout(readTimeoutMillis); - - Map<String, String> requestHeaders = new HashMap<>(); - if (defaultRequestProperties != null) { - requestHeaders.putAll(defaultRequestProperties.getSnapshot()); - } - requestHeaders.putAll(requestProperties.getSnapshot()); - requestHeaders.putAll(requestParameters); - - for (Map.Entry<String, String> property : requestHeaders.entrySet()) { - connection.setRequestProperty(property.getKey(), property.getValue()); - } - - if (!(position == 0 && length == C.LENGTH_UNSET)) { - String rangeRequest = "bytes=" + position + "-"; - if (length != C.LENGTH_UNSET) { - rangeRequest += (position + length - 1); - } - connection.setRequestProperty("Range", rangeRequest); - } - connection.setRequestProperty("User-Agent", userAgent); - connection.setRequestProperty("Accept-Encoding", allowGzip ? "gzip" : "identity"); - connection.setInstanceFollowRedirects(followRedirects); - connection.setDoOutput(httpBody != null); - connection.setRequestMethod(DataSpec.getStringForHttpMethod(httpMethod)); - - if (httpBody != null) { - connection.setFixedLengthStreamingMode(httpBody.length); - connection.connect(); - OutputStream os = connection.getOutputStream(); - os.write(httpBody); - os.close(); - } else { - connection.connect(); - } - return connection; + Log.i(TAG, "This is Tor Browser. Skipping."); + throw new IOException(); } /** Creates an {@link HttpURLConnection} that is connected with the {@code url}. */ diff --git a/mobile/android/fenix/.buildconfig.yml b/mobile/android/fenix/.buildconfig.yml index 11c87288484b2bc186c4967d10f3d69bc57e710e..3c698e244724b0d2bfe11d69d1c45bc1bc69b496 100644 --- a/mobile/android/fenix/.buildconfig.yml +++ b/mobile/android/fenix/.buildconfig.yml @@ -56,8 +56,8 @@ projects: - feature-toolbar - feature-top-sites - feature-webauthn - - feature-webcompat - - feature-webcompat-reporter +# - feature-webcompat +# - feature-webcompat-reporter - feature-webnotifications - lib-crash - lib-crash-sentry diff --git a/mobile/android/fenix/app/build.gradle b/mobile/android/fenix/app/build.gradle index 17a65b308af8670bba9173ce8ed0b7e2cc7cb229..ff8cfb69b90ec2b50cad8e45599e0808089f732b 100644 --- a/mobile/android/fenix/app/build.gradle +++ b/mobile/android/fenix/app/build.gradle @@ -44,7 +44,17 @@ import static org.gradle.api.tasks.testing.TestResult.ResultType apply from: 'benchmark.gradle' +def obtainTestBuildType() { + def result = "debug"; + if (project.hasProperty("testBuildType")) { + result = project.getProperties().get("testBuildType") + } + result +} + android { + testBuildType obtainTestBuildType() + project.maybeConfigForJetpackBenchmark(it) if (project.hasProperty("testBuildType")) { // Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..) @@ -53,7 +63,7 @@ android { } defaultConfig { - applicationId "org.mozilla" + applicationId "org.torproject" minSdkVersion config.minSdkVersion compileSdk config.compileSdkVersion targetSdkVersion config.targetSdkVersion @@ -84,8 +94,7 @@ android { "}" // This should be the base URL used to call the AMO API. buildConfigField "String", "AMO_SERVER_URL", "\"https://services.addons.mozilla.org\"" - - def deepLinkSchemeValue = "fenix-dev" + def deepLinkSchemeValue = "torbrowser-dev" buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\"" // This allows overriding the target activity for MozillaOnline builds, which happens @@ -106,6 +115,8 @@ android { ] buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", getSupportedLocales() + + buildConfigField "boolean", "DATA_COLLECTION_DISABLED", "true" } def releaseTemplate = { @@ -137,14 +148,14 @@ android { debug { shrinkResources false minifyEnabled false - applicationIdSuffix ".fenix.debug" + applicationIdSuffix ".torbrowser_debug" resValue "bool", "IS_DEBUG", "true" pseudoLocalesEnabled true } nightly releaseTemplate >> { - applicationIdSuffix ".fenix" + applicationIdSuffix ".torbrowser_nightly" buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true" - def deepLinkSchemeValue = "fenix-nightly" + def deepLinkSchemeValue = "torbrowser-nightly" buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\"" manifestPlaceholders.putAll([ "deepLinkScheme": deepLinkSchemeValue @@ -152,8 +163,8 @@ android { } beta releaseTemplate >> { buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true" - applicationIdSuffix ".firefox_beta" - def deepLinkSchemeValue = "fenix-beta" + applicationIdSuffix ".torbrowser_alpha" + def deepLinkSchemeValue = "torbrowser-alpha" buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\"" manifestPlaceholders.putAll([ // This release type is meant to replace Firefox (Beta channel) and therefore needs to inherit @@ -163,14 +174,14 @@ android { // fatal consequences. For example see: // - https://issuetracker.google.com/issues/36924841 // - https://issuetracker.google.com/issues/36905922 - "sharedUserId": "org.mozilla.firefox.sharedID", + "sharedUserId": "org.torproject.torbrowser_alpha.sharedID", "deepLinkScheme": deepLinkSchemeValue, ]) } release releaseTemplate >> { buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true" - applicationIdSuffix ".firefox" - def deepLinkSchemeValue = "fenix" + applicationIdSuffix ".torbrowser" + def deepLinkSchemeValue = "torbrowser" buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\"" manifestPlaceholders.putAll([ // This release type is meant to replace Firefox (Release channel) and therefore needs to inherit @@ -180,7 +191,7 @@ android { // fatal consequences. For example see: // - https://issuetracker.google.com/issues/36924841 // - https://issuetracker.google.com/issues/36905922 - "sharedUserId": "org.mozilla.firefox.sharedID", + "sharedUserId": "org.torproject.torbrowser.sharedID", "deepLinkScheme": deepLinkSchemeValue, ]) } @@ -309,14 +320,24 @@ android.applicationVariants.configureEach { variant -> // ------------------------------------------------------------------------------------------------- def isDebug = variant.buildType.resValues['bool/IS_DEBUG']?.value ?: false + def isDataCollectionDisabled = variant.buildType.buildConfigFields['DATA_COLLECTION_DISABLED']?.value ?: true + def isDebugOrDCD = isDebug || isDataCollectionDisabled def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false + def disableTor = false + if (project.hasProperty("disableTor")) { + disableTor = project.getProperty("disableTor") + } + println("----------------------------------------------") println("Variant name: " + variant.name) println("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join()) println("Build type: " + variant.buildType.name) println("Flavor: " + variant.flavorName) - println("Telemetry enabled: " + !isDebug) + println("Telemetry enabled: " + !isDebugOrDCD) + println("Tor is disabled: " + disableTor) + + buildConfigField "boolean", "DISABLE_TOR", "$disableTor" if (useReleaseVersioning) { // The Google Play Store does not allow multiple APKs for the same app that all have the @@ -358,7 +379,7 @@ android.applicationVariants.configureEach { variant -> // ------------------------------------------------------------------------------------------------- buildConfigField 'String', 'SENTRY_TOKEN', 'null' - if (!isDebug) { + if (!isDebugOrDCD) { buildConfigField 'boolean', 'CRASH_REPORTING', 'true' // Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available. try { @@ -369,7 +390,7 @@ android.applicationVariants.configureEach { variant -> buildConfigField 'boolean', 'CRASH_REPORTING', 'false' } - if (!isDebug) { + if (!isDebugOrDCD) { buildConfigField 'boolean', 'TELEMETRY', 'true' } else { buildConfigField 'boolean', 'TELEMETRY', 'false' @@ -390,7 +411,7 @@ android.applicationVariants.configureEach { variant -> print("Adjust token: ") - if (!isDebug) { + if (!isDebugOrDCD) { try { def token = new File("${rootDir}/.adjust_token").text.trim() buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"' @@ -617,9 +638,9 @@ dependencies { implementation project(':feature-share') implementation project(':feature-accounts-push') implementation project(':feature-webauthn') - implementation project(':feature-webcompat') +// implementation project(':feature-webcompat') implementation project(':feature-webnotifications') - implementation project(':feature-webcompat-reporter') +// implementation project(':feature-webcompat-reporter') implementation project(':service-pocket') implementation project(':service-contile') @@ -700,12 +721,8 @@ dependencies { implementation ComponentsDependencies.protobuf_javalite implementation ComponentsDependencies.google_material - implementation FenixDependencies.adjust implementation FenixDependencies.installreferrer // Required by Adjust - // Required for the Google Advertising ID - implementation ComponentsDependencies.play_services_ads_id - // Required for in-app reviews implementation ComponentsDependencies.play_review implementation ComponentsDependencies.play_review_ktx @@ -757,6 +774,9 @@ dependencies { lintChecks project(":mozilla-lint-rules") lintChecks project(':tooling-lint') + + // Tor Expert Bundle + implementation files('tor-expert-bundle.aar') } protobuf { @@ -914,16 +934,24 @@ def getSupportedLocales() { // This isn't running as a task, instead the array is build when the gradle file is parsed. // https://github.com/mozilla-mobile/fenix/issues/14175 def foundLocales = new StringBuilder() + def languageCodes = [] foundLocales.append("new String[]{") fileTree("src/main/res").visit { FileVisitDetails details -> - if (details.file.path.endsWith("${File.separator}strings.xml")) { + if (details.file.path.endsWith("${File.separator}torbrowser_strings.xml")) { def languageCode = details.file.parent.tokenize(File.separator).last().replaceAll('values-', '').replaceAll('-r', '-') languageCode = (languageCode == "values") ? "en-US" : languageCode - foundLocales.append("\"").append(languageCode).append("\"").append(",") + languageCodes.add(languageCode) } } + // The order of files in a `FileTree` is not stable, even on a single + // computer. Thus we need to sort the `languageCode`s. See: fenix#40083. + languageCodes.sort() + languageCodes.each { + foundLocales.append("\"").append(it).append("\"").append(",") + } + foundLocales.append("}") def foundLocalesString = foundLocales.toString().replaceAll(',}', '}') return foundLocalesString diff --git a/mobile/android/fenix/app/lint-baseline.xml b/mobile/android/fenix/app/lint-baseline.xml index d683580828eb0df4b3f1e2a34e2ee708d008fd15..e16dbb2f86f40e34bd2ce0a3580e5a8ea515b135 100644 --- a/mobile/android/fenix/app/lint-baseline.xml +++ b/mobile/android/fenix/app/lint-baseline.xml @@ -744,7 +744,7 @@ errorLine1=" android:width="973dp"" errorLine2=" ~~~~~"> <location - file="src/main/res/drawable/ic_notification_permission.xml" + file="src/main/res/drawable/mozac_lib_crash_notification.xml" line="7" column="20"/> </issue> @@ -777,7 +777,7 @@ errorLine1=" android:width="312dp"" errorLine2=" ~~~~~"> <location - file="src/main/res/drawable/ic_onboarding_search_widget.xml" + file="src/main/res/drawable/mozac_lib_crash_notification.xml" line="7" column="20"/> </issue> @@ -788,7 +788,7 @@ errorLine1="<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="235dp" android:height="298dp" android:viewportWidth="235" android:viewportHeight="298">" errorLine2=" ~~~~~"> <location - file="src/main/res/drawable/ic_onboarding_sync.xml" + file="src/main/res/drawable/mozac_lib_crash_notification.xml" line="5" column="128"/> </issue> diff --git a/mobile/android/fenix/app/onboarding.fml.yaml b/mobile/android/fenix/app/onboarding.fml.yaml index 7f61c5fafa6d6d60c070c193a2047e273618bba0..c71b483202529e8b8ffef6cf1f9f3768af0e972b 100644 --- a/mobile/android/fenix/app/onboarding.fml.yaml +++ b/mobile/android/fenix/app/onboarding.fml.yaml @@ -26,7 +26,7 @@ features: title: juno_onboarding_default_browser_title_nimbus_2 ordering: 10 body: juno_onboarding_default_browser_description_nimbus_3 - image-res: ic_onboarding_welcome + image-res: mozac_lib_crash_notification primary-button-label: juno_onboarding_default_browser_positive_button secondary-button-label: juno_onboarding_default_browser_negative_button @@ -34,7 +34,7 @@ features: card-type: add-search-widget title: juno_onboarding_add_search_widget_title body: juno_onboarding_add_search_widget_description - image-res: ic_onboarding_search_widget + image-res: mozac_lib_crash_notification ordering: 15 primary-button-label: juno_onboarding_add_search_widget_positive_button secondary-button-label: juno_onboarding_add_search_widget_negative_button @@ -43,7 +43,7 @@ features: card-type: sync-sign-in title: juno_onboarding_sign_in_title_2 body: juno_onboarding_sign_in_description_3 - image-res: ic_onboarding_sync + image-res: mozac_lib_crash_notification ordering: 20 primary-button-label: juno_onboarding_sign_in_positive_button secondary-button-label: juno_onboarding_sign_in_negative_button @@ -52,7 +52,7 @@ features: card-type: notification-permission title: juno_onboarding_enable_notifications_title_nimbus_2 body: juno_onboarding_enable_notifications_description_nimbus_2 - image-res: ic_notification_permission + image-res: mozac_lib_crash_notification ordering: 30 primary-button-label: juno_onboarding_enable_notifications_positive_button secondary-button-label: juno_onboarding_enable_notifications_negative_button @@ -85,7 +85,7 @@ objects: type: Image description: The resource id of the image to be displayed. # This should never be defaulted. - default: ic_onboarding_welcome + default: mozac_lib_crash_notification ordering: type: Int description: Used to sequence the cards. diff --git a/mobile/android/fenix/app/proguard-rules.pro b/mobile/android/fenix/app/proguard-rules.pro index 982ef996de7b4f27e7bec4153725f6f2aeefa00c..a677401fb2d9dc66cfd4379126003ccbd651fb85 100644 --- a/mobile/android/fenix/app/proguard-rules.pro +++ b/mobile/android/fenix/app/proguard-rules.pro @@ -130,3 +130,6 @@ -dontwarn java.beans.IntrospectionException -dontwarn java.beans.Introspector -dontwarn java.beans.PropertyDescriptor + +# Workaround for 'already has mapping' r8 issue (https://issuetracker.google.com/issues/140851070) +-keep class com.google.android.gms.common.internal.BaseGmsClient { *; } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/AppStartupTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/AppStartupTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..9b1eee3a4de223e63017dbf4180913ce0c6dfafa --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/AppStartupTest.kt @@ -0,0 +1,40 @@ +package org.mozilla.fenix + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + + +@RunWith(AndroidJUnit4::class) +class LaunchTest { + + @get:Rule + var rule: ActivityScenarioRule<HomeActivity> = ActivityScenarioRule(HomeActivity::class.java) + + @Test + fun appLaunchesWithoutCrash() { + val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + device.waitForIdle() + + // Simulate a 30-second delay + val latch = CountDownLatch(1) + Thread { + try { + Thread.sleep(30_000) + latch.countDown() + } catch (e: InterruptedException) { + e.printStackTrace() + } + }.start() + + latch.await(30, TimeUnit.SECONDS) + + // If we got here, the app did not crash. Test passed. + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt index 588078298ef8d67ab0b720feab8a7f12f997ad40..cc818e9906919107a7fd66ec06b937267c0cbe12 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt @@ -359,7 +359,7 @@ val privacyCaption: Caption = mockk(relaxed = true) private val defaultBrowserPageUiDataWithPrivacyCaption = OnboardingPageUiData( type = OnboardingPageUiData.Type.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = "default browser title", description = "default browser body", primaryButtonLabel = "default browser primary button text", @@ -368,7 +368,7 @@ private val defaultBrowserPageUiDataWithPrivacyCaption = OnboardingPageUiData( ) private val addSearchWidgetPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET, - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = "add search widget title", description = "add search widget body", primaryButtonLabel = "add search widget primary button text", @@ -377,7 +377,7 @@ private val addSearchWidgetPageUiData = OnboardingPageUiData( ) private val addSearchWidgetPageUiDataWithPrivacyCaption = OnboardingPageUiData( type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET, - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = "add search widget title", description = "add search widget body", primaryButtonLabel = "add search widget primary button text", @@ -386,7 +386,7 @@ private val addSearchWidgetPageUiDataWithPrivacyCaption = OnboardingPageUiData( ) private val syncPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = "sync title", description = "sync body", primaryButtonLabel = "sync primary button text", @@ -395,7 +395,7 @@ private val syncPageUiData = OnboardingPageUiData( ) private val syncPageUiDataWithPrivacyCaption = OnboardingPageUiData( type = OnboardingPageUiData.Type.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = "sync title", description = "sync body", primaryButtonLabel = "sync primary button text", @@ -404,7 +404,7 @@ private val syncPageUiDataWithPrivacyCaption = OnboardingPageUiData( ) private val notificationPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, - imageRes = R.drawable.ic_notification_permission, + imageRes = R.drawable.mozac_lib_crash_notification, title = "notification title", description = "notification body", primaryButtonLabel = "notification primary button text", @@ -414,7 +414,7 @@ private val notificationPageUiData = OnboardingPageUiData( private val defaultBrowserCardData = OnboardingCardData( cardType = OnboardingCardType.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "default browser title"), body = StringHolder(null, "default browser body"), primaryButtonLabel = StringHolder(null, "default browser primary button text"), @@ -426,7 +426,7 @@ private val defaultBrowserCardData = OnboardingCardData( private val defaultBrowserCardDataNoDisqualifiers = OnboardingCardData( cardType = OnboardingCardType.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "default browser title"), body = StringHolder(null, "default browser body"), primaryButtonLabel = StringHolder(null, "default browser primary button text"), @@ -438,7 +438,7 @@ private val defaultBrowserCardDataNoDisqualifiers = OnboardingCardData( private val addSearchWidgetCardDataNoConditions = OnboardingCardData( cardType = OnboardingCardType.ADD_SEARCH_WIDGET, - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "add search widget title"), body = StringHolder(null, "add search widget body"), primaryButtonLabel = StringHolder(null, "add search widget primary button text"), @@ -450,7 +450,7 @@ private val addSearchWidgetCardDataNoConditions = OnboardingCardData( private val addSearchWidgetCardData = OnboardingCardData( cardType = OnboardingCardType.ADD_SEARCH_WIDGET, - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "add search widget title"), body = StringHolder(null, "add search widget body"), primaryButtonLabel = StringHolder(null, "add search widget primary button text"), @@ -460,7 +460,7 @@ private val addSearchWidgetCardData = OnboardingCardData( private val syncCardData = OnboardingCardData( cardType = OnboardingCardType.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "sync title"), body = StringHolder(null, "sync body"), primaryButtonLabel = StringHolder(null, "sync primary button text"), @@ -472,7 +472,7 @@ private val syncCardData = OnboardingCardData( private val notificationCardData = OnboardingCardData( cardType = OnboardingCardType.NOTIFICATION_PERMISSION, - imageRes = R.drawable.ic_notification_permission, + imageRes = R.drawable.mozac_lib_crash_notification, title = StringHolder(null, "notification title"), body = StringHolder(null, "notification body"), primaryButtonLabel = StringHolder(null, "notification primary button text"), diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index 230dda4059d8ceb5518a58c5d683dd7a4b0b1c13..a3276e64b4674995dcc892f936b375bc166eabca 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -134,7 +134,7 @@ class BrowserRobot { verifyUrl("/releaseNotes") } catch (e: AssertionError) { Log.i(TAG, "verifyWhatsNewURL: AssertionError caught, checking redirect URL") - verifyUrl(SupportUtils.WHATS_NEW_URL) + verifyUrl(SupportUtils.getTorWhatsNewUrl()) } } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt index 5200fc54334c4c23856853d4676855e6e733d58c..c381e21b1f0cfd2071ade59dfbca470fd7f35d59 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt @@ -78,10 +78,10 @@ class SettingsSubMenuAboutRobot { } fun verifyProductCompany() { - Log.i(TAG, "verifyProductCompany: Trying to verify that the about section contains the company that produced the app info: ${"$appName is produced by Mozilla."}") + Log.i(TAG, "verifyProductCompany: Trying to verify that the about section contains the company that produced the app info: ${"$appName is produced by the Tor Project, a U.S.-based 501(c)(3) nonprofit."}") onView(withId(R.id.about_content)) - .check(matches(withText(containsString("$appName is produced by Mozilla.")))) - Log.i(TAG, "verifyProductCompany: Verified that the about section contains the company that produced the app info: \"$appName is produced by Mozilla.\"") + .check(matches(withText(containsString("$appName is produced by the Tor Project, a U.S.-based 501(c)(3) nonprofit.")))) + Log.i(TAG, "verifyProductCompany: Verified that the about section contains the company that produced the app info: \"$appName is produced by the Tor Project, a U.S.-based 501(c)(3) nonprofit.\"") } fun verifyCurrentTimestamp() { diff --git a/mobile/android/fenix/app/src/beta/ic_launcher-playstore.png b/mobile/android/fenix/app/src/beta/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..713e640aff3202e629e4fa32f6eb7d06c922fa2b Binary files /dev/null and b/mobile/android/fenix/app/src/beta/ic_launcher-playstore.png differ diff --git a/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.png b/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..679bc00a694c64f092be95f7a717bf0940375a7f Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.png differ diff --git a/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.webp b/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.webp deleted file mode 100644 index b6938e566132ca158e1b7efefbf1de322bb9685d..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/beta/res/drawable-hdpi/fenix_search_widget.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/beta/res/drawable/animated_splash_screen.xml b/mobile/android/fenix/app/src/beta/res/drawable/animated_splash_screen.xml deleted file mode 100644 index 02b55b57a3da82b4919f0814a1be1cf32fd785d4..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/beta/res/drawable/animated_splash_screen.xml +++ /dev/null @@ -1,566 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" > - <aapt:attr name="android:drawable"> - <vector - android:width="432dp" - android:height="432dp" - android:viewportWidth="432" - android:viewportHeight="432"> - <group - android:name="a1_t" - android:pivotX="216" - android:pivotY="216"> - <path - android:pathData="M303.8,251.4h-79.2c-2.3,0 -4.2,1.9 -4.2,4.2v12.7c0,18.7 15.1,33.8 33.8,33.8l0,0H298c14,0 25.3,-11.4 25.3,-25.3v-11.1C323.3,259.3 317,251.4 303.8,251.4L303.8,251.4z" - android:fillColor="#008787"/> - <path - android:pathData="M303.8,251.4h-79.2c-2.3,0 -4.2,1.9 -4.2,4.2v12.7c0,18.7 15.1,33.8 33.8,33.8l0,0H298c14,0 25.3,-11.4 25.3,-25.3v-11.1C323.3,259.3 317,251.4 303.8,251.4L303.8,251.4z" - android:strokeAlpha="0.9" - android:fillAlpha="0.9"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="301.7" - android:startY="300.03" - android:endX="274.29" - android:endY="274.08" - android:type="linear"> - <item android:offset="0" android:color="#7F054096"/> - <item android:offset="0.05" android:color="#700F3D9C"/> - <item android:offset="0.26" android:color="#3F2F35B1"/> - <item android:offset="0.47" android:color="#1C462FBF"/> - <item android:offset="0.67" android:color="#07542BC8"/> - <item android:offset="0.86" android:color="#00592ACB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M316.4,179.2c-4.7,-11.3 -14.2,-23.5 -21.7,-27.4c6.1,11.9 9.6,23.9 11,32.9c0,0 0,0 0,0.2c-12.3,-30.5 -33,-42.8 -50,-69.7c-0.9,-1.4 -1.7,-2.7 -2.6,-4.1c-0.4,-0.7 -0.8,-1.5 -1.2,-2.3c-0.7,-1.4 -1.3,-2.8 -1.6,-4.3c0,-0.1 -0.1,-0.3 -0.2,-0.3c0,0 -0.1,0 -0.2,0l0,0c0,0 0,0 -0.1,0l0,0c-27.2,16 -36.5,45.4 -37.3,60.2c-10.9,0.8 -21.3,4.7 -29.8,11.5c-0.9,-0.8 -1.8,-1.4 -2.8,-2.1c-2.5,-8.7 -2.6,-17.8 -0.3,-26.5c-11.1,5 -19.8,13.1 -26.1,20.2l0,0c-4.3,-5.5 -4,-23.4 -3.7,-27.1c0,-0.2 -3.2,1.6 -3.6,1.9c-3.8,2.7 -7.3,5.7 -10.6,9.1c-3.7,3.7 -7.1,7.8 -10.1,12.1l0,0l0,0c-7,9.9 -11.9,21 -14.5,32.8c0,0.2 -0.1,0.5 -0.1,0.7c-0.2,0.9 -0.9,5.7 -1.1,6.8c0,0.1 0,0.1 0,0.2c-0.9,4.9 -1.5,9.9 -1.8,15c0,0.2 0,0.4 0,0.5c0,59.7 48.5,108.2 108.3,108.2c53.6,0 98.1,-38.9 106.8,-90c0.2,-1.4 0.3,-2.8 0.5,-4.2C325.6,215 323.2,195.5 316.4,179.2zM191.5,263.9c0.5,0.2 1,0.5 1.5,0.7c0,0 0,0 0.1,0C192.6,264.5 192.1,264.2 191.5,263.9zM305.7,184.8L305.7,184.8L305.7,184.8L305.7,184.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="296.59" - android:startY="138.83" - android:endX="128.16" - android:endY="312.38" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M316.4,179.2c-4.7,-11.3 -14.2,-23.5 -21.7,-27.4c6.1,11.9 9.6,23.9 11,32.9c0,0 0,0 0,0.1v0.1c10.2,27.7 4.6,55.9 -3.4,73.1c-12.4,26.6 -42.5,54 -89.5,52.6c-50.8,-1.4 -95.5,-39.2 -103.9,-88.6c-1.5,-7.8 0,-11.8 0.8,-18.1c-0.9,4.9 -1.3,6.3 -1.8,15c0,0.2 0,0.4 0,0.5c0,59.8 48.5,108.3 108.3,108.3c53.6,0 98.1,-38.9 106.8,-90c0.2,-1.4 0.3,-2.8 0.5,-4.2C325.6,215 323.2,195.5 316.4,179.2z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="297.63" - android:centerY="151.73" - android:gradientRadius="221.61" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M316.4,179.2c-4.7,-11.3 -14.2,-23.5 -21.7,-27.4c6.1,11.9 9.6,23.9 11,32.9c0,0 0,0 0,0.1v0.1c10.2,27.7 4.6,55.9 -3.4,73.1c-12.4,26.6 -42.5,54 -89.5,52.6c-50.8,-1.4 -95.5,-39.2 -103.9,-88.6c-1.5,-7.8 0,-11.8 0.8,-18.1c-0.9,4.9 -1.3,6.3 -1.8,15c0,0.2 0,0.4 0,0.5c0,59.8 48.5,108.3 108.3,108.3c53.6,0 98.1,-38.9 106.8,-90c0.2,-1.4 0.3,-2.8 0.5,-4.2C325.6,215 323.2,195.5 316.4,179.2z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="213.81" - android:centerY="222.16" - android:gradientRadius="227.15" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#56DB293D"/> - <item android:offset="0.5" android:color="#16F5334B"/> - <item android:offset="0.53" android:color="#00FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M263.7,191.9c0.2,0.2 0.5,0.3 0.7,0.5c-2.7,-4.8 -6.1,-9.2 -10.1,-13.1c-33.7,-33.7 -8.8,-73 -4.6,-75l0,0c-27.2,16 -36.5,45.4 -37.3,60.2c1.3,-0.1 2.5,-0.2 3.8,-0.2C236.6,164.2 254.3,175.4 263.7,191.9L263.7,191.9z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="237.41" - android:centerY="93.62" - android:gradientRadius="72.74" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,198.6c-0.2,2.7 -9.7,12 -13,12c-30.8,0 -35.8,18.6 -35.8,18.6c1.4,15.7 12.3,28.6 25.5,35.4c0.6,0.3 1.2,0.6 1.8,0.9c1,0.5 2.1,0.9 3.2,1.3c4.6,1.6 9.3,2.5 14.1,2.7c54,2.5 64.5,-64.6 25.5,-84c10,-1.8 20.3,2.3 26.1,6.4c-9.5,-16.5 -27.1,-27.7 -47.5,-27.7c-1.3,0 -2.5,0.1 -3.8,0.2c-10.9,0.8 -21.3,4.7 -29.8,11.5c1.7,1.4 3.5,3.2 7.4,7.1C197.5,190.2 216.3,197.8 216.4,198.6L216.4,198.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="189.41" - android:centerY="280.33" - android:gradientRadius="96.24" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,198.6c-0.2,2.7 -9.7,12 -13,12c-30.8,0 -35.8,18.6 -35.8,18.6c1.4,15.7 12.3,28.6 25.5,35.4c0.6,0.3 1.2,0.6 1.8,0.9c1,0.5 2.1,0.9 3.2,1.3c4.6,1.6 9.3,2.5 14.1,2.7c54,2.5 64.5,-64.6 25.5,-84c10,-1.8 20.3,2.3 26.1,6.4c-9.5,-16.5 -27.1,-27.7 -47.5,-27.7c-1.3,0 -2.5,0.1 -3.8,0.2c-10.9,0.8 -21.3,4.7 -29.8,11.5c1.7,1.4 3.5,3.2 7.4,7.1C197.5,190.2 216.3,197.8 216.4,198.6L216.4,198.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="212.55" - android:centerY="199" - android:gradientRadius="51.11" - android:type="radial"> - <item android:offset="0.21" android:color="#009059FF"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M177.6,172.2c0.8,0.5 1.5,1 2.3,1.5c-2.5,-8.7 -2.6,-17.8 -0.3,-26.5c-11.1,5 -19.8,13.1 -26.1,20.2C154,167.4 169.7,167.1 177.6,172.2L177.6,172.2z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="208.87" - android:centerY="120.79" - android:gradientRadius="76.52" - android:type="radial"> - <item android:offset="0.1" android:color="#FFFFE226"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M108.8,222c8.4,49.4 53.2,87.1 104,88.5c47.1,1.4 77.1,-26 89.5,-52.6c8,-17.2 13.6,-45.4 3.4,-73.1l0,0v-0.1c0,-0.1 0,-0.1 0,-0.1s0,0 0,0.2c3.8,25.1 -8.9,49.4 -28.9,65.8v0.1c-38.9,31.6 -76.1,19.1 -83.6,14c-0.5,-0.3 -1,-0.5 -1.6,-0.8c-22.7,-10.8 -32.1,-31.5 -30,-49.2c-19.2,0 -25.7,-16.1 -25.7,-16.1s17.2,-12.3 39.9,-1.6c21,9.9 40.7,1.6 40.7,1.6c0,-0.9 -18.9,-8.4 -26.2,-15.6c-3.9,-3.9 -5.8,-5.7 -7.4,-7.1c-0.9,-0.8 -1.8,-1.4 -2.8,-2.1c-0.7,-0.5 -1.5,-1 -2.3,-1.5c-7.9,-5.1 -23.6,-4.9 -24.1,-4.8l0,0c-4.3,-5.5 -4,-23.4 -3.7,-27.1c0,-0.2 -3.2,1.6 -3.6,1.9c-3.8,2.7 -7.3,5.7 -10.6,9.1c-3.7,3.7 -7.1,7.8 -10.1,12.1l0,0l0,0c-7,9.9 -11.9,21 -14.5,32.8C110.7,196.5 106.9,213.3 108.8,222L108.8,222z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="278.74" - android:centerY="70.41" - android:gradientRadius="365.3" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M254.4,179.3c4,3.9 7.3,8.3 10.1,13.1c0.6,0.5 1.2,0.9 1.6,1.4c24.6,22.6 11.7,54.6 10.7,56.9c20,-16.5 32.7,-40.8 28.9,-65.8c-12.3,-30.5 -33,-42.8 -50,-69.7c-0.9,-1.4 -1.7,-2.7 -2.6,-4.1c-0.4,-0.7 -0.8,-1.5 -1.2,-2.3c-0.7,-1.4 -1.3,-2.8 -1.6,-4.3c0,-0.1 -0.1,-0.3 -0.2,-0.3c0,0 -0.1,0 -0.2,0l0,0c0,0 0,0 -0.1,0C245.5,106.2 220.7,145.6 254.4,179.3L254.4,179.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="247.82" - android:centerY="76.43" - android:gradientRadius="240.17" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M266,193.8c-0.5,-0.5 -1,-0.9 -1.6,-1.4c-0.2,-0.2 -0.5,-0.3 -0.7,-0.5c-5.8,-4.1 -16.1,-8.1 -26.1,-6.4c39,19.5 28.5,86.6 -25.5,84c-4.8,-0.2 -9.6,-1.1 -14.1,-2.7c-1.1,-0.4 -2.1,-0.9 -3.2,-1.3c-0.6,-0.3 -1.2,-0.5 -1.8,-0.9c0,0 0,0 0.1,0c7.5,5.1 44.7,17.7 83.6,-14v-0.1C277.8,248.4 290.6,216.4 266,193.8L266,193.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="209.65" - android:centerY="148.39" - android:gradientRadius="209.74" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M167.5,229.2c0,0 5,-18.6 35.8,-18.6c3.3,0 12.8,-9.3 13,-12s-19.7,8.3 -40.7,-1.6c-22.6,-10.6 -39.9,1.6 -39.9,1.6s6.5,16.1 25.7,16.1c-2,17.7 7.3,38.4 30,49.2c0.5,0.2 1,0.5 1.5,0.7C179.8,257.9 168.9,245 167.5,229.2z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="264.09" - android:centerY="160.45" - android:gradientRadius="252.1" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M316.4,179.2c-4.7,-11.3 -14.2,-23.5 -21.7,-27.4c6.1,11.9 9.6,23.9 11,32.9c0,0 0,0 0,0.2c-12.3,-30.5 -33,-42.8 -50,-69.7c-0.9,-1.4 -1.7,-2.7 -2.6,-4.1c-0.4,-0.7 -0.8,-1.5 -1.2,-2.3c-0.7,-1.4 -1.3,-2.8 -1.6,-4.3c0,-0.1 -0.1,-0.3 -0.2,-0.3c0,0 -0.1,0 -0.2,0l0,0c0,0 0,0 -0.1,0l0,0c-27.2,16 -36.5,45.4 -37.3,60.2c1.3,-0.1 2.5,-0.2 3.8,-0.2c20.3,0 38,11.2 47.5,27.7c-5.8,-4.1 -16.1,-8.1 -26.1,-6.4c39,19.5 28.5,86.6 -25.5,84c-4.8,-0.2 -9.6,-1.1 -14.1,-2.7c-1.1,-0.4 -2.1,-0.9 -3.2,-1.3c-0.6,-0.3 -1.2,-0.5 -1.8,-0.9c0,0 0,0 0.1,0c-0.5,-0.3 -1,-0.5 -1.6,-0.8c0.5,0.2 1,0.5 1.5,0.7c-13.3,-6.9 -24.2,-19.7 -25.5,-35.4c0,0 5,-18.6 35.8,-18.6c3.3,0 12.8,-9.3 13,-12c0,-0.9 -18.9,-8.4 -26.2,-15.6c-3.9,-3.9 -5.8,-5.7 -7.4,-7.1c-0.9,-0.8 -1.8,-1.4 -2.8,-2.1c-2.5,-8.7 -2.6,-17.8 -0.3,-26.5c-11.1,5 -19.8,13.1 -26.1,20.2l0,0c-4.3,-5.5 -4,-23.4 -3.7,-27.1c0,-0.2 -3.2,1.6 -3.6,1.9c-3.8,2.7 -7.3,5.7 -10.6,9.1c-3.7,3.7 -7.1,7.8 -10.1,12.1l0,0l0,0c-7,9.9 -11.9,21 -14.5,32.8c0,0.2 -0.1,0.5 -0.1,0.7c-0.2,0.9 -1.1,5.8 -1.3,6.9c0,0.1 0,-0.1 0,0c-0.9,5 -1.4,10.1 -1.6,15.1c0,0.2 0,0.4 0,0.5c0,59.7 48.5,108.2 108.3,108.2c53.6,0 98.1,-38.9 106.8,-90c0.2,-1.4 0.3,-2.8 0.5,-4.2C325.6,215 323.2,195.5 316.4,179.2zM305.7,184.7v0.1l0,0V184.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="285.98" - android:startY="140.07" - android:endX="151.82" - android:endY="296.61" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.6" android:color="#00FFF44F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M319.1,269.9h-72.8c-17.2,0 -31.2,14 -31.2,31.2l0,0v15.2c0,2.3 1.9,4.2 4.2,4.2h72.8c17.2,0 31.2,-14 31.2,-31.2v-23.7C323.3,268 321.4,269.9 319.1,269.9L319.1,269.9z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="227.01" - android:startY="274.49" - android:endX="325.95" - android:endY="316.35" - android:type="linear"> - <item android:offset="0" android:color="#FF54FFBD"/> - <item android:offset="1" android:color="#FF00DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M247.6,295c1.5,-0.9 2.5,-2.5 2.4,-4.2c0,-3.7 -2.6,-5.9 -7.3,-5.9H234v21h8.7c4.6,0 7.5,-2.1 7.5,-6.2C250.4,297.4 249.4,295.8 247.6,295L247.6,295zM238.1,288.4h4.8c2.1,0 3.1,0.9 3.1,2.3s-0.9,2.5 -3.1,2.5h-4.8V288.4zM242.9,302.2h-4.8V297h4.6c2.6,0 3.5,0.9 3.5,2.6C246.3,301.1 245.1,302.2 242.9,302.2L242.9,302.2zM254.3,305.8h14.1V302h-10.1v-4.8h10.1v-3.8h-10.1v-4.7h10.1v-3.8h-14.1L254.3,305.8L254.3,305.8zM287.4,284.9h-15.6v3.7h5.8v17.2h4v-17.3h5.8L287.4,284.9zM298.3,284.9h-4l-7.9,21h4.1l1.4,-3.8h8.7l1.4,3.8h4.1L298.3,284.9zM293.3,298.3l3.1,-8.3l3,8.3H293.3z" - android:fillColor="#20123A"/> - </group> - </vector> - </aapt:attr> - <target - android:name="a1_t"> - <aapt:attr - name="android:animation"> - <set> - <objectAnimator - android:propertyName="scaleX" - android:duration="300" - android:valueFrom="0.75" - android:valueTo="0.75" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleX" - android:duration="700" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="300" - android:valueFrom="0.75002400000000002" - android:valueTo="0.75002400000000002" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleY" - android:duration="700" - android:valueFrom="0.75002400000000002" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - </set> - </aapt:attr> - </target> -</animated-vector> diff --git a/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_background.xml b/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..000da4ba4a2ad422d3da33b67125ed5cb6bd8499 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_background.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="432" + android:viewportHeight="432"> + <path + android:pathData="m0,0h432v432h-432z" + android:fillColor="#dcf9ef"/> +</vector> diff --git a/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_foreground.xml b/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 736e0f6aef6bd23118c0160fd3ad6e82eb871229..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,221 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportWidth="108" - android:viewportHeight="108"> - <path - android:pathData="M75.22,60.55H51.81a1.25,1.25 0,0 0,-1.25 1.25v3.75a10,10 0,0 0,10 10h13A7.49,7.49 0,0 0,81 68v-3.23c0,-1.88 -1.87,-4.22 -5.78,-4.22z" - android:fillColor="#008787"/> - <path - android:pathData="M75.22,60.55H51.81a1.25,1.25 0,0 0,-1.25 1.25v3.75a10,10 0,0 0,10 10h13A7.49,7.49 0,0 0,81 68v-3.23c0,-1.88 -1.87,-4.22 -5.78,-4.22z" - android:strokeAlpha="0.9" - android:fillAlpha="0.9"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="75.100006" - android:startX="74.920456" - android:endY="72.55" - android:endX="65.785286" - android:type="linear"> - <item android:offset="0" android:color="#7F054096"/> - <item android:offset="0.7" android:color="#07542BC8"/> - <item android:offset="0.85" android:color="#00592ACB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46A12.92,12.92 0,0 0,46 43.49a10.031,10.031 0,0 0,-0.68 -0.51,12 12,0 0,1 -0.07,-6.36A19.21,19.21 0,0 0,39 41.46c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.159,39.159 0,0 0,-0.26 1.62,0.13 0.13,0 0,1 0,0.06 26.47,26.47 0,0 0,-0.5 3.59L28,54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM48.13,64.66l0.36,0.18zM54.13,48.96zM75.6,45.65z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="34.731655" - android:startX="73.6671" - android:endY="77.194664" - android:endX="32.80596" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64V54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="53.746716" - android:centerX="68.339355" - android:centerY="37.69" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64V54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="55.09038" - android:centerX="48.56332" - android:centerY="55.002163" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#56DB293D"/> - <item android:offset="0.5" android:color="#16F5334B"/> - <item android:offset="0.53" android:color="#00FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M65.47,47.34l0.17,0.12a14.35,14.35 0,0 0,-2.42 -3.15c-8.09,-8.09 -2.12,-17.55 -1.12,-18a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.45 6.57z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="29.610003" - android:centerX="59.1192" - android:centerY="23.771997" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.08,49c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,46 43.49c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="26.21" - android:centerX="48.315395" - android:centerY="69.29355" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.08,49c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,46 43.49c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="13.917509" - android:centerX="50.381275" - android:centerY="49.283504" - android:type="radial"> - <item android:offset="0.21" android:color="#009059FF"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M44.77,42.62l0.54,0.36a12,12 0,0 1,-0.07 -6.36A19.21,19.21 0,0 0,39 41.46c0.1,0 3.87,-0.07 5.77,1.16z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="18.444002" - android:centerX="52.251003" - android:centerY="30.259998" - android:type="radial"> - <item android:offset="0.1" android:color="#FFFFE226"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M28.24,54.58c2,11.88 12.77,20.94 25,21.29 11.3,0.32 18.52,-6.25 21.51,-12.65a23.55,23.55 0,0 0,0.81 -17.57c0.92,6 -2.15,11.87 -6.94,15.82 -9.34,7.61 -18.28,4.59 -20.09,3.35l-0.38,-0.19c-5.45,-2.6 -7.7,-7.56 -7.22,-11.82A6.67,6.67 0,0 1,34.74 49a9.8,9.8 0,0 1,9.57 -0.38A13,13 0,0 0,54.08 49c0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71a10.031,10.031 0,0 0,-0.68 -0.51l-0.54,-0.36c-1.9,-1.23 -5.67,-1.16 -5.8,-1.16 -1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88c-0.02,0.02 -0.95,4.07 -0.49,6.16z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="89.619446" - android:centerX="69.60241" - android:centerY="18.083904" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M63.22,44.31a14.35,14.35 0,0 1,2.42 3.15l0.39,0.32c5.9,5.44 2.81,13.13 2.58,13.68 4.79,-4 7.86,-9.79 6.94,-15.82 -3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07H62.1c-1,0.47 -6.97,9.93 1.12,18.02z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="95.36754" - android:centerX="-6.76699" - android:centerY="37.10374" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M66,47.78l-0.39,-0.32 -0.17,-0.12a9,9 0,0 0,-6.27 -1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21c1.81,1.24 10.75,4.26 20.09,-3.35 0.3,-0.58 3.39,-8.27 -2.54,-13.71z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="56.180176" - android:centerX="52.887726" - android:centerY="35.519154" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M42.35,56.32s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88a13,13 0,0 1,-9.77 -0.38,9.8 9.8,0 0,0 -9.57,0.38 6.67,6.67 0,0 0,6.16 3.88c-0.48,4.26 1.77,9.22 7.22,11.82l0.36,0.18a11,11 0,0 1,-6.13 -8.52z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="60.55354" - android:centerX="65.548615" - android:centerY="39.680077" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.4 6.66,9 9,0 0,0 -6.27,-1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21 -0.38,-0.19 0.36,0.18a11,11 0,0 1,-6.13 -8.52s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88 0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71A10.031,10.031 0,0 0,45.27 43a12,12 0,0 1,-0.07 -6.36,19.21 19.21,0 0,0 -6.2,4.82c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.815,39.815 0,0 0,-0.3 1.64A31.77,31.77 0,0 0,28 53.83L28,54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM75.54,45.62z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="33.91085" - android:startX="69.86179" - android:endY="72.21511" - android:endX="37.319843" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.6" android:color="#00FFF44F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M79.75,66H58.23A9.23,9.23 0,0 0,49 75.24v4.51A1.25,1.25 0,0 0,50.25 81h21.52A9.23,9.23 0,0 0,81 71.77v-7A1.24,1.24 0,0 1,79.75 66z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="67.2045" - android:startX="52.19842" - android:endY="79.377" - android:endX="82.60009" - android:type="linear"> - <item android:offset="0.001" android:color="#FF54FFBD"/> - <item android:offset="1" android:color="#FF00DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.26,70.33h2.65c1.43,0 2.23,0.64 2.23,1.79a1.42,1.42 0,0 1,-0.74 1.3,1.47 1.47,0 0,1 0.83,1.42c0,1.27 -0.87,1.9 -2.3,1.9h-2.67zM55.48,71.42v1.49L57,72.91c0.66,0 0.94,-0.33 0.94,-0.77s-0.31,-0.72 -1,-0.72zM55.48,74.02v1.6L57,75.62c0.68,0 1,-0.3 1,-0.8s-0.3,-0.8 -1.08,-0.8zM60.42,70.33h4.31v1.16h-3.07v1.45h3.07v1.16h-3.07v1.46h3.07v1.18h-4.31zM67.58,71.47L65.8,71.47v-1.14h4.77v1.14L68.8,71.47v5.27h-1.22zM72.67,70.33h1.22l2.43,6.41L75,76.74l-0.42,-1.17h-2.64l-0.42,1.17h-1.28zM72.35,74.45h1.86l-0.93,-2.55z" - android:fillColor="#20123a"/> -</vector> diff --git a/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_monochrome_foreground.xml b/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_monochrome_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..9c32b4365e7e2022e843ccd5f6ca77ab1c43dff3 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/drawable/ic_launcher_monochrome_foreground.xml @@ -0,0 +1,18 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="256" + android:viewportHeight="257"> + <group android:scaleX="0.4869866" + android:scaleY="0.4888889" + android:translateX="65.66572" + android:translateY="65.67778"> + <path + android:pathData="M62.56,111.94C67,111.94 70.72,110.38 73.92,107.17C77.13,103.96 78.68,99.93 78.68,94.86C78.68,90.5 77.04,86.73 73.65,83.34L73.63,83.32C70.34,79.95 66.63,78.31 62.29,78.31C58.59,78.31 55.28,79.9 52.17,83.17C49.12,86.38 47.63,90.16 47.63,94.72C47.63,97.37 47.99,99.8 48.7,101.94C49.48,104.04 50.53,105.88 51.84,107.43C53.11,108.84 54.66,109.98 56.45,110.81C58.27,111.56 60.33,111.94 62.56,111.94Z" + android:fillColor="#4A454E"/> + <path + android:pathData="M128,256.91C198.69,256.91 256,199.6 256,128.91C256,58.22 198.69,0.91 128,0.91C57.31,0.91 0,58.22 0,128.91C0,199.6 57.31,256.91 128,256.91ZM233,128.91C233,70.92 185.99,23.91 128,23.91V39.91C177.15,39.91 217,79.75 217,128.91C217,178.06 177.15,217.91 128,217.91V233.91C185.99,233.91 233,186.9 233,128.91ZM193.75,128.91C193.75,92.6 164.31,63.16 128,63.16V79.16C155.48,79.16 177.75,101.43 177.75,128.91C177.75,156.38 155.48,178.66 128,178.66V194.66C164.31,194.66 193.75,165.22 193.75,128.91ZM128,101.66C143.05,101.66 155.25,113.86 155.25,128.91C155.25,143.96 143.05,156.16 128,156.16V101.66ZM90.71,94.86C90.71,102.56 93.36,108.02 98.8,111.54C100.29,112.5 101.06,114.24 100.75,115.96L99.93,120.5C99.68,121.87 98.79,123.03 97.53,123.61C96.29,124.18 94.9,124.11 93.71,123.42C89.35,120.88 86.16,117.89 84.18,114.5C82.28,116.93 79.87,119.01 76.97,120.71L76.97,120.72L76.75,120.84C72.29,123.36 67.51,124.64 62.56,124.64C53.76,124.64 46.62,121.63 41.34,115.68L41.3,115.63C36.54,110.19 34.13,103.15 34.13,94.72C34.13,87.5 36.44,81.01 40.98,75.43L41.23,75.12L41.48,74.83C46.84,68.62 53.54,65.47 62.56,65.47C71.58,65.47 78.82,68.88 84.13,75.62C86.04,71.65 89.25,68.27 93.74,65.52C94.97,64.77 96.45,64.71 97.73,65.34C99.04,66 99.91,67.26 100.05,68.73L100.51,73.51C100.64,74.82 100.16,76.11 99.2,77.03C93.49,82.51 90.71,88.34 90.71,94.86Z" + android:fillColor="#4A454E" + android:fillType="evenOdd"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..803115f3476cf8ea75ee5057a6ddd79803549902 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_launcher_monochrome_foreground" /> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..d372a4fca9b35d26af58c251afcad94bd67642ec --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp index 705987f0bd136af6898b373df4d77f4ad1b6fa85..e7bed2fc08f778a5fe1461e618bf15fd15ec1f33 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..f7e8e5434db4e73d36ccf3481c05b204b14fd070 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..243f0e941481c982da9582234acd34059720b0ab Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1a3f17aa47b348c03c8d76a83ad50684cf741a56 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp index 1710c1b6449c5fc244dac921f1cc1522d0a13076..c0e64e4d78223ec47b22e3639779d5b8fd6fa6fe 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp index eac2ba11c550f65e87277b4861526442660c9b3a..b831645423a8f042d67ac8efd85e438fdff93938 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..1d7a1b9ff3da7e43be757e04964027ad5893acac Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..632473a0063e4be0c376e1d640fbd9e652cbe446 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..7b72764bae7de21dcd960eafd31c8792b0458903 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_round.webp index 17186974ad9c3c59b2e245bd747cd40c0d6dcf5d..14b5ffcb94f888fe7490ab304bc98ed0522e8991 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher.webp index 7bb69c9fbf3fabcb3c20f95978bbb45826f9a91c..1b8092aa6fa7e9d47be93e73fad2b83fab5c9697 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..8820f55b06195ce0eb9a8df89c19ce4d8e177255 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..246e0035c5b4a947d975d2c96de94ae381f7c3e4 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..cd406fa68ba392ad9a3b601208e5e4e853ac6f84 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_round.webp index 66db0df3a22e32e25896d81e7d91129f44ce5073..dde29e3b36655eb411100741509bbf30eea68f83 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher.webp index d63a58937842600f3dcbd908ac491194093f279e..b2fd1b7425c937901b1c6ce888951257d94d8b7b 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..d598c9a61b767290295648c6d28723b73557c245 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..08b7cf151a243dc16d4e43084e5b2fddac5bb2e1 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..d1f8dda6b16933206af3d08b4114839a9e2c167d Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_round.webp index 4dbc3878ec6e1bbc511a822d095e4967056e780c..f60a6c2cff37e429e5af529f13803791e9e3437a 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher.webp index 2a2421af1c17ab03340b921e467172aed04e025c..bdba0a8102d3b6f2b752f961baf7f494f7289ff7 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..34444f223d904551656deca74bad8c21ae78ac02 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..3fa2ec00b701b22f18af751ff17ceb09852536f7 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..f6b902942bb2435202b1880a43d4ee7feb1caff9 Binary files /dev/null and b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_round.webp index 70f7527d6bf24073342e50ceaf34e3109af89796..01328dc7c8c4f54080f38dc1875a2d7354df812a 100644 Binary files a/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/beta/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/beta/res/values/ic_launcher_monochrome_background.xml b/mobile/android/fenix/app/src/beta/res/values/ic_launcher_monochrome_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..70a105458b46dbc72a2bce80b62fa57c36cdbcf1 --- /dev/null +++ b/mobile/android/fenix/app/src/beta/res/values/ic_launcher_monochrome_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_monochrome_background">#FEFBFF</color> +</resources> diff --git a/mobile/android/fenix/app/src/beta/res/values/static_strings.xml b/mobile/android/fenix/app/src/beta/res/values/static_strings.xml index 18bddf2c9e98e888fd6dff71c8da7c1951fcd12c..40f346f34786d0f5b0cc83050ba9411ffdb196e3 100644 --- a/mobile/android/fenix/app/src/beta/res/values/static_strings.xml +++ b/mobile/android/fenix/app/src/beta/res/values/static_strings.xml @@ -4,5 +4,5 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <!-- Name of the application --> - <string name="app_name" translatable="false">Firefox Beta</string> + <string name="app_name" translatable="false">Tor Browser Alpha</string> </resources> diff --git a/mobile/android/fenix/app/src/beta/res/xml/shortcuts.xml b/mobile/android/fenix/app/src/beta/res/xml/shortcuts.xml index 2da32f3afedb959d9af610a7d1ac82311484ebb5..eb584ae772ef9c206dd4cc3008934d48ab19c41c 100644 --- a/mobile/android/fenix/app/src/beta/res/xml/shortcuts.xml +++ b/mobile/android/fenix/app/src/beta/res/xml/shortcuts.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- <shortcut android:shortcutId="password_manager" android:enabled="true" @@ -21,7 +22,7 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_TAB" - android:targetPackage="org.mozilla.firefox_beta" + android:targetPackage="org.torproject.torbrowser_alpha" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> <shortcut @@ -31,7 +32,8 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_private_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_PRIVATE_TAB" - android:targetPackage="org.mozilla.firefox_beta" + android:targetPackage="org.torproject.torbrowser_alpha" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> + --> </shortcuts> diff --git a/mobile/android/fenix/app/src/debug/ic_launcher-web.webp b/mobile/android/fenix/app/src/debug/ic_launcher-web.webp deleted file mode 100644 index 7e09e488ad86b49e65f1f2175553d102bf130d0b..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/debug/ic_launcher-web.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/debug/res/drawable-hdpi/fenix_search_widget.png b/mobile/android/fenix/app/src/debug/res/drawable-hdpi/fenix_search_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..4af23121eb4c1ba61d871dcbbb54c0eef9664888 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/drawable-hdpi/fenix_search_widget.png differ diff --git a/mobile/android/fenix/app/src/debug/res/drawable/animated_splash_screen.xml b/mobile/android/fenix/app/src/debug/res/drawable/animated_splash_screen.xml deleted file mode 100644 index e2b7ead51803a66037c7b90aba5e71fb8a523078..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/debug/res/drawable/animated_splash_screen.xml +++ /dev/null @@ -1,1036 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" > - <aapt:attr name="android:drawable"> - <vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="432dp" - android:height="432dp" - android:viewportWidth="432" - android:viewportHeight="432"> - <group - android:name="a1_t" - android:pivotX="216" - android:pivotY="216"> - <path - android:pathData="M155.3,238.8l8.3,23.3l12.7,17l29.5,5.7l14.1,1.2l24.1,-6.1l10.4,-9.9L155.3,238.8z" - android:fillColor="#09204D"/> - <path - android:pathData="M280.6,204.4l-2.9,-9.8l-8.4,-16l-9.6,-10.2l-10.3,-7.4l-8.9,-3.4l-10.7,-3.8l-17.7,-1.2l-11.1,2.1l-9,2.7l-16.1,9.4l-10,11.3l-9.2,15l-3.6,12.9l-0.7,19.4l3.4,13.3l7.8,15.1l5.4,7.4l7.6,6.9l9.3,6.4l11.6,5l19.2,2.3l10.1,0.3l14.9,-4.2l13.3,-7.4l8.5,-7.4l6.7,-8l9.4,-18.5l2.2,-12.7L280.6,204.4z" - android:fillColor="#09204D"/> - <path - android:pathData="M212.3,161.5l-8,7.9l13,5.2l9.5,-11.9L212.3,161.5z" - android:fillColor="#0E56D7"/> - <path - android:pathData="M217.3,174.6l24.9,-0.8l-15.3,-11.1L217.3,174.6z" - android:fillColor="#1053D1"/> - <path - android:pathData="M240.2,162.6l-13.4,0.1l15.3,11.1l14.1,-1L240.2,162.6z" - android:fillColor="#0B4FBF"/> - <path - android:pathData="M256.3,172.9l-8,-11.2l11.2,6.7L256.3,172.9z" - android:fillColor="#0B48B0"/> - <path - android:pathData="M267,179.8l-10.7,-6.9l3,-4.4L267,179.8z" - android:fillColor="#0C45A7"/> - <path - android:pathData="M256.3,172.9l-1.9,7.7l9.7,3.9L256.3,172.9z" - android:fillColor="#0F46AF"/> - <path - android:pathData="M256.3,172.9l10.7,6.9l-2.7,4.7L256.3,172.9z" - android:fillColor="#0C47AD"/> - <path - android:pathData="M242.2,173.8l14.1,-1l-1.9,7.7L242.2,173.8z" - android:fillColor="#0E4FC3"/> - <path - android:pathData="M242.2,173.8L231,183.9l14.4,7.1L242.2,173.8z" - android:fillColor="#174DCA"/> - <path - android:pathData="M217.3,174.6l24.9,-0.8L231,183.9L217.3,174.6z" - android:fillColor="#1650D4"/> - <path - android:pathData="M254.6,180.6l6.8,13.3l2.9,-9.2L254.6,180.6z" - android:fillColor="#1246B2"/> - <path - android:pathData="M261.4,193.7l2.9,-9.2l7.2,17L261.4,193.7z" - android:fillColor="#133EA1"/> - <path - android:pathData="M264.4,184.4l10.9,8l-3.7,8.9L264.4,184.4z" - android:fillColor="#103D98"/> - <path - android:pathData="M267,179.8l2.2,-1.1l6.1,13.6L267,179.8z" - android:fillColor="#0B3785"/> - <path - android:pathData="M275.2,192.3l2.5,2.4l-8.4,-16L275.2,192.3z" - android:fillColor="#0B3685"/> - <path - android:pathData="M275.2,192.3l-8.1,-12.7l-2.7,4.7L275.2,192.3zM259.5,168.5l7.7,11.3l2.2,-1.1L259.5,168.5z" - android:fillColor="#0C3B91"/> - <path - android:pathData="M280.1,212.2l-2.5,-17.6l2.8,9.8L280.1,212.2L280.1,212.2z" - android:fillColor="#0B3279"/> - <path - android:pathData="M275.2,192.3l4.8,19.7l-2.5,-17.6L275.2,192.3z" - android:fillColor="#0F388D"/> - <path - android:pathData="M271.5,201.4l8.5,10.8l-4.8,-19.7L271.5,201.4z" - android:fillColor="#0D3481"/> - <path - android:pathData="M280,212.2l0.6,-7.8l0.6,19.6L280,212.2L280,212.2z" - android:fillColor="#0B2E71"/> - <path - android:pathData="M278.6,227.8l2.7,-3.5l-1.2,-12.1L278.6,227.8z" - android:fillColor="#0E2F77"/> - <path - android:pathData="M279.1,236.7l-2.1,1l4.1,-13.5L279.1,236.7z" - android:fillColor="#0E2969"/> - <path - android:pathData="M277.1,237.8l4.1,-13.5l-2.7,3.5L277.1,237.8z" - android:fillColor="#0C2A69"/> - <path - android:pathData="M278.6,227.8l1.5,-15.5l-4.4,5.2L278.6,227.8z" - android:fillColor="#123180"/> - <path - android:pathData="M277.1,237.8l1.6,-10l-8.4,14.2L277.1,237.8z" - android:fillColor="#112B70"/> - <path - android:pathData="M271.5,201.4l8.5,10.8l-4.4,5.2L271.5,201.4z" - android:fillColor="#12378C"/> - <path - android:pathData="M278.6,227.8l-2.9,-10.4l-4.4,12.9L278.6,227.8z" - android:fillColor="#122E7B"/> - <path - android:pathData="M269.7,255.2l7.4,-17.5l-6.9,12.8L269.7,255.2z" - android:fillColor="#11296C"/> - <path - android:pathData="M270.2,250.5l6.9,-12.8l-7,4.2L270.2,250.5z" - android:fillColor="#142A72"/> - <path - android:pathData="M277.1,237.8l-7.4,17.5l9.4,-18.5L277.1,237.8zM263,263.1l6.7,-8l0.5,-4.7L263,263.1zM254.5,270.5l8.5,-7.4l-9,4.1L254.5,270.5z" - android:fillColor="#112768"/> - <path - android:pathData="M204.4,275.5l-8.6,2.2l0.3,-6.1L204.4,275.5z" - android:fillColor="#1C226A"/> - <path - android:pathData="M156.2,193.1l2.5,-0.9l-6.1,13.6L156.2,193.1z" - android:fillColor="#182B7A"/> - <path - android:pathData="M152.6,206l4.5,-0.9l1.5,-12.9L152.6,206z" - android:fillColor="#1F308D"/> - <path - android:pathData="M152.9,222.5l-0.3,-16.5l4.5,-0.9L152.9,222.5z" - android:fillColor="#1E2B7F"/> - <path - android:pathData="M254.6,180.6l-9.1,10.5l16,2.7L254.6,180.6zM174.4,169.8l11.8,-8l-10.5,5.2L174.4,169.8z" - android:fillColor="#1346B5"/> - <path - android:pathData="M175.7,166.8l16.1,-9.4l-5.6,4.2L175.7,166.8" - android:fillColor="#1244AC"/> - <path - android:pathData="M186.2,161.7l14.7,-7.1l-9,2.7L186.2,161.7z" - android:fillColor="#0E4AB6"/> - <path - android:pathData="M242.2,173.8l3.1,17.3l9.1,-10.5L242.2,173.8zM195,160.8l13.6,-5.5l-8,-0.7L195,160.8z" - android:fillColor="#0E4BBA"/> - <path - android:pathData="M211.9,152.7l-11.1,2.1l8,0.7L211.9,152.7z" - android:fillColor="#0A4EBC"/> - <path - android:pathData="M222.5,155.2l-13.6,0.1l3.1,-2.7" - android:fillColor="#0C54CC"/> - <path - android:pathData="M248.3,161.7l-8,0.9l16.1,10.3L248.3,161.7zM222.5,155.2l17.9,2.4l-10.7,-3.8L222.5,155.2z" - android:fillColor="#0B4BB4"/> - <path - android:pathData="M248.3,161.7l-8,-4.1l8.9,3.4L248.3,161.7z" - android:fillColor="#0C3889"/> - <path - android:pathData="M155.3,238.8l5.3,4.3l-7.9,-20.6L155.3,238.8zM228.2,279.7l4.6,-10.9l-16.9,4.5L228.2,279.7zM232.8,268.8l14,3.9l0.9,-10.9L232.8,268.8z" - android:fillColor="#202575"/> - <path - android:pathData="M254,267.2l-6.2,-5.4l15,-10L254,267.2z" - android:fillColor="#1B2773"/> - <path - android:pathData="M262.7,251.8l-8.7,15.4l9,-4.1l7.2,-12.7L262.7,251.8z" - android:fillColor="#15276D"/> - <path - android:pathData="M249.2,161.1l-0.9,0.7l11.2,6.7L249.2,161.1zM240.2,162.6l8,-0.9l-8,-4.1V162.6z" - android:fillColor="#0C409D"/> - <path - android:pathData="M211.9,152.7l10.5,2.7l7.2,-1.5L211.9,152.7zM240.2,157.6l-17.9,-2.4l18,7.4L240.2,157.6z" - android:fillColor="#0B4CB7"/> - <path - android:pathData="M222.5,155.2l4.3,7.5l13.4,-0.1L222.5,155.2z" - android:fillColor="#0B55CE"/> - <path - android:pathData="M222.5,155.2l4.3,7.5l-14.5,-1.2L222.5,155.2z" - android:fillColor="#0A52C5"/> - <path - android:pathData="M208.7,155.3l3.4,6.2l10.2,-6.3L208.7,155.3z" - android:fillColor="#0951C4"/> - <path - android:pathData="M195,160.8l13.6,-5.5l3.4,6.2L195,160.8z" - android:fillColor="#0B50C4"/> - <path - android:pathData="M186.2,161.7l8.9,-0.8l5.8,-6.2L186.2,161.7zM195,160.8l9.2,8.4l8,-7.9L195,160.8z" - android:fillColor="#0F4DBF"/> - <path - android:pathData="M195,160.8L179.9,175l6.2,-13.4L195,160.8z" - android:fillColor="#1546B6"/> - <path - android:pathData="M179.9,175.1l9.6,1.7l5.5,-15.8L179.9,175.1z" - android:fillColor="#1549BD"/> - <path - android:pathData="M189.5,176.6l5.5,-15.8l9.2,8.4L189.5,176.6z" - android:fillColor="#144BC3"/> - <path - android:pathData="M165.4,178.1l0.6,5.7l8.1,-14L165.4,178.1z" - android:fillColor="#173794"/> - <path - android:pathData="M158.7,192.2l6.9,-14.1l0.6,5.7L158.7,192.2z" - android:fillColor="#192F84"/> - <path - android:pathData="M166.1,183.8l8.1,-14l5.6,5.3L166.1,183.8z" - android:fillColor="#1A389B"/> - <path - android:pathData="M165.5,196.1l0.5,-12.3l-7.6,8.4L165.5,196.1z" - android:fillColor="#1D3089"/> - <path - android:pathData="M165.5,196.1l0.5,-12.3l9.7,8L165.5,196.1z" - android:fillColor="#1E389F"/> - <path - android:pathData="M175.8,191.7l4,-16.7l-13.7,8.7L175.8,191.7z" - android:fillColor="#1C40AF"/> - <path - android:pathData="M175.8,191.7l4,-16.7l9.6,1.7L175.8,191.7z" - android:fillColor="#1E41B7"/> - <path - android:pathData="M157.2,205.2l1.5,-12.9l7,3.7L157.2,205.2z" - android:fillColor="#192C7D"/> - <path - android:pathData="M228.2,279.7l13.1,-2.1l5.8,-5L228.2,279.7zM151.9,225.4l1,-2.9l-0.3,-16.5L151.9,225.4zM157.2,205.2l-4.3,17.4l7.9,20.6l-3.8,-24L157.2,205.2z" - android:fillColor="#162467"/> - <path - android:pathData="M160.6,243.1l6.5,0.9l-4.5,-10.5L160.6,243.1z" - android:fillColor="#1A236A"/> - <path - android:pathData="M254,267.2l-7.1,5.5l-5.8,5l13.3,-7.4L254,267.2zM216.2,281.7l10.1,0.3l14.9,-4.2l-13.1,2.1L216.2,281.7zM166.6,255.1l6.8,1.3L167,244L166.6,255.1z" - android:fillColor="#132668"/> - <path - android:pathData="M196.1,271.7l-11.5,-8.7l-4.7,4.5l15.9,10.3L196.1,271.7zM155.3,238.8l7.8,15.1l-2.5,-10.8L155.3,238.8zM151.9,225.4l3.4,13.3l-2.6,-16.3L151.9,225.4zM215.9,273.3l-19.8,-1.9l8.3,3.9l-8.6,2.2l-10.4,-3.2l11.6,5l19.2,2.3l12.1,-2L215.9,273.3zM167.1,244l-6.5,-0.9l6,12L167.1,244zM156.9,219.1l3.8,24l2,-9.6L156.9,219.1zM173.4,256.3l-6.8,-1.3l-3.5,-1.2l5.4,7.4l7.6,6.9l9.3,6.4l-5.5,-7.1L173.4,256.3z" - android:fillColor="#1B2268"/> - <path - android:pathData="M157.2,205.2l9,14l-0.7,-23.2L157.2,205.2z" - android:fillColor="#212A81"/> - <path - android:pathData="M156.9,219.2l5.7,14.2l3.6,-14.2H156.9z" - android:fillColor="#21267A"/> - <path - android:pathData="M162.6,233.5l3.6,-14.2l4.5,11.3L162.6,233.5z" - android:fillColor="#262781"/> - <path - android:pathData="M167.1,244l17.5,10.8l-13.7,-24.2L167.1,244z" - android:fillColor="#272379"/> - <path - android:pathData="M163.1,253.9l3.5,1.2l-6,-12L163.1,253.9zM201.6,260.1l-5.5,11.5l19.8,1.9L201.6,260.1zM167.1,244l6.4,12.4l6.4,11l4.7,-4.5l-0.1,-8L167.1,244z" - android:fillColor="#1E226D"/> - <path - android:pathData="M247.8,261.7l-0.9,10.9l7.1,-5.5L247.8,261.7zM217.4,260.3l-1.5,13.2l16.9,-4.5l-0.6,-14.7L217.4,260.3z" - android:fillColor="#222475"/> - <path - android:pathData="M156.9,219.2h9.3l-9,-14L156.9,219.2zM232.2,254.1l0.6,14.7l14.9,-7.1L232.2,254.1z" - android:fillColor="#23277D"/> - <path - android:pathData="M232.2,254.1l9.6,-8.7l6,16.5L232.2,254.1z" - android:fillColor="#1E2776"/> - <path - android:pathData="M247.8,261.7l7.4,-22.1l-13.3,5.6L247.8,261.7z" - android:fillColor="#222B86"/> - <path - android:pathData="M262.7,251.8l-14.9,9.9l7.4,-22.1L262.7,251.8z" - android:fillColor="#192974"/> - <path - android:pathData="M270.2,241.9l-15,-2.3l7.8,12.1l7.5,-1.5L270.2,241.9z" - android:fillColor="#172A75"/> - <path - android:pathData="M271.2,230l-16.1,9.6l15,2.3l8.4,-14.2L271.2,230z" - android:fillColor="#172D7D"/> - <path - android:pathData="M158.7,192.2l6.9,-14.1l-9.2,15L158.7,192.2zM265.2,209.9l6,20.2l4.4,-12.9L265.2,209.9z" - android:fillColor="#18338A"/> - <path - android:pathData="M275.7,217.4l-4.1,-16l-6.4,8.4L275.7,217.4z" - android:fillColor="#153791"/> - <path - android:pathData="M255.1,239.8l16.1,-9.6l-15.6,-7L255.1,239.8z" - android:fillColor="#1B318B"/> - <path - android:pathData="M255.1,239.8L240.5,225l1.4,20.3L255.1,239.8z" - android:fillColor="#242D8D"/> - <path - android:pathData="M232.2,254.1l-11.2,-9.9l20.8,1.2L232.2,254.1z" - android:fillColor="#2A2B8F"/> - <path - android:pathData="M167.1,244l3.6,-13.4l-8.1,2.9L167.1,244zM221,244.2l-3.6,16.1l14.8,-6.2L221,244.2z" - android:fillColor="#27267F"/> - <path - android:pathData="M197.7,247.4l-10.8,-5.5l-2.6,12.9l17,5.3l15.8,0.2L197.7,247.4z" - android:fillColor="#2D2381"/> - <path - android:pathData="M217.4,260.3l3.6,-16.1l-23.3,3.2L217.4,260.3z" - android:fillColor="#2F2485"/> - <path - android:pathData="M166.2,219.1l4.6,-14.8l-5.3,-8.2L166.2,219.1z" - android:fillColor="#233196"/> - <path - android:pathData="M175.8,191.7l20.4,-6l-10.8,22.1L175.8,191.7z" - android:fillColor="#293CB7"/> - <path - android:pathData="M255.1,239.8L240.5,225l15.1,-1.9L255.1,239.8z" - android:fillColor="#25339C"/> - <path - android:pathData="M271.2,230l-6,-20.2l-9.6,13.3L271.2,230z" - android:fillColor="#19348F"/> - <path - android:pathData="M241.8,245.3l-16.7,-16.2l15.3,-4.2L241.8,245.3z" - android:fillColor="#2A309A"/> - <path - android:pathData="M221,244.2l20.8,1.2l-16.7,-16.2L221,244.2z" - android:fillColor="#302B96"/> - <path - android:pathData="M221,244.2l-11.4,-9.2l15.6,-5.7L221,244.2z" - android:fillColor="#3630A7"/> - <path - android:pathData="M174.4,169.8l1.3,-2.7l-10,11.3L174.4,169.8zM261.4,193.7l3.7,16.2l6.4,-8.4L261.4,193.7z" - android:fillColor="#173DA2"/> - <path - android:pathData="M175.8,191.7l9.6,16.1l-14.5,-3.4L175.8,191.7z" - android:fillColor="#2A36A8"/> - <path - android:pathData="M170.8,204.3l14.5,3.4l-9.8,15.5L170.8,204.3z" - android:fillColor="#312E9F"/> - <path - android:pathData="M196.3,185.8l8,-16.4l-14.7,7.4L196.3,185.8z" - android:fillColor="#184DCD"/> - <path - android:pathData="M166.2,219.1l9.3,4.1l-4.8,7.2L166.2,219.1z" - android:fillColor="#272986"/> - <path - android:pathData="M175.7,223.4l-4.8,7.2l13.6,24.2l2.6,-12.9L175.7,223.4z" - android:fillColor="#2C2584"/> - <path - android:pathData="M186.9,241.9l1.6,-22.6l-13,3.9L186.9,241.9z" - android:fillColor="#32268B"/> - <path - android:pathData="M186.9,241.9l22.6,-7.2l-21,-15.4L186.9,241.9z" - android:fillColor="#372999"/> - <path - android:pathData="M209.5,234.8l-2.3,-17.5l-18.8,2.1L209.5,234.8z" - android:fillColor="#392DA5"/> - <path - android:pathData="M207.4,217.5l15.9,-6l1.9,17.8L207.4,217.5z" - android:fillColor="#3338BC"/> - <path - android:pathData="M197.7,247.4l23.3,-3.2l-11.4,-9.2L197.7,247.4z" - android:fillColor="#362896"/> - <path - android:pathData="M197.7,247.4l-10.8,-5.5l22.6,-7.2L197.7,247.4z" - android:fillColor="#35268F"/> - <path - android:pathData="M196.3,185.8l13.7,1.5l-5.8,-17.9L196.3,185.8z" - android:fillColor="#2648D3"/> - <path - android:pathData="M217.3,174.6l-13,-5.2l5.8,17.9L217.3,174.6z" - android:fillColor="#1057DC"/> - <path - android:pathData="M217.3,174.6l13.6,9.4l-20.8,3.2L217.3,174.6z" - android:fillColor="#1653DA"/> - <path - android:pathData="M210.1,187.1l20.4,10.9l-7.3,13.4L210.1,187.1z" - android:fillColor="#2B46D5"/> - <path - android:pathData="M230.5,198l0.4,-14l-20.8,3.2L230.5,198z" - android:fillColor="#244AD7"/> - <path - android:pathData="M230.5,198l0.4,-14l14.4,7.1L230.5,198z" - android:fillColor="#2547CF"/> - <path - android:pathData="M210.1,187.1l13.3,24.2l-23.2,-11.6L210.1,187.1z" - android:fillColor="#333CC5"/> - <path - android:pathData="M207.4,217.5l15.9,-6l-23.2,-11.6L207.4,217.5z" - android:fillColor="#3833B6"/> - <path - android:pathData="M223.4,211.5l20.4,-3.7l-13.3,-9.6L223.4,211.5z" - android:fillColor="#2A41C6"/> - <path - android:pathData="M245.3,191.1l-1.7,16.7l-13.3,-9.6L245.3,191.1z" - android:fillColor="#2045C1"/> - <path - android:pathData="M245.3,191.1l9.6,13.2l-11.3,3.5L245.3,191.1z" - android:fillColor="#1B43B7"/> - <path - android:pathData="M261.4,193.7l-16,-2.7l9.6,13.2L261.4,193.7z" - android:fillColor="#1742AF"/> - <path - android:pathData="M180,175.1l6.2,-13.4l-11.8,8L180,175.1zM261.4,193.7l-6.4,10.4l10.1,5.7L261.4,193.7z" - android:fillColor="#1740A9"/> - <path - android:pathData="M255.7,223.2l9.6,-13.3l-10.1,-5.7L255.7,223.2z" - android:fillColor="#1B3CA4"/> - <path - android:pathData="M255.7,223.2l-0.6,-18.9l-11.3,3.5L255.7,223.2z" - android:fillColor="#1F3DAD"/> - <path - android:pathData="M175.8,191.7l20.4,-6l-6.8,-9L175.8,191.7zM223.4,211.5l17.2,13.5l3.2,-17.3L223.4,211.5z" - android:fillColor="#2543C3"/> - <path - android:pathData="M225.1,229.1l15.3,-4.2l-17.2,-13.5L225.1,229.1z" - android:fillColor="#2E37B2"/> - <path - android:pathData="M196.3,185.8l3.8,14l9.9,-12.7L196.3,185.8z" - android:fillColor="#2D40C7"/> - <path - android:pathData="M196.3,185.8l-10.8,22.1l14.6,-8L196.3,185.8z" - android:fillColor="#3537B8"/> - <path - android:pathData="M200.2,199.9l-11.7,19.5l18.8,-2.1L200.2,199.9z" - android:fillColor="#3931B0"/> - <path - android:pathData="M207.4,217.5l2.3,17.5l15.6,-5.7L207.4,217.5zM188.5,219.3l11.7,-19.5l-14.6,8L188.5,219.3z" - android:fillColor="#3735B8"/> - <path - android:pathData="M175.7,223.4l9.8,-15.5l3,11.6L175.7,223.4z" - android:fillColor="#342892"/> - <path - android:pathData="M185.4,274.4l10.4,3.2l-15.9,-10.3L185.4,274.4zM184.6,262.7l11.5,8.7l5.5,-11.5l-17,-5.3V262.7zM215.9,273.3l1.5,-13.2l-15.8,-0.2L215.9,273.3zM232.8,268.8l-4.6,10.9l18.7,-7.1L232.8,268.8z" - android:fillColor="#232372"/> - <path - android:pathData="M166.2,219.1l4.6,-14.8l4.7,18.9L166.2,219.1z" - android:fillColor="#2A2F96"/> - <path - android:pathData="M170.8,204.3l4.9,-12.7l-10.2,4.3L170.8,204.3zM243.7,207.7l-3.2,17.3l15.1,-1.9L243.7,207.7z" - android:fillColor="#2636A5"/> - <path - android:pathData="M281.5,224.1L281.5,224.1l-0.6,-19.7l0,0l-2.9,-9.8l0,0l-8.4,-16l-9.7,-10.3l0,0l-10.3,-7.4l0,0l-8.9,-3.4h-0.1l-10.7,-3.8h-0.1l-17.7,-1.2h-0.1l-11.1,2.1l0,0l-9,2.7h-0.1l-16.1,9.3l-10,11.2l-9.2,15l0,0l-3.6,12.9l0,0l-0.7,19.4v0.1l3.4,13.3l0,0l7.8,15.1l0,0l5.3,7.6l0,0l7.6,6.9l0,0l9.3,6.4l0,0l11.6,5h0.1l19.2,2.3l0,0l10.1,0.3h0.1l14.9,-4.2h0.1l13.3,-7.4l0,0l0,0l8.5,-7.4l6.7,-8l0,0l9.4,-18.5v0l2.1,-12.7l0,0V224.1zM176.1,267.8l-2,-1.8l4.3,3.3L176.1,267.8zM204.4,275.2l-6.9,-3.1l16.1,1.5L204.4,275.2zM207,217.2l-18,2l11,-18.6L207,217.2zM200.7,200.5l21.9,11l-15,5.6L200.7,200.5zM207.2,217.8l2.2,16.5l-19.9,-14.6L207.2,217.8zM208.9,234.7l-21.6,6.9l1.5,-21.6L208.9,234.7zM207.8,218.1l16.8,11.1l-14.6,5.3L207.8,218.1zM207.9,217.6l15,-5.6l1.8,16.8L207.9,217.6zM231.1,198.1l13.9,-6.6l-1.6,15.6L231.1,198.1zM243,207.7l-19.1,3.4l6.9,-12.6L243,207.7zM223.3,210.9l-12.5,-23l19.3,10.2L223.3,210.9zM222.6,210.8l-22,-11l9.4,-12.1L222.6,210.8zM188.6,218.6l-2.7,-10.7l13.4,-7.4L188.6,218.6zM186.7,241L176,223.5l12.2,-3.6L186.7,241zM208.5,235.4l-10.9,11.7l-9.9,-5.1L208.5,235.4zM224.6,229.6l-3.8,13.9l-10.7,-8.6L224.6,229.6zM223.7,212.2l16.2,12.8l-14.4,3.9L223.7,212.2zM223.9,211.7l19.3,-3.5l-3,16.4L223.9,211.7zM244.1,207.4l1.6,-15.5l8.9,12.2L244.1,207.4zM254.8,204.5l0.5,17.8l-11.1,-14.3L254.8,204.5zM230.8,197.5l0.4,-13.3l13.4,6.7L230.8,197.5zM230.2,197.5L211,187.3l19.6,-3L230.2,197.5zM200.3,199.2l-3.5,-13.2l13,1.4L200.3,199.2zM199.8,199.7l-13.6,7.5l10,-20.5L199.8,199.7zM188.1,219.1l-11.9,3.5l9,-14.2L188.1,219.1zM186.1,240.9l-14.8,-10.5l4.4,-6.6L186.1,240.9zM187.1,242.4l9.9,5.1l-12.3,6.8L187.1,242.4zM209.5,235.2l10.7,8.6l-21.7,3L209.5,235.2zM225.2,229.7L241,245l-19.6,-1.2L225.2,229.7zM225.7,229.3l14.4,-3.9l1.4,19.2L225.7,229.3zM243.9,208.4l11.2,14.5l-14.1,1.8L243.9,208.4zM255.4,204.6l9.4,5.3l-8.9,12.4L255.4,204.6zM255.5,204l5.9,-9.5l3.4,14.8L255.5,204zM255,203.6l-8.9,-12.2l14.8,2.5L255,203.6zM231.4,183.9l10.5,-9.5l2.9,16.2L231.4,183.9zM210.6,186.8l6.7,-11.9l12.9,8.7L210.6,186.8zM196.8,185.6l7.6,-15.4l5.4,16.8L196.8,185.6zM185.5,207.3l-9.1,-15.3l19.4,-5.7L185.5,207.3zM175.8,222.7l-4.4,-17.9L185,208L175.8,222.7zM170.7,229.8l-4,-10.1l8.3,3.6L170.7,229.8zM186.7,242.1l-2.4,11.9l-12.8,-22.5L186.7,242.1zM197.5,247.9l3.4,11.8l-15.8,-4.9L197.5,247.9zM220.6,244.6l-3.4,15.2l-18.7,-12.2L220.6,244.6zM241.1,245.5l-8.9,8l-10.4,-9.1L241.1,245.5zM240.7,225.7l13.6,13.8l-12.5,5.3L240.7,225.7zM241,225.2l14.1,-1.8l-0.5,15.6L241,225.2zM265.1,210.5l5.7,19L256,223L265.1,210.5zM261.7,194.4l9.2,7.1l-5.8,7.9L261.7,194.4zM245.9,190.9l8.5,-9.8l6.4,12.3L245.9,190.9zM245.5,190.5l-2.9,-16l11.6,6.3L245.5,190.5zM230.9,183.6l-12.9,-8.7l23.3,-0.7L230.9,183.6zM210.1,186.5l-5.4,-16.7l12.1,4.8L210.1,186.5zM196.3,185.3l-6.2,-8.3l13.6,-6.8L196.3,185.3zM195.8,185.7l-19,5.6l12.9,-13.9L195.8,185.7zM184.9,207.5l-13.5,-3.1l4.6,-11.8L184.9,207.5zM175.3,222.9l-8.5,-3.7l4.2,-13.5L175.3,222.9zM170.5,230.3L163,233l3.2,-13L170.5,230.3zM183.7,254l-16.3,-10l3.4,-12.7L183.7,254zM200.2,260.1l-15.3,2.5l-0.1,-7.3L200.2,260.1zM198.2,248.2l18.2,11.9l-14.6,-0.2L198.2,248.2zM221.1,244.8l10.5,9.2l-13.8,5.8L221.1,244.8zM241.7,245.8l5.6,15.3l-14.5,-7.3L241.7,245.8zM242.2,245.5l12.4,-5.2l-6.9,20.6L242.2,245.5zM255.9,223.7l14.7,6.6l-15.1,9L255.9,223.7zM265.7,210.6l9.6,6.9l-4.1,11.8L265.7,210.6zM265.6,209.8l5.8,-7.9l3.8,14.6L265.6,209.8zM261.6,193.6l2.7,-8.2l6.4,15.2L261.6,193.6zM261.3,192.9l-6.2,-11.9l8.7,3.5L261.3,192.9zM243.2,174.1l12.9,-0.9l-1.7,6.9L243.2,174.1zM217.9,174.3l9,-11.2l14.4,10.5L217.9,174.3zM217.4,174.1l-4.6,-12.2l13.5,1.1L217.4,174.1zM216.7,174.1l-11.9,-4.8l7.3,-7.3L216.7,174.1zM190.1,176l5.1,-14.7l8.6,8L190.1,176zM176.3,190.8l3.7,-15.3l8.8,1.5L176.3,190.8zM170.8,203.7l-4.8,-7.6l9.2,-3.9L170.8,203.7zM170.6,204.4l-4,13.1l-0.6,-20.3L170.6,204.4zM165.8,219.5l-3.3,13.1l-5.2,-13.1H165.8zM157.2,218.9l0.3,-12.9l8.2,12.9H157.2zM170.5,231l-3.3,12.2l-4,-9.4L170.5,231zM183.7,254.7l-10,1.5l-5.8,-11.3L183.7,254.7zM184.2,255.2l0.1,7.2l-9.9,-5.7L184.2,255.2zM201.1,260.6l-5.1,10.7l-10.6,-8.1L201.1,260.6zM201.7,260.7l13.4,12.5l-18.7,-1.7L201.7,260.7zM202.4,260.5l14.7,0.2l-1.4,12.3L202.4,260.5zM231.9,254.6l0.6,13.7l-14.4,-8L231.9,254.6zM232.5,254.7l14.5,7.3l-14,6.6L232.5,254.7zM255.2,240.4l7.3,11.4l-14,9.3L255.2,240.4zM255.7,240.1l13.9,2.1l-6.9,9L255.7,240.1zM255.9,239.7l14.9,-8.9l-1,11L255.9,239.7zM275.7,218.4l2.7,9.2l-6.7,2.2L275.7,218.4zM272.1,202.5l7.6,9.5l-3.8,4.6L272.1,202.5zM265.1,185.3l9.8,7.3l-3.3,8L265.1,185.3zM255,180.4l1.6,-6.8l7.1,10.2L255,180.4zM242.4,173.5l-1.8,-10.3l14.7,9.4L242.4,173.5zM241.7,173.2l-14,-10.2l12.4,-0.1L241.7,173.2zM213.2,161.3l9.1,-5.6l3.9,6.7L213.2,161.3zM204.3,169l-8.4,-7.9l15.7,0.6L204.3,169zM189.3,176.3l-8.8,-1.5l13.8,-13.1L189.3,176.3zM175.7,191.3l-9,-7.4l12.9,-8.1L175.7,191.3zM175.3,191.7l-9.3,3.9l0.5,-11.2L175.3,191.7zM165.8,218.3l-8.3,-13.1l7.9,-8.3L165.8,218.3zM162.3,233.6l-1.6,8l-3.1,-19.7L162.3,233.6zM162.7,234.5l3.9,9.1l-5.6,-0.8L162.7,234.5zM172.9,255.9l-5.9,-1.2l0.4,-9.7L172.9,255.9zM184.1,262.8l-4.2,4l-5.7,-9.7L184.1,262.8zM184.6,263.1l10.1,7.9l-14.3,-3.7L184.6,263.1zM217.6,260.8l14.4,8l-15.8,4.2L217.6,260.8zM247.4,262.3l-0.8,10l-13.1,-3.6L247.4,262.3zM261.8,252.8l-8,14l-5.7,-5L261.8,252.8zM269.8,242.9v7.4l-6.5,1.3L269.8,242.9zM271.5,230.3l6.6,-2.2l-7.5,12.6L271.5,230.3zM276,217.5l3.6,-4.3l-1.2,13.2L276,217.5zM271.9,201.4l3.2,-8l4.3,17.7L271.9,201.4zM264.7,184.4l2.4,-4l7.1,11L264.7,184.4zM264.3,183.9l-7,-9.9l9.2,5.9L264.3,183.9zM241.1,162.8l7.1,-0.8l7.1,9.7L241.1,162.8zM226.9,162.4l-3.8,-6.6l15.7,6.5L226.9,162.4zM212.4,161.1l-3,-5.4l12.2,-0.1L212.4,161.1zM211.7,161.2l-15.3,-0.6l12.3,-4.9L211.7,161.2zM180.9,173.9l5.5,-11.9l8,-0.8L180.9,173.9zM179.8,174.6l-5,-4.8l10.6,-7.3L179.8,174.6zM179.5,175.1l-12.5,8l7.5,-12.8L179.5,175.1zM165.3,195.6l-6.3,-3.3l6.7,-7.7L165.3,195.6zM165.1,196.2l-7.7,8.1l1.4,-11.6L165.1,196.2zM156.5,219l-3.1,2.7l3.4,-13.8L156.5,219zM156.6,219.7l3.2,20.5l-6.8,-17.8L156.6,219.7zM166.7,244.3l-0.4,9.6l-5.2,-10.4L166.7,244.3zM173.2,256.6l5.3,9.1l-11,-10.2L173.2,256.6zM195.7,271.8l-0.2,5.3l-13.9,-9L195.7,271.8zM196.3,271.9l7.3,3.3l-7.6,1.9L196.3,271.9zM215.6,273.7l0.2,7.5l-10.5,-5.5L215.6,273.7zM232.3,269.3l-4.2,10l-11.3,-5.9L232.3,269.3zM233,269.2l13.1,3.5l-17.3,6.5L233,269.2zM248,262.4l5.5,4.8l-6.3,4.9L248,262.4zM262.9,252.1l6.4,-1.3l-13.8,14.4L262.9,252.1zM270.5,249.4v-7.2l5.9,-3.5L270.5,249.4zM271,241.1l7.2,-12l-1.4,8.3L271,241.1zM280,215.3l0.9,8.7l-2,2.7L280,215.3zM275.7,193.2l1.7,1.6l1.7,11.8L275.7,193.2zM267.4,179.9l1.6,-0.8l4.4,10L267.4,179.9zM256.7,172.8l2.7,-3.8l6.6,9.7L256.7,172.8zM256.3,172.4l-7.1,-9.6l9.7,5.8L256.3,172.4zM240.5,162.3v-4.2l6.8,3.4L240.5,162.3zM240,162.2l-15.4,-6.4l15.3,2.1L240,162.2zM209.5,155l2.5,-2.2l8,2.1L209.5,155zM196.2,160l4.7,-5.1l6.6,0.6L196.2,160zM194.9,160.5l-7.3,0.7l11.9,-5.7L194.9,160.5zM175.1,169l0.8,-1.9l6.7,-3.2L175.1,169zM166.2,182.9l-0.5,-4.7l7.3,-6.9L166.2,182.9zM165.7,183.7l-6,6.8l5.5,-11.4L165.7,183.7zM156.9,204.9l-3.8,0.7l5,-11.5L156.9,204.9zM156.7,205.6l-3.6,14.7l-0.2,-13.9L156.7,205.6zM160,242.2l-4.3,-3.5l-2.2,-13.4L160,242.2zM166,254.6l-2.7,-0.9l-1.9,-8.2L166,254.6zM177.9,266.1l-9.1,-5l-1.5,-5L177.9,266.1zM179.6,267.5l3.9,5.1l-12.2,-9.5L179.6,267.5zM181.2,268.5l12.8,8.1l-8.2,-2.7L181.2,268.5zM204.3,275.9l9.8,5.1l-17.2,-3.3L204.3,275.9zM216.2,273.8l11,5.8l-10.8,1.8L216.2,273.8zM245.4,273.5l-4.4,3.8l-10.1,1.6L245.4,273.5zM253.8,267.7l0.4,2.5l-5.8,1.8L253.8,267.7zM268.7,252.3l-6,10.6l-7.7,3.4L268.7,252.3zM270.5,250.5l3.9,-7.4l-4.2,10.1L270.5,250.5zM278.8,227.9l1.6,-2.2l-2.5,8L278.8,227.9zM280.3,212.2V212l0.2,-2l0.2,5.1L280.3,212.2zM279.9,209.2l-1.6,-10.9l1.9,6.2L279.9,209.2zM275.5,192.1l-2.7,-6.3l3.8,7.3L275.5,192.1zM267.1,179.4l-5.5,-8l7.1,7.5L267.1,179.4zM248.8,161.7l0.4,-0.3l4.2,2.9L248.8,161.7zM248.3,161.4l-2.8,-1.5l3.1,1.3L248.3,161.4zM224.1,155.1l5.4,-1.1l8,2.8L224.1,155.1zM222.5,154.9l-7.4,-1.9l12.3,0.8L222.5,154.9zM208.5,155l-5.7,-0.5l8,-1.5L208.5,155zM188.5,160.1l3.2,-2.5l5.2,-1.7L188.5,160.1zM186,161.4l-2.7,1.5l4.3,-2.6L186,161.4zM174.1,169.6l-3.3,3.1l3.8,-4.2L174.1,169.6zM158.5,192l-1.5,0.6l5.8,-9.3L158.5,192zM156.4,193.4l1.7,-0.6l-4,9.2L156.4,193.4zM152.5,217.4l0.1,5.1l-0.3,1L152.5,217.4zM152.8,223.8l1.5,9.4l-2.1,-7.8L152.8,223.8zM160.3,243.3l1.9,8.3l-6,-11.8L160.3,243.3zM166.4,255.4l1.4,4.4l-3.8,-5.2L166.4,255.4zM195.6,277.8l0.6,0.9l-5.7,-2.6L195.6,277.8zM197.1,279.1l-0.7,-1.1l12.5,2.5L197.1,279.1zM227.4,280.2l-1.4,1.5l-6.9,-0.2L227.4,280.2zM228.4,280l8,-1.3l-9.3,2.7L228.4,280zM247,272.9l4.7,-1.5l-8.3,4.6L247,272.9zM254.7,269.9l-0.4,-2.5l7,-3.1L254.7,269.9zM269.7,251.7l-0.3,3.2l-4.5,5.5L269.7,251.7zM277.3,238l1.2,-0.6L273,248L277.3,238zM278.8,236.5l-1.4,0.7l2.7,-8.6L278.8,236.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="223.08" - android:centerY="184.89" - android:gradientRadius="77.77" - android:type="radial"> - <item android:offset="0.1" android:color="#6600DDFF"/> - <item android:offset="0.9" android:color="#3F7542E5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M281.5,224.1L281.5,224.1l-0.6,-19.7l0,0l-2.9,-9.8l0,0l-8.4,-16l-9.7,-10.3l0,0l-10.3,-7.4l0,0l-8.9,-3.4h-0.1l-10.7,-3.8h-0.1l-17.7,-1.2h-0.1l-11.1,2.1l0,0l-9,2.7h-0.1l-16.1,9.3l-10,11.2l-9.2,15l0,0l-3.6,12.9l0,0l-0.7,19.4v0.1l3.4,13.3l0,0l7.8,15.1l0,0l5.3,7.6l0,0l7.6,6.9l0,0l9.3,6.4l0,0l11.6,5h0.1l19.2,2.3l0,0l10.1,0.3h0.1l14.9,-4.2h0.1l13.3,-7.4l0,0l0,0l8.5,-7.4l6.7,-8l0,0l9.4,-18.5v0l2.1,-12.7l0,0V224.1zM176.1,267.8l-2,-1.8l4.3,3.3L176.1,267.8zM204.4,275.2l-6.9,-3.1l16.1,1.5L204.4,275.2zM207,217.2l-18,2l11,-18.6L207,217.2zM200.7,200.5l21.9,11l-15,5.6L200.7,200.5zM207.2,217.8l2.2,16.5l-19.9,-14.6L207.2,217.8zM208.9,234.7l-21.6,6.9l1.5,-21.6L208.9,234.7zM207.8,218.1l16.8,11.1l-14.6,5.3L207.8,218.1zM207.9,217.6l15,-5.6l1.8,16.8L207.9,217.6zM231.1,198.1l13.9,-6.6l-1.6,15.6L231.1,198.1zM243,207.7l-19.1,3.4l6.9,-12.6L243,207.7zM223.3,210.9l-12.5,-23l19.3,10.2L223.3,210.9zM222.6,210.8l-22,-11l9.4,-12.1L222.6,210.8zM188.6,218.6l-2.7,-10.7l13.4,-7.4L188.6,218.6zM186.7,241L176,223.5l12.2,-3.6L186.7,241zM208.5,235.4l-10.9,11.7l-9.9,-5.1L208.5,235.4zM224.6,229.6l-3.8,13.9l-10.7,-8.6L224.6,229.6zM223.7,212.2l16.2,12.8l-14.4,3.9L223.7,212.2zM223.9,211.7l19.3,-3.5l-3,16.4L223.9,211.7zM244.1,207.4l1.6,-15.5l8.9,12.2L244.1,207.4zM254.8,204.5l0.5,17.8l-11.1,-14.3L254.8,204.5zM230.8,197.5l0.4,-13.3l13.4,6.7L230.8,197.5zM230.2,197.5L211,187.3l19.6,-3L230.2,197.5zM200.3,199.2l-3.5,-13.2l13,1.4L200.3,199.2zM199.8,199.7l-13.6,7.5l10,-20.5L199.8,199.7zM188.1,219.1l-11.9,3.5l9,-14.2L188.1,219.1zM186.1,240.9l-14.8,-10.5l4.4,-6.6L186.1,240.9zM187.1,242.4l9.9,5.1l-12.3,6.8L187.1,242.4zM209.5,235.2l10.7,8.6l-21.7,3L209.5,235.2zM225.2,229.7L241,245l-19.6,-1.2L225.2,229.7zM225.7,229.3l14.4,-3.9l1.4,19.2L225.7,229.3zM243.9,208.4l11.2,14.5l-14.1,1.8L243.9,208.4zM255.4,204.6l9.4,5.3l-8.9,12.4L255.4,204.6zM255.5,204l5.9,-9.5l3.4,14.8L255.5,204zM255,203.6l-8.9,-12.2l14.8,2.5L255,203.6zM231.4,183.9l10.5,-9.5l2.9,16.2L231.4,183.9zM210.6,186.8l6.7,-11.9l12.9,8.7L210.6,186.8zM196.8,185.6l7.6,-15.4l5.4,16.8L196.8,185.6zM185.5,207.3l-9.1,-15.3l19.4,-5.7L185.5,207.3zM175.8,222.7l-4.4,-17.9L185,208L175.8,222.7zM170.7,229.8l-4,-10.1l8.3,3.6L170.7,229.8zM186.7,242.1l-2.4,11.9l-12.8,-22.5L186.7,242.1zM197.5,247.9l3.4,11.8l-15.8,-4.9L197.5,247.9zM220.6,244.6l-3.4,15.2l-18.7,-12.2L220.6,244.6zM241.1,245.5l-8.9,8l-10.4,-9.1L241.1,245.5zM240.7,225.7l13.6,13.8l-12.5,5.3L240.7,225.7zM241,225.2l14.1,-1.8l-0.5,15.6L241,225.2zM265.1,210.5l5.7,19L256,223L265.1,210.5zM261.7,194.4l9.2,7.1l-5.8,7.9L261.7,194.4zM245.9,190.9l8.5,-9.8l6.4,12.3L245.9,190.9zM245.5,190.5l-2.9,-16l11.6,6.3L245.5,190.5zM230.9,183.6l-12.9,-8.7l23.3,-0.7L230.9,183.6zM210.1,186.5l-5.4,-16.7l12.1,4.8L210.1,186.5zM196.3,185.3l-6.2,-8.3l13.6,-6.8L196.3,185.3zM195.8,185.7l-19,5.6l12.9,-13.9L195.8,185.7zM184.9,207.5l-13.5,-3.1l4.6,-11.8L184.9,207.5zM175.3,222.9l-8.5,-3.7l4.2,-13.5L175.3,222.9zM170.5,230.3L163,233l3.2,-13L170.5,230.3zM183.7,254l-16.3,-10l3.4,-12.7L183.7,254zM200.2,260.1l-15.3,2.5l-0.1,-7.3L200.2,260.1zM198.2,248.2l18.2,11.9l-14.6,-0.2L198.2,248.2zM221.1,244.8l10.5,9.2l-13.8,5.8L221.1,244.8zM241.7,245.8l5.6,15.3l-14.5,-7.3L241.7,245.8zM242.2,245.5l12.4,-5.2l-6.9,20.6L242.2,245.5zM255.9,223.7l14.7,6.6l-15.1,9L255.9,223.7zM265.7,210.6l9.6,6.9l-4.1,11.8L265.7,210.6zM265.6,209.8l5.8,-7.9l3.8,14.6L265.6,209.8zM261.6,193.6l2.7,-8.2l6.4,15.2L261.6,193.6zM261.3,192.9l-6.2,-11.9l8.7,3.5L261.3,192.9zM243.2,174.1l12.9,-0.9l-1.7,6.9L243.2,174.1zM217.9,174.3l9,-11.2l14.4,10.5L217.9,174.3zM217.4,174.1l-4.6,-12.2l13.5,1.1L217.4,174.1zM216.7,174.1l-11.9,-4.8l7.3,-7.3L216.7,174.1zM190.1,176l5.1,-14.7l8.6,8L190.1,176zM176.3,190.8l3.7,-15.3l8.8,1.5L176.3,190.8zM170.8,203.7l-4.8,-7.6l9.2,-3.9L170.8,203.7zM170.6,204.4l-4,13.1l-0.6,-20.3L170.6,204.4zM165.8,219.5l-3.3,13.1l-5.2,-13.1H165.8zM157.2,218.9l0.3,-12.9l8.2,12.9H157.2zM170.5,231l-3.3,12.2l-4,-9.4L170.5,231zM183.7,254.7l-10,1.5l-5.8,-11.3L183.7,254.7zM184.2,255.2l0.1,7.2l-9.9,-5.7L184.2,255.2zM201.1,260.6l-5.1,10.7l-10.6,-8.1L201.1,260.6zM201.7,260.7l13.4,12.5l-18.7,-1.7L201.7,260.7zM202.4,260.5l14.7,0.2l-1.4,12.3L202.4,260.5zM231.9,254.6l0.6,13.7l-14.4,-8L231.9,254.6zM232.5,254.7l14.5,7.3l-14,6.6L232.5,254.7zM255.2,240.4l7.3,11.4l-14,9.3L255.2,240.4zM255.7,240.1l13.9,2.1l-6.9,9L255.7,240.1zM255.9,239.7l14.9,-8.9l-1,11L255.9,239.7zM275.7,218.4l2.7,9.2l-6.7,2.2L275.7,218.4zM272.1,202.5l7.6,9.5l-3.8,4.6L272.1,202.5zM265.1,185.3l9.8,7.3l-3.3,8L265.1,185.3zM255,180.4l1.6,-6.8l7.1,10.2L255,180.4zM242.4,173.5l-1.8,-10.3l14.7,9.4L242.4,173.5zM241.7,173.2l-14,-10.2l12.4,-0.1L241.7,173.2zM213.2,161.3l9.1,-5.6l3.9,6.7L213.2,161.3zM204.3,169l-8.4,-7.9l15.7,0.6L204.3,169zM189.3,176.3l-8.8,-1.5l13.8,-13.1L189.3,176.3zM175.7,191.3l-9,-7.4l12.9,-8.1L175.7,191.3zM175.3,191.7l-9.3,3.9l0.5,-11.2L175.3,191.7zM165.8,218.3l-8.3,-13.1l7.9,-8.3L165.8,218.3zM162.3,233.6l-1.6,8l-3.1,-19.7L162.3,233.6zM162.7,234.5l3.9,9.1l-5.6,-0.8L162.7,234.5zM172.9,255.9l-5.9,-1.2l0.4,-9.7L172.9,255.9zM184.1,262.8l-4.2,4l-5.7,-9.7L184.1,262.8zM184.6,263.1l10.1,7.9l-14.3,-3.7L184.6,263.1zM217.6,260.8l14.4,8l-15.8,4.2L217.6,260.8zM247.4,262.3l-0.8,10l-13.1,-3.6L247.4,262.3zM261.8,252.8l-8,14l-5.7,-5L261.8,252.8zM269.8,242.9v7.4l-6.5,1.3L269.8,242.9zM271.5,230.3l6.6,-2.2l-7.5,12.6L271.5,230.3zM276,217.5l3.6,-4.3l-1.2,13.2L276,217.5zM271.9,201.4l3.2,-8l4.3,17.7L271.9,201.4zM264.7,184.4l2.4,-4l7.1,11L264.7,184.4zM264.3,183.9l-7,-9.9l9.2,5.9L264.3,183.9zM241.1,162.8l7.1,-0.8l7.1,9.7L241.1,162.8zM226.9,162.4l-3.8,-6.6l15.7,6.5L226.9,162.4zM212.4,161.1l-3,-5.4l12.2,-0.1L212.4,161.1zM211.7,161.2l-15.3,-0.6l12.3,-4.9L211.7,161.2zM180.9,173.9l5.5,-11.9l8,-0.8L180.9,173.9zM179.8,174.6l-5,-4.8l10.6,-7.3L179.8,174.6zM179.5,175.1l-12.5,8l7.5,-12.8L179.5,175.1zM165.3,195.6l-6.3,-3.3l6.7,-7.7L165.3,195.6zM165.1,196.2l-7.7,8.1l1.4,-11.6L165.1,196.2zM156.5,219l-3.1,2.7l3.4,-13.8L156.5,219zM156.6,219.7l3.2,20.5l-6.8,-17.8L156.6,219.7zM166.7,244.3l-0.4,9.6l-5.2,-10.4L166.7,244.3zM173.2,256.6l5.3,9.1l-11,-10.2L173.2,256.6zM195.7,271.8l-0.2,5.3l-13.9,-9L195.7,271.8zM196.3,271.9l7.3,3.3l-7.6,1.9L196.3,271.9zM215.6,273.7l0.2,7.5l-10.5,-5.5L215.6,273.7zM232.3,269.3l-4.2,10l-11.3,-5.9L232.3,269.3zM233,269.2l13.1,3.5l-17.3,6.5L233,269.2zM248,262.4l5.5,4.8l-6.3,4.9L248,262.4zM262.9,252.1l6.4,-1.3l-13.8,14.4L262.9,252.1zM270.5,249.4v-7.2l5.9,-3.5L270.5,249.4zM271,241.1l7.2,-12l-1.4,8.3L271,241.1zM280,215.3l0.9,8.7l-2,2.7L280,215.3zM275.7,193.2l1.7,1.6l1.7,11.8L275.7,193.2zM267.4,179.9l1.6,-0.8l4.4,10L267.4,179.9zM256.7,172.8l2.7,-3.8l6.6,9.7L256.7,172.8zM256.3,172.4l-7.1,-9.6l9.7,5.8L256.3,172.4zM240.5,162.3v-4.2l6.8,3.4L240.5,162.3zM240,162.2l-15.4,-6.4l15.3,2.1L240,162.2zM209.5,155l2.5,-2.2l8,2.1L209.5,155zM196.2,160l4.7,-5.1l6.6,0.6L196.2,160zM194.9,160.5l-7.3,0.7l11.9,-5.7L194.9,160.5zM175.1,169l0.8,-1.9l6.7,-3.2L175.1,169zM166.2,182.9l-0.5,-4.7l7.3,-6.9L166.2,182.9zM165.7,183.7l-6,6.8l5.5,-11.4L165.7,183.7zM156.9,204.9l-3.8,0.7l5,-11.5L156.9,204.9zM156.7,205.6l-3.6,14.7l-0.2,-13.9L156.7,205.6zM160,242.2l-4.3,-3.5l-2.2,-13.4L160,242.2zM166,254.6l-2.7,-0.9l-1.9,-8.2L166,254.6zM177.9,266.1l-9.1,-5l-1.5,-5L177.9,266.1zM179.6,267.5l3.9,5.1l-12.2,-9.5L179.6,267.5zM181.2,268.5l12.8,8.1l-8.2,-2.7L181.2,268.5zM204.3,275.9l9.8,5.1l-17.2,-3.3L204.3,275.9zM216.2,273.8l11,5.8l-10.8,1.8L216.2,273.8zM245.4,273.5l-4.4,3.8l-10.1,1.6L245.4,273.5zM253.8,267.7l0.4,2.5l-5.8,1.8L253.8,267.7zM268.7,252.3l-6,10.6l-7.7,3.4L268.7,252.3zM270.5,250.5l3.9,-7.4l-4.2,10.1L270.5,250.5zM278.8,227.9l1.6,-2.2l-2.5,8L278.8,227.9zM280.3,212.2V212l0.2,-2l0.2,5.1L280.3,212.2zM279.9,209.2l-1.6,-10.9l1.9,6.2L279.9,209.2zM275.5,192.1l-2.7,-6.3l3.8,7.3L275.5,192.1zM267.1,179.4l-5.5,-8l7.1,7.5L267.1,179.4zM248.8,161.7l0.4,-0.3l4.2,2.9L248.8,161.7zM248.3,161.4l-2.8,-1.5l3.1,1.3L248.3,161.4zM224.1,155.1l5.4,-1.1l8,2.8L224.1,155.1zM222.5,154.9l-7.4,-1.9l12.3,0.8L222.5,154.9zM208.5,155l-5.7,-0.5l8,-1.5L208.5,155zM188.5,160.1l3.2,-2.5l5.2,-1.7L188.5,160.1zM186,161.4l-2.7,1.5l4.3,-2.6L186,161.4zM174.1,169.6l-3.3,3.1l3.8,-4.2L174.1,169.6zM158.5,192l-1.5,0.6l5.8,-9.3L158.5,192zM156.4,193.4l1.7,-0.6l-4,9.2L156.4,193.4zM152.5,217.4l0.1,5.1l-0.3,1L152.5,217.4zM152.8,223.8l1.5,9.4l-2.1,-7.8L152.8,223.8zM160.3,243.3l1.9,8.3l-6,-11.8L160.3,243.3zM166.4,255.4l1.4,4.4l-3.8,-5.2L166.4,255.4zM195.6,277.8l0.6,0.9l-5.7,-2.6L195.6,277.8zM197.1,279.1l-0.7,-1.1l12.5,2.5L197.1,279.1zM227.4,280.2l-1.4,1.5l-6.9,-0.2L227.4,280.2zM228.4,280l8,-1.3l-9.3,2.7L228.4,280zM247,272.9l4.7,-1.5l-8.3,4.6L247,272.9zM254.7,269.9l-0.4,-2.5l7,-3.1L254.7,269.9zM269.7,251.7l-0.3,3.2l-4.5,5.5L269.7,251.7zM277.3,238l1.2,-0.6L273,248L277.3,238zM278.8,236.5l-1.4,0.7l2.7,-8.6L278.8,236.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="215.6" - android:centerY="220.76" - android:gradientRadius="66.13" - android:type="radial"> - <item android:offset="0.91" android:color="#007542E5"/> - <item android:offset="1" android:color="#6600DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3c0,0 0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-15.2,32.8 -52.2,66.4 -110,64.6c-62.4,-1.8 -117.6,-48.1 -127.8,-108.9c-1.9,-9.5 0,-14.4 1,-22.2c-1.3,6.1 -2.1,12.2 -2.2,18.4v0.7c0.3,73.6 60.2,133.1 133.7,132.8c64.6,-0.2 119.7,-46.7 130.8,-110.2c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,215 347.8,191.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="311.87" - android:centerY="109.01" - android:gradientRadius="340.74" - android:type="radial"> - <item android:offset="0" android:color="#FF80EBFF"/> - <item android:offset="0.26" android:color="#FF00DDFF"/> - <item android:offset="0.53" android:color="#FF0090ED"/> - <item android:offset="0.86" android:color="#FF0060DF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3c0,0 0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-15.2,32.8 -52.2,66.4 -110,64.6c-62.4,-1.8 -117.6,-48.1 -127.8,-108.9c-1.9,-9.5 0,-14.4 1,-22.2c-1.3,6.1 -2.1,12.2 -2.2,18.4v0.7c0.3,73.6 60.2,133.1 133.7,132.8c64.6,-0.2 119.7,-46.7 130.8,-110.2c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,215 347.8,191.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="209.99" - android:centerY="223.55" - android:gradientRadius="340.74" - android:type="radial"> - <item android:offset="0.3" android:color="#CC321C64"/> - <item android:offset="0.37" android:color="#7F212F83"/> - <item android:offset="0.48" android:color="#230A47AC"/> - <item android:offset="0.53" android:color="#000250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M84.2,223.5c10.3,60.7 65.4,107 127.9,108.9c57.8,1.7 94.8,-31.9 110,-64.6c13,-28.3 14.4,-60.5 4.1,-89.8v-0.2c0,-0.1 0,-0.2 0,-0.1v0.2c4.7,30.8 -11,60.7 -35.4,80.9l-0.1,0.2c-47.8,38.9 -93.6,23.5 -102.9,17.2c-0.7,-0.3 -1.3,-0.7 -2,-1c-27.9,-13.3 -39.5,-38.7 -36.9,-60.5c-13.4,0.2 -25.9,-7.7 -31.5,-19.8c14.8,-9.1 33.5,-9.8 49,-2c15.8,7.2 33.8,8 50.1,2c0,-1.1 -23.3,-10.3 -32.3,-19.1c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-0.8,-0.6 -1.7,-1.2 -2.7,-1.9c-9.7,-6.3 -29.1,-6 -29.6,-6h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-1.6,0.6 -3,1.5 -4.4,2.4c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0c-8.5,12.2 -14.6,25.8 -17.9,40.2C86.5,192 81.8,212.8 84.2,223.5L84.2,223.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="308.05" - android:centerY="18.36" - android:gradientRadius="524.13" - android:type="radial"> - <item android:offset="0" android:color="#FF80EBFF"/> - <item android:offset="0.47" android:color="#FF00B3F4"/> - <item android:offset="0.84" android:color="#FF0060DF"/> - <item android:offset="1" android:color="#FF592ACB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M263.1,170.8c4.8,4.7 9,10.2 12.4,16.1c0.7,0.5 1.4,1.1 2.1,1.7c30.1,27.9 14.3,67 13.3,69.9c24.5,-20.2 40.2,-50.1 35.4,-80.9c-15,-37.5 -40.5,-52.6 -61.5,-85.6c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.9,-1.7 -1.6,-3.4 -2.1,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0h-0.1h-0.2C252.3,81.1 221.8,129.5 263.1,170.8L263.1,170.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="277.55" - android:startY="60.69" - android:endX="293.77" - android:endY="283.77" - android:type="linear"> - <item android:offset="0" android:color="#FFAAF2FF"/> - <item android:offset="0.29" android:color="#FF00DDFF"/> - <item android:offset="0.61" android:color="#FF0090ED"/> - <item android:offset="0.89" android:color="#FF0250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M211.9,152.7l17.7,1.2l10.7,3.8l8.9,3.4l10.3,7.4l9.6,10.2l3.3,6.4c0.8,0.5 1.5,1 2.3,1.5c0.3,0.2 0.6,0.4 0.9,0.6c-3.3,-6 -7.6,-11.4 -12.4,-16.1c-41.4,-41.3 -10.9,-89.7 -5.7,-92.2l0.1,-0.1C224.1,98.3 212.9,134.5 211.9,152.7L211.9,152.7L211.9,152.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="233.01" - android:startY="79.68" - android:endX="248.96" - android:endY="213.99" - android:type="linear"> - <item android:offset="0" android:color="#FFAAF2FF"/> - <item android:offset="0.29" android:color="#FF00DDFF"/> - <item android:offset="0.74" android:color="#FF0090ED"/> - <item android:offset="1" android:color="#FF0250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M168.8,162.3c1,0.6 1.9,1.2 2.7,1.9c-3,-10.6 -3.1,-21.9 -0.4,-32.5c-12.3,6 -23.3,14.3 -32.1,24.7C139.7,156.3 159.1,155.9 168.8,162.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="206.55" - android:centerY="97.78" - android:gradientRadius="97.33" - android:type="radial"> - <item android:offset="0" android:color="#FF00DDFF"/> - <item android:offset="0.82" android:color="#FF0090ED"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M156.3,232.3c0,0 6.2,-23 44.1,-23c4.1,0 15.8,-11.4 16,-14.7c-16.3,5.9 -34.3,5.2 -50.1,-2c-15.6,-8 -34.2,-7.2 -49,2c5.7,12.3 18.1,20 31.5,19.8c-2.6,21.8 9,47.1 36.9,60.5c0.6,0.3 1.3,0.6 1.9,0.9C171.3,267.4 158,251.5 156.3,232.3L156.3,232.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="270.8" - android:centerY="147.43" - android:gradientRadius="309.81" - android:type="radial"> - <item android:offset="0.29" android:color="#FF80EBFF"/> - <item android:offset="1" android:color="#FF00B3F4"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M277.4,188.7c-0.7,-0.6 -1.4,-1.2 -2.1,-1.7c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-9.3,-6.5 -20.8,-9.2 -32.1,-7.9c47.9,24 35,106.3 -31.3,103.3c-5.9,-0.2 -11.8,-1.4 -17.4,-3.3c-1.4,-0.5 -2.7,-1.1 -3.9,-1.7c-0.8,-0.4 -1.6,-0.7 -2.3,-1.1l0.1,0.1c9.2,6.3 55.1,21.8 102.9,-17.2l0.1,-0.2C291.9,255.8 307.8,216.5 277.4,188.7L277.4,188.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="203.95" - android:centerY="132.63" - android:gradientRadius="248.83" - android:type="radial"> - <item android:offset="0.18" android:color="#FFAAF2FF"/> - <item android:offset="0.43" android:color="#FF00DDFF"/> - <item android:offset="0.69" android:color="#FF0060DF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3v0.2c-15,-37.5 -40.5,-52.6 -61.5,-85.6c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.9,-1.7 -1.6,-3.4 -2.1,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1l0.1,-0.1c-33.5,19.5 -44.9,55.9 -45.8,74h0.3l17.7,1.2l9.9,3.5l9.7,3.7l10.3,7.4l9.6,10.2c0,0 3.3,6.3 3.3,6.4c-8.9,-5.5 -19.5,-7.9 -29.9,-6.4c47.9,24 35,106.3 -31.3,103.3c-5.9,-0.3 -11.8,-1.4 -17.4,-3.3c-1.3,-0.5 -2.7,-1.1 -3.9,-1.7c-0.8,-0.4 -1.6,-0.7 -2.3,-1.1l0.1,0.1c-0.7,-0.3 -1.3,-0.7 -2,-1c0.6,0.3 1.3,0.6 1.9,0.9c-16.3,-8.3 -29.6,-24.2 -31.4,-43.6c0,0 6.2,-23 44.1,-23c4.1,0 15.8,-11.4 16,-14.7c0,-1.1 -23.3,-10.3 -32.3,-19.1c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-3,-10.6 -3.1,-21.9 -0.4,-32.5c-12.3,6 -23.3,14.3 -32.1,24.7h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-1.6,0.7 -3,1.5 -4.4,2.4c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.6,9.6 -12.5,14.9c-8.5,12.2 -14.6,25.8 -17.9,40.2c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.4,7.2 -1.6,8.3l0,0c-1.1,6.2 -1.7,12.4 -2,18.7v0.7c0.1,73.6 60,133.1 133.5,133c64.8,-0.1 120,-46.7 131,-110.5c0.2,-1.8 0.4,-3.4 0.6,-5.1C350.9,214.9 347.8,191.9 339.5,170.7L339.5,170.7zM326.1,177.6L326.1,177.6L326.1,177.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="311.47" - android:startY="119.54" - android:endX="135.81" - android:endY="309.08" - android:type="linear"> - <item android:offset="0.24" android:color="#7F80EBFF"/> - <item android:offset="0.7" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c0,0 -0.6,0.2 -1.7,0.6c-2.7,4.4 -11.9,12.9 -15.4,12.9c-37.9,-0.2 -44.2,22.5 -44.2,22.5c0.7,7.8 3.2,15.2 7.5,21.8c-3.5,-6.1 -5.7,-13 -6.4,-19.9c0,0 6.2,-23 44.1,-23C204.4,209.4 216.2,197.9 216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="192.31" - android:startY="188.84" - android:endX="167.23" - android:endY="280.42" - android:type="linear"> - <item android:offset="0" android:color="#E5BFF3FF"/> - <item android:offset="1" android:color="#7F80EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M326.2,177.7L326.2,177.7c0,-0.2 0,-0.3 0,-0.2C326.2,177.6 326.2,177.5 326.2,177.7c-0.9,-2.3 -1.9,-4.4 -2.7,-6.7c-0.4,-0.8 -0.7,-1.5 -1.1,-2.2c-0.7,-1.4 -1.4,-2.7 -2.1,-4c-0.4,-0.8 -0.9,-1.6 -1.4,-2.4c-0.7,-1.2 -1.3,-2.4 -2,-3.4c-0.5,-0.8 -1,-1.6 -1.5,-2.5c-0.7,-1.1 -1.3,-2.1 -2,-3c-0.5,-0.8 -1.1,-1.6 -1.7,-2.4c-0.7,-1 -1.4,-2 -2.1,-2.7c-0.6,-0.8 -1.2,-1.6 -1.8,-2.4c-0.7,-0.9 -1.4,-1.9 -2.1,-2.7c-0.6,-0.8 -1.2,-1.5 -1.8,-2.3c-0.7,-0.9 -1.4,-1.8 -2.2,-2.7c-0.6,-0.8 -1.3,-1.5 -1.9,-2.3c-0.4,-0.4 -0.7,-0.8 -1,-1.2l0.4,0.5c-11.6,-13.5 -24.1,-26.1 -35.2,-43.9c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.8,-1.6 -1.4,-3 -1.9,-4.7c0,-0.1 -0.1,-0.2 -0.1,-0.3s-0.1,-0.2 -0.1,-0.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0H257c0,0 -0.1,0 -0.1,0.1c-0.3,0.2 -0.6,0.4 -0.8,0.6c-0.1,0.1 -0.1,0.1 -0.2,0.2c-0.4,0.4 -0.8,0.8 -1.1,1.2l0,0c-8,9.3 -28.4,50.2 4.5,86.8c-30.7,-36.1 -11.4,-75.3 -2.9,-85.5c0.5,1.4 1,2.7 1.7,4c0.5,1 1,1.9 1.5,2.7c1.1,1.8 2.2,3.4 3.1,5.1c20.8,33 46.4,48.1 61.5,85.6c0,-0.1 0,-0.2 0,-0.2s0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-5.3,11.3 -12.5,21.5 -21.2,30.3c9.4,-9.2 17.2,-20 22.8,-32C335.1,239.4 336.4,207.2 326.2,177.7L326.2,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="287.95" - android:startY="74.23" - android:endX="285.22" - android:endY="385.68" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M257.4,78.8L257.4,78.8c-30,17.6 -42.3,48.7 -45.2,67.9c4.8,-25.1 19.2,-47.4 40.2,-62C253.8,82.3 255.5,80.3 257.4,78.8L257.4,78.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="235.68" - android:startY="75.96" - android:endX="233.41" - android:endY="175.93" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#7FAAF2FF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M290.7,258.8l0.1,-0.2c1.2,-2.7 17,-42.1 -13.3,-69.9c-0.7,-0.6 -1.4,-1.2 -2.1,-1.7c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-9,-6.3 -19.9,-9 -30.9,-8l0,0c-0.4,0.1 -0.8,0.1 -1.3,0.2c47.4,23.8 35.3,104.4 -29.2,103.4h0.5c65.4,2.7 78.2,-77.6 32.9,-102.8c8.9,0.1 17.7,2.7 25.2,7.4c0.3,0.2 0.6,0.4 0.9,0.6c0.7,0.5 1.5,1 2.1,1.6c31.2,26.6 17,66.5 15.9,69.4l-0.1,0.2"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="257.29" - android:startY="176.16" - android:endX="252.36" - android:endY="325.64" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M166.7,194c15.3,6.4 32.6,6.9 48.2,1.2c-15.9,5.3 -33.3,4.4 -48.5,-2.6c-15.3,-7.8 -33.6,-7.2 -48.4,1.6l-0.2,0.1l0,0l-0.1,0.1l-0.1,0.1h-0.1l0,0l0,0l0,0l0.1,0.2l0,0l0.1,0.2l0,0l0.1,0.3l0,0c0.3,0.6 0.6,1.2 0.9,1.7c6.1,11 17.9,17.8 30.3,17.6c-2.5,21.1 8.3,45.5 34.6,59.2c-24.9,-14.3 -35.3,-40.4 -32.5,-61.2c-19.2,-0.5 -27.9,-12.1 -30.3,-17C134.9,187.9 152,187.4 166.7,194L166.7,194z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="165.56" - android:startY="185.57" - android:endX="173.37" - android:endY="293.51" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#3380EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M171.4,164.1l-0.7,-0.4L171.4,164.1L171.4,164.1zM171.3,163.6c-2.8,-10.4 -2.9,-21.5 -0.2,-32c-11.8,5.7 -22.3,13.5 -30.8,23.5c8.1,-8.1 17.7,-14.9 28.2,-19.8C167.2,144.6 168.2,154.4 171.3,163.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="176.81" - android:startY="124.11" - android:endX="147.78" - android:endY="173.26" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#3380EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M87.3,237.4l-0.1,-0.4c-1.3,-4.4 -2.4,-8.9 -3,-13.5c-0.9,-5.7 -0.9,-11.5 0,-17.2c-0.7,4.4 -1.1,8.8 -1.3,13.3v0.7c0,56.6 35.8,107.1 89.4,125.7C126.3,328.1 93.6,286.5 87.3,237.4L87.3,237.4z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="129.41" - android:startY="204.87" - android:endX="124.93" - android:endY="397.63" - android:type="linear"> - <item android:offset="0" android:color="#6600DDFF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M86.2,223.9c-2.4,-10.7 2.5,-31.4 2.6,-31.7c3.2,-14.4 9.3,-28.2 17.9,-40.2l0,0l0,0c3.7,-5.3 8,-10.3 12.5,-14.9c4,-4 8.3,-7.9 13.1,-11.2c0.2,-0.1 0.4,-0.2 0.6,-0.4c0,10.1 0.5,27.2 5.2,32.8h0.1c0.7,0 20,-0.9 29.9,5.1c1.1,0.7 2.1,1.3 2.7,1.8c1.3,0.8 2.5,1.7 3.5,2.6c2.2,1.7 4.4,3.8 9.4,8.4c7.3,6.8 23,13.4 29.6,16.6c-6.7,-3.3 -22.2,-10.4 -29.3,-17.4c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-0.8,-0.6 -1.7,-1.2 -2.7,-1.9c-9.7,-6.3 -29.1,-6 -29.6,-6h-0.1c-4.8,-6.1 -4.9,-25 -4.7,-31.8c0,-0.3 0,-0.5 0,-0.7v-0.2c0,-0.1 0,-0.3 0,-0.4c0,0 0,0 -0.1,0h-0.1h-0.1H134h-0.1l-0.1,0.1l-0.1,0.1l-0.1,0.1l-0.2,0.1l-0.1,0.1l-0.2,0.1l-0.1,0.1c-1,0.6 -2.1,1.2 -2.9,1.8c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0C96,163.8 90,177.4 86.7,191.8c-0.1,0.3 -4.8,20.9 -2.6,31.7c8.7,51.6 50,93 100.5,105C135,315.6 95,274.9 86.2,223.9L86.2,223.9z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="148.45" - android:startY="98.32" - android:endX="148.45" - android:endY="326.46" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.1,-12.3 -13.2,-23.2 -23.5,-31.6l-0.2,-0.2c-0.3,-0.2 -0.5,-0.4 -0.8,-0.6c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c-0.3,-0.2 -0.5,-0.3 -0.8,-0.5l-0.3,-0.2c-0.3,-0.2 -0.7,-0.4 -1,-0.6c0.4,0.7 0.7,1.5 1.1,2.2c0.2,0.5 0.4,0.9 0.7,1.4c5.7,11.7 9.6,24.1 11.8,36.9v0.2c4.7,30.8 -11,60.7 -35.4,80.9l-0.1,0.2c-30.4,24.7 -60.2,27.5 -80,24.5c19.8,3.6 51,2.2 83.2,-24l0.1,-0.2c24.5,-20.2 40.2,-50.1 35.4,-80.9v-0.2c-1.9,-11.2 -5.1,-22.1 -9.7,-32.4c5.9,6.2 10.7,13.3 14.5,20.7c9.5,20.3 13.7,42.8 12.4,65.3c-0.1,1.8 -0.2,3.3 -0.3,5.1c-8,63.9 -60.8,112.9 -125,116c-8.7,0.5 -17.7,0.1 -26.3,-1.1c72.1,11.6 140.1,-36.9 152.5,-109c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,214.9 347.8,191.9 339.5,170.7L339.5,170.7zM326.2,177.7L326.2,177.7L326.2,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="276.75" - android:startY="130.61" - android:endX="267.51" - android:endY="444.06" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - </group> - </vector> - </aapt:attr> - <target - android:name="a1_t"> - <aapt:attr - name="android:animation"> - <set> - <objectAnimator - android:propertyName="scaleX" - android:duration="300" - android:valueFrom="0.75" - android:valueTo="0.75" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleX" - android:duration="700" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="300" - android:valueFrom="0.75002400000000002" - android:valueTo="0.75002400000000002" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleY" - android:duration="700" - android:valueFrom="0.75002400000000002" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - </set> - </aapt:attr> - </target> -</animated-vector> diff --git a/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_background.xml b/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..a086a9aae981d8d6cd1f13660b734b14c4f06293 --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_background.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="432" + android:viewportHeight="432"> + <path + android:pathData="M0,0h432v432h-432z" + android:fillColor="#E4E0FA"/> +</vector> diff --git a/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_foreground.xml b/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 844e479ef48a7125aadd9719147feef2166a23b7..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,83 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="108dp" - android:height="108dp" - android:viewportWidth="208" - android:viewportHeight="208"> - <path android:pathData="M163.2,113.7c6.4,-1.2 3.9,-14.4 6.6,-5.2" - android:strokeWidth="1.1" - android:fillColor="#000" - android:strokeColor="#000"/> - <path android:pathData="M171.8,59c2.1,-5.6 5.7,-6.7 8.6,-8.3 -4.7,7.3 -1.4,10.2 -2.5,13 -2.3,5.5 -7.9,0 -6,-4.8z" - android:strokeWidth="1.1" - android:fillColor="#fe9d2a" - android:strokeColor="#000"/> - <path android:pathData="M44.3,75.2c1.8,-4.2 4.8,-5 7.3,-6.1 -4,5.4 -1.2,7.6 -2.2,9.7 -1.9,4.1 -6.6,0 -5,-3.6zM27.3,51.9c4,5.4 3,9.6 4,11.7 1.8,4.1 5.9,0.5 4.3,-3.1a19,19 0,0 0,-8.4 -8.6z" - android:strokeWidth="1.1" - android:fillColor="#f3611e" - android:strokeColor="#000"/> - <path android:pathData="M89.3,91.9l2.8,12.1L23,104l2.5,-19.7a50.9,50.9 0,0 1,18.3 -19c-6.4,7.6 -5.7,21.1 8.6,24.8 9.2,2.4 28.6,-9.8 36.8,1.8zM120.7,92.6c21.9,-9.5 26.4,-1.8 34.8,-4 17.2,-5.3 15.7,-13.6 9.7,-23.4A51,51 0,0 1,183.5 84l2.5,20h-66.6l1.3,-11.4zM89.3,91.9zM159.5,78c0.3,3 5.5,3.2 6.4,0 -0.3,-7 -5.5,-9.2 -10.7,-10.8 2.8,3.6 4.3,5.3 4.3,10.8zM34.1,64.4c-1.8,-4.1 -6.6,-5.2 -9.1,-6.3 4,5.4 3,7.8 4,9.9 1.8,4.1 6.6,0 5,-3.6z" - android:strokeWidth="1.1" - android:fillColor="#f00027" - android:strokeColor="#000"/> - <path android:pathData="M87.3,92.8c-24.6,-8.2 -41,7 -45.9,6.5 -19,-2.3 -19,-16.2 -13.8,-28.6 -4.3,6.5 -9.6,7 -12.3,22.7 -2.3,-2.3 -4.8,-3 -5.8,-11.6 -5.4,16.9 -2,20.8 0.5,26.2 -2.6,-1.6 -5,-3.5 -7.2,-5.5 0.7,7.9 3.5,11.6 5.8,16.3l-5.8,-3.5c9.5,25.9 23.3,35.6 39.6,36.1 16,-1.5 24.2,-4 33.7,-6.3l11.2,-52.3zM123.3,94.8c4,-2.3 10.3,-3.1 15.4,-3 8.7,-0.5 25.2,7.9 29,7.9 9.3,0.1 21.1,-9.6 14,-28.3 4.9,6.5 9.9,10.8 12,22 3.5,-2 4.6,-6.3 6,-10.4 4,9.1 3,17.4 -0.2,25.3 2,-1.1 4,-2.4 6.6,-5.6 0.3,7 -3.6,11 -6,16l5,-2.6c-6,17.8 -15.6,32.7 -36.1,35.6 -13,-2.9 -25.4,-6.9 -41,-6.4l-9.2,-24.4s6.1,-28.4 4.6,-26.1" - android:strokeWidth="1.1" - android:fillColor="#cc002b" - android:strokeColor="#000"/> - <path android:pathData="M163,113.5c2.8,-0.6 4.8,-3.2 5.9,-8.7l1,3.6" - android:strokeWidth="1.1" - android:fillColor="#0000" - android:strokeColor="#000" - android:strokeLineCap="square"/> - <path android:pathData="M177,110a19,19 0,0 0,5.4 -6.8l1,7M154,129.3c5.6,0.8 6.9,-2.7 9.4,-5l-0.5,3.7" - android:strokeLineJoin="bevel" - android:strokeWidth="1.1" - android:fillColor="#0000" - android:strokeColor="#000"/> - <path android:pathData="M44,112.7c-2.7,-0.6 -4.7,-3.2 -5.9,-8.7l-1,3.6" - android:strokeWidth="1.1" - android:fillColor="#0000" - android:strokeColor="#000" - android:strokeLineCap="square"/> - <path android:pathData="M30.1,109.2a19,19 0,0 1,-5.4 -6.8l-1,7M53,128.4c-5.5,0.7 -6.8,-2.7 -9.3,-5l0.5,3.7" - android:strokeLineJoin="bevel" - android:strokeWidth="1.1" - android:fillColor="#0000" - android:strokeColor="#000"/> - <path android:pathData="M24.3 105c0.3 7 1.1 13.8 6.2 18.6a24 24 0 0 1-6.8-2.7c2.2 4.4 4.5 8.8 9 12l-4.7-0.3c2.5 4.5 6.3 8.1 10 11.8-8.3-3.7-17.7-5.7-20.6-18.9 2.3 2.2 3 1.6 4.1 1.9-4-4-5.3-9.3-7-13.8 2 2 4.3 3.5 6.8 4.4-6-6.2-4.5-14.3-4.2-22.2 1.8 3.8 3.9 7.3 7.2 9.2zm10.2 18c3 1.6 4.2 4.3 9.7 4 1 5.4 5 8.4 9.4 11.4-6.1 0.7-14.1-0.1-19-15.4zm5.8-0.8C30.3 119 29 109.4 31 98.9c2 6.6 3.9 7.2 6 8.2-0.7 6-0.5 12 3.3 15z" - android:strokeWidth="1.1" - android:fillColor="#f00027" - android:strokeColor="#000"/> - <path android:pathData="M182.8 105.8c3.3-1.9 5.3-5.4 7.2-9.1 0.3 7.8 1.8 16-4.2 22.1a17 17 0 0 0 6.7-4.3c-1.6 4.4-2.8 9.6-6.9 13.7 1.2-0.3 1.8 0.3 4.2-1.9-3 13.2-12.4 15.3-20.7 19 3.7-3.8 7.5-7.4 10-12-1.8 0.3-3.4 0.4-4.7 0.4 4.5-3.2 6.8-7.6 9-12a24 24 0 0 1-6.8 2.7c5-4.8 6-11.6 6.2-18.6zm-20 22c5.6 0.3 6.8-2.4 9.8-4-5 15.3-13 16-19.1 15.4 4.3-3 8.4-6 9.4-11.3zm4-3.1c10-3.2 11.3-12.8 9.3-23.3-2 6.6-3.9 7.2-6 8.2 0.7 6 0.5 12-3.3 15z" - android:strokeWidth="1.1" - android:fillColor="#f00027" - android:strokeColor="#000"/> - <path android:pathData="M146.8,95.8c0,-3.6 -2.8,-6.5 -6.4,-6.5a6.5,6.5 0,0 0,-6.4 6.5v26.7c0,3.5 3,6.4 6.4,6.4 3.5,0 6.4,-3 6.4,-6.4L146.8,95.7zM72,95.8c0,-3.6 -2.8,-6.5 -6.4,-6.5a6.5,6.5 0,0 0,-6.4 6.5v26.7c0,3.5 3,6.4 6.4,6.4 3.5,0 6.4,-3 6.5,-6.4L72.1,95.7zM117,65.2l4.6,-8.2s0.4,-0.7 -0.4,-1.2c-0.7,-0.4 -1.2,0.4 -1.2,0.4l-4.6,8.2a30.4,30.4 0,0 0,-24.7 0L86,56.2s-0.5,-0.8 -1.2,-0.4c-0.8,0.4 -0.4,1.3 -0.4,1.3l4.5,8.1a26,26 0,0 0,-14.6 23h57.2a26,26 0,0 0,-14.5 -23zM74.4,90.5v41.4a7,7 0,0 0,7 6.9h4.5v14.1c0,3.6 3,6.4 6.4,6.4 3.6,0 6.4,-2.8 6.5,-6.4v-14.1h8.5v14.1c0,3.6 3,6.4 6.4,6.4 3.5,0 6.4,-2.8 6.4,-6.4v-14.1h4.6a7,7 0,0 0,7 -6.9L131.7,90.4L74.3,90.4z" - android:fillColor="#79c257"/> - <path android:pathData="M94.6,88.6c4.5,5 11.5,3.3 17.2,3 -6,-1 -12.6,-2.5 -17,-8.6" - android:strokeWidth="1" - android:fillColor="#f8db00" - android:strokeColor="#000"/> - <path android:pathData="M106.5,90.2c4,-2.8 8.9,-2.5 13.3,-1.4 -2.3,-1.8 -1.5,-3.4 -14.6,-2.6a17,17 0,0 1,-9.4 -2.4c1.8,3.2 6.1,6 10.7,6.4z" - android:strokeWidth="1" - android:fillColor="#d36224" - android:strokeColor="#000"/> - <path android:pathData="M122.2,91c2,-4 -5,-9.6 -6.8,-9.6 -5,-0.5 -14.7,-0.3 -14.4,-3 -3,-0.4 -5,1 -5.8,4 2.7,2.2 5.7,3.7 9.3,3.8 12.3,-0.9 14,0.8 15,2.6l2.7,2.2z" - android:strokeLineJoin="bevel" - android:strokeWidth="1" - android:fillColor="#ecd404" - android:strokeColor="#000"/> - <path android:pathData="M89.7,77.2L84,79.5l1,-2.3L89,74l0.8,1v2.2zM114.8,76.7l-5.7,1.9 1.2,-2.2 4,-3 0.7,1 -0.2,2.3z" - android:strokeWidth="1" - android:fillColor="#680000" - android:strokeColor="#000"/> - <path android:pathData="M84.3,78.6c1.8,-4.7 3.7,-6.3 7.3,-5.1 0.6,0.3 1.3,0.3 1.5,2.2 -0.1,1.4 -0.8,2 -2,2 -2.3,0 -2,-1.5 -2,-3 -2.4,0 -4.8,8.6 -7,3h0.7c0,1.1 1.3,1.4 1.5,0.9zM109.3,77.7c2.2,-4.5 4.2,-6 7.7,-4.6 0.6,0.4 1.3,0.4 1.3,2.4 -0.2,1.3 -0.9,1.9 -2,1.8 -2.3,0 -2,-1.7 -1.8,-3.2 -2.5,-0.1 -5.5,8.3 -7.2,2.6h0.6c0,1.1 1.2,1.5 1.4,1z" - android:strokeWidth="1" - android:fillColor="#000" - android:strokeColor="#000"/> - <path android:pathData="M92.3,75.7c0,0.6 -0.4,1 -1,1a1,1 0,0 1,-1 -1c0,-0.5 0.5,-1 1,-1 0.6,0 1,0.5 1,1zM117.6,75.4c0,0.6 -0.5,1 -1,1a1,1 0,0 1,-1 -1.1c0,-0.5 0.5,-1 1,-1a1,1 0,0 1,1 1.1z" - android:fillColor="#fff"/> -</vector> diff --git a/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_monochrome_foreground.xml b/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_monochrome_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..2fd30875c394713bb0ae5042048e2b47b38eeb3e --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_monochrome_foreground.xml @@ -0,0 +1,15 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="256" + android:viewportHeight="257"> + <group android:scaleX="0.4869866" + android:scaleY="0.4888889" + android:translateX="65.66572" + android:translateY="65.67778"> + <path + android:pathData="M128,256.91C198.69,256.91 256,199.6 256,128.91C256,58.22 198.69,0.91 128,0.91C57.31,0.91 0,58.22 0,128.91C0,199.6 57.31,256.91 128,256.91ZM233,128.91C233,70.92 185.99,23.91 128,23.91V39.91C177.15,39.91 217,79.75 217,128.91C217,178.06 177.15,217.91 128,217.91V233.91C185.99,233.91 233,186.9 233,128.91ZM193.75,128.91C193.75,92.6 164.31,63.16 128,63.16V79.16C155.48,79.16 177.75,101.43 177.75,128.91C177.75,156.38 155.48,178.66 128,178.66V194.66C164.31,194.66 193.75,165.22 193.75,128.91ZM128,101.66C143.05,101.66 155.25,113.86 155.25,128.91C155.25,143.96 143.05,156.16 128,156.16V101.66ZM94.04,61.23C94.36,61.18 94.46,60.77 94.2,60.59C89.25,57.25 83.29,55.31 76.87,55.31C59.75,55.31 45.87,69.16 45.87,86.24C45.87,103.33 59.75,117.18 76.87,117.18C84.6,117.18 91.66,114.35 97.09,109.69C97.34,109.48 97.19,109.08 96.86,109.07C83.98,108.56 73.7,97.99 73.7,85.01C73.7,73 82.52,63.04 94.04,61.23Z" + android:fillColor="#4A454E" + android:fillType="evenOdd"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..803115f3476cf8ea75ee5057a6ddd79803549902 --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_launcher_monochrome_foreground" /> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml new file mode 100644 index 0000000000000000000000000000000000000000..d21eef1e51e223d7851fb8202cb6d20dd5b575a0 --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..d21eef1e51e223d7851fb8202cb6d20dd5b575a0 --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4a603d4cce78b2fbd8094bd0224d4778bc8c976 --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher.webp index 89cb320575070387a91a1c3977b9eee611fbf402..a4f3299482510d7b93acd133250805f5e313d696 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..62e616d691cd7c42bd9d445150a641d611993e49 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..fd1b625ddbe3bf02ba0bd6c5ef2e19b2a212d684 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..5e0f9baee22fd0abf37e0596d9e9929da6b04c90 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_round.webp index be7dca2cfc5eaa54faceeacdb00224852ebaf5e1..5816b4af9c3fd7a189b3889a67fadd9b63960557 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher.webp index f66844b07591ed893205e1c8c2b35570c1c33403..6010a370d4b412e48cb61f4b9c30daa204d24b51 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..cdd6b6b4135bb7a4f923a4e80199790f43380b81 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..c83a8331dafa72ebf62d59a75aaf044bbe22e29c Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..a9a47e0917446500b0eaa4de550f4f0930cc817b Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_round.webp index 6293cbc77443c74207144bd81e3805444b9fe2d3..8fda9983408a16534dfceec97047152c418fdc55 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher.webp index 587f881a1d3127aa78779045aad4ba774c5793fe..7d4e5ec20bcca1914b52e3f603d741672714ea27 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..5c651b124d4a6961b95c65d08476c100d4efc4bc Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..fa54c04df3f248ffe57d26c45f8e9fd43b779b16 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..046b668cf0f59ddd2c2d9bbf5a01fbfcc18c157b Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.webp index 7335929883a0ce81271b7be4f934c695fa9cd488..00e899c1dc1faaba0a14497d5422ed195b27f8e0 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher.webp index 36dfdf39895c8e1142afb956d166e3b0d4b41ecd..0972805292da5a1d0e4adbc5cb1eff365644a0eb 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..8d3ca2a9772bcd6edb7b1ee12d1c3a4820f66d3f Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..2dec8754336d9ba05a144d7ab95cbf6b33261034 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..8e88ea6e0c7054de5ee7fdf2ff236ff6dfa617dc Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.webp index b8981becf0693c4391f19937fa4d1d3c9d690d3d..a2f24571b32be1bc99a941df479ef3b241f8d725 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.webp index 5a943bd097e056fa6182f0555936c977ee5d9e08..33b2429e648fc4dff82457e2d44f61bac9019af5 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..88b75110b69f6ef1da2e53ced92d3733d1cedd1c Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..e1a6f6d64b746289901c85e8ee0c5d7ee71a03bc Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1e025904e78eb4bdde9844db442d699250a9c064 Binary files /dev/null and b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.webp index 4e5d20ba16af6f0d4b8e5182959446c0173e2411..5efbcb1d62bafacbf7353ce1ad874c8fddf4da15 100644 Binary files a/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/debug/res/values/colors.xml b/mobile/android/fenix/app/src/debug/res/values/colors.xml index 31d64e96800979a9de3248d5d115dbaa58d69701..0b56ec400f5ab46d9d85244154a4871732260a62 100644 --- a/mobile/android/fenix/app/src/debug/res/values/colors.xml +++ b/mobile/android/fenix/app/src/debug/res/values/colors.xml @@ -3,5 +3,5 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> - <color name="ic_launcher_background">@color/photonInk20</color> + <color name="ic_launcher_background">#220033</color> </resources> diff --git a/mobile/android/fenix/app/src/debug/res/values/ic_launcher_monochrome_background.xml b/mobile/android/fenix/app/src/debug/res/values/ic_launcher_monochrome_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..71d80a9056ada38dc05a0fd5a5f7e984a39d1ccf --- /dev/null +++ b/mobile/android/fenix/app/src/debug/res/values/ic_launcher_monochrome_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_monochrome_background">#FEFBFF</color> +</resources> \ No newline at end of file diff --git a/mobile/android/fenix/app/src/debug/res/xml/shortcuts.xml b/mobile/android/fenix/app/src/debug/res/xml/shortcuts.xml index 42f365234c5f482b49d0c5f71ab1883485977548..31e590320bc959a6ca229fd2690185c632da9572 100644 --- a/mobile/android/fenix/app/src/debug/res/xml/shortcuts.xml +++ b/mobile/android/fenix/app/src/debug/res/xml/shortcuts.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- <shortcut android:shortcutId="password_manager" android:enabled="true" @@ -21,7 +22,7 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_TAB" - android:targetPackage="org.mozilla.fenix.debug" + android:targetPackage="org.torproject.torbrowser_debug" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> <shortcut @@ -31,7 +32,8 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_private_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_PRIVATE_TAB" - android:targetPackage="org.mozilla.fenix.debug" + android:targetPackage="org.torproject.torbrowser_debug" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> + --> </shortcuts> diff --git a/mobile/android/fenix/app/src/main/AndroidManifest.xml b/mobile/android/fenix/app/src/main/AndroidManifest.xml index fd83241025d61ce446040fc07685440df48d443f..d38fd1158bb13e66956f8c6023a87a9f3c2c5c4d 100644 --- a/mobile/android/fenix/app/src/main/AndroidManifest.xml +++ b/mobile/android/fenix/app/src/main/AndroidManifest.xml @@ -7,15 +7,12 @@ xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" tools:ignore="ScopedStorage" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CAMERA" /> <!-- This is needed because the android.permission.CAMERA above automatically @@ -32,9 +29,6 @@ <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" /> - <!-- Needed for Google Play policy https://support.google.com/googleplay/android-developer/answer/6048248 --> - <uses-permission android:name="com.google.android.gms.permission.AD_ID"/> - <!-- Needed to prompt the user to give permission to install a downloaded apk --> <uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> @@ -57,10 +51,10 @@ android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:roundIcon="@mipmap/ic_launcher_round" + android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" android:theme="@style/NormalTheme" - android:usesCleartextTraffic="true" + android:usesCleartextTraffic="false" tools:ignore="UnusedAttribute"> <profileable @@ -127,6 +121,7 @@ android:exported="true" android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|layoutDirection|smallestScreenSize|screenLayout" android:launchMode="singleTask" + android:taskAffinity="" android:resizeableActivity="true" android:supportsPictureInPicture="true" android:windowSoftInputMode="adjustResize"> @@ -240,11 +235,11 @@ <data android:mimeType="application/xhtml+xml" /> </intent-filter> - <intent-filter> - <action android:name="android.intent.action.SEND" /> - <category android:name="android.intent.category.DEFAULT" /> - <data android:mimeType="text/plain" /> - </intent-filter> +<!-- <intent-filter>--> +<!-- <action android:name="android.intent.action.SEND" />--> +<!-- <category android:name="android.intent.category.DEFAULT" />--> +<!-- <data android:mimeType="text/plain" />--> +<!-- </intent-filter>--> <intent-filter> <action android:name="android.intent.action.SEARCH" /> @@ -391,6 +386,7 @@ <service android:name=".push.FirebasePushService" + android:enabled="false" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> diff --git a/mobile/android/fenix/app/src/main/assets/common/torrc-defaults b/mobile/android/fenix/app/src/main/assets/common/torrc-defaults new file mode 100644 index 0000000000000000000000000000000000000000..88bead72acc1d1e611d4d98eee38b6ec47a14aab --- /dev/null +++ b/mobile/android/fenix/app/src/main/assets/common/torrc-defaults @@ -0,0 +1,9 @@ +## torrc-defaults for Tor Browser for Android +AvoidDiskWrites 1 +# (stderr|stdout|syslog|file FILENAME). +Log notice stdout +CookieAuthentication 1 +DormantCanceledByStartup 1 +ClientTransportPlugin meek_lite,obfs2,obfs3,obfs4,scramblesuit,webtunnel exec ./libObfs4proxy.so +ClientTransportPlugin snowflake exec ./libSnowflake.so +ClientTransportPlugin conjure exec ./libConjure.so -registerURL https://registration.refraction.network/api diff --git a/mobile/android/fenix/app/src/main/assets/searchplugins/reddit.xml b/mobile/android/fenix/app/src/main/assets/searchplugins/reddit.xml deleted file mode 100644 index 4f761ba2362c89e7788591d44a4dc225ddda1775..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/assets/searchplugins/reddit.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> - <ShortName>Reddit</ShortName> - <Description>Search Reddit</Description> - <LongName>Reddit Search</LongName> - <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAD9UlEQVR4AcyYA9QkSwyF69k2j59te/Bs27Zt2/batm3btu1v+55eN6p6uPec/P/MlJJCchNTCHCj2YGsuYq0+dqTxp4MJ2VmkDZLkfifh6tNfdRXY0w5weVmD1LmHtKmticLvc8kEY3RWM2huUqn+JVmR9LmDU/mSZFCiObSnJq7eIrfaLYibR7yZJIWLYZobq2htQqr/BXmIFKmuyeUSLprzcIonzanW3a9mKdxen7Kp8wdnizWhGWSxdIhH+XZTOSOxNem1DtvkcXSyf3BFvrOP3A0PHMOXLFjsO3q3eCTO+C7x+C6PWPfhHSzusqieJuxg0FYsRyG94YGv8IX98FjJ8PwXqzD1LGxRki3WBcrH1xw5bXDq1bByyl4/gL4/SVoVwMpG4rvH7d5p4ciI2xR3OVLl8DyZXDZ9sG2bx4mAF0lm3sNi9gK5UV5gH++BkO7h7ddtQuMG8I6TBoJ1+zuEiPeCBCzPLlNtHSsA3V/jG6/cmf4/F748n5dN2futBEBFCMsmgucMQk+vasYc9+z4fWpXRTlbz0YhHsPLwbVqL0uGYnm83nKO9fB/NmQ2qIYBiyU7kbZUcEmlaIPHgNvXQ3fPAI9m8O08b5rfPsaeOg4SG9ZMCOku1GKl9ckl24LH9wMnerBvFlYoRNR3w9v1dh8T+FrGdDYaWdfzcJvL/o7md0GMlvDL8/B7GnkjDnT4feXfUMyW/knpzXeuELfXQxoLAOGx3YSf+nbho0wsi+M6k/BoFgwtAcbYVAXa0yQ7kYVg9hO1T6nbGj4m+0UZugEltqIWNkwY5LtBJbaDZg0iliIlInviBaIsOl7dF/1UV+Nie8rzJ1hNcB+hWp9SwykyEb9pWAE1BYgerFo+o/1CtkfsXarfwciIC4T6B8Jtbn2HT0Art/b+ojd3KiCz6ypbrv6StrxBCyndeVOTm7UPZDNmmK91/4bGEck1ObSVwnQZds5BjJXKjGgIyWDDHOmEq5krupnlAytKrmTOWc6fduhSsopCZ44zZ1OJ0po/n+PUMiwmw+Av9+AxQuJxLKlUOMruGEfWDCHUDT5O3lC45xSyht1aUAoWlb0SyJyq8oD/n8X6v8Ctb+DX1+Ad6+Ha/eAq3eFRr8TiiHdlPwnTykTJfVioo3+iKbKCj6iyo+cCDcf6J+M8oD3bhC3iWavoth+THFP6vMqq3x8O0yfQN6YOxO+fyKY6NjLKvkXtkS1lRMoaiaGSij/vGWrxLkXtvIuLerK/Pg0tKqsXMFnkksX+w9XQXDMQGhf06/MPX1WDnny+tJi4uJu+WX1EIO7Q3p4fUhPcAzpKaaRO8k38NOsoxPd9F9qMLrYY6gttwEAUidatlp2alsAAAAASUVORK5CYII=</Image> - <Url type="text/html" method="get" template="https://www.reddit.com/search/?q={searchTerms}"/> -</SearchPlugin> diff --git a/mobile/android/fenix/app/src/main/assets/searchplugins/youtube.xml b/mobile/android/fenix/app/src/main/assets/searchplugins/youtube.xml deleted file mode 100644 index 60a7897ae417b0d3c8d09b0f53dcd10c80951327..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/assets/searchplugins/youtube.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> - <ShortName>YouTube</ShortName> - <Description>Search for videos on YouTube</Description> - <Tags>youtube video</Tags> - <Image height="16" width="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABa0lEQVR42u2YoYoCURSGBzSLk62L0TJvsEywWAxabRaFlQ2GQdY38AF8Ci0Gsy9gECybRU0GkQn++4fLbjm7K8wdmQPng6+I3rkfqHPnBIZhGIbxCAiCkL7QiL7SFu3QHu3TIX2nY5rQCf1wTtxrY/eeoftMz63RcmtG7hqhj82+0RX9pDeKJ3tz1165vVQf3XxMTxQF80Tj/zbfoFeKgnqljb8C1hQFd/3b5mv0riDgTmtSQJtCiW0pIFEUkEgBc0UBcylgkXnhKAIqlWcELKSATeaFp1PgeAT6faBUyjNgIwXsfQR8s90CcZxXwF4KOHgM+GG5BOp13wEHKeDiP8CRpsBsBoShr4CLFJB6DJA5n4HBACiXswakUsA9hwCZ3Q5oNjPdjfUH6P8K6f8R6/8b1X8j03+U0H+Y03+c1v9Ao/+RUv9Dvf6xiv7Blv7RojzcHRVouDui1TzG610P4/WuOF43DMMwjAf4ArcA0xFiL427AAAAAElFTkSuQmCC</Image> - <Url type="text/html" template="https://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch" /> - <Query role="example" searchTerms="cat" /> -</SearchPlugin> diff --git a/mobile/android/fenix/app/src/main/ic_launcher-web.webp b/mobile/android/fenix/app/src/main/ic_launcher-web.webp deleted file mode 100644 index 6cf56fdd15bfc46cbbc3d2fc66bbb07f640c5a24..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/ic_launcher-web.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt index a32c9838924ea02fddd01d8ff33afda516e53f88..e43062d2fbd39e48b3206224b1e4de330006034c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt @@ -42,4 +42,5 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) { FromTranslationsDialogFragment(R.id.translationsDialogFragment), FromDownloadLanguagesPreferenceFragment(R.id.downloadLanguagesPreferenceFragment), FromMenuDialogFragment(R.id.menuDialogFragment), + FromTorConnectionAssistFragment(R.id.torConnectionAssistFragment), } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index c5fb195ab063d53e55130d156fe644dc334bbb6a..9e33e91a01acc6e09b2b3fb1a617e77c1f231ecf 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -139,6 +139,8 @@ open class FenixApplication : LocaleAwareApplication(), Provider { isDeviceRamAboveThreshold() } + var terminating = false + open val components by lazy { Components(this) } var visibilityLifecycleCallback: VisibilityLifecycleCallback? = null @@ -188,10 +190,28 @@ open class FenixApplication : LocaleAwareApplication(), Provider { } } + fun isTerminating() = terminating + + fun terminate() { + onTerminate() + } + + override fun onTerminate() { + terminating = true + + super.onTerminate() + components.torController.stop() + components.torController.stopTor() + } + @OptIn(DelicateCoroutinesApi::class) // GlobalScope usage @VisibleForTesting protected open fun initializeGlean() { val telemetryEnabled = settings().isTelemetryEnabled + if (!telemetryEnabled) { + logger.debug("Preventing Glean from initializing, since telemetry is disabled") + return + } logger.debug("Initializing Glean (uploadEnabled=$telemetryEnabled})") @@ -215,7 +235,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { ) // Set the metric configuration from Nimbus. - Glean.applyServerKnobsConfig(FxNimbus.features.glean.value().metricsEnabled.toString()) + // Glean.applyServerKnobsConfig(FxNimbus.features.glean.value().metricsEnabled.toString()) Glean.initialize( applicationContext = this, @@ -247,7 +267,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { // // We can initialize Nimbus before Glean because Glean will queue messages // before it's initialized. - initializeNimbus() + // initializeNimbus() ProfilerMarkerFactProcessor.create { components.core.engine.profiler }.register() @@ -315,6 +335,8 @@ open class FenixApplication : LocaleAwareApplication(), Provider { components.analytics.metricsStorage.tryRegisterAsUsageRecorder(this) downloadWallpapers() + + components.torController.start() } @OptIn(DelicateCoroutinesApi::class) // GlobalScope usage @@ -920,7 +942,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { clipboardSuggestionsEnabled.set(settings.shouldShowClipboardSuggestions) searchShortcutsEnabled.set(settings.shouldShowSearchShortcuts) voiceSearchEnabled.set(settings.shouldShowVoiceSearch) - openLinksInAppEnabled.set(settings.openLinksInExternalApp) + //openLinksInAppEnabled.set(settings.openLinksInExternalApp) signedInSync.set(settings.signedInFxaAccount) val syncedItems = SyncEnginesStorage(applicationContext).getStatus().entries.filter { @@ -1059,9 +1081,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { @OptIn(DelicateCoroutinesApi::class) open fun downloadWallpapers() { - GlobalScope.launch { - components.useCases.wallpaperUseCases.initialize() - } + // IN TOR BROWSER: we don't download wallpapers. } /** diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index bcbad58918a07c0022d3df5facdf2c17b631396d..8a088ebfe93cc1ac62b007d153844165448dc8bc 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix import android.annotation.SuppressLint import android.app.assist.AssistContent +import android.app.PendingIntent import android.content.ComponentName import android.content.Context import android.content.Intent @@ -26,6 +27,7 @@ import android.view.MotionEvent import android.view.View import android.view.ViewConfiguration import android.view.WindowManager.LayoutParams.FLAG_SECURE +import androidx.activity.viewModels import androidx.annotation.CallSuper import androidx.annotation.IdRes import androidx.annotation.RequiresApi @@ -60,6 +62,8 @@ import mozilla.components.browser.state.state.WebExtensionState import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineView import mozilla.components.concept.storage.HistoryMetadataKey +import mozilla.components.feature.app.links.RedirectDialogFragment +import mozilla.components.feature.app.links.SimpleRedirectDialogFragment import mozilla.components.feature.contextmenu.DefaultSelectionActionDelegate import mozilla.components.feature.media.ext.findActiveMediaTab import mozilla.components.feature.privatemode.notification.PrivateNotificationFeature @@ -79,6 +83,8 @@ import mozilla.components.support.utils.BootUtils import mozilla.components.support.utils.BrowsersCache import mozilla.components.support.utils.ManufacturerCodes import mozilla.components.support.utils.SafeIntent +import mozilla.components.support.utils.TorUtils +import mozilla.components.support.utils.ext.getParcelableExtraCompat import mozilla.components.support.utils.toSafeIntent import mozilla.components.support.webextensions.WebExtensionPopupObserver import mozilla.telemetry.glean.private.NoExtras @@ -115,7 +121,6 @@ import org.mozilla.fenix.ext.getIntentSource import org.mozilla.fenix.ext.getNavDirections import org.mozilla.fenix.ext.hasTopDestination import org.mozilla.fenix.ext.nav -import org.mozilla.fenix.ext.recordEventInNimbus import org.mozilla.fenix.ext.setNavigationIcon import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.systemGesturesInsets @@ -150,11 +155,19 @@ import org.mozilla.fenix.tabhistory.TabHistoryDialogFragment import org.mozilla.fenix.tabstray.TabsTrayFragment import org.mozilla.fenix.theme.DefaultThemeManager import org.mozilla.fenix.theme.ThemeManager +import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections +import org.mozilla.fenix.tor.TorEvents import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.changeAppLauncherIconBackgroundColor import java.lang.ref.WeakReference import java.util.Locale +import mozilla.components.browser.engine.gecko.GeckoEngine +import org.mozilla.fenix.components.FenixSnackbar +import org.mozilla.fenix.home.HomeFragment +import org.mozilla.fenix.tor.TorConnectionAssistViewModel +import org.mozilla.geckoview.TorIntegrationAndroid + /** * The main activity of the application. The application is primarily a single Activity (this one) * with fragments switching out to display different views. The most important views shown here are the: @@ -162,7 +175,7 @@ import java.util.Locale * - browser screen */ @SuppressWarnings("TooManyFunctions", "LargeClass", "LongMethod") -open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { +open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIntegrationAndroid.BootstrapStateChangeListener { @VisibleForTesting internal lateinit var binding: ActivityHomeBinding lateinit var themeManager: ThemeManager @@ -227,7 +240,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { OpenSpecificTabIntentProcessor(this), OpenPasswordManagerIntentProcessor(), OpenRecentlyClosedIntentProcessor(), - ReEngagementIntentProcessor(this, settings()), + //ReEngagementIntentProcessor(this, settings()), ) } @@ -242,6 +255,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { private val startupPathProvider = StartupPathProvider() private lateinit var startupTypeTelemetry: StartupTypeTelemetry + private var dialog: RedirectDialogFragment? = null + + private val torConnectionAssistViewModel: TorConnectionAssistViewModel by viewModels() + @Suppress("ComplexMethod") final override fun onCreate(savedInstanceState: Bundle?) { // DO NOT MOVE ANYTHING ABOVE THIS getProfilerTime CALL. @@ -330,6 +347,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { it.start() } + /* if (settings().shouldShowOnboarding( hasUserBeenOnboarded = components.fenixOnboarding.userHasBeenOnboarded(), isLauncherIntent = intent.toSafeIntent().isLauncherIntent, @@ -340,8 +358,9 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { navHost.navController.navigate(NavGraphDirections.actionGlobalOnboarding()) } } else { + */ lifecycleScope.launch(IO) { - showFullscreenMessageIfNeeded(applicationContext) + // showFullscreenMessageIfNeeded(applicationContext) } // Unless the activity is recreated, navigate to home first (without rendering it) @@ -355,11 +374,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } else { StartOnHome.enterHomeScreen.record(NoExtras()) } - + /* if (settings().showHomeOnboardingDialog && components.fenixOnboarding.userHasBeenOnboarded()) { navHost.navController.navigate(NavGraphDirections.actionGlobalHomeOnboardingDialog()) } - } + */ + //} Performance.processIntentIfPerformanceTest(intent, this) @@ -385,7 +405,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { ) } // This will record an event in Nimbus' internal event store. Used for behavioral targeting - recordEventInNimbus("app_opened") + // recordEventInNimbus("app_opened") if (safeIntent.action.equals(ACTION_OPEN_PRIVATE_TAB) && source == APP_ICON) { AppIcon.newPrivateTabTapped.record(NoExtras()) @@ -468,6 +488,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { ), ) + val engine = components.core.engine + if (engine is GeckoEngine) { + val torIntegration = engine.getTorIntegrationController() + torIntegration.registerBootstrapStateChangeListener(this) + } + StartupTimeline.onActivityCreateEndHome(this) // DO NOT MOVE ANYTHING BELOW HERE. } @@ -482,7 +508,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } } - if (FxNimbus.features.splashScreen.value().enabled) { + if (false) { // FxNimbus.features.splashScreen.value().enabled val splashScreen = installSplashScreen() var maxDurationReached = false val delay = FxNimbus.features.splashScreen.value().maximumDurationMs.toLong() @@ -645,7 +671,9 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { override fun onProvideAssistContent(outContent: AssistContent?) { super.onProvideAssistContent(outContent) val currentTabUrl = components.core.store.state.selectedTab?.content?.url - outContent?.webUri = currentTabUrl?.let { Uri.parse(it) } + if (components.core.store.state.selectedTab?.content?.private == false) { + outContent?.webUri = currentTabUrl?.let { Uri.parse(it) } + } } @CallSuper @@ -671,6 +699,22 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { if (this !is ExternalAppBrowserActivity && !activityStartedWithLink) { stopMediaSession() } + + if (isFinishing && !(application as FenixApplication).isTerminating()) { + // We assume the Activity is being destroyed because the user + // swiped away the app on the Recent screen. When this happens, + // we assume the user expects the entire Application is destroyed + // and not only the top Activity/Task. Therefore we kill the + // underlying Application, as well. + (application as FenixApplication).terminate() + if (settings().useHtmlConnectionUi) { + val engine = components.core.engine + if (engine is GeckoEngine) { + val torIntegration = engine.getTorIntegrationController() + torIntegration.unregisterBootstrapStateChangeListener(this) + } + } + } } final override fun onConfigurationChanged(newConfig: Configuration) { @@ -699,10 +743,49 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { super.recreate() } + // Copied from mozac AppLinksFeature.kt + internal fun getOrCreateDialog(): RedirectDialogFragment { + val existingDialog = dialog + if (existingDialog != null) { + return existingDialog + } + + SimpleRedirectDialogFragment.newInstance().also { + dialog = it + return it + } + } + private fun isAlreadyADialogCreated(): Boolean { + return findPreviousDialogFragment() != null + } + + private fun findPreviousDialogFragment(): RedirectDialogFragment? { + return supportFragmentManager.findFragmentByTag(RedirectDialogFragment.FRAGMENT_TAG) as? RedirectDialogFragment + } + /** * Handles intents received when the activity is open. */ + @SuppressLint("MissingSuperCall") // super.onNewIntent is called in [onNewIntentInternal(intent)] final override fun onNewIntent(intent: Intent) { + if (intent.action == ACTION_MAIN || components.torController.isConnected) { + onNewIntentInternal(intent) + } else { + // Wait until Tor is connected to handle intents from external apps for links, search, etc. + components.torController.registerTorListener(object : TorEvents { + override fun onTorConnected() { + components.torController.unregisterTorListener(this) + onNewIntentInternal(intent) + } + override fun onTorConnecting() { /* no-op */ } + override fun onTorStopped() { /* no-op */ } + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { /* no-op */ } + }) + return + } + } + + private fun onNewIntentInternal(intent: Intent) { super.onNewIntent(intent) handleNewIntent(intent) startupPathProvider.onIntentReceived(intent) @@ -714,6 +797,26 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { return } + val startIntent = intent.getParcelableExtraCompat(TorUtils.TORBROWSER_START_ACTIVITY_PROMPT, PendingIntent::class.java) + if (startIntent != null) { + if (startIntent.creatorPackage == applicationContext.packageName) { + val dialog = getOrCreateDialog() + dialog.onConfirmRedirect = { + @Suppress("EmptyCatchBlock") + try { + startIntent.send() + } catch (error: PendingIntent.CanceledException) { + } + } + dialog.onCancelRedirect = {} + + if (!isAlreadyADialogCreated()) { + dialog.showNow(supportFragmentManager, RedirectDialogFragment.FRAGMENT_TAG) + } + } + return + } + // Diagnostic breadcrumb for "Display already aquired" crash: // https://github.com/mozilla-mobile/android-components/issues/7960 breadcrumb( @@ -949,11 +1052,16 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { internal fun getModeFromIntentOrLastKnown(intent: Intent?): BrowsingMode { intent?.toSafeIntent()?.let { if (it.hasExtra(PRIVATE_BROWSING_MODE)) { - val startPrivateMode = it.getBooleanExtra(PRIVATE_BROWSING_MODE, false) + val startPrivateMode = settings().shouldDisableNormalMode || + it.getBooleanExtra(PRIVATE_BROWSING_MODE, settings().openLinksInAPrivateTab) return BrowsingMode.fromBoolean(isPrivate = startPrivateMode) } } - return settings().lastKnownMode + return when { + settings().shouldDisableNormalMode -> BrowsingMode.Private + settings().openLinksInAPrivateTab -> BrowsingMode.Private + else -> settings().lastKnownMode + } } /** @@ -1060,6 +1168,25 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { historyMetadata: HistoryMetadataKey? = null, additionalHeaders: Map<String, String>? = null, ) { + if (!components.torController.isBootstrapped && !searchTermOrURL.startsWith("about:")) { + FenixSnackbar.make( + view = binding.root, + ) + .setText(getString(R.string.connection_assist_connect_to_tor_before_opening_links)) + .setAllCapsForActionButton(false) + .setAction(getString(R.string.connection_assist_connect_to_tor_before_opening_links_confirmation)) { + torConnectionAssistViewModel.handleConnect(searchTermOrURL) + if (navHost.navController.previousBackStackEntry?.destination?.id == R.id.torConnectionAssistFragment) { + supportFragmentManager.popBackStack() + } else { + navHost.navController.navigate( + TorConnectionAssistFragmentDirections.actionConnectToTorBeforeOpeningLinks() + ) + } + } + .show() + return + } openToBrowser(from, customTabSessionId) load( searchTermOrURL = searchTermOrURL, @@ -1195,11 +1322,20 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { @VisibleForTesting internal fun navigateToHome(navController: NavController) { - if (this is ExternalAppBrowserActivity) { - return - } + //if (this is ExternalAppBrowserActivity) { + // return + //} - navController.navigate(NavGraphDirections.actionStartupHome()) + if (!settings().useHtmlConnectionUi) { + navController.navigate(NavGraphDirections.actionStartupTorConnectionAssist()) + } else { + navController.navigate(NavGraphDirections.actionStartupHome()) + openToBrowserAndLoad( + searchTermOrURL = "about:torconnect", + newTab = true, + from = BrowserDirection.FromHome, + ) + } } final override fun attachBaseContext(base: Context) { @@ -1288,14 +1424,17 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { /** * Indicates if the user should be redirected to the [BrowserFragment] or to the [HomeFragment], - * links from an external apps should always opened in the [BrowserFragment]. + * links from an external apps should always opened in the [BrowserFragment], + * unless Tor is not yet connected. */ @VisibleForTesting internal fun shouldStartOnHome(intent: Intent? = this.intent): Boolean { return components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) { // We only want to open on home when users tap the app, - // we want to ignore other cases when the app gets open by users clicking on links. - getSettings().shouldStartOnHome() && intent?.action == ACTION_MAIN + // we want to ignore other cases when the app gets open by users clicking on links, + // unless Tor is not yet connected. + getSettings().shouldStartOnHome() && (intent?.action == ACTION_MAIN || + !components.torController.isConnected) } } @@ -1326,10 +1465,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { keyDismissButtonText = null, ) + /* researchSurfaceDialogFragment.onAccept = { processIntent(messaging.getIntentForMessage(nextMessage)) components.appStore.dispatch(AppAction.MessagingAction.MessageClicked(nextMessage)) } + */ researchSurfaceDialogFragment.onDismiss = { components.appStore.dispatch(AppAction.MessagingAction.MessageDismissed(nextMessage)) @@ -1342,10 +1483,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { ) } - // Update message as displayed. - val currentBootUniqueIdentifier = BootUtils.getBootIdentifier(context) - - messaging.onMessageDisplayed(nextMessage, currentBootUniqueIdentifier) +// // Update message as displayed. +// val currentBootUniqueIdentifier = BootUtils.getBootIdentifier(context) +// +// messaging.onMessageDisplayed(nextMessage, currentBootUniqueIdentifier) } @VisibleForTesting @@ -1379,4 +1520,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { // telemetry purposes. private const val PWA_RECENTLY_USED_THRESHOLD = DateUtils.DAY_IN_MILLIS * 30L } + + override fun onBootstrapStateChange(state: String) = Unit + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit + override fun onBootstrapComplete() { + if (settings().useHtmlConnectionUi) { + components.useCases.tabsUseCases.removeAllTabs() + navHost.navController.navigate(NavGraphDirections.actionStartupHome()) + } + } + override fun onBootstrapError(code: String?, message: String?, phase: String?, reason: String?) = Unit } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt index 806724b49c7c9714f58fdb28ab0a11d2bca74165..4dda20d1ea5c3665437ce419d78d159a57431ae2 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix import android.app.Activity import android.content.Intent +import android.content.Intent.ACTION_MAIN import android.content.pm.PackageManager import android.net.Uri import android.os.Build @@ -30,6 +31,7 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.MarkersActivityLifecycleCallbacks import org.mozilla.fenix.perf.StartupTimeline import org.mozilla.fenix.shortcut.NewTabShortcutIntentProcessor +import org.mozilla.fenix.tor.TorEvents /** * Processes incoming intents and sends them to the corresponding activity. @@ -53,7 +55,23 @@ class IntentReceiverActivity : Activity() { // the HomeActivity. val intent = intent?.let { Intent(it) } ?: Intent() intent.sanitize().stripUnwantedFlags() - processIntent(intent) + if (intent.action == ACTION_MAIN || components.torController.isConnected) { + processIntent(intent) + } else { + // Wait until Tor is connected to handle intents from external apps for links, search, etc. + components.torController.registerTorListener(object : TorEvents { + override fun onTorConnected() { + components.torController.unregisterTorListener(this) + processIntent(intent) + } + override fun onTorConnecting() { /* no-op */ } + override fun onTorStopped() { /* no-op */ } + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { /* no-op */ } + }) + + // In the meantime, open the HomeActivity so the user can get connected. + processIntent(Intent()) + } components.core.engine.profiler?.addMarker( MarkersActivityLifecycleCallbacks.MARKER_NAME, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt index fca5d414fcabf03858619da257f15c15942a8126..852a36ef2b1bd5609c2192adec4e81975a7867e2 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt @@ -27,6 +27,7 @@ import mozilla.components.feature.addons.AddonManagerException import mozilla.components.feature.addons.ui.translateName import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.BuildConfig +import mozilla.components.support.webextensions.WebExtensionSupport.installedExtensions import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.databinding.FragmentInstalledAddOnDetailsBinding @@ -50,6 +51,8 @@ class InstalledAddonDetailsFragment : Fragment() { @Suppress("VariableNaming") internal var _binding: FragmentInstalledAddOnDetailsBinding? = null + private var isBundledAddon = false; + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -57,6 +60,7 @@ class InstalledAddonDetailsFragment : Fragment() { ): View { if (!::addon.isInitialized) { addon = AddonDetailsFragmentArgs.fromBundle(requireNotNull(arguments)).addon + isBundledAddon = installedExtensions[addon.id]?.isBundled() ?: false } setBindingAndBindUI( @@ -175,6 +179,7 @@ class InstalledAddonDetailsFragment : Fragment() { // When the ad-on is blocklisted or not correctly signed, we do not want to enable the toggle switch // because users shouldn't be able to re-enable an add-on in this state. if ( + isBundledAddon || addon.isDisabledAsBlocklisted() || addon.isDisabledAsNotCorrectlySigned() || addon.isDisabledAsIncompatible() @@ -193,7 +198,7 @@ class InstalledAddonDetailsFragment : Fragment() { runIfFragmentIsAttached { this.addon = it switch.isClickable = true - privateBrowsingSwitch.isVisible = it.isEnabled() + privateBrowsingSwitch.isVisible = false privateBrowsingSwitch.isChecked = it.incognito != Addon.Incognito.NOT_ALLOWED && it.isAllowedInPrivateBrowsing() binding.settings.isVisible = shouldSettingsBeVisible() @@ -293,7 +298,7 @@ class InstalledAddonDetailsFragment : Fragment() { @VisibleForTesting internal fun bindAllowInPrivateBrowsingSwitch() { val switch = providePrivateBrowsingSwitch() - switch.isVisible = addon.isEnabled() + switch.isVisible = false if (addon.incognito == Addon.Incognito.NOT_ALLOWED) { switch.isChecked = false @@ -330,6 +335,7 @@ class InstalledAddonDetailsFragment : Fragment() { } private fun bindReportButton() { + binding.reportAddOn.isVisible = !isBundledAddon binding.reportAddOn.setOnClickListener { val shouldCreatePrivateSession = (activity as HomeActivity).browsingModeManager.mode.isPrivate @@ -394,6 +400,7 @@ class InstalledAddonDetailsFragment : Fragment() { } private fun bindRemoveButton() { + binding.removeAddOn.isVisible = !isBundledAddon binding.removeAddOn.setOnClickListener { setAllInteractiveViewsClickable(binding, false) requireContext().components.addonManager.uninstallAddon( diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 66a7faf3d511e3076ce8118ebb3e26d2e896f6f3..317cad524570f65419d02c977b9dd06926e1ae31 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -159,7 +159,7 @@ import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FindInPageIntegration import org.mozilla.fenix.components.StoreProvider -import org.mozilla.fenix.components.accounts.FxaWebChannelIntegration +// import org.mozilla.fenix.components.accounts.FxaWebChannelIntegration import org.mozilla.fenix.components.appstate.AppAction import org.mozilla.fenix.components.appstate.AppAction.MessagingAction import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MicrosurveyAction @@ -298,7 +298,7 @@ abstract class BaseBrowserFragment : private val sitePermissionsFeature = ViewBoundFeatureWrapper<SitePermissionsFeature>() private val fullScreenFeature = ViewBoundFeatureWrapper<FullScreenFeature>() private val swipeRefreshFeature = ViewBoundFeatureWrapper<SwipeRefreshFeature>() - private val webchannelIntegration = ViewBoundFeatureWrapper<FxaWebChannelIntegration>() + // private val webchannelIntegration = ViewBoundFeatureWrapper<FxaWebChannelIntegration>() private val sitePermissionWifiIntegration = ViewBoundFeatureWrapper<SitePermissionsWifiIntegration>() private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>() @@ -757,7 +757,7 @@ abstract class BaseBrowserFragment : PreferenceManager.getDefaultSharedPreferences(context).getBoolean( context.getPreferenceKey(R.string.pref_key_external_download_manager), false, - ) + ) && false }, promptsStyling = DownloadsFeature.PromptsStyling( gravity = Gravity.BOTTOM, @@ -1200,6 +1200,7 @@ abstract class BaseBrowserFragment : ) } +/* webchannelIntegration.set( feature = FxaWebChannelIntegration( customTabSessionId = customTabSessionId, @@ -1212,6 +1213,7 @@ abstract class BaseBrowserFragment : owner = this, view = view, ) +*/ initializeEngineView( topToolbarHeight = context.settings().getTopToolbarHeight( @@ -1962,6 +1964,9 @@ abstract class BaseBrowserFragment : val context = requireContext() resumeDownloadDialogState(selectedTab.id, context.components.core.store, context) it.announceForAccessibility(selectedTab.toDisplayTitle()) + if (getCurrentTab()?.content?.url == "about:torconnect") { + browserToolbarView.view.visibility = View.GONE + } } } else { view?.let { view -> initializeUI(view) } @@ -1988,6 +1993,22 @@ abstract class BaseBrowserFragment : } evaluateMessagesForMicrosurvey(components) + handleBetaHtmlTorConnect() + } + + private fun handleBetaHtmlTorConnect() { + val currentTab = getCurrentTab() ?: return + if (currentTab.content.url == "about:torconnect") { + if (!requireActivity().settings().useHtmlConnectionUi) { + requireContext().components.useCases.tabsUseCases.removeTab(currentTab.id) + (requireActivity() as HomeActivity).navigateToHome(findNavController()) + } else { + // This just makes it not flash (be visible for a split second) before handleTabSelected() hides it again + browserToolbarView.view.visibility = View.GONE + } + } else if (currentTab.content.url == "about:tor") { + requireContext().components.useCases.tabsUseCases.removeTab(currentTab.id) + } } private fun evaluateMessagesForMicrosurvey(components: Components) = diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index 93d55325a6eb74ca3d0645bab4f719ee6e5460b4..02f15ae1095f7c760d00d6241a8f86690fd9f25c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -139,7 +139,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { view = view, ) - if (context.settings().shouldShowOpenInAppCfr) { + if (false) { // context.settings().shouldShowOpenInAppCfr openInAppOnboardingObserver.set( feature = OpenInAppOnboardingObserver( context = context, @@ -731,7 +731,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { override fun navToQuickSettingsSheet(tab: SessionState, sitePermissions: SitePermissions?) { val useCase = requireComponents.useCases.trackingProtectionUseCases - FxNimbus.features.cookieBanners.recordExposure() + // FxNimbus.features.cookieBanners.recordExposure() useCase.containsException(tab.id) { hasTrackingProtectionException -> lifecycleScope.launch { val cookieBannersStorage = requireComponents.core.cookieBannersStorage diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt index 6e5e2c074763232d82dd42f97029954e11280580..8cb87dc05c706b17e2c760d380e9d7f1bb41ff08 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt @@ -66,7 +66,7 @@ class OpenInAppOnboardingObserver( currentUrl = tab.content.url } else { // Loading state has changed - maybeShowOpenInAppBanner(tab.content.url, tab.content.loading) +// maybeShowOpenInAppBanner(tab.content.url, tab.content.loading) } } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt index 098ccfb9f87e33713105ee21b323de46ee39711b..c50bf4a6837100985b39f0c9f0d96d5ae3d0d7b5 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt @@ -117,7 +117,7 @@ class Analytics( appName = context.getString(R.string.app_name), organizationName = "Mozilla", ), - enabled = true, + enabled = !isDataColectionDisabled(), nonFatalCrashIntent = pendingIntent, notificationsDelegate = context.components.notificationsDelegate, useLegacyReporting = !context.settings().useNewCrashReporter, @@ -149,6 +149,7 @@ class Analytics( } } +fun isDataColectionDisabled() = BuildConfig.DATA_COLLECTION_DISABLED private fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty() private fun getSentryProjectUrl(): String? { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index 5a850fbe1d895cc90ca2e5b17f1edf6f488f671d..b7e562817fca32ca0d83fb8f26483c25bd590cfc 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -49,7 +49,6 @@ import org.mozilla.fenix.GleanMetrics.SyncAuth import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.maxActiveTime -import org.mozilla.fenix.ext.recordEventInNimbus import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.StrictModeManager import org.mozilla.fenix.perf.lazyMonitored @@ -267,7 +266,7 @@ internal class TelemetryAccountObserver( // User signed-in into an existing FxA account. AuthType.Signin -> { SyncAuth.signIn.record(NoExtras()) - context.recordEventInNimbus("sync_auth.sign_in") + // context.recordEventInNimbus("sync_auth.sign_in") } // User created a new FxA account. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt index 7731b77933746a0da32bd439250e2e69943cf098..95c837e21f6ba7b2659aa6129abe448a5556efd9 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -49,6 +49,7 @@ import org.mozilla.fenix.perf.StartupActivityLog import org.mozilla.fenix.perf.StartupStateProvider import org.mozilla.fenix.perf.StrictModeManager import org.mozilla.fenix.perf.lazyMonitored +import org.mozilla.fenix.tor.TorControllerGV import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.wifi.WifiConnectionMonitor @@ -247,6 +248,8 @@ class Components(private val context: Context) { } val fxSuggest by lazyMonitored { FxSuggest(context) } + + val torController by lazyMonitored { TorControllerGV(context) } } /** diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt index 57858f1f6582075bf3e80ad2b6d3b6432936e7f8..28b5ca786ae68274520ce04fc3f4f16e08b6c3a9 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -20,7 +20,7 @@ import mozilla.components.browser.domains.autocomplete.BaseDomainAutocompletePro import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider import mozilla.components.browser.engine.gecko.GeckoEngine import mozilla.components.browser.engine.gecko.cookiebanners.GeckoCookieBannersStorage -import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository +//import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository import mozilla.components.browser.engine.gecko.fetch.GeckoViewFetchClient import mozilla.components.browser.engine.gecko.permission.GeckoSitePermissionsStorage import mozilla.components.browser.icons.BrowserIcons @@ -58,21 +58,21 @@ import mozilla.components.feature.readerview.ReaderViewMiddleware import mozilla.components.feature.recentlyclosed.RecentlyClosedMiddleware import mozilla.components.feature.recentlyclosed.RecentlyClosedTabsStorage import mozilla.components.feature.search.ext.createApplicationSearchEngine -import mozilla.components.feature.search.middleware.AdsTelemetryMiddleware +// import mozilla.components.feature.search.middleware.AdsTelemetryMiddleware import mozilla.components.feature.search.middleware.SearchExtraParams import mozilla.components.feature.search.middleware.SearchMiddleware import mozilla.components.feature.search.region.RegionMiddleware -import mozilla.components.feature.search.telemetry.SerpTelemetryRepository -import mozilla.components.feature.search.telemetry.ads.AdsTelemetry -import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry +// import mozilla.components.feature.search.telemetry.SerpTelemetryRepository +// import mozilla.components.feature.search.telemetry.ads.AdsTelemetry +// import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry import mozilla.components.feature.session.HistoryDelegate import mozilla.components.feature.session.middleware.LastAccessMiddleware import mozilla.components.feature.session.middleware.undo.UndoMiddleware import mozilla.components.feature.sitepermissions.OnDiskSitePermissionsStorage import mozilla.components.feature.top.sites.DefaultTopSitesStorage import mozilla.components.feature.top.sites.PinnedSiteStorage -import mozilla.components.feature.webcompat.WebCompatFeature -import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature +// import mozilla.components.feature.webcompat.WebCompatFeature +// import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature import mozilla.components.feature.webnotifications.WebNotificationFeature import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.service.contile.ContileTopSitesProvider @@ -169,8 +169,10 @@ class Core( cookieBannerHandlingDetectOnlyMode = context.settings().shouldEnableCookieBannerDetectOnly, cookieBannerHandlingGlobalRules = context.settings().shouldEnableCookieBannerGlobalRules, cookieBannerHandlingGlobalRulesSubFrames = context.settings().shouldEnableCookieBannerGlobalRulesSubFrame, - emailTrackerBlockingPrivateBrowsing = true, + emailTrackerBlockingPrivateBrowsing = false, userCharacteristicPingCurrentVersion = FxNimbus.features.userCharacteristics.value().currentVersion, + torSecurityLevel = context.settings().torSecurityLevel().intRepresentation, + spoofEnglish = context.settings().spoofEnglish, ) // Apply fingerprinting protection overrides if the feature is enabled in Nimbus @@ -184,7 +186,7 @@ class Core( defaultSettings, geckoRuntime, ).also { - WebCompatFeature.install(it) + // WebCompatFeature.install(it) /** * There are some issues around localization to be resolved, as well as questions around @@ -192,9 +194,11 @@ class Core( * disabled in Fenix Release builds for now. * This is consistent with both Fennec and Firefox Desktop. */ - if (Config.channel.isNightlyOrDebug || Config.channel.isBeta) { - WebCompatReporterFeature.install(it, "fenix") - } + // if (Config.channel.isNightlyOrDebug || Config.channel.isBeta) { + // WebCompatReporterFeature.install(it, "fenix") + // } + + TorBrowserFeatures.install(context, it) } } @@ -230,14 +234,14 @@ class Core( ) } - private val Context.dataStore by preferencesDataStore( - name = ReportSiteDomainsRepository.REPORT_SITE_DOMAINS_REPOSITORY_NAME, - ) +// private val Context.dataStore by preferencesDataStore( +// name = ReportSiteDomainsRepository.REPORT_SITE_DOMAINS_REPOSITORY_NAME, +// ) val cookieBannersStorage by lazyMonitored { GeckoCookieBannersStorage( geckoRuntime, - ReportSiteDomainsRepository(context.dataStore), +// ReportSiteDomainsRepository(context.dataStore), ) } @@ -258,7 +262,7 @@ class Core( } val applicationSearchEngines: List<SearchEngine> by lazyMonitored { - listOf( + listOfNotNull( createApplicationSearchEngine( id = BOOKMARKS_SEARCH_ENGINE_ID, name = context.getString(R.string.library_bookmarks), @@ -271,12 +275,16 @@ class Core( url = "", icon = getDrawable(context, R.drawable.ic_tabs_search)?.toBitmap()!!, ), - createApplicationSearchEngine( - id = HISTORY_SEARCH_ENGINE_ID, - name = context.getString(R.string.library_history), - url = "", - icon = getDrawable(context, R.drawable.ic_history_search)?.toBitmap()!!, - ), + if (!context.settings().shouldDisableNormalMode) { + createApplicationSearchEngine( + id = HISTORY_SEARCH_ENGINE_ID, + name = context.getString(R.string.library_history), + url = "", + icon = getDrawable(context, R.drawable.ic_history_search)?.toBitmap()!!, + ) + } else { + null + }, ) } @@ -312,7 +320,7 @@ class Core( ), RecordingDevicesMiddleware(context, context.components.notificationsDelegate), PromptMiddleware(), - AdsTelemetryMiddleware(adsTelemetry), + // AdsTelemetryMiddleware(adsTelemetry), LastMediaAccessMiddleware(), HistoryMetadataMiddleware(historyMetadataService), SessionPrioritizationMiddleware(), @@ -342,6 +350,7 @@ class Core( // Install the "icons" WebExtension to automatically load icons for every visited website. icons.install(engine, this) +/* CoroutineScope(Dispatchers.Main).launch { val readJson = { context.assets.readJSONObject("search/search_telemetry_v2.json") } val providerList = withContext(Dispatchers.IO) { @@ -361,12 +370,13 @@ class Core( // Install the "cookies" WebExtension and tracks user interaction with SERPs. searchTelemetry.install(engine, this@apply, providerList) } +*/ WebNotificationFeature( context, engine, icons, - R.drawable.ic_status_logo, + R.drawable.mozac_lib_crash_notification, permissionStorage.permissionsStorage, IntentReceiverActivity::class.java, notificationsDelegate = context.components.notificationsDelegate, @@ -406,13 +416,13 @@ class Core( context.components.analytics.metrics } - val adsTelemetry by lazyMonitored { - AdsTelemetry() - } + // val adsTelemetry by lazyMonitored { + // AdsTelemetry() + // } - val searchTelemetry by lazyMonitored { - InContentTelemetry() - } + // val searchTelemetry by lazyMonitored { + // InContentTelemetry() + // } /** * Shortcut component for managing shortcuts on the device home screen. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt index 8295daf466ac64263629e2be2755c9a987c245be..7e4fc13f5073b266b937390bdb667a801b830512 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt @@ -98,6 +98,14 @@ class FenixSnackbar private constructor( } } + /** + * @param textAllCaps Present the text in ALL CAPS. This may use a small-caps form when available. + * Overwrites the default value set in fenix_snackbar.xml + */ + fun setAllCapsForActionButton(textAllCaps: Boolean) = this.apply { + binding.snackbarBtn.isAllCaps = textAllCaps + } + companion object { const val LENGTH_LONG = Snackbar.LENGTH_LONG const val LENGTH_SHORT = Snackbar.LENGTH_SHORT diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt index ad90042055a48518f9270274037214fbb536a4f7..ae27191648140306178f9bf2ea5e48f6f9f02860 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt @@ -5,17 +5,28 @@ package org.mozilla.fenix.components import android.content.Context +import android.content.Intent +import android.net.Uri import mozilla.components.service.nimbus.NimbusApi +import mozilla.components.service.nimbus.NimbusDisabled import mozilla.components.service.nimbus.messaging.FxNimbusMessaging +import mozilla.components.service.nimbus.messaging.Message +import mozilla.components.service.nimbus.messaging.Message.Metadata +import mozilla.components.service.nimbus.messaging.MessageData +import mozilla.components.service.nimbus.messaging.MessageMetadataStorage +import mozilla.components.service.nimbus.messaging.MessageSurfaceId import mozilla.components.service.nimbus.messaging.NimbusMessagingController import mozilla.components.service.nimbus.messaging.NimbusMessagingControllerInterface import mozilla.components.service.nimbus.messaging.NimbusMessagingStorage import mozilla.components.service.nimbus.messaging.OnDiskMessageMetadataStorage +import mozilla.components.service.nimbus.messaging.StyleData import org.mozilla.experiments.nimbus.NimbusEventStore import org.mozilla.experiments.nimbus.NimbusMessagingHelperInterface +import org.mozilla.experiments.nimbus.NullNimbus import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.experiments.createNimbus import org.mozilla.fenix.messaging.CustomAttributeProvider +import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.perf.lazyMonitored /** @@ -28,7 +39,14 @@ class NimbusComponents(private val context: Context) { * should be mediated through a FML generated class, e.g. [FxNimbus]. */ val sdk: NimbusApi by lazyMonitored { - createNimbus(context, BuildConfig.NIMBUS_ENDPOINT) + if (BuildConfig.DATA_COLLECTION_DISABLED) { + NimbusDisabled(context) + } else { + createNimbus(context, BuildConfig.NIMBUS_ENDPOINT).also { api -> + FxNimbus.api = api + } + } + } /** @@ -44,7 +62,8 @@ class NimbusComponents(private val context: Context) { * the JEXL helper available from [createJexlHelper]. */ val events: NimbusEventStore by lazyMonitored { - sdk.events + NullNimbus(context) + //sdk.events } /** @@ -78,7 +97,7 @@ class NimbusComponents(private val context: Context) { * from the Nimbus Messaging component. */ val messaging: NimbusMessagingControllerInterface by lazyMonitored { - NimbusMessagingController( + NullNimbusMessagingController( messagingStorage = messagingStorage, deepLinkScheme = BuildConfig.DEEP_LINK_SCHEME, ) @@ -92,10 +111,132 @@ class NimbusComponents(private val context: Context) { private val messagingStorage by lazyMonitored { NimbusMessagingStorage( context = context, - metadataStorage = OnDiskMessageMetadataStorage(context), + metadataStorage = NullMessageMetadataStorage(), //OnDiskMessageMetadataStorage(context), nimbus = sdk, messagingFeature = FxNimbusMessaging.features.messaging, attributeProvider = CustomAttributeProvider, ) } } +// Noop impl of MessageMetadataStorage to replace OnDiskMessageMetadataStorage +class NullMessageMetadataStorage(): MessageMetadataStorage { + override suspend fun getMetadata(): Map<String, Message.Metadata> { + var metadataMap: MutableMap<String, Message.Metadata> = hashMapOf() + return metadataMap + } + + override suspend fun addMetadata(metadata: Message.Metadata): Message.Metadata { + return metadata + } + + override suspend fun updateMetadata(metadata: Message.Metadata) { + // noop + } +} + +class NullNimbusMessagingController( + messagingStorage: NimbusMessagingStorage, + deepLinkScheme: String, +) : NimbusMessagingController(messagingStorage, deepLinkScheme) { + + private val nullMessage: Message = Message( + id = "", + data = MessageData(), + action = "", + style = StyleData(), + triggerIfAll = listOf(), + excludeIfAny = listOf(), + metadata = Metadata(""), + ) + + override suspend fun onMessageDisplayed(displayedMessage: Message, bootIdentifier: String?): Message { + return nullMessage + } + + /** + * Called when a message has been dismissed by the user. + * + * Records a messageDismissed event, and records that the message + * has been dismissed. + */ + override suspend fun onMessageDismissed(message: Message) { + return + } + + /** + * Called when a microsurvey attached to a message has been completed by the user. + * + * @param message The message containing the microsurvey that was completed. + * @param answer The user's response to the microsurvey question. + */ + override suspend fun onMicrosurveyCompleted(message: Message, answer: String) { + return + } + + /** + * Called once the user has clicked on a message. + * + * This records that the message has been clicked on, but does not record a + * glean event. That should be done via [processMessageActionToUri]. + */ + override suspend fun onMessageClicked(message: Message) { + return + } + + /** + * Create and return the relevant [Intent] for the given [Message]. + * + * @param message the [Message] to create the [Intent] for. + * @return an [Intent] using the processed [Message]. + */ + override fun getIntentForMessage(message: Message) = Intent() + + /** + * Will attempt to get the [Message] for the given [id]. + * + * @param id the [Message.id] of the [Message] to try to match. + * @return the [Message] with a matching [id], or null if no [Message] has a matching [id]. + */ + override suspend fun getMessage(id: String): Message? { + return nullMessage + } + + /** + * The [message] action needs to be examined for string substitutions + * and any `uuid` needs to be recorded in the Glean event. + * + * We call this `process` as it has a side effect of logging a Glean event while it + * creates a URI string for the message action. + */ + override fun processMessageActionToUri(message: Message): Uri { + return Uri.EMPTY + } + + override fun sendDismissedMessageTelemetry(messageId: String) { + return + } + + override fun sendShownMessageTelemetry(messageId: String) { + return + } + + override fun sendExpiredMessageTelemetry(messageId: String) { + return + } + + override fun sendClickedMessageTelemetry(messageId: String, uuid: String?) { + return + } + + override fun sendMicrosurveyCompletedTelemetry(messageId: String, answer: String) { + return + } + + override fun convertActionIntoDeepLinkSchemeUri(action: String): Uri = Uri.EMPTY + + override suspend fun getMessages(): List<Message> = listOf() + + override suspend fun getNextMessage(surfaceId: MessageSurfaceId) = nullMessage + + override fun getNextMessage(surfaceId: MessageSurfaceId, messages: List<Message>) = nullMessage +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt index 9ed2abdcae25a58a8a585681a6437bb34428f83e..222500d3afa2aecd4dcdc21d67256bc385e1b3f7 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt @@ -112,7 +112,7 @@ class NotificationManager(private val context: Context) { val extras = bundleOf(TOTAL_TABS_CLOSED_EXTRA to totalCount) addExtras(extras) - setSmallIcon(R.drawable.ic_status_logo) + setSmallIcon(R.drawable.mozac_lib_crash_notification) setWhen(System.currentTimeMillis()) setAutoCancel(true) setDefaults(Notification.DEFAULT_VIBRATE or Notification.DEFAULT_SOUND) @@ -145,7 +145,7 @@ class NotificationManager(private val context: Context) { PendingIntent.getActivity(context, 0, intent, showReceivedTabsIntentFlags) val builder = NotificationCompat.Builder(context, RECEIVE_TABS_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_status_logo) + .setSmallIcon(R.drawable.mozac_lib_crash_notification) .setSendTabTitle(context, device, tab) .setWhen(System.currentTimeMillis()) .setContentText(tab.url) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/TorBrowserFeatures.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/TorBrowserFeatures.kt new file mode 100644 index 0000000000000000000000000000000000000000..47d06dd4910e1c864d51d381f30fb021205dc0e6 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/TorBrowserFeatures.kt @@ -0,0 +1,172 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Copyright (c) 2020, The Tor Project, Inc. + +package org.mozilla.fenix.components + +import android.os.StrictMode +import android.content.Context +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.IOException +import mozilla.components.concept.engine.webextension.WebExtension +import mozilla.components.concept.engine.webextension.WebExtensionRuntime +import mozilla.components.support.webextensions.WebExtensionSupport +import mozilla.components.support.base.log.logger.Logger +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.tor.TorEvents + +object TorBrowserFeatures { + private val logger = Logger("torbrowser-features") + private const val NOSCRIPT_ID = "{73a6fe31-595d-460b-a920-fcc0f8843232}" + + private fun installNoScript( + context: Context, + runtime: WebExtensionRuntime, + onSuccess: ((WebExtension) -> Unit), + onError: ((Throwable) -> Unit) + ) { + /** + * Copy the xpi from assets to cacheDir, we do not care if the file is later deleted. + */ + val xpiName = "$NOSCRIPT_ID.xpi" + val addonPath = context.cacheDir.resolve(xpiName) + val policy = StrictMode.getThreadPolicy() + try { + context.assets.open("extensions/$xpiName") + .use { inStream -> + // we don't want penaltyDeath() on disk write + StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX) + + addonPath.outputStream().use { outStream -> + inStream.copyTo(outStream) + } + } + } catch (throwable: IOException) { + onError(throwable) + return + } finally { + StrictMode.setThreadPolicy(policy) + } + + /** + * Install with a file:// URI pointing to the temp location where the addon was copied to. + */ + runtime.installWebExtension( + url = addonPath.toURI().toString(), + onSuccess = { extension -> + runtime.setAllowedInPrivateBrowsing( + extension, + true, + onSuccess, + onError + ) + }, + onError = { throwable -> onError(throwable) }) + } + + @OptIn(DelicateCoroutinesApi::class) // GlobalScope usage + private fun uninstallHTTPSEverywhere( + runtime: WebExtensionRuntime, + onSuccess: (() -> Unit), + onError: ((Throwable) -> Unit) + ) { + // Wait for WebExtensionSupport on the I/O thread to avoid deadlocks. + GlobalScope.launch(Dispatchers.IO) { + WebExtensionSupport.awaitInitialization() + // Back to the main thread. + withContext(Dispatchers.Main) { + val extension = + WebExtensionSupport.installedExtensions["https-everywhere-eff@eff.org"] + ?: return@withContext onSuccess() // Fine, nothing to uninstall. + runtime.uninstallWebExtension( + extension, + onSuccess = onSuccess, + onError = { _, throwable -> onError(throwable) } + ) + } + } + } + + fun install(context: Context, runtime: WebExtensionRuntime) { + val settings = context.settings() + /** + * Remove HTTPS Everywhere if we didn't yet. + */ + if (!settings.httpsEverywhereRemoved) { + /** + * Ensure HTTPS-Only is enabled. + */ + settings.shouldUseHttpsOnly = true + settings.shouldUseHttpsOnlyInAllTabs = true + uninstallHTTPSEverywhere( + runtime, + onSuccess = { + settings.httpsEverywhereRemoved = true + logger.debug("HTTPS Everywhere extension was uninstalled successfully") + }, + onError = { throwable -> + logger.error("Could not uninstall HTTPS Everywhere extension", throwable) + } + ) + } + /** + * Install NoScript as a user WebExtension if we have not already done so. + * AMO signature is checked, but automatic updates still need to be enabled. + */ + if (!settings.noscriptInstalled) { + installNoScript( + context, + runtime, + onSuccess = { + settings.noscriptInstalled = true + logger.debug("NoScript extension was installed successfully") + }, + onError = { throwable -> + logger.error("Could not install NoScript extension", throwable) + } + ) + } + + /** + * Enable automatic updates for NoScript and, if we've not done it yet, force a + * one-time immediate update check, in order to upgrade old profiles and ensure we've got + * the latest stable AMO version available on first startup. + * We will do it as soon as the Tor is connected, to prevent early addonUpdater activation + * causing automatic update checks failures (components.addonUpdater being a lazy prop). + * The extension, from then on, should behave as if the user had installed it manually. + */ + context.components.torController.registerTorListener(object : TorEvents { + override fun onTorConnected() { + context.components.torController.unregisterTorListener(this) + // Enable automatic updates. This must be done on every startup (tor-browser#42353) + context.components.addonUpdater.registerForFutureUpdates(NOSCRIPT_ID) + // Force a one-time immediate update check for older installations + if (settings.noscriptUpdated < 2) { + context.components.addonUpdater.update(NOSCRIPT_ID) + settings.noscriptUpdated = 2 + } + } + + @SuppressWarnings("EmptyFunctionBlock") + override fun onTorConnecting() { + } + + @SuppressWarnings("EmptyFunctionBlock") + override fun onTorStopped() { + } + + @SuppressWarnings("EmptyFunctionBlock") + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { + } + }) + } + + +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/UseCases.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/UseCases.kt index a8a140e11c6bdd544021da7be662cec8e7fe7487..bb4886bb98cb722034af9c720712008cc60b311c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/UseCases.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/UseCases.kt @@ -76,6 +76,7 @@ class UseCases( store, tabsUseCases, sessionUseCases, + engine.settings, ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/middleware/MenuNavigationMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/middleware/MenuNavigationMiddleware.kt index e825dfdc339cf47729889cb7e6df8d5bc5530967..85f7b01fac37336faa460c45b5f898cfdd8aa935 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/middleware/MenuNavigationMiddleware.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/middleware/MenuNavigationMiddleware.kt @@ -140,7 +140,7 @@ class MenuNavigationMiddleware( ) is MenuAction.Navigate.ReleaseNotes -> openToBrowser( - BrowserNavigationParams(url = SupportUtils.WHATS_NEW_URL), + BrowserNavigationParams(url = SupportUtils.getTorWhatsNewUrl()), ) is MenuAction.Navigate.Tools -> navHostController.navigate(route = TOOLS_MENU_ROUTE) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt index b58ac2caff2f4f65f663a27f6b0a93e18bc4233b..238ac344c8328b494a632c5cfca33efe0e6098c9 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt @@ -8,11 +8,6 @@ import android.app.Activity import android.app.Application import android.os.Bundle import android.util.Log -import com.adjust.sdk.Adjust -import com.adjust.sdk.AdjustConfig -import com.adjust.sdk.AdjustEvent -import com.adjust.sdk.Constants.ADJUST_PREINSTALL_SYSTEM_PROPERTY_PATH -import com.adjust.sdk.LogLevel import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -33,84 +28,16 @@ class AdjustMetricsService( override val type = MetricServiceType.Marketing override fun start() { - if ((BuildConfig.ADJUST_TOKEN.isNullOrBlank())) { - Log.i(LOGTAG, "No adjust token defined") - - if (Config.channel.isReleased) { - throw IllegalStateException("No adjust token defined for release build") - } - - return - } - - System.setProperty(ADJUST_PREINSTALL_SYSTEM_PROPERTY_PATH, "/preload/etc/adjust.preinstall") - - val config = AdjustConfig( - application, - BuildConfig.ADJUST_TOKEN, - AdjustConfig.ENVIRONMENT_PRODUCTION, - true, - ) - config.setPreinstallTrackingEnabled(true) - - val installationPing = FirstSessionPing(application) - - FirstSession.adjustAttributionTimespan.start() - val timerId = FirstSession.adjustAttributionTime.start() - config.setOnAttributionChangedListener { - if (!installationPing.wasAlreadyTriggered()) { - FirstSession.adjustAttributionTimespan.stop() - } - - FirstSession.adjustAttributionTime.stopAndAccumulate(timerId) - if (!it.network.isNullOrEmpty()) { - application.applicationContext.settings().adjustNetwork = - it.network - } - if (!it.adgroup.isNullOrEmpty()) { - application.applicationContext.settings().adjustAdGroup = - it.adgroup - } - if (!it.creative.isNullOrEmpty()) { - application.applicationContext.settings().adjustCreative = - it.creative - } - if (!it.campaign.isNullOrEmpty()) { - application.applicationContext.settings().adjustCampaignId = - it.campaign - } - - installationPing.checkAndSend() - } - - config.setLogLevel(LogLevel.SUPRESS) - Adjust.onCreate(config) - Adjust.setEnabled(true) - application.registerActivityLifecycleCallbacks(AdjustLifecycleCallbacks()) + /* noop */ } override fun stop() { - FirstSession.adjustAttributionTimespan.cancel() - Adjust.setEnabled(false) - Adjust.gdprForgetMe(application.applicationContext) + /* noop */ } @Suppress("TooGenericExceptionCaught") override fun track(event: Event) { - CoroutineScope(dispatcher).launch { - try { - if (event is Event.GrowthData) { - if (storage.shouldTrack(event)) { - Adjust.trackEvent(AdjustEvent(event.tokenName)) - storage.updateSentState(event) - } else { - storage.updatePersistentState(event) - } - } - } catch (e: Exception) { - crashReporter.submitCaughtException(e) - } - } + /* noop */ } override fun shouldTrack(event: Event): Boolean = @@ -122,11 +49,11 @@ class AdjustMetricsService( private class AdjustLifecycleCallbacks : Application.ActivityLifecycleCallbacks { override fun onActivityResumed(activity: Activity) { - Adjust.onResume() + /* noop */ } override fun onActivityPaused(activity: Activity) { - Adjust.onPause() + /* noop */ } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { /* noop */ } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index c7c5c64aff0348a57d4b2a119493fda2d9166fea..79e8c18f44d8f6a541167551165346ec535f3c9b 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.components.metrics import android.content.Context import mozilla.components.support.base.log.logger.Logger import mozilla.telemetry.glean.Glean +import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.GleanMetrics.Pings import org.mozilla.fenix.ext.components @@ -35,6 +36,9 @@ private class EventWrapper<T : Enum<T>>( } fun track(event: Event) { + if (BuildConfig.DATA_COLLECTION_DISABLED) { + return + } val extras = if (keyMapper != null) { event.extras?.mapKeys { (key) -> keyMapper.invoke(key.toString().asCamelCase()) @@ -68,6 +72,12 @@ class GleanMetricsService( private val activationPing = ActivationPing(context) override fun start() { + if (BuildConfig.DATA_COLLECTION_DISABLED) { + Logger.debug("Data collection is disabled, not initializing Glean.") + initialized = true + return + } + logger.debug("Enabling Glean.") // Initialization of Glean already happened in FenixApplication. Glean.setUploadEnabled(true) @@ -94,10 +104,12 @@ class GleanMetricsService( } override fun track(event: Event) { - event.wrapper?.track(event) + if (!BuildConfig.DATA_COLLECTION_DISABLED) { + event.wrapper?.track(event) + } } override fun shouldTrack(event: Event): Boolean { - return event.wrapper != null + return !BuildConfig.DATA_COLLECTION_DISABLED && event.wrapper != null } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index bb5aaccb388cab3fab6ed0ce181a1b1fa84373eb..76917cf96898d21c15d7a298cea9d73e615b0ab6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -532,10 +532,11 @@ internal class ReleaseMetricController( private fun isInitialized(type: MetricServiceType): Boolean = initialized.contains(type) - private fun isTelemetryEnabled(type: MetricServiceType): Boolean = when (type) { - MetricServiceType.Data -> isDataTelemetryEnabled() - MetricServiceType.Marketing -> isMarketingDataTelemetryEnabled() - } + private fun isTelemetryEnabled(type: MetricServiceType): Boolean = + !BuildConfig.DATA_COLLECTION_DISABLED && when (type) { + MetricServiceType.Data -> isDataTelemetryEnabled() + MetricServiceType.Marketing -> isMarketingDataTelemetryEnabled() + } companion object { /** diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsUtils.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsUtils.kt index fe90ec01e7426f19d3e7d07f115687852b2c4890..3838abafa7abb4db50bca28ee8315dbc338adfdc 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsUtils.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsUtils.kt @@ -7,9 +7,6 @@ package org.mozilla.fenix.components.metrics import android.content.Context import android.util.Base64 import androidx.annotation.VisibleForTesting -import com.google.android.gms.ads.identifier.AdvertisingIdClient -import com.google.android.gms.common.GooglePlayServicesNotAvailableException -import com.google.android.gms.common.GooglePlayServicesRepairableException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import mozilla.components.browser.state.search.SearchEngine @@ -106,14 +103,8 @@ object MetricsUtils { */ @Suppress("TooGenericExceptionCaught") @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal fun getAdvertisingID(context: Context): String? { + internal fun getAdvertisingID(@Suppress("UNUSED_PARAMETER") context: Context): String? { return try { - AdvertisingIdClient.getAdvertisingIdInfo(context).id - } catch (e: GooglePlayServicesNotAvailableException) { - Logger.debug("getAdvertisingID() - Google Play not installed on the device") - null - } catch (e: GooglePlayServicesRepairableException) { - Logger.debug("getAdvertisingID() - recoverable error connecting to Google Play Services") null } catch (e: IllegalStateException) { // This is unlikely to happen, as this should be running off the main thread. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserMenuSignIn.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserMenuSignIn.kt index 635fc7bcdd0f5da815234c4ed474e32aa45f2b6c..497f3102e2db293a077fce9369dec69aa9d3e0e9 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserMenuSignIn.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserMenuSignIn.kt @@ -26,7 +26,7 @@ import org.mozilla.fenix.ext.components */ class BrowserMenuSignIn( @ColorRes private val textColorResource: Int, - @DrawableRes imageResource: Int = R.drawable.ic_signed_out, + @DrawableRes imageResource: Int = R.drawable.mozac_lib_crash_notification, listener: () -> Unit = {}, ) : BrowserMenuImageText( String(), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarCFRPresenter.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarCFRPresenter.kt index bcb62210ba11c258c2cdd0e9dd5176a86505d61e..9a5ec71ee6781f1f51cd2b61833a152ca96ab524 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarCFRPresenter.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarCFRPresenter.kt @@ -75,49 +75,50 @@ class BrowserToolbarCFRPresenter( */ @Suppress("MagicNumber") fun start() { - when (getCFRToShow()) { - ToolbarCFR.COOKIE_BANNERS -> { - scope = browserStore.flowScoped { flow -> - flow.mapNotNull { it.findCustomTabOrSelectedTab(customTabId) } - .ifAnyChanged { tab -> - arrayOf( - tab.cookieBanner, - ) - } - .filter { - it.content.private && it.cookieBanner == CookieBannerHandlingStatus.HANDLED - } - .collect { - scope?.cancel() - settings.shouldShowCookieBannersCFR = false - showCookieBannersCFR() - } - } - } - - ToolbarCFR.ERASE -> { - scope = browserStore.flowScoped { flow -> - flow - .mapNotNull { it.findCustomTabOrSelectedTab(customTabId) } - .filter { it.content.private } - .map { it.content.progress } - // The "transformWhile" below ensures that the 100% progress is only collected once. - .transformWhile { progress -> - emit(progress) - progress != 100 - } - .filter { popup == null && it == 100 } - .collect { - scope?.cancel() - showEraseCfr() - } - } - } - - ToolbarCFR.NONE -> { - // no-op - } - } +// Removed for tor-browser#42089: Remove ability to submit site support requests +// when (getCFRToShow()) { +// ToolbarCFR.COOKIE_BANNERS -> { +// scope = browserStore.flowScoped { flow -> +// flow.mapNotNull { it.findCustomTabOrSelectedTab(customTabId) } +// .ifAnyChanged { tab -> +// arrayOf( +// tab.cookieBanner, +// ) +// } +// .filter { +// it.content.private && it.cookieBanner == CookieBannerHandlingStatus.HANDLED +// } +// .collect { +// scope?.cancel() +// settings.shouldShowCookieBannersCFR = false +// showCookieBannersCFR() +// } +// } +// } +// +// ToolbarCFR.ERASE -> { +// scope = browserStore.flowScoped { flow -> +// flow +// .mapNotNull { it.findCustomTabOrSelectedTab(customTabId) } +// .filter { it.content.private } +// .map { it.content.progress } +// // The "transformWhile" below ensures that the 100% progress is only collected once. +// .transformWhile { progress -> +// emit(progress) +// progress != 100 +// } +// .filter { popup == null && it == 100 } +// .collect { +// scope?.cancel() +// showEraseCfr() +// } +// } +// } +// +// ToolbarCFR.NONE -> { +// // no-op +// } +// } } private fun getCFRToShow(): ToolbarCFR = when { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt index 0345868ef2c5e76926db090a8164c3a32ea86aac..ab66c134fa411772038d5b375347f88b2fc6184f 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.appservices.places.BookmarkRoot +import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.browser.state.action.EngineAction import mozilla.components.browser.state.ext.getUrl import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab @@ -401,6 +402,13 @@ class DefaultBrowserToolbarMenuController( BrowserFragmentDirections.actionBrowserFragmentToTranslationsDialogFragment() navController.navigateSafe(R.id.browserFragment, directions) } + + ToolbarMenu.Item.NewTorCircuit -> { + currentSession?.let { + sessionUseCases.reload.invoke(it.id) + (it.engineState.engineSession as GeckoEngineSession).newTorCircuit() + } + } } } @@ -484,6 +492,10 @@ class DefaultBrowserToolbarMenuController( "translate", ), ) + + ToolbarMenu.Item.NewTorCircuit -> { + /* Tor doesn't use telemetry and therefore this doesn't need to be implemented */ + } } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index f22be81592d8149a6b67a90fb03a07e55522baf9..601aedd71b4b31513a427753603915df4f1078b4 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -32,7 +32,7 @@ import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.storage.BookmarksStorage import mozilla.components.feature.top.sites.PinnedSiteStorage -import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature +// import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature import mozilla.components.lib.state.ext.flowScoped import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged @@ -71,7 +71,6 @@ open class DefaultToolbarMenu( private var isCurrentUrlBookmarked = false private var isBookmarkedJob: Job? = null - private val shouldDeleteDataOnQuit = context.settings().shouldDeleteBrowsingDataOnQuit private val shouldUseBottomToolbar = context.settings().shouldUseBottomToolbar private val shouldShowMenuToolbar = !context.settings().navigationToolbarEnabled private val shouldShowTopSites = context.settings().showTopSitesFeature @@ -212,6 +211,14 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.NewTab) } + private val newCircuitItem = BrowserMenuImageText( + context.getString(R.string.library_new_circuit), + R.drawable.new_circuit, + primaryTextColor(), + ) { + onItemTapped.invoke(ToolbarMenu.Item.NewTorCircuit) + } + private val historyItem = BrowserMenuImageText( context.getString(R.string.library_history), R.drawable.ic_history, @@ -266,12 +273,12 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.RequestDesktop(checked)) } - private val openInRegularTabItem = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_open_in_regular_tab), - imageResource = R.drawable.ic_open_in_regular_tab, - ) { - onItemTapped.invoke(ToolbarMenu.Item.OpenInRegularTab) - } + // private val openInRegularTabItem = BrowserMenuImageText( + // label = context.getString(R.string.browser_menu_open_in_regular_tab), + // imageResource = R.drawable.ic_open_in_regular_tab, + // ) { + // onItemTapped.invoke(ToolbarMenu.Item.OpenInRegularTab) + // } private val customizeReaderView = BrowserMenuImageText( label = context.getString(R.string.browser_menu_customize_reader_view), @@ -294,23 +301,23 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.OpenInApp) } - private val reportSiteIssuePlaceholder = WebExtensionPlaceholderMenuItem( - id = WebCompatReporterFeature.WEBCOMPAT_REPORTER_EXTENSION_ID, - iconTintColorResource = primaryTextColor(), - ) - - private val addToHomeScreenItem = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_add_to_homescreen), - imageResource = R.drawable.mozac_ic_add_to_homescreen_24, - iconTintColorResource = primaryTextColor(), - isCollapsingMenuLimit = true, - ) { - if (context.components.useCases.webAppUseCases.isInstallable()) { - onItemTapped.invoke(ToolbarMenu.Item.InstallPwaToHomeScreen) - } else { - onItemTapped.invoke(ToolbarMenu.Item.AddToHomeScreen) - } - } + //private val reportSiteIssuePlaceholder = WebExtensionPlaceholderMenuItem( + // id = WebCompatReporterFeature.WEBCOMPAT_REPORTER_EXTENSION_ID, + // iconTintColorResource = primaryTextColor(), + //) + + //private val addToHomeScreenItem = BrowserMenuImageText( + // label = context.getString(R.string.browser_menu_add_to_homescreen), + // imageResource = R.drawable.mozac_ic_add_to_homescreen_24, + // iconTintColorResource = primaryTextColor(), + // isCollapsingMenuLimit = true, + //) { + // if (context.components.useCases.webAppUseCases.isInstallable()) { + // onItemTapped.invoke(ToolbarMenu.Item.InstallPwaToHomeScreen) + // } else { + // onItemTapped.invoke(ToolbarMenu.Item.AddToHomeScreen) + // } + //} private val addRemoveTopSitesItem = TwoStateBrowserMenuImageText( primaryLabel = context.getString(R.string.browser_menu_add_to_shortcuts), @@ -330,13 +337,13 @@ open class DefaultToolbarMenu( }, ) - private val saveToCollectionItem = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_save_to_collection_2), - imageResource = R.drawable.ic_tab_collection, - iconTintColorResource = primaryTextColor(), - ) { - onItemTapped.invoke(ToolbarMenu.Item.SaveToCollection) - } + //private val saveToCollectionItem = BrowserMenuImageText( + // label = context.getString(R.string.browser_menu_save_to_collection_2), + // imageResource = R.drawable.ic_tab_collection, + // iconTintColorResource = primaryTextColor(), + //) { + // onItemTapped.invoke(ToolbarMenu.Item.SaveToCollection) + //} private val printPageItem = BrowserMenuImageText( label = context.getString(R.string.menu_print), @@ -361,7 +368,7 @@ open class DefaultToolbarMenu( primaryTextColor() }, highlight = BrowserMenuHighlight.HighPriority( - endImageResource = R.drawable.ic_sync_disconnected, + endImageResource = R.drawable.mozac_lib_crash_notification, backgroundTint = context.getColorFromAttr(R.attr.syncDisconnectedBackground), canPropagate = false, ), @@ -395,13 +402,13 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.Quit) } - private fun syncMenuItem(): BrowserMenuItem { - return BrowserMenuSignIn(primaryTextColor()) { - onItemTapped.invoke( - ToolbarMenu.Item.SyncAccount(accountManager.accountState), - ) - } - } + //private fun syncMenuItem(): BrowserMenuItem { + // return BrowserMenuSignIn(primaryTextColor()) { + // onItemTapped.invoke( + // ToolbarMenu.Item.SyncAccount(accountManager.accountState), + // ) + // } + //} @VisibleForTesting(otherwise = PRIVATE) val coreMenuItems by lazy { @@ -410,28 +417,30 @@ open class DefaultToolbarMenu( if (shouldUseBottomToolbar || !shouldShowMenuToolbar) null else menuToolbar, newTabItem, BrowserMenuDivider(), + newCircuitItem, + BrowserMenuDivider(), bookmarksItem, - historyItem, + if (context.settings().shouldDisableNormalMode) null else historyItem, downloadsItem, passwordsItem, extensionsItem, - syncMenuItem(), + // syncMenuItem(), BrowserMenuDivider(), findInPageItem, translationsItem.apply { visible = ::shouldShowTranslations }, desktopSiteItem, - openInRegularTabItem.apply { visible = ::shouldShowOpenInRegularTab }, + // openInRegularTabItem.apply { visible = ::shouldShowOpenInRegularTab }, customizeReaderView.apply { visible = ::shouldShowReaderViewCustomization }, - openInApp.apply { visible = ::shouldShowOpenInApp }, - reportSiteIssuePlaceholder, + // openInApp.apply { visible = ::shouldShowOpenInApp }, + // reportSiteIssuePlaceholder, BrowserMenuDivider(), - addToHomeScreenItem.apply { visible = ::canAddToHomescreen }, - if (shouldShowTopSites) addRemoveTopSitesItem else null, - saveToCollectionItem, - if (FxNimbus.features.print.value().browserPrintEnabled) printPageItem else null, + // addToHomeScreenItem.apply { visible = ::canAddToHomescreen }, + // if (shouldShowTopSites) addRemoveTopSitesItem else null, + // saveToCollectionItem, + printPageItem, BrowserMenuDivider(), settingsItem, - if (shouldDeleteDataOnQuit) deleteDataOnQuit else null, + deleteDataOnQuit, if (shouldUseBottomToolbar) BrowserMenuDivider() else null, if (shouldUseBottomToolbar && shouldShowMenuToolbar) menuToolbar else null, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt index ebffb049091144b368d5fae251783c73615d0784..af089ea09334f97e7c243fc11c2460c0ad556d3d 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt @@ -55,6 +55,7 @@ interface ToolbarMenu { object Passwords : Item() object Downloads : Item() object NewTab : Item() + object NewTorCircuit : Item() } val menuBuilder: BrowserMenuBuilder diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt index ca4fec486ae2bd368b84e5f1a197fa8e9a0bebd7..6da42d8a92302c5cbb536d788038b5a54d9f438b 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt @@ -128,7 +128,7 @@ class CustomTabToolbarMenu( sharePage.apply { visible = { isNavBarEnabled && !isSandboxCustomTab } }, desktopMode, findInPage, - openInApp.apply { visible = ::shouldShowOpenInApp }, +// openInApp.apply { visible = ::shouldShowOpenInApp }, openInFenix.apply { visible = { !isSandboxCustomTab && !isNavBarEnabled } }, BrowserMenuDivider(), if (shouldShowMenuToolbar) menuToolbar else null, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt index 8c208d5ff5617c75b09ab8d92eb57de8fb73b8ab..4c3d94b8536c7217667bb79e69fd5a9321a184b0 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt @@ -59,7 +59,7 @@ class PoweredByNotification( with(applicationContext) { val appName = getString(R.string.app_name) return NotificationCompat.Builder(this, channelId) - .setSmallIcon(R.drawable.ic_status_logo) + .setSmallIcon(R.drawable.mozac_lib_crash_notification) .setContentTitle(applicationContext.getString(R.string.browser_menu_powered_by2, appName)) .setBadgeIconType(BADGE_ICON_NONE) .setColor(ContextCompat.getColor(this, R.color.primary_text_light_theme)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/dialog/DynamicDownloadDialog.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/dialog/DynamicDownloadDialog.kt index 8b67abe5a5e7b7cfc0455ee68715b8d468d7eb47..b75007523d27221e7c9f843e331b99a080bd0a0c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/dialog/DynamicDownloadDialog.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/dialog/DynamicDownloadDialog.kt @@ -60,6 +60,7 @@ class DynamicDownloadDialog( ) binding.downloadDialogActionButton.apply { + visibility = View.VISIBLE text = context.getString( mozilla.components.feature.downloads.R.string.mozac_feature_downloads_button_try_again, ) @@ -80,6 +81,7 @@ class DynamicDownloadDialog( ) binding.downloadDialogActionButton.apply { + visibility = View.GONE text = context.getString( mozilla.components.feature.downloads.R.string.mozac_feature_downloads_button_open, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/view/ResearchSurfaceSurvey.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/view/ResearchSurfaceSurvey.kt index f413162cf5d1feec9455aa45ed35fec67a634b9d..a937bd472c0291f9c6333e6dc7f89f031fc82de6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/view/ResearchSurfaceSurvey.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/view/ResearchSurfaceSurvey.kt @@ -119,10 +119,11 @@ fun ResearchSurfaceSurvey( modifier = Modifier.padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Image( - painter = painterResource(R.drawable.ic_firefox), - contentDescription = null, - ) +// Removed as part of tor-browser#42386 +// Image( +// painter = painterResource(R.drawable.ic_firefox), +// contentDescription = null, +// ) Spacer(modifier = Modifier.height(16.dp)) Text( text = messageText, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Activity.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Activity.kt index 5556d86219aca38221a28e80175ee9e9c26af70c..1a6fe51234ed11fe19a470aa0c14c54aa8e53301 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Activity.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Activity.kt @@ -54,6 +54,7 @@ import org.mozilla.fenix.settings.wallpaper.WallpaperSettingsFragmentDirections import org.mozilla.fenix.share.AddNewDeviceFragmentDirections import org.mozilla.fenix.shopping.ReviewQualityCheckFragmentDirections import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections +import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections import org.mozilla.fenix.translations.TranslationsDialogFragmentDirections import org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguagesPreferenceFragmentDirections @@ -331,6 +332,9 @@ private fun getHomeNavDirections( BrowserDirection.FromDownloadLanguagesPreferenceFragment -> DownloadLanguagesPreferenceFragmentDirections.actionGlobalBrowser() + + BrowserDirection.FromTorConnectionAssistFragment -> + TorConnectionAssistFragmentDirections.actionGlobalBrowser() } const val REQUEST_CODE_BROWSER_ROLE = 1 diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt index 158218bbfe967862273c5362b9fd0f3d294f7b5c..b61c4b5318e217472a4165011656e53764072be5 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt @@ -15,6 +15,7 @@ import mozilla.components.experiment.NimbusExperimentDelegate import mozilla.components.lib.crash.handler.CrashHandlerService import mozilla.components.service.sync.autofill.GeckoCreditCardsAddressesStorageDelegate import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate +import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -139,6 +140,7 @@ object GeckoProvider { .extensionsWebAPIEnabled(true) .translationsOfferPopup(context.settings().offerTranslation) .disableShip(FxNimbus.features.ship.value().disabled) + .supportedLocales(BuildConfig.SUPPORTED_LOCALE_ARRAY.toList()) .build() } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index df3d50af622f46bc3b7e1dce105327c449fd0170..3a9e0e9de1ff717531c414aeb007ac0b8ed62b2a 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -42,6 +42,9 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat.getColor import androidx.core.content.res.ResourcesCompat +import androidx.core.view.children +import androidx.core.view.doOnLayout +import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -89,11 +92,13 @@ import mozilla.components.feature.top.sites.TopSitesProviderConfig import mozilla.components.lib.state.ext.consumeFlow import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.lib.state.ext.observeAsState +import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.ui.colors.PhotonColors import mozilla.components.ui.tabcounter.TabCounterMenu import mozilla.telemetry.glean.private.NoExtras import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.GleanMetrics.HomeScreen import org.mozilla.fenix.GleanMetrics.Homepage import org.mozilla.fenix.GleanMetrics.NavigationBar @@ -175,6 +180,9 @@ import org.mozilla.fenix.snackbar.SnackbarBinding import org.mozilla.fenix.tabstray.Page import org.mozilla.fenix.tabstray.TabsTrayAccessPoint import org.mozilla.fenix.theme.FirefoxTheme +import org.mozilla.fenix.tor.TorBootstrapFragmentDirections +import org.mozilla.fenix.tor.TorBootstrapStatus +import org.mozilla.fenix.tor.TorConnectionAssistViewModel import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.wallpapers.Wallpaper @@ -182,7 +190,7 @@ import java.lang.ref.WeakReference import org.mozilla.fenix.GleanMetrics.TabStrip as TabStripMetrics @Suppress("TooManyFunctions", "LargeClass") -class HomeFragment : Fragment() { +class HomeFragment : Fragment(), UserInteractionHandler { private val args by navArgs<HomeFragmentArgs>() @VisibleForTesting @@ -195,6 +203,7 @@ class HomeFragment : Fragment() { private val snackbarBinding = ViewBoundFeatureWrapper<SnackbarBinding>() private val homeViewModel: HomeScreenViewModel by activityViewModels() + private val torConnectionAssistViewModel: TorConnectionAssistViewModel by activityViewModels() private var _bottomToolbarContainerView: BottomToolbarContainerView? = null private val bottomToolbarContainerView: BottomToolbarContainerView @@ -272,6 +281,8 @@ class HomeFragment : Fragment() { private val bottomToolbarContainerIntegration = ViewBoundFeatureWrapper<BottomToolbarContainerIntegration>() private val homeScreenPopupManager = ViewBoundFeatureWrapper<HomeScreenPopupManager>() + private lateinit var torBootstrapStatus: TorBootstrapStatus + override fun onCreate(savedInstanceState: Bundle?) { // DO NOT ADD ANYTHING ABOVE THIS getProfilerTime CALL! val profilerStartTime = requireComponents.core.engine.profiler?.getProfilerTime() @@ -304,6 +315,12 @@ class HomeFragment : Fragment() { val activity = activity as HomeActivity val components = requireComponents + torBootstrapStatus = TorBootstrapStatus( + !BuildConfig.DISABLE_TOR, + components.torController, + ::dispatchModeChanges + ) + val currentWallpaperName = requireContext().settings().currentWallpaperName applyWallpaper( wallpaperName = currentWallpaperName, @@ -311,6 +328,16 @@ class HomeFragment : Fragment() { orientation = requireContext().resources.configuration.orientation, ) + // Splits by full stops or commas and puts the parts in different lines. + // Ignoring separators at the end of the string, it is expected + // that there are at most two parts (e.g. "Explore. Privately."). + val localBinding = binding + binding.exploreprivately.text = localBinding + .exploreprivately + .text + ?.replace(" *([.,。।]) *".toRegex(), "$1\n") + ?.trim() + components.appStore.dispatch(AppAction.ModeChange(browsingModeManager.mode)) lifecycleScope.launch(IO) { @@ -527,7 +554,7 @@ class HomeFragment : Fragment() { activity.themeManager.applyStatusBarTheme(activity) - FxNimbus.features.homescreen.recordExposure() + // FxNimbus.features.homescreen.recordExposure() // DO NOT MOVE ANYTHING BELOW THIS addMarker CALL! requireComponents.core.engine.profiler?.addMarker( @@ -1044,6 +1071,8 @@ class HomeFragment : Fragment() { Homepage.privateModeIconTapped.record(mozilla.telemetry.glean.private.NoExtras()) } + binding.privateBrowsingButton.isGone = view.context.settings().shouldDisableNormalMode + consumeFrom(requireComponents.core.store) { toolbarView?.updateTabCounter(it) showCollectionsPlaceholder(it) @@ -1129,6 +1158,17 @@ class HomeFragment : Fragment() { view = view, ) + torConnectionAssistViewModel.urlToLoadAfterConnecting.also { + if(!it.isNullOrBlank()){ + (requireActivity() as HomeActivity).openToBrowserAndLoad( + searchTermOrURL = it, + newTab = true, + from = BrowserDirection.FromHome, + ) + torConnectionAssistViewModel.urlToLoadAfterConnecting = null // Only load this url once + } + } + // DO NOT MOVE ANYTHING BELOW THIS addMarker CALL! requireComponents.core.engine.profiler?.addMarker( MarkersFragmentLifecycleCallbacks.MARKER_NAME, @@ -1279,6 +1319,7 @@ class HomeFragment : Fragment() { override fun onStop() { dismissRecommendPrivateBrowsingShortcut() super.onStop() + torBootstrapStatus.unregisterTorListener() } override fun onStart() { @@ -1329,6 +1370,15 @@ class HomeFragment : Fragment() { } } + private fun dispatchModeChanges(isBootstrapping: Boolean) { + if (isBootstrapping) { + val directions = + TorBootstrapFragmentDirections + .actionStartupTorbootstrap() + findNavController().navigate(directions) + } + } + @VisibleForTesting internal fun removeCollectionWithUndo(tabCollection: TabCollection) { val snackbarMessage = getString(R.string.snackbar_collection_deleted) @@ -1351,6 +1401,7 @@ class HomeFragment : Fragment() { override fun onResume() { super.onResume() + torBootstrapStatus.registerTorListener() if (browsingModeManager.mode == BrowsingMode.Private) { activity?.window?.setBackgroundDrawableResource(R.drawable.private_home_background_gradient) } @@ -1583,7 +1634,8 @@ class HomeFragment : Fragment() { else -> ColorStateList.valueOf(color) } - binding.wordmarkText.imageTintList = tintColor + // tor-browser#42590 + // binding.wordmarkText.imageTintList = tintColor binding.privateBrowsingButton.imageTintList = tintColor } @@ -1632,4 +1684,9 @@ class HomeFragment : Fragment() { // Elevation for undo toasts internal const val TOAST_ELEVATION = 80f } + + override fun onBackPressed(): Boolean { + requireActivity().finish() + return true + } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index 93b9518b5a45cb6fa2748fc8aa9fed94a94fabdf..efaf2b4cab288e5f1d2cc31d2429da52f7df4040 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -63,7 +63,7 @@ class HomeMenu( object ManageAccountAndDevices : Item() object WhatsNew : Item() object Help : Item() - object CustomizeHome : Item() +// object CustomizeHome : Item() object Settings : Item() object Quit : Item() object ReconnectSync : Item() @@ -82,7 +82,7 @@ class HomeMenu( private val reconnectToSyncItem by lazy { BrowserMenuHighlightableItem( context.getString(R.string.sync_reconnect), - R.drawable.ic_sync_disconnected, + R.drawable.mozac_lib_crash_notification, iconTintColorResource = syncDisconnectedColor, textColorResource = primaryTextColor, highlight = BrowserMenuHighlight.HighPriority( @@ -121,7 +121,7 @@ class HomeMenu( @Suppress("ComplexMethod") private fun coreMenuItems(): List<BrowserMenuItem> { - val settings = context.components.settings + // val settings = context.components.settings val bookmarksItem = BrowserMenuImageText( context.getString(R.string.library_bookmarks), @@ -155,13 +155,13 @@ class HomeMenu( onItemTapped.invoke(Item.Passwords) } - val extensionsItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_extensions), - R.drawable.ic_addons_extensions, - primaryTextColor, - ) { - onItemTapped.invoke(Item.Extensions) - } +// val extensionsItem = BrowserMenuImageText( +// context.getString(R.string.browser_menu_extensions), +// R.drawable.ic_addons_extensions, +// primaryTextColor, +// ) { +// onItemTapped.invoke(Item.Extensions) +// } val manageAccountAndDevicesItem = SimpleBrowserMenuItem( context.getString(R.string.browser_menu_manage_account_and_devices), @@ -190,19 +190,19 @@ class HomeMenu( onItemTapped.invoke(Item.Help) } - val customizeHomeItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_customize_home_1), - R.drawable.ic_customize, - primaryTextColor, - ) { - onItemTapped.invoke(Item.CustomizeHome) - AppMenu.customizeHomepage.record(NoExtras()) - } +// val customizeHomeItem = BrowserMenuImageText( +// context.getString(R.string.browser_menu_customize_home_1), +// R.drawable.ic_customize, +// primaryTextColor, +// ) { +// onItemTapped.invoke(Item.CustomizeHome) +// AppMenu.customizeHomepage.record(NoExtras()) +// } // Use nimbus to set the icon and title. - val nimbusValidation = FxNimbus.features.nimbusValidation.value() + // val nimbusValidation = FxNimbus.features.nimbusValidation.value() val settingsItem = BrowserMenuImageText( - nimbusValidation.settingsTitle, + context.getString(R.string.browser_menu_settings), R.drawable.mozac_ic_settings_24, primaryTextColor, ) { @@ -224,15 +224,15 @@ class HomeMenu( // We will show syncSignIn item when the accountAuth item: // 1. is not needed or // 2. it is needed, but the account manager is not available yet - val syncSignInMenuItem = if (accountAuthItem == null) syncSignInMenuItem() else null + // val syncSignInMenuItem = if (accountAuthItem == null) syncSignInMenuItem() else null val menuItems = listOfNotNull( bookmarksItem, - historyItem, + if (context.settings().shouldDisableNormalMode) null else historyItem, downloadsItem, passwordsItem, - extensionsItem, - syncSignInMenuItem, + // extensionsItem, + // syncSignInMenuItem, accountAuthItem, if (Config.channel.isMozillaOnline) manageAccountAndDevicesItem else null, BrowserMenuDivider(), @@ -240,9 +240,9 @@ class HomeMenu( BrowserMenuDivider(), whatsNewItem, helpItem, - customizeHomeItem, +// customizeHomeItem, settingsItem, - if (settings.shouldDeleteBrowsingDataOnQuit) quitItem else null, + quitItem ).also { items -> items.getHighlight()?.let { onHighlightPresent(it) } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenuView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenuView.kt index 63e3363393fe2a294c6d2ee896509427a69a6972..7913c879399b52718bc99a7f97d905ebbbd80644 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenuView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenuView.kt @@ -122,14 +122,14 @@ class HomeMenuView( HomeFragmentDirections.actionGlobalSettingsFragment(), ) } - HomeMenu.Item.CustomizeHome -> { - HomeScreen.customizeHomeClicked.record(NoExtras()) - - navController.nav( - R.id.homeFragment, - HomeFragmentDirections.actionGlobalHomeSettingsFragment(), - ) - } +// HomeMenu.Item.CustomizeHome -> { +// HomeScreen.customizeHomeClicked.record(NoExtras()) +// +// navController.nav( +// R.id.homeFragment, +// HomeFragmentDirections.actionGlobalHomeSettingsFragment(), +// ) +// } is HomeMenu.Item.SyncAccount -> { navController.nav( R.id.homeFragment, @@ -186,10 +186,7 @@ class HomeMenuView( HomeMenu.Item.Help -> { HomeMenuMetrics.helpTapped.record(NoExtras()) homeActivity.openToBrowserAndLoad( - searchTermOrURL = SupportUtils.getSumoURLForTopic( - context = context, - topic = SupportUtils.SumoTopic.HELP, - ), + searchTermOrURL = SupportUtils.getTorHelpPageUrl(), newTab = true, from = BrowserDirection.FromHome, ) @@ -199,7 +196,7 @@ class HomeMenuView( Events.whatsNewTapped.record(NoExtras()) homeActivity.openToBrowserAndLoad( - searchTermOrURL = SupportUtils.WHATS_NEW_URL, + searchTermOrURL = SupportUtils.getTorWhatsNewUrl(), newTab = true, from = BrowserDirection.FromHome, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/intent/HomeDeepLinkIntentProcessor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/intent/HomeDeepLinkIntentProcessor.kt index 85a854be3af58b7b4316daf0ea400ee2abbeed6e..0c92f34aaaa491b80b570bd736b8bbdd74eef506 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/intent/HomeDeepLinkIntentProcessor.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/intent/HomeDeepLinkIntentProcessor.kt @@ -93,6 +93,15 @@ class HomeDeepLinkIntentProcessor( logger.info("Not opening deep link: $url") return } + if (BuildConfig.DEEP_LINK_SCHEME.startsWith("torbrowser")) { + // tor-browser#42578 + // TODO: + // Maybe just warn users about linkability but + // give them the choice to open anyway, once + // the other deep link related issues are fixed. + logger.info("Tor Browser rejects open intent deep link: $deepLink") + return + } activity.openToBrowserAndLoad( url, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/PocketStoriesComposables.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/PocketStoriesComposables.kt index 2c4a2b27eccd91b7c93256eb7a5f3ee5323d476c..c643f12a4231bfea5de23070c734f45136004731 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/PocketStoriesComposables.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/PocketStoriesComposables.kt @@ -438,7 +438,7 @@ fun PoweredByPocketHeader( verticalAlignment = Alignment.CenterVertically, ) { Icon( - painter = painterResource(id = R.drawable.pocket_vector), + painter = painterResource(id = R.drawable.mozac_lib_crash_notification), contentDescription = null, // Apply the red tint in code. Otherwise the image is black and white. tint = Color(0xFFEF4056), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt index e16f79d51316389becacc06907f43254bedb285c..6884412a1ddf23dc94624961ff8d57ba6d534fd7 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt @@ -150,7 +150,7 @@ fun RecentSyncedTab( ) } else { Image( - painter = painterResource(R.drawable.ic_synced_tabs), + painter = painterResource(R.drawable.mozac_lib_crash_notification), contentDescription = stringResource( R.string.recent_tabs_synced_device_icon_content_description, ), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/PrivateBrowsingDescriptionViewHolder.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/PrivateBrowsingDescriptionViewHolder.kt index 82b40d286b32042d5bdde7f659c67176b6041ef2..eb2095be8abdb0be1206a5eae17e75128d853744 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/PrivateBrowsingDescriptionViewHolder.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/PrivateBrowsingDescriptionViewHolder.kt @@ -77,49 +77,8 @@ class PrivateBrowsingDescriptionViewHolder( */ @Composable fun PrivateBrowsingDescription( - onLearnMoreClick: () -> Unit, -) { - val interactionSource = remember { MutableInteractionSource() } - - Column( - modifier = Modifier.padding(horizontal = 4.dp), - ) { - Text( - text = stringResource( - R.string.private_browsing_placeholder_description_2, - stringResource(R.string.app_name), - ), - modifier = Modifier.padding(top = 4.dp), - color = FirefoxTheme.colors.textPrimary, - fontSize = 14.sp, - lineHeight = 20.sp, - ) - - // The text is wrapped in a box to increase the tap area. - Box( - modifier = Modifier - .fillMaxWidth() - .height(48.dp) - .clickable( - interactionSource = interactionSource, - indication = null, - onClickLabel = stringResource(R.string.a11y_action_label_read_article), - onClick = onLearnMoreClick, - ), - ) { - Text( - text = stringResource(R.string.private_browsing_common_myths), - modifier = Modifier.padding(top = 10.dp), - style = TextStyle( - color = FirefoxTheme.colors.textPrimary, - fontSize = 14.sp, - textDecoration = TextDecoration.Underline, - textDirection = TextDirection.Content, - ), - ) - } - } -} + @Suppress("UNUSED_PARAMETER") onLearnMoreClick: () -> Unit, +) {} @Composable @Preview diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/PagerIndicator.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/PagerIndicator.kt index 8046ed3dfd4867ea177a1ee1464c95b4bf639870..db8957af31cd3d5e2b3ca3ed9d29b2a15ff2c38b 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/PagerIndicator.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/PagerIndicator.kt @@ -41,7 +41,7 @@ class PagerIndicator : LinearLayout { val isLast = i == size - 1 addView( View(context).apply { - setBackgroundResource(R.drawable.pager_dot) + setBackgroundResource(R.drawable.mozac_lib_crash_notification) isSelected = i == selectedIndex }, LayoutParams(dpToPx(DOT_SIZE_IN_DP), dpToPx(DOT_SIZE_IN_DP)).apply { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt index 251ac766524a1cde65a27d370ad1ce9d372575fb..72eed8dfe4b739e45dc6fafaf5358df7a8099a27 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt @@ -144,7 +144,7 @@ class TopSiteItemViewHolder( } else { when (topSite.url) { SupportUtils.POCKET_TRENDING_URL -> { - binding.faviconImage.setImageDrawable(getDrawable(itemView.context, R.drawable.ic_pocket)) + binding.faviconImage.setImageDrawable(getDrawable(itemView.context, R.drawable.mozac_lib_crash_notification)) } SupportUtils.BAIDU_URL -> { binding.faviconImage.setImageDrawable(getDrawable(itemView.context, R.drawable.ic_baidu)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSites.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSites.kt index 833628484bf1a2797cb4edc33167be858ea409b3..e045e51561a76702f7a80df1d1132bfb4a9753d8 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSites.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/topsites/TopSites.kt @@ -426,7 +426,7 @@ private fun FaviconImage(painter: Painter) { @Composable private fun TopSiteFavicon(url: String, imageUrl: String? = null) { when (url) { - SupportUtils.POCKET_TRENDING_URL -> FaviconImage(painterResource(R.drawable.ic_pocket)) + SupportUtils.POCKET_TRENDING_URL -> FaviconImage(painterResource(R.drawable.mozac_lib_crash_notification)) SupportUtils.BAIDU_URL -> FaviconImage(painterResource(R.drawable.ic_baidu)) SupportUtils.JD_URL -> FaviconImage(painterResource(R.drawable.ic_jd)) SupportUtils.PDD_URL -> FaviconImage(painterResource(R.drawable.ic_pdd)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt index cc29a67b20205285aa1f59a44ada668c712a0234..56ec2d8d5d54091adb2bbbf5a934400dd95684cf 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt @@ -254,17 +254,9 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan if (requireContext().settings().useNewBookmarks) { return } requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) - - val accountManager = requireComponents.backgroundServices.accountManager consumeFrom(bookmarkStore) { bookmarkView.update(it) - - // Only display the sign-in prompt if we're inside of the virtual "Desktop Bookmarks" node. - // Don't want to pester user too much with it, and if there are lots of bookmarks present, - // it'll just get visually lost. Inside of the "Desktop Bookmarks" node, it'll nicely stand-out, - // since there are always only three other items in there. It's also the right place contextually. - bookmarkView.binding.bookmarkFoldersSignIn.isVisible = - it.tree?.guid == BookmarkRoot.Root.id && accountManager.authenticatedAccount() == null + bookmarkView.binding.bookmarkFoldersSignIn.isVisible = false } } @@ -309,6 +301,10 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan } else { inflater.inflate(R.menu.bookmarks_select_multi, menu) + menu.findItem(R.id.open_bookmarks_in_new_tabs_multi_select)?.apply { + isVisible = !requireContext().settings().shouldDisableNormalMode + } + menu.findItem(R.id.delete_bookmarks_multi_select).title = SpannableString(getString(R.string.bookmark_menu_delete_button)).apply { setTextColor(requireContext(), R.attr.textCritical) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt index 58864f750fd3a59f82f8dbbc1649be158e53538f..974cf79faa167016caff5602719d50b6be113462 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt @@ -14,6 +14,7 @@ import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.R import org.mozilla.fenix.ext.bookmarkStorage +import org.mozilla.fenix.ext.settings class BookmarkItemMenu( private val context: Context, @@ -37,6 +38,7 @@ class BookmarkItemMenu( @SuppressWarnings("LongMethod") internal suspend fun menuItems(itemType: BookmarkNodeType, itemId: String): List<TextMenuCandidate> { val hasAtLeastOneChild = !context.bookmarkStorage.getTree(itemId, false)?.children.isNullOrEmpty() + val shouldDisableNormalMode = context.settings().shouldDisableNormalMode return listOfNotNull( if (itemType != BookmarkNodeType.SEPARATOR) { @@ -66,7 +68,7 @@ class BookmarkItemMenu( } else { null }, - if (itemType == BookmarkNodeType.ITEM) { + if (!shouldDisableNormalMode && itemType == BookmarkNodeType.ITEM) { TextMenuCandidate( text = context.getString(R.string.bookmark_menu_open_in_new_tab_button), ) { @@ -84,7 +86,7 @@ class BookmarkItemMenu( } else { null }, - if (hasAtLeastOneChild && itemType == BookmarkNodeType.FOLDER) { + if (!shouldDisableNormalMode && hasAtLeastOneChild && itemType == BookmarkNodeType.FOLDER) { TextMenuCandidate( text = context.getString(R.string.bookmark_menu_open_all_in_tabs_button), ) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyCompleted.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyCompleted.kt index 9e6ec5b6438ae3a43065cd05b431b874df883327..6a55d57f3440174566faadd8101931a8a039383f 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyCompleted.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyCompleted.kt @@ -62,7 +62,7 @@ fun MicrosurveyCompleted( Row { Image( - painter = painterResource(R.drawable.microsurvey_success), + painter = painterResource(R.drawable.mozac_lib_crash_notification), contentDescription = null, contentScale = ContentScale.None, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyHeader.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyHeader.kt index 03c3daff5a1b166f1a5b9fd6936c63a912720fac..8cf843dd14a9a585916ff868c58a976bf7648509 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyHeader.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyHeader.kt @@ -54,11 +54,12 @@ fun MicrosurveyHeader( .weight(1f, fill = false) .padding(start = 32.dp), ) { - Image( - painter = painterResource(R.drawable.ic_firefox), - contentDescription = stringResource(id = R.string.microsurvey_app_icon_content_description), - modifier = Modifier.size(24.dp), - ) +// Removed as part of tor-browser#42386 +// Image( +// painter = painterResource(R.drawable.ic_firefox), +// contentDescription = stringResource(id = R.string.microsurvey_app_icon_content_description), +// modifier = Modifier.size(24.dp), +// ) Spacer(modifier = Modifier.width(8.dp)) Text( text = title, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyRequestPrompt.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyRequestPrompt.kt index b9a0eac34da6f6de713223a0cc8bf8f1c942f96d..e5960644656869bef9899a81adc8416a79abe89a 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyRequestPrompt.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/microsurvey/ui/MicrosurveyRequestPrompt.kt @@ -102,11 +102,12 @@ private fun Header( onCloseButtonClicked: () -> Unit, ) { Row(modifier = Modifier.fillMaxWidth()) { - Image( - painter = painterResource(R.drawable.ic_firefox), - contentDescription = stringResource(id = R.string.microsurvey_app_icon_content_description), - modifier = Modifier.size(24.dp), - ) +// Removed as part of tor-browser#42386 +// Image( +// painter = painterResource(R.drawable.ic_firefox), +// contentDescription = stringResource(id = R.string.microsurvey_app_icon_content_description), +// modifier = Modifier.size(24.dp), +// ) Spacer(modifier = Modifier.width(8.dp)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/FenixOnboarding.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/FenixOnboarding.kt index a6f3b77a477e2ac39ed7068b40668dc2a97c6524..a877324aaecafd4d72f2b7929b2dadf83d8dcfd3 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/FenixOnboarding.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/FenixOnboarding.kt @@ -33,7 +33,7 @@ class FenixOnboarding(context: Context) : PreferencesHolder { // - We would like to evaluate the configuration only once (and thus it's kept in memory // and not re-evaluated) val config by lazy { - FxNimbus.features.onboarding.recordExposure() + // FxNimbus.features.onboarding.recordExposure() FxNimbus.features.onboarding.value() } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/ReEngagementNotificationWorker.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/ReEngagementNotificationWorker.kt index ef8ce2c293e033c32cb3b824cfd14a3bdf9237a1..a5c6becb2d70bab66a2b50f6a9d2ca4298b529d0 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/ReEngagementNotificationWorker.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/ReEngagementNotificationWorker.kt @@ -45,7 +45,7 @@ class ReEngagementNotificationWorker( // Recording the exposure event here to capture all users who met all criteria to receive // the re-engagement notification - FxNimbus.features.reEngagementNotification.recordExposure() + // FxNimbus.features.reEngagementNotification.recordExposure() if (!settings.reEngagementNotificationEnabled) { return Result.success() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingPage.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingPage.kt index 757b2bce9479ac807ffe7082d227989e6739e44d..88df951fc2574c9b8e0b3b6f7576242b434c8aff 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingPage.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingPage.kt @@ -189,7 +189,9 @@ private fun OnboardingPagePreview() { FirefoxTheme { OnboardingPage( pageState = OnboardingPageState( - imageRes = R.drawable.ic_notification_permission, + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource( id = R.string.onboarding_home_enable_notifications_title, formatArgs = arrayOf(stringResource(R.string.app_name)), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingScreen.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingScreen.kt index 55a19c5cf45c61697ce280c68dae2eab1c6dd1f2..9aab96e674851250685a2539b259dc86bf377bad 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingScreen.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/OnboardingScreen.kt @@ -257,7 +257,9 @@ private fun OnboardingScreenPreview() { private fun defaultPreviewPages() = listOf( OnboardingPageUiData( type = OnboardingPageUiData.Type.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource(R.string.juno_onboarding_default_browser_title_nimbus_2), description = stringResource(R.string.juno_onboarding_default_browser_description_nimbus_3), primaryButtonLabel = stringResource(R.string.juno_onboarding_default_browser_positive_button), @@ -273,7 +275,9 @@ private fun defaultPreviewPages() = listOf( ), OnboardingPageUiData( type = OnboardingPageUiData.Type.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource(R.string.juno_onboarding_sign_in_title_2), description = stringResource(R.string.juno_onboarding_sign_in_description_3), primaryButtonLabel = stringResource(R.string.juno_onboarding_sign_in_positive_button), @@ -289,7 +293,9 @@ private fun defaultPreviewPages() = listOf( ), OnboardingPageUiData( type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, - imageRes = R.drawable.ic_notification_permission, + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource(R.string.juno_onboarding_enable_notifications_title_nimbus_2), description = stringResource(R.string.juno_onboarding_enable_notifications_description_nimbus_2), primaryButtonLabel = stringResource(R.string.juno_onboarding_enable_notifications_positive_button), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/UpgradeOnboarding.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/UpgradeOnboarding.kt index ba0078c58c3ef8cdb4a5d997e9698502b7b28519..33fd799d3a0ed57a0690955354e25cc62aa992c1 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/UpgradeOnboarding.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/view/UpgradeOnboarding.kt @@ -69,7 +69,9 @@ fun UpgradeOnboarding( OnboardingPage( pageState = when (onboardingState) { UpgradeOnboardingState.Welcome -> OnboardingPageState( - imageRes = R.drawable.ic_onboarding_welcome, + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource(id = R.string.onboarding_home_welcome_title_2), description = stringResource(id = R.string.onboarding_home_welcome_description), primaryButton = Action( @@ -88,8 +90,9 @@ fun UpgradeOnboarding( }, ) UpgradeOnboardingState.SyncSignIn -> OnboardingPageState( - imageRes = R.drawable.ic_onboarding_sync, - title = stringResource(id = R.string.onboarding_home_sync_title_3), + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + imageRes = R.drawable.mozac_lib_crash_notification, title = stringResource(id = R.string.onboarding_home_sync_title_3), description = stringResource(id = R.string.onboarding_home_sync_description), primaryButton = Action( text = stringResource(id = R.string.onboarding_home_sign_in_button), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index 9b165d41e7f48a7f3c01c8792e86d5a2cee19034..23822379a050346d3104f2eaafe637cc90bf6510 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -444,6 +444,13 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { searchSuggestionHintBinding.title.text = getString(R.string.search_suggestions_onboarding_title) + + // Hide Search Suggestions prompt and disable + inflated.visibility = View.GONE + requireContext().settings().also { + it.shouldShowSearchSuggestionsInPrivate = false + it.showSearchSuggestionsInPrivateOnboardingFinished = true + } } binding.searchSuggestionsHint.setOnInflateListener((stubListener)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt index 12f002394625125a9f2cb0309d94d07a1d96fb97..5f58bce10ca04c8c1d9aece15f79739ff5cc712a 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt @@ -129,7 +129,7 @@ class AwesomeBarView( components.core.icons, engineForSpeculativeConnects, showEditSuggestion = false, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), ) defaultCombinedHistoryProvider = @@ -141,7 +141,7 @@ class AwesomeBarView( engine = engineForSpeculativeConnects, maxNumberOfSuggestions = METADATA_SUGGESTION_LIMIT, showEditSuggestion = false, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), ) val searchBitmap = getDrawable(activity, R.drawable.ic_search)!!.apply { @@ -328,12 +328,12 @@ class AwesomeBarView( } } - if (activity.browsingModeManager.mode == BrowsingMode.Normal && state.showAllSessionSuggestions) { + if (/* activity.browsingModeManager.mode == BrowsingMode.Normal && */ state.showAllSessionSuggestions) { // Unlike other providers, we don't exclude sponsored suggestions for open tabs. providersToAdd.add(getLocalTabsProvider()) } - if (activity.browsingModeManager.mode == BrowsingMode.Normal && state.showSessionSuggestionsForCurrentEngine) { + if (/* activity.browsingModeManager.mode == BrowsingMode.Normal && */ state.showSessionSuggestionsForCurrentEngine) { getFilterForCurrentEngineResults(state)?.let { providersToAdd.add(getLocalTabsProvider(it)) } @@ -346,7 +346,7 @@ class AwesomeBarView( loadUrlUseCase = loadUrlUseCase, includeSponsoredSuggestions = state.showSponsoredSuggestions, includeNonSponsoredSuggestions = state.showNonSponsoredSuggestions, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), contextId = activity.settings().contileContextId, ), ) @@ -379,7 +379,7 @@ class AwesomeBarView( engine = engineForSpeculativeConnects, maxNumberOfSuggestions = METADATA_SUGGESTION_LIMIT, showEditSuggestion = false, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), resultsUriFilter = filter::shouldIncludeUri, ) } else { @@ -394,7 +394,7 @@ class AwesomeBarView( engine = engineForSpeculativeConnects, maxNumberOfSuggestions = METADATA_SUGGESTION_LIMIT, showEditSuggestion = false, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), resultsUriFilter = filter::shouldIncludeUri, ) } else { @@ -498,7 +498,7 @@ class AwesomeBarView( getDrawable(activity, R.drawable.ic_search_results_device_mobile), getDrawable(activity, R.drawable.ic_search_results_device_tablet), ), - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), resultsUrlFilter = filter?.let { it::shouldIncludeUrl }, ) } @@ -521,7 +521,7 @@ class AwesomeBarView( components.core.icons, getDrawable(activity, R.drawable.ic_search_results_tab), excludeSelectedSession = !fromHomeFragment, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), resultsUriFilter = filter?.let { it::shouldIncludeUri }, ) } @@ -544,7 +544,7 @@ class AwesomeBarView( indicatorIcon = getDrawable(activity, R.drawable.ic_search_results_bookmarks), engine = engineForSpeculativeConnects, showEditSuggestion = false, - suggestionsHeader = activity.getString(R.string.firefox_suggest_header), +// suggestionsHeader = activity.getString(R.string.firefox_suggest_header), resultsUriFilter = filter?.let { it::shouldIncludeUri }, ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HttpsOnlyFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HttpsOnlyFragment.kt index 52b5072e900f6a977acc5fddd71bb0f2968de531..f269f0aadc1dc54f604c4a13a4263d2a6639889e 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HttpsOnlyFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HttpsOnlyFragment.kt @@ -15,6 +15,7 @@ import android.view.ViewGroup import androidx.core.text.HtmlCompat import androidx.core.text.getSpans import androidx.core.view.children +import androidx.core.view.isGone import androidx.fragment.app.Fragment import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -60,6 +61,8 @@ class HttpsOnlyFragment : Fragment() { updateEngineHttpsOnlyMode() } + binding.httpsOnlyModes.isGone = requireContext().settings().shouldDisableNormalMode + return binding.root } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt index 74eab8454e47398af9ff36c6d01d29e2f40bf66c..7374123349c5b4d0556c76420a54cfafa750aee2 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt @@ -52,7 +52,7 @@ enum class PhoneFeature(val androidPermissionsList: Array<String>) : Parcelable AUTOPLAY_AUDIBLE -> when (settings?.getAutoplayUserSetting() ?: AUTOPLAY_BLOCK_ALL) { AUTOPLAY_ALLOW_ALL -> R.string.preference_option_autoplay_allowed2 - AUTOPLAY_ALLOW_ON_WIFI -> R.string.preference_option_autoplay_allowed_wifi_only2 + // AUTOPLAY_ALLOW_ON_WIFI -> R.string.preference_option_autoplay_allowed_wifi_only2 AUTOPLAY_BLOCK_AUDIBLE -> R.string.preference_option_autoplay_block_audio2 AUTOPLAY_BLOCK_ALL -> R.string.preference_option_autoplay_blocked3 else -> R.string.preference_option_autoplay_blocked3 @@ -124,6 +124,7 @@ enum class PhoneFeature(val androidPermissionsList: Array<String>) : Parcelable return when (this) { AUTOPLAY_AUDIBLE -> SitePermissionsRules.Action.BLOCKED AUTOPLAY_INAUDIBLE -> SitePermissionsRules.Action.ALLOWED + LOCATION -> SitePermissionsRules.Action.BLOCKED else -> SitePermissionsRules.Action.ASK_TO_ALLOW } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 043195b46414f6a5b0d4dbc2192e1bbf96c28417..57328b9b0c74442a1396002f2cad07eafae26af4 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -13,8 +13,10 @@ import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper +import android.util.Log import android.view.LayoutInflater import android.view.View +import android.view.WindowManager import android.widget.Toast import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AlertDialog @@ -40,6 +42,7 @@ import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile import mozilla.components.feature.addons.ui.AddonFilePicker import mozilla.components.support.base.feature.ViewBoundFeatureWrapper +import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.ktx.android.view.showKeyboard import mozilla.components.ui.widgets.withCenterAlignedButtons import mozilla.telemetry.glean.private.NoExtras @@ -53,6 +56,7 @@ import org.mozilla.fenix.GleanMetrics.TrackingProtection import org.mozilla.fenix.GleanMetrics.Translations import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R +import org.mozilla.fenix.ReleaseChannel import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint import org.mozilla.fenix.databinding.AmoCollectionOverrideDialogBinding import org.mozilla.fenix.ext.application @@ -63,17 +67,23 @@ import org.mozilla.fenix.ext.openSetDefaultBrowserOption import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.gecko.GeckoProvider import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.perf.ProfilerViewModel import org.mozilla.fenix.settings.account.AccountUiView import org.mozilla.fenix.snackbar.FenixSnackbarDelegate import org.mozilla.fenix.snackbar.SnackbarBinding +import org.mozilla.fenix.tor.QuickStartPreference +import org.mozilla.fenix.tor.SecurityLevel +import org.mozilla.fenix.tor.TorBridgeTransportConfig +import org.mozilla.fenix.tor.TorEvents import org.mozilla.fenix.utils.Settings +import org.mozilla.geckoview.BuildConfig import kotlin.system.exitProcess import org.mozilla.fenix.GleanMetrics.Settings as SettingsMetrics @Suppress("LargeClass", "TooManyFunctions") -class SettingsFragment : PreferenceFragmentCompat() { +class SettingsFragment : PreferenceFragmentCompat(), UserInteractionHandler { private val args by navArgs<SettingsFragmentArgs>() private lateinit var accountUiView: AccountUiView @@ -173,6 +183,8 @@ class SettingsFragment : PreferenceFragmentCompat() { } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + //setPreferencesFromResource(R.xml.tor_network_settings_preferences, rootKey) + //setupConnectionPreferences() setPreferencesFromResource(R.xml.preferences, rootKey) } @@ -197,11 +209,14 @@ class SettingsFragment : PreferenceFragmentCompat() { override fun onResume() { super.onResume() - // Use nimbus to set the title, and a trivial addition - val nimbusValidation = FxNimbus.features.nimbusValidation.value() + // IN TOR BROWSER: We don't talk about Nimbus! + // ~Use nimbus to set the title, and a trivial addition~ + // val nimbusValidation = FxNimbus.features.nimbusValidation.value() - val title = nimbusValidation.settingsTitle - val suffix = nimbusValidation.settingsPunctuation + // val title = nimbusValidation.settingsTitle + // val suffix = nimbusValidation.settingsPunctuation + val title = getString(R.string.settings_title) + val suffix = "" showToolbar("$title$suffix") @@ -210,7 +225,11 @@ class SettingsFragment : PreferenceFragmentCompat() { update(shouldUpdateAccountUIState = !creatingFragment) requireView().findViewById<RecyclerView>(R.id.recycler_view) - ?.hideInitialScrollBar(viewLifecycleOwner.lifecycleScope) + .also { + it?.hideInitialScrollBar(viewLifecycleOwner.lifecycleScope) + // Prevent disabled settings from having a collapsing animation on open + it?.disableHidingAnimation() + } args.preferenceToScrollTo?.let { scrollToPreference(it) @@ -257,20 +276,26 @@ class SettingsFragment : PreferenceFragmentCompat() { getString(R.string.delete_browsing_data_quit_off) } - val tabSettingsPreference = - requirePreference<Preference>(R.string.pref_key_tabs) - tabSettingsPreference.summary = context?.settings()?.getTabTimeoutString() - - val autofillPreference = requirePreference<Preference>(R.string.pref_key_credit_cards) - autofillPreference.title = if (settings.addressFeature) { - getString(R.string.preferences_autofill) - } else { - getString(R.string.preferences_credit_cards_2) + if (!settings.shouldDisableNormalMode) { + val tabSettingsPreference = + requirePreference<Preference>(R.string.pref_key_tabs) + tabSettingsPreference.summary = context?.settings()?.getTabTimeoutString() } - val openLinksInAppsSettingsPreference = - requirePreference<Preference>(R.string.pref_key_open_links_in_apps) - openLinksInAppsSettingsPreference.summary = context?.settings()?.getOpenLinksInAppsString() +// val autofillPreference = requirePreference<Preference>(R.string.pref_key_credit_cards) +// autofillPreference.title = if (settings.addressFeature) { +// getString(R.string.preferences_autofill) +// } else { +// getString(R.string.preferences_credit_cards_2) +// } + +// val openLinksInAppsSettingsPreference = +// requirePreference<Preference>(R.string.pref_key_open_links_in_apps) +// openLinksInAppsSettingsPreference.summary = context?.settings()?.getOpenLinksInAppsString() + + // Hide "Delete browsing data on quit" when in Private Browsing-only mode + deleteBrowsingDataPreference.isVisible = + !deleteBrowsingDataPreference.context.settings().shouldDisableNormalMode setupPreferences() @@ -318,9 +343,9 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToTabsSettingsFragment() } - resources.getString(R.string.pref_key_home) -> { - SettingsFragmentDirections.actionSettingsFragmentToHomeSettingsFragment() - } +// resources.getString(R.string.pref_key_home) -> { +// SettingsFragmentDirections.actionSettingsFragmentToHomeSettingsFragment() +// } resources.getString(R.string.pref_key_customize) -> { SettingsFragmentDirections.actionSettingsFragmentToCustomizationFragment() @@ -331,10 +356,10 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToSavedLoginsAuthFragment() } - resources.getString(R.string.pref_key_credit_cards) -> { - SettingsMetrics.autofill.record() - SettingsFragmentDirections.actionSettingsFragmentToAutofillSettingFragment() - } +// resources.getString(R.string.pref_key_credit_cards) -> { +// SettingsMetrics.autofill.record() +// SettingsFragmentDirections.actionSettingsFragmentToAutofillSettingFragment() +// } resources.getString(R.string.pref_key_accessibility) -> { SettingsFragmentDirections.actionSettingsFragmentToAccessibilityFragment() @@ -354,6 +379,10 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToPrivateBrowsingFragment() } + resources.getString(R.string.pref_key_tor_security_level_settings) -> { + SettingsFragmentDirections.actionSettingsFragmentToTorSecurityLevelFragment() + } + resources.getString(R.string.pref_key_https_only_settings) -> { SettingsFragmentDirections.actionSettingsFragmentToHttpsOnlyFragment() } @@ -439,9 +468,9 @@ class SettingsFragment : PreferenceFragmentCompat() { null } - resources.getString(R.string.pref_key_open_links_in_apps) -> { - SettingsFragmentDirections.actionSettingsFragmentToOpenLinksInAppsFragment() - } +// resources.getString(R.string.pref_key_open_links_in_apps) -> { +// SettingsFragmentDirections.actionSettingsFragmentToOpenLinksInAppsFragment() +// } resources.getString(R.string.pref_key_sync_debug) -> { SettingsFragmentDirections.actionSettingsFragmentToSyncDebugFragment() @@ -467,6 +496,15 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToAboutFragment() } + resources.getString(R.string.pref_key_donate) -> { + (activity as HomeActivity).openToBrowserAndLoad( + searchTermOrURL = SupportUtils.DONATE_URL, + newTab = true, + from = BrowserDirection.FromSettings + ) + null + } + // Only displayed when secret settings are enabled resources.getString(R.string.pref_key_debug_settings) -> { SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment() @@ -505,6 +543,19 @@ class SettingsFragment : PreferenceFragmentCompat() { val preferenceMakeDefaultBrowser = requirePreference<DefaultBrowserPreference>(R.string.pref_key_make_default_browser) + requirePreference<Preference>(R.string.pref_key_allow_screenshots_in_private_mode).apply { + onPreferenceChangeListener = object : SharedPreferenceUpdater() { + override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { + if (newValue == false) { + activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + } else { + activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + return super.onPreferenceChange(preference, newValue) + } + } + } + if (!Config.channel.isReleased) { preferenceLeakCanary?.setOnPreferenceChangeListener { _, newValue -> val isEnabled = newValue == true @@ -551,11 +602,13 @@ class SettingsFragment : PreferenceFragmentCompat() { setupAmoCollectionOverridePreference(requireContext().settings()) setupGeckoLogsPreference(requireContext().settings()) setupAllowDomesticChinaFxaServerPreference() + setupSecurityLevelPreference() setupHttpsOnlyPreferences() setupNotificationPreference() setupSearchPreference() setupHomepagePreference() setupTrackingProtectionPreference() + setupConnectionPreferences() } /** @@ -590,6 +643,10 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + private fun RecyclerView.disableHidingAnimation() { + this.setItemAnimator(null) + this.setLayoutAnimation(null) + } private fun updateFxAAllowDomesticChinaServerMenu() { val settings = requireContext().settings() val preferenceAllowDomesticChinaServer = @@ -691,20 +748,20 @@ class SettingsFragment : PreferenceFragmentCompat() { @VisibleForTesting internal fun setupHomepagePreference() { - with(requirePreference<Preference>(R.string.pref_key_home)) { - summary = when { - context.settings().alwaysOpenTheHomepageWhenOpeningTheApp -> - getString(R.string.opening_screen_homepage_summary) - - context.settings().openHomepageAfterFourHoursOfInactivity -> - getString(R.string.opening_screen_after_four_hours_of_inactivity_summary) - - context.settings().alwaysOpenTheLastTabWhenOpeningTheApp -> - getString(R.string.opening_screen_last_tab_summary) - - else -> null - } - } +// with(requirePreference<Preference>(R.string.pref_key_home)) { +// summary = when { +// context.settings().alwaysOpenTheHomepageWhenOpeningTheApp -> +// getString(R.string.opening_screen_homepage_summary) +// +// context.settings().openHomepageAfterFourHoursOfInactivity -> +// getString(R.string.opening_screen_after_four_hours_of_inactivity_summary) +// +// context.settings().alwaysOpenTheLastTabWhenOpeningTheApp -> +// getString(R.string.opening_screen_last_tab_summary) +// +// else -> null +// } +// } } @VisibleForTesting @@ -728,9 +785,46 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + internal fun setupConnectionPreferences() { + // will be needed for phase2 + //val torController = requireContext().components.torController + + requirePreference<Preference>(R.string.pref_key_tor_network_settings_bridge_config).apply { + setOnPreferenceClickListener { + val directions = + SettingsFragmentDirections + .actionSettingsFragmentToTorBridgeConfigFragment() + requireView().findNavController().navigate(directions) + true + } + } + + requirePreference<QuickStartPreference>(R.string.pref_key_quick_start).apply { + setOnPreferenceClickListener { + context.components.torController.quickstart = !context.components.torController.quickstart + updateSwitch() + true + } + } + + requirePreference<Preference>(R.string.pref_key_use_html_connection_ui).apply { + onPreferenceChangeListener = object : SharedPreferenceUpdater() {} + isVisible = Config.channel != ReleaseChannel.Release + } + + requirePreference<Preference>(R.string.pref_key_tor_logs).apply { + setOnPreferenceClickListener { + val directions = + SettingsFragmentDirections.actionSettingsFragmentToTorLogsFragment() + requireView().findNavController().navigate(directions) + true + } + } + } + @VisibleForTesting internal fun setupCookieBannerPreference() { - FxNimbus.features.cookieBanners.recordExposure() + // FxNimbus.features.cookieBanners.recordExposure() if (context?.settings()?.shouldShowCookieBannerUI == false) return with(requirePreference<SwitchPreference>(R.string.pref_key_cookie_banner_private_mode)) { isVisible = context.settings().shouldShowCookieBannerUI @@ -768,6 +862,19 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + @VisibleForTesting + internal fun setupSecurityLevelPreference() { + val securityLevelPreference = + requirePreference<Preference>(R.string.pref_key_tor_security_level_settings) + securityLevelPreference.summary = context?.settings()?.torSecurityLevel()?.let { + when (it) { + SecurityLevel.STANDARD -> getString(R.string.tor_security_level_standard_option) + SecurityLevel.SAFER -> getString(R.string.tor_security_level_safer_option) + SecurityLevel.SAFEST -> getString(R.string.tor_security_level_safest_option) + } + } + } + @VisibleForTesting internal fun setupHttpsOnlyPreferences() { val httpsOnlyPreference = @@ -801,4 +908,18 @@ class SettingsFragment : PreferenceFragmentCompat() { private const val FXA_SYNC_OVERRIDE_EXIT_DELAY = 2000L private const val AMO_COLLECTION_OVERRIDE_EXIT_DELAY = 3000L } + + override fun onBackPressed(): Boolean { + // If tor is already bootstrapped, skip going back to [TorConnectionAssistFragment] and instead go directly to [HomeFragment] + if (requireComponents.torController.isBootstrapped) { + val navController = findNavController() + if (navController.previousBackStackEntry?.destination?.id == R.id.torConnectionAssistFragment) { + navController.navigate( + SettingsFragmentDirections.actionGlobalHomeFragment(), + ) + return true + } + } + return false + } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt index f8788cec1c52afbda1555855736f08799a356436..4e154037d30dca24690eef3fb3e1f42c190462bd 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt @@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException import java.net.URLEncoder import java.util.Locale +@Suppress("TooManyFunctions") object SupportUtils { const val RATE_APP_URL = "market://details?id=" + BuildConfig.APPLICATION_ID const val POCKET_TRENDING_URL = "https://getpocket.com/fenix-top-articles" @@ -37,7 +38,9 @@ object SupportUtils { const val MEITUAN_URL = "https://tb.j5k6.com/6ZSOp" const val GOOGLE_US_URL = "https://www.google.com/webhp?client=firefox-b-1-m&channel=ts" const val GOOGLE_XX_URL = "https://www.google.com/webhp?client=firefox-b-m&channel=ts" - const val WHATS_NEW_URL = "https://www.mozilla.org/firefox/android/notes" + // const val WHATS_NEW_URL = "https://www.torproject.org/releases/" + const val DONATE_URL = "https://donate.torproject.org/" + const val TB_MANUAL_URL = "https://tb-manual.torproject.org/mobile-tor" // This is locale-less on purpose so that the content negotiation happens on the AMO side because the current // user language might not be supported by AMO and/or the language might not be exactly what AMO is expecting @@ -103,6 +106,21 @@ object SupportUtils { return "https://support.mozilla.org/kb/access-mozilla-services-firefox-account" } + fun getTorHelpPageUrl(): String { + return TB_MANUAL_URL + } + + fun getTorWhatsNewUrl(): String { + val versionNumber = BuildConfig.VERSION_NAME.substringBefore(' ') // e.g. "13.5a5" + if (versionNumber.isEmpty()) { + return "https://blog.torproject.org/" + } + val alpha: String = if (versionNumber.contains('a')) "alpha-" else "" + val versionNumberNoDecimals: String = + versionNumber.split('.').joinToString("") // e.g. "135a5" + return "https://blog.torproject.org/new-${alpha}release-tor-browser-${versionNumberNoDecimals}/" // e.g. "https://blog.torproject.org/new-alpha-release-tor-browser-135a5/ + } + fun getMozillaPageUrl(page: MozillaPage, locale: Locale = Locale.getDefault()): String { val path = page.path val langTag = getLanguageTag(locale) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt index 2aeb6cb931ffd85b37f6f3a2e4b62bc2e461b236..e9108692fe722805688ff5102bb5c7156e8d6d41 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt @@ -32,6 +32,14 @@ class TabsSettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.tabs_preferences, rootKey) + + findPreference<RadioButtonPreference>(getString(R.string.pref_key_close_tabs_manually))?.parent?.apply { + isVisible = !context.settings().shouldDisableNormalMode + } + + findPreference<PreferenceCategory>(getString(R.string.pref_key_inactive_tabs_category))?.apply { + isVisible = !context.settings().shouldDisableNormalMode + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorBridgeConfigFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorBridgeConfigFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..5a6cc7dcebca61611005a471cce3ac18d3b86ba9 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorBridgeConfigFragment.kt @@ -0,0 +1,155 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.settings + +import android.os.Bundle +import androidx.preference.EditTextPreference +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SwitchPreference +import org.mozilla.fenix.Config +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.tor.TorBridgeTransportConfig +import org.mozilla.fenix.utils.view.addToRadioGroup +import org.mozilla.fenix.utils.view.GroupableRadioButton +import org.mozilla.fenix.utils.view.uncheckAll + +/** + * Displays the toggle for enabling bridges, options for built-in pluggable transports, and an additional + * preference for configuring a user-provided bridge. + */ +@Suppress("SpreadOperator") +class TorBridgeConfigFragment : PreferenceFragmentCompat() { + private val builtinBridgeRadioGroups = mutableListOf<GroupableRadioButton>() + private var previousTransportConfig: TorBridgeTransportConfig? = null + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.tor_bridge_config_preferences, rootKey) + + // Initialize radio button group for built-in bridge transport types + val radioObfs4 = bindBridgeTransportRadio(TorBridgeTransportConfig.BUILTIN_OBFS4) + val radioMeekAzure = bindBridgeTransportRadio(TorBridgeTransportConfig.BUILTIN_MEEK_AZURE) + val radioSnowflake = bindBridgeTransportRadio(TorBridgeTransportConfig.BUILTIN_SNOWFLAKE) + + builtinBridgeRadioGroups.addAll(mutableListOf(radioObfs4, radioMeekAzure, radioSnowflake)) + + // `*` is Kotlin's "spread" operator, for expanding an Array as a vararg. + addToRadioGroup(*builtinBridgeRadioGroups.toTypedArray()) + } + + override fun onResume() { + super.onResume() + + showToolbar(getString(R.string.preferences_tor_network_settings_bridge_config)) + + val bridgesEnabled = requireContext().components.torController.bridgesEnabled + + val prefBridgeConfig = + requirePreference<SwitchPreference>(R.string.pref_key_tor_network_settings_bridge_config_toggle) + prefBridgeConfig.apply { + isChecked = bridgesEnabled + setOnPreferenceChangeListener<Boolean> { preference, enabled -> + preference.context.components.torController.bridgesEnabled = enabled + updateCurrentConfiguredBridgePref(preference) + preference.context.components.torController.restartTor() + true + } + } + + val userProvidedBridges = requirePreference<EditTextPreference>( + R.string.pref_key_tor_network_settings_bridge_config_user_provided_bridge + ) + userProvidedBridges.apply { + setOnPreferenceChangeListener<String> { preference, userProvidedBridge -> + builtinBridgeRadioGroups.uncheckAll() + + preference.context.components.torController.bridgeTransport = TorBridgeTransportConfig.USER_PROVIDED + preference.context.components.torController.userProvidedBridges = userProvidedBridge + updateCurrentConfiguredBridgePref(preference) + preference.context.components.torController.restartTor() + true + } + val userProvidedBridge: String? = context.components.torController.userProvidedBridges + if (userProvidedBridge != null) { + setText(userProvidedBridge) + } + } + + val currentBridgeType = prefBridgeConfig.context.components.torController.bridgeTransport + // Cache the current configured transport type + previousTransportConfig = currentBridgeType + builtinBridgeRadioGroups.uncheckAll() + if (currentBridgeType != TorBridgeTransportConfig.USER_PROVIDED) { + val bridgeRadioButton = requirePreference<RadioButtonPreference>(currentBridgeType.preferenceKey) + bridgeRadioButton.setCheckedWithoutClickListener(true) + } + + updateCurrentConfiguredBridgePref(prefBridgeConfig) + } + + private fun bindBridgeTransportRadio( + bridge: TorBridgeTransportConfig + ): RadioButtonPreference { + val radio = requirePreference<RadioButtonPreference>(bridge.preferenceKey) + + radio.apply { + setOnPreferenceChangeListener<Boolean> { preference, isChecked -> + if (isChecked && (previousTransportConfig!! != bridge)) { + preference.context.components.torController.bridgeTransport = bridge + previousTransportConfig = bridge + updateCurrentConfiguredBridgePref(preference) + preference.context.components.torController.restartTor() + } + true + } + } + + return radio + } + + private fun setCurrentBridgeLabel(currentBridgePref: Preference?, bridge: String) { + currentBridgePref?.apply { + title = getString( + R + .string + .preferences_tor_network_settings_bridge_config_current_bridge, + bridge + ) + } + } + + private fun updateCurrentConfiguredBridgePref(preference: Preference) { + val currentBridge: Preference? = + findPreference( + getString( + R.string.pref_key_tor_network_settings_bridge_config_current_bridge + ) + ) + + val enabled = requireContext().components.torController.bridgesEnabled + + if (enabled) { + val configuredBridge = preference.context.components.torController.bridgeTransport + var bridges = when (configuredBridge) { + TorBridgeTransportConfig.USER_PROVIDED -> + preference.context.components.torController.userProvidedBridges + else -> configuredBridge.transportName + } + + if (bridges == null) { + bridges = "not known" + } + setCurrentBridgeLabel(currentBridge, bridges) + } else { + setCurrentBridgeLabel( + currentBridge, + getString(R.string.tor_network_settings_bridge_not_configured) + ) + } + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorSecurityLevelFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorSecurityLevelFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..87b4c29c68ecb7a125b2c32d889ae8c3c715488f --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorSecurityLevelFragment.kt @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.settings + +import android.os.Bundle +import androidx.preference.PreferenceFragmentCompat +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.tor.SecurityLevel +import org.mozilla.fenix.tor.SecurityLevelUtil +import org.mozilla.fenix.utils.view.GroupableRadioButton +import org.mozilla.fenix.utils.view.addToRadioGroup +import org.mozilla.fenix.utils.view.uncheckAll + +/** + * Lets the user choose their security level + */ +@Suppress("SpreadOperator") +class TorSecurityLevelFragment : PreferenceFragmentCompat() { + private val securityLevelRadioGroups = mutableListOf<GroupableRadioButton>() + private var previousSecurityLevel: SecurityLevel? = null + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.tor_security_level_preferences, rootKey) + + val currentLevel: SecurityLevel? = context?.components?.let { + try { + SecurityLevelUtil.getSecurityLevelFromInt( + it.core.engine.settings.torSecurityLevel + ) + } catch (e: IllegalStateException) { + // The default state is 0. If we get an invalid state then + // default to Standard (4). + SecurityLevel.STANDARD + } + } + + if (currentLevel == null) { + throw IllegalStateException("context or Components is null.") + } + + val radioSafer = bindSecurityLevelRadio(SecurityLevel.SAFER) + val radioSafest = bindSecurityLevelRadio(SecurityLevel.SAFEST) + val radioStandard = bindSecurityLevelRadio(SecurityLevel.STANDARD) + + securityLevelRadioGroups.addAll(mutableListOf(radioSafer, radioSafest, radioStandard)) + // `*` is Kotlin's "spread" operator, for expanding an Array as a vararg. + addToRadioGroup(*securityLevelRadioGroups.toTypedArray()) + + securityLevelRadioGroups.uncheckAll() + val securityLevelRadioButton = requirePreference<RadioButtonPreference>(currentLevel.preferenceKey) + // Cache this for later comparison in the OnPreferenceChangeListener + previousSecurityLevel = currentLevel + securityLevelRadioButton.setCheckedWithoutClickListener(true) + } + + private fun bindSecurityLevelRadio( + level: SecurityLevel + ): RadioButtonPreference { + val radio = requirePreference<RadioButtonPreference>(level.preferenceKey) + + radio.summary = getString(level.contentDescriptionRes) + + radio.apply { + setOnPreferenceChangeListener<Boolean> { preference, isChecked -> + if (isChecked && (previousSecurityLevel!! != level)) { + preference.context.components.core.engine.settings.torSecurityLevel = + level.intRepresentation + previousSecurityLevel = level + } + true + } + } + + return radio + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt index 98511da8e4c73d2a819d5f7ff83fcfd95acbeed9..5f15010aaa4cbc774d106e5691544922c0129031 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt @@ -119,7 +119,7 @@ class AboutFragment : Fragment(), AboutPageListener { "" } - val content = getString(R.string.about_content, appName) + val content = getString(R.string.tor_about_content, appName) val buildDate = BuildConfig.BUILD_DATE binding.aboutText.text = aboutText @@ -128,13 +128,13 @@ class AboutFragment : Fragment(), AboutPageListener { } private fun populateAboutList(): List<AboutPageItem> { - val context = requireContext() + //val context = requireContext() return listOf( AboutPageItem( AboutItem.ExternalLink( WHATS_NEW, - SupportUtils.WHATS_NEW_URL, + SupportUtils.getTorWhatsNewUrl(), ), // Note: Fenix only has release notes for 'Release' versions, NOT 'Beta' & 'Nightly'. getString(R.string.about_whats_new, getString(R.string.firefox)), @@ -142,28 +142,28 @@ class AboutFragment : Fragment(), AboutPageListener { AboutPageItem( AboutItem.ExternalLink( SUPPORT, - SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.HELP), + SupportUtils.getTorHelpPageUrl() ), getString(R.string.about_support), ), - AboutPageItem( - AboutItem.Crashes, - getString(R.string.about_crashes), - ), - AboutPageItem( - AboutItem.ExternalLink( - PRIVACY_NOTICE, - SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE), - ), - getString(R.string.about_privacy_notice), - ), - AboutPageItem( - AboutItem.ExternalLink( - RIGHTS, - SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS), - ), - getString(R.string.about_know_your_rights), - ), + //AboutPageItem( + // AboutItem.Crashes, + // getString(R.string.about_crashes), + //), + //AboutPageItem( + // AboutItem.ExternalLink( + // PRIVACY_NOTICE, + // SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE), + // ), + // getString(R.string.about_privacy_notice), + //), + //AboutPageItem( + // AboutItem.ExternalLink( + // RIGHTS, + // SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS), + // ), + // getString(R.string.about_know_your_rights), + //), AboutPageItem( AboutItem.ExternalLink(LICENSING_INFO, ABOUT_LICENSE_URL), getString(R.string.about_licensing_information), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/account/AccountUiView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/account/AccountUiView.kt index bf6041c6edb930de45cce882bb3ea767465a281f..b53b1668f524cef9eb064177b6ed3c80bb5ff9a6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/account/AccountUiView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/account/AccountUiView.kt @@ -86,7 +86,7 @@ class AccountUiView( // Signed-out. } else { - preferenceSignIn.isVisible = true + preferenceSignIn.isVisible = false preferenceFirefoxAccount.isVisible = false preferenceFirefoxAccountAuthError.isVisible = false accountPreferenceCategory.isVisible = false @@ -104,7 +104,7 @@ class AccountUiView( * Returns generic avatar for accounts. */ private fun genericAvatar(context: Context) = - AppCompatResources.getDrawable(context, R.drawable.ic_account) + AppCompatResources.getDrawable(context, R.drawable.mozac_lib_crash_notification) /** * Gets a rounded drawable from a URL if possible, else null. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/DefaultLocaleSettingsController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/DefaultLocaleSettingsController.kt index e387bc4ae08ab544a08be6501fbec9c372125ce9..a45b32ad9b27eac13169da58fbb22ab8b74f1624 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/DefaultLocaleSettingsController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/DefaultLocaleSettingsController.kt @@ -12,6 +12,7 @@ import mozilla.components.browser.state.store.BrowserStore import mozilla.components.support.locale.LocaleManager import mozilla.components.support.locale.LocaleUseCases import org.mozilla.fenix.nimbus.FxNimbus +import org.mozilla.fenix.ext.components import java.util.Locale interface LocaleSettingsController { @@ -39,7 +40,7 @@ class DefaultLocaleSettingsController( LocaleManager.updateBaseConfiguration(activity, locale) // Invalidate cached values to use the new locale - FxNimbus.features.nimbusValidation.withCachedValue(null) + // FxNimbus.features.nimbusValidation.withCachedValue(null) activity.recreate() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { activity.overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN, 0, 0) @@ -59,7 +60,7 @@ class DefaultLocaleSettingsController( LocaleManager.updateBaseConfiguration(activity, localeSettingsStore.state.localeList[0]) // Invalidate cached values to use the default locale - FxNimbus.features.nimbusValidation.withCachedValue(null) + // FxNimbus.features.nimbusValidation.withCachedValue(null) activity.recreate() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { activity.overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN, 0, 0) @@ -83,5 +84,9 @@ class DefaultLocaleSettingsController( config.setLocale(locale) config.setLayoutDirection(locale) resources.updateConfiguration(config, resources.displayMetrics) + // A slightly hacky way of triggering a `runtime.settings.locales` update, + // so that the locales are updated in GeckoView. + val spoofEnglish = context.components.core.engine.settings.spoofEnglish + context.components.core.engine.settings.spoofEnglish = spoofEnglish } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt index 91929aab38cdf247622190180455e9a6ac38b025..a45b807f8495898fb014a81afbf4a0439f21f2f4 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt @@ -23,6 +23,8 @@ import org.mozilla.fenix.R import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.databinding.FragmentLocaleSettingsBinding import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar class LocaleSettingsFragment : Fragment(), MenuProvider { @@ -46,6 +48,8 @@ class LocaleSettingsFragment : Fragment(), MenuProvider { _binding = FragmentLocaleSettingsBinding.inflate(inflater, container, false) val view = binding.root + bindEnableSwitch() + val browserStore = requireContext().components.core.store val localeUseCase = LocaleUseCases(browserStore) @@ -62,10 +66,19 @@ class LocaleSettingsFragment : Fragment(), MenuProvider { localeUseCase = localeUseCase, ), ) - localeView = LocaleSettingsView(binding.root, interactor) + localeView = LocaleSettingsView(binding.localeContainer, interactor) return view } + private fun bindEnableSwitch() { + val switch = binding.enableSwitch + switch.isChecked = requireComponents.core.engine.settings.spoofEnglish + switch.setOnCheckedChangeListener { _, isChecked -> + context?.settings()?.spoofEnglish = isChecked + requireComponents.core.engine.settings.spoofEnglish = isChecked + } + } + override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.languages_list, menu) val searchItem = menu.findItem(R.id.search) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt index 6c87e6c907c8f16052c77101c90789768fd02f13..879e2bbd9c82cb7a45e0ee22940ef9844ad4b6ef 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt @@ -64,7 +64,7 @@ class SavedLoginsListView( } else { binding.progressBar.isVisible = false binding.savedLoginsList.isVisible = state.loginList.isNotEmpty() - binding.savedPasswordsEmptyView.isVisible = state.loginList.isEmpty() + binding.savedPasswordsEmptyView.isVisible = false } loginsAdapter.submitList(state.filteredItems) { // Reset scroll position to the first item after submitted list was committed. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt index 3f5c19f39af0a5d121d2574eca0c9290cd8c01d0..10324f951ddcdc00fa1414c8567b833647eef3e8 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt @@ -137,7 +137,8 @@ class QuickSettingsSheetDialogFragment : FenixDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - observeTrackersChange(requireComponents.core.store) +// Removed as part of Bug_42115: Enhanced Tracking Protection can still be enabled +// observeTrackersChange(requireComponents.core.store) consumeFrom(quickSettingsStore) { websiteInfoView.update(it.webInfoState) websitePermissionsView.update(it.websitePermissionsState) @@ -195,34 +196,36 @@ class QuickSettingsSheetDialogFragment : FenixDialogFragment() { @VisibleForTesting internal fun provideTabId(): String = args.sessionId - @VisibleForTesting - internal fun observeTrackersChange(store: BrowserStore) { - consumeFlow(store) { flow -> - flow.mapNotNull { state -> - state.findTabOrCustomTab(provideTabId()) - }.ifAnyChanged { tab -> - arrayOf( - tab.trackingProtection.blockedTrackers, - tab.trackingProtection.loadedTrackers, - ) - }.collect { - updateTrackers(it) - } - } - } - - @VisibleForTesting - internal fun updateTrackers(tab: SessionState) { - provideTrackingProtectionUseCases().fetchTrackingLogs( - tab.id, - onSuccess = { trackers -> - protectionsView.updateDetailsSection(trackers.isNotEmpty()) - }, - onError = { - Logger.error("QuickSettingsSheetDialogFragment - fetchTrackingLogs onError", it) - }, - ) - } +// Removed as part of Bug_42115: Enhanced Tracking Protection can still be enabled +// @VisibleForTesting +// internal fun observeTrackersChange(store: BrowserStore) { +// consumeFlow(store) { flow -> +// flow.mapNotNull { state -> +// state.findTabOrCustomTab(provideTabId()) +// }.ifAnyChanged { tab -> +// arrayOf( +// tab.trackingProtection.blockedTrackers, +// tab.trackingProtection.loadedTrackers, +// ) +// }.collect { +// updateTrackers(it) +// } +// } +// } + +// Removed as part of Bug_42115: Enhanced Tracking Protection can still be enabled +// @VisibleForTesting +// internal fun updateTrackers(tab: SessionState) { +// provideTrackingProtectionUseCases().fetchTrackingLogs( +// tab.id, +// onSuccess = { trackers -> +// protectionsView.updateDetailsSection(trackers.isNotEmpty()) +// }, +// onError = { +// Logger.error("QuickSettingsSheetDialogFragment - fetchTrackingLogs onError", it) +// }, +// ) +// } @VisibleForTesting internal fun provideTrackingProtectionUseCases() = requireComponents.useCases.trackingProtectionUseCases diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/ProtectionsView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/ProtectionsView.kt index 533a7d906d79f680441c950f5ffa9b8f50985f48..21048852075d6cad8c2026504aea6cac04386f56 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/ProtectionsView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/ProtectionsView.kt @@ -33,7 +33,7 @@ import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.databinding.QuicksettingsProtectionsPanelBinding import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.trackingprotection.CookieBannerUIMode -import org.mozilla.fenix.trackingprotection.CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED +// import org.mozilla.fenix.trackingprotection.CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED import org.mozilla.fenix.trackingprotection.CookieBannerUIMode.SITE_NOT_SUPPORTED import org.mozilla.fenix.trackingprotection.ProtectionsState import org.mozilla.fenix.utils.Settings @@ -59,39 +59,45 @@ class ProtectionsView( * Allows changing what this View displays. */ fun update(state: ProtectionsState) { - bindTrackingProtectionInfo(state.isTrackingProtectionEnabled) +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// bindTrackingProtectionInfo(state.isTrackingProtectionEnabled) bindCookieBannerProtection(state.cookieBannerUIMode) - binding.trackingProtectionSwitch.isVisible = settings.shouldUseTrackingProtection +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// binding.trackingProtectionSwitch.isVisible = settings.shouldUseTrackingProtection val isPrivateSession = state.tab?.content?.private == true binding.cookieBannerItem.isVisible = isPrivateSession && shouldShowCookieBanner && state.cookieBannerUIMode != CookieBannerUIMode.HIDE - binding.trackingProtectionDetails.setOnClickListener { - interactor.onTrackingProtectionDetailsClicked() - } - updateDividerVisibility() +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// binding.trackingProtectionDetails.setOnClickListener { +// interactor.onTrackingProtectionDetailsClicked() +// } +// updateDividerVisibility() } - private fun updateDividerVisibility() { - trackingProtectionDivider.isVisible = !( - !binding.trackingProtectionSwitch.isVisible && - !binding.trackingProtectionDetails.isVisible && - !binding.cookieBannerItem.isVisible - ) - } - - @VisibleForTesting - internal fun updateDetailsSection(show: Boolean) { - binding.trackingProtectionDetails.isVisible = show - updateDividerVisibility() - } - - private fun bindTrackingProtectionInfo(isTrackingProtectionEnabled: Boolean) { - binding.trackingProtectionSwitch.isChecked = isTrackingProtectionEnabled - binding.trackingProtectionSwitch.setOnCheckedChangeListener { _, isChecked -> - interactor.onTrackingProtectionToggled(isChecked) - } - } +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// private fun updateDividerVisibility() { +// trackingProtectionDivider.isVisible = !( +// !binding.trackingProtectionSwitch.isVisible && +// !binding.trackingProtectionDetails.isVisible && +// !binding.cookieBannerItem.isVisible +// ) +// } + +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// @VisibleForTesting +// internal fun updateDetailsSection(show: Boolean) { +// binding.trackingProtectionDetails.isVisible = show +// updateDividerVisibility() +// } + +// Removed as part of tor-browser#42115: Enhanced Tracking Protection can still be enabled +// private fun bindTrackingProtectionInfo(isTrackingProtectionEnabled: Boolean) { +// binding.trackingProtectionSwitch.isChecked = isTrackingProtectionEnabled +// binding.trackingProtectionSwitch.setOnCheckedChangeListener { _, isChecked -> +// interactor.onTrackingProtectionToggled(isChecked) +// } +// } @VisibleForTesting internal val binding = QuicksettingsProtectionsPanelBinding.inflate( @@ -111,7 +117,7 @@ class ProtectionsView( setContent { FirefoxTheme { if (cookieBannerMode in listOf( - REQUEST_UNSUPPORTED_SITE_SUBMITTED, +// REQUEST_UNSUPPORTED_SITE_SUBMITTED, SITE_NOT_SUPPORTED, ) ) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt index 0eb4e8ecbb9a87e2e04643d27fd52c3d8c468722..4ba8c1d2219f24f165c22221e6ef3f7c03b3c8ad 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt @@ -55,7 +55,7 @@ interface CookieBannerDetailsController { /** * @see [CookieBannerDetailsInteractor.handleRequestSiteSupportPressed] */ - fun handleRequestSiteSupportPressed() +// fun handleRequestSiteSupportPressed() } /** @@ -144,37 +144,37 @@ class DefaultCookieBannerDetailsController( } } - override fun handleRequestSiteSupportPressed() { - val tab = requireNotNull(browserStore.state.findTabOrCustomTab(sessionId)) { - "A session is required to report site domain" - } - CookieBanners.reportDomainSiteButton.record(NoExtras()) - ioScope.launch { - val siteDomain = getTabDomain(tab) - siteDomain?.let { domain -> - withContext(Dispatchers.Main) { - protectionsStore.dispatch(ProtectionsAction.RequestReportSiteDomain(domain)) - CookieBanners.reportSiteDomain.set(domain) - Pings.cookieBannerReportSite.submit() - protectionsStore.dispatch( - ProtectionsAction.UpdateCookieBannerMode( - cookieBannerUIMode = CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED, - ), - ) - fragment.activity?.getRootView()?.let { view -> - showSnackBar( - view, - context.getString(R.string.cookie_banner_handling_report_site_snack_bar_text_2), - FenixSnackbar.LENGTH_LONG, - ) - } - withContext(Dispatchers.IO) { - cookieBannersStorage.saveSiteDomain(domain) - } - } - } - } - } +// override fun handleRequestSiteSupportPressed() { +// val tab = requireNotNull(browserStore.state.findTabOrCustomTab(sessionId)) { +// "A session is required to report site domain" +// } +// CookieBanners.reportDomainSiteButton.record(NoExtras()) +// ioScope.launch { +// val siteDomain = getTabDomain(tab) +// siteDomain?.let { domain -> +// withContext(Dispatchers.Main) { +// protectionsStore.dispatch(ProtectionsAction.RequestReportSiteDomain(domain)) +// CookieBanners.reportSiteDomain.set(domain) +// Pings.cookieBannerReportSite.submit() +// protectionsStore.dispatch( +// ProtectionsAction.UpdateCookieBannerMode( +// cookieBannerUIMode = CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED, +// ), +// ) +// fragment.activity?.getRootView()?.let { view -> +// showSnackBar( +// view, +// context.getString(R.string.cookie_banner_handling_report_site_snack_bar_text_2), +// FenixSnackbar.LENGTH_LONG, +// ) +// } +// withContext(Dispatchers.IO) { +// cookieBannersStorage.saveSiteDomain(domain) +// } +// } +// } +// } +// } @VisibleForTesting internal suspend fun clearSiteData(tab: SessionState) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsInteractor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsInteractor.kt index dce8ddd578c2ce38a1ca389e074c8a1020dc418f..c8dc2f16ef12e1b4bc626a19d4b1844579de3670 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsInteractor.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsInteractor.kt @@ -21,7 +21,7 @@ interface CookieBannerDetailsInteractor { /** * Called whenever the user press request support site domain. */ - fun handleRequestSiteSupportPressed() +// fun handleRequestSiteSupportPressed() } /** @@ -45,7 +45,7 @@ class DefaultCookieBannerDetailsInteractor( controller.handleTogglePressed(vale) } - override fun handleRequestSiteSupportPressed() { - controller.handleRequestSiteSupportPressed() - } +// override fun handleRequestSiteSupportPressed() { +// controller.handleRequestSiteSupportPressed() +// } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsView.kt index c6328213c48b47dc8772bb66559b31c8e9749b21..39a333772ddb5329816d90422d514347b56e2b02 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsView.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsView.kt @@ -60,7 +60,7 @@ class CookieBannerHandlingDetailsView( when (state.cookieBannerUIMode) { CookieBannerUIMode.ENABLE -> setUiForExceptionMode(state) CookieBannerUIMode.DISABLE -> setUiForExceptionMode(state) - CookieBannerUIMode.SITE_NOT_SUPPORTED -> setUiForReportSiteMode() +// CookieBannerUIMode.SITE_NOT_SUPPORTED -> setUiForReportSiteMode() else -> {} } } @@ -70,19 +70,19 @@ class CookieBannerHandlingDetailsView( bindSwitch(state.cookieBannerUIMode) } - private fun setUiForReportSiteMode() { - binding.cancelButton.visibility = View.VISIBLE - binding.requestSupport.visibility = View.VISIBLE - binding.cookieBannerSwitch.visibility = View.GONE - binding.requestSupport.setOnClickListener { - interactor.handleRequestSiteSupportPressed() - onDismiss.invoke() - } - binding.cancelButton.setOnClickListener { - CookieBanners.reportSiteCancelButton.record(NoExtras()) - interactor.onBackPressed() - } - } +// private fun setUiForReportSiteMode() { +// binding.cancelButton.visibility = View.VISIBLE +// binding.requestSupport.visibility = View.VISIBLE +// binding.cookieBannerSwitch.visibility = View.GONE +// binding.requestSupport.setOnClickListener { +// interactor.handleRequestSiteSupportPressed() +// onDismiss.invoke() +// } +// binding.cancelButton.setOnClickListener { +// CookieBanners.reportSiteCancelButton.record(NoExtras()) +// interactor.onBackPressed() +// } +// } @VisibleForTesting internal fun bindTitle(url: String, state: CookieBannerUIMode) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannersStorageExt.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannersStorageExt.kt index 7bd7b7b21b466496b6fa3b71d7d2d53606cdd7f2..58a1cdb61708911de1a5df41340bab76079e1c36 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannersStorageExt.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannersStorageExt.kt @@ -24,15 +24,15 @@ suspend fun CookieBannersStorage.getCookieBannerUIMode( tab: SessionState, ): CookieBannerUIMode { return if (context.settings().shouldUseCookieBannerPrivateMode) { - val isSiteDomainReported = withContext(Dispatchers.IO) { - val host = tab.content.url.toUri().host.orEmpty() - val siteDomain = context.components.publicSuffixList.getPublicSuffixPlusOne(host).await() - siteDomain?.let { isSiteDomainReported(it) } - } - - if (isSiteDomainReported == true) { - return CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED - } +// val isSiteDomainReported = withContext(Dispatchers.IO) { +// val host = tab.content.url.toUri().host.orEmpty() +// val siteDomain = context.components.publicSuffixList.getPublicSuffixPlusOne(host).await() +// siteDomain?.let { isSiteDomainReported(it) } +// } +// +// if (isSiteDomainReported == true) { +// return CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED +// } val hasException = withContext(Dispatchers.IO) { hasException(tab.content.url, tab.content.private) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt index 0f8f9704e8748e14f4d78ea8aeca6814a23c927e..083b6361c1f0059a64063dff248a7e6cc806cea4 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt @@ -34,16 +34,24 @@ class SearchEngineFragment : PreferenceFragmentCompat() { rootKey, ) - requirePreference<SwitchPreference>(R.string.pref_key_show_sponsored_suggestions).apply { - isVisible = context.settings().enableFxSuggest + findPreference<CheckBoxPreference>(getString(R.string.pref_key_show_search_suggestions_in_private))?.apply { + isVisible = !context.settings().shouldDisableNormalMode } - requirePreference<SwitchPreference>(R.string.pref_key_show_nonsponsored_suggestions).apply { - isVisible = context.settings().enableFxSuggest - } - requirePreference<Preference>(R.string.pref_key_learn_about_fx_suggest).apply { - isVisible = context.settings().enableFxSuggest + + findPreference<SwitchPreference>(getString(R.string.pref_key_search_browsing_history))?.apply { + isVisible = !context.settings().shouldDisableNormalMode } +// requirePreference<SwitchPreference>(R.string.pref_key_show_sponsored_suggestions).apply { +// isVisible = context.settings().enableFxSuggest +// } +// requirePreference<SwitchPreference>(R.string.pref_key_show_nonsponsored_suggestions).apply { +// isVisible = context.settings().enableFxSuggest +// } +// requirePreference<Preference>(R.string.pref_key_learn_about_fx_suggest).apply { +// isVisible = context.settings().enableFxSuggest +// } + view?.hideKeyboard() } @@ -83,10 +91,10 @@ class SearchEngineFragment : PreferenceFragmentCompat() { isChecked = context.settings().shouldShowBookmarkSuggestions } - val showSyncedTabsSuggestions = - requirePreference<SwitchPreference>(R.string.pref_key_search_synced_tabs).apply { - isChecked = context.settings().shouldShowSyncedTabsSuggestions - } +// val showSyncedTabsSuggestions = +// requirePreference<SwitchPreference>(R.string.pref_key_search_synced_tabs).apply { +// isChecked = context.settings().shouldShowSyncedTabsSuggestions +// } val showClipboardSuggestions = requirePreference<SwitchPreference>(R.string.pref_key_show_clipboard_suggestions).apply { @@ -98,28 +106,28 @@ class SearchEngineFragment : PreferenceFragmentCompat() { isChecked = context.settings().shouldShowVoiceSearch } - val showSponsoredSuggestionsPreference = - requirePreference<SwitchPreference>(R.string.pref_key_show_sponsored_suggestions).apply { - isChecked = context.settings().showSponsoredSuggestions - summary = getString( - R.string.preferences_show_sponsored_suggestions_summary, - getString(R.string.app_name), - ) - } - - val showNonSponsoredSuggestionsPreference = - requirePreference<SwitchPreference>(R.string.pref_key_show_nonsponsored_suggestions).apply { - isChecked = context.settings().showNonSponsoredSuggestions - title = getString( - R.string.preferences_show_nonsponsored_suggestions, - getString(R.string.app_name), - ) - } +// val showSponsoredSuggestionsPreference = +// requirePreference<SwitchPreference>(R.string.pref_key_show_sponsored_suggestions).apply { +// isChecked = context.settings().showSponsoredSuggestions +// summary = getString( +// R.string.preferences_show_sponsored_suggestions_summary, +// getString(R.string.app_name), +// ) +// } +// +// val showNonSponsoredSuggestionsPreference = +// requirePreference<SwitchPreference>(R.string.pref_key_show_nonsponsored_suggestions).apply { +// isChecked = context.settings().showNonSponsoredSuggestions +// title = getString( +// R.string.preferences_show_nonsponsored_suggestions, +// getString(R.string.app_name), +// ) +// } searchSuggestionsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() showHistorySuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() showBookmarkSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() - showSyncedTabsSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() +// showSyncedTabsSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() showClipboardSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() searchSuggestionsInPrivatePreference.onPreferenceChangeListener = SharedPreferenceUpdater() showVoiceSearchPreference.onPreferenceChangeListener = object : Preference.OnPreferenceChangeListener { @@ -135,15 +143,15 @@ class SearchEngineFragment : PreferenceFragmentCompat() { autocompleteURLsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() searchSuggestionsPreference.setOnPreferenceClickListener { - if (!searchSuggestionsPreference.isChecked) { + if (!requireContext().settings().shouldDisableNormalMode && !searchSuggestionsPreference.isChecked) { searchSuggestionsInPrivatePreference.isChecked = false searchSuggestionsInPrivatePreference.callChangeListener(false) } true } - showSponsoredSuggestionsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() - showNonSponsoredSuggestionsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() +// showSponsoredSuggestionsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() +// showNonSponsoredSuggestionsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() } override fun onPreferenceTreeClick(preference: Preference): Boolean { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt index 201406cf273c1fc3dd6a642dcb5814644eff707a..d83061a158762f7966e285fd9b217c7d096b8401 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt @@ -58,6 +58,7 @@ class SitePermissionsFragment : PreferenceFragmentCompat() { // Autoplay inaudible should be set in the same menu as autoplay audible, so it does // not need to be bound .filter { it != PhoneFeature.AUTOPLAY_INAUDIBLE } + .filter { it != PhoneFeature.LOCATION } .forEach(::initPhoneFeature) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt index 5f5ceb60c0a3b51ede052bedd3a01ebb0f13c145..b11f2165b76147304d776dbce69de45d61250de4 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt @@ -119,6 +119,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { saveActionInSettings(AUTOPLAY_ALLOW_ON_WIFI) } restoreState(AUTOPLAY_ALLOW_ON_WIFI) + visibility = View.GONE } else { text = getString(R.string.preference_option_phone_feature_blocked) setOnClickListener { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/SaveToPDFMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/SaveToPDFMiddleware.kt index aa7a251fe746a85731e7e46bc85c2e0bcf4974ce..e6797a7378dfc9246f1de2c8946f2a5f48a0b89c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/SaveToPDFMiddleware.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/SaveToPDFMiddleware.kt @@ -22,7 +22,6 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.StandardSnackbarError import org.mozilla.fenix.components.appstate.AppAction import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.recordEventInNimbus import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSession.GeckoPrintException.ERROR_NO_ACTIVITY_CONTEXT import org.mozilla.geckoview.GeckoSession.GeckoPrintException.ERROR_NO_ACTIVITY_CONTEXT_DELEGATE @@ -153,7 +152,7 @@ class SaveToPDFMiddleware( source = telemetrySource(isPdf), ), ) - context.recordEventInNimbus("print_tapped") + // context.recordEventInNimbus("print_tapped") } else { Events.saveToPdfTapped.record( Events.SaveToPdfTappedExtra( diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt index 87fee4d6f1492e6893c4b45d5359dadf4ff36189..c0b7848d9f8a374a94ee51775509dd33c585ee85 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt @@ -36,6 +36,7 @@ import mozilla.components.support.ktx.kotlin.isExtensionUrl import mozilla.telemetry.glean.private.NoExtras import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.SyncAccount +import mozilla.components.support.utils.TorUtils import org.mozilla.fenix.R import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint @@ -141,7 +142,7 @@ class DefaultShareController( @Suppress("TooGenericExceptionCaught") val result = try { - context.startActivity(intent) + TorUtils.startActivityPrompt(context, intent) ShareController.Result.SUCCESS } catch (e: Exception) { when (e) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 7057dafc7dd5baa7c46bd7a534ba537a4fbff05c..18998a4586561524b9310c763908e24b7fc44a17 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -39,7 +39,6 @@ class ShareFragment : AppCompatDialogFragment() { } private lateinit var shareInteractor: ShareInteractor private lateinit var shareCloseView: ShareCloseView - private lateinit var shareToAccountDevicesView: ShareToAccountDevicesView private lateinit var shareToAppsView: ShareToAppsView override fun onAttach(context: Context) { @@ -104,9 +103,6 @@ class ShareFragment : AppCompatDialogFragment() { ) binding.shareWrapper.setOnClickListener { shareInteractor.onShareClosed() } - shareToAccountDevicesView = - ShareToAccountDevicesView(binding.devicesShareLayout, shareInteractor) - if (args.showPage) { // Show the previous fragment underneath the share background scrim // by making it translucent. @@ -143,9 +139,6 @@ class ShareFragment : AppCompatDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - viewModel.devicesList.observe(viewLifecycleOwner) { devicesShareOptions -> - shareToAccountDevicesView.setShareTargets(devicesShareOptions) - } viewModel.appsList.observe(viewLifecycleOwner) { appsToShareTo -> shareToAppsView.setShareTargets(appsToShareTo) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/NoAnalysis.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/NoAnalysis.kt index 1b87211dd24c21eef688163be8ed8517525bdead..a5df5ccd0d96f0690f0068d15e9297a431c6adbb 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/NoAnalysis.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/NoAnalysis.kt @@ -112,7 +112,9 @@ private fun ReviewQualityNoAnalysisCard( modifier = Modifier.fillMaxWidth(), ) { Image( - painter = painterResource(id = R.drawable.shopping_no_analysis), + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + painter = painterResource(id = R.drawable.mozac_lib_crash_notification), contentDescription = null, modifier = Modifier .fillMaxWidth() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt index cbe1f8bfa04714618750eeffb6e16081cf7a3e18..7277f750371a7a24947e11562a13290fc8a54c51 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt @@ -146,7 +146,9 @@ fun ReviewQualityCheckContextualOnboarding( Spacer(modifier = Modifier.height(16.dp)) Image( - painter = painterResource(id = R.drawable.shopping_onboarding), + // Removed to reduce APK size as part of https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/42386 + // Set to something else to make the compiler happy + painter = painterResource(id = R.drawable.mozac_lib_crash_notification), contentDescription = null, modifier = Modifier .fillMaxWidth() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingObserver.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingObserver.kt index 0e1544c5b56108eae7a320749fc82bcdd1c77520..fb99627643e930c7be22d2c26558631c9357d790 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingObserver.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingObserver.kt @@ -42,8 +42,9 @@ class PwaOnboardingObserver( it.content.webAppManifest } .collect { + @SuppressWarnings("CollapsibleIfStatements") if (webAppUseCases.isInstallable() && !settings.userKnowsAboutPwas) { - settings.incrementVisitedInstallableCount() + // settings.incrementVisitedInstallableCount() if (settings.shouldShowPwaCfr) { navigateToPwaOnboarding() settings.lastCfrShownTimeInMillis = System.currentTimeMillis() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt index 64025b4a9a57d96973c1957960c34e9b85d38390..c756180ebbcba72f0569c8638d0790945166f6c3 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt @@ -4,8 +4,10 @@ package org.mozilla.fenix.tabstray +import android.view.View import androidx.annotation.VisibleForTesting import androidx.viewpager2.widget.ViewPager2 +import androidx.core.view.isGone import com.google.android.material.tabs.TabLayout import mozilla.components.browser.state.store.BrowserStore import mozilla.components.support.base.feature.LifecycleAwareFeature @@ -35,6 +37,15 @@ class TabLayoutMediator( tabLayout.addOnTabSelectedListener(observer) selectActivePage() + + // Find normal mode tabs and set visibility + tabLayout.getTabAt(POSITION_NORMAL_TABS)?.getCustomView()?.apply { + // The View we get from getCustomView() is only a sub-component + // of the actual tab (for example, the tab-count box). We need + // the "Custom View"'s parent for controlling the visibility + // of the entire tab. + (getParent() as? View)?.isGone = true + } } override fun stop() { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt index 1d3111d6305328120a2b5c868c43015942c2eb05..fe25d3090022946bbeb7e44ff8999f3825870ab6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt @@ -47,6 +47,7 @@ import org.mozilla.fenix.compose.Divider import org.mozilla.fenix.compose.MenuItem import org.mozilla.fenix.compose.TabCounter import org.mozilla.fenix.compose.annotation.LightDarkPreview +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.tabstray.ext.getMenuItems import org.mozilla.fenix.theme.FirefoxTheme import kotlin.math.max @@ -191,6 +192,7 @@ private fun TabPageBanner( onTabPageIndicatorClicked: (Page) -> Unit, onDismissClick: () -> Unit, ) { + val shouldDisableNormalMode = LocalContext.current.settings().shouldDisableNormalMode val selectedColor = FirefoxTheme.colors.iconActive val inactiveColor = FirefoxTheme.colors.iconPrimaryInactive var showMenu by remember { mutableStateOf(false) } @@ -214,27 +216,29 @@ private fun TabPageBanner( horizontalArrangement = Arrangement.spacedBy(16.dp), ) { TabRow( - selectedTabIndex = selectedPage.ordinal, + selectedTabIndex = if (shouldDisableNormalMode) 0 else selectedPage.ordinal, modifier = Modifier.fillMaxWidth(MAX_WIDTH_TAB_ROW_PERCENT), backgroundColor = Color.Transparent, contentColor = selectedColor, divider = {}, ) { - Tab( - selected = selectedPage == Page.NormalTabs, - onClick = { onTabPageIndicatorClicked(Page.NormalTabs) }, - modifier = Modifier - .fillMaxHeight() - .testTag(TabsTrayTestTag.normalTabsPageButton), - selectedContentColor = selectedColor, - unselectedContentColor = inactiveColor, - ) { - val tabCounterAlpha = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) - TabCounter( - tabCount = normalTabCount, - textColor = tabCounterAlpha, - iconColor = tabCounterAlpha, - ) + if (!shouldDisableNormalMode) { + Tab( + selected = selectedPage == Page.NormalTabs, + onClick = { onTabPageIndicatorClicked(Page.NormalTabs) }, + modifier = Modifier + .fillMaxHeight() + .testTag(TabsTrayTestTag.normalTabsPageButton), + selectedContentColor = selectedColor, + unselectedContentColor = inactiveColor, + ) { + val tabCounterAlpha = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + TabCounter( + tabCount = normalTabCount, + textColor = tabCounterAlpha, + iconColor = tabCounterAlpha, + ) + } } Tab( @@ -253,6 +257,7 @@ private fun TabPageBanner( unselectedContentColor = inactiveColor, ) +/* Tab( selected = selectedPage == Page.SyncedTabs, onClick = { onTabPageIndicatorClicked(Page.SyncedTabs) }, @@ -268,6 +273,7 @@ private fun TabPageBanner( selectedContentColor = selectedColor, unselectedContentColor = inactiveColor, ) +*/ } Spacer(modifier = Modifier.weight(1.0f)) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsList.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsList.kt index a2a9aaefebe64eac5cc840f2d5068cf620b50934..aa18ea09888f1b2db71fb728812ab669dc64ea51 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsList.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsList.kt @@ -212,7 +212,7 @@ fun SyncedTabsErrorItem( PrimaryButton( text = it.buttonText, - icon = painterResource(R.drawable.ic_sign_in), + icon = painterResource(R.drawable.mozac_lib_crash_notification), onClick = it.onClick, ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.kt new file mode 100644 index 0000000000000000000000000000000000000000..98cad808a91fe92069be7c6cc7e21f2164773476 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.kt @@ -0,0 +1,280 @@ +package org.mozilla.fenix.tor + +import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.annotation.IntRange +import androidx.annotation.StringRes +import org.mozilla.fenix.R + +enum class ConnectAssistUiState( + val progressBarVisible: Boolean, + @IntRange(0, 100) var progress: Int = 0, + @ColorRes val progressTintColorResource: Int? = null, + val backButtonVisible: Boolean, + val settingsButtonVisible: Boolean, + val torConnectImageVisible: Boolean, + @DrawableRes val torConnectImageResource: Int = R.drawable.connect, + val titleLargeTextViewVisible: Boolean, + @StringRes val titleLargeTextViewTextStringResource: Int = R.string.connection_assist_tor_connect_title, + val titleDescriptionVisible: Boolean, + @StringRes val learnMoreStringResource: Int? = null, + @StringRes val internetErrorDescription: Int? = null, + @StringRes val internetErrorDescription1: Int? = null, + @StringRes val internetErrorDescription2: Int? = null, + @StringRes val titleDescriptionTextStringResource: Int? = R.string.preferences_tor_network_settings_explanation, + val quickstartSwitchVisible: Boolean, + val unblockTheInternetInCountryDescriptionVisible: Boolean, + val countryDropDownVisible: Boolean, + val torBootstrapButton1Visible: Boolean, + @StringRes val torBootstrapButton1TextStringResource: Int = R.string.tor_bootstrap_connect, + val torBootstrapButton1ShouldShowTryingABridge: Boolean = false, + val torBootstrapButton2Visible: Boolean, + @StringRes val torBootstrapButton2TextStringResource: Int? = R.string.connection_assist_configure_connection_button, + val torBootstrapButton2ShouldOpenSettings: Boolean = true, + val wordmarkLogoVisible: Boolean = false, + val torBootstrapButton2ShouldRestartApp: Boolean = false, +) { + Splash( + progressBarVisible = false, + backButtonVisible = false, + settingsButtonVisible = false, + torConnectImageVisible = false, + titleLargeTextViewVisible = false, + titleDescriptionVisible = false, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = false, + torBootstrapButton2Visible = false, + wordmarkLogoVisible = true, + ), + Configuring( + progressBarVisible = false, + progress = 0, + backButtonVisible = false, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_tor_connect_title, + titleDescriptionVisible = true, + titleDescriptionTextStringResource = R.string.preferences_tor_network_settings_explanation, + quickstartSwitchVisible = true, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = true, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.connection_assist_configure_connection_button, + torBootstrapButton2ShouldOpenSettings = true, + ), + Connecting( + progressBarVisible = true, + progress = 0, + backButtonVisible = false, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_connecting_title, + titleDescriptionVisible = true, + titleDescriptionTextStringResource = R.string.preferences_tor_network_settings_explanation, + quickstartSwitchVisible = true, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = false, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.btn_cancel, + torBootstrapButton2ShouldOpenSettings = false, + ), + InternetError( + progressBarVisible = true, + progress = 100, + progressTintColorResource = R.color.warning_yellow, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.globe_broken, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_internet_error_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_internet_error_learn_more, + internetErrorDescription = R.string.connection_assist_internet_error_description, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = true, + torBootstrapButton1TextStringResource = R.string.connection_assist_internet_error_try_again, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.connection_assist_configure_connection_button, + torBootstrapButton2ShouldOpenSettings = true, + ), + TryingAgain( + progressBarVisible = true, + progress = 0, + progressTintColorResource = null, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_trying_again_waiting_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_internet_error_learn_more, + internetErrorDescription = R.string.connection_assist_internet_error_description, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = false, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.btn_cancel, + torBootstrapButton2ShouldOpenSettings = false, + ), + ConnectionAssist( + progressBarVisible = true, + progress = 100, + progressTintColorResource = R.color.warning_yellow, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect_broken, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_cant_connect_to_tor_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_internet_error_learn_more, + internetErrorDescription = R.string.connection_assist_try_a_bridge_description, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = true, + countryDropDownVisible = true, + torBootstrapButton1Visible = true, + torBootstrapButton1TextStringResource = R.string.connection_assist_try_a_bridge_button, + torBootstrapButton1ShouldShowTryingABridge = true, + torBootstrapButton2Visible = false, + torBootstrapButton2TextStringResource = null, + torBootstrapButton2ShouldOpenSettings = true, + ), + TryingABridge( + progressBarVisible = true, + progress = 0, + progressTintColorResource = null, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_trying_a_bridge_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_internet_error_learn_more, + internetErrorDescription = R.string.connection_assist_try_a_bridge_description, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = true, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = false, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.btn_cancel, + torBootstrapButton2ShouldOpenSettings = false, + ), + LocationError( + progressBarVisible = true, + progress = 100, + progressTintColorResource = R.color.warning_yellow, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.browser_location, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_location_error_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_location_error_learn_more_link, + internetErrorDescription = R.string.connection_assist_location_error_description, + internetErrorDescription1 = R.string.connection_assist_find_bridge_location_description, + internetErrorDescription2 = R.string.connection_assist_select_country_try_again, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = true, + countryDropDownVisible = true, + torBootstrapButton1Visible = true, + torBootstrapButton1TextStringResource = R.string.connection_assist_try_a_bridge_button, + torBootstrapButton1ShouldShowTryingABridge = true, + torBootstrapButton2Visible = false, + torBootstrapButton2TextStringResource = null, + torBootstrapButton2ShouldOpenSettings = true, + ), + LocationCheck( + progressBarVisible = true, + progress = 100, + progressTintColorResource = R.color.warning_yellow, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.browser_location, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_location_check_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_location_error_learn_more_link, + internetErrorDescription = R.string.connection_assist_location_error_description, + internetErrorDescription1 = R.string.connection_assist_find_bridge_location_description, + internetErrorDescription2 = R.string.connection_assist_select_country_try_again, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = true, + countryDropDownVisible = true, + torBootstrapButton1Visible = true, + torBootstrapButton1TextStringResource = R.string.connection_assist_try_a_bridge_button, + torBootstrapButton1ShouldShowTryingABridge = true, + torBootstrapButton2Visible = false, + torBootstrapButton2TextStringResource = null, + torBootstrapButton2ShouldOpenSettings = true, + ), + LastTry( + progressBarVisible = true, + progress = 0, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_last_try_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_location_error_learn_more_link, + internetErrorDescription = R.string.connection_assist_location_error_description, + internetErrorDescription1 = R.string.connection_assist_find_bridge_location_description, + internetErrorDescription2 = R.string.connection_assist_select_country_try_again, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = true, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = false, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.btn_cancel, + torBootstrapButton2ShouldOpenSettings = false, + ), + FinalError( + progressBarVisible = true, + progress = 100, + progressTintColorResource = R.color.warning_yellow, + backButtonVisible = true, + settingsButtonVisible = true, + torConnectImageVisible = true, + torConnectImageResource = R.drawable.connect_broken, + titleLargeTextViewVisible = true, + titleLargeTextViewTextStringResource = R.string.connection_assist_final_error_title, + titleDescriptionVisible = true, + learnMoreStringResource = R.string.connection_assist_final_error_learn_more_link, + internetErrorDescription = R.string.connection_assist_final_error_description1, + internetErrorDescription1 = R.string.connection_assist_final_error_troubleshoot_connection_link, + titleDescriptionTextStringResource = null, + quickstartSwitchVisible = false, + unblockTheInternetInCountryDescriptionVisible = false, + countryDropDownVisible = false, + torBootstrapButton1Visible = true, + torBootstrapButton1TextStringResource = R.string.connection_assist_configure_connection_button, + torBootstrapButton2Visible = true, + torBootstrapButton2TextStringResource = R.string.mozac_lib_crash_dialog_button_restart, + torBootstrapButton2ShouldOpenSettings = false, + torBootstrapButton2ShouldRestartApp = true, + ) +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/QuickStartPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/QuickStartPreference.kt new file mode 100644 index 0000000000000000000000000000000000000000..c0ef358cb652159447721d43b8be9e24e574c3c4 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/QuickStartPreference.kt @@ -0,0 +1,32 @@ +package org.mozilla.fenix.tor + +import android.content.Context +import android.util.AttributeSet +import androidx.preference.PreferenceViewHolder +import androidx.preference.SwitchPreference +import com.google.android.material.switchmaterial.SwitchMaterial +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components + +class QuickStartPreference @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, +) : SwitchPreference(context, attrs) { + + private var switchView: SwitchMaterial? = null + + init { + widgetLayoutResource = R.layout.preference_quick_start + } + + override fun onBindViewHolder(holder: PreferenceViewHolder) { + super.onBindViewHolder(holder) + switchView = holder.findViewById(R.id.switch_widget) as SwitchMaterial + + updateSwitch() + } + + fun updateSwitch() { + switchView?.isChecked = context.components.torController.quickstart + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/SecurityLevel.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/SecurityLevel.kt new file mode 100644 index 0000000000000000000000000000000000000000..f5e4770666cd7f8d54983f5c6acdbf92e9973e76 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/SecurityLevel.kt @@ -0,0 +1,53 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.os.Parcelable +import androidx.annotation.StringRes +import kotlinx.parcelize.Parcelize +import org.mozilla.fenix.R + + +const val SECURITY_LEVEL_STANDARD = 4 +const val SECURITY_LEVEL_SAFER = 2 +const val SECURITY_LEVEL_SAFEST = 1 + +@Parcelize +enum class SecurityLevel( + @StringRes val preferenceKey: Int, + @StringRes val contentDescriptionRes: Int, + val intRepresentation: Int +) : Parcelable { + + STANDARD( + preferenceKey = R.string.pref_key_tor_security_level_standard_option, + contentDescriptionRes = R.string.tor_security_level_standard_description, + intRepresentation = SECURITY_LEVEL_STANDARD + ), + SAFER( + preferenceKey = R.string.pref_key_tor_security_level_safer_option, + contentDescriptionRes = R.string.tor_security_level_safer_description, + intRepresentation = SECURITY_LEVEL_SAFER + ), + SAFEST( + preferenceKey = R.string.pref_key_tor_security_level_safest_option, + contentDescriptionRes = R.string.tor_security_level_safest_description, + intRepresentation = SECURITY_LEVEL_SAFEST + ); + + + +} + +object SecurityLevelUtil { + fun getSecurityLevelFromInt(level: Int): SecurityLevel { + return when (level) { + SECURITY_LEVEL_STANDARD -> SecurityLevel.STANDARD + SECURITY_LEVEL_SAFER -> SecurityLevel.SAFER + SECURITY_LEVEL_SAFEST -> SecurityLevel.SAFEST + else -> throw IllegalStateException("Security Level $level is not valid") + } + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapStatus.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapStatus.kt new file mode 100644 index 0000000000000000000000000000000000000000..413f92c66978980a9ac4a58dafbc25db41e7b5f5 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapStatus.kt @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +@SuppressWarnings("LongParameterList", "TooManyFunctions") +class TorBootstrapStatus( + private val shouldStartTor: Boolean, + private val torController: TorController, + private val dispatchModeChanges: (isShouldBootstrap: Boolean) -> Unit + ) : TorEvents { + + init { + torController.registerTorListener(this) + } + + fun isBootstrapping() = (shouldStartTor && !torController.isBootstrapped) + + + @SuppressWarnings("EmptyFunctionBlock") + override fun onTorConnecting() { + } + + override fun onTorConnected() { + dispatchModeChanges(isBootstrapping()) + } + + override fun onTorStopped() { + dispatchModeChanges(isBootstrapping()) + } + + @SuppressWarnings("EmptyFunctionBlock") + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { + } + + fun unregisterTorListener() { + torController.unregisterTorListener(this) + } + + fun registerTorListener() { + torController.registerTorListener(this) + } + +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBridgeTransports.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBridgeTransports.kt new file mode 100644 index 0000000000000000000000000000000000000000..f2e5bb20f28c72caa045da84eaaad0f40f83e17b --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBridgeTransports.kt @@ -0,0 +1,48 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.os.Parcelable +import androidx.annotation.StringRes +import kotlinx.parcelize.Parcelize +import org.mozilla.fenix.R + +@Parcelize +enum class TorBridgeTransportConfig( + @StringRes val preferenceKey: Int, + val transportName: String +) : Parcelable { + + BUILTIN_OBFS4( + preferenceKey = R.string.pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4, + transportName = "obfs4" + ), + BUILTIN_MEEK_AZURE( + preferenceKey = R.string.pref_key_tor_network_settings_bridge_config_builtin_bridge_meek_azure, + transportName = "meek" + ), + BUILTIN_SNOWFLAKE( + preferenceKey = R.string.pref_key_tor_network_settings_bridge_config_builtin_bridge_snowflake, + transportName = "snowflake" + ), + USER_PROVIDED( + preferenceKey = R.string.pref_key_tor_network_settings_bridge_config_user_provided_bridge, + transportName = "user_provided" + ) +} + +object TorBridgeTransportConfigUtil { + fun getStringToBridgeTransport(bridge: String): TorBridgeTransportConfig { + return when (bridge) { + TorBridgeTransportConfig.BUILTIN_OBFS4.transportName -> + TorBridgeTransportConfig.BUILTIN_OBFS4 + TorBridgeTransportConfig.BUILTIN_MEEK_AZURE.transportName -> + TorBridgeTransportConfig.BUILTIN_MEEK_AZURE + TorBridgeTransportConfig.BUILTIN_SNOWFLAKE.transportName -> + TorBridgeTransportConfig.BUILTIN_SNOWFLAKE + else -> TorBridgeTransportConfig.USER_PROVIDED + } + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..a89aaf76046d5bd0f0b620254098ce6ef94fe0e7 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt @@ -0,0 +1,312 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.content.Intent +import android.graphics.Color +import android.os.Build +import android.os.Bundle +import android.text.SpannableString +import android.text.Spanned +import android.text.TextPaint +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.content.res.AppCompatResources +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.fragment.findNavController +import kotlinx.coroutines.launch +import mozilla.components.support.base.feature.UserInteractionHandler +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentTorConnectionAssistBinding +import org.mozilla.fenix.ext.hideToolbar + +class TorConnectionAssistFragment : Fragment(), UserInteractionHandler { + + private val TAG = "TorConnectionAssistFrag" + private val viewModel: TorConnectionAssistViewModel by activityViewModels() + private var _binding: FragmentTorConnectionAssistBinding? = null + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + _binding = FragmentTorConnectionAssistBinding.inflate( + inflater, container, false, + ) + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.collectLastKnownStatus() + } + } + + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.torConnectScreen.collect { screen -> + Log.d(TAG, "torConnectScreen is $screen") + showScreen(screen) + } + } + } + + return binding.root + } + + override fun onResume() { + super.onResume() + hideToolbar() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.progress().observe( + viewLifecycleOwner, + ) { progress -> + setProgressBarCompat(progress) + } + + viewModel.quickstartToggle().observe( + viewLifecycleOwner, + ) { + binding.quickstartSwitch.isChecked = it == true + } + + viewModel.shouldOpenHome().observe( + viewLifecycleOwner, + ) { + Log.d(TAG, "shouldOpenHome() = $it") + if (it) { + openHome() + } + } + + } + + private fun setProgressBarCompat(progress: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + binding.torBootstrapProgressBar.setProgress(progress, true) + } else { + binding.torBootstrapProgressBar.progress = progress + } + } + + private fun showScreen(screen: ConnectAssistUiState) { + setProgressBar(screen) + setSettingsButton(screen) + setBackButton(screen) + setTorConnectImage(screen) + setTitle(screen) + setQuickStart(screen) + setCountryDropDown(screen) + setButton1(screen) + setButton2(screen) + setSplashLogo(screen) + } + + private fun setProgressBar(screen: ConnectAssistUiState) { + binding.torBootstrapProgressBar.visibility = + if (screen.progressBarVisible) View.VISIBLE else View.GONE + binding.torBootstrapProgressBar.progress = screen.progress + binding.torBootstrapProgressBar.progressTintList = + screen.progressTintColorResource?.let { + AppCompatResources.getColorStateList( + requireContext(), + it, + ) + } + } + + private fun setSettingsButton(screen: ConnectAssistUiState) { + binding.settingsButton.visibility = if (screen.settingsButtonVisible) View.VISIBLE else View.GONE + binding.settingsButton.setOnClickListener { + openSettings() + } + } + + private fun setBackButton(screen: ConnectAssistUiState) { + binding.backButton.visibility = if (screen.backButtonVisible) View.VISIBLE else View.INVISIBLE + binding.backButton.setOnClickListener { + viewModel.handleBackButtonPressed() + } + } + + private fun setTorConnectImage(screen: ConnectAssistUiState) { + binding.torConnectImage.visibility = if (screen.torConnectImageVisible) View.VISIBLE else View.GONE + binding.torConnectImage.setImageResource(screen.torConnectImageResource) + } + + private fun setTitle(screen: ConnectAssistUiState) { + binding.titleLargeTextView.visibility = + if (screen.titleLargeTextViewVisible) View.VISIBLE else View.GONE + binding.titleLargeTextView.text = getString(screen.titleLargeTextViewTextStringResource) + binding.titleDescription.visibility = + if (screen.titleDescriptionVisible) View.VISIBLE else View.GONE + if (screen.learnMoreStringResource != null && screen.internetErrorDescription != null) { + val learnMore: String = getString(screen.learnMoreStringResource) + val internetErrorDescription: String = + if (screen.internetErrorDescription1 == null) { + getString( + screen.internetErrorDescription, + learnMore, + ) + } else if (screen.internetErrorDescription2 == null) { + getString( + screen.internetErrorDescription, + getString(screen.internetErrorDescription1), + learnMore, + ) + } else { + getString( + screen.internetErrorDescription, + getString(screen.internetErrorDescription1), + getString(screen.internetErrorDescription2), + learnMore, + ) + } + handleDescriptionWithClickable(internetErrorDescription, learnMore) + } else if (screen.titleDescriptionTextStringResource != null) { + binding.titleDescription.text = getString(screen.titleDescriptionTextStringResource) + } + } + + private fun setQuickStart(screen: ConnectAssistUiState) { + binding.quickstartSwitch.visibility = + if (screen.quickstartSwitchVisible) View.VISIBLE else View.GONE + binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true + binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked -> + viewModel.handleQuickstartChecked(isChecked) + } + } + + private fun setCountryDropDown(screen: ConnectAssistUiState) { + binding.unblockTheInternetInCountryDescription.visibility = + if (screen.unblockTheInternetInCountryDescriptionVisible) View.VISIBLE else View.GONE + binding.countryDropDown.visibility = if (screen.countryDropDownVisible) View.VISIBLE else View.GONE + } + + private fun setButton1(screen: ConnectAssistUiState) { + binding.torBootstrapButton1.visibility = + if (screen.torBootstrapButton1Visible) View.VISIBLE else View.GONE + binding.torBootstrapButton1.text = getString(screen.torBootstrapButton1TextStringResource) + binding.torBootstrapButton1.setOnClickListener { + viewModel.handleButton1Pressed( + screen, + lifecycleScope, + ) + } + } + + private fun setButton2(screen: ConnectAssistUiState) { + binding.torBootstrapButton2.visibility = + if (screen.torBootstrapButton2Visible) View.VISIBLE else View.GONE + if (screen.torBootstrapButton2ShouldRestartApp) { + binding.torBootstrapButton2.text = + screen.torBootstrapButton2TextStringResource?.let { + getString( + it, + getString(R.string.app_name), + ) + } + } else { + binding.torBootstrapButton2.text = + screen.torBootstrapButton2TextStringResource?.let { + getString( + it, + ) + } + } + binding.torBootstrapButton2.setOnClickListener { + viewModel.cancelTorBootstrap() + if (screen.torBootstrapButton2ShouldOpenSettings) { + openTorConnectionSettings() + } else if (screen.torBootstrapButton2ShouldRestartApp) { + restartApplication() + } else { + showScreen(ConnectAssistUiState.Configuring) + } + } + } + + private fun setSplashLogo(screen: ConnectAssistUiState) { + binding.wordmarkLogo.visibility = if (screen.wordmarkLogoVisible) View.VISIBLE else View.GONE + } + + /** + * from https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the-text-view-is-clickable + */ + private fun handleDescriptionWithClickable(errorDescription: String, learnMore: String) { + val errorDescriptionSpannableString = SpannableString(errorDescription) + val clickableSpan: ClickableSpan = object : ClickableSpan() { + override fun onClick(textView: View) { + showLearnMore() + } + + override fun updateDrawState(drawState: TextPaint) { + super.updateDrawState(drawState) + drawState.isUnderlineText = true + } + } + errorDescriptionSpannableString.setSpan( + clickableSpan, + errorDescription.length - learnMore.length, + errorDescription.length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, + ) + binding.titleDescription.text = errorDescriptionSpannableString + binding.titleDescription.movementMethod = LinkMovementMethod.getInstance() + binding.titleDescription.highlightColor = Color.TRANSPARENT + } + + private fun showLearnMore() { + Log.d(TAG, "showLearnMore() tapped") + //TODO("Not yet implemented") + } + + private fun openHome() { + Log.d(TAG, "openHome()") + viewModel.openHome(findNavController()) + } + + private fun openSettings(preferenceToScrollTo: String? = null) { + findNavController().navigate( + TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToSettingsFragment( + preferenceToScrollTo, + ), + ) + } + + private fun openTorConnectionSettings() { + findNavController().navigate( + TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToSettingsFragment( + requireContext().getString(R.string.pref_key_connection) + ), + ) + } + + private fun restartApplication() { + startActivity( + Intent(requireContext(), HomeActivity::class.java).addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK, + ), + ) + Runtime.getRuntime().exit(0) + } + + override fun onBackPressed(): Boolean { + return viewModel.handleBackButtonPressed() + } + +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..dd8e34edb5139f3609c30e6a433de6193ca85c90 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt @@ -0,0 +1,270 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.app.Application +import android.util.Log +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LifecycleCoroutineScope +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.navigation.NavController +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import org.mozilla.fenix.ext.components + +class TorConnectionAssistViewModel( + application: Application, +) : AndroidViewModel(application), TorEvents { + + private val TAG = "torConnectionAssistVM" + private val components = getApplication<Application>().components + + private val _torController: TorControllerGV = components.torController + + private val _torConnectScreen = MutableStateFlow(ConnectAssistUiState.Splash) + internal val torConnectScreen: StateFlow<ConnectAssistUiState> = _torConnectScreen + + private val _quickStartToggle = MutableLiveData<Boolean>() // don't initialize with quickstart off the bat + fun quickstartToggle(): LiveData<Boolean?> { + _quickStartToggle.value = _torController.quickstart // quickstart isn't ready until torSettings is ready + return _quickStartToggle + } + + + private val _shouldOpenHome = MutableLiveData(false) + fun shouldOpenHome(): LiveData<Boolean> { + return _shouldOpenHome + } + + private val _progress = MutableLiveData(0) + fun progress(): LiveData<Int> { + return _progress + } + + init { + Log.d(TAG, "initiating TorConnectionAssistViewModel $this") + _torController.registerTorListener(this) + } + + var urlToLoadAfterConnecting: String? = null + + fun handleConnect( + urlToLoadAfterConnecting: String? = null, + withDebugLogging: Boolean = false, + lifecycleScope: LifecycleCoroutineScope? = null, + ) { + this.urlToLoadAfterConnecting = urlToLoadAfterConnecting + if (_torController.lastKnownStatus.value.isOff()) { + Log.d(TAG, "handleConnect() triggered, initiatingTorBootstrap") + _torController.initiateTorBootstrap( + withDebugLogging = withDebugLogging, + lifecycleScope = lifecycleScope, + ) + } + } + + fun handleQuickstartChecked(checked: Boolean) { + _torController.quickstart = checked + _quickStartToggle.value = checked + } + + fun handleButton1Pressed( + screen: ConnectAssistUiState, + lifecycleScope: LifecycleCoroutineScope?, + ) { + if (screen.torBootstrapButton1ShouldShowTryingABridge) { + tryABridge() + } else { + handleConnect(lifecycleScope = lifecycleScope) + } + } + + fun cancelTorBootstrap() { + _torController.stopTor() + _torController.setTorStopped() + } + + override fun onTorConnecting() { + Log.d(TAG, "onTorConnecting()") + } + + override fun onTorConnected() { + Log.d(TAG, "onTorConnected()") + _torController.unregisterTorListener(this) + } + + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { + Log.d(TAG, "onTorStatusUpdate($entry, $status, $progress)") + if (progress != null) { + _progress.value = progress.toInt() + } + + } + + suspend fun collectLastKnownStatus() { + _torController.lastKnownStatus.collect { + when (it) { + TorConnectState.Initial -> _torConnectScreen.value = ConnectAssistUiState.Splash + TorConnectState.Configuring -> handleConfiguring() + TorConnectState.AutoBootstrapping -> handleBootstrap() + TorConnectState.Bootstrapping -> handleBootstrap() + TorConnectState.Bootstrapped -> _shouldOpenHome.value = true + TorConnectState.Disabled -> _shouldOpenHome.value = true + TorConnectState.Error -> handleError() + } + } + } + + private fun handleConfiguring() { + if (_torController.lastKnownError == null) { + _torConnectScreen.value = ConnectAssistUiState.Configuring + } else { + handleError() + } + } + + private fun handleBootstrap() { + when (_torConnectScreen.value) { + ConnectAssistUiState.InternetError -> { + _torConnectScreen.value = ConnectAssistUiState.TryingAgain + } + + ConnectAssistUiState.TryingAgain -> { + /** stay here */ + } + + ConnectAssistUiState.ConnectionAssist -> { + _torConnectScreen.value = ConnectAssistUiState.TryingABridge + } + + ConnectAssistUiState.LocationError -> { + _torConnectScreen.value = ConnectAssistUiState.TryingABridge + } + + ConnectAssistUiState.TryingABridge -> { + /** stay here */ + } + + ConnectAssistUiState.LocationCheck -> { + _torConnectScreen.value = ConnectAssistUiState.LastTry + } + + ConnectAssistUiState.LastTry -> { + /** stay here */ + } + + else -> _torConnectScreen.value = + ConnectAssistUiState.Connecting.also { connectAssistUiState -> + // covers the case of when the bootstrap is already in progress when the UiState "catches up" + connectAssistUiState.progress = _progress.value ?: 0 + } + } + } + + private fun handleError() { + _torController.lastKnownError?.apply { + Log.d( + TAG, + "TorError(message = $message, details = $details, phase = $phase, reason = $reason", + ) + // TODO better error handling + when (reason) { +// "noroute" -> handleNoRoute() TODO re-add when working better + else -> handleUnknownError() + } + } + } + + private fun handleNoRoute() { + Log.d(TAG, "handleNoRoute(), _torConnectScreen.value = ${_torConnectScreen.value}") + when (_torConnectScreen.value) { + ConnectAssistUiState.Connecting -> _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist + ConnectAssistUiState.ConnectionAssist -> {/** no op, likely a duplicate error */} + ConnectAssistUiState.TryingABridge -> _torConnectScreen.value = ConnectAssistUiState.LocationCheck + ConnectAssistUiState.LocationCheck -> {/** no op, likely a duplicate error */} + ConnectAssistUiState.LastTry -> _torConnectScreen.value = ConnectAssistUiState.FinalError + ConnectAssistUiState.FinalError -> {/** no op, likely a duplicate error */} + else -> _torConnectScreen.value = ConnectAssistUiState.InternetError + } + } + + private fun handleUnknownError() { + // TODO should we have a dedicated screen for unknown errors? + _torConnectScreen.value = ConnectAssistUiState.InternetError + } + + override fun onTorStopped() { + Log.d(TAG, "onTorStopped()") + } + + private fun tryABridge() { + if (!locationFound()) { + _torConnectScreen.value = ConnectAssistUiState.LocationError + return + } + if (!_torController.bridgesEnabled) { + _torController.bridgesEnabled = true + _torController.bridgeTransport = + TorBridgeTransportConfig.BUILTIN_SNOWFLAKE // TODO select based on country + } + handleConnect(withDebugLogging = true) + } + + private fun locationFound(): Boolean { + // TODO try to find location + return true + } + + fun handleBackButtonPressed(): Boolean { + when (torConnectScreen.value) { + ConnectAssistUiState.Splash -> return false + ConnectAssistUiState.Configuring -> return false + ConnectAssistUiState.Connecting -> cancelTorBootstrap() + ConnectAssistUiState.InternetError -> { + _torController.lastKnownError = null + _torConnectScreen.value = ConnectAssistUiState.Configuring + } + + ConnectAssistUiState.TryingAgain -> { + cancelTorBootstrap() + } + + ConnectAssistUiState.ConnectionAssist -> { + _torController.lastKnownError = null + _torConnectScreen.value = ConnectAssistUiState.Configuring + } + + ConnectAssistUiState.TryingABridge -> { + _torController.stopTor() + _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist + } + + ConnectAssistUiState.LocationError -> { + _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist + } + + ConnectAssistUiState.LocationCheck -> { + _torConnectScreen.value = ConnectAssistUiState.LocationError + } + + ConnectAssistUiState.LastTry -> { + _torController.stopTor() + _torConnectScreen.value = ConnectAssistUiState.LocationCheck + } + + ConnectAssistUiState.FinalError -> { + _torConnectScreen.value = ConnectAssistUiState.LocationCheck + } + } + return true + } + + fun openHome(navController: NavController) { + navController.navigate( + TorConnectionAssistFragmentDirections.actionHome(), + ) + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt new file mode 100644 index 0000000000000000000000000000000000000000..65d6ae456e26109f6908e0bc4f487c47948ac291 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt @@ -0,0 +1,65 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import androidx.lifecycle.LifecycleCoroutineScope + +interface TorEvents { + fun onTorConnecting() + fun onTorConnected() + fun onTorStatusUpdate(entry: String?, status: String?, progress: Double? = 0.0) + fun onTorStopped() +} +class TorError( + var message: String, + var details: String, + var phase: String, + var reason: String, +) { } + +interface TorLogs { + fun onLog(type: String?, message: String?, timestamp: String?) +} + +internal enum class TorStatus(val status: String) { + OFF("OFF"), + STARTING("STARTING"), + ON("ON"), + STOPPING("STOPPING"), + UNKNOWN("UNKNOWN"); +} + +interface TorController: TorEvents { + val logEntries: MutableList<TorLog> + val isStarting: Boolean + val isRestarting: Boolean + val isBootstrapped: Boolean + val isConnected: Boolean + var bridgesEnabled: Boolean + var bridgeTransport: TorBridgeTransportConfig + var userProvidedBridges: String? + var quickstart: Boolean + + fun start() + fun stop() + + override fun onTorConnecting() + override fun onTorConnected() + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) + override fun onTorStopped() + + fun getLastErrorState() : TorError? + + fun registerTorListener(l: TorEvents) + fun unregisterTorListener(l: TorEvents) + + fun registerTorLogListener(l: TorLogs) + fun unregisterTorLogListener(l: TorLogs) + + fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false) + fun stopTor() + fun setTorStopped() + fun restartTor() +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt new file mode 100644 index 0000000000000000000000000000000000000000..1d927a7d5141b8c6b28fecd6f8ccc6fa81ca77cc --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt @@ -0,0 +1,349 @@ +package org.mozilla.fenix.tor + + +import android.content.Context +import android.util.Log +import androidx.lifecycle.LifecycleCoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import mozilla.components.browser.engine.gecko.GeckoEngine +import org.mozilla.fenix.ext.components +import org.mozilla.geckoview.TorIntegrationAndroid +import org.mozilla.geckoview.TorIntegrationAndroid.BootstrapStateChangeListener +import org.mozilla.geckoview.TorIntegrationAndroid.TorLogListener +import org.mozilla.geckoview.TorSettings +import org.mozilla.geckoview.TorSettings.BridgeBuiltinType +import org.mozilla.geckoview.TorSettings.BridgeSource + +// Enum matching TorConnectState from TorConnect.sys.mjs that we get from onBootstrapStateChange +internal enum class TorConnectState(val state: String) { + Initial("Initial"), + Configuring("Configuring"), + AutoBootstrapping("AutoBootstrapping"), + Bootstrapping("Bootstrapping"), + Error("Error"), + Bootstrapped("Bootstrapped"), + Disabled("Disabled"); + + fun isStarting() = this == Bootstrapping || this == AutoBootstrapping + fun isError() = this == Error + + fun isStarted() = this == Bootstrapped + + fun isOff() = this == Initial || this == Configuring || this == Disabled || this == Error + + + // Convert to TorStatus that firefox-android uses based on tor-android-service + fun toTorStatus(): TorStatus { + return when (this) { + Initial -> TorStatus.OFF + Configuring -> TorStatus.OFF + AutoBootstrapping -> TorStatus.STARTING + Bootstrapping -> TorStatus.STARTING + Error -> TorStatus.UNKNOWN + Bootstrapped -> TorStatus.ON + Disabled -> TorStatus.OFF + } + } +} + +class TorControllerGV( + private val context: Context, +) : TorController, TorEvents, BootstrapStateChangeListener, TorLogListener { + + private val TAG = "TorControllerGV" + + private var torListeners = mutableListOf<TorEvents>() + private var torLogListeners = mutableListOf<TorLogs>() + + private val _lastKnownStatus = MutableStateFlow(TorConnectState.Initial) + internal val lastKnownStatus: StateFlow<TorConnectState> = _lastKnownStatus + + internal var lastKnownError: TorError? = null + private var wasTorBootstrapped = false + private var isTorRestarting = false + + private var isTorBootstrapped = false + get() = ((_lastKnownStatus.value.isStarted()) && wasTorBootstrapped) + + private val entries = mutableListOf<TorLog>() + override val logEntries get() = entries + override val isStarting get() = _lastKnownStatus.value.isStarting() + override val isRestarting get() = isTorRestarting + override val isBootstrapped get() = isTorBootstrapped + override val isConnected get() = (_lastKnownStatus.value.isStarted() && !isTorRestarting) + + override var quickstart: Boolean + get() { + return getTorSettings()?.quickstart ?: false + } + set(value) { + getTorSettings()?.let { + it.quickstart = value + getTorIntegration().setSettings(it) + } + } + + private fun getTorIntegration(): TorIntegrationAndroid { + return (context.components.core.engine as GeckoEngine).getTorIntegrationController() + } + + private fun getTorSettings(): TorSettings? { + return getTorIntegration().getSettings() + } + + + // On a fresh install bridgeEnagled can be set to true without a valid bridgeSource + // having been selected. After first use this will not happen because last selected bridge + // will be remembered and reused. + // However, on first use, submitting this to TorSettings is an invalid state. + // TorSettings.sys.mjs's #cleanupSettings will remove a lone bridgeEnabled with no source + // selected. Therefore we check and don't call setSettings if bridgeSource isn't selected + // (when trying to enable). Disabeling is always valid. + private var _bridgesEnabled: Boolean? = null + override var bridgesEnabled: Boolean + get() { + return _bridgesEnabled ?: getTorSettings()?.bridgesEnabled ?: false + } + set(value) { + _bridgesEnabled = value + getTorSettings()?.let { + if (!value || it.bridgesSource != BridgeSource.Invalid) { + it.bridgesEnabled = value + getTorIntegration().setSettings(it) + } + } + } + + + override var bridgeTransport: TorBridgeTransportConfig + get() { + return when (getTorSettings()?.bridgesSource) { + BridgeSource.BuiltIn -> { + when (getTorSettings()?.bridgesBuiltinType) { + BridgeBuiltinType.Obfs4 -> TorBridgeTransportConfig.BUILTIN_OBFS4 + BridgeBuiltinType.MeekAzure -> TorBridgeTransportConfig.BUILTIN_MEEK_AZURE + BridgeBuiltinType.Snowflake -> TorBridgeTransportConfig.BUILTIN_SNOWFLAKE + else -> TorBridgeTransportConfig.USER_PROVIDED + } + + } + + BridgeSource.UserProvided -> TorBridgeTransportConfig.USER_PROVIDED + else -> TorBridgeTransportConfig.USER_PROVIDED + } + } + set(value) { + getTorSettings()?.let { + it.bridgesEnabled = true + if (value == TorBridgeTransportConfig.USER_PROVIDED) { + // NOOP: all settings will be set in call to set userProvidedBridges and submited + // at the same time to clear TorSettings.sys.mjs #cleanupSettings + return + } else { + it.bridgesSource = BridgeSource.BuiltIn + val bbt: BridgeBuiltinType = when (value) { + TorBridgeTransportConfig.BUILTIN_OBFS4 -> BridgeBuiltinType.Obfs4 + TorBridgeTransportConfig.BUILTIN_MEEK_AZURE -> BridgeBuiltinType.MeekAzure + TorBridgeTransportConfig.BUILTIN_SNOWFLAKE -> BridgeBuiltinType.Snowflake + else -> BridgeBuiltinType.Invalid + } + it.bridgesBuiltinType = bbt + } + getTorIntegration().setSettings(it) + } + } + + + // Currently the UI takes a user provided string and sets this in one step so there is where we + // actually set it.bridgesSource = BridgeSource.UserProvided, not above, + // as TorSettings.sys.mjs #cleanupSettings could reject BridgeSource.UserProvided + // with no bridge strings + override var userProvidedBridges: String? + get() { + return getTorSettings()?.let { + if (it.bridgesSource == BridgeSource.UserProvided) { + return getTorSettings()?.bridgeBridgeStrings?.joinToString("\n") + } + return "" + } + } + set(value) { + getTorSettings()?.let { + Log.i(TAG, "setUserProvidedBridges: '$value'") + // Hack: we don't have validation so lets do something quick and dirty (each line has a length) + val userProvidedLines: Array<String> = value?.split("\n")?.filter { it.length > 4 }?.toTypedArray() ?: arrayOf<String>() + it.bridgesSource = BridgeSource.UserProvided + it.bridgeBridgeStrings = userProvidedLines + getTorIntegration().setSettings(it) + } + } + + override fun start() { + getTorIntegration().registerBootstrapStateChangeListener(this) + getTorIntegration().registerLogListener(this) + } + + override fun stop() { + getTorIntegration().unregisterBootstrapStateChangeListener(this) + getTorIntegration().unregisterLogListener(this) + } + + // TorEvents + override fun onTorConnecting() { + synchronized(torListeners) { + torListeners.toList().forEach { it.onTorConnecting() } + } + } + + // TorEvents + override fun onTorConnected() { + synchronized(torListeners) { + torListeners.toList().forEach { it.onTorConnected() } + } + } + + // TorEvents + override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { + synchronized(torListeners) { + torListeners.toList().forEach { it.onTorStatusUpdate(entry, status, progress) } + } + } + + // TorEvents + override fun onTorStopped() { + synchronized(torListeners) { + torListeners.toList().forEach { it.onTorStopped() } + } + } + + override fun onLog(type: String?, message: String?, timestamp: String?) { + synchronized(torLogListeners) { + entries.add(TorLog(type ?: "null", message ?: "null", timestamp ?: "null")) + torLogListeners.toList().forEach { it.onLog(type ?: "null", message ?: "null", timestamp) } + } + } + + override fun registerTorListener(l: TorEvents) { + synchronized(torListeners) { + if (torListeners.contains(l)) { + return + } + torListeners.add(l) + } + } + + override fun unregisterTorListener(l: TorEvents) { + synchronized(torListeners) { + if (!torListeners.contains(l)) { + return + } + torListeners.remove(l) + } + } + + override fun registerTorLogListener(l: TorLogs) { + synchronized(torLogListeners) { + if (torLogListeners.contains(l)) { + return + } + torLogListeners.add(l) + } + } + override fun unregisterTorLogListener(l: TorLogs) { + synchronized(torLogListeners) { + if (!torLogListeners.contains(l)) { + return + } + torLogListeners.remove(l) + } + } + + override fun initiateTorBootstrap( + lifecycleScope: LifecycleCoroutineScope?, + withDebugLogging: Boolean, + ) { + getTorIntegration().beginBootstrap() + } + + override fun stopTor() { + getTorIntegration().cancelBootstrap() + } + + override fun setTorStopped() { + _lastKnownStatus.value = TorConnectState.Configuring + onTorStatusUpdate(null, lastKnownStatus.toString(), 0.0) + onTorStopped() + } + + override fun restartTor() { + if (!_lastKnownStatus.value.isStarted() && wasTorBootstrapped) { + // If we aren't started, but we were previously bootstrapped, + // then we handle a "restart" request as a "start" restart + initiateTorBootstrap() + } else { + // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state + // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor + // service. + isTorRestarting = true + stopTor() + } + } + + override fun getLastErrorState() : TorError? { + return lastKnownError + } + + // TorEventsBootstrapStateChangeListener -> (lastKnowStatus, TorEvents) + // Handle events from GeckoView TorAndroidIntegration and map to TorEvents based events + // and state for firefox-android (designed for tor-android-service) + // fun onTorConnecting() + // fun onTorConnected() + // fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) + // fun onTorStopped() + + // TorEventsBootstrapStateChangeListener + override fun onBootstrapStateChange(newStateVal: String?) { + Log.d(TAG, "onBootstrapStateChange(newStateVal = $newStateVal)") + val newState: TorConnectState = TorConnectState.valueOf(newStateVal ?: "Error") + + if (newState.isError() && wasTorBootstrapped) { + stopTor() + } + + if (newState.isStarted()) { + wasTorBootstrapped = true + onTorConnected() + } + + if (wasTorBootstrapped && newState == TorConnectState.Configuring) { + wasTorBootstrapped = false + if (isTorRestarting) { + initiateTorBootstrap() + } else { + setTorStopped() + } + } + + if (_lastKnownStatus.value.isOff() && newState.isStarting()) { + isTorRestarting = false + } + + _lastKnownStatus.value = newState + onTorStatusUpdate(null, newStateVal, null) + } + + // TorEventsBootstrapStateChangeListener + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) { + Log.d(TAG, "onBootstrapProgress(progress = $progress, hasWarnings = $hasWarnings)") + onTorStatusUpdate("", _lastKnownStatus.value.toTorStatus().status, progress) + } + + // TorEventsBootstrapStateChangeListener + override fun onBootstrapComplete() = Unit + + // TorEventsBootstrapStateChangeListener + override fun onBootstrapError(code: String?, message: String?, phase: String?, reason: String?) { + lastKnownError = TorError(code ?: "", message ?: "", phase ?: "", reason ?: "") + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLog.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLog.kt new file mode 100644 index 0000000000000000000000000000000000000000..e36239a7e9648dcaec088ad5f2883e4acf38806b --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLog.kt @@ -0,0 +1,10 @@ +package org.mozilla.fenix.tor + +import androidx.compose.runtime.Stable + +@Stable +data class TorLog( + val type: String, + val text: String, + val timestamp: String, +) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsComposeFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsComposeFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..497a226ea963bc9dcdd87ed0c6821cf2f69238ba --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsComposeFragment.kt @@ -0,0 +1,138 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.DisableSelection +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.FloatingActionButton +import androidx.compose.material.Icon +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.Stable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.Observer +import androidx.lifecycle.compose.LocalLifecycleOwner +import mozilla.components.ui.colors.PhotonColors +import org.mozilla.fenix.R + +class TorLogsComposeFragment : Fragment() { + private val viewModel: TorLogsViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + return ComposeView(requireContext()).apply { + setContent { + Scaffold( + floatingActionButton = { CopyLogsButton() }, + content = { TorLogs(paddingValues = it) }, + ) + } + } + } + + @Composable + private fun TorLogs(paddingValues: PaddingValues) { + val torLogsState = remember { mutableStateOf<List<TorLog>>(emptyList()) } + val lifecycleOwner = LocalLifecycleOwner.current + val scrollState = rememberScrollState() + + DisposableEffect(viewModel.torLogs(), lifecycleOwner) { + val observer = Observer<List<TorLog>> { logs -> + torLogsState.value = logs + } + viewModel.torLogs().observe(lifecycleOwner, observer) + onDispose { + viewModel.torLogs().removeObserver(observer) + } + } + + val torLogs = torLogsState.value + + LaunchedEffect(torLogs) { + scrollState.animateScrollTo(scrollState.maxValue) + } + + SelectionContainer { + Column( + // Column instead of LazyColumn so that you can select all the logs, and not just one "screen" at a time + // The logs won't be too big so loading them all instead of just whats visible shouldn't be a big deal + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + .padding(paddingValues) + .background(PhotonColors.Ink50), // Standard background color + ) { + for (log in torLogs) { + LogRow(log = log) + } + } + } + } + + @Composable + @Stable + private fun LogRow(log: TorLog, modifier: Modifier = Modifier) { + Column( + modifier + .fillMaxWidth() + .padding( + start = 16.dp, + end = 16.dp, + bottom = 16.dp, + ), + ) { + Text( + text = log.timestamp, + color = PhotonColors.LightGrey40, + modifier = modifier + .padding(bottom = 4.dp), + ) + Text( + text = "[${log.type}] " + log.text, + color = PhotonColors.LightGrey05, + ) + } + } + + @Composable + private fun CopyLogsButton() { + FloatingActionButton( + onClick = { viewModel.copyAllLogsToClipboard() }, + content = { + Icon( + painter = painterResource(id = R.drawable.ic_copy), + contentDescription = getString(R.string.share_copy_link_to_clipboard), + ) + }, + backgroundColor = PhotonColors.Violet50, // Same color as connect button + contentColor = PhotonColors.LightGrey05, + ) + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsViewModel.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..145c5855dba1a640b7f95f7c89291541fc611cf7 --- /dev/null +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsViewModel.kt @@ -0,0 +1,83 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tor + +import android.app.Application +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.os.Build +import android.widget.Toast +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components + +class TorLogsViewModel(application: Application) : AndroidViewModel(application), TorLogs { + private val torController = application.components.torController + private val clipboardManager = + application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + + private val _torLogs: MutableLiveData<List<TorLog>> = MutableLiveData(mutableListOf()) + + fun torLogs(): LiveData<List<TorLog>> { + return _torLogs + } + + private fun addLog(log: TorLog) { + _torLogs.value = _torLogs.value?.plus(log) ?: return + } + + init { + setupClipboardListener() + torController.registerTorLogListener(this) + val currentEntries = torController.logEntries + for (log in currentEntries) { + addLog(log) + } + } + + override fun onLog(type: String?, message: String?, timestamp: String?) { + addLog(TorLog(type ?: "null", message ?: "null", timestamp ?: "null")) + } + + override fun onCleared() { + super.onCleared() + torController.unregisterTorLogListener(this) + } + + private fun setupClipboardListener() { + clipboardManager.addPrimaryClipChangedListener { + // Only show a toast for Android 12 and lower. + // https://developer.android.com/develop/ui/views/touch-and-input/copy-paste#duplicate-notifications + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + Toast.makeText( + getApplication<Application>().applicationContext, + getApplication<Application>().getString(R.string.toast_copy_link_to_clipboard), // "Copied to clipboard" already translated + Toast.LENGTH_SHORT, + ).show() + } + } + } + + fun copyAllLogsToClipboard() { + clipboardManager.setPrimaryClip( + ClipData.newPlainText( + getApplication<Application>().getString(R.string.preferences_tor_logs), + getAllTorLogs(), + ), + ) + } + + private fun getAllTorLogs(): String { + var ret = "" + for (log in torLogs().value + ?: return getApplication<Application>().getString(R.string.default_error_msg)) { + ret += "${log.timestamp} [${log.type}] ${log.text}\n" + } + return ret + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/ProtectionsStore.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/ProtectionsStore.kt index 4f876e92033f41440a0554b8f42edfed5c081c19..f99a70ed1a023df881056229124081feb69578c6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/ProtectionsStore.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/ProtectionsStore.kt @@ -52,9 +52,9 @@ sealed class ProtectionsAction : Action { * * @property url to report. */ - data class RequestReportSiteDomain( - val url: String, - ) : ProtectionsAction() +// data class RequestReportSiteDomain( +// val url: String, +// ) : ProtectionsAction() /** * Indicates that cookie banner handling mode has been updated. @@ -167,10 +167,10 @@ enum class CookieBannerUIMode( * REQUEST_UNSUPPORTED_SITE_SUBMITTED - The user submitted a request * for adding support for cookie banner handling for the domain. */ - REQUEST_UNSUPPORTED_SITE_SUBMITTED( - R.string.reduce_cookie_banner_unsupported_site_request_submitted_2, - R.drawable.ic_cookies_disabled, - ), +// REQUEST_UNSUPPORTED_SITE_SUBMITTED( +// R.string.reduce_cookie_banner_unsupported_site_request_submitted_2, +// R.drawable.ic_cookies_disabled, +// ), /** HIDE - All the cookie banner handling in the tracking panel is hidden. @@ -247,9 +247,9 @@ fun protectionsStateReducer( is ProtectionsAction.ToggleCookieBannerHandlingProtectionEnabled -> state.copy( cookieBannerUIMode = action.cookieBannerUIMode, ) - is ProtectionsAction.RequestReportSiteDomain -> state.copy( - url = action.url, - ) +// is ProtectionsAction.RequestReportSiteDomain -> state.copy( +// url = action.url, +// ) is ProtectionsAction.UpdateCookieBannerMode -> state.copy( cookieBannerUIMode = action.cookieBannerUIMode, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/NotificationBase.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/NotificationBase.kt index 93fe4e96a4399d78365bb5f20e1e0c4ea847c625..6fe8e1e57290ce9bb0025919272d515a4607e5bc 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/NotificationBase.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/NotificationBase.kt @@ -23,7 +23,7 @@ fun createBaseNotification( onDismiss: PendingIntent? = null, ): Notification { return NotificationCompat.Builder(context, channelId) - .setSmallIcon(R.drawable.ic_status_logo) + .setSmallIcon(R.drawable.mozac_lib_crash_notification) .setContentTitle(title) .setContentText(text) .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 596998e7677cffb045b16bb931683f06c3a80225..eaba998387ee20d70eccaa6acb787a5f901c212b 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -61,6 +61,7 @@ import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_AUDIBLE import org.mozilla.fenix.wallpapers.Wallpaper +import org.mozilla.fenix.tor.SecurityLevel import java.security.InvalidParameterException import java.util.UUID @@ -148,7 +149,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showTopSitesFeature by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_show_top_sites), featureFlag = true, - default = { homescreenSections[HomeScreenSection.TOP_SITES] == true }, + default = { true } ) var numberOfAppLaunches by intPreference( @@ -288,12 +289,12 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showWallpaperOnboarding by lazyFeatureFlagPreference( key = appContext.getPreferenceKey(R.string.pref_key_wallpapers_onboarding), featureFlag = true, - default = { mr2022Sections[Mr2022Section.WALLPAPERS_SELECTION_TOOL] == true }, + default = { true /* mr2022Sections[Mr2022Section.WALLPAPERS_SELECTION_TOOL] == true */ }, ) var openLinksInAPrivateTab by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_open_links_in_a_private_tab), - default = false, + default = true, ) var allowScreenshotsInPrivateMode by booleanPreference( @@ -306,6 +307,38 @@ class Settings(private val appContext: Context) : PreferencesHolder { false, ) + var standardSecurityLevel by booleanPreference( + appContext.getPreferenceKey(SecurityLevel.STANDARD.preferenceKey), + default = true + ) + + var saferSecurityLevel by booleanPreference( + appContext.getPreferenceKey(SecurityLevel.SAFER.preferenceKey), + default = false + ) + + var safestSecurityLevel by booleanPreference( + appContext.getPreferenceKey(SecurityLevel.SAFEST.preferenceKey), + default = false + ) + + // torSecurityLevel is defined as the first |true| preference, + // beginning at the safest level. + // If multiple preferences are true, then that is a bug and the + // highest |true| security level is chosen. + // Standard is the default level. + fun torSecurityLevel(): SecurityLevel = when { + safestSecurityLevel -> SecurityLevel.SAFEST + saferSecurityLevel -> SecurityLevel.SAFER + standardSecurityLevel -> SecurityLevel.STANDARD + else -> SecurityLevel.STANDARD + } + + var spoofEnglish by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_spoof_english), + default = false + ) + var defaultSearchEngineName by stringPreference( appContext.getPreferenceKey(R.string.pref_key_search_engine), default = "", @@ -340,7 +373,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var isTelemetryEnabled by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_telemetry), - default = true, + default = BuildConfig.DATA_COLLECTION_DISABLED == false ) var isMarketingTelemetryEnabled by booleanPreference( @@ -383,9 +416,14 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = 1f, ) + val shouldDisableNormalMode by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_disable_normal_mode), + true + ) + val shouldShowHistorySuggestions by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_search_browsing_history), - default = true, + default = !shouldDisableNormalMode, ) val shouldShowBookmarkSuggestions by booleanPreference( @@ -395,7 +433,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { val shouldShowSyncedTabsSuggestions by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_search_synced_tabs), - default = true, + default = false, ) val shouldShowClipboardSuggestions by booleanPreference( @@ -586,6 +624,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { /** * Get the display string for the current open links in apps setting */ + /* fun getOpenLinksInAppsString(): String = when (openLinksInExternalApp) { appContext.getString(R.string.pref_key_open_links_in_apps_always) -> { @@ -602,6 +641,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { appContext.getString(R.string.preferences_open_links_in_apps_never) } } + */ var shouldUseDarkTheme by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_dark_theme), @@ -615,7 +655,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var shouldUseHttpsOnly by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_https_only), - default = false, + default = true ) var shouldUseHttpsOnlyInAllTabs by booleanPreference( @@ -630,7 +670,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var shouldUseTrackingProtection by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_tracking_protection), - default = true, + default = false ) var shouldEnableGlobalPrivacyControl by booleanPreference( @@ -641,38 +681,38 @@ class Settings(private val appContext: Context) : PreferencesHolder { var shouldUseCookieBannerPrivateMode by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_cookie_banner_private_mode), featureFlag = true, - default = { shouldUseCookieBannerPrivateModeDefaultValue }, + default = { false /* shouldUseCookieBannerPrivateModeDefaultValue */ }, ) val shouldUseCookieBannerPrivateModeDefaultValue: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE_PBM] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE_PBM] == 1 val shouldUseCookieBanner: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE] == 1 val shouldShowCookieBannerUI: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_UI] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_UI] == 1 val shouldEnableCookieBannerDetectOnly: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_SETTING_DETECT_ONLY] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_SETTING_DETECT_ONLY] == 1 val shouldEnableCookieBannerGlobalRules: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_SETTING_GLOBAL_RULES] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_SETTING_GLOBAL_RULES] == 1 val shouldEnableCookieBannerGlobalRulesSubFrame: Boolean - get() = cookieBannersSection[CookieBannersSection.FEATURE_SETTING_GLOBAL_RULES_SUB_FRAMES] == 1 + get() = false // cookieBannersSection[CookieBannersSection.FEATURE_SETTING_GLOBAL_RULES_SUB_FRAMES] == 1 val shouldEnableQueryParameterStripping: Boolean - get() = queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING] == "1" + get() = true // queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING] == "1" val shouldEnableQueryParameterStrippingPrivateBrowsing: Boolean - get() = queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_PMB] == "1" + get() = true // queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_PMB] == "1" val queryParameterStrippingAllowList: String - get() = queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_ALLOW_LIST].orEmpty() + get() = "" // queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_ALLOW_LIST].orEmpty() val queryParameterStrippingStripList: String - get() = queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_STRIP_LIST].orEmpty() + get() = "" // queryParameterStrippingSection[QUERY_PARAMETER_STRIPPING_STRIP_LIST].orEmpty() /** * Declared as a function for performance purposes. This could be declared as a variable using @@ -722,7 +762,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ var reEngagementNotificationEnabled by lazyFeatureFlagPreference( key = appContext.getPreferenceKey(R.string.pref_key_re_engagement_notification_enabled), - default = { FxNimbus.features.reEngagementNotification.value().enabled }, + default = { false }, featureFlag = true, ) @@ -730,8 +770,8 @@ class Settings(private val appContext: Context) : PreferencesHolder { * Indicates if the re-engagement notification feature is enabled */ val reEngagementNotificationType: Int - get() = - FxNimbus.features.reEngagementNotification.value().type + get() = 0 // Neither Type A or B + // FxNimbus.features.reEngagementNotification.value().type val shouldUseAutoBatteryTheme by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_auto_battery_theme), @@ -782,7 +822,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) val enabledTotalCookieProtection: Boolean - get() = mr2022Sections[Mr2022Section.TCP_FEATURE] == true + get() = /*mr2022Sections[Mr2022Section.TCP_FEATURE] ==*/ false /** * Indicates if the total cookie protection CRF should be shown. @@ -872,11 +912,11 @@ class Settings(private val appContext: Context) : PreferencesHolder { return touchExplorationIsEnabled || switchServiceIsEnabled } - var lastKnownMode: BrowsingMode = BrowsingMode.Normal + var lastKnownMode: BrowsingMode = BrowsingMode.Private get() { val lastKnownModeWasPrivate = preferences.getBoolean( appContext.getPreferenceKey(R.string.pref_key_last_known_mode_private), - false, + shouldDisableNormalMode, ) return if (lastKnownModeWasPrivate) { @@ -1017,7 +1057,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { val shouldShowSearchSuggestions by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_show_search_suggestions), - default = true, + default = false, ) val shouldAutocompleteInAwesomebar by booleanPreference( @@ -1032,7 +1072,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var shouldShowSearchSuggestionsInPrivate by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_show_search_suggestions_in_private), - default = false, + default = shouldDisableNormalMode, ) var showSearchSuggestionsInPrivateOnboardingFinished by booleanPreference( @@ -1304,7 +1344,8 @@ class Settings(private val appContext: Context) : PreferencesHolder { numTimesPrivateModeOpened.value >= CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED } - if (showCondition && !showedPrivateModeContextualFeatureRecommender) { + if (!shouldDisableNormalMode && showCondition && + !showedPrivateModeContextualFeatureRecommender) { return true } @@ -1319,26 +1360,31 @@ class Settings(private val appContext: Context) : PreferencesHolder { /** * Check to see if we should open the link in an external app */ + @Suppress("UNUSED_PARAMETER") fun shouldOpenLinksInApp(isCustomTab: Boolean = false): Boolean { - return when (openLinksInExternalApp) { - appContext.getString(R.string.pref_key_open_links_in_apps_always) -> true - appContext.getString(R.string.pref_key_open_links_in_apps_ask) -> true + return false + //return when (openLinksInExternalApp) { + // appContext.getString(R.string.pref_key_open_links_in_apps_always) -> true + // appContext.getString(R.string.pref_key_open_links_in_apps_ask) -> true /* Some applications will not work if custom tab never open links in apps, return true if it's custom tab */ - appContext.getString(R.string.pref_key_open_links_in_apps_never) -> isCustomTab - else -> false - } + // appContext.getString(R.string.pref_key_open_links_in_apps_never) -> isCustomTab + //else -> false + //} } /** * Check to see if we need to prompt the user if the link can be opened in an external app */ fun shouldPromptOpenLinksInApp(): Boolean { + return true + /* return when (openLinksInExternalApp) { appContext.getString(R.string.pref_key_open_links_in_apps_always) -> false appContext.getString(R.string.pref_key_open_links_in_apps_ask) -> true appContext.getString(R.string.pref_key_open_links_in_apps_never) -> true else -> true } + */ } var openLinksInExternalApp by stringPreference( @@ -1526,25 +1572,27 @@ class Settings(private val appContext: Context) : PreferencesHolder { ).contains(langTag) } - private val mr2022Sections: Map<Mr2022Section, Boolean> - get() = - FxNimbus.features.mr2022.value().sectionsEnabled +// private val mr2022Sections: Map<Mr2022Section, Boolean> +// get() = +// FxNimbus.features.mr2022.value().sectionsEnabled - private val cookieBannersSection: Map<CookieBannersSection, Int> - get() = - FxNimbus.features.cookieBanners.value().sectionsEnabled +// private val cookieBannersSection: Map<CookieBannersSection, Int> +// get() = +// FxNimbus.features.cookieBanners.value().sectionsEnabled - private val queryParameterStrippingSection: Map<QueryParameterStrippingSection, String> - get() = - FxNimbus.features.queryParameterStripping.value().sectionsEnabled +// private val queryParameterStrippingSection: Map<QueryParameterStrippingSection, String> +// get() = +// FxNimbus.features.queryParameterStripping.value().sectionsEnabled - private val homescreenSections: Map<HomeScreenSection, Boolean> - get() = - FxNimbus.features.homescreen.value().sectionsEnabled +// private val homescreenSections: Map<HomeScreenSection, Boolean> +// get() = +// FxNimbus.features.homescreen.value().sectionsEnabled + // IN TOR BROWSER: we want to avoid ever calling Nimbus, so we hard-code defaults + // for everything that would have accessed this property. var historyMetadataUIFeature by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_history_metadata_feature), - default = { homescreenSections[HomeScreenSection.RECENT_EXPLORATIONS] == true }, + default = { true }, featureFlag = true, ) @@ -1554,7 +1602,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showSyncCFR by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_should_show_sync_cfr), featureFlag = true, - default = { mr2022Sections[Mr2022Section.SYNC_CFR] == true }, + default = { false /* mr2022Sections[Mr2022Section.SYNC_CFR] == true */ }, ) /** @@ -1563,7 +1611,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showHomeOnboardingDialog by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_should_show_home_onboarding_dialog), featureFlag = true, - default = { mr2022Sections[Mr2022Section.HOME_ONBOARDING_DIALOG_EXISTING_USERS] == true }, + default = { true /* mr2022Sections[Mr2022Section.HOME_ONBOARDING_DIALOG_EXISTING_USERS] == true */ }, ) /** @@ -1572,7 +1620,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showRecentTabsFeature by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_recent_tabs), featureFlag = true, - default = { homescreenSections[HomeScreenSection.JUMP_BACK_IN] == true }, + default = { true }, ) /** @@ -1580,7 +1628,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ var showBookmarksHomeFeature by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_customization_bookmarks), - default = { homescreenSections[HomeScreenSection.BOOKMARKS] == true }, + default = { true }, featureFlag = true, ) @@ -1606,7 +1654,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ var shouldAutofillCreditCardDetails by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_credit_cards_save_and_autofill_cards), - default = true, + default = BuildConfig.DATA_COLLECTION_DISABLED == false, ) /** @@ -1626,7 +1674,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var showPocketRecommendationsFeature by lazyFeatureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_pocket_homescreen_recommendations), featureFlag = FeatureFlags.isPocketRecommendationsFeatureEnabled(appContext), - default = { homescreenSections[HomeScreenSection.POCKET] == true }, + default = { false }, ) /** @@ -1634,7 +1682,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ val showPocketSponsoredStories by lazyFeatureFlagPreference( key = appContext.getPreferenceKey(R.string.pref_key_pocket_sponsored_stories), - default = { homescreenSections[HomeScreenSection.POCKET_SPONSORED_STORIES] == true }, + default = { false }, featureFlag = FeatureFlags.isPocketSponsoredStoriesFeatureEnabled(appContext), ) @@ -1709,8 +1757,8 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ fun shouldShowOnboarding(hasUserBeenOnboarded: Boolean, isLauncherIntent: Boolean): Boolean { return if (!hasUserBeenOnboarded && isLauncherIntent) { - FxNimbus.features.junoOnboarding.recordExposure() - true + // FxNimbus.features.junoOnboarding.recordExposure() + false } else { false } @@ -1927,6 +1975,21 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = false, ) + var noscriptInstalled by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_noscript_installed), + default = false + ) + + var noscriptUpdated by intPreference( + appContext.getPreferenceKey(R.string.pref_key_noscript_updated), + default = 0 + ) + + var httpsEverywhereRemoved by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_https_everywhere_removed), + default = false + ) + /** * Indicates if the new Search settings UI is enabled. */ @@ -1947,7 +2010,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { */ var enableFxSuggest by lazyFeatureFlagPreference( key = appContext.getPreferenceKey(R.string.pref_key_enable_fxsuggest), - default = { FxNimbus.features.fxSuggest.value().enabled }, + default = { false }, // { FxNimbus.features.fxSuggest.value().enabled }, featureFlag = FeatureFlags.fxSuggest, ) @@ -2204,4 +2267,9 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = { FxNimbus.features.bookmarks.value().newComposeUi }, featureFlag = true, ) + + var useHtmlConnectionUi by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_use_html_connection_ui), + default = false, + ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt index 658065e1bbab511458a2d618d87d80b9285350fe..496da804d1c1944e91a15a976978ee76664b6f53 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt @@ -171,14 +171,14 @@ class SearchWidgetProvider : AppWidgetProvider() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { setImageViewResource( R.id.button_search_widget_new_tab_icon, - R.drawable.ic_launcher_foreground, + R.mipmap.ic_launcher_foreground ) } else { setImageViewBitmap( R.id.button_search_widget_new_tab_icon, AppCompatResources.getDrawable( context, - R.drawable.ic_launcher_foreground, + R.mipmap.ic_launcher_foreground )?.toBitmap(), ) } diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.png b/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..4af23121eb4c1ba61d871dcbbb54c0eef9664888 Binary files /dev/null and b/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.png differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.webp b/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.webp deleted file mode 100644 index f7ab59cb987b009899d09395f7251d5a7853fdef..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-hdpi/fenix_search_widget.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 75aadf1b6c06f4ebef2a5b1862e28cd6bf83d3a6..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 9909b7b8d492af925a2d4f647a195418e835e174..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_no_analysis.webp deleted file mode 100644 index 9f6b45029621ff57c11a6ab52fe16bb428213267..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_onboarding.webp deleted file mode 100644 index f73288ac14c3500fc5ebb46b8f860ca7db82eec2..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-hdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index e17f36940437517d0f6b7a9025ffcc12688cd218..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 02a3f0281cc0c2a9c7a752c163fec96dcbda8c25..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-mdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_no_analysis.webp deleted file mode 100644 index 8857aa7e4c60b6ab7f1faf812e01262d99541bad..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_onboarding.webp deleted file mode 100644 index 925d64a93a634bacafdd5fedf0733ac5bc8a4936..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-mdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_no_analysis.webp deleted file mode 100644 index 9962a5a3bced8f2a87eca251eca31f783f9a7b78..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_onboarding.webp deleted file mode 100644 index 99dfa5d60560d1be3508cae5c58a326afc5d5f88..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-hdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_no_analysis.webp deleted file mode 100644 index f49811704affde853f7ad26f17b48a0735b80621..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_onboarding.webp deleted file mode 100644 index 9972cee8ed39a760691f22f67fb4fcbe66ed472f..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-mdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_no_analysis.webp deleted file mode 100644 index ae8a6a466119a6df58fecf91259e02c072a97f19..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_onboarding.webp deleted file mode 100644 index cf99284369231f609da8bb8cda09415c56333267..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_no_analysis.webp deleted file mode 100644 index 92c6f7c173e3e49596fd9c4111960c9536f35a35..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_onboarding.webp deleted file mode 100644 index 8a1606e6580442e2780da4bbb4447121cfb2dd02..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xxhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_no_analysis.webp deleted file mode 100644 index 0620484d2e3d3813a5fb4df0a61f8ef7fa69b388..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_onboarding.webp deleted file mode 100644 index 93242d9fdfbb8a7cd16834cf9aea7ac9d672e9ea..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-night-xxxhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-night/ic_logo_wordmark_normal.xml b/mobile/android/fenix/app/src/main/res/drawable-night/ic_logo_wordmark_normal.xml deleted file mode 100644 index accec68ac83dfd3b2444ae44f2da724cc9f1a01c..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable-night/ic_logo_wordmark_normal.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_logo_wordmark_private"/> diff --git a/mobile/android/fenix/app/src/main/res/drawable-night/onboarding_ctd_default_browser.xml b/mobile/android/fenix/app/src/main/res/drawable-night/onboarding_ctd_default_browser.xml deleted file mode 100644 index 14fd32702f55a09fa3fc1c425eeb27a7fecbbe69..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable-night/onboarding_ctd_default_browser.xml +++ /dev/null @@ -1,111 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="316dp" - android:height="304dp" - android:viewportWidth="316" - android:viewportHeight="304"> - <group> - <clip-path - android:pathData="M264.6,0L6.81,8.52L0,113.4L6.81,270.98L169.83,281.1H307.19V128.3L315.17,0H264.6Z"/> - <path - android:pathData="M-0.09,-14.57h441.06v388.85h-441.06z" - android:fillColor="#FFBDC5"/> - <path - android:pathData="M386.98,179.29L307.53,179.29A38.63,38.63 0,0 1,268.9 140.66L268.9,140.66A38.63,38.63 0,0 1,307.53 102.04L386.98,102.04A38.63,38.63 0,0 1,425.61 140.66L425.61,140.66A38.63,38.63 0,0 1,386.98 179.29z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,141.37m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M386.98,297.21L307.53,297.21A38.63,38.63 0,0 1,268.9 258.59L268.9,258.59A38.63,38.63 0,0 1,307.53 219.96L386.98,219.96A38.63,38.63 0,0 1,425.61 258.59L425.61,258.59A38.63,38.63 0,0 1,386.98 297.21z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,259.28m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M386.98,61.35L307.53,61.35A38.63,38.63 45,0 1,268.9 22.72L268.9,22.72A38.63,38.63 135,0 1,307.53 -15.9L386.98,-15.9A38.63,38.63 135,0 1,425.61 22.72L425.61,22.72A38.63,38.63 45,0 1,386.98 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,23.43m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M197.61,297.21L118.16,297.21A38.63,38.63 0,0 1,79.53 258.59L79.53,258.59A38.63,38.63 0,0 1,118.16 219.96L197.61,219.96A38.63,38.63 0,0 1,236.24 258.59L236.24,258.59A38.63,38.63 0,0 1,197.61 297.21z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M118.29,259.28m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M197.61,61.35L118.16,61.35A38.63,38.63 45,0 1,79.53 22.72L79.53,22.72A38.63,38.63 135,0 1,118.16 -15.9L197.61,-15.9A38.63,38.63 135,0 1,236.24 22.72L236.24,22.72A38.63,38.63 45,0 1,197.61 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M118.29,23.43m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M6.24,297.22L-73.21,297.22A38.63,38.63 0,0 1,-111.84 258.59L-111.84,258.59A38.63,38.63 0,0 1,-73.21 219.96L6.24,219.96A38.63,38.63 0,0 1,44.87 258.59L44.87,258.59A38.63,38.63 0,0 1,6.24 297.22z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M192.4,92.73L109.07,107.42A41.21,41.21 80.09,0 0,75.64 155.17L75.64,155.17A41.21,41.21 80.09,0 0,123.38 188.6L206.72,173.91A41.21,41.21 80.09,0 0,240.15 126.16L240.15,126.16A41.21,41.21 80.09,0 0,192.4 92.73z" - android:strokeWidth="2.19" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M198.57,132.74m33.08,-3.51a33.26,33.26 128.94,1 0,-66.16 7.03a33.26,33.26 128.94,1 0,66.16 -7.03" - android:strokeWidth="2.19" - android:fillColor="#2AC3A2" - android:strokeColor="#000000"/> - <path - android:pathData="M205.3,124.39m2.66,-0.28a2.68,2.68 128.94,1 0,-5.32 0.57a2.68,2.68 128.94,1 0,5.32 -0.57" - android:fillColor="#000000"/> - <path - android:pathData="M191.1,125.9m2.66,-0.28a2.68,2.68 128.94,1 0,-5.32 0.57a2.68,2.68 128.94,1 0,5.32 -0.57" - android:fillColor="#000000"/> - <path - android:pathData="M177.98,129.09C179.18,140.37 189.29,148.53 200.56,147.34C211.83,146.14 220,136.03 218.8,124.75" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="M6.24,179.29L-73.21,179.29A38.63,38.63 0,0 1,-111.84 140.66L-111.84,140.66A38.63,38.63 0,0 1,-73.21 102.04L6.24,102.04A38.63,38.63 0,0 1,44.87 140.66L44.87,140.66A38.63,38.63 0,0 1,6.24 179.29z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M6.24,61.35L-73.21,61.35A38.63,38.63 45,0 1,-111.84 22.72L-111.84,22.72A38.63,38.63 135,0 1,-73.21 -15.9L6.24,-15.9A38.63,38.63 0,0 1,44.87 22.72L44.87,22.72A38.63,38.63 0,0 1,6.24 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - </group> - <path - android:pathData="M185.29,263.99L193.01,244.47L37.44,240.82L33.38,265.98L24.27,270.75L29.86,300.24L187.19,304L198.89,295.67L197.17,265.98L185.29,263.99Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M52.58,271.72C47.67,271.72 44.41,268.07 44.41,263.53C44.41,258.87 47.89,255.33 52.58,255.33C55.67,255.33 58.27,256.9 59.69,259.26L56.34,261.38C55.62,259.96 54.36,259.07 52.61,259.07C50.07,259.07 48.3,261.06 48.3,263.53C48.3,265.95 50.03,267.94 52.56,267.94C54.46,267.94 55.78,266.85 56.43,265.34L59.95,267.22C58.6,269.86 55.99,271.72 52.58,271.72ZM70.19,271.5V265.36H64.97V271.5H61.14V255.55H64.97V261.6H70.19V255.55H74.01V271.5H70.19ZM74.94,271.5L80.84,255.55H84.51L90.41,271.5H86.54L85.71,269.12H79.61L78.78,271.5H74.94ZM82.67,260.44L80.79,265.8H84.55L82.67,260.44ZM91.32,271.5V255.55H95.14V267.85H102.1V271.5H91.32ZM103.67,271.5V255.55H107.49V267.85H114.44V271.5H103.67ZM116.01,271.5V255.55H127.03V259.09H119.82V261.71H127.03V265.25H119.82V267.96H127.03V271.5H116.01ZM128.9,271.5V255.55H132.87L138.88,265.12V255.55H142.51V271.5H138.82L132.54,261.47V271.5H128.9ZM152.46,271.72C147.26,271.72 144.09,267.94 144.09,263.53C144.09,258.89 147.5,255.33 152.31,255.33C155.37,255.33 157.62,256.6 159.13,258.54L155.94,260.79C155.17,259.61 153.95,258.94 152.33,258.94C149.86,258.94 147.9,260.9 147.9,263.53C147.9,266.24 149.75,268.09 152.4,268.09C154.23,268.09 155.52,267.17 156.07,265.6H151.63V262.06H160.2V263.88C160.2,268.09 157.07,271.72 152.46,271.72ZM161.83,271.5V255.55H172.84V259.09H165.63V261.71H172.84V265.25H165.63V267.96H172.84V271.5H161.83Z" - android:fillColor="#181818"/> - <path - android:pathData="M97.56,291.61V275.65H103.22C108.18,275.65 111.52,279.11 111.52,283.63C111.52,288.18 108.03,291.61 103.29,291.61H97.56ZM103.04,279.19H101.36V288.04H103.11C105.91,288.04 107.68,286.1 107.68,283.63C107.68,281.12 106.04,279.19 103.04,279.19ZM113.11,291.61V275.65H124.12V279.19H116.91V281.82H124.12V285.36H116.91V288.07H124.12V291.61H113.11ZM125.99,291.61V275.65H136.96V279.24H129.79V282.08H136.96V285.6H129.79V291.61H125.99ZM136.37,291.61L142.27,275.65H145.94L151.84,291.61H147.97L147.14,289.23H141.05L140.21,291.61H136.37ZM144.1,280.55L142.23,285.9H145.99L144.1,280.55ZM158.17,291.83C154.24,291.83 151.73,289.46 151.73,285.33V275.65H155.6V285.33C155.6,287.11 156.6,288.11 158.15,288.11C159.68,288.11 160.75,287.11 160.75,285.33V275.65H164.62V285.33C164.62,289.46 162.11,291.83 158.17,291.83ZM166.53,291.61V275.65H170.35V287.96H177.3V291.61H166.53ZM179.33,291.61V279.17H175.01V275.65H187.33V279.17H183.05V291.61H179.33Z" - android:fillColor="#181818"/> - <path - android:pathData="M50.88,291.61V279.17H46.55V275.65H58.88V279.17H54.59V291.61H50.88ZM69.59,291.61V285.47H64.37V291.61H60.55V275.65H64.37V281.71H69.59V275.65H73.42V291.61H69.59ZM75.39,291.61V275.65H86.41V279.19H79.19V281.82H86.41V285.36H79.19V288.07H86.41V291.61H75.39Z" - android:fillColor="#181818"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable-v23/splash_screen.xml b/mobile/android/fenix/app/src/main/res/drawable-v23/splash_screen.xml index 74d441577462747500fdcafd9ac098b5180497f2..b26895c298d4a787a0a9c341603eb378bc4bf4c3 100644 --- a/mobile/android/fenix/app/src/main/res/drawable-v23/splash_screen.xml +++ b/mobile/android/fenix/app/src/main/res/drawable-v23/splash_screen.xml @@ -4,8 +4,8 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item - android:drawable="@mipmap/ic_launcher_round" - android:width="160dp" - android:height="160dp" + android:drawable="@mipmap/ic_launcher_foreground" + android:width="192dp" + android:height="192dp" android:gravity="center" /> </layer-list> diff --git a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index d45952336f7fbd1dcddf47b040bb86e12d8f39b2..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index cac1470fb6bcc02d2d4c02d735b511d8b61a3f4d..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_no_analysis.webp deleted file mode 100644 index df6fcb9901aefa0675ad0eac94fe7a814f0f1a4f..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_onboarding.webp deleted file mode 100644 index 1d4ead34c2223f51f00d225b09056426410c1e0c..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 27ac27db2813e1080a8f711a58a14ca7c00a456d..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 7e085ce1938040acc5a0de6dbe973125cfb64117..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_no_analysis.webp deleted file mode 100644 index 9d1b79d6205e421af56a2c525cd02487fe7dfde8..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_onboarding.webp deleted file mode 100644 index 3d9cb1d184dbfcd6c8f8391bf950e7f862376340..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 9b82d62c4f4bd739dd45071c901b8d5d83244a18..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 66894b3cb6b624e906d22e4148fa70bbf2b8adfb..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_no_analysis.webp b/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_no_analysis.webp deleted file mode 100644 index 6aa8878bd614eeb4ca1d18ee144c701a6d5205df..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_no_analysis.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_onboarding.webp b/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_onboarding.webp deleted file mode 100644 index 791b0af3d13b3f31bd81335d06010ee9b3345f4c..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable-xxxhdpi/shopping_onboarding.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable/animated_splash_screen.xml b/mobile/android/fenix/app/src/main/res/drawable/animated_splash_screen.xml deleted file mode 100644 index e2b7ead51803a66037c7b90aba5e71fb8a523078..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/animated_splash_screen.xml +++ /dev/null @@ -1,1036 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" > - <aapt:attr name="android:drawable"> - <vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="432dp" - android:height="432dp" - android:viewportWidth="432" - android:viewportHeight="432"> - <group - android:name="a1_t" - android:pivotX="216" - android:pivotY="216"> - <path - android:pathData="M155.3,238.8l8.3,23.3l12.7,17l29.5,5.7l14.1,1.2l24.1,-6.1l10.4,-9.9L155.3,238.8z" - android:fillColor="#09204D"/> - <path - android:pathData="M280.6,204.4l-2.9,-9.8l-8.4,-16l-9.6,-10.2l-10.3,-7.4l-8.9,-3.4l-10.7,-3.8l-17.7,-1.2l-11.1,2.1l-9,2.7l-16.1,9.4l-10,11.3l-9.2,15l-3.6,12.9l-0.7,19.4l3.4,13.3l7.8,15.1l5.4,7.4l7.6,6.9l9.3,6.4l11.6,5l19.2,2.3l10.1,0.3l14.9,-4.2l13.3,-7.4l8.5,-7.4l6.7,-8l9.4,-18.5l2.2,-12.7L280.6,204.4z" - android:fillColor="#09204D"/> - <path - android:pathData="M212.3,161.5l-8,7.9l13,5.2l9.5,-11.9L212.3,161.5z" - android:fillColor="#0E56D7"/> - <path - android:pathData="M217.3,174.6l24.9,-0.8l-15.3,-11.1L217.3,174.6z" - android:fillColor="#1053D1"/> - <path - android:pathData="M240.2,162.6l-13.4,0.1l15.3,11.1l14.1,-1L240.2,162.6z" - android:fillColor="#0B4FBF"/> - <path - android:pathData="M256.3,172.9l-8,-11.2l11.2,6.7L256.3,172.9z" - android:fillColor="#0B48B0"/> - <path - android:pathData="M267,179.8l-10.7,-6.9l3,-4.4L267,179.8z" - android:fillColor="#0C45A7"/> - <path - android:pathData="M256.3,172.9l-1.9,7.7l9.7,3.9L256.3,172.9z" - android:fillColor="#0F46AF"/> - <path - android:pathData="M256.3,172.9l10.7,6.9l-2.7,4.7L256.3,172.9z" - android:fillColor="#0C47AD"/> - <path - android:pathData="M242.2,173.8l14.1,-1l-1.9,7.7L242.2,173.8z" - android:fillColor="#0E4FC3"/> - <path - android:pathData="M242.2,173.8L231,183.9l14.4,7.1L242.2,173.8z" - android:fillColor="#174DCA"/> - <path - android:pathData="M217.3,174.6l24.9,-0.8L231,183.9L217.3,174.6z" - android:fillColor="#1650D4"/> - <path - android:pathData="M254.6,180.6l6.8,13.3l2.9,-9.2L254.6,180.6z" - android:fillColor="#1246B2"/> - <path - android:pathData="M261.4,193.7l2.9,-9.2l7.2,17L261.4,193.7z" - android:fillColor="#133EA1"/> - <path - android:pathData="M264.4,184.4l10.9,8l-3.7,8.9L264.4,184.4z" - android:fillColor="#103D98"/> - <path - android:pathData="M267,179.8l2.2,-1.1l6.1,13.6L267,179.8z" - android:fillColor="#0B3785"/> - <path - android:pathData="M275.2,192.3l2.5,2.4l-8.4,-16L275.2,192.3z" - android:fillColor="#0B3685"/> - <path - android:pathData="M275.2,192.3l-8.1,-12.7l-2.7,4.7L275.2,192.3zM259.5,168.5l7.7,11.3l2.2,-1.1L259.5,168.5z" - android:fillColor="#0C3B91"/> - <path - android:pathData="M280.1,212.2l-2.5,-17.6l2.8,9.8L280.1,212.2L280.1,212.2z" - android:fillColor="#0B3279"/> - <path - android:pathData="M275.2,192.3l4.8,19.7l-2.5,-17.6L275.2,192.3z" - android:fillColor="#0F388D"/> - <path - android:pathData="M271.5,201.4l8.5,10.8l-4.8,-19.7L271.5,201.4z" - android:fillColor="#0D3481"/> - <path - android:pathData="M280,212.2l0.6,-7.8l0.6,19.6L280,212.2L280,212.2z" - android:fillColor="#0B2E71"/> - <path - android:pathData="M278.6,227.8l2.7,-3.5l-1.2,-12.1L278.6,227.8z" - android:fillColor="#0E2F77"/> - <path - android:pathData="M279.1,236.7l-2.1,1l4.1,-13.5L279.1,236.7z" - android:fillColor="#0E2969"/> - <path - android:pathData="M277.1,237.8l4.1,-13.5l-2.7,3.5L277.1,237.8z" - android:fillColor="#0C2A69"/> - <path - android:pathData="M278.6,227.8l1.5,-15.5l-4.4,5.2L278.6,227.8z" - android:fillColor="#123180"/> - <path - android:pathData="M277.1,237.8l1.6,-10l-8.4,14.2L277.1,237.8z" - android:fillColor="#112B70"/> - <path - android:pathData="M271.5,201.4l8.5,10.8l-4.4,5.2L271.5,201.4z" - android:fillColor="#12378C"/> - <path - android:pathData="M278.6,227.8l-2.9,-10.4l-4.4,12.9L278.6,227.8z" - android:fillColor="#122E7B"/> - <path - android:pathData="M269.7,255.2l7.4,-17.5l-6.9,12.8L269.7,255.2z" - android:fillColor="#11296C"/> - <path - android:pathData="M270.2,250.5l6.9,-12.8l-7,4.2L270.2,250.5z" - android:fillColor="#142A72"/> - <path - android:pathData="M277.1,237.8l-7.4,17.5l9.4,-18.5L277.1,237.8zM263,263.1l6.7,-8l0.5,-4.7L263,263.1zM254.5,270.5l8.5,-7.4l-9,4.1L254.5,270.5z" - android:fillColor="#112768"/> - <path - android:pathData="M204.4,275.5l-8.6,2.2l0.3,-6.1L204.4,275.5z" - android:fillColor="#1C226A"/> - <path - android:pathData="M156.2,193.1l2.5,-0.9l-6.1,13.6L156.2,193.1z" - android:fillColor="#182B7A"/> - <path - android:pathData="M152.6,206l4.5,-0.9l1.5,-12.9L152.6,206z" - android:fillColor="#1F308D"/> - <path - android:pathData="M152.9,222.5l-0.3,-16.5l4.5,-0.9L152.9,222.5z" - android:fillColor="#1E2B7F"/> - <path - android:pathData="M254.6,180.6l-9.1,10.5l16,2.7L254.6,180.6zM174.4,169.8l11.8,-8l-10.5,5.2L174.4,169.8z" - android:fillColor="#1346B5"/> - <path - android:pathData="M175.7,166.8l16.1,-9.4l-5.6,4.2L175.7,166.8" - android:fillColor="#1244AC"/> - <path - android:pathData="M186.2,161.7l14.7,-7.1l-9,2.7L186.2,161.7z" - android:fillColor="#0E4AB6"/> - <path - android:pathData="M242.2,173.8l3.1,17.3l9.1,-10.5L242.2,173.8zM195,160.8l13.6,-5.5l-8,-0.7L195,160.8z" - android:fillColor="#0E4BBA"/> - <path - android:pathData="M211.9,152.7l-11.1,2.1l8,0.7L211.9,152.7z" - android:fillColor="#0A4EBC"/> - <path - android:pathData="M222.5,155.2l-13.6,0.1l3.1,-2.7" - android:fillColor="#0C54CC"/> - <path - android:pathData="M248.3,161.7l-8,0.9l16.1,10.3L248.3,161.7zM222.5,155.2l17.9,2.4l-10.7,-3.8L222.5,155.2z" - android:fillColor="#0B4BB4"/> - <path - android:pathData="M248.3,161.7l-8,-4.1l8.9,3.4L248.3,161.7z" - android:fillColor="#0C3889"/> - <path - android:pathData="M155.3,238.8l5.3,4.3l-7.9,-20.6L155.3,238.8zM228.2,279.7l4.6,-10.9l-16.9,4.5L228.2,279.7zM232.8,268.8l14,3.9l0.9,-10.9L232.8,268.8z" - android:fillColor="#202575"/> - <path - android:pathData="M254,267.2l-6.2,-5.4l15,-10L254,267.2z" - android:fillColor="#1B2773"/> - <path - android:pathData="M262.7,251.8l-8.7,15.4l9,-4.1l7.2,-12.7L262.7,251.8z" - android:fillColor="#15276D"/> - <path - android:pathData="M249.2,161.1l-0.9,0.7l11.2,6.7L249.2,161.1zM240.2,162.6l8,-0.9l-8,-4.1V162.6z" - android:fillColor="#0C409D"/> - <path - android:pathData="M211.9,152.7l10.5,2.7l7.2,-1.5L211.9,152.7zM240.2,157.6l-17.9,-2.4l18,7.4L240.2,157.6z" - android:fillColor="#0B4CB7"/> - <path - android:pathData="M222.5,155.2l4.3,7.5l13.4,-0.1L222.5,155.2z" - android:fillColor="#0B55CE"/> - <path - android:pathData="M222.5,155.2l4.3,7.5l-14.5,-1.2L222.5,155.2z" - android:fillColor="#0A52C5"/> - <path - android:pathData="M208.7,155.3l3.4,6.2l10.2,-6.3L208.7,155.3z" - android:fillColor="#0951C4"/> - <path - android:pathData="M195,160.8l13.6,-5.5l3.4,6.2L195,160.8z" - android:fillColor="#0B50C4"/> - <path - android:pathData="M186.2,161.7l8.9,-0.8l5.8,-6.2L186.2,161.7zM195,160.8l9.2,8.4l8,-7.9L195,160.8z" - android:fillColor="#0F4DBF"/> - <path - android:pathData="M195,160.8L179.9,175l6.2,-13.4L195,160.8z" - android:fillColor="#1546B6"/> - <path - android:pathData="M179.9,175.1l9.6,1.7l5.5,-15.8L179.9,175.1z" - android:fillColor="#1549BD"/> - <path - android:pathData="M189.5,176.6l5.5,-15.8l9.2,8.4L189.5,176.6z" - android:fillColor="#144BC3"/> - <path - android:pathData="M165.4,178.1l0.6,5.7l8.1,-14L165.4,178.1z" - android:fillColor="#173794"/> - <path - android:pathData="M158.7,192.2l6.9,-14.1l0.6,5.7L158.7,192.2z" - android:fillColor="#192F84"/> - <path - android:pathData="M166.1,183.8l8.1,-14l5.6,5.3L166.1,183.8z" - android:fillColor="#1A389B"/> - <path - android:pathData="M165.5,196.1l0.5,-12.3l-7.6,8.4L165.5,196.1z" - android:fillColor="#1D3089"/> - <path - android:pathData="M165.5,196.1l0.5,-12.3l9.7,8L165.5,196.1z" - android:fillColor="#1E389F"/> - <path - android:pathData="M175.8,191.7l4,-16.7l-13.7,8.7L175.8,191.7z" - android:fillColor="#1C40AF"/> - <path - android:pathData="M175.8,191.7l4,-16.7l9.6,1.7L175.8,191.7z" - android:fillColor="#1E41B7"/> - <path - android:pathData="M157.2,205.2l1.5,-12.9l7,3.7L157.2,205.2z" - android:fillColor="#192C7D"/> - <path - android:pathData="M228.2,279.7l13.1,-2.1l5.8,-5L228.2,279.7zM151.9,225.4l1,-2.9l-0.3,-16.5L151.9,225.4zM157.2,205.2l-4.3,17.4l7.9,20.6l-3.8,-24L157.2,205.2z" - android:fillColor="#162467"/> - <path - android:pathData="M160.6,243.1l6.5,0.9l-4.5,-10.5L160.6,243.1z" - android:fillColor="#1A236A"/> - <path - android:pathData="M254,267.2l-7.1,5.5l-5.8,5l13.3,-7.4L254,267.2zM216.2,281.7l10.1,0.3l14.9,-4.2l-13.1,2.1L216.2,281.7zM166.6,255.1l6.8,1.3L167,244L166.6,255.1z" - android:fillColor="#132668"/> - <path - android:pathData="M196.1,271.7l-11.5,-8.7l-4.7,4.5l15.9,10.3L196.1,271.7zM155.3,238.8l7.8,15.1l-2.5,-10.8L155.3,238.8zM151.9,225.4l3.4,13.3l-2.6,-16.3L151.9,225.4zM215.9,273.3l-19.8,-1.9l8.3,3.9l-8.6,2.2l-10.4,-3.2l11.6,5l19.2,2.3l12.1,-2L215.9,273.3zM167.1,244l-6.5,-0.9l6,12L167.1,244zM156.9,219.1l3.8,24l2,-9.6L156.9,219.1zM173.4,256.3l-6.8,-1.3l-3.5,-1.2l5.4,7.4l7.6,6.9l9.3,6.4l-5.5,-7.1L173.4,256.3z" - android:fillColor="#1B2268"/> - <path - android:pathData="M157.2,205.2l9,14l-0.7,-23.2L157.2,205.2z" - android:fillColor="#212A81"/> - <path - android:pathData="M156.9,219.2l5.7,14.2l3.6,-14.2H156.9z" - android:fillColor="#21267A"/> - <path - android:pathData="M162.6,233.5l3.6,-14.2l4.5,11.3L162.6,233.5z" - android:fillColor="#262781"/> - <path - android:pathData="M167.1,244l17.5,10.8l-13.7,-24.2L167.1,244z" - android:fillColor="#272379"/> - <path - android:pathData="M163.1,253.9l3.5,1.2l-6,-12L163.1,253.9zM201.6,260.1l-5.5,11.5l19.8,1.9L201.6,260.1zM167.1,244l6.4,12.4l6.4,11l4.7,-4.5l-0.1,-8L167.1,244z" - android:fillColor="#1E226D"/> - <path - android:pathData="M247.8,261.7l-0.9,10.9l7.1,-5.5L247.8,261.7zM217.4,260.3l-1.5,13.2l16.9,-4.5l-0.6,-14.7L217.4,260.3z" - android:fillColor="#222475"/> - <path - android:pathData="M156.9,219.2h9.3l-9,-14L156.9,219.2zM232.2,254.1l0.6,14.7l14.9,-7.1L232.2,254.1z" - android:fillColor="#23277D"/> - <path - android:pathData="M232.2,254.1l9.6,-8.7l6,16.5L232.2,254.1z" - android:fillColor="#1E2776"/> - <path - android:pathData="M247.8,261.7l7.4,-22.1l-13.3,5.6L247.8,261.7z" - android:fillColor="#222B86"/> - <path - android:pathData="M262.7,251.8l-14.9,9.9l7.4,-22.1L262.7,251.8z" - android:fillColor="#192974"/> - <path - android:pathData="M270.2,241.9l-15,-2.3l7.8,12.1l7.5,-1.5L270.2,241.9z" - android:fillColor="#172A75"/> - <path - android:pathData="M271.2,230l-16.1,9.6l15,2.3l8.4,-14.2L271.2,230z" - android:fillColor="#172D7D"/> - <path - android:pathData="M158.7,192.2l6.9,-14.1l-9.2,15L158.7,192.2zM265.2,209.9l6,20.2l4.4,-12.9L265.2,209.9z" - android:fillColor="#18338A"/> - <path - android:pathData="M275.7,217.4l-4.1,-16l-6.4,8.4L275.7,217.4z" - android:fillColor="#153791"/> - <path - android:pathData="M255.1,239.8l16.1,-9.6l-15.6,-7L255.1,239.8z" - android:fillColor="#1B318B"/> - <path - android:pathData="M255.1,239.8L240.5,225l1.4,20.3L255.1,239.8z" - android:fillColor="#242D8D"/> - <path - android:pathData="M232.2,254.1l-11.2,-9.9l20.8,1.2L232.2,254.1z" - android:fillColor="#2A2B8F"/> - <path - android:pathData="M167.1,244l3.6,-13.4l-8.1,2.9L167.1,244zM221,244.2l-3.6,16.1l14.8,-6.2L221,244.2z" - android:fillColor="#27267F"/> - <path - android:pathData="M197.7,247.4l-10.8,-5.5l-2.6,12.9l17,5.3l15.8,0.2L197.7,247.4z" - android:fillColor="#2D2381"/> - <path - android:pathData="M217.4,260.3l3.6,-16.1l-23.3,3.2L217.4,260.3z" - android:fillColor="#2F2485"/> - <path - android:pathData="M166.2,219.1l4.6,-14.8l-5.3,-8.2L166.2,219.1z" - android:fillColor="#233196"/> - <path - android:pathData="M175.8,191.7l20.4,-6l-10.8,22.1L175.8,191.7z" - android:fillColor="#293CB7"/> - <path - android:pathData="M255.1,239.8L240.5,225l15.1,-1.9L255.1,239.8z" - android:fillColor="#25339C"/> - <path - android:pathData="M271.2,230l-6,-20.2l-9.6,13.3L271.2,230z" - android:fillColor="#19348F"/> - <path - android:pathData="M241.8,245.3l-16.7,-16.2l15.3,-4.2L241.8,245.3z" - android:fillColor="#2A309A"/> - <path - android:pathData="M221,244.2l20.8,1.2l-16.7,-16.2L221,244.2z" - android:fillColor="#302B96"/> - <path - android:pathData="M221,244.2l-11.4,-9.2l15.6,-5.7L221,244.2z" - android:fillColor="#3630A7"/> - <path - android:pathData="M174.4,169.8l1.3,-2.7l-10,11.3L174.4,169.8zM261.4,193.7l3.7,16.2l6.4,-8.4L261.4,193.7z" - android:fillColor="#173DA2"/> - <path - android:pathData="M175.8,191.7l9.6,16.1l-14.5,-3.4L175.8,191.7z" - android:fillColor="#2A36A8"/> - <path - android:pathData="M170.8,204.3l14.5,3.4l-9.8,15.5L170.8,204.3z" - android:fillColor="#312E9F"/> - <path - android:pathData="M196.3,185.8l8,-16.4l-14.7,7.4L196.3,185.8z" - android:fillColor="#184DCD"/> - <path - android:pathData="M166.2,219.1l9.3,4.1l-4.8,7.2L166.2,219.1z" - android:fillColor="#272986"/> - <path - android:pathData="M175.7,223.4l-4.8,7.2l13.6,24.2l2.6,-12.9L175.7,223.4z" - android:fillColor="#2C2584"/> - <path - android:pathData="M186.9,241.9l1.6,-22.6l-13,3.9L186.9,241.9z" - android:fillColor="#32268B"/> - <path - android:pathData="M186.9,241.9l22.6,-7.2l-21,-15.4L186.9,241.9z" - android:fillColor="#372999"/> - <path - android:pathData="M209.5,234.8l-2.3,-17.5l-18.8,2.1L209.5,234.8z" - android:fillColor="#392DA5"/> - <path - android:pathData="M207.4,217.5l15.9,-6l1.9,17.8L207.4,217.5z" - android:fillColor="#3338BC"/> - <path - android:pathData="M197.7,247.4l23.3,-3.2l-11.4,-9.2L197.7,247.4z" - android:fillColor="#362896"/> - <path - android:pathData="M197.7,247.4l-10.8,-5.5l22.6,-7.2L197.7,247.4z" - android:fillColor="#35268F"/> - <path - android:pathData="M196.3,185.8l13.7,1.5l-5.8,-17.9L196.3,185.8z" - android:fillColor="#2648D3"/> - <path - android:pathData="M217.3,174.6l-13,-5.2l5.8,17.9L217.3,174.6z" - android:fillColor="#1057DC"/> - <path - android:pathData="M217.3,174.6l13.6,9.4l-20.8,3.2L217.3,174.6z" - android:fillColor="#1653DA"/> - <path - android:pathData="M210.1,187.1l20.4,10.9l-7.3,13.4L210.1,187.1z" - android:fillColor="#2B46D5"/> - <path - android:pathData="M230.5,198l0.4,-14l-20.8,3.2L230.5,198z" - android:fillColor="#244AD7"/> - <path - android:pathData="M230.5,198l0.4,-14l14.4,7.1L230.5,198z" - android:fillColor="#2547CF"/> - <path - android:pathData="M210.1,187.1l13.3,24.2l-23.2,-11.6L210.1,187.1z" - android:fillColor="#333CC5"/> - <path - android:pathData="M207.4,217.5l15.9,-6l-23.2,-11.6L207.4,217.5z" - android:fillColor="#3833B6"/> - <path - android:pathData="M223.4,211.5l20.4,-3.7l-13.3,-9.6L223.4,211.5z" - android:fillColor="#2A41C6"/> - <path - android:pathData="M245.3,191.1l-1.7,16.7l-13.3,-9.6L245.3,191.1z" - android:fillColor="#2045C1"/> - <path - android:pathData="M245.3,191.1l9.6,13.2l-11.3,3.5L245.3,191.1z" - android:fillColor="#1B43B7"/> - <path - android:pathData="M261.4,193.7l-16,-2.7l9.6,13.2L261.4,193.7z" - android:fillColor="#1742AF"/> - <path - android:pathData="M180,175.1l6.2,-13.4l-11.8,8L180,175.1zM261.4,193.7l-6.4,10.4l10.1,5.7L261.4,193.7z" - android:fillColor="#1740A9"/> - <path - android:pathData="M255.7,223.2l9.6,-13.3l-10.1,-5.7L255.7,223.2z" - android:fillColor="#1B3CA4"/> - <path - android:pathData="M255.7,223.2l-0.6,-18.9l-11.3,3.5L255.7,223.2z" - android:fillColor="#1F3DAD"/> - <path - android:pathData="M175.8,191.7l20.4,-6l-6.8,-9L175.8,191.7zM223.4,211.5l17.2,13.5l3.2,-17.3L223.4,211.5z" - android:fillColor="#2543C3"/> - <path - android:pathData="M225.1,229.1l15.3,-4.2l-17.2,-13.5L225.1,229.1z" - android:fillColor="#2E37B2"/> - <path - android:pathData="M196.3,185.8l3.8,14l9.9,-12.7L196.3,185.8z" - android:fillColor="#2D40C7"/> - <path - android:pathData="M196.3,185.8l-10.8,22.1l14.6,-8L196.3,185.8z" - android:fillColor="#3537B8"/> - <path - android:pathData="M200.2,199.9l-11.7,19.5l18.8,-2.1L200.2,199.9z" - android:fillColor="#3931B0"/> - <path - android:pathData="M207.4,217.5l2.3,17.5l15.6,-5.7L207.4,217.5zM188.5,219.3l11.7,-19.5l-14.6,8L188.5,219.3z" - android:fillColor="#3735B8"/> - <path - android:pathData="M175.7,223.4l9.8,-15.5l3,11.6L175.7,223.4z" - android:fillColor="#342892"/> - <path - android:pathData="M185.4,274.4l10.4,3.2l-15.9,-10.3L185.4,274.4zM184.6,262.7l11.5,8.7l5.5,-11.5l-17,-5.3V262.7zM215.9,273.3l1.5,-13.2l-15.8,-0.2L215.9,273.3zM232.8,268.8l-4.6,10.9l18.7,-7.1L232.8,268.8z" - android:fillColor="#232372"/> - <path - android:pathData="M166.2,219.1l4.6,-14.8l4.7,18.9L166.2,219.1z" - android:fillColor="#2A2F96"/> - <path - android:pathData="M170.8,204.3l4.9,-12.7l-10.2,4.3L170.8,204.3zM243.7,207.7l-3.2,17.3l15.1,-1.9L243.7,207.7z" - android:fillColor="#2636A5"/> - <path - android:pathData="M281.5,224.1L281.5,224.1l-0.6,-19.7l0,0l-2.9,-9.8l0,0l-8.4,-16l-9.7,-10.3l0,0l-10.3,-7.4l0,0l-8.9,-3.4h-0.1l-10.7,-3.8h-0.1l-17.7,-1.2h-0.1l-11.1,2.1l0,0l-9,2.7h-0.1l-16.1,9.3l-10,11.2l-9.2,15l0,0l-3.6,12.9l0,0l-0.7,19.4v0.1l3.4,13.3l0,0l7.8,15.1l0,0l5.3,7.6l0,0l7.6,6.9l0,0l9.3,6.4l0,0l11.6,5h0.1l19.2,2.3l0,0l10.1,0.3h0.1l14.9,-4.2h0.1l13.3,-7.4l0,0l0,0l8.5,-7.4l6.7,-8l0,0l9.4,-18.5v0l2.1,-12.7l0,0V224.1zM176.1,267.8l-2,-1.8l4.3,3.3L176.1,267.8zM204.4,275.2l-6.9,-3.1l16.1,1.5L204.4,275.2zM207,217.2l-18,2l11,-18.6L207,217.2zM200.7,200.5l21.9,11l-15,5.6L200.7,200.5zM207.2,217.8l2.2,16.5l-19.9,-14.6L207.2,217.8zM208.9,234.7l-21.6,6.9l1.5,-21.6L208.9,234.7zM207.8,218.1l16.8,11.1l-14.6,5.3L207.8,218.1zM207.9,217.6l15,-5.6l1.8,16.8L207.9,217.6zM231.1,198.1l13.9,-6.6l-1.6,15.6L231.1,198.1zM243,207.7l-19.1,3.4l6.9,-12.6L243,207.7zM223.3,210.9l-12.5,-23l19.3,10.2L223.3,210.9zM222.6,210.8l-22,-11l9.4,-12.1L222.6,210.8zM188.6,218.6l-2.7,-10.7l13.4,-7.4L188.6,218.6zM186.7,241L176,223.5l12.2,-3.6L186.7,241zM208.5,235.4l-10.9,11.7l-9.9,-5.1L208.5,235.4zM224.6,229.6l-3.8,13.9l-10.7,-8.6L224.6,229.6zM223.7,212.2l16.2,12.8l-14.4,3.9L223.7,212.2zM223.9,211.7l19.3,-3.5l-3,16.4L223.9,211.7zM244.1,207.4l1.6,-15.5l8.9,12.2L244.1,207.4zM254.8,204.5l0.5,17.8l-11.1,-14.3L254.8,204.5zM230.8,197.5l0.4,-13.3l13.4,6.7L230.8,197.5zM230.2,197.5L211,187.3l19.6,-3L230.2,197.5zM200.3,199.2l-3.5,-13.2l13,1.4L200.3,199.2zM199.8,199.7l-13.6,7.5l10,-20.5L199.8,199.7zM188.1,219.1l-11.9,3.5l9,-14.2L188.1,219.1zM186.1,240.9l-14.8,-10.5l4.4,-6.6L186.1,240.9zM187.1,242.4l9.9,5.1l-12.3,6.8L187.1,242.4zM209.5,235.2l10.7,8.6l-21.7,3L209.5,235.2zM225.2,229.7L241,245l-19.6,-1.2L225.2,229.7zM225.7,229.3l14.4,-3.9l1.4,19.2L225.7,229.3zM243.9,208.4l11.2,14.5l-14.1,1.8L243.9,208.4zM255.4,204.6l9.4,5.3l-8.9,12.4L255.4,204.6zM255.5,204l5.9,-9.5l3.4,14.8L255.5,204zM255,203.6l-8.9,-12.2l14.8,2.5L255,203.6zM231.4,183.9l10.5,-9.5l2.9,16.2L231.4,183.9zM210.6,186.8l6.7,-11.9l12.9,8.7L210.6,186.8zM196.8,185.6l7.6,-15.4l5.4,16.8L196.8,185.6zM185.5,207.3l-9.1,-15.3l19.4,-5.7L185.5,207.3zM175.8,222.7l-4.4,-17.9L185,208L175.8,222.7zM170.7,229.8l-4,-10.1l8.3,3.6L170.7,229.8zM186.7,242.1l-2.4,11.9l-12.8,-22.5L186.7,242.1zM197.5,247.9l3.4,11.8l-15.8,-4.9L197.5,247.9zM220.6,244.6l-3.4,15.2l-18.7,-12.2L220.6,244.6zM241.1,245.5l-8.9,8l-10.4,-9.1L241.1,245.5zM240.7,225.7l13.6,13.8l-12.5,5.3L240.7,225.7zM241,225.2l14.1,-1.8l-0.5,15.6L241,225.2zM265.1,210.5l5.7,19L256,223L265.1,210.5zM261.7,194.4l9.2,7.1l-5.8,7.9L261.7,194.4zM245.9,190.9l8.5,-9.8l6.4,12.3L245.9,190.9zM245.5,190.5l-2.9,-16l11.6,6.3L245.5,190.5zM230.9,183.6l-12.9,-8.7l23.3,-0.7L230.9,183.6zM210.1,186.5l-5.4,-16.7l12.1,4.8L210.1,186.5zM196.3,185.3l-6.2,-8.3l13.6,-6.8L196.3,185.3zM195.8,185.7l-19,5.6l12.9,-13.9L195.8,185.7zM184.9,207.5l-13.5,-3.1l4.6,-11.8L184.9,207.5zM175.3,222.9l-8.5,-3.7l4.2,-13.5L175.3,222.9zM170.5,230.3L163,233l3.2,-13L170.5,230.3zM183.7,254l-16.3,-10l3.4,-12.7L183.7,254zM200.2,260.1l-15.3,2.5l-0.1,-7.3L200.2,260.1zM198.2,248.2l18.2,11.9l-14.6,-0.2L198.2,248.2zM221.1,244.8l10.5,9.2l-13.8,5.8L221.1,244.8zM241.7,245.8l5.6,15.3l-14.5,-7.3L241.7,245.8zM242.2,245.5l12.4,-5.2l-6.9,20.6L242.2,245.5zM255.9,223.7l14.7,6.6l-15.1,9L255.9,223.7zM265.7,210.6l9.6,6.9l-4.1,11.8L265.7,210.6zM265.6,209.8l5.8,-7.9l3.8,14.6L265.6,209.8zM261.6,193.6l2.7,-8.2l6.4,15.2L261.6,193.6zM261.3,192.9l-6.2,-11.9l8.7,3.5L261.3,192.9zM243.2,174.1l12.9,-0.9l-1.7,6.9L243.2,174.1zM217.9,174.3l9,-11.2l14.4,10.5L217.9,174.3zM217.4,174.1l-4.6,-12.2l13.5,1.1L217.4,174.1zM216.7,174.1l-11.9,-4.8l7.3,-7.3L216.7,174.1zM190.1,176l5.1,-14.7l8.6,8L190.1,176zM176.3,190.8l3.7,-15.3l8.8,1.5L176.3,190.8zM170.8,203.7l-4.8,-7.6l9.2,-3.9L170.8,203.7zM170.6,204.4l-4,13.1l-0.6,-20.3L170.6,204.4zM165.8,219.5l-3.3,13.1l-5.2,-13.1H165.8zM157.2,218.9l0.3,-12.9l8.2,12.9H157.2zM170.5,231l-3.3,12.2l-4,-9.4L170.5,231zM183.7,254.7l-10,1.5l-5.8,-11.3L183.7,254.7zM184.2,255.2l0.1,7.2l-9.9,-5.7L184.2,255.2zM201.1,260.6l-5.1,10.7l-10.6,-8.1L201.1,260.6zM201.7,260.7l13.4,12.5l-18.7,-1.7L201.7,260.7zM202.4,260.5l14.7,0.2l-1.4,12.3L202.4,260.5zM231.9,254.6l0.6,13.7l-14.4,-8L231.9,254.6zM232.5,254.7l14.5,7.3l-14,6.6L232.5,254.7zM255.2,240.4l7.3,11.4l-14,9.3L255.2,240.4zM255.7,240.1l13.9,2.1l-6.9,9L255.7,240.1zM255.9,239.7l14.9,-8.9l-1,11L255.9,239.7zM275.7,218.4l2.7,9.2l-6.7,2.2L275.7,218.4zM272.1,202.5l7.6,9.5l-3.8,4.6L272.1,202.5zM265.1,185.3l9.8,7.3l-3.3,8L265.1,185.3zM255,180.4l1.6,-6.8l7.1,10.2L255,180.4zM242.4,173.5l-1.8,-10.3l14.7,9.4L242.4,173.5zM241.7,173.2l-14,-10.2l12.4,-0.1L241.7,173.2zM213.2,161.3l9.1,-5.6l3.9,6.7L213.2,161.3zM204.3,169l-8.4,-7.9l15.7,0.6L204.3,169zM189.3,176.3l-8.8,-1.5l13.8,-13.1L189.3,176.3zM175.7,191.3l-9,-7.4l12.9,-8.1L175.7,191.3zM175.3,191.7l-9.3,3.9l0.5,-11.2L175.3,191.7zM165.8,218.3l-8.3,-13.1l7.9,-8.3L165.8,218.3zM162.3,233.6l-1.6,8l-3.1,-19.7L162.3,233.6zM162.7,234.5l3.9,9.1l-5.6,-0.8L162.7,234.5zM172.9,255.9l-5.9,-1.2l0.4,-9.7L172.9,255.9zM184.1,262.8l-4.2,4l-5.7,-9.7L184.1,262.8zM184.6,263.1l10.1,7.9l-14.3,-3.7L184.6,263.1zM217.6,260.8l14.4,8l-15.8,4.2L217.6,260.8zM247.4,262.3l-0.8,10l-13.1,-3.6L247.4,262.3zM261.8,252.8l-8,14l-5.7,-5L261.8,252.8zM269.8,242.9v7.4l-6.5,1.3L269.8,242.9zM271.5,230.3l6.6,-2.2l-7.5,12.6L271.5,230.3zM276,217.5l3.6,-4.3l-1.2,13.2L276,217.5zM271.9,201.4l3.2,-8l4.3,17.7L271.9,201.4zM264.7,184.4l2.4,-4l7.1,11L264.7,184.4zM264.3,183.9l-7,-9.9l9.2,5.9L264.3,183.9zM241.1,162.8l7.1,-0.8l7.1,9.7L241.1,162.8zM226.9,162.4l-3.8,-6.6l15.7,6.5L226.9,162.4zM212.4,161.1l-3,-5.4l12.2,-0.1L212.4,161.1zM211.7,161.2l-15.3,-0.6l12.3,-4.9L211.7,161.2zM180.9,173.9l5.5,-11.9l8,-0.8L180.9,173.9zM179.8,174.6l-5,-4.8l10.6,-7.3L179.8,174.6zM179.5,175.1l-12.5,8l7.5,-12.8L179.5,175.1zM165.3,195.6l-6.3,-3.3l6.7,-7.7L165.3,195.6zM165.1,196.2l-7.7,8.1l1.4,-11.6L165.1,196.2zM156.5,219l-3.1,2.7l3.4,-13.8L156.5,219zM156.6,219.7l3.2,20.5l-6.8,-17.8L156.6,219.7zM166.7,244.3l-0.4,9.6l-5.2,-10.4L166.7,244.3zM173.2,256.6l5.3,9.1l-11,-10.2L173.2,256.6zM195.7,271.8l-0.2,5.3l-13.9,-9L195.7,271.8zM196.3,271.9l7.3,3.3l-7.6,1.9L196.3,271.9zM215.6,273.7l0.2,7.5l-10.5,-5.5L215.6,273.7zM232.3,269.3l-4.2,10l-11.3,-5.9L232.3,269.3zM233,269.2l13.1,3.5l-17.3,6.5L233,269.2zM248,262.4l5.5,4.8l-6.3,4.9L248,262.4zM262.9,252.1l6.4,-1.3l-13.8,14.4L262.9,252.1zM270.5,249.4v-7.2l5.9,-3.5L270.5,249.4zM271,241.1l7.2,-12l-1.4,8.3L271,241.1zM280,215.3l0.9,8.7l-2,2.7L280,215.3zM275.7,193.2l1.7,1.6l1.7,11.8L275.7,193.2zM267.4,179.9l1.6,-0.8l4.4,10L267.4,179.9zM256.7,172.8l2.7,-3.8l6.6,9.7L256.7,172.8zM256.3,172.4l-7.1,-9.6l9.7,5.8L256.3,172.4zM240.5,162.3v-4.2l6.8,3.4L240.5,162.3zM240,162.2l-15.4,-6.4l15.3,2.1L240,162.2zM209.5,155l2.5,-2.2l8,2.1L209.5,155zM196.2,160l4.7,-5.1l6.6,0.6L196.2,160zM194.9,160.5l-7.3,0.7l11.9,-5.7L194.9,160.5zM175.1,169l0.8,-1.9l6.7,-3.2L175.1,169zM166.2,182.9l-0.5,-4.7l7.3,-6.9L166.2,182.9zM165.7,183.7l-6,6.8l5.5,-11.4L165.7,183.7zM156.9,204.9l-3.8,0.7l5,-11.5L156.9,204.9zM156.7,205.6l-3.6,14.7l-0.2,-13.9L156.7,205.6zM160,242.2l-4.3,-3.5l-2.2,-13.4L160,242.2zM166,254.6l-2.7,-0.9l-1.9,-8.2L166,254.6zM177.9,266.1l-9.1,-5l-1.5,-5L177.9,266.1zM179.6,267.5l3.9,5.1l-12.2,-9.5L179.6,267.5zM181.2,268.5l12.8,8.1l-8.2,-2.7L181.2,268.5zM204.3,275.9l9.8,5.1l-17.2,-3.3L204.3,275.9zM216.2,273.8l11,5.8l-10.8,1.8L216.2,273.8zM245.4,273.5l-4.4,3.8l-10.1,1.6L245.4,273.5zM253.8,267.7l0.4,2.5l-5.8,1.8L253.8,267.7zM268.7,252.3l-6,10.6l-7.7,3.4L268.7,252.3zM270.5,250.5l3.9,-7.4l-4.2,10.1L270.5,250.5zM278.8,227.9l1.6,-2.2l-2.5,8L278.8,227.9zM280.3,212.2V212l0.2,-2l0.2,5.1L280.3,212.2zM279.9,209.2l-1.6,-10.9l1.9,6.2L279.9,209.2zM275.5,192.1l-2.7,-6.3l3.8,7.3L275.5,192.1zM267.1,179.4l-5.5,-8l7.1,7.5L267.1,179.4zM248.8,161.7l0.4,-0.3l4.2,2.9L248.8,161.7zM248.3,161.4l-2.8,-1.5l3.1,1.3L248.3,161.4zM224.1,155.1l5.4,-1.1l8,2.8L224.1,155.1zM222.5,154.9l-7.4,-1.9l12.3,0.8L222.5,154.9zM208.5,155l-5.7,-0.5l8,-1.5L208.5,155zM188.5,160.1l3.2,-2.5l5.2,-1.7L188.5,160.1zM186,161.4l-2.7,1.5l4.3,-2.6L186,161.4zM174.1,169.6l-3.3,3.1l3.8,-4.2L174.1,169.6zM158.5,192l-1.5,0.6l5.8,-9.3L158.5,192zM156.4,193.4l1.7,-0.6l-4,9.2L156.4,193.4zM152.5,217.4l0.1,5.1l-0.3,1L152.5,217.4zM152.8,223.8l1.5,9.4l-2.1,-7.8L152.8,223.8zM160.3,243.3l1.9,8.3l-6,-11.8L160.3,243.3zM166.4,255.4l1.4,4.4l-3.8,-5.2L166.4,255.4zM195.6,277.8l0.6,0.9l-5.7,-2.6L195.6,277.8zM197.1,279.1l-0.7,-1.1l12.5,2.5L197.1,279.1zM227.4,280.2l-1.4,1.5l-6.9,-0.2L227.4,280.2zM228.4,280l8,-1.3l-9.3,2.7L228.4,280zM247,272.9l4.7,-1.5l-8.3,4.6L247,272.9zM254.7,269.9l-0.4,-2.5l7,-3.1L254.7,269.9zM269.7,251.7l-0.3,3.2l-4.5,5.5L269.7,251.7zM277.3,238l1.2,-0.6L273,248L277.3,238zM278.8,236.5l-1.4,0.7l2.7,-8.6L278.8,236.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="223.08" - android:centerY="184.89" - android:gradientRadius="77.77" - android:type="radial"> - <item android:offset="0.1" android:color="#6600DDFF"/> - <item android:offset="0.9" android:color="#3F7542E5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M281.5,224.1L281.5,224.1l-0.6,-19.7l0,0l-2.9,-9.8l0,0l-8.4,-16l-9.7,-10.3l0,0l-10.3,-7.4l0,0l-8.9,-3.4h-0.1l-10.7,-3.8h-0.1l-17.7,-1.2h-0.1l-11.1,2.1l0,0l-9,2.7h-0.1l-16.1,9.3l-10,11.2l-9.2,15l0,0l-3.6,12.9l0,0l-0.7,19.4v0.1l3.4,13.3l0,0l7.8,15.1l0,0l5.3,7.6l0,0l7.6,6.9l0,0l9.3,6.4l0,0l11.6,5h0.1l19.2,2.3l0,0l10.1,0.3h0.1l14.9,-4.2h0.1l13.3,-7.4l0,0l0,0l8.5,-7.4l6.7,-8l0,0l9.4,-18.5v0l2.1,-12.7l0,0V224.1zM176.1,267.8l-2,-1.8l4.3,3.3L176.1,267.8zM204.4,275.2l-6.9,-3.1l16.1,1.5L204.4,275.2zM207,217.2l-18,2l11,-18.6L207,217.2zM200.7,200.5l21.9,11l-15,5.6L200.7,200.5zM207.2,217.8l2.2,16.5l-19.9,-14.6L207.2,217.8zM208.9,234.7l-21.6,6.9l1.5,-21.6L208.9,234.7zM207.8,218.1l16.8,11.1l-14.6,5.3L207.8,218.1zM207.9,217.6l15,-5.6l1.8,16.8L207.9,217.6zM231.1,198.1l13.9,-6.6l-1.6,15.6L231.1,198.1zM243,207.7l-19.1,3.4l6.9,-12.6L243,207.7zM223.3,210.9l-12.5,-23l19.3,10.2L223.3,210.9zM222.6,210.8l-22,-11l9.4,-12.1L222.6,210.8zM188.6,218.6l-2.7,-10.7l13.4,-7.4L188.6,218.6zM186.7,241L176,223.5l12.2,-3.6L186.7,241zM208.5,235.4l-10.9,11.7l-9.9,-5.1L208.5,235.4zM224.6,229.6l-3.8,13.9l-10.7,-8.6L224.6,229.6zM223.7,212.2l16.2,12.8l-14.4,3.9L223.7,212.2zM223.9,211.7l19.3,-3.5l-3,16.4L223.9,211.7zM244.1,207.4l1.6,-15.5l8.9,12.2L244.1,207.4zM254.8,204.5l0.5,17.8l-11.1,-14.3L254.8,204.5zM230.8,197.5l0.4,-13.3l13.4,6.7L230.8,197.5zM230.2,197.5L211,187.3l19.6,-3L230.2,197.5zM200.3,199.2l-3.5,-13.2l13,1.4L200.3,199.2zM199.8,199.7l-13.6,7.5l10,-20.5L199.8,199.7zM188.1,219.1l-11.9,3.5l9,-14.2L188.1,219.1zM186.1,240.9l-14.8,-10.5l4.4,-6.6L186.1,240.9zM187.1,242.4l9.9,5.1l-12.3,6.8L187.1,242.4zM209.5,235.2l10.7,8.6l-21.7,3L209.5,235.2zM225.2,229.7L241,245l-19.6,-1.2L225.2,229.7zM225.7,229.3l14.4,-3.9l1.4,19.2L225.7,229.3zM243.9,208.4l11.2,14.5l-14.1,1.8L243.9,208.4zM255.4,204.6l9.4,5.3l-8.9,12.4L255.4,204.6zM255.5,204l5.9,-9.5l3.4,14.8L255.5,204zM255,203.6l-8.9,-12.2l14.8,2.5L255,203.6zM231.4,183.9l10.5,-9.5l2.9,16.2L231.4,183.9zM210.6,186.8l6.7,-11.9l12.9,8.7L210.6,186.8zM196.8,185.6l7.6,-15.4l5.4,16.8L196.8,185.6zM185.5,207.3l-9.1,-15.3l19.4,-5.7L185.5,207.3zM175.8,222.7l-4.4,-17.9L185,208L175.8,222.7zM170.7,229.8l-4,-10.1l8.3,3.6L170.7,229.8zM186.7,242.1l-2.4,11.9l-12.8,-22.5L186.7,242.1zM197.5,247.9l3.4,11.8l-15.8,-4.9L197.5,247.9zM220.6,244.6l-3.4,15.2l-18.7,-12.2L220.6,244.6zM241.1,245.5l-8.9,8l-10.4,-9.1L241.1,245.5zM240.7,225.7l13.6,13.8l-12.5,5.3L240.7,225.7zM241,225.2l14.1,-1.8l-0.5,15.6L241,225.2zM265.1,210.5l5.7,19L256,223L265.1,210.5zM261.7,194.4l9.2,7.1l-5.8,7.9L261.7,194.4zM245.9,190.9l8.5,-9.8l6.4,12.3L245.9,190.9zM245.5,190.5l-2.9,-16l11.6,6.3L245.5,190.5zM230.9,183.6l-12.9,-8.7l23.3,-0.7L230.9,183.6zM210.1,186.5l-5.4,-16.7l12.1,4.8L210.1,186.5zM196.3,185.3l-6.2,-8.3l13.6,-6.8L196.3,185.3zM195.8,185.7l-19,5.6l12.9,-13.9L195.8,185.7zM184.9,207.5l-13.5,-3.1l4.6,-11.8L184.9,207.5zM175.3,222.9l-8.5,-3.7l4.2,-13.5L175.3,222.9zM170.5,230.3L163,233l3.2,-13L170.5,230.3zM183.7,254l-16.3,-10l3.4,-12.7L183.7,254zM200.2,260.1l-15.3,2.5l-0.1,-7.3L200.2,260.1zM198.2,248.2l18.2,11.9l-14.6,-0.2L198.2,248.2zM221.1,244.8l10.5,9.2l-13.8,5.8L221.1,244.8zM241.7,245.8l5.6,15.3l-14.5,-7.3L241.7,245.8zM242.2,245.5l12.4,-5.2l-6.9,20.6L242.2,245.5zM255.9,223.7l14.7,6.6l-15.1,9L255.9,223.7zM265.7,210.6l9.6,6.9l-4.1,11.8L265.7,210.6zM265.6,209.8l5.8,-7.9l3.8,14.6L265.6,209.8zM261.6,193.6l2.7,-8.2l6.4,15.2L261.6,193.6zM261.3,192.9l-6.2,-11.9l8.7,3.5L261.3,192.9zM243.2,174.1l12.9,-0.9l-1.7,6.9L243.2,174.1zM217.9,174.3l9,-11.2l14.4,10.5L217.9,174.3zM217.4,174.1l-4.6,-12.2l13.5,1.1L217.4,174.1zM216.7,174.1l-11.9,-4.8l7.3,-7.3L216.7,174.1zM190.1,176l5.1,-14.7l8.6,8L190.1,176zM176.3,190.8l3.7,-15.3l8.8,1.5L176.3,190.8zM170.8,203.7l-4.8,-7.6l9.2,-3.9L170.8,203.7zM170.6,204.4l-4,13.1l-0.6,-20.3L170.6,204.4zM165.8,219.5l-3.3,13.1l-5.2,-13.1H165.8zM157.2,218.9l0.3,-12.9l8.2,12.9H157.2zM170.5,231l-3.3,12.2l-4,-9.4L170.5,231zM183.7,254.7l-10,1.5l-5.8,-11.3L183.7,254.7zM184.2,255.2l0.1,7.2l-9.9,-5.7L184.2,255.2zM201.1,260.6l-5.1,10.7l-10.6,-8.1L201.1,260.6zM201.7,260.7l13.4,12.5l-18.7,-1.7L201.7,260.7zM202.4,260.5l14.7,0.2l-1.4,12.3L202.4,260.5zM231.9,254.6l0.6,13.7l-14.4,-8L231.9,254.6zM232.5,254.7l14.5,7.3l-14,6.6L232.5,254.7zM255.2,240.4l7.3,11.4l-14,9.3L255.2,240.4zM255.7,240.1l13.9,2.1l-6.9,9L255.7,240.1zM255.9,239.7l14.9,-8.9l-1,11L255.9,239.7zM275.7,218.4l2.7,9.2l-6.7,2.2L275.7,218.4zM272.1,202.5l7.6,9.5l-3.8,4.6L272.1,202.5zM265.1,185.3l9.8,7.3l-3.3,8L265.1,185.3zM255,180.4l1.6,-6.8l7.1,10.2L255,180.4zM242.4,173.5l-1.8,-10.3l14.7,9.4L242.4,173.5zM241.7,173.2l-14,-10.2l12.4,-0.1L241.7,173.2zM213.2,161.3l9.1,-5.6l3.9,6.7L213.2,161.3zM204.3,169l-8.4,-7.9l15.7,0.6L204.3,169zM189.3,176.3l-8.8,-1.5l13.8,-13.1L189.3,176.3zM175.7,191.3l-9,-7.4l12.9,-8.1L175.7,191.3zM175.3,191.7l-9.3,3.9l0.5,-11.2L175.3,191.7zM165.8,218.3l-8.3,-13.1l7.9,-8.3L165.8,218.3zM162.3,233.6l-1.6,8l-3.1,-19.7L162.3,233.6zM162.7,234.5l3.9,9.1l-5.6,-0.8L162.7,234.5zM172.9,255.9l-5.9,-1.2l0.4,-9.7L172.9,255.9zM184.1,262.8l-4.2,4l-5.7,-9.7L184.1,262.8zM184.6,263.1l10.1,7.9l-14.3,-3.7L184.6,263.1zM217.6,260.8l14.4,8l-15.8,4.2L217.6,260.8zM247.4,262.3l-0.8,10l-13.1,-3.6L247.4,262.3zM261.8,252.8l-8,14l-5.7,-5L261.8,252.8zM269.8,242.9v7.4l-6.5,1.3L269.8,242.9zM271.5,230.3l6.6,-2.2l-7.5,12.6L271.5,230.3zM276,217.5l3.6,-4.3l-1.2,13.2L276,217.5zM271.9,201.4l3.2,-8l4.3,17.7L271.9,201.4zM264.7,184.4l2.4,-4l7.1,11L264.7,184.4zM264.3,183.9l-7,-9.9l9.2,5.9L264.3,183.9zM241.1,162.8l7.1,-0.8l7.1,9.7L241.1,162.8zM226.9,162.4l-3.8,-6.6l15.7,6.5L226.9,162.4zM212.4,161.1l-3,-5.4l12.2,-0.1L212.4,161.1zM211.7,161.2l-15.3,-0.6l12.3,-4.9L211.7,161.2zM180.9,173.9l5.5,-11.9l8,-0.8L180.9,173.9zM179.8,174.6l-5,-4.8l10.6,-7.3L179.8,174.6zM179.5,175.1l-12.5,8l7.5,-12.8L179.5,175.1zM165.3,195.6l-6.3,-3.3l6.7,-7.7L165.3,195.6zM165.1,196.2l-7.7,8.1l1.4,-11.6L165.1,196.2zM156.5,219l-3.1,2.7l3.4,-13.8L156.5,219zM156.6,219.7l3.2,20.5l-6.8,-17.8L156.6,219.7zM166.7,244.3l-0.4,9.6l-5.2,-10.4L166.7,244.3zM173.2,256.6l5.3,9.1l-11,-10.2L173.2,256.6zM195.7,271.8l-0.2,5.3l-13.9,-9L195.7,271.8zM196.3,271.9l7.3,3.3l-7.6,1.9L196.3,271.9zM215.6,273.7l0.2,7.5l-10.5,-5.5L215.6,273.7zM232.3,269.3l-4.2,10l-11.3,-5.9L232.3,269.3zM233,269.2l13.1,3.5l-17.3,6.5L233,269.2zM248,262.4l5.5,4.8l-6.3,4.9L248,262.4zM262.9,252.1l6.4,-1.3l-13.8,14.4L262.9,252.1zM270.5,249.4v-7.2l5.9,-3.5L270.5,249.4zM271,241.1l7.2,-12l-1.4,8.3L271,241.1zM280,215.3l0.9,8.7l-2,2.7L280,215.3zM275.7,193.2l1.7,1.6l1.7,11.8L275.7,193.2zM267.4,179.9l1.6,-0.8l4.4,10L267.4,179.9zM256.7,172.8l2.7,-3.8l6.6,9.7L256.7,172.8zM256.3,172.4l-7.1,-9.6l9.7,5.8L256.3,172.4zM240.5,162.3v-4.2l6.8,3.4L240.5,162.3zM240,162.2l-15.4,-6.4l15.3,2.1L240,162.2zM209.5,155l2.5,-2.2l8,2.1L209.5,155zM196.2,160l4.7,-5.1l6.6,0.6L196.2,160zM194.9,160.5l-7.3,0.7l11.9,-5.7L194.9,160.5zM175.1,169l0.8,-1.9l6.7,-3.2L175.1,169zM166.2,182.9l-0.5,-4.7l7.3,-6.9L166.2,182.9zM165.7,183.7l-6,6.8l5.5,-11.4L165.7,183.7zM156.9,204.9l-3.8,0.7l5,-11.5L156.9,204.9zM156.7,205.6l-3.6,14.7l-0.2,-13.9L156.7,205.6zM160,242.2l-4.3,-3.5l-2.2,-13.4L160,242.2zM166,254.6l-2.7,-0.9l-1.9,-8.2L166,254.6zM177.9,266.1l-9.1,-5l-1.5,-5L177.9,266.1zM179.6,267.5l3.9,5.1l-12.2,-9.5L179.6,267.5zM181.2,268.5l12.8,8.1l-8.2,-2.7L181.2,268.5zM204.3,275.9l9.8,5.1l-17.2,-3.3L204.3,275.9zM216.2,273.8l11,5.8l-10.8,1.8L216.2,273.8zM245.4,273.5l-4.4,3.8l-10.1,1.6L245.4,273.5zM253.8,267.7l0.4,2.5l-5.8,1.8L253.8,267.7zM268.7,252.3l-6,10.6l-7.7,3.4L268.7,252.3zM270.5,250.5l3.9,-7.4l-4.2,10.1L270.5,250.5zM278.8,227.9l1.6,-2.2l-2.5,8L278.8,227.9zM280.3,212.2V212l0.2,-2l0.2,5.1L280.3,212.2zM279.9,209.2l-1.6,-10.9l1.9,6.2L279.9,209.2zM275.5,192.1l-2.7,-6.3l3.8,7.3L275.5,192.1zM267.1,179.4l-5.5,-8l7.1,7.5L267.1,179.4zM248.8,161.7l0.4,-0.3l4.2,2.9L248.8,161.7zM248.3,161.4l-2.8,-1.5l3.1,1.3L248.3,161.4zM224.1,155.1l5.4,-1.1l8,2.8L224.1,155.1zM222.5,154.9l-7.4,-1.9l12.3,0.8L222.5,154.9zM208.5,155l-5.7,-0.5l8,-1.5L208.5,155zM188.5,160.1l3.2,-2.5l5.2,-1.7L188.5,160.1zM186,161.4l-2.7,1.5l4.3,-2.6L186,161.4zM174.1,169.6l-3.3,3.1l3.8,-4.2L174.1,169.6zM158.5,192l-1.5,0.6l5.8,-9.3L158.5,192zM156.4,193.4l1.7,-0.6l-4,9.2L156.4,193.4zM152.5,217.4l0.1,5.1l-0.3,1L152.5,217.4zM152.8,223.8l1.5,9.4l-2.1,-7.8L152.8,223.8zM160.3,243.3l1.9,8.3l-6,-11.8L160.3,243.3zM166.4,255.4l1.4,4.4l-3.8,-5.2L166.4,255.4zM195.6,277.8l0.6,0.9l-5.7,-2.6L195.6,277.8zM197.1,279.1l-0.7,-1.1l12.5,2.5L197.1,279.1zM227.4,280.2l-1.4,1.5l-6.9,-0.2L227.4,280.2zM228.4,280l8,-1.3l-9.3,2.7L228.4,280zM247,272.9l4.7,-1.5l-8.3,4.6L247,272.9zM254.7,269.9l-0.4,-2.5l7,-3.1L254.7,269.9zM269.7,251.7l-0.3,3.2l-4.5,5.5L269.7,251.7zM277.3,238l1.2,-0.6L273,248L277.3,238zM278.8,236.5l-1.4,0.7l2.7,-8.6L278.8,236.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="215.6" - android:centerY="220.76" - android:gradientRadius="66.13" - android:type="radial"> - <item android:offset="0.91" android:color="#007542E5"/> - <item android:offset="1" android:color="#6600DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3c0,0 0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-15.2,32.8 -52.2,66.4 -110,64.6c-62.4,-1.8 -117.6,-48.1 -127.8,-108.9c-1.9,-9.5 0,-14.4 1,-22.2c-1.3,6.1 -2.1,12.2 -2.2,18.4v0.7c0.3,73.6 60.2,133.1 133.7,132.8c64.6,-0.2 119.7,-46.7 130.8,-110.2c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,215 347.8,191.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="311.87" - android:centerY="109.01" - android:gradientRadius="340.74" - android:type="radial"> - <item android:offset="0" android:color="#FF80EBFF"/> - <item android:offset="0.26" android:color="#FF00DDFF"/> - <item android:offset="0.53" android:color="#FF0090ED"/> - <item android:offset="0.86" android:color="#FF0060DF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3c0,0 0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-15.2,32.8 -52.2,66.4 -110,64.6c-62.4,-1.8 -117.6,-48.1 -127.8,-108.9c-1.9,-9.5 0,-14.4 1,-22.2c-1.3,6.1 -2.1,12.2 -2.2,18.4v0.7c0.3,73.6 60.2,133.1 133.7,132.8c64.6,-0.2 119.7,-46.7 130.8,-110.2c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,215 347.8,191.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="209.99" - android:centerY="223.55" - android:gradientRadius="340.74" - android:type="radial"> - <item android:offset="0.3" android:color="#CC321C64"/> - <item android:offset="0.37" android:color="#7F212F83"/> - <item android:offset="0.48" android:color="#230A47AC"/> - <item android:offset="0.53" android:color="#000250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M84.2,223.5c10.3,60.7 65.4,107 127.9,108.9c57.8,1.7 94.8,-31.9 110,-64.6c13,-28.3 14.4,-60.5 4.1,-89.8v-0.2c0,-0.1 0,-0.2 0,-0.1v0.2c4.7,30.8 -11,60.7 -35.4,80.9l-0.1,0.2c-47.8,38.9 -93.6,23.5 -102.9,17.2c-0.7,-0.3 -1.3,-0.7 -2,-1c-27.9,-13.3 -39.5,-38.7 -36.9,-60.5c-13.4,0.2 -25.9,-7.7 -31.5,-19.8c14.8,-9.1 33.5,-9.8 49,-2c15.8,7.2 33.8,8 50.1,2c0,-1.1 -23.3,-10.3 -32.3,-19.1c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-0.8,-0.6 -1.7,-1.2 -2.7,-1.9c-9.7,-6.3 -29.1,-6 -29.6,-6h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-1.6,0.6 -3,1.5 -4.4,2.4c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0c-8.5,12.2 -14.6,25.8 -17.9,40.2C86.5,192 81.8,212.8 84.2,223.5L84.2,223.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="308.05" - android:centerY="18.36" - android:gradientRadius="524.13" - android:type="radial"> - <item android:offset="0" android:color="#FF80EBFF"/> - <item android:offset="0.47" android:color="#FF00B3F4"/> - <item android:offset="0.84" android:color="#FF0060DF"/> - <item android:offset="1" android:color="#FF592ACB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M263.1,170.8c4.8,4.7 9,10.2 12.4,16.1c0.7,0.5 1.4,1.1 2.1,1.7c30.1,27.9 14.3,67 13.3,69.9c24.5,-20.2 40.2,-50.1 35.4,-80.9c-15,-37.5 -40.5,-52.6 -61.5,-85.6c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.9,-1.7 -1.6,-3.4 -2.1,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0h-0.1h-0.2C252.3,81.1 221.8,129.5 263.1,170.8L263.1,170.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="277.55" - android:startY="60.69" - android:endX="293.77" - android:endY="283.77" - android:type="linear"> - <item android:offset="0" android:color="#FFAAF2FF"/> - <item android:offset="0.29" android:color="#FF00DDFF"/> - <item android:offset="0.61" android:color="#FF0090ED"/> - <item android:offset="0.89" android:color="#FF0250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M211.9,152.7l17.7,1.2l10.7,3.8l8.9,3.4l10.3,7.4l9.6,10.2l3.3,6.4c0.8,0.5 1.5,1 2.3,1.5c0.3,0.2 0.6,0.4 0.9,0.6c-3.3,-6 -7.6,-11.4 -12.4,-16.1c-41.4,-41.3 -10.9,-89.7 -5.7,-92.2l0.1,-0.1C224.1,98.3 212.9,134.5 211.9,152.7L211.9,152.7L211.9,152.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="233.01" - android:startY="79.68" - android:endX="248.96" - android:endY="213.99" - android:type="linear"> - <item android:offset="0" android:color="#FFAAF2FF"/> - <item android:offset="0.29" android:color="#FF00DDFF"/> - <item android:offset="0.74" android:color="#FF0090ED"/> - <item android:offset="1" android:color="#FF0250BB"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M168.8,162.3c1,0.6 1.9,1.2 2.7,1.9c-3,-10.6 -3.1,-21.9 -0.4,-32.5c-12.3,6 -23.3,14.3 -32.1,24.7C139.7,156.3 159.1,155.9 168.8,162.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="206.55" - android:centerY="97.78" - android:gradientRadius="97.33" - android:type="radial"> - <item android:offset="0" android:color="#FF00DDFF"/> - <item android:offset="0.82" android:color="#FF0090ED"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M156.3,232.3c0,0 6.2,-23 44.1,-23c4.1,0 15.8,-11.4 16,-14.7c-16.3,5.9 -34.3,5.2 -50.1,-2c-15.6,-8 -34.2,-7.2 -49,2c5.7,12.3 18.1,20 31.5,19.8c-2.6,21.8 9,47.1 36.9,60.5c0.6,0.3 1.3,0.6 1.9,0.9C171.3,267.4 158,251.5 156.3,232.3L156.3,232.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="270.8" - android:centerY="147.43" - android:gradientRadius="309.81" - android:type="radial"> - <item android:offset="0.29" android:color="#FF80EBFF"/> - <item android:offset="1" android:color="#FF00B3F4"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M277.4,188.7c-0.7,-0.6 -1.4,-1.2 -2.1,-1.7c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-9.3,-6.5 -20.8,-9.2 -32.1,-7.9c47.9,24 35,106.3 -31.3,103.3c-5.9,-0.2 -11.8,-1.4 -17.4,-3.3c-1.4,-0.5 -2.7,-1.1 -3.9,-1.7c-0.8,-0.4 -1.6,-0.7 -2.3,-1.1l0.1,0.1c9.2,6.3 55.1,21.8 102.9,-17.2l0.1,-0.2C291.9,255.8 307.8,216.5 277.4,188.7L277.4,188.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="203.95" - android:centerY="132.63" - android:gradientRadius="248.83" - android:type="radial"> - <item android:offset="0.18" android:color="#FFAAF2FF"/> - <item android:offset="0.43" android:color="#FF00DDFF"/> - <item android:offset="0.69" android:color="#FF0060DF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.8 -17.6,-29 -26.7,-33.7c6.6,12.8 11.1,26.3 13.4,40.3v0.2c-15,-37.5 -40.5,-52.6 -61.5,-85.6c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.9,-1.7 -1.6,-3.4 -2.1,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1l0.1,-0.1c-33.5,19.5 -44.9,55.9 -45.8,74h0.3l17.7,1.2l9.9,3.5l9.7,3.7l10.3,7.4l9.6,10.2c0,0 3.3,6.3 3.3,6.4c-8.9,-5.5 -19.5,-7.9 -29.9,-6.4c47.9,24 35,106.3 -31.3,103.3c-5.9,-0.3 -11.8,-1.4 -17.4,-3.3c-1.3,-0.5 -2.7,-1.1 -3.9,-1.7c-0.8,-0.4 -1.6,-0.7 -2.3,-1.1l0.1,0.1c-0.7,-0.3 -1.3,-0.7 -2,-1c0.6,0.3 1.3,0.6 1.9,0.9c-16.3,-8.3 -29.6,-24.2 -31.4,-43.6c0,0 6.2,-23 44.1,-23c4.1,0 15.8,-11.4 16,-14.7c0,-1.1 -23.3,-10.3 -32.3,-19.1c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-3,-10.6 -3.1,-21.9 -0.4,-32.5c-12.3,6 -23.3,14.3 -32.1,24.7h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-1.6,0.7 -3,1.5 -4.4,2.4c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.6,9.6 -12.5,14.9c-8.5,12.2 -14.6,25.8 -17.9,40.2c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.4,7.2 -1.6,8.3l0,0c-1.1,6.2 -1.7,12.4 -2,18.7v0.7c0.1,73.6 60,133.1 133.5,133c64.8,-0.1 120,-46.7 131,-110.5c0.2,-1.8 0.4,-3.4 0.6,-5.1C350.9,214.9 347.8,191.9 339.5,170.7L339.5,170.7zM326.1,177.6L326.1,177.6L326.1,177.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="311.47" - android:startY="119.54" - android:endX="135.81" - android:endY="309.08" - android:type="linear"> - <item android:offset="0.24" android:color="#7F80EBFF"/> - <item android:offset="0.7" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c0,0 -0.6,0.2 -1.7,0.6c-2.7,4.4 -11.9,12.9 -15.4,12.9c-37.9,-0.2 -44.2,22.5 -44.2,22.5c0.7,7.8 3.2,15.2 7.5,21.8c-3.5,-6.1 -5.7,-13 -6.4,-19.9c0,0 6.2,-23 44.1,-23C204.4,209.4 216.2,197.9 216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="192.31" - android:startY="188.84" - android:endX="167.23" - android:endY="280.42" - android:type="linear"> - <item android:offset="0" android:color="#E5BFF3FF"/> - <item android:offset="1" android:color="#7F80EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M326.2,177.7L326.2,177.7c0,-0.2 0,-0.3 0,-0.2C326.2,177.6 326.2,177.5 326.2,177.7c-0.9,-2.3 -1.9,-4.4 -2.7,-6.7c-0.4,-0.8 -0.7,-1.5 -1.1,-2.2c-0.7,-1.4 -1.4,-2.7 -2.1,-4c-0.4,-0.8 -0.9,-1.6 -1.4,-2.4c-0.7,-1.2 -1.3,-2.4 -2,-3.4c-0.5,-0.8 -1,-1.6 -1.5,-2.5c-0.7,-1.1 -1.3,-2.1 -2,-3c-0.5,-0.8 -1.1,-1.6 -1.7,-2.4c-0.7,-1 -1.4,-2 -2.1,-2.7c-0.6,-0.8 -1.2,-1.6 -1.8,-2.4c-0.7,-0.9 -1.4,-1.9 -2.1,-2.7c-0.6,-0.8 -1.2,-1.5 -1.8,-2.3c-0.7,-0.9 -1.4,-1.8 -2.2,-2.7c-0.6,-0.8 -1.3,-1.5 -1.9,-2.3c-0.4,-0.4 -0.7,-0.8 -1,-1.2l0.4,0.5c-11.6,-13.5 -24.1,-26.1 -35.2,-43.9c-1.1,-1.7 -2.2,-3.3 -3.1,-5.1c-0.5,-0.9 -1.1,-1.9 -1.5,-2.7c-0.8,-1.6 -1.4,-3 -1.9,-4.7c0,-0.1 -0.1,-0.2 -0.1,-0.3s-0.1,-0.2 -0.1,-0.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0H257c0,0 -0.1,0 -0.1,0.1c-0.3,0.2 -0.6,0.4 -0.8,0.6c-0.1,0.1 -0.1,0.1 -0.2,0.2c-0.4,0.4 -0.8,0.8 -1.1,1.2l0,0c-8,9.3 -28.4,50.2 4.5,86.8c-30.7,-36.1 -11.4,-75.3 -2.9,-85.5c0.5,1.4 1,2.7 1.7,4c0.5,1 1,1.9 1.5,2.7c1.1,1.8 2.2,3.4 3.1,5.1c20.8,33 46.4,48.1 61.5,85.6c0,-0.1 0,-0.2 0,-0.2s0,0 0,0.1v0.1c10.3,29.4 8.7,61.5 -4.1,89.8c-5.3,11.3 -12.5,21.5 -21.2,30.3c9.4,-9.2 17.2,-20 22.8,-32C335.1,239.4 336.4,207.2 326.2,177.7L326.2,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="287.95" - android:startY="74.23" - android:endX="285.22" - android:endY="385.68" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M257.4,78.8L257.4,78.8c-30,17.6 -42.3,48.7 -45.2,67.9c4.8,-25.1 19.2,-47.4 40.2,-62C253.8,82.3 255.5,80.3 257.4,78.8L257.4,78.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="235.68" - android:startY="75.96" - android:endX="233.41" - android:endY="175.93" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#7FAAF2FF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M290.7,258.8l0.1,-0.2c1.2,-2.7 17,-42.1 -13.3,-69.9c-0.7,-0.6 -1.4,-1.2 -2.1,-1.7c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-9,-6.3 -19.9,-9 -30.9,-8l0,0c-0.4,0.1 -0.8,0.1 -1.3,0.2c47.4,23.8 35.3,104.4 -29.2,103.4h0.5c65.4,2.7 78.2,-77.6 32.9,-102.8c8.9,0.1 17.7,2.7 25.2,7.4c0.3,0.2 0.6,0.4 0.9,0.6c0.7,0.5 1.5,1 2.1,1.6c31.2,26.6 17,66.5 15.9,69.4l-0.1,0.2"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="257.29" - android:startY="176.16" - android:endX="252.36" - android:endY="325.64" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M166.7,194c15.3,6.4 32.6,6.9 48.2,1.2c-15.9,5.3 -33.3,4.4 -48.5,-2.6c-15.3,-7.8 -33.6,-7.2 -48.4,1.6l-0.2,0.1l0,0l-0.1,0.1l-0.1,0.1h-0.1l0,0l0,0l0,0l0.1,0.2l0,0l0.1,0.2l0,0l0.1,0.3l0,0c0.3,0.6 0.6,1.2 0.9,1.7c6.1,11 17.9,17.8 30.3,17.6c-2.5,21.1 8.3,45.5 34.6,59.2c-24.9,-14.3 -35.3,-40.4 -32.5,-61.2c-19.2,-0.5 -27.9,-12.1 -30.3,-17C134.9,187.9 152,187.4 166.7,194L166.7,194z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="165.56" - android:startY="185.57" - android:endX="173.37" - android:endY="293.51" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#3380EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M171.4,164.1l-0.7,-0.4L171.4,164.1L171.4,164.1zM171.3,163.6c-2.8,-10.4 -2.9,-21.5 -0.2,-32c-11.8,5.7 -22.3,13.5 -30.8,23.5c8.1,-8.1 17.7,-14.9 28.2,-19.8C167.2,144.6 168.2,154.4 171.3,163.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="176.81" - android:startY="124.11" - android:endX="147.78" - android:endY="173.26" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#3380EBFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M87.3,237.4l-0.1,-0.4c-1.3,-4.4 -2.4,-8.9 -3,-13.5c-0.9,-5.7 -0.9,-11.5 0,-17.2c-0.7,4.4 -1.1,8.8 -1.3,13.3v0.7c0,56.6 35.8,107.1 89.4,125.7C126.3,328.1 93.6,286.5 87.3,237.4L87.3,237.4z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="129.41" - android:startY="204.87" - android:endX="124.93" - android:endY="397.63" - android:type="linear"> - <item android:offset="0" android:color="#6600DDFF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M86.2,223.9c-2.4,-10.7 2.5,-31.4 2.6,-31.7c3.2,-14.4 9.3,-28.2 17.9,-40.2l0,0l0,0c3.7,-5.3 8,-10.3 12.5,-14.9c4,-4 8.3,-7.9 13.1,-11.2c0.2,-0.1 0.4,-0.2 0.6,-0.4c0,10.1 0.5,27.2 5.2,32.8h0.1c0.7,0 20,-0.9 29.9,5.1c1.1,0.7 2.1,1.3 2.7,1.8c1.3,0.8 2.5,1.7 3.5,2.6c2.2,1.7 4.4,3.8 9.4,8.4c7.3,6.8 23,13.4 29.6,16.6c-6.7,-3.3 -22.2,-10.4 -29.3,-17.4c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-1 -2.3,-1.9 -3.4,-2.7c-0.8,-0.6 -1.7,-1.2 -2.7,-1.9c-9.7,-6.3 -29.1,-6 -29.6,-6h-0.1c-4.8,-6.1 -4.9,-25 -4.7,-31.8c0,-0.3 0,-0.5 0,-0.7v-0.2c0,-0.1 0,-0.3 0,-0.4c0,0 0,0 -0.1,0h-0.1h-0.1H134h-0.1l-0.1,0.1l-0.1,0.1l-0.1,0.1l-0.2,0.1l-0.1,0.1l-0.2,0.1l-0.1,0.1c-1,0.6 -2.1,1.2 -2.9,1.8c-4.6,3.2 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0C96,163.8 90,177.4 86.7,191.8c-0.1,0.3 -4.8,20.9 -2.6,31.7c8.7,51.6 50,93 100.5,105C135,315.6 95,274.9 86.2,223.9L86.2,223.9z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="148.45" - android:startY="98.32" - android:endX="148.45" - android:endY="326.46" - android:type="linear"> - <item android:offset="0" android:color="#FFBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.1,-12.3 -13.2,-23.2 -23.5,-31.6l-0.2,-0.2c-0.3,-0.2 -0.5,-0.4 -0.8,-0.6c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c-0.3,-0.2 -0.5,-0.3 -0.8,-0.5l-0.3,-0.2c-0.3,-0.2 -0.7,-0.4 -1,-0.6c0.4,0.7 0.7,1.5 1.1,2.2c0.2,0.5 0.4,0.9 0.7,1.4c5.7,11.7 9.6,24.1 11.8,36.9v0.2c4.7,30.8 -11,60.7 -35.4,80.9l-0.1,0.2c-30.4,24.7 -60.2,27.5 -80,24.5c19.8,3.6 51,2.2 83.2,-24l0.1,-0.2c24.5,-20.2 40.2,-50.1 35.4,-80.9v-0.2c-1.9,-11.2 -5.1,-22.1 -9.7,-32.4c5.9,6.2 10.7,13.3 14.5,20.7c9.5,20.3 13.7,42.8 12.4,65.3c-0.1,1.8 -0.2,3.3 -0.3,5.1c-8,63.9 -60.8,112.9 -125,116c-8.7,0.5 -17.7,0.1 -26.3,-1.1c72.1,11.6 140.1,-36.9 152.5,-109c0.2,-1.8 0.4,-3.3 0.6,-5.1C350.9,214.9 347.8,191.9 339.5,170.7L339.5,170.7zM326.2,177.7L326.2,177.7L326.2,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="276.75" - android:startY="130.61" - android:endX="267.51" - android:endY="444.06" - android:type="linear"> - <item android:offset="0" android:color="#CCBFF3FF"/> - <item android:offset="1" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> - </group> - </vector> - </aapt:attr> - <target - android:name="a1_t"> - <aapt:attr - name="android:animation"> - <set> - <objectAnimator - android:propertyName="scaleX" - android:duration="300" - android:valueFrom="0.75" - android:valueTo="0.75" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleX" - android:duration="700" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="300" - android:valueFrom="0.75002400000000002" - android:valueTo="0.75002400000000002" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleY" - android:duration="700" - android:valueFrom="0.75002400000000002" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - </set> - </aapt:attr> - </target> -</animated-vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/browser_location.xml b/mobile/android/fenix/app/src/main/res/drawable/browser_location.xml new file mode 100644 index 0000000000000000000000000000000000000000..57d2d215ae5e9428d7355f577b810af0a64307a1 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/browser_location.xml @@ -0,0 +1,17 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <group> + <clip-path + android:pathData="M0,0h40v40h-40z"/> + <path + android:pathData="M19.332,28.605C19.332,23.853 23.361,20 28.332,20C33.303,20 37.332,23.853 37.332,28.605C37.332,32.002 32.736,36.822 30.113,39.296C29.636,39.748 28.997,40 28.332,40C27.667,40 27.028,39.748 26.551,39.296C23.928,36.822 19.332,32.001 19.332,28.605ZM26.865,24.958C27.33,24.766 27.829,24.667 28.332,24.667C29.349,24.667 30.324,25.07 31.043,25.789C31.761,26.508 32.165,27.483 32.165,28.5C32.165,29.517 31.761,30.492 31.043,31.211C30.324,31.93 29.349,32.333 28.332,32.333C27.829,32.333 27.33,32.234 26.865,32.042C26.4,31.849 25.977,31.566 25.621,31.211C25.265,30.855 24.983,30.432 24.791,29.967C24.598,29.502 24.499,29.003 24.499,28.5C24.499,27.997 24.598,27.498 24.791,27.033C24.983,26.568 25.265,26.146 25.621,25.789C25.977,25.434 26.4,25.151 26.865,24.958Z" + android:fillColor="#FFA436" + android:fillType="evenOdd"/> + <path + android:pathData="M38.509,22.9C38.721,21.771 38.832,20.607 38.832,19.417C38.832,9.061 30.438,0.667 20.082,0.667C9.727,0.667 1.332,9.061 1.332,19.417C1.332,29.772 9.727,38.167 20.082,38.167C20.825,38.167 21.559,38.124 22.279,38.039C19.438,34.942 16.665,31.167 16.665,28.233C16.665,25.223 17.971,22.499 20.082,20.526V14.846C22.098,14.846 23.809,16.151 24.416,17.962C25.33,17.658 26.298,17.458 27.301,17.375C26.412,14.225 23.517,11.917 20.082,11.917L20.082,9.221C25.042,9.221 29.175,12.764 30.089,17.456C31.169,17.608 32.2,17.899 33.161,18.308C32.598,11.578 26.957,6.292 20.082,6.292V3.596C28.819,3.596 35.903,10.679 35.903,19.417C35.903,19.589 35.9,19.761 35.894,19.933C36.942,20.767 37.83,21.771 38.509,22.9Z" + android:fillColor="#FBFBFE"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/connect.xml b/mobile/android/fenix/app/src/main/res/drawable/connect.xml new file mode 100644 index 0000000000000000000000000000000000000000..2235ebaeac77e2c54a8432b2c9a1d8c7a6946603 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/connect.xml @@ -0,0 +1,17 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <path + android:pathData="M20,1.253C9.647,1.253 1.253,9.647 1.253,20C1.253,28.967 7.547,36.46 15.96,38.307C16.84,38.5 17.733,38.633 18.653,38.693V24.373C16.787,23.8 15.427,22.06 15.427,20C15.427,17.473 17.473,15.427 20,15.427C22.527,15.427 24.573,17.473 24.573,20C24.573,22.06 23.213,23.8 21.347,24.373V38.693C22.267,38.633 23.16,38.5 24.04,38.307C32.453,36.46 38.747,28.967 38.747,20C38.747,9.647 30.353,1.253 20,1.253ZM24.04,35.293V26.32C26.12,24.987 27.5,22.653 27.5,20C27.5,15.86 24.14,12.5 20,12.5C15.86,12.5 12.5,15.86 12.5,20C12.5,22.653 13.88,24.987 15.96,26.32V35.293C9.18,33.513 4.18,27.347 4.18,20C4.18,11.26 11.26,4.18 20,4.18C28.74,4.18 35.82,11.26 35.82,20C35.82,27.347 30.82,33.513 24.04,35.293Z" + android:fillColor="#FBFBFE" + android:fillType="evenOdd"/> + <path + android:pathData="M20,6.873C12.753,6.873 6.873,12.753 6.873,20C6.873,25.84 10.687,30.787 15.96,32.487V29.36C12.34,27.8 9.807,24.193 9.807,20C9.807,14.367 14.367,9.807 20,9.807C25.633,9.807 30.193,14.367 30.193,20C30.193,24.193 27.66,27.8 24.04,29.36V32.487C29.313,30.787 33.127,25.84 33.127,20C33.127,12.753 27.247,6.873 20,6.873Z" + android:fillColor="#FBFBFE" + android:fillType="evenOdd"/> + <path + android:pathData="M20,22.1C21.16,22.1 22.1,21.159 22.1,20C22.1,18.84 21.16,17.9 20,17.9C18.84,17.9 17.9,18.84 17.9,20C17.9,21.159 18.84,22.1 20,22.1Z" + android:fillColor="#FBFBFE"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/connect_broken.xml b/mobile/android/fenix/app/src/main/res/drawable/connect_broken.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9a1b783b2c538fadc0ffeb6e4bdbdd945082cae --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/connect_broken.xml @@ -0,0 +1,37 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <group> + <clip-path + android:pathData="M0,0h40v40h-40z"/> + <path + android:pathData="M8.317,5.337C11.521,2.781 15.582,1.253 19.999,1.253C30.352,1.253 38.745,9.647 38.745,20C38.745,24.418 37.218,28.478 34.662,31.681L32.577,29.597C34.611,26.937 35.819,23.611 35.819,20C35.819,11.26 28.739,4.18 19.999,4.18C16.389,4.18 13.063,5.388 10.401,7.421L8.317,5.337Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M5.89,7.656C3.002,10.954 1.252,15.273 1.252,20C1.252,28.967 7.545,36.46 15.959,38.307C16.839,38.5 17.732,38.633 18.652,38.693V24.373C16.785,23.8 15.425,22.06 15.425,20C15.425,19.19 15.635,18.43 16.004,17.771L13.887,15.653C13.013,16.88 12.499,18.38 12.499,20C12.499,22.653 13.879,24.987 15.959,26.32V35.293C9.179,33.513 4.179,27.347 4.179,20C4.179,16.08 5.603,12.493 7.963,9.73L5.89,7.656Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M16.399,13.419L18.618,15.638C19.054,15.501 19.517,15.427 19.998,15.427C22.525,15.427 24.572,17.473 24.572,20C24.572,20.481 24.498,20.945 24.36,21.38L26.579,23.599C27.165,22.531 27.498,21.304 27.498,20C27.498,15.86 24.138,12.5 19.998,12.5C18.694,12.5 17.468,12.833 16.399,13.419Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M24.349,26.112L22.232,23.995C21.954,24.151 21.658,24.278 21.349,24.373V38.693C22.269,38.633 23.162,38.5 24.042,38.307C27.176,37.619 30.015,36.147 32.345,34.109L30.271,32.034C28.492,33.552 26.372,34.681 24.042,35.293V26.32C24.146,26.253 24.249,26.184 24.349,26.112Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M30.653,27.67C32.21,25.514 33.127,22.864 33.127,20C33.127,12.753 27.247,6.873 20,6.873C17.138,6.873 14.488,7.791 12.33,9.348L14.437,11.455C16.037,10.412 17.947,9.807 20,9.807C25.634,9.807 30.194,14.367 30.194,20C30.194,22.051 29.587,23.962 28.544,25.562L30.653,27.67Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M26.272,28.037L28.357,30.121C27.095,31.163 25.635,31.973 24.041,32.487V29.36C24.844,29.014 25.593,28.568 26.272,28.037Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M11.962,13.727L9.878,11.643C8.001,13.914 6.873,16.826 6.873,20C6.873,25.84 10.686,30.787 15.96,32.487V29.36C12.34,27.8 9.806,24.193 9.806,20C9.806,17.633 10.611,15.457 11.962,13.727Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M17.922,19.688L20.311,22.077C20.21,22.092 20.105,22.1 19.999,22.1C18.84,22.1 17.899,21.16 17.899,20C17.899,19.894 17.907,19.79 17.922,19.688Z" + android:fillColor="#FBFBFE"/> + <path + android:pathData="M2.89,4.642L35.228,36.98C35.879,37.632 35.879,38.688 35.228,39.339L35.228,39.339C34.576,39.991 33.52,39.991 32.868,39.339L0.53,7.001C-0.121,6.35 -0.121,5.294 0.53,4.642C1.182,3.991 2.238,3.991 2.89,4.642Z" + android:fillColor="#FBFBFE"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/globe_broken.xml b/mobile/android/fenix/app/src/main/res/drawable/globe_broken.xml new file mode 100644 index 0000000000000000000000000000000000000000..bcd883469056004de6f8c2f57d0cac581e5f6079 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/globe_broken.xml @@ -0,0 +1,18 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <path + android:pathData="M4.209,1.999L37.355,35.145L35.145,37.355L1.999,4.209L4.209,1.999Z" + android:fillColor="#FBFBFE" + android:fillType="evenOdd"/> + <path + android:pathData="M7.869,5.703C3.82,9.142 1.25,14.271 1.25,20C1.25,30.03 9.126,38.221 19.031,38.725L19.041,38.733L19.047,38.726C19.363,38.742 19.681,38.75 20,38.75C20.32,38.75 20.638,38.742 20.954,38.726L20.96,38.733L20.97,38.725C26.306,38.453 31.053,35.951 34.297,32.132L32.079,29.913C30.228,32.166 27.759,33.891 24.931,34.831C26.854,32.438 28.243,29.75 29.097,26.931L26.534,24.368C25.642,28.517 23.465,32.438 20,35.474C15.763,31.76 13.451,26.722 13.063,21.563H23.728L20.603,18.438H13.063C13.22,16.35 13.692,14.282 14.479,12.313L12.102,9.936C10.844,12.632 10.12,15.52 9.93,18.438H4.453C4.872,14.209 6.978,10.477 10.087,7.922L7.869,5.703ZM15.069,34.831C11.952,30.951 10.239,26.295 9.93,21.563H4.453C5.07,27.779 9.331,32.924 15.069,34.831Z" + android:fillColor="#FBFBFE" + android:fillType="evenOdd"/> + <path + android:pathData="M13.678,7.093C14.106,6.433 14.569,5.791 15.069,5.169C14.263,5.437 13.486,5.769 12.744,6.159L10.448,3.863C12.985,2.358 15.907,1.434 19.031,1.275L19.041,1.267L19.047,1.274C19.363,1.258 19.681,1.25 20,1.25C20.32,1.25 20.638,1.258 20.954,1.274L20.96,1.267L20.97,1.275C30.875,1.779 38.75,9.97 38.75,20C38.75,23.489 37.798,26.755 36.138,29.553L33.842,27.257C34.752,25.525 35.346,23.601 35.548,21.563H30.071C30.033,22.146 29.974,22.728 29.893,23.308L25.023,18.438H26.938C26.55,13.278 24.238,8.24 20,4.526C18.361,5.963 17.01,7.598 15.947,9.361L13.678,7.093ZM30.071,18.438H35.548C34.931,12.221 30.67,7.076 24.931,5.169C28.049,9.049 29.762,13.705 30.071,18.438Z" + android:fillColor="#FBFBFE" + android:fillType="evenOdd"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_account.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_account.xml deleted file mode 100644 index b8784a442ff316a3868121314940e0d5abf5ad1d..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_account.xml +++ /dev/null @@ -1,12 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:pathData="m10,20c-5.5228,0 -10,-4.4772 -10,-10s4.4772,-10 10,-10 10,4.4772 10,10c-0.0061,5.5203 -4.4797,9.9939 -10,10zM10,2c-4.4183,0 -8,3.5817 -8,8s3.5817,8 8,8 8,-3.5817 8,-8c-0.005,-4.4162 -3.5838,-7.995 -8,-8zM15.6655,12.2092c-1.4812,-1.7094 -3.5322,0.5908 -5.6658,0.5908 -2.1322,0 -4.1846,-2.3002 -5.6658,-0.5908 -0.42,0.4844 -0.4536,1.19 -0.0938,1.7192 1.2558,1.848 3.3558,3.0716 5.7596,3.0716 2.4038,0 4.5038,-1.2236 5.7596,-3.0716 0.3612,-0.5292 0.3262,-1.2348 -0.0938,-1.7192m-5.6655,-0.7092c2.3474,0 4.25,-1.9026 4.25,-4.25 0,-2.3474 -1.9026,-4.25 -4.25,-4.25 -2.3474,0 -4.25,1.9026 -4.25,4.25 0,2.3474 1.9026,4.25 4.25,4.25" - android:fillColor="?attr/textPrimary"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_account_warning.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_account_warning.xml deleted file mode 100644 index 2dda9b20aa6a75ae2a11e125b0267d0350ba9314..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_account_warning.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path android:pathData="M15.85 11a4.25 4.25 0 1 0-0.4 0.7l-1.24 2.5a5.9 5.9 0 0 1-2.21 0.6c-2.13 0-4.2-2.3-5.7-0.6a1.4 1.4 0 0 0-0.1 1.7A6.95 6.95 0 0 0 11.82 19l-0.54 1.06c-0.3 0.6-0.35 1.27-0.2 1.9a10 10 0 1 1 10.7-7.82l-1.3-2.6a2.72 2.72 0 0 0-4.59-0.5zm8.01 9.47A1.72 1.72 0 0 1 22.23 23h-8.55a1.73 1.73 0 0 1-1.5-2.5l4.27-8.5a1.7 1.7 0 0 1 3.1 0l4.31 8.55zm-6.7-5.7v2.6a0.87 0.87 0 0 0 1.7 0v-2.6a0.87 0.87 0 1 0-1.72 0zM19.1 20a1 1 0 1 0-2.04 0 1 1 0 0 0 2.04 0z" - android:fillColor="@color/sync_error_text_color"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_favorite.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_favorite.xml new file mode 100644 index 0000000000000000000000000000000000000000..121817c6feb5d5ffeff16fa6aa9abcb6a04d9b0f --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/ic_favorite.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="18dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" + android:fillColor="#ffffff"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_firefox.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_firefox.xml deleted file mode 100644 index 8e369db27ceeefcb6614387a86b396e2e6c99a9d..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_firefox.xml +++ /dev/null @@ -1,141 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector android:height="112.7dp" android:viewportHeight="54.28" - android:viewportWidth="52.03" android:width="108.02839dp" - xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android"> - <path android:pathData="M50.15,18.05c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46A12.92,12.92 0,0 0,18.02 17.26a10.031,10.031 0,0 0,-0.68 -0.51,12 12,0 0,1 -0.07,-6.36A19.21,19.21 0,0 0,11.02 15.23c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.159,39.159 0,0 0,-0.26 1.62,0.13 0.13,0 0,1 0,0.06 26.47,26.47 0,0 0,-0.5 3.59L0.02,27.77a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM20.15,38.43l0.36,0.18zM26.15,22.73zM47.62,19.42z"> - <aapt:attr name="android:fillColor"> - <gradient android:endX="4.825955" android:endY="50.964695" - android:startX="45.6871" android:startY="8.501661" android:type="linear"> - <item android:color="#FFFFF44F" android:offset="0.05"/> - <item android:color="#FFFF980E" android:offset="0.37"/> - <item android:color="#FFFF3647" android:offset="0.53"/> - <item android:color="#FFE31587" android:offset="0.7"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M50.15,18.05c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64L0.02,27.77a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="45.955353" - android:centerY="11.459999" - android:gradientRadius="53.746708" android:type="radial"> - <item android:color="#FFFFBD4F" android:offset="0.13"/> - <item android:color="#FFFF980E" android:offset="0.28"/> - <item android:color="#FFFF3750" android:offset="0.47"/> - <item android:color="#FFEB0878" android:offset="0.78"/> - <item android:color="#FFE50080" android:offset="0.86"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M50.15,18.05c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64L0.02,27.77a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="25.630222" - android:centerY="28.77216" - android:gradientRadius="55.090374" android:type="radial"> - <item android:color="#FF960E18" android:offset="0.3"/> - <item android:color="#BCB11927" android:offset="0.35"/> - <item android:color="#56DB293D" android:offset="0.43"/> - <item android:color="#16F5334B" android:offset="0.5"/> - <item android:color="#00FF3750" android:offset="0.53"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M37.49,21.11l0.17,0.12a14.35,14.35 0,0 0,-2.42 -3.15c-8.09,-8.09 -2.12,-17.55 -1.12,-18a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.45 6.57z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="31.1392" - android:centerY="-2.457998" - android:gradientRadius="29.609999" android:type="radial"> - <item android:color="#FFFFF44F" android:offset="0.13"/> - <item android:color="#FFFF980E" android:offset="0.53"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M26.1,22.77c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,18.02 17.26c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="20.335398" - android:centerY="43.06355" - android:gradientRadius="26.210001" android:type="radial"> - <item android:color="#FF3A8EE6" android:offset="0.35"/> - <item android:color="#FF9059FF" android:offset="0.67"/> - <item android:color="#FFC139E6" android:offset="1"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M26.1,22.77c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,18.02 17.26c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="25.19928" - android:centerY="23.053501" - android:gradientRadius="13.91751" android:type="radial"> - <item android:color="#009059FF" android:offset="0.21"/> - <item android:color="#996E008B" android:offset="0.97"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M16.79,16.39l0.54,0.36a12,12 0,0 1,-0.07 -6.36A19.21,19.21 0,0 0,11.02 15.23c0.1,0 3.87,-0.07 5.77,1.16z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="24.271004" - android:centerY="4.029999" - android:gradientRadius="18.444002" android:type="radial"> - <item android:color="#FFFFE226" android:offset="0.1"/> - <item android:color="#FFFF7139" android:offset="0.79"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M0.26,28.35c2,11.88 12.77,20.94 25,21.29 11.3,0.32 18.52,-6.25 21.51,-12.65a23.55,23.55 0,0 0,0.81 -17.57c0.92,6 -2.15,11.87 -6.94,15.82 -9.34,7.61 -18.28,4.59 -20.09,3.35l-0.38,-0.19c-5.45,-2.6 -7.7,-7.56 -7.22,-11.82A6.67,6.67 0,0 1,6.76 22.77a9.8,9.8 0,0 1,9.57 -0.38A13,13 0,0 0,26.1 22.77c0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71a10.031,10.031 0,0 0,-0.68 -0.51l-0.54,-0.36c-1.9,-1.23 -5.67,-1.16 -5.8,-1.16 -1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88c-0.02,0.02 -0.95,4.07 -0.49,6.16z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="41.62241" - android:centerY="-8.146102" - android:gradientRadius="89.61946" android:type="radial"> - <item android:color="#FFFFF44F" android:offset="0.11"/> - <item android:color="#FFFF980E" android:offset="0.46"/> - <item android:color="#FFFF3647" android:offset="0.72"/> - <item android:color="#FFE31587" android:offset="0.9"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M35.24,18.08a14.35,14.35 0,0 1,2.42 3.15l0.39,0.32c5.9,5.44 2.81,13.13 2.58,13.68 4.79,-4 7.86,-9.79 6.94,-15.82 -3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07L34.12,0.06c-1,0.47 -6.97,9.93 1.12,18.02z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="6.13348" - android:centerY="14.259094" - android:gradientRadius="95.36752" android:type="radial"> - <item android:color="#FFFFF44F" android:offset="0"/> - <item android:color="#FFFF980E" android:offset="0.3"/> - <item android:color="#FFFF3647" android:offset="0.57"/> - <item android:color="#FFE31587" android:offset="0.74"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M38.02,21.55l-0.39,-0.32 -0.17,-0.12a9,9 0,0 0,-6.27 -1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21c1.81,1.24 10.75,4.26 20.09,-3.35 0.3,-0.58 3.39,-8.27 -2.54,-13.71z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="24.90772" - android:centerY="9.289151" - android:gradientRadius="56.180176" android:type="radial"> - <item android:color="#FFFFF44F" android:offset="0.14"/> - <item android:color="#FFFF980E" android:offset="0.48"/> - <item android:color="#FFFF3647" android:offset="0.66"/> - <item android:color="#FFE31587" android:offset="0.9"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M14.37,30.09s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88a13,13 0,0 1,-9.77 -0.38,9.8 9.8,0 0,0 -9.57,0.38 6.67,6.67 0,0 0,6.16 3.88c-0.48,4.26 1.77,9.22 7.22,11.82l0.36,0.18a11,11 0,0 1,-6.13 -8.52z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="37.568623" - android:centerY="13.450078" - android:gradientRadius="60.55354" android:type="radial"> - <item android:color="#FFFFF44F" android:offset="0.09"/> - <item android:color="#FFFF980E" android:offset="0.63"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M50.15,18.05c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.4 6.66,9 9,0 0,0 -6.27,-1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21 -0.38,-0.19 0.36,0.18a11,11 0,0 1,-6.13 -8.52s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88 0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71A10.031,10.031 0,0 0,17.29 16.77a12,12 0,0 1,-0.07 -6.36,19.21 19.21,0 0,0 -6.2,4.82c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.815,39.815 0,0 0,-0.3 1.64A31.77,31.77 0,0 0,0.02 27.6L0.02,27.77a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM47.56,19.39z"> - <aapt:attr name="android:fillColor"> - <gradient android:endX="9.339838" android:endY="45.985138" - android:startX="41.88179" android:startY="7.6808558" android:type="linear"> - <item android:color="#CCFFF44F" android:offset="0.17"/> - <item android:color="#00FFF44F" android:offset="0.6"/> - </gradient> - </aapt:attr> - </path> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_fx_accounts_avatar.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_fx_accounts_avatar.xml deleted file mode 100644 index c9d8f81943fcaeda93afb9109b54912929814cce..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_fx_accounts_avatar.xml +++ /dev/null @@ -1,108 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="72dp" - android:height="72dp" - android:viewportWidth="72" - android:viewportHeight="72"> - <path - android:pathData="M343,20.2c0,3.8 -3.1,6.9 -6.8,6.9h-27.5c-2.9,0 -5.2,-2.4 -5.2,-5.3s2.3,-5.3 5.2,-5.3c0.4,0 0.9,0.1 1.3,0.2c-0.1,-0.4 -0.1,-0.8 -0.1,-1.2c0,-3 2.4,-5.4 5.4,-5.4c1.1,0 2.2,0.4 3.1,0.9c1,-3.9 4.6,-6.8 8.8,-6.8c5,0 9.1,4.1 9.1,9.1C339.9,13.3 343,16.4 343,20.2zM283,34.2c-0.7,0 -1.3,0.1 -1.9,0.2c0.1,-0.6 0.2,-1.2 0.2,-1.8c0,-4.5 -3.7,-8.2 -8.2,-8.2c-1.7,0 -3.3,0.5 -4.6,1.4c-1.5,-5.9 -6.9,-10.2 -13.3,-10.2c-7.6,0 -13.7,6.1 -13.7,13.7c-5.7,0 -10.3,4.6 -10.3,10.3s4.6,10.3 10.3,10.3H283c4.3,0 7.9,-3.5 7.9,-7.9C290.9,37.7 287.3,34.2 283,34.2z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="65.8039" - android:centerX="287.1183" - android:centerY="27.0893" - android:type="radial"> - <item android:offset="0.3012" android:color="#00CDCDD4"/> - <item android:offset="0.8464" android:color="#33CDCDD4"/> - </gradient> - </aapt:attr> - </path> - <path - android:fillColor="#000000" - android:pathData="M289.8,31.5m-49,0a49,49 0,1 1,98 0a49,49 0,1 1,-98 0"/> - <path - android:fillColor="#000000" - android:pathData="M289.8,-4.7c-20,0 -36.2,16.2 -36.2,36.2c0,20 16.2,36.2 36.2,36.2c20,0 36.2,-16.2 36.2,-36.2C326,11.5 309.8,-4.7 289.8,-4.7zM289.8,5.7c8.6,0 15.5,6.9 15.5,15.5c0,8.6 -6.9,15.5 -15.5,15.5c-8.6,0 -15.5,-6.9 -15.5,-15.5C274.3,12.6 281.3,5.7 289.8,5.7zM311.1,46c-4.6,6.8 -12.4,11.3 -21.3,11.3s-16.6,-4.5 -21.3,-11.3c-1.3,-2 -1.2,-4.6 0.3,-6.3c5.5,-6.3 13,2.2 20.9,2.2c7.9,0 15.5,-8.5 20.9,-2.2C312.3,41.5 312.4,44.1 311.1,46z"/> - <group> - <clip-path android:pathData="M289.8,-4.7c-20,0 -36.2,16.2 -36.2,36.2c0,20 16.2,36.2 36.2,36.2c20,0 36.2,-16.2 36.2,-36.2C326,11.5 309.8,-4.7 289.8,-4.7zM289.8,5.7c8.6,0 15.5,6.9 15.5,15.5c0,8.6 -6.9,15.5 -15.5,15.5c-8.6,0 -15.5,-6.9 -15.5,-15.5C274.3,12.6 281.3,5.7 289.8,5.7zM311.1,46c-4.6,6.8 -12.4,11.3 -21.3,11.3s-16.6,-4.5 -21.3,-11.3c-1.3,-2 -1.2,-4.6 0.3,-6.3c5.5,-6.3 13,2.2 20.9,2.2c7.9,0 15.5,-8.5 20.9,-2.2C312.3,41.5 312.4,44.1 311.1,46z M 0,0"/> - <path - android:pathData="M333.6,20.5c0,3.8 -3.1,6.9 -6.8,6.9h-27.5c-2.9,0 -5.2,-2.4 -5.2,-5.3s2.3,-5.3 5.2,-5.3c0.4,0 0.9,0.1 1.3,0.2c-0.1,-0.4 -0.1,-0.8 -0.1,-1.2c0,-3 2.4,-5.4 5.4,-5.4c1.1,0 2.2,0.4 3.1,0.9c1,-3.9 4.6,-6.8 8.8,-6.8c5,0 9.1,4.1 9.1,9.1C330.5,13.6 333.6,16.7 333.6,20.5zM273.9,33.9c-0.7,0 -1.3,0.1 -1.9,0.2c0.1,-0.6 0.2,-1.2 0.2,-1.8c0,-4.5 -3.7,-8.2 -8.2,-8.2c-1.7,0 -3.3,0.5 -4.6,1.4c-1.5,-5.9 -6.9,-10.2 -13.3,-10.2c-7.6,0 -13.7,6.1 -13.7,13.7c-5.7,0 -10.3,4.6 -10.3,10.3s4.6,10.3 10.3,10.3h41.5c4.3,0 7.9,-3.5 7.9,-7.9C281.8,37.4 278.3,33.9 273.9,33.9z" - android:strokeAlpha="0.3" - android:fillAlpha="0.3"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="85.3299" - android:centerX="311.5509" - android:centerY="-2.3418" - android:type="radial"> - <item android:offset="0.1494" android:color="#00DDFF"/> - <item android:offset="0.5173" android:color="#70BAFF"/> - <item android:offset="0.8279" android:color="#CB9EFF"/> - </gradient> - </aapt:attr> - </path> - </group> - <path - android:fillColor="#000000" - android:pathData="M274.3,21.2c0,-8.6 6.9,-15.5 15.5,-15.5c8.6,0 15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5C281.3,36.7 274.3,29.8 274.3,21.2zM289.8,41.9c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3c8.9,0 16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C305.3,33.4 297.7,41.9 289.8,41.9z"/> - <group> - <clip-path android:pathData="M274.3,21.2c0,-8.6 6.9,-15.5 15.5,-15.5c8.6,0 15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5C281.3,36.7 274.3,29.8 274.3,21.2zM289.8,41.9c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3c8.9,0 16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C305.3,33.4 297.7,41.9 289.8,41.9z M 0,0"/> - <path - android:pathData="M276.8,18.1c0,-8.6 6.9,-15.5 15.5,-15.5c8.6,0 15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5C283.7,33.6 276.8,26.7 276.8,18.1zM292.3,38.8c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3c8.9,0 16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C307.7,30.3 300.2,38.8 292.3,38.8z" - android:fillColor="#FBFBFE"/> - </group> - <path - android:fillColor="#000000" - android:pathData="M145.3,-4.1c-20,0 -36.2,16.2 -36.2,36.2c0,20 16.2,36.2 36.2,36.2c20,0 36.2,-16.2 36.2,-36.2C181.5,12.1 165.3,-4.1 145.3,-4.1zM145.3,6.3c8.6,0 15.5,6.9 15.5,15.5c0,8.6 -6.9,15.5 -15.5,15.5c-8.6,0 -15.5,-6.9 -15.5,-15.5C129.8,13.2 136.8,6.3 145.3,6.3zM166.6,46.6C162,53.5 154.2,58 145.3,58c-8.9,0 -16.6,-4.5 -21.3,-11.3c-1.3,-2 -1.2,-4.6 0.3,-6.3c5.5,-6.3 13,2.2 20.9,2.2c7.9,0 15.5,-8.5 20.9,-2.2C167.8,42.1 167.9,44.7 166.6,46.6z"/> - <group> - <clip-path android:pathData="M145.3,-4.1c-20,0 -36.2,16.2 -36.2,36.2c0,20 16.2,36.2 36.2,36.2c20,0 36.2,-16.2 36.2,-36.2C181.5,12.1 165.3,-4.1 145.3,-4.1zM145.3,6.3c8.6,0 15.5,6.9 15.5,15.5c0,8.6 -6.9,15.5 -15.5,15.5c-8.6,0 -15.5,-6.9 -15.5,-15.5C129.8,13.2 136.8,6.3 145.3,6.3zM166.6,46.6C162,53.5 154.2,58 145.3,58c-8.9,0 -16.6,-4.5 -21.3,-11.3c-1.3,-2 -1.2,-4.6 0.3,-6.3c5.5,-6.3 13,2.2 20.9,2.2c7.9,0 15.5,-8.5 20.9,-2.2C167.8,42.1 167.9,44.7 166.6,46.6z M 0,0"/> - <path - android:pathData="M189.1,21.1c0,3.8 -3.1,6.9 -6.8,6.9h-27.5c-2.9,0 -5.2,-2.4 -5.2,-5.3s2.3,-5.3 5.2,-5.3c0.4,0 0.9,0.1 1.3,0.2c-0.1,-0.4 -0.1,-0.8 -0.1,-1.2c0,-3 2.4,-5.4 5.4,-5.4c1.1,0 2.2,0.4 3.1,0.9c1,-3.9 4.6,-6.8 8.8,-6.8c5,0 9.1,4.1 9.1,9.1C186,14.2 189.1,17.3 189.1,21.1zM129.4,34.5c-0.7,0 -1.3,0.1 -1.9,0.2c0.1,-0.6 0.2,-1.2 0.2,-1.8c0,-4.5 -3.7,-8.2 -8.2,-8.2c-1.7,0 -3.3,0.5 -4.6,1.4c-1.5,-5.9 -6.9,-10.2 -13.3,-10.2c-7.6,0 -13.7,6.1 -13.7,13.7c-5.7,0 -10.3,4.6 -10.3,10.3s4.6,10.3 10.3,10.3h41.5c4.3,0 7.9,-3.5 7.9,-7.9C137.3,38 133.7,34.5 129.4,34.5z" - android:strokeAlpha="0.3" - android:fillAlpha="0.3"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="85.3299" - android:centerX="167.0467" - android:centerY="-1.7465" - android:type="radial"> - <item android:offset="0.1494" android:color="#00DDFF"/> - <item android:offset="0.5173" android:color="#70BAFF"/> - <item android:offset="0.8279" android:color="#CB9EFF"/> - </gradient> - </aapt:attr> - </path> - </group> - <path - android:fillColor="#000000" - android:pathData="M129.8,21.8c0,-8.6 6.9,-15.5 15.5,-15.5c8.6,0 15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5C136.8,37.3 129.8,30.4 129.8,21.8zM145.3,42.5c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3s16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C160.8,34 153.2,42.5 145.3,42.5z"/> - <group> - <clip-path android:pathData="M129.8,21.8c0,-8.6 6.9,-15.5 15.5,-15.5c8.6,0 15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5C136.8,37.3 129.8,30.4 129.8,21.8zM145.3,42.5c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3s16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C160.8,34 153.2,42.5 145.3,42.5z M 0,0"/> - <path - android:pathData="M132.3,18.7c0,-8.6 6.9,-15.5 15.5,-15.5s15.5,6.9 15.5,15.5s-6.9,15.5 -15.5,15.5S132.3,27.3 132.3,18.7zM147.8,39.4c-7.9,0 -15.5,-8.5 -20.9,-2.2c-1.5,1.8 -1.7,4.4 -0.3,6.3c4.6,6.8 12.4,11.3 21.3,11.3s16.6,-4.5 21.3,-11.3c1.3,-2 1.2,-4.6 -0.3,-6.3C163.2,30.9 155.7,39.4 147.8,39.4z" - android:fillColor="#FBFBFE"/> - </group> - <path - android:pathData="M36,36m-24.5,0a24.5,24.5 0,1 1,49 0a24.5,24.5 0,1 1,-49 0"/> - <path - android:pathData="M36,7.2C20.1,7.2 7.2,20.1 7.2,36c0,15.9 12.9,28.8 28.8,28.8c15.9,0 28.8,-12.9 28.8,-28.8C64.8,20.1 51.9,7.2 36,7.2zM36,15.4c6.8,0 12.3,5.5 12.3,12.3c0,6.8 -5.5,12.3 -12.3,12.3c-6.8,0 -12.3,-5.5 -12.3,-12.3C23.7,21 29.2,15.4 36,15.4zM52.9,47.5c-3.7,5.4 -9.9,9 -16.9,9s-13.2,-3.6 -16.9,-9c-1.1,-1.6 -1,-3.6 0.3,-5.1c4.3,-5 10.4,1.7 16.6,1.7c6.3,0 12.3,-6.8 16.6,-1.7C53.9,43.9 54,46 52.9,47.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="70.8581" - android:startX="3.3842" - android:endY="6.5572" - android:endX="63.5488" - android:type="linear"> - <item android:offset="0.2552" android:color="#9059FF"/> - <item android:offset="0.9618" android:color="#00B3F4"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M-56,7.2c-15.9,0 -28.8,12.9 -28.8,28.8c0,15.9 12.9,28.8 28.8,28.8c15.9,0 28.8,-12.9 28.8,-28.8C-27.2,20.1 -40.1,7.2 -56,7.2zM-56,15.4c6.8,0 12.3,5.5 12.3,12.3c0,6.8 -5.5,12.3 -12.3,12.3c-6.8,0 -12.3,-5.5 -12.3,-12.3C-68.3,21 -62.8,15.4 -56,15.4zM-39.1,47.5c-3.7,5.4 -9.9,9 -16.9,9s-13.2,-3.6 -16.9,-9c-1.1,-1.6 -1,-3.6 0.3,-5.1c4.3,-5 10.4,1.7 16.6,1.7c6.3,0 12.3,-6.8 16.6,-1.7C-38.1,43.9 -38,46 -39.1,47.5z" - android:fillColor="#393473"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 8c5623c666a1932d8ba0a7261471bb1a0d2af703..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportWidth="108" - android:viewportHeight="108"> - <path - android:pathData="M78 44.4c-1.2-2.7-3.8-6-5.7-6.8-0.5-0.2-1.2 00.5-1 1-2.8-3.3-6-6.3-8-10.2l-0.6-1.3c-0.3-0.5-1-0.6-1.7-0a20 20 0 0 0-8.6 13.6c-0.5 0-3.3 0.3-3 1.8 0.7 1.3 1.8 0 3.2 0 4.4-0.3 7 0.7 9.4 3-1.6-0.3-4-0.6-4 0.9 0 0.5 1.3 1 1.8 1.5a9 9 0 0 1 3.5 9.3 9.2 9.2 0 0 1-10 7.6c-8.7-0.5-9.7-8.3-9.7-8.3 1.3-3 5.6-3.6 6.6-3.5 1.4 0 1.8-0.3 2.8-1 2-1.6 2.5-3 1.2-3.5-1-0.5-3-1.4-4.3-2.4-3-2-2.4-2.4-3.6-3-0.3-1.6-0.4-2.3-0.2-4 0-1 0.5-1.8 0-2-0.6-0.5-0.7-0.3-1.2-0-2.3 0.8-4.3 3-5 3.7a17 17 0 0 1-0.4-4c0.2-1.3-0.5-2-1.8-1a22.7 22.7 0 0 0-9.6 19.5 26 26 0 1 0 50-10.5zm-18.8-3c-1.6-0.5-3.3-1-5-1 0.2-2.8 2.6-7.6 4.4-9.2-0.7 2-1.3 7 0.6 10.2zm0.5-5.5c0-3.6 0.7-5 1.5-6.7a29.7 29.7 0 0 0 2.5 3.6c3.7 4.4 8 8 10 13.3 1 2.3-0 8.4-4 12a13 13 0 0 0-1.3-8c-0.8-1-1.5-2.3-2.6-3-2.2-3.5-2.4-2.7-4-4.8a11.2 11.2 0 0 1-2.2-6.6zm1.6 28c5-4 5.4-12 0.7-16.6 7.8 2.6 6.2 12 5.2 13.3-1 1.3-3.8 2.4-6 3.4zm-9.8-13.5c0 1.2-1.8 0.3-5 1.2-3 0.8-4.2 3.3-4.2 3.3 0-0.8 0.2-2.4-0.3-2.8-0.3-0.4-1-0.2-1.7-0.4a5.4 5.4 0 0 1-3.6-2.3c2.8-1.5 5.7-1 8.5 0.4 1.8 1 4.3 0.5 6.3 0.6zm-7.3-11.3s-0.2 1.3 0 2.7c0 0-1.6-0.5-2.7-0.5 1-1 2.7-2.2 2.7-2.2zM30 54.5c-1-5.4 2.4-13 7.6-17 0 2 0 4.3 1.3 5.4 0.3 0.2 1 0 1.8 0 1.4 0 3 0.4 4.2 1.2 1.7 1.2 2.2 2.8 6.5 4.7 0 0-4 0-5.2-0.3-2-0.6-3.3-1.7-7.3-1.5-1.7 0-4.8 1.4-4.5 2.3 0.7 2.6 3.6 4.3 6 4.5-0.8 7 7.3 13.4 14.5 13.2a21 21 0 0 0 20.2-14.3c0.3 4.8-1 10-4 13.6C66 73 58 75.2 49.3 73.7a24 24 0 0 1-19.2-19.2zm48 2.8a24.3 24.3 0 0 1-45.8 7.4c5.4 7.2 12 10.8 20.6 11 11.5 0.6 20.8-6 23.5-16.8 1.5-6-0-11.3-1.6-16.7a22.7 22.7 0 0 1 3.3 15z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="25.09" - android:startX="78.92" - android:endY="74.45" - android:endX="37.26" - android:type="linear"> - <item android:offset="0.09" android:color="#FF980E"/> - <item android:offset="0.18" android:color="#FF8B16"/> - <item android:offset="0.36" android:color="#FF672A"/> - <item android:offset="0.56" android:color="#FF3647"/> - <item android:offset="0.94" android:color="#E31587"/> - </gradient> - </aapt:attr> - </path> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_monochrome.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_monochrome.xml deleted file mode 100644 index 764616943fdeb6255e17f7c7361ba77a0384f8e1..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_launcher_monochrome.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="108dp" - android:height="109dp" - android:viewportWidth="108" - android:viewportHeight="109"> - <group> - <clip-path - android:pathData="M25.75,25.93h56.5v58.25h-56.5z"/> - <path - android:pathData="M80.22,45.46C78.99,42.51 76.5,39.33 74.54,38.32C75.94,41.01 76.9,43.9 77.41,46.89L77.41,46.93C74.21,38.98 68.79,35.78 64.36,28.79C64.13,28.43 63.91,28.07 63.69,27.71C63.58,27.52 63.48,27.33 63.38,27.13C63.2,26.77 63.06,26.4 62.96,26.01C62.96,25.99 62.95,25.98 62.94,25.96C62.93,25.95 62.91,25.94 62.89,25.94C62.88,25.93 62.86,25.93 62.84,25.94C62.84,25.94 62.83,25.94 62.83,25.95C62.82,25.95 62.81,25.95 62.81,25.96L62.82,25.94C56.53,29.61 53.92,36.05 53.25,40.14C51.31,40.25 49.4,40.74 47.64,41.57C47.47,41.65 47.34,41.8 47.27,41.98C47.21,42.16 47.22,42.36 47.3,42.53C47.38,42.71 47.52,42.84 47.7,42.91C47.88,42.97 48.08,42.96 48.25,42.88C49.79,42.16 51.44,41.73 53.13,41.61L53.3,41.6C53.53,41.59 53.76,41.58 53.99,41.57C55.37,41.56 56.73,41.75 58.05,42.14C58.13,42.16 58.21,42.18 58.28,42.21C58.5,42.28 58.72,42.35 58.94,42.43C59.09,42.49 59.25,42.55 59.4,42.61C59.53,42.66 59.66,42.71 59.78,42.77C59.98,42.85 60.17,42.94 60.36,43.04C60.45,43.08 60.54,43.12 60.62,43.17C60.81,43.27 60.99,43.37 61.17,43.47C61.29,43.54 61.41,43.61 61.52,43.68C63.57,44.94 65.27,46.7 66.47,48.79C64.47,47.41 62.05,46.82 59.65,47.13C69.83,52.21 67.09,69.68 52.99,69.02C51.74,68.97 50.5,68.73 49.31,68.32C49.04,68.21 48.76,68.1 48.48,67.98C48.32,67.91 48.16,67.83 48.01,67.75C44.55,65.97 41.7,62.6 41.34,58.51C41.34,58.51 42.65,53.66 50.69,53.66C51.56,53.66 54.05,51.24 54.1,50.54C54.09,50.31 49.16,48.35 47.24,46.47C46.22,45.46 45.73,44.97 45.3,44.61C45.07,44.41 44.82,44.23 44.57,44.06C43.92,41.81 43.89,39.42 44.49,37.16C41.88,38.42 39.56,40.2 37.68,42.41H37.67C36.54,40.99 36.62,36.32 36.68,35.34C36.35,35.47 36.03,35.64 35.74,35.84C34.75,36.54 33.82,37.34 32.97,38.2C32.01,39.18 31.12,40.24 30.33,41.37V41.37V41.37C28.51,43.94 27.22,46.84 26.53,49.92C26.35,50.78 26.19,51.64 26.07,52.52C26.04,52.74 26.01,52.96 25.98,53.18C25.9,53.72 25.85,54.25 25.82,54.79C25.82,54.82 25.82,54.85 25.81,54.88C25.79,55.19 25.77,55.5 25.75,55.82V55.96C25.82,63.05 28.51,69.86 33.3,75.06C38.1,80.25 44.65,83.47 51.67,84.06C58.7,84.66 65.7,82.6 71.29,78.28C76.88,73.97 80.68,67.71 81.92,60.74C81.97,60.37 82.01,60.01 82.05,59.64C82.63,54.84 82,49.96 80.21,45.47L80.22,45.46Z" - android:fillColor="#20123A"/> - </group> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_notification_permission.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_notification_permission.xml deleted file mode 100644 index c77633704d80e2ab99a69ba2bd9019da806b9983..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_notification_permission.xml +++ /dev/null @@ -1,546 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="973dp" - android:height="947dp" - android:viewportWidth="973" - android:viewportHeight="947"> - <path - android:pathData="M594.96,784.94C594.48,784.34 593.8,783.47 593.09,782.58C592.17,784.97 589,784.64 586.29,781.8C585.58,784.93 583.6,783.12 582.02,782.74C579.62,782.16 577.25,781.47 574.88,780.78C574.32,780.62 573.6,780.42 573.31,779.99C571.7,777.6 569.45,779.3 567.79,778.54C564.54,777.06 561.01,780.46 557.79,776.53C556.52,774.97 553.56,774.9 551.36,774.2C548.33,773.25 545.26,772.52 542.28,771.39C538.98,770.14 536.83,766.42 533.05,765.92C531.68,765.73 530.35,764.79 528.99,764.28C528.03,763.92 526.95,763.91 526.08,763.4C522.48,761.28 518.71,759.38 515.48,756.72C513.39,754.99 511.34,753.4 509,752.1C506.31,750.61 503.73,748.84 501.15,747.1C497.7,744.77 494.3,742.34 490.86,739.98C490.36,739.64 489.78,739.43 489.25,739.14C486.08,737.39 483.15,735.49 480.8,732.32C479.62,730.72 476.92,730.45 475.09,729.25C470.91,726.5 466.62,723.84 462.78,720.59C459.08,717.46 454.99,715.05 451.11,712.33C445.1,708.1 438.55,704.81 432.3,700.97C428.64,698.72 425.22,695.99 421.52,693.86C419.79,692.86 417.62,692.84 415.69,692.2C414.84,691.92 412.71,693.17 413.47,690.43C412.02,690.36 410.58,690.28 409.13,690.26C408.95,690.25 408.78,690.61 408.61,690.8C406.7,688.48 404.17,688.13 401.62,687.68C400.97,687.57 400.4,686.55 399.76,686.44C395.47,685.69 391.37,683.85 386.84,684.29C384.5,684.52 381.79,682.41 379.14,681.3C378.82,682.04 378.52,682.73 378.23,683.41C376.39,682.61 374.84,681.1 372.84,683.01C372.24,683.57 370,682.23 368.26,681.68C368.26,681.68 367.77,682.35 367.24,682.33C365.83,682.28 364.14,682.39 363.06,681.61C361.03,680.16 360.78,681.59 360.21,682.85C359.39,679.87 357.66,682.04 356.37,681.82C356.03,681.76 355.33,682.59 355.3,682.56C352.94,679.64 350.48,681.63 348.07,681.81C348,681.82 347.84,681.63 347.84,681.63C345.83,684.27 343.02,682.79 340.49,682.7C339.16,682.66 337.76,682.32 336.52,682.59C334.17,683.1 331.92,683.96 329.4,684.74C329.68,683.75 329.89,682.98 330.14,682.12C326.6,683.66 323.34,685.84 319.52,682.61L314.94,684.78C314.6,684.57 313.39,683.73 313.34,683.81C312.06,685.7 309.41,684.57 308.49,685.39C306.65,687.03 305,685.36 303.37,685.78C302.08,686.11 300.65,685.95 298.45,686.04C295.4,682.88 291.78,688.23 288.4,686.59C287.41,687.05 286.11,687.9 285.95,687.71C283.88,685.17 281.33,687.4 278.98,686.37C277.67,685.79 275.56,687.59 273.58,688.41C273.15,687.97 272.56,687.37 271.6,686.38C271.68,687.48 271.72,688.02 271.78,688.72C270.96,687.88 270.21,687.13 269.3,686.19C268.22,686.36 267.26,689.78 265.94,687.28C264.4,687.24 263.29,687.18 262.19,687.18C261.47,687.18 260.76,687.34 260.05,687.3C259.09,687.25 258.13,687.08 256.77,686.92C255,689.14 253.44,688.79 249.49,684.95L250.46,687.01C250.09,687.16 249.85,687.36 249.62,687.32C246.23,686.83 242.83,686.46 239.48,685.75C237.55,685.33 235.7,684.34 233.82,683.62C233.35,683.45 232.64,683.07 232.41,683.27C230.29,685.04 227.98,682.5 225.7,683.14C224.72,683.41 223.22,682.07 221.96,681.43C221.66,681.28 221.43,680.91 221.13,680.82C216.53,679.42 211.84,678.31 207.34,676.56C204.85,675.6 202.74,673.38 200.31,672.08C197.01,670.31 194.58,667.03 190.67,666.11C189.13,665.75 187.92,663.09 186.83,661.79C185.87,661.68 184.93,661.86 184.33,661.44C182.64,660.27 181.04,658.91 179.5,657.49C178.81,656.85 178.37,655.9 177.71,654.92C177.03,654.33 176.07,653.51 175.12,652.68C171.24,649.26 167.36,645.84 163.48,642.42C163.32,642.28 163.05,642.15 163.03,642.01C162.49,637.69 158.43,636.26 156.35,633.19C154.08,629.83 151.29,626.85 148.96,623.53C146.9,620.6 145.52,617.08 143.19,614.44C140.45,611.33 138.92,607.49 136.62,604.37C134.41,601.39 133.15,598 131.03,595.08C130.64,594.53 131.04,593.36 131.04,593.36C129.69,592.05 127.9,591.01 127.94,590.2C128.03,588.19 127.03,587.1 125.97,585.8C125.55,585.28 125.39,584.52 125.18,583.85C124.03,580.15 122.81,576.47 121.82,572.74C121.32,570.87 121.26,568.91 121,566.98C120.98,566.78 121.07,566.47 120.97,566.4C117.4,563.61 119.45,559.86 118.85,556.57C117.75,550.5 116.6,544.44 115.7,538.35C115.29,535.49 115.25,532.55 115.36,529.69C115.5,526.04 115.84,522.41 116.34,518.83C116.8,515.57 116.46,512.1 118.16,509.12C118.71,508.15 118.37,506.57 118.43,505.27C118.15,505.23 117.86,505.2 117.58,505.16C117.63,504.96 117.64,504.62 117.73,504.6C122.08,503.88 118.75,500.35 119.27,498.25C119.62,496.82 118.42,494.84 119.85,494.33C119.94,489.66 119.59,485.18 120.35,481.01C120.6,479.61 122.57,478.52 121.7,476.32C121.63,476.15 122.08,475.63 122.39,475.51C124.75,474.61 125.32,472.99 124.75,470.25C124.56,469.37 126,468.27 126.43,466.73C128.32,460.05 130.86,453.59 133.59,447.28C134.69,444.73 136.9,442.79 138.54,440.53C138.8,440.18 138.59,439.44 138.83,439.07C139.76,437.61 140.87,436.29 141.77,434.81C143.12,432.59 144.34,430.29 145.6,428.01C145.74,427.76 145.69,427.35 145.87,427.16C147.44,425.54 149.06,423.98 150.64,422.37C153.3,419.66 155.68,416.56 158.67,414.33C161.93,411.9 164.18,408.49 167.14,405.83C169.83,403.42 172.97,401.57 175.71,399.22C178.55,396.79 181.13,394.06 183.85,391.5C184.25,391.12 184.78,390.82 185.3,390.68C186.86,390.24 188.77,390.27 188.24,387.61C188.21,387.46 188.37,387.13 188.44,387.14C191.92,387.26 192.44,382.74 195.73,382.29C196.92,382.12 197.81,380.26 198.81,379.15C203.12,374.38 207.36,369.53 211.74,364.83C214.32,362.08 217.54,359.91 219.71,356.86C222.25,353.29 225.1,349.96 227.49,346.21C229,343.85 230.02,340.95 232.12,338.74C234.54,336.22 235.51,332.2 237.34,328.98C238.11,327.62 239.48,326.65 240.59,325.53C240.66,325.45 240.99,325.6 241.01,325.54C242.07,322.83 243.29,320.19 244.05,317.37C244.4,316.03 245.54,315.65 246.02,314.28C247.72,309.41 250.57,305.08 252.45,300.27C254.86,294.07 256.74,287.64 259.87,281.75C261.78,278.17 262.38,273.77 263.7,269.79C264.13,268.49 265.08,267.42 265.58,266.14C267.56,260.99 269.3,255.71 271.44,250.65C272.55,248.04 274.5,245.89 275.76,243.34C277.19,240.46 278.09,237.26 279.55,234.4C281.5,230.59 283.87,227.04 285.89,223.27C287.61,220.06 289.08,216.68 290.69,213.4C291.11,212.54 291.57,211.67 292.17,210.96C296.94,205.28 301.8,199.69 306.52,193.96C308.46,191.6 310.04,188.89 311.94,186.49C312.73,185.49 313.94,184.88 314.8,183.92C315.98,182.8 317.19,181.71 318.33,180.55C319.58,179.29 320.67,177.84 322.01,176.69C323.8,175.14 325.77,173.82 327.65,172.37C327.86,172.21 327.99,171.94 328.15,171.71C328.43,171.29 328.61,170.71 328.99,170.49C332.32,168.54 335.29,166.04 338.5,163.9C339.93,162.95 341.34,161.97 343.2,160.71L349.4,157.78C350.95,157.81 352.52,156.22 353.18,152.77C354.1,153.47 354.99,154.15 356.01,154.92C356,154.4 355.83,153.51 356.01,153.44C358.06,152.56 360.17,151.81 362.26,151.02C364.27,150.26 366.27,149.5 368.27,148.74C369.7,148.19 371.09,147.55 372.55,147.1C375.05,146.32 377.54,145.32 380.13,145.03C383.74,144.62 386.52,142.14 390.06,141.68C392.43,141.38 395.12,140.04 397.09,140.9C399.9,142.14 400.34,140.38 401.72,139.16C401.51,139.64 401.29,140.12 400.67,141.51C402.75,140.32 404.15,139.51 406.18,138.35C405.69,139.39 405.5,139.77 405.59,139.59C407.68,139.83 410.15,140.53 412.44,140.25C414.77,139.97 416.93,138.71 419.47,137.77C419.88,139.15 420.24,140.39 420.67,141.84C420.99,140.2 424.43,137.74 425.21,138.59C427.76,141.37 430.76,139.5 433.52,140.41C436.69,141.45 440.2,140.91 443.55,141.34C444.53,141.47 445.41,142.83 446.43,143.13C449.21,143.94 452.08,144.34 454.86,145.18C457.64,146.03 460.38,147.14 463.09,148.29C464.28,148.8 465.31,149.8 466.48,150.4C467.49,150.91 468.6,151.23 469.68,151.5C470.57,151.74 471.6,151.54 472.39,151.96C477.76,154.82 483.16,157.63 488.38,160.8C491.57,162.74 494.4,165.38 497.5,167.52C498.51,168.22 499.84,168.35 501.17,168.78C501.91,169.44 502.89,170.42 503.96,171.26C506.8,173.47 509.64,175.69 512.56,177.79C514.91,179.48 517.4,180.94 519.76,182.61C523.26,185.07 526.76,187.56 530.16,190.18C532.33,191.84 534.24,193.92 536.45,195.51C540.13,198.15 543.95,200.55 547.72,203.02C550.81,205.05 553.9,207.09 557.04,209.02C557.97,209.59 559.1,209.75 560.09,210.21C563.4,211.73 566.7,213.25 569.97,214.87C572.39,216.06 574.74,217.46 577.17,218.66C578.64,219.39 580.17,220.02 581.72,220.51C585.11,221.58 588.55,222.42 591.91,223.56C595.22,224.69 598.47,226.09 601.75,227.35C602.46,227.62 603.2,227.77 603.92,228.02C606.87,229.05 609.81,230.1 613.16,231.28C614.9,231.33 617.2,231.4 620.03,231.49C622,235.63 625.83,233.44 629.5,233.6C628.89,234.28 628.49,234.73 627.37,235.97C634.77,235.44 641.13,236.84 647.19,240.92C649.19,239.43 653.36,239.9 655.4,242.29C657.97,240.36 660.09,241.2 662.8,243.38C665,245.14 668.25,245.38 671.03,246.26C671.46,246.39 672.05,246.18 672.36,246.43C674.49,248.19 676.53,248.08 678.72,246.98C679.16,246.76 680.05,247.34 680.69,247.66C681.18,247.9 681.58,248.51 682.06,248.62C684.34,249.13 686.78,249.09 688.88,250.05C691.75,251.38 694.63,251.46 697.51,252.11C700.13,252.71 702.55,254.77 705.06,256.19C705.47,255.82 705.89,255.44 705.97,255.36C710.26,258.39 714.89,258.67 719.33,259.79C720.44,260.07 721.44,261.05 722.7,261.84C724.36,260.12 725.93,262.12 727.6,262.91C730.14,264.1 732.64,265.38 735.5,266.79C735.65,266.63 735.33,266.96 734.99,267.32C737.99,268.02 740.88,268.35 743.57,269.39C746.92,270.68 750.14,272.47 753.35,274.21C754.3,274.73 754.77,276.28 756.23,275.17C756.61,274.89 757.83,275.65 758.59,276.1C760.13,277.02 761.61,278.1 763.14,279.05C764.71,280.02 766.38,280.81 767.88,281.89C768.97,282.67 769.45,284.85 771.34,283.47C771.45,283.4 772.17,284.37 772.68,284.72C774.36,285.85 776.08,286.93 777.79,288.01C777.94,288.11 778.15,288.1 778.29,288.2C781.65,290.75 785.05,293.24 788.36,295.86C792.41,299.05 796.49,302.21 800.35,305.66C802.39,307.48 803.72,311.02 805.85,311.71C807.99,312.41 809.33,313.68 810.39,315.09C812.14,317.45 815.52,317.95 816.34,321.45C816.55,322.35 818.79,322.67 819.65,323.68C821.36,325.7 822.8,327.97 824.26,330.21C826.02,332.9 827.01,336.03 830.08,337.85C831.58,338.74 832.3,341.13 833.53,342.71C835.34,345.04 837.3,347.25 839.62,350.02C839.61,350.15 839.57,351.17 839.52,352.28C841.4,353.17 843.2,354.04 843.09,356.89C843.05,357.9 843.98,359.43 844.86,360.06C846.99,361.58 847.87,363.8 848.11,366.02C848.36,368.28 849.39,368.86 850.76,368.95C851.61,371.21 852.02,373.43 853.18,375.12C854.49,377.04 855.92,378.52 854.54,380.93C854.39,381.19 855.65,382.54 856.37,383.27C857.58,384.49 858.72,385.24 857.95,387.59C857.41,389.23 857.84,391.74 859.83,393.59C861.08,394.74 861.48,396.96 862.27,398.69C861.88,398.84 861.5,398.98 860.72,399.27C861.93,401.48 863.34,403.65 864.33,405.99C864.96,407.47 864.9,409.22 865.31,410.81C865.6,411.91 866.06,413 866.63,413.98C867.48,415.46 868.08,416.69 866.61,417.02C866.67,418.3 866.74,419.58 866.8,420.86C866.82,421.28 866.69,421.77 866.85,422.1C869.94,428.27 869.32,434.9 870.32,441.33C870.87,444.92 871.23,448.53 871.63,452.13C871.71,452.83 871.85,453.7 871.56,454.2C870.78,455.51 871.27,456.49 871.54,457.96C872.18,461.4 872.15,465.29 871.12,468.45C870.67,469.83 871.62,469.65 871.6,470.21C871.45,474.45 870.68,478.77 871.38,482.92C871.81,485.48 870.68,487.41 870.95,489.77C871.11,491.24 869.96,492.74 869.55,494.29C868.87,496.91 868.17,499.54 867.75,502.23C867.38,504.58 867.31,506.97 865.22,508.42C864.85,508.67 864.37,509.19 864.41,509.56C864.9,513.83 862.28,516.74 861.01,520.25C859.97,523.13 859.34,526.2 858.4,529.13C857.52,531.89 856.57,534.63 855.47,537.28C854.65,539.24 853.73,541.2 852.5,542.85C851.83,543.74 852.39,545.84 850.38,545.6C850.3,545.59 849.9,546.98 850.11,547.54C851.37,550.86 848.21,551.62 847.34,553.68C847.27,553.86 846.65,553.74 846.84,553.73C846.38,555.27 846.28,556.64 845.64,557.57C843.2,561.11 839.96,564.17 838.21,568.08C836.58,571.72 834.81,574.72 831.7,577.06C830.01,578.34 829.28,580.91 827.92,582.72C825.54,585.89 823.06,588.97 820.52,591.98C818.65,594.18 816.6,596.21 814.66,598.33C810.85,602.51 807.02,606.66 803.28,610.9C800.77,613.75 798.74,617.17 795.9,619.54C791.67,623.07 787.96,627.03 784.31,631.18C780.65,635.34 776.15,638.64 772.27,642.6C769.56,645.36 767.37,648.69 764.77,651.58C763.63,652.84 761.8,653.41 760.69,654.69C758.86,656.8 757.47,659.32 755.7,661.49C753.22,664.54 750.59,667.45 747.99,670.39C746.28,672.33 744.44,674.14 742.81,676.14C741.69,677.52 740.89,679.18 739.82,680.6C739.23,681.39 738.38,681.94 737.31,682.91C737.14,683.64 737.14,685.36 736.4,686.48C732.57,692.23 728.64,697.89 724.57,703.44C722.51,706.24 719.9,708.59 717.9,711.43C716.84,712.93 716.55,715.06 715.95,716.92C715.86,717.18 716.03,717.76 715.94,717.79C711.57,719.21 711.77,724.8 708.31,727.27C706.44,728.61 705.91,731.8 704.37,733.81C700.09,739.39 695.63,744.81 691.16,750.23C690.65,750.85 689.38,750.83 688.98,751.48C686.4,755.72 682.23,758.06 678.67,761.09C676.34,763.09 673.66,764.63 671.07,766.29C670.56,766.61 669.78,766.52 669.66,767.15C668.61,768.18 667.65,769.32 666.5,770.21C665.07,771.33 663.58,772.45 661.95,773.18C660.54,773.81 658.91,773.98 657.35,774.2C653.66,774.72 650.29,776.48 646.36,776.14C645.04,776.03 643.7,777.39 642.38,778.09C640.95,778.86 639.66,780.71 637.89,778.16C637.58,778.82 637.46,779.68 637.06,779.83C634.1,780.94 631.08,781.91 628.08,782.92C627.91,782.98 627.67,783.13 627.55,783.05C624.53,781.22 622.44,784.11 619.82,784.13C618.52,784.14 617.17,783.53 615.52,783.11C615.58,783.06 615.08,783.78 614.42,783.95C612.58,784.41 610.67,784.67 608.78,784.96C608.45,785.01 607.94,784.95 607.76,784.72C605.86,782.36 604.09,783.44 602.04,784.14C600.66,784.62 598.91,784.05 597.35,784.13C596.6,784.17 595.89,784.61 594.96,784.94L594.96,784.94Z" - android:fillColor="#9059FF" - android:fillAlpha="0.3"/> - <path - android:pathData="M512.2,327.58C517.67,329.63 522.42,333.25 525.86,337.98C531.21,345.35 534.63,353.94 535.81,362.96C535.85,363.24 535.89,363.51 535.93,363.78C535.98,364.19 536.04,364.6 536.09,365.01C538.29,392.48 519.11,417.07 491.93,421.61C464.75,426.16 438.61,409.16 431.75,382.48L431.68,382.21C431.17,379.8 430.85,377.36 430.7,374.9L430.67,374.79C430.61,374.28 430.38,371.92 430.36,371.45L430.34,371.08C430.16,365.16 431.16,359.27 433.28,353.73C434.19,351.31 435.3,348.98 436.61,346.74C437.74,344.76 439.06,342.89 440.53,341.15C440.98,340.65 441.47,340.19 442.01,339.79C442.71,344.28 444.45,348.53 447.09,352.22C449.48,347.33 452.86,343 457.02,339.48C456.99,343.89 458.16,348.21 460.38,352.01C460.97,352.23 461.45,352.43 461.97,352.68C465.21,348.44 469.66,345.28 474.73,343.6C472.77,331.54 476.62,319.27 485.11,310.48L485.15,310.47C485.18,310.45 485.21,310.45 485.25,310.45C485.32,310.44 485.39,310.49 485.4,310.56C485.76,311.22 486.19,311.84 486.69,312.4C486.93,312.68 487.2,312.99 487.53,313.3C487.95,313.72 488.38,314.14 488.81,314.56C488.96,314.7 489.1,314.84 489.24,314.98C493.79,319.26 498.35,322.35 502.79,325.37C509.39,329.86 515.74,334.18 521.43,341.95L521.41,341.86C519.09,336.65 515.99,331.83 512.2,327.58ZM476.89,393.43C476.97,393.44 477.05,393.46 477.13,393.48L476.89,393.43ZM477.13,393.48C477.16,393.48 477.2,393.49 477.24,393.5C477.39,393.53 477.54,393.57 477.7,393.6L477.13,393.48Z" - android:fillType="evenOdd"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="462.98" - android:startY="286.69" - android:endX="395.39" - android:endY="388.74" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.11" android:color="#FFFFE847"/> - <item android:offset="0.23" android:color="#FFFFC830"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.4" android:color="#FFFF8B16"/> - <item android:offset="0.46" android:color="#FFFF672A"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M525.86,337.98C522.42,333.25 517.67,329.63 512.2,327.58C515.99,331.83 519.09,336.65 521.41,341.86L521.43,341.96C528.31,352.29 530.92,364.87 528.74,377.08C525.11,395.24 510.86,409.41 492.68,412.94C468.22,418.48 443.2,406.27 432.53,383.58C431.36,380.83 430.74,377.89 430.7,374.9C430.79,377.36 431.12,379.81 431.68,382.21L431.75,382.48C438.61,409.16 464.75,426.16 491.93,421.61C519.11,417.07 538.29,392.48 536.09,365.01C536.01,364.33 535.9,363.65 535.81,362.96C534.63,353.94 531.21,345.35 525.86,337.98V337.98Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="509.01" - android:centerY="316.92" - android:gradientRadius="110.67" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.19" android:color="#FFFFAC31"/> - <item android:offset="0.25" android:color="#FFFF9D17"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.4" android:color="#FFFF563B"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.71" android:color="#FFF5156C"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M525.86,337.98C522.42,333.25 517.67,329.63 512.2,327.58C515.99,331.83 519.09,336.65 521.41,341.86L521.43,341.96C528.31,352.29 530.92,364.87 528.74,377.08C525.11,395.24 510.86,409.41 492.68,412.94C468.22,418.48 443.2,406.27 432.53,383.58C431.36,380.83 430.74,377.89 430.7,374.9C430.79,377.36 431.12,379.81 431.68,382.21L431.75,382.48C438.61,409.16 464.75,426.16 491.93,421.61C519.11,417.07 538.29,392.48 536.09,365.01C536.01,364.33 535.9,363.65 535.81,362.96C534.63,353.94 531.21,345.35 525.86,337.98V337.98Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="481.06" - android:centerY="370.78" - android:gradientRadius="110.67" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#57DB293D"/> - <item android:offset="0.5" android:color="#17F5334B"/> - <item android:offset="0.53" android:color="#02FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M502.41,350.43L502.8,350.58C500.92,348.63 498.77,346.94 496.42,345.58C483.95,338.74 478.98,323.37 485.1,310.53C476.63,319.3 472.78,331.56 474.73,343.6C475.32,343.41 475.9,343.2 476.51,343.05C485.84,340.67 495.73,343.49 502.41,350.43V350.43Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="476.52" - android:centerY="299.31" - android:gradientRadius="80.18" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.25" android:color="#FFFFDC3E"/> - <item android:offset="0.51" android:color="#FFFF9D12"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M480.73,359.39C480.05,362.29 478.38,364.86 476.01,366.66C461.41,370.4 461.27,379.87 461.27,379.87C464.07,386.93 470.25,392.1 477.7,393.6C478.02,393.67 478.35,393.73 478.67,393.79C479.23,393.88 479.79,393.96 480.34,394.02C482.69,394.24 485.06,394.11 487.38,393.63C497.71,392.01 505.47,383.33 505.92,372.88C506.38,362.43 499.4,353.11 489.24,350.6C493.46,348.91 498.15,348.85 502.41,350.43C495.73,343.48 485.82,340.67 476.48,343.05C475.87,343.21 475.29,343.41 474.7,343.61C469.63,345.28 465.18,348.45 461.94,352.69C462.9,353.15 464.01,353.81 466.35,355.17C471.01,357.01 475.82,358.42 480.73,359.39V359.39Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="476.37" - android:centerY="401.83" - android:gradientRadius="52.7" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.47" android:color="#FF5C79F0"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M480.73,359.39C480.05,362.29 478.38,364.86 476.01,366.66C461.41,370.4 461.27,379.87 461.27,379.87C464.07,386.93 470.25,392.1 477.7,393.6C478.02,393.67 478.35,393.73 478.67,393.79C479.23,393.88 479.79,393.96 480.34,394.02C482.69,394.24 485.06,394.11 487.38,393.63C497.71,392.01 505.47,383.33 505.92,372.88C506.38,362.43 499.4,353.11 489.24,350.6C493.46,348.91 498.15,348.85 502.41,350.43C495.73,343.48 485.82,340.67 476.48,343.05C475.87,343.21 475.29,343.41 474.7,343.61C469.63,345.28 465.18,348.45 461.94,352.69C462.9,353.15 464.01,353.81 466.35,355.17C471.01,357.01 475.82,358.42 480.73,359.39V359.39Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="479.27" - android:centerY="357.86" - android:gradientRadius="27.94" - android:type="radial"> - <item android:offset="0.21" android:color="#029059FF"/> - <item android:offset="0.28" android:color="#108C4FF3"/> - <item android:offset="0.75" android:color="#727716A8"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M459.13,351.58L460.38,352.01C458.16,348.21 456.99,343.89 457.02,339.48C452.86,343 449.48,347.33 447.09,352.22C451,351.08 455.12,350.86 459.13,351.58V351.58Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="467.35" - android:centerY="322.92" - android:gradientRadius="37.91" - android:type="radial"> - <item android:offset="0" android:color="#FFFFE226"/> - <item android:offset="0.12" android:color="#FFFFDB27"/> - <item android:offset="0.29" android:color="#FFFFC82A"/> - <item android:offset="0.5" android:color="#FFFFA930"/> - <item android:offset="0.73" android:color="#FFFF7E37"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M432.53,383.58C443.19,406.27 468.2,418.49 492.66,412.97C510.86,409.44 525.12,395.26 528.74,377.08C530.93,364.87 528.32,352.29 521.45,341.96L521.43,341.88L521.46,341.97C525.8,353.75 523.63,366.95 515.76,376.73L515.74,376.81C501.14,396.56 481.95,395.13 477.75,393.61L476.9,393.43C466.61,391.92 458.45,383.97 456.65,373.73C451.46,375.14 445.92,373.36 442.52,369.18C447.36,364.19 454.44,362.07 461.23,363.57C468.03,364.78 475.03,363.28 480.73,359.39C475.83,358.41 471.02,357 466.37,355.17C464.04,353.8 462.93,353.14 461.97,352.68C461.45,352.43 460.98,352.23 460.38,352.01L459.13,351.58C455.12,350.86 451,351.08 447.09,352.22C444.45,348.53 442.71,344.28 442.01,339.79C441.47,340.19 440.98,340.65 440.53,341.15C439.06,342.89 437.74,344.76 436.61,346.74C435.3,348.98 434.19,351.31 433.28,353.73C431.16,359.27 430.16,365.16 430.34,371.08C430.4,375.34 431.14,379.56 432.53,383.58Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="490.25" - android:centerY="292.22" - android:gradientRadius="161.75" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.62" android:color="#FFFF5634"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M496.42,345.58C498.77,346.94 500.92,348.63 502.8,350.58C503.13,350.73 503.45,350.87 503.74,351.05C512.59,356.39 517.34,366.55 515.76,376.77C523.64,366.98 525.8,353.76 521.45,341.97C511.92,328.96 500.55,325.62 489.24,314.98C488.67,314.42 488.09,313.86 487.53,313.3C487.2,312.99 486.93,312.68 486.69,312.4C486.19,311.84 485.76,311.22 485.4,310.56C485.39,310.49 485.32,310.44 485.25,310.45C485.21,310.45 485.18,310.45 485.15,310.47L485.11,310.48C478.96,323.33 483.93,338.74 496.42,345.58V345.58Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="479.89" - android:centerY="313.47" - android:gradientRadius="118.55" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.06" android:color="#FFFFE847"/> - <item android:offset="0.17" android:color="#FFFFC830"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.36" android:color="#FFFF8B16"/> - <item android:offset="0.46" android:color="#FFFF672A"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M503.73,351.02C503.45,350.87 503.13,350.73 502.79,350.55L502.4,350.4C498.14,348.82 493.45,348.88 489.23,350.57C499.35,353.11 506.29,362.41 505.83,372.83C505.38,383.25 497.66,391.91 487.36,393.56C485.05,394.04 482.67,394.17 480.32,393.95C479.77,393.89 479.21,393.82 478.65,393.72C478.33,393.66 478.01,393.6 477.68,393.53C481.89,395.05 501.07,396.49 515.67,376.73L515.69,376.65C517.25,366.48 512.53,356.36 503.73,351.02V351.02Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="469.97" - android:centerY="336.74" - android:gradientRadius="100.98" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.59" android:color="#FFFF5634"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M461.27,379.87C461.27,379.87 461.38,370.41 476.01,366.66C478.38,364.86 480.05,362.29 480.73,359.39C475.03,363.28 468.03,364.78 461.23,363.57C454.44,362.07 447.36,364.19 442.52,369.18C445.92,373.36 451.46,375.14 456.65,373.73C458.45,383.97 466.6,391.91 476.89,393.43C477.16,393.48 477.41,393.55 477.7,393.6C470.25,392.1 464.07,386.93 461.27,379.87Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="497.26" - android:centerY="335.85" - android:gradientRadius="110.52" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.23" android:color="#FFFFE141"/> - <item android:offset="0.51" android:color="#FFFFAF1E"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M525.86,337.98C522.42,333.25 517.67,329.63 512.2,327.58C515.99,331.83 519.09,336.65 521.41,341.86L521.43,341.95C511.92,328.96 500.55,325.62 489.24,314.98C488.67,314.42 488.09,313.86 487.53,313.3C487.2,312.99 486.93,312.68 486.69,312.4C486.19,311.84 485.76,311.22 485.4,310.56C485.39,310.49 485.32,310.44 485.25,310.45C485.21,310.45 485.18,310.45 485.15,310.47L485.11,310.48C476.62,319.27 472.77,331.54 474.73,343.6C475.32,343.41 475.9,343.2 476.51,343.05C485.85,340.66 495.75,343.48 502.44,350.42C498.18,348.85 493.48,348.91 489.27,350.59C499.39,353.13 506.32,362.43 505.87,372.86C505.41,383.28 497.69,391.94 487.39,393.59C485.08,394.07 482.71,394.2 480.36,393.98C479.81,393.92 479.25,393.84 478.69,393.75C478.37,393.69 478.04,393.63 477.72,393.56L476.88,393.38C477.14,393.43 477.4,393.5 477.68,393.54C470.25,392.05 464.08,386.91 461.27,379.87C461.27,379.87 461.38,370.41 476.01,366.66C478.38,364.86 480.05,362.29 480.73,359.39C475.83,358.41 471.02,357 466.37,355.17C464.04,353.8 462.93,353.14 461.97,352.68C461.45,352.43 460.97,352.23 460.38,352.01C458.16,348.21 456.99,343.89 457.02,339.48C452.86,343 449.48,347.33 447.09,352.22C444.45,348.53 442.71,344.28 442.01,339.79C441.47,340.19 440.98,340.65 440.53,341.15C439.06,342.89 437.74,344.76 436.61,346.74C435.3,348.98 434.19,351.31 433.28,353.73C431.16,359.27 430.16,365.16 430.34,371.08L430.36,371.45C430.38,371.92 430.53,374.33 430.6,374.84C430.6,374.84 430.59,374.8 430.6,374.84C430.81,377.32 431.17,379.78 431.68,382.21L431.75,382.48C438.61,409.16 464.75,426.16 491.93,421.61C519.11,417.07 538.29,392.48 536.09,365.01C536.01,364.33 535.9,363.65 535.81,362.96C534.63,353.94 531.21,345.35 525.86,337.98V337.98Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="468.23" - android:startY="291.87" - android:endX="411.29" - android:endY="381.28" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.27" android:color="#A1FFF44F"/> - <item android:offset="0.49" android:color="#37FFF44F"/> - <item android:offset="0.6" android:color="#02FFF44F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M809.71,732.48C813.73,727.11 818.3,729.59 822.89,730.03C822.85,729.68 822.62,729.05 822.78,728.57C822.96,728.05 823.43,727.46 823.92,727.27C824.24,727.15 824.95,727.56 825.26,727.92C830.28,733.67 835.19,739.53 840.29,745.2C844.56,749.94 848.97,754.56 853.47,759.08C857.91,763.53 862.65,767.68 867,772.22C867.82,773.08 868.09,775.61 867.43,776.51C866.29,778.1 864.81,776.81 863.65,775.67C858.28,770.42 852.69,765.37 847.52,759.93C842.58,754.74 838.06,749.15 833.58,743.98C833.58,746.07 833.7,748.58 833.56,751.08C832.69,766.06 827.91,779.02 814.91,787.96C808.17,792.6 801.86,797.85 795.15,802.53C790.11,806.04 784.81,809.19 779.52,812.33C767.18,819.63 753.68,824.41 740.55,829.98C733.05,833.16 725.34,834.91 716.42,831.58C718.75,835.3 720.58,838.38 722.56,841.37C726.65,847.53 730.82,853.64 734.93,859.78C735.26,860.28 735.67,860.94 735.6,861.47C735.47,862.58 735.05,863.66 734.75,864.75C733.67,864.23 732.15,864 731.58,863.14C727.59,857.09 723.74,850.95 719.95,844.77C716.51,839.18 713.72,833.12 709.71,828C704.62,821.51 705.53,814.55 707.61,808C708.79,804.28 707.18,803.37 705.29,801.82C695.69,793.94 684.87,788.1 673.5,783.3C667.6,780.8 661.47,778.84 655.47,776.55C650.5,774.65 645.61,772.55 640.64,770.67C632.54,767.62 624.29,764.97 616.33,761.63C607.64,757.98 599.28,753.71 591.54,748.14C583.52,742.36 576.04,736.07 569.32,728.89C563.62,722.8 558.45,716.19 552.53,710.33C548.6,706.43 543.88,703.28 539.3,700.09C532.74,695.5 525.85,691.31 521.16,684.59C517.94,679.98 514.99,675.16 516.26,669.15C517.49,663.36 521,659.36 526.35,656.82C532.78,653.77 539.27,655.56 545.63,656.64C552.68,657.83 559.64,659.81 565.37,664.46C569.89,668.13 574.11,672.16 578.64,675.82C581.27,677.95 584.16,679.8 587.08,681.54C590.97,683.87 595,685.98 598.99,688.17C599.58,688.49 600.25,688.68 601.63,689.24C591.06,673.29 580.97,657.98 570.78,642.72C568.64,639.51 566.25,636.46 563.84,633.45C563.4,632.89 562.24,632.51 561.53,632.64C551.32,634.49 541.14,636.47 530.95,638.37C521.88,640.06 512.8,641.71 503.72,643.32C500.37,643.91 497,644.36 493.63,644.8C491.84,645.03 490.87,646 489.65,647.36C487.39,649.9 484.39,651.77 481.75,653.97C476.74,658.16 471.66,662.28 466.8,666.64C463.62,669.49 460.48,672.48 457.87,675.83C455.28,679.16 453.46,683.07 451.16,686.64C446.71,693.54 442.13,700.35 437.67,707.24C433.47,713.76 429.35,720.32 425.26,726.9C424.93,727.43 424.87,728.27 425,728.9C425.57,731.68 426.25,734.43 426.92,737.18C427.02,737.58 427.39,737.92 427.49,738.32C427.75,739.4 428.4,740.66 428.08,741.56C425.25,749.56 422.15,757.47 419.32,765.47C417.67,770.14 416.45,774.95 414.86,779.64C414.32,781.24 413.7,783.56 411.37,782.9C408.79,782.16 409.62,779.83 410.19,778.1C412.8,770.2 415.52,762.34 418.25,754.48C419.01,752.3 419.97,750.18 420.88,747.92C417.03,749.72 413.61,751.7 409.94,752.95C402.48,755.48 394.76,756.33 387.03,754.41C377.67,752.08 368.73,748.53 360.22,744C351.89,739.57 343.41,735.28 335.58,730.07C325.21,723.17 314.67,716.38 305.87,707.41C302.42,703.89 299.27,700.07 296.07,696.32C292.38,691.98 288.79,687.56 285.1,683.11C282.14,688.25 279.08,693.52 276.05,698.82C275.32,700.1 274.92,701.64 273.99,702.73C273.26,703.59 271.89,704.49 270.89,704.4C268.9,704.21 268.9,702.41 269.58,701.07C271.52,697.24 273.62,693.5 275.73,689.76C278.49,684.87 281.56,680.14 284.05,675.12C288.2,666.71 300.74,663.53 308.28,669.78C308.9,670.29 309.62,670.67 310.54,671.27C313.76,666.49 316.99,661.76 320.17,656.99C323.4,652.15 326.68,647.33 329.75,642.38C333.82,635.82 337.73,629.17 341.64,622.51C343.8,618.83 345.91,615.12 347.8,611.3C348.35,610.21 347.8,608.62 348.19,607.41C350.92,599.09 352.39,590.51 353.17,581.85C353.64,576.72 353.38,571.51 353.36,566.34C353.33,558.37 353.32,550.4 353.12,542.44C352.99,537.52 352.46,532.61 352.23,527.69C351.96,522.1 351.81,516.5 351.63,510.91C351.46,505.73 351.25,500.56 351.19,495.39C351.11,488.61 351.29,481.83 351.12,475.05C350.89,465.77 352.25,456.65 353.17,447.45C354.34,435.63 354.62,423.71 354.92,411.83C355.11,404.7 354.65,397.55 354.41,390.4C354.18,383.48 357.07,377.48 359.81,371.42C362.33,365.87 372.47,363.24 377.62,368.41C377.86,368.65 378.18,368.82 378.91,369.35C377.63,365.16 376.41,361.49 375.39,357.77C372.72,348.01 370.02,338.27 367.54,328.46C365.74,321.32 364.2,314.11 362.7,306.9C360.9,298.3 362.42,290.16 367.31,282.92C370.01,278.91 374.39,276.53 378.76,274.74C388.27,270.84 397.89,267.15 407.61,263.8C414.6,261.39 421.8,259.55 428.96,257.67C435.14,256.06 441.42,254.85 447.61,253.27C452.62,251.99 457.54,250.32 462.54,248.99C468.26,247.46 473.99,245.97 479.77,244.72C488.28,242.89 496.84,241.25 505.39,239.63C508.84,238.98 512.33,238.47 515.82,238.17C521.4,237.69 526.99,237.32 532.59,237.14C534.61,237.07 536.76,237.37 538.68,238.01C550.18,241.84 556.17,250.24 558.51,261.85C559.63,267.42 561.6,272.82 562.91,278.36C565.15,287.82 567.08,297.36 569.31,306.83C570.86,313.46 572.6,320.06 574.41,326.63C576.53,334.3 579,341.88 581,349.58C583.31,358.47 585.27,367.45 587.4,376.39C588.6,381.41 589.85,386.41 591.04,391.43C591.19,392.07 590.99,392.8 591.14,393.45C591.52,395.18 592.04,396.89 592.44,398.62C593.52,403.23 595.51,407.69 594.91,413.28C596.99,412.7 599.13,412.14 601.25,411.49C608.61,409.23 615.54,410.96 621.16,415.46C626.66,419.88 627.79,426.69 626.6,433.52C626,436.92 624.57,440.18 623.46,443.66C627.26,445.49 630.76,448.79 632.61,453.2C634.93,458.74 633.54,464.34 630.92,469.52C629.88,471.6 629.64,473.04 630.82,475.36C632.84,479.35 633.24,483.82 632.01,488.34C631.02,491.96 630.34,495.67 629.45,499.67C633.8,504.74 632.13,511.54 632.48,517.94C632.87,525.03 629.66,530.44 625.09,534.3C628,545.53 630.81,556.38 633.64,567.3C634.35,566.76 635.39,565.88 636.5,565.09C641.59,561.5 647.33,560.07 653.31,561.56C655.93,562.22 658.3,564.35 660.47,566.19C662.81,568.16 664.77,570.58 667.06,572.97C667.75,571.4 668.56,569.96 669.02,568.42C670.93,561.94 676.24,560.56 681.89,559.76C689.73,558.66 695.67,562.51 701.02,567.52C709.88,575.82 718.66,584.2 727.43,592.59C737.04,601.79 745.99,611.59 753.1,622.88C756.73,628.64 760.19,634.59 762.93,640.81C768.21,652.78 773.22,664.88 777.77,677.14C782.34,689.45 787.3,701.56 794.47,712.56C798.94,719.42 804.42,725.63 809.71,732.48H809.71ZM541.9,695.81C544.83,697.81 547.9,699.55 550.55,701.79C559.14,709.04 567.64,716.38 576.03,723.85C585.34,732.13 594.51,740.59 605.03,747.33C614.29,753.27 623.9,758.33 634.45,762.04C649.34,767.28 664.41,772.28 678.44,779.78C686.56,784.12 694.78,788.26 702.91,792.59C704.58,793.48 706.04,794.76 707.58,795.88C710.3,797.85 713.19,799.63 715.69,801.86C723.02,808.38 727.57,816.99 732.71,825.13C733.68,826.66 734.41,827.14 736.13,826.4C742.28,823.75 748.51,821.3 754.65,818.65C761.34,815.75 768.2,813.13 774.55,809.61C782.39,805.26 789.77,800.11 797.35,795.3C799.5,793.93 801.78,792.72 803.72,791.1C808.3,787.32 812.67,783.3 817.19,779.46C821.78,775.57 824.72,770.67 826.47,765.48C824.57,763.94 822.65,762.82 821.32,761.23C814.4,752.95 807.33,744.78 800.86,736.15C788.51,719.68 779.63,701.39 773.22,681.83C769.99,671.97 766.14,662.31 762.37,652.64C760.66,648.24 758.46,644.04 756.53,639.72C753.47,632.85 749.71,626.4 744.69,620.79C740.86,616.52 736.79,612.48 732.74,608.41C729.65,605.3 726.42,602.34 723.29,599.26C720.9,596.91 718.57,594.5 716.24,592.09C712.36,588.07 708.43,584.08 704.63,579.98C701.45,576.53 698.52,572.84 695.31,569.42C688.03,561.64 675.74,564.34 674.35,575.36C674.3,575.76 673.92,576.16 673.93,576.54C674.02,578.25 673.54,580.52 674.44,581.55C681.24,589.3 688.47,596.69 695.22,604.47C697.14,606.68 701.82,608.34 698.03,613.07C696.18,615.39 695.37,616.79 692.85,615C689.93,612.93 687.38,610.16 685.19,607.3C681.4,602.36 678.23,597 673.87,592.46C669.76,588.2 665.93,583.65 662.18,579.07C658.56,574.63 653.78,571.79 648.94,569.05C647.67,568.33 645.97,567.79 644.58,567.97C638.74,568.74 634.58,573.14 633.54,578.87C632.74,583.31 633.9,586.86 637.25,589.92C640.51,592.9 643.52,596.16 646.61,599.32C652.33,605.15 657.92,611.13 663.81,616.78C666.05,618.93 668.15,620.69 667.8,624.22C667.6,626.18 666.69,627.66 664.73,627.1C663.22,626.67 661.63,625.77 660.57,624.62C657.28,621.07 654.26,617.27 651.08,613.62C646.25,608.1 641.03,602.88 636.58,597.07C630.33,588.92 623.03,581.94 615.13,575.51C608.37,570 601.96,570.43 595.52,576.07C590.41,580.55 590.6,586.14 591.24,591.93C591.47,594.03 591.76,596.49 592.97,598.07C597.37,603.85 602.21,609.32 606.82,614.95C610.63,619.61 614.29,624.38 618.11,629.03C621.3,632.9 624.67,636.63 627.89,640.48C629.61,642.55 632.2,644.23 631.42,647.59C631,649.41 629.48,650.37 628.07,649.42C626.67,648.48 625.3,647.42 624.16,646.18C621.67,643.47 619.29,640.66 616.95,637.82C612.79,632.78 608.66,627.73 604.6,622.62C600.74,617.77 597.04,612.79 593.17,607.94C589.44,603.27 585.65,598.63 581.77,594.08C576.28,587.62 570.58,581.33 565.16,574.82C558.59,566.93 552.28,558.82 545.72,550.93C543.67,548.46 541.16,546.38 538.85,544.12C538.56,544.29 538.26,544.46 537.96,544.64C542.03,549.35 539.73,553.39 536.65,556.96C534.66,559.28 532.08,561.2 529.51,562.9C525.36,565.64 524.61,565.35 521.03,561.87C518.95,559.86 516.66,558.06 514.75,556.42C516.49,559.2 518.33,562.54 520.52,565.62C526.63,574.22 532.92,582.68 539.08,591.25C541.69,594.89 544.01,598.75 546.68,602.34C550.78,607.85 555.13,613.17 559.26,618.66C563.29,624.02 567.2,629.46 571.1,634.91C575.07,640.43 579.09,645.92 582.86,651.58C588.31,659.76 593.56,668.07 598.88,676.35C602.16,681.46 605.52,686.53 608.6,691.76C609.33,693 609.11,694.81 609.32,696.35C607.78,696.49 606.09,697.13 604.73,696.69C599.21,694.9 593.72,692.96 588.36,690.73C582.84,688.43 578.27,684.63 573.65,680.88C567.81,676.14 561.92,671.4 555.67,667.24C549.04,662.84 541.08,662.18 533.43,660.93C528.66,660.16 524.51,662.69 523,666.36C524.91,666.8 527.16,666.83 528.86,667.81C532.65,670 536.43,672.36 539.72,675.22C543.76,678.74 546.07,683.23 544.16,688.89C543.41,691.14 542.69,693.4 541.9,695.81V695.81ZM608.79,555.41C606.34,556.02 605.14,555.31 604.48,552.51C603.56,548.64 602.8,544.74 602.03,540.83C600.44,532.74 598.99,524.61 597.28,516.54C595.54,508.36 593.32,500.29 591.75,492.09C589.83,482.01 588.38,471.85 586.68,461.73C585.57,455.11 584.55,448.48 583.14,441.92C581.44,434.02 579.58,426.15 577.4,418.37C575.59,411.9 574.92,405.22 573.15,398.75C571.29,391.97 569.82,385.07 568.24,378.21C566.4,370.18 564.65,362.12 562.81,354.09C561.74,349.37 560.61,344.67 559.43,339.98C557.51,332.38 555.48,324.8 553.56,317.2C552.01,311.08 550.57,304.93 549.01,298.81C547.7,293.67 547.55,288.17 545.02,283.43C542.94,279.55 540.29,275.94 537.73,272.33C536.61,270.74 535.25,269.55 532.8,270.15C524.91,272.11 516.93,273.74 509.02,275.65C501.99,277.34 495.01,279.29 488,281.05C477.61,283.65 467.21,286.25 456.79,288.75C446.64,291.18 436.45,293.48 426.29,295.86C420.59,297.2 414.92,298.66 409.21,299.92C404.16,301.04 399.11,302.23 393.99,302.89C387.1,303.78 384.28,309.17 383.98,314.02C383.77,317.47 384.48,321.04 385.2,324.47C387.18,334.02 389.37,343.53 391.49,353.05C392.53,357.67 393.57,362.3 394.65,366.91C396.28,373.85 397.98,380.77 399.61,387.71C401.42,395.41 403.06,403.16 405.01,410.83C407.24,419.65 409.86,428.38 412.07,437.21C413.63,443.44 414.78,449.78 416.12,456.06C418.07,465.23 419.93,474.43 422.03,483.57C423.45,489.7 425.35,495.73 426.81,501.86C430.08,515.53 433.19,529.24 436.41,542.93C439.2,554.82 442,566.72 444.91,578.58C446.78,586.22 448.79,593.83 450.87,601.41C451.81,604.81 453.25,605.58 456.67,604.85C462.02,603.71 467.33,602.35 472.71,601.29C482.48,599.36 492.23,597.19 502.09,595.87C511.35,594.63 520.59,593.55 529.53,590.75C529.94,590.62 530.5,589.46 530.34,589.23C528.41,586.44 526.3,583.78 524.34,581C521.47,576.92 518.56,572.86 515.92,568.63C513.88,565.38 512.39,561.78 510.39,558.5C504.72,549.19 506.02,538.49 514.34,531.66C518.65,528.13 523.79,527.27 529.39,529.13C533.94,530.64 536.93,533.97 540.1,537.12C542.95,539.97 545.44,543.19 548.34,545.98C558.32,555.63 567.76,565.75 575.86,577.07C576.24,577.61 577.11,578.19 577.7,578.13C579.54,577.97 581.35,577.37 583.2,577.2C586.23,576.9 589.36,576.17 590.88,573.58C593.61,568.92 597.97,567.67 602.63,566.81C605.76,566.23 608.96,566.04 612.19,565.67C611.14,562.49 609.97,558.95 608.79,555.41H608.79ZM361.12,403.09C361.12,407.87 361.22,413.2 361.1,418.53C360.95,424.8 360.78,431.09 360.33,437.35C359.63,447.05 358.49,456.71 357.91,466.41C357.43,474.37 357.44,482.36 357.32,490.33C357.25,495.45 357.2,500.57 357.4,505.67C357.63,511.66 358.29,517.64 358.5,523.62C358.77,531.2 358.92,538.78 358.86,546.36C358.72,563.77 358.51,581.18 358.16,598.58C357.97,608.2 353.86,616.62 349.31,624.81C347.06,628.87 344.65,632.85 342.12,636.75C336.57,645.3 330.94,653.8 325.27,662.28C323.15,665.44 320.83,668.47 318.62,671.57C313,679.45 307.38,687.35 301.56,695.53C304.6,698.83 307.63,702.59 311.16,705.82C314.85,709.19 318.89,712.22 323.01,715.08C331.53,720.98 339.99,727.03 348.88,732.33C356.52,736.87 364.63,740.65 372.71,744.39C377.52,746.61 382.57,748.54 387.7,749.82C393.74,751.33 399.96,751.01 405.64,749.52C406.52,747.54 407.23,745.71 408.15,744C409.24,741.95 410.62,740.05 411.7,737.99C415.01,731.67 418.05,725.2 421.54,718.98C426.1,710.87 430.92,702.91 435.76,694.96C439.07,689.53 442.4,684.11 446.07,678.93C453.77,668.08 463.92,659.73 474.5,651.87C477.16,649.9 479.77,647.86 482.86,645.5C479.79,645.5 477.31,645.1 475.02,645.59C469.78,646.71 464.8,646.2 459.65,644.88C452.86,643.14 448,639.27 445.12,633.01C442.52,627.34 439.73,621.68 437.91,615.75C435.1,606.53 433.15,597.05 430.66,587.74C428.61,580.1 426.29,572.53 424.1,564.93C423.47,565.8 423.28,566.7 423.08,567.59C422.64,569.6 422.37,571.66 421.71,573.59C421.23,574.99 421.02,577.27 418.79,576.79C416.44,576.28 417.04,574.04 417.26,572.45C417.74,569.1 418.69,565.81 419.11,562.46C419.77,557.24 420.5,552.1 418.88,546.78C416.81,539.94 415.46,532.88 413.87,525.9C412.32,519.13 411.8,512.16 407.46,506.14C405.03,502.76 404.2,498.29 402.3,494.49C398.39,486.64 395.72,478.5 396.67,469.64C397.77,459.27 396.59,449 395.48,438.77C394.77,432.12 392.98,425.58 391.62,419.01C391.43,418.11 391,417.26 390.62,416.42C390.04,415.13 389.1,413.92 388.87,412.58C388.15,408.36 388.26,403.93 387.02,399.89C385.09,393.56 382.35,387.47 379.89,381.31C378.42,377.61 377.23,373.66 373.16,372.05C373.43,376.96 373.69,381.86 373.98,386.75C374.34,392.99 371.58,397.67 366.57,401.06C365.21,401.97 363.43,402.26 361.12,403.09L361.12,403.09ZM542.36,605.9C539.69,602.13 537.41,598.87 535.03,595.67C534.78,595.32 533.92,595.16 533.43,595.28C527.27,596.78 521.18,598.64 514.96,599.81C506.46,601.42 497.85,602.49 489.3,603.87C483.43,604.82 477.54,605.69 471.74,607C466.43,608.21 461.27,610.04 455.98,611.4C454.88,611.68 453.42,611.34 452.36,610.81C448.7,608.98 446.49,605.99 445.57,601.95C444.13,595.62 442.54,589.33 441.04,583.01C439.1,574.83 437.21,566.64 435.26,558.47C431.98,544.74 428.68,531.01 425.36,517.29C422.83,506.86 420.13,496.47 417.77,486C415.55,476.16 413.82,466.2 411.6,456.36C409.37,446.45 406.8,436.61 404.36,426.74C402.45,418.99 400.53,411.25 398.59,403.52C397.31,398.43 395.96,393.36 394.7,388.27C393.59,383.8 392.51,379.31 391.49,374.82C389.77,367.14 388.19,359.43 386.38,351.77C384.14,342.31 381.54,332.93 379.49,323.42C378.54,319.02 378.47,314.41 378.09,309.88C377.64,304.56 380.62,299.56 384.67,298.62C387.42,297.99 390.17,297.34 392.92,296.7C393.35,296.61 393.8,296.57 394.24,296.52C396.88,296.16 399.58,296.05 402.15,295.4C406.54,294.3 410.82,292.74 415.21,291.61C420.48,290.26 425.83,289.28 431.09,287.91C435.36,286.8 439.49,285.22 443.75,284.09C451.3,282.1 458.91,280.28 466.49,278.41C471.72,277.12 476.94,275.83 482.19,274.62C483.71,274.27 485.33,274.35 486.83,273.94C488.47,273.49 489.97,272.51 491.61,272.11C499.53,270.22 507.47,268.43 515.41,266.67C515.96,266.54 516.6,266.86 517.38,267C517.83,266.7 518.53,265.95 519.38,265.73C521.59,265.14 523.86,265.38 526.18,264.44C528.97,263.32 532.28,263.18 535.36,263.21C539.8,263.25 544.33,264.3 546.67,268.4C548.89,272.27 550.36,276.61 551.75,280.88C554.09,288.07 556.07,295.34 556.56,302.99C556.82,306.95 558.06,310.86 558.98,314.76C561.16,324.02 563.46,333.26 565.65,342.53C568.33,353.89 570.92,365.28 573.6,376.64C574.66,381.09 575.78,385.52 577.01,389.92C578.89,396.65 581.03,403.32 582.81,410.08C584.08,414.88 584.9,419.8 586.01,424.66C587.54,431.37 589.2,438.06 590.68,444.78C590.93,445.89 590.53,447.13 590.42,448.39C590.85,449.07 591.65,449.85 591.9,450.77C592.93,454.63 593.94,458.49 594.69,462.41C596.45,471.64 598.1,480.9 599.73,490.16C601.09,497.9 602.35,505.65 603.72,513.78C604.64,510.14 605.44,506.97 606.34,503.43C601.57,495.3 603.42,486.33 605.01,478.33C603.78,475.48 602.65,473.4 602.01,471.17C601.23,468.53 600.6,465.78 600.42,463.05C600.22,459.84 600.68,456.6 600.61,453.38C600.59,452.3 600.13,450.96 599.4,450.19C591.32,441.69 587.36,432.11 591.09,420.33C591.34,419.56 591.32,418.6 591.1,417.81C589.88,413.33 588.37,408.93 587.33,404.42C585.23,395.26 583.45,386.03 581.39,376.87C579.9,370.23 578.26,363.63 576.55,357.04C574.72,349.97 572.72,342.95 570.83,335.9C569.14,329.61 567.45,323.31 565.84,317C564.7,312.54 563.87,308.01 562.61,303.59C560.18,295.04 557.5,286.56 555.03,278.02C554.75,277.04 555.12,275.87 555.2,274.73C554.82,274.56 553.74,274.44 553.54,273.95C552.23,270.78 550.97,267.57 549.98,264.29C548.69,260.03 547.49,255.8 543.77,252.86C542.73,252.04 541.91,250.92 540.9,250.04C537.4,246.99 534.16,243.41 529.14,242.99C526.62,242.78 524.04,242.77 521.53,243.08C517.38,243.59 513.26,244.4 509.14,245.15C502.43,246.36 495.66,247.35 489.03,248.92C477.91,251.56 466.88,254.62 455.8,257.44C442.5,260.83 429.15,264.05 415.89,267.58C409.05,269.4 402.27,271.52 395.59,273.9C390.97,275.55 386.66,278.07 382.06,279.8C379.95,280.6 378.41,281.61 377.37,283.53C373.24,291.16 370.11,299.19 370.87,307.97C371.48,315.1 372.82,322.2 374.31,329.21C375.69,335.75 377.8,342.13 379.41,348.62C382.38,360.58 384.5,372.72 388.71,384.39C391.1,390.99 392.55,397.95 394.11,404.82C396.36,414.75 398.4,424.72 400.36,434.7C401.56,440.81 401.78,447.15 404.9,452.78C405.55,453.95 406.32,455.12 406.66,456.39C408.26,462.37 409.87,468.35 411.22,474.39C412.91,481.91 414.33,489.5 415.91,497.05C417.3,503.72 418.71,510.39 420.2,517.05C420.86,519.95 421.8,522.78 422.49,525.68C423.6,530.39 424.55,535.13 425.66,539.84C427.14,546.08 428.67,552.3 430.26,558.5C432.04,565.41 433.84,572.33 435.78,579.2C437.63,585.76 439.65,592.27 441.64,598.79C443.41,604.59 445.2,610.39 447.04,616.18C447.9,618.9 448.97,621.56 449.81,624.28C450.3,625.89 450.33,627.65 450.92,629.2C451.62,631.01 452.77,632.65 453.6,634.41C455.2,637.82 457.93,639.66 461.6,639.84C468.07,640.13 474.57,640.56 481.03,640.3C487.08,640.05 493.02,638.63 498.97,637.3C506.48,635.63 514.2,634.88 521.75,633.4C531.14,631.55 540.47,629.38 549.8,627.28C552.3,626.72 554.74,625.9 557.66,625.06C553.25,619.65 549.13,614.59 545.3,609.89C541.62,610.72 538.14,611.57 534.63,612.29C525.94,614.09 517.24,615.8 508.55,617.6C507.15,617.89 505.52,618.33 505.49,616.36C505.47,615.43 506.73,614.04 507.73,613.63C509.77,612.79 512.01,612.43 514.19,611.96C523.43,609.96 532.68,607.98 542.36,605.9V605.9ZM620.52,431.35C621.08,426.62 617.92,423.42 614.4,420.57C610.12,417.1 604.83,417.28 599.74,417.24C598.23,417.23 596.16,417.78 595.94,420.15C595.76,422.25 595.64,424.36 595.22,426.41C593.75,433.51 596.42,439.37 600.96,444.38C603,446.64 606.04,448.04 609.41,446.95C617,444.48 620.48,439.18 620.52,431.35ZM605.24,452.85C605.24,454.35 605.23,455.89 605.25,457.42C605.26,458.93 605.23,460.45 605.37,461.95C605.63,464.79 605.61,467.74 606.41,470.42C607.37,473.67 611.62,475.9 615.32,475.79C618.82,475.68 622.22,472.66 623.75,468.43C625.38,463.91 625.24,459.26 624.05,454.81C623.42,452.44 621.66,450.13 619.8,448.48C619.21,447.96 616.65,449.68 614.99,450.37C614.74,450.47 614.5,450.61 614.24,450.67C611.31,451.38 608.39,452.09 605.24,452.85V452.85ZM625.29,477.37C620.64,479.8 616.14,481.58 610.97,479.78C609.2,479.16 608.89,480.37 609.02,481.89C609.14,483.37 609.25,484.88 609.04,486.34C608.45,490.55 608.27,494.69 609.56,498.82C610.75,502.66 615.36,504.3 618.79,502.42C623.24,499.96 624.95,495.87 626.1,491.4C627.3,486.75 628.2,482.03 625.29,477.37V477.37ZM617.82,568.66C617.6,568.79 617.39,568.92 617.18,569.05C619.78,571.48 622.38,573.92 625.11,576.47C625.24,575.94 625.39,575.67 625.35,575.44C624.37,568.72 623.42,561.99 622.35,555.28C621.94,552.67 620.97,550.12 620.8,547.51C620.59,544.5 618.64,541.61 620.11,538.41C620.28,538.03 619.27,536.74 618.55,536.4C616.41,535.38 614.04,534.83 611.96,533.71C610.37,532.86 609.09,531.43 607.14,529.82C607.41,531.46 607.5,532.43 607.75,533.35C609.49,539.8 611.13,546.27 613.09,552.66C614.31,556.65 616.13,560.46 617.47,564.42C617.91,565.72 617.72,567.24 617.82,568.66V568.66ZM521.97,535.43C520.24,536.38 517.89,536.91 516.89,538.36C514.73,541.53 514.44,545.33 516.18,548.87C517.6,551.74 519.37,554.46 521.14,557.15C523.11,560.15 524.91,560.54 528.06,558.88C531.22,557.22 533.51,554.68 534.87,551.43C535.25,550.53 535.25,548.96 534.71,548.24C531.96,544.61 529.06,541.07 526.02,537.68C525.15,536.71 523.62,536.31 521.97,535.43V535.43ZM615.24,509.54C614.05,512.26 612.79,514.91 611.73,517.64C610.17,521.64 609.72,525.49 613.59,528.68C617.5,531.9 622.75,530.51 624.39,525.81C626.65,519.34 626.76,512.77 625.7,505.63C622.97,509.52 619.24,509.88 615.24,509.54H615.24ZM538.25,693.05C538.74,691.83 539.15,691.11 539.31,690.34C539.87,687.61 540.77,684.76 539.23,682.16C536.56,677.66 532.52,674.56 527.89,672.28C526.77,671.73 524.61,671.33 524.11,671.89C523.1,673.03 522.64,674.86 522.5,676.45C522.4,677.59 522.91,679.01 523.62,679.96C527.58,685.23 532.71,689.2 538.25,693.05V693.05ZM308.58,674.29C305.1,673.16 302.06,671.67 298.88,671.26C292.53,670.45 287.52,675.8 289.94,680.73C291.55,684.01 294.25,686.75 296.42,689.66C300.65,684.32 304.44,679.53 308.58,674.29V674.29ZM728.97,828.15C724.81,819.88 718.97,813.45 712.09,807.74C709.99,814.42 710.37,822.09 713.68,824.83C717.97,828.37 723.15,829.52 728.97,828.15V828.15ZM361.41,398.05C364.66,396.52 367.98,395.16 368.67,391.21C369.79,384.84 369.19,378.55 367.32,372.05C362.41,375.31 361.61,380.08 361.44,385.05C361.29,389.23 361.41,393.42 361.41,398.05V398.05ZM828.5,754.37C829.44,747.72 827.87,742.55 824.92,737.7C823.15,734.77 818.47,733.08 815.17,734.05C813.2,734.63 812.86,735.5 814.4,737.04C815.8,738.43 817.14,739.91 818.37,741.46C821.64,745.54 824.83,749.69 828.5,754.37V754.37ZM412.4,746.95C420.3,743.47 423.7,739.11 421.27,733.71C419.98,736.33 418.85,738.69 417.63,741C417.2,741.83 416.46,743.2 415.97,743.16C413.32,742.92 413.47,744.97 412.4,746.95V746.95ZM585.15,589.35C585.38,589.24 585.61,589.13 585.83,589.01V581.78C583.54,581.94 581.54,582.08 578.98,582.25C581.27,584.89 583.21,587.12 585.15,589.35V589.35ZM405.85,485.48C406.21,485.39 406.57,485.31 406.93,485.23C405.67,479.74 404.4,474.26 403.14,468.78C402.78,468.86 402.42,468.94 402.06,469.03C403.32,474.51 404.58,480 405.85,485.48V485.48Z" - android:fillColor="#000000"/> - <path - android:pathData="M541.9,695.81C542.69,693.4 543.41,691.14 544.17,688.89C546.07,683.23 543.76,678.74 539.72,675.22C536.43,672.36 532.65,670 528.86,667.81C527.16,666.83 524.91,666.8 523,666.36C524.51,662.69 528.66,660.16 533.43,660.93C541.08,662.18 549.04,662.84 555.67,667.24C561.92,671.4 567.81,676.14 573.65,680.88C578.27,684.63 582.84,688.43 588.36,690.73C593.72,692.96 599.21,694.9 604.73,696.69C606.09,697.13 607.78,696.49 609.32,696.35C609.11,694.81 609.33,693 608.6,691.76C605.52,686.53 602.16,681.46 598.88,676.35C593.56,668.07 588.31,659.76 582.86,651.58C579.09,645.92 575.07,640.43 571.1,634.91C567.2,629.46 563.29,624.02 559.26,618.66C555.13,613.18 550.78,607.85 546.68,602.34C544.01,598.75 541.69,594.89 539.08,591.25C532.92,582.68 526.63,574.22 520.52,565.62C518.33,562.54 516.49,559.2 514.76,556.42C516.66,558.06 518.95,559.86 521.03,561.87C524.61,565.35 525.36,565.64 529.51,562.9C532.08,561.2 534.66,559.28 536.65,556.96C539.73,553.39 542.03,549.35 537.96,544.64C538.26,544.47 538.56,544.29 538.86,544.12C541.16,546.38 543.67,548.46 545.72,550.93C552.28,558.82 558.59,566.93 565.16,574.82C570.58,581.33 576.28,587.62 581.77,594.08C585.65,598.63 589.44,603.27 593.17,607.94C597.04,612.79 600.74,617.77 604.6,622.62C608.66,627.73 612.8,632.78 616.95,637.82C619.29,640.66 621.67,643.48 624.16,646.18C625.3,647.42 626.67,648.48 628.07,649.42C629.48,650.37 631,649.41 631.42,647.59C632.2,644.23 629.61,642.55 627.89,640.48C624.67,636.63 621.3,632.9 618.11,629.03C614.29,624.38 610.63,619.61 606.82,614.95C602.21,609.32 597.37,603.85 592.97,598.07C591.76,596.49 591.47,594.03 591.24,591.93C590.6,586.14 590.41,580.55 595.52,576.07C601.96,570.43 608.37,570.01 615.13,575.51C623.03,581.94 630.34,588.92 636.58,597.07C641.03,602.88 646.25,608.1 651.08,613.62C654.26,617.27 657.28,621.07 660.57,624.62C661.63,625.77 663.22,626.67 664.73,627.1C666.69,627.66 667.6,626.18 667.8,624.22C668.15,620.69 666.05,618.93 663.81,616.78C657.92,611.13 652.33,605.15 646.61,599.32C643.52,596.16 640.51,592.9 637.25,589.92C633.9,586.86 632.74,583.31 633.54,578.87C634.58,573.14 638.74,568.74 644.58,567.97C645.97,567.79 647.67,568.33 648.94,569.05C653.78,571.79 658.56,574.63 662.19,579.07C665.93,583.65 669.77,588.2 673.87,592.46C678.23,597 681.4,602.36 685.19,607.3C687.38,610.16 689.93,612.93 692.85,615C695.37,616.79 696.18,615.39 698.03,613.07C701.82,608.34 697.14,606.68 695.22,604.47C688.47,596.69 681.24,589.3 674.44,581.55C673.54,580.52 674.02,578.25 673.94,576.54C673.92,576.16 674.3,575.77 674.35,575.36C675.74,564.34 688.03,561.64 695.32,569.42C698.52,572.84 701.45,576.53 704.63,579.98C708.43,584.08 712.36,588.07 716.24,592.09C718.57,594.5 720.9,596.91 723.29,599.26C726.42,602.34 729.65,605.3 732.74,608.41C736.79,612.48 740.86,616.52 744.69,620.79C749.71,626.4 753.47,632.85 756.53,639.72C758.46,644.04 760.66,648.24 762.37,652.64C766.14,662.31 769.99,671.97 773.22,681.83C779.64,701.4 788.52,719.68 800.86,736.15C807.33,744.78 814.4,752.95 821.32,761.23C822.65,762.82 824.57,763.94 826.47,765.48C824.72,770.67 821.78,775.57 817.19,779.46C812.67,783.3 808.3,787.32 803.72,791.1C801.78,792.72 799.5,793.93 797.35,795.3C789.78,800.11 782.39,805.26 774.55,809.61C768.2,813.13 761.34,815.75 754.65,818.65C748.51,821.3 742.28,823.75 736.13,826.4C734.41,827.14 733.68,826.66 732.71,825.13C727.57,816.99 723.02,808.38 715.69,801.86C713.2,799.63 710.3,797.85 707.58,795.88C706.04,794.76 704.58,793.48 702.91,792.59C694.78,788.27 686.56,784.12 678.44,779.78C664.41,772.28 649.34,767.28 634.45,762.04C623.9,758.33 614.29,753.27 605.03,747.33C594.51,740.59 585.34,732.13 576.03,723.85C567.64,716.38 559.14,709.04 550.55,701.79C547.9,699.55 544.83,697.81 541.9,695.81V695.81Z" - android:fillColor="#86573C"/> - <path - android:pathData="M608.8,555.41C609.97,558.95 611.14,562.49 612.19,565.67C608.96,566.04 605.76,566.23 602.63,566.81C597.97,567.67 593.61,568.92 590.88,573.58C589.36,576.17 586.23,576.9 583.2,577.2C581.35,577.37 579.54,577.97 577.7,578.13C577.11,578.19 576.24,577.61 575.86,577.07C567.76,565.75 558.32,555.63 548.34,545.98C545.44,543.19 542.95,539.97 540.1,537.12C536.93,533.97 533.94,530.64 529.39,529.13C523.79,527.27 518.65,528.13 514.34,531.66C506.02,538.49 504.72,549.19 510.39,558.5C512.39,561.78 513.88,565.38 515.92,568.63C518.56,572.86 521.47,576.92 524.34,581C526.3,583.78 528.41,586.44 530.34,589.23C530.5,589.46 529.94,590.62 529.53,590.75C520.59,593.55 511.35,594.63 502.09,595.87C492.23,597.19 482.48,599.36 472.71,601.29C467.33,602.35 462.02,603.71 456.67,604.85C453.25,605.58 451.81,604.81 450.88,601.41C448.79,593.83 446.78,586.22 444.91,578.58C442,566.72 439.2,554.82 436.41,542.93C433.19,529.24 430.08,515.53 426.81,501.86C425.35,495.73 423.45,489.7 422.03,483.57C419.93,474.43 418.07,465.23 416.12,456.06C414.78,449.78 413.63,443.44 412.07,437.21C409.86,428.38 407.24,419.65 405.01,410.83C403.06,403.16 401.42,395.41 399.61,387.71C397.98,380.77 396.28,373.85 394.65,366.91C393.57,362.3 392.53,357.67 391.49,353.05C389.37,343.53 387.18,334.02 385.2,324.47C384.48,321.04 383.77,317.47 383.98,314.02C384.28,309.17 387.1,303.78 393.99,302.89C399.11,302.23 404.16,301.04 409.21,299.92C414.92,298.66 420.59,297.2 426.29,295.86C436.45,293.48 446.64,291.18 456.79,288.75C467.21,286.25 477.61,283.65 488,281.05C495.02,279.29 501.99,277.34 509.02,275.65C516.93,273.74 524.91,272.11 532.8,270.15C535.26,269.55 536.61,270.74 537.73,272.33C540.29,275.94 542.94,279.55 545.02,283.43C547.55,288.17 547.7,293.67 549.01,298.81C550.57,304.93 552.01,311.08 553.56,317.2C555.48,324.8 557.51,332.38 559.43,339.98C560.61,344.67 561.74,349.37 562.81,354.09C564.65,362.12 566.4,370.18 568.24,378.21C569.82,385.07 571.29,391.97 573.15,398.75C574.92,405.22 575.59,411.9 577.4,418.37C579.58,426.15 581.44,434.02 583.14,441.92C584.55,448.48 585.57,455.11 586.68,461.73C588.38,471.85 589.83,482.01 591.75,492.09C593.32,500.29 595.54,508.36 597.28,516.54C598.99,524.61 600.44,532.74 602.04,540.83C602.8,544.74 603.56,548.64 604.48,552.51C605.14,555.31 606.34,556.02 608.8,555.41H608.8ZM446.01,350.86C445.05,349.38 444.14,347.86 443.11,346.42C440.92,343.38 437.09,343.2 435.4,346.19C432.63,351.09 430.98,356.37 430.16,361.98C429.08,369.26 430.56,376.35 431.46,383.43C432.8,393.96 438.38,402.31 446.22,409.41C451.45,414.14 457.57,416.6 464.13,418.63C470.64,420.65 477.04,421.21 483.95,420.85C493.17,420.38 501.61,418.08 509.7,414.09C512.43,412.75 514.65,410.4 517.19,408.64C522.43,405.02 526.4,400.3 528.83,394.48C530.71,389.96 531.94,385.17 533.63,380.56C537.09,371.11 536.33,361.8 532.79,352.62C530.07,345.57 525.51,339.69 520.55,334.05C517.61,330.7 514.34,327.88 510.37,325.97C509.15,325.38 507.5,325.68 506.04,325.57C506.36,326.93 506.69,328.3 506.99,329.67C507.02,329.79 506.86,329.95 506.65,330.34C502.36,327.33 497.95,324.53 493.89,321.3C490.55,318.65 487.64,315.45 484.5,312.55C482.19,310.41 480.27,310.5 478.56,313.1C476.3,316.55 473.88,319.7 472.96,324.14C471.64,330.49 470.7,336.63 471.94,342.55C468.33,345.72 464.88,348.74 461.27,351.91C461.01,351.52 460.4,350.93 460.18,350.22C459.38,347.57 458.78,344.85 457.95,342.21C457.68,341.35 457.09,340.29 456.37,339.96C455.78,339.7 454.46,340.15 453.98,340.72C451.29,343.96 448.75,347.33 446.01,350.86L446.01,350.86ZM574.69,476.89C574.97,476.79 575.26,476.7 575.55,476.6C574.78,474.92 574.47,472.52 573.17,471.72C570.07,469.81 566.47,470.79 563.11,471.57C555.41,473.36 547.77,475.4 540.05,477.05C529.38,479.33 518.62,481.21 507.96,483.51C499.15,485.41 490.44,487.73 481.67,489.76C473.17,491.72 464.57,493.29 456.17,495.58C452.93,496.45 448.13,495.51 447.56,501.45C447.35,503.64 446.32,505.77 447.07,508.09C447.69,510.03 448.31,511.98 448.83,513.95C450.32,519.57 451.64,525.24 453.28,530.81C453.77,532.49 454.78,534.78 456.11,535.28C458.59,536.2 461.63,536.68 464.19,536.16C471.79,534.61 479.27,532.48 486.8,530.58C496.88,528.03 506.93,525.32 517.06,522.96C524.16,521.31 531.36,520.01 538.54,518.74C550.34,516.67 562.19,514.88 573.96,512.69C576.66,512.18 579.85,511.24 580.24,507.66C580.54,504.93 580.82,502.05 580.3,499.4C579.22,493.78 577.63,488.26 576.23,482.71C575.74,480.76 575.2,478.83 574.69,476.89V476.89ZM451.16,487.84C453.59,487.34 457.77,486.69 461.82,485.6C470.79,483.17 479.64,480.27 488.66,478.04C498.87,475.51 509.21,473.51 519.49,471.27C526.56,469.72 533.59,467.92 540.7,466.62C548.93,465.13 557,463.26 564.41,459.28C566.12,458.36 568.05,457.04 568.82,455.41C569.63,453.67 569.51,451.29 569.22,449.28C567.86,440 566.32,430.74 564.81,421.48C564.4,418.97 560.89,416.01 558.81,416.43C556.67,416.86 554.58,417.48 552.48,418.05C544.8,420.11 537.13,422.2 529.44,424.24C524,425.68 518.54,427.06 513.09,428.46C509.72,429.33 506.35,430.22 502.96,431.08C497.93,432.35 492.87,433.53 487.85,434.86C481.93,436.42 476.06,438.17 470.14,439.69C460.58,442.14 450.94,444.24 441.45,446.9C434.74,448.79 433.21,452.55 434.65,458.87C436.11,465.22 437.77,471.52 439.22,477.88C440.61,483.95 444.48,487.83 451.16,487.84V487.84Z" - android:fillColor="#C8ABF2"/> - <path - android:pathData="M361.12,403.09C363.43,402.26 365.21,401.97 366.57,401.06C371.58,397.67 374.34,392.99 373.98,386.75C373.69,381.86 373.43,376.96 373.16,372.05C377.23,373.66 378.42,377.61 379.89,381.31C382.35,387.47 385.09,393.56 387.02,399.89C388.26,403.93 388.15,408.36 388.87,412.58C389.1,413.92 390.05,415.13 390.62,416.42C391,417.26 391.43,418.11 391.62,419.01C392.98,425.58 394.77,432.12 395.49,438.77C396.59,449 397.77,459.27 396.67,469.64C395.72,478.5 398.39,486.64 402.3,494.49C404.2,498.29 405.03,502.76 407.46,506.14C411.8,512.16 412.32,519.13 413.87,525.9C415.46,532.88 416.81,539.94 418.88,546.78C420.5,552.1 419.77,557.24 419.11,562.46C418.69,565.81 417.74,569.1 417.26,572.45C417.04,574.04 416.44,576.28 418.79,576.79C421.02,577.27 421.23,574.99 421.71,573.6C422.38,571.66 422.64,569.6 423.08,567.59C423.28,566.7 423.47,565.8 424.1,564.93C426.29,572.53 428.61,580.1 430.66,587.74C433.15,597.05 435.1,606.53 437.91,615.75C439.73,621.68 442.52,627.34 445.13,633.01C448,639.27 452.86,643.14 459.66,644.88C464.8,646.2 469.78,646.71 475.02,645.59C477.31,645.1 479.79,645.5 482.86,645.5C479.77,647.86 477.16,649.9 474.5,651.87C463.92,659.73 453.77,668.08 446.07,678.93C442.4,684.11 439.07,689.53 435.77,694.96C430.92,702.91 426.1,710.87 421.54,718.98C418.05,725.2 415.01,731.67 411.7,737.99C410.62,740.05 409.24,741.95 408.15,744C407.23,745.71 406.53,747.54 405.64,749.52C399.96,751.01 393.74,751.33 387.7,749.82C382.57,748.54 377.52,746.61 372.71,744.39C364.63,740.65 356.52,736.88 348.88,732.33C339.99,727.03 331.53,720.98 323.01,715.08C318.89,712.22 314.85,709.19 311.16,705.82C307.63,702.59 304.6,698.83 301.56,695.53C307.38,687.35 313,679.45 318.62,671.57C320.83,668.47 323.15,665.44 325.27,662.28C330.94,653.8 336.57,645.3 342.12,636.75C344.65,632.85 347.06,628.87 349.32,624.81C353.86,616.62 357.97,608.2 358.16,598.58C358.51,581.18 358.72,563.77 358.86,546.36C358.92,538.78 358.77,531.2 358.5,523.62C358.29,517.64 357.63,511.66 357.4,505.67C357.2,500.57 357.25,495.45 357.32,490.33C357.44,482.36 357.43,474.37 357.91,466.41C358.49,456.71 359.63,447.05 360.33,437.36C360.78,431.09 360.95,424.8 361.1,418.53C361.22,413.2 361.12,407.87 361.12,403.09L361.12,403.09Z" - android:fillColor="#86573C"/> - <path - android:pathData="M542.36,605.9C532.68,607.98 523.43,609.96 514.19,611.96C512.01,612.43 509.77,612.79 507.73,613.63C506.73,614.04 505.48,615.43 505.49,616.36C505.52,618.33 507.15,617.89 508.56,617.6C517.24,615.8 525.94,614.09 534.63,612.3C538.14,611.57 541.62,610.73 545.3,609.89C549.13,614.59 553.25,619.65 557.66,625.06C554.74,625.9 552.3,626.72 549.8,627.28C540.47,629.38 531.14,631.55 521.76,633.4C514.2,634.88 506.48,635.63 498.97,637.3C493.02,638.63 487.08,640.05 481.03,640.3C474.57,640.56 468.07,640.13 461.6,639.84C457.93,639.66 455.2,637.82 453.6,634.41C452.77,632.65 451.62,631.02 450.92,629.2C450.33,627.65 450.3,625.89 449.81,624.28C448.97,621.56 447.9,618.9 447.04,616.18C445.2,610.39 443.41,604.59 441.64,598.79C439.65,592.27 437.63,585.76 435.78,579.2C433.84,572.33 432.04,565.41 430.26,558.5C428.67,552.3 427.14,546.08 425.66,539.84C424.55,535.13 423.6,530.39 422.49,525.68C421.8,522.78 420.86,519.95 420.21,517.05C418.71,510.4 417.3,503.73 415.91,497.05C414.33,489.5 412.91,481.91 411.22,474.39C409.87,468.35 408.27,462.37 406.66,456.39C406.32,455.12 405.55,453.95 404.9,452.78C401.78,447.15 401.56,440.81 400.36,434.7C398.4,424.72 396.36,414.75 394.11,404.83C392.55,397.95 391.1,390.99 388.71,384.39C384.5,372.72 382.38,360.58 379.41,348.62C377.8,342.13 375.69,335.75 374.31,329.21C372.82,322.2 371.48,315.1 370.87,307.97C370.12,299.19 373.24,291.16 377.37,283.53C378.41,281.61 379.96,280.6 382.06,279.8C386.66,278.07 390.97,275.55 395.6,273.9C402.27,271.52 409.05,269.4 415.89,267.58C429.16,264.05 442.5,260.83 455.8,257.44C466.88,254.62 477.91,251.56 489.04,248.92C495.66,247.35 502.43,246.36 509.14,245.15C513.26,244.41 517.38,243.59 521.54,243.08C524.04,242.77 526.62,242.78 529.14,242.99C534.16,243.41 537.4,246.99 540.91,250.04C541.92,250.92 542.73,252.04 543.77,252.86C547.49,255.8 548.7,260.03 549.98,264.29C550.97,267.57 552.23,270.78 553.54,273.95C553.74,274.44 554.82,274.56 555.2,274.73C555.12,275.87 554.75,277.04 555.03,278.02C557.51,286.56 560.18,295.04 562.61,303.59C563.87,308.01 564.7,312.55 565.84,317C567.45,323.31 569.14,329.61 570.83,335.9C572.72,342.95 574.72,349.97 576.56,357.04C578.26,363.63 579.91,370.23 581.39,376.87C583.45,386.03 585.23,395.26 587.33,404.42C588.37,408.93 589.89,413.34 591.1,417.81C591.32,418.6 591.34,419.56 591.09,420.33C587.36,432.11 591.32,441.69 599.4,450.19C600.13,450.96 600.59,452.3 600.61,453.38C600.68,456.6 600.22,459.84 600.42,463.05C600.6,465.78 601.24,468.53 602.01,471.18C602.65,473.4 603.78,475.48 605.01,478.33C603.42,486.33 601.58,495.3 606.34,503.43C605.44,506.97 604.64,510.14 603.72,513.78C602.35,505.65 601.09,497.9 599.73,490.16C598.1,480.9 596.45,471.64 594.69,462.41C593.94,458.49 592.93,454.63 591.9,450.77C591.65,449.85 590.85,449.07 590.42,448.39C590.53,447.13 590.93,445.89 590.69,444.78C589.2,438.06 587.54,431.37 586.01,424.66C584.9,419.8 584.08,414.88 582.81,410.08C581.03,403.32 578.89,396.65 577.01,389.92C575.78,385.52 574.66,381.09 573.6,376.64C570.92,365.28 568.33,353.89 565.65,342.53C563.46,333.26 561.16,324.02 558.98,314.76C558.06,310.86 556.82,306.95 556.57,302.99C556.07,295.34 554.09,288.07 551.75,280.88C550.36,276.61 548.89,272.27 546.67,268.4C544.33,264.3 539.8,263.25 535.36,263.21C532.28,263.18 528.97,263.32 526.18,264.44C523.87,265.38 521.6,265.14 519.38,265.73C518.54,265.95 517.83,266.7 517.38,267C516.6,266.86 515.96,266.54 515.41,266.67C507.47,268.44 499.53,270.22 491.61,272.11C489.97,272.51 488.47,273.49 486.83,273.94C485.33,274.35 483.71,274.27 482.19,274.62C476.94,275.83 471.72,277.12 466.49,278.41C458.91,280.28 451.3,282.1 443.75,284.09C439.49,285.22 435.36,286.8 431.1,287.91C425.84,289.28 420.48,290.26 415.21,291.61C410.82,292.74 406.55,294.3 402.15,295.4C399.58,296.05 396.88,296.16 394.24,296.52C393.8,296.58 393.35,296.61 392.92,296.7C390.17,297.34 387.42,297.99 384.67,298.62C380.62,299.56 377.64,304.56 378.09,309.88C378.47,314.41 378.54,319.02 379.49,323.42C381.54,332.93 384.14,342.31 386.38,351.77C388.19,359.43 389.77,367.14 391.5,374.82C392.51,379.31 393.59,383.8 394.7,388.27C395.96,393.36 397.31,398.43 398.59,403.52C400.53,411.25 402.45,418.99 404.36,426.74C406.8,436.61 409.37,446.45 411.6,456.36C413.82,466.2 415.55,476.16 417.77,486C420.13,496.47 422.84,506.86 425.36,517.29C428.68,531.01 431.98,544.74 435.26,558.47C437.21,566.64 439.1,574.83 441.04,583.01C442.54,589.33 444.13,595.62 445.57,601.95C446.49,605.99 448.71,608.98 452.36,610.81C453.42,611.34 454.89,611.68 455.98,611.4C461.27,610.04 466.43,608.21 471.75,607C477.54,605.69 483.43,604.82 489.3,603.87C497.85,602.49 506.46,601.42 514.96,599.81C521.18,598.64 527.27,596.78 533.43,595.28C533.92,595.16 534.78,595.32 535.03,595.67C537.41,598.87 539.69,602.13 542.36,605.9V605.9ZM465.97,267.99C465.02,264.63 463.28,264.42 460.99,265.36C459.58,265.94 458.11,266.37 456.64,266.82C452.19,268.18 447.71,269.49 443.26,270.89C441.59,271.42 440.53,272.7 441.25,274.4C441.91,275.97 443.38,275.76 444.91,275.25C450.59,273.36 456.34,271.66 462.03,269.81C463.41,269.36 464.69,268.6 465.97,267.99H465.97ZM474.27,265.41C474.36,262.36 472.67,261.83 471.26,262.01C470.3,262.13 469.48,263.51 468.6,264.33C469.68,265.23 470.64,266.53 471.87,266.87C472.6,267.08 473.75,265.75 474.27,265.41V265.41Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M620.52,431.35C620.48,439.18 617.01,444.48 609.41,446.95C606.04,448.04 603,446.64 600.96,444.38C596.42,439.37 593.75,433.51 595.22,426.41C595.64,424.36 595.76,422.25 595.95,420.15C596.16,417.78 598.23,417.23 599.74,417.24C604.83,417.28 610.12,417.1 614.4,420.57C617.92,423.42 621.08,426.62 620.52,431.35Z" - android:fillColor="#86573C"/> - <path - android:pathData="M605.24,452.85C608.39,452.09 611.31,451.39 614.24,450.67C614.5,450.61 614.74,450.47 614.99,450.37C616.65,449.68 619.21,447.96 619.8,448.48C621.66,450.13 623.42,452.44 624.05,454.81C625.24,459.26 625.39,463.91 623.75,468.43C622.22,472.66 618.82,475.68 615.32,475.79C611.62,475.9 607.37,473.67 606.41,470.43C605.61,467.74 605.63,464.79 605.37,461.95C605.23,460.45 605.27,458.93 605.25,457.42C605.23,455.89 605.24,454.35 605.24,452.85V452.85Z" - android:fillColor="#86573C"/> - <path - android:pathData="M625.29,477.37C628.2,482.03 627.3,486.75 626.1,491.4C624.95,495.87 623.24,499.96 618.79,502.42C615.36,504.31 610.75,502.66 609.56,498.82C608.28,494.69 608.45,490.55 609.04,486.34C609.25,484.89 609.14,483.37 609.02,481.89C608.89,480.37 609.2,479.16 610.97,479.78C616.14,481.58 620.64,479.8 625.29,477.37V477.37Z" - android:fillColor="#86573C"/> - <path - android:pathData="M617.82,568.66C617.72,567.24 617.91,565.72 617.47,564.42C616.13,560.46 614.31,556.65 613.09,552.66C611.13,546.27 609.49,539.8 607.75,533.35C607.5,532.43 607.41,531.47 607.14,529.83C609.09,531.43 610.37,532.86 611.96,533.71C614.04,534.83 616.41,535.38 618.55,536.4C619.27,536.74 620.28,538.03 620.11,538.41C618.64,541.61 620.59,544.5 620.8,547.51C620.97,550.12 621.94,552.67 622.35,555.28C623.42,561.99 624.37,568.72 625.35,575.44C625.39,575.67 625.24,575.94 625.11,576.47C622.38,573.92 619.78,571.48 617.18,569.05C617.39,568.92 617.6,568.79 617.82,568.66V568.66Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M521.97,535.43C523.62,536.31 525.15,536.71 526.02,537.68C529.06,541.07 531.96,544.61 534.71,548.24C535.25,548.96 535.25,550.53 534.87,551.43C533.51,554.68 531.22,557.22 528.07,558.88C524.91,560.54 523.11,560.15 521.14,557.15C519.37,554.46 517.6,551.74 516.18,548.87C514.44,545.33 514.73,541.53 516.89,538.36C517.89,536.91 520.24,536.38 521.97,535.43V535.43Z" - android:fillColor="#BB8160"/> - <path - android:pathData="M615.24,509.54C619.25,509.88 622.97,509.52 625.7,505.63C626.76,512.77 626.65,519.34 624.39,525.81C622.75,530.51 617.51,531.9 613.59,528.68C609.72,525.49 610.17,521.64 611.73,517.64C612.79,514.91 614.05,512.26 615.24,509.54V509.54Z" - android:fillColor="#86573C"/> - <path - android:pathData="M538.25,693.05C532.71,689.2 527.58,685.23 523.62,679.96C522.91,679.01 522.4,677.59 522.5,676.45C522.64,674.86 523.1,673.03 524.11,671.89C524.61,671.33 526.77,671.73 527.89,672.28C532.52,674.56 536.56,677.66 539.23,682.16C540.77,684.76 539.87,687.61 539.31,690.34C539.15,691.11 538.74,691.83 538.25,693.05V693.05Z" - android:fillColor="#BB8160"/> - <path - android:pathData="M361.41,398.05C361.41,393.42 361.29,389.23 361.44,385.05C361.61,380.08 362.41,375.31 367.33,372.05C369.19,378.55 369.79,384.84 368.67,391.21C367.98,395.16 364.66,396.52 361.41,398.05V398.05Z" - android:fillColor="#BB8160"/> - <path - android:pathData="M585.15,589.35C583.21,587.12 581.27,584.89 578.98,582.25C581.54,582.08 583.54,581.94 585.83,581.78V589.01C585.61,589.13 585.38,589.24 585.15,589.35V589.35Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M405.85,485.48C404.58,480 403.32,474.51 402.06,469.03C402.42,468.95 402.78,468.86 403.14,468.78C404.4,474.26 405.67,479.74 406.93,485.23C406.57,485.31 406.21,485.39 405.85,485.48V485.48Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M463.57,177.08C447.18,172.08 431.48,174.75 415.41,178.93C415.86,176.4 415.41,174.39 416.34,172.03C417.65,168.71 417.66,164.87 418.18,161.25C418.6,158.32 419.18,155.39 419.26,152.45C419.39,147.72 422.18,144.18 424.2,140.31C426.39,136.12 429.64,132.75 433.59,130.17C434.46,129.6 435.87,129.63 437.01,129.71C440.08,129.94 443.21,130.06 446.21,130.73C451.31,131.87 455.34,134.63 458.04,139.32C462.54,147.13 463.56,155.64 463.57,164.4C463.57,168.49 463.57,172.57 463.57,177.08V177.08Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M408.53,194.2C408.53,194.11 408.35,193.53 408.55,193.13C409.61,191.07 410.65,188.99 411.91,187.06C414.03,183.81 417.82,183.6 420.99,183.2C427.75,182.35 434.65,181.65 441.4,182.12C448.92,182.65 456.49,183.94 463.52,187.05C464.21,187.35 464.67,188.28 465.11,189C466.07,190.59 466.94,192.22 467.96,194.03C448.2,188.5 428.51,192.57 408.53,194.2L408.53,194.2Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M451.63,195.95C459.69,196.26 467,198.55 474.87,201.22C468.91,206.51 462.46,209.25 454.55,210.4C456.31,204.82 454.91,200.26 451.63,195.95V195.95Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M425.22,197.07C424.03,201.02 422.93,204.67 421.75,208.59C418.69,208.78 415.22,209.17 411.75,209.16C409.19,209.15 405.21,205.57 404.72,203.07C404.61,202.46 405.15,201.27 405.68,201.06C411.9,198.49 418.47,197.67 425.22,197.07L425.22,197.07Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M225.31,335.88C228.4,333.97 231.28,332.18 234.17,330.41C234.38,330.28 234.7,330.31 234.95,330.22C239.03,328.81 243.06,327.21 247.21,326.04C251.99,324.68 257.01,324.08 261.69,322.49C270.46,319.51 279.45,320.62 288.37,320.45C291.39,320.4 294.42,320.76 297.44,321.02C299.73,321.21 301.26,323.58 301.42,326.62C301.77,333.23 301.67,339.92 302.78,346.41C304.36,355.62 303.94,364.78 303.82,373.99C303.75,379.45 302.83,384.81 300.74,389.75C298.8,394.34 296.23,398.76 293.33,402.82C288.64,409.36 283.47,415.56 278.45,421.86C276.92,423.79 275.16,425.52 273.63,427.44C272.68,428.62 272.19,428.48 271.13,427.46C268.63,425.08 265.83,423.01 263.31,420.65C261.93,419.37 260.92,417.71 259.64,416.33C258.14,414.73 256.46,413.3 254.95,411.7C252.8,409.4 250.71,407.04 248.63,404.67C247.79,403.71 247.05,402.68 246.27,401.66C243.42,397.92 240.45,394.27 237.74,390.42C234.43,385.7 231.87,380.63 231.14,374.76C230.91,372.83 229.79,370.98 229.74,369.08C229.64,365.63 228.55,362.36 228.41,358.93C228.26,355.36 227.83,351.79 227.34,348.24C226.78,344.17 226.02,340.13 225.31,335.88V335.88ZM264.75,376.59C262.79,373.7 261.2,370.96 259.2,368.58C257.87,366.99 256,364.96 254.27,364.86C252.71,364.78 250.84,366.86 249.4,368.29C247.05,370.63 248.33,373.46 249.03,375.99C249.67,378.28 251.02,380.18 252.84,381.93C254.6,383.62 255.51,386.17 256.89,388.28C258.69,391.05 260.77,393.65 262.38,396.52C263.94,399.29 268.44,400.58 269.87,398.17C272.26,394.17 274.52,390.05 276.29,385.75C277.83,382.01 278.56,377.94 279.73,374.05C281.08,369.54 282.36,365.01 283.95,360.59C285.63,355.95 287.82,351.5 289.4,346.84C289.99,345.1 289.29,342.97 289.55,341.07C290.09,337.08 288.33,335.05 284.26,335.37C282.47,335.51 280.93,335.77 280.23,338.02C279.17,341.45 277.64,344.74 276.29,348.08C274.55,352.35 272.72,356.59 271.07,360.91C269.96,363.82 269.22,366.87 268.1,369.77C267.3,371.86 266.14,373.8 264.75,376.59H264.75Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M611.23,155.43C612.58,156.85 613.92,157.88 614.79,159.22C618.85,165.48 622.99,171.7 626.68,178.17C629.39,182.93 631.51,188.03 633.7,193.06C634.07,193.9 633.77,195.33 633.27,196.19C630.13,201.52 625.33,205.08 620.18,208.32C612.94,212.89 605.86,217.71 598.61,222.27C596.16,223.81 593.52,225.3 590.77,225.98C589.41,226.32 587.09,225.18 586.06,223.98C583.31,220.78 580.93,217.26 578.58,213.74C573.64,206.34 568.96,198.76 563.82,191.49C562.69,189.89 562.94,189.05 563.93,188.25C567.07,185.7 570.35,183.31 573.62,180.92C577.85,177.84 582.12,174.81 586.39,171.78C588.56,170.24 590.79,168.8 592.96,167.25C596.52,164.71 599.98,162.02 603.61,159.6C605.9,158.08 608.43,156.94 611.23,155.43L611.23,155.43ZM590.73,177.13C587.1,178.79 586.38,180.25 587.89,183.3C589.29,186.14 591.11,188.77 592.6,191.57C593.2,192.68 594.03,194.21 593.68,195.17C592.8,197.64 593.54,199.82 594.54,201.78C596.13,204.88 598.57,207.29 602.43,206.99C605.63,206.73 607.82,204.76 609.11,201.91C611.1,197.5 610.57,190.06 603.62,189.55C600.56,189.33 598.54,188.02 596.9,185.45C595.04,182.52 592.77,179.85 590.73,177.13H590.73Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M560.97,184.62C560.01,182.3 559.06,179.98 558.07,177.67C556.72,174.53 555.03,171.5 554.01,168.26C551.75,161.08 549.84,153.65 551.46,146.18C553.5,136.73 558.87,130.61 570.05,129.41C573.48,129.04 576.89,128.45 580.27,129.65C584.99,131.34 589.29,133.74 593.05,137.07C595.72,139.43 598.49,141.71 600.92,144.31C602.79,146.3 604.2,148.73 605.84,150.95C606.03,151.23 606.34,151.41 606.62,152.33C605.93,152.27 604.85,152.46 604.61,152.1C602.28,148.6 598.79,146.61 595.33,144.51C591.65,142.28 588.2,139.66 584.43,137.62C578.06,134.18 571.28,132.95 564.26,135.5C561.92,136.34 560.32,137.98 558.54,139.98C554.64,144.37 554.58,149.43 554.67,154.24C554.82,162.26 557.13,169.99 560.72,177.26C561.47,178.77 562.16,180.37 562.51,182.01C562.68,182.79 561.98,183.76 561.67,184.64C561.44,184.64 561.2,184.63 560.97,184.62Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M700.23,428.3C704.02,428.81 707.71,429.59 711.42,429.72C715.9,429.88 720.4,429.46 724.88,429.36C727.29,429.3 729.77,429.74 732.09,429.31C733.71,429 735.14,427.62 736.61,426.65C738.15,425.65 739.64,424.57 741.14,423.51C741.99,422.92 742.84,422.33 743.68,421.71C745.26,420.55 746.77,419.27 748.42,418.22C751.15,416.48 753.97,414.91 756.73,413.23C757.53,412.75 758.24,412.14 759.22,411.41C760.19,413.89 761.63,416.19 761.24,419.17C760.8,422.49 760.01,425.93 760.03,429.13C760.07,434.55 758.83,439.75 758.53,445.07C758.34,448.46 757.58,451.97 758.22,455.2C758.74,457.86 757.05,459.85 757.47,462.42C757.86,464.78 756.82,467.34 756.61,469.83C756.28,473.68 756.11,477.55 755.89,481.42C755.79,483.12 755.94,484.86 755.63,486.51C755.44,487.49 754.74,488.81 753.96,489.1C753.12,489.4 751.57,489.01 750.9,488.35C747.81,485.27 744.55,482.56 740.56,480.63C738.17,479.48 736.2,477.49 733.95,476.01C730.86,473.97 727.77,471.91 724.52,470.15C720.25,467.83 715.43,468.27 710.79,468.01C708.24,467.86 705.67,467.98 703.11,467.9C701.56,467.85 699.53,464.49 699.65,462.17C699.94,455.99 700.4,449.81 700.55,443.62C700.65,439.42 700.35,435.21 700.24,431C700.22,430.17 700.23,429.34 700.23,428.3V428.3Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M639.79,344.35C638.22,341.43 636.64,338.94 635.5,336.27C633.25,331.03 631.2,325.71 629.15,320.39C626.7,314.04 624.37,307.65 621.93,301.3C620.67,298 619.38,294.71 617.96,291.48C616.89,289.04 615.6,286.7 614.55,284.6C616.93,280.55 620.86,281.88 624.03,281.44C628.53,280.83 633.16,281 637.72,281.05C643.22,281.12 648.73,281.27 654.22,281.65C658.68,281.97 663.11,282.86 667.58,283.17C673.03,283.54 678.49,283.56 683.94,283.73C686.46,283.8 688.98,283.75 691.48,283.96C693.6,284.14 694.01,285.61 693.08,287.66C690.95,292.35 687.23,295.75 683.93,299.52C681.81,301.93 680.13,304.72 678.21,307.31C673.51,313.65 668.33,319.49 661.9,324.24C659.01,326.37 656.72,329.33 654.27,332.02C650.91,335.7 647.78,339.6 644.26,343.11C643.3,344.07 641.28,343.97 639.79,344.35V344.35Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M301.58,227.85C297.81,222.81 297.04,217.02 295.7,211.51C294.19,205.28 293.32,198.89 292.04,192.6C291.78,191.32 290.56,190.18 290.46,188.92C290.35,187.37 290.96,185.77 291.27,184.08C296.29,185.93 301.37,187.83 306.46,189.66C308.91,190.54 311.91,189.17 312.9,186.73C316.03,179.02 319.09,171.29 322.23,163.6C322.58,162.74 323.28,162.04 323.49,161.73C327.75,163.06 331.58,164.27 335.92,165.63C333.39,171.98 331.05,177.86 328.68,183.72C327.17,187.44 325.58,191.13 324.08,194.85C323.5,196.3 325.23,199.39 327.01,199.98C329.05,200.65 331.17,201.15 333.26,201.69C335.01,202.15 336.83,202.44 338.5,203.12C338.9,203.28 339.21,204.87 338.89,205.43C335.63,211.2 330.03,213.99 324.32,216.66C318.69,219.3 313.13,222.1 307.55,224.84C305.53,225.83 303.53,226.86 301.58,227.85H301.58Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M643.51,362.64C649.3,358.96 654.77,355.47 660.25,352.01C661.49,351.23 662.82,350.59 664.07,349.81C666.45,348.32 668.73,346.65 671.17,345.27C676.46,342.28 681.88,339.52 687.14,336.48C690.84,334.34 694.33,331.85 697.96,329.59C699.34,328.73 700.87,328.1 702.33,327.36C705.41,325.79 708.46,324.15 711.58,322.67C712.8,322.09 714.16,321.76 715.49,321.46C717.99,320.88 719.78,321.97 720.13,324.39C720.2,324.91 719.53,325.73 718.98,326.11C717.83,326.92 716.53,327.52 715.31,328.23C710.44,331.03 705.55,333.78 700.74,336.66C695.73,339.64 690.89,342.93 685.81,345.77C679.37,349.38 672.75,352.64 666.25,356.12C661.45,358.69 656.71,361.38 651.94,364C651.25,364.38 650.49,364.63 649.8,365.02C646.99,366.61 644.21,366.01 643.51,362.64L643.51,362.64Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M261.86,229.59C270.17,232.2 277.79,236.53 285.79,239.88C293.74,243.21 301.67,246.59 309.48,250.21C317.47,253.91 325.32,257.93 333.23,261.81L332.83,262.97C330.41,262.41 327.84,262.2 325.59,261.23C318.51,258.19 311.56,254.84 304.53,251.66C299.74,249.49 294.89,247.43 290.09,245.28C286.89,243.84 283.73,242.31 280.54,240.84C275.5,238.53 270.42,236.31 265.44,233.9C263.88,233.14 262.57,231.86 261.14,230.82C261.38,230.41 261.62,230 261.86,229.59L261.86,229.59Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M446.01,350.86C448.75,347.33 451.29,343.96 453.98,340.72C454.45,340.15 455.78,339.7 456.36,339.96C457.09,340.29 457.67,341.35 457.95,342.21C458.78,344.85 459.38,347.57 460.18,350.22C460.4,350.93 461.01,351.52 461.27,351.91C464.88,348.74 468.33,345.72 471.94,342.55C470.7,336.63 471.64,330.49 472.96,324.14C473.88,319.7 476.3,316.55 478.56,313.1C480.27,310.5 482.19,310.41 484.5,312.55C487.64,315.45 490.55,318.65 493.89,321.3C497.95,324.53 502.36,327.33 506.65,330.34C506.86,329.95 507.02,329.79 506.99,329.67C506.69,328.3 506.36,326.93 506.04,325.57C507.5,325.68 509.15,325.38 510.37,325.97C514.34,327.88 517.61,330.7 520.55,334.05C525.51,339.69 530.07,345.57 532.79,352.62C536.33,361.8 537.09,371.11 533.63,380.56C531.94,385.17 530.71,389.96 528.83,394.48C526.4,400.3 522.43,405.02 517.19,408.64C514.65,410.4 512.43,412.75 509.7,414.09C501.61,418.08 493.17,420.38 483.95,420.85C477.04,421.21 470.64,420.65 464.13,418.63C457.57,416.6 451.45,414.14 446.22,409.41C438.38,402.31 432.8,393.96 431.46,383.43C430.56,376.35 429.08,369.26 430.16,361.98C430.98,356.37 432.63,351.09 435.4,346.19C437.08,343.2 440.92,343.38 443.11,346.42C444.14,347.86 445.05,349.38 446.01,350.86L446.01,350.86ZM439.15,347.64C434.9,353.19 433.6,359.47 433.58,365.85C433.57,371.7 434.29,377.6 435.21,383.4C436.2,389.62 438.87,395.22 442.99,400.09C446.78,404.57 450.16,409.59 455.98,411.67C461.95,413.81 467.94,416.08 474.11,417.31C478.11,418.11 482.46,417.28 486.64,416.93C496.45,416.13 505.5,413.17 513.36,407.04C520.11,401.78 525.67,395.67 528,387.13C529.03,383.35 530.77,379.7 531.32,375.87C531.95,371.48 532.2,366.86 531.56,362.5C530.43,354.82 526.94,347.94 522.17,341.82C519.8,338.77 517.12,335.97 514.13,332.55C514.79,335.97 515.37,338.58 515.74,341.22C515.84,342 515.44,343.49 515.06,343.56C514.15,343.74 512.97,343.49 512.16,342.99C511.74,342.73 511.93,341.56 511.73,340.83C511.26,339.15 511.24,336.84 510.11,335.95C507.62,334 504.55,332.78 501.74,331.22C494.29,327.07 488.04,321.39 481.48,315.14C479.98,317.51 478.03,319.6 477.23,322.08C476.03,325.78 475.42,329.72 474.99,333.6C474.72,335.95 475.17,338.4 475.48,340.79C475.54,341.26 476.46,342 476.94,341.97C479.66,341.8 482.36,341.19 485.07,341.2C490.09,341.21 494.58,343.03 498.44,346.19C499.28,346.88 499.61,348.18 500.32,349.46C497.27,349.8 495.05,350.05 492.72,350.31C493.77,351.6 494.38,353.14 495.27,353.33C499.3,354.18 500.79,357.52 502.52,360.44C505.99,366.3 507.43,372.6 505.06,379.28C503.04,384.99 498.56,388.69 493.47,391.2C484.92,395.4 476.09,394.88 467.53,390.75C461.35,387.77 458.62,381.04 461.48,375.67C463.58,371.72 466.68,368.84 470.96,367.09C473.37,366.1 476.47,365.57 477.17,362.2C467.29,359.85 456.34,359.12 454.79,345.53C453.61,346.82 452.55,347.74 451.8,348.86C450.66,350.56 449.76,352.42 448.74,354.19C448.24,355.06 447.8,356.45 447.13,356.59C446.4,356.74 445.17,355.92 444.59,355.18C442.71,352.8 441.02,350.26 439.15,347.64L439.15,347.64ZM464.77,355.55C469.2,356.57 473.57,357.66 477.99,358.54C479.73,358.89 481.67,358.91 481.25,361.33C480.63,364.94 478.87,367.85 475.36,369.5C472.86,370.68 470.39,371.95 468.01,373.37C465.51,374.86 463.81,377.26 464.05,380.11C464.32,383.3 465.95,385.98 469.19,387.48C475.75,390.53 482.32,391.05 489.28,388.82C498.85,385.75 503.82,378.42 501.75,368.8C500.66,363.75 498.42,358.96 493.74,356.03C491.34,354.52 488.65,353.48 486.18,352.09C485.58,351.75 484.9,350.83 484.96,350.26C485.03,349.7 485.9,349.04 486.57,348.77C488.34,348.06 490.19,347.54 492.34,346.83C482.62,341.26 467.26,347.41 464.77,355.55L464.77,355.55Z" - android:fillColor="#000000"/> - <path - android:pathData="M574.68,476.89C575.2,478.83 575.74,480.76 576.23,482.71C577.63,488.26 579.22,493.78 580.3,499.4C580.82,502.06 580.54,504.93 580.24,507.66C579.85,511.24 576.66,512.19 573.96,512.69C562.19,514.88 550.34,516.67 538.54,518.74C531.35,520.01 524.16,521.31 517.06,522.96C506.93,525.32 496.88,528.03 486.8,530.58C479.27,532.48 471.79,534.61 464.19,536.16C461.63,536.68 458.59,536.2 456.11,535.28C454.77,534.79 453.77,532.49 453.28,530.81C451.64,525.24 450.32,519.57 448.83,513.95C448.31,511.98 447.69,510.03 447.07,508.09C446.32,505.77 447.35,503.64 447.56,501.45C448.13,495.51 452.93,496.45 456.17,495.58C464.57,493.29 473.17,491.72 481.67,489.76C490.44,487.73 499.15,485.41 507.96,483.51C518.62,481.21 529.38,479.33 540.05,477.05C547.77,475.4 555.41,473.36 563.11,471.57C566.47,470.79 570.07,469.81 573.17,471.72C574.47,472.52 574.78,474.93 575.55,476.6C575.26,476.7 574.97,476.79 574.68,476.89V476.89ZM459.04,532.07C460.42,532.01 462.12,532.2 463.67,531.81C468.07,530.71 472.4,529.29 476.79,528.14C481.84,526.81 486.95,525.7 492.01,524.37C498.02,522.8 503.96,520.96 509.99,519.49C514.75,518.33 519.6,517.54 524.41,516.6C530.63,515.38 536.84,514.06 543.08,512.96C551.04,511.57 559.05,510.38 567.03,509.04C569.48,508.62 571.9,508 574.31,507.41C574.68,507.32 575.24,506.89 575.25,506.6C575.35,503.76 575.89,500.78 575.28,498.08C573.55,490.46 571.33,482.96 569.34,475.54C564.34,476.7 559.13,477.93 553.91,479.11C547.23,480.62 540.55,482.14 533.85,483.54C520.98,486.23 508.08,488.71 495.25,491.55C488.71,493 482.36,495.28 475.83,496.78C469.55,498.22 463.18,499.34 456.8,500.25C451.15,501.05 450.67,504.22 451.7,507.85C453.95,515.8 456.48,523.68 459.04,532.07V532.07Z" - android:fillColor="#000000"/> - <path - android:pathData="M451.16,487.84C444.48,487.83 440.61,483.95 439.22,477.88C437.77,471.52 436.11,465.22 434.65,458.87C433.21,452.55 434.74,448.79 441.45,446.9C450.94,444.24 460.58,442.14 470.14,439.69C476.06,438.17 481.93,436.42 487.85,434.86C492.87,433.53 497.93,432.35 502.96,431.08C506.35,430.22 509.72,429.33 513.1,428.46C518.54,427.06 524,425.68 529.44,424.24C537.13,422.2 544.8,420.11 552.48,418.05C554.58,417.48 556.67,416.86 558.81,416.43C560.89,416.01 564.4,418.97 564.81,421.48C566.33,430.74 567.86,440 569.22,449.28C569.51,451.29 569.63,453.67 568.82,455.41C568.05,457.04 566.12,458.36 564.41,459.28C557,463.26 548.93,465.13 540.71,466.62C533.59,467.92 526.56,469.72 519.49,471.27C509.21,473.51 498.87,475.51 488.66,478.04C479.64,480.27 470.79,483.17 461.82,485.6C457.77,486.69 453.59,487.34 451.16,487.84V487.84ZM559.82,421.45C558.37,421.77 557.31,421.98 556.27,422.24C549.75,423.85 543.21,425.44 536.7,427.1C529.93,428.81 523.19,430.6 516.43,432.34C513.7,433.05 511.29,434.64 508.09,434.08C506.41,433.78 504.45,435.58 502.52,436.09C495.28,438.03 488,439.81 480.74,441.69C475.58,443.03 470.46,444.53 465.28,445.8C457.76,447.64 450.18,449.26 442.67,451.13C438.77,452.11 437.91,454.21 439.22,457.99C440.21,460.88 441.04,463.83 441.85,466.77C443.09,471.33 444.26,475.91 445.44,480.49C446.01,482.7 447.46,483.78 449.64,483.27C458.89,481.1 468.13,478.86 477.34,476.55C486.04,474.37 494.66,471.85 503.4,469.86C516.08,466.95 528.85,464.45 541.55,461.65C548.49,460.12 555.48,458.83 561.84,455.2C564.51,453.68 564.49,451.89 564.21,449.62C563.73,445.7 563.22,441.78 562.61,437.88C561.76,432.51 560.79,427.15 559.82,421.45H559.82Z" - android:fillColor="#000000"/> - <path - android:pathData="M465.97,267.99C464.69,268.6 463.41,269.36 462.03,269.81C456.34,271.66 450.59,273.36 444.91,275.25C443.37,275.76 441.91,275.97 441.25,274.4C440.53,272.7 441.58,271.42 443.26,270.89C447.71,269.49 452.18,268.18 456.64,266.82C458.1,266.37 459.58,265.94 460.99,265.36C463.28,264.42 465.02,264.63 465.97,267.99V267.99Z" - android:fillColor="#000000"/> - <path - android:pathData="M474.27,265.41C473.75,265.75 472.6,267.08 471.87,266.87C470.64,266.53 469.68,265.23 468.6,264.33C469.48,263.51 470.3,262.13 471.26,262.01C472.67,261.83 474.36,262.36 474.27,265.41V265.41Z" - android:fillColor="#000000"/> - <path - android:pathData="M459.04,532.07C456.48,523.68 453.95,515.8 451.7,507.85C450.67,504.22 451.15,501.05 456.8,500.25C463.18,499.34 469.55,498.22 475.83,496.78C482.36,495.28 488.71,493 495.25,491.55C508.08,488.71 520.98,486.23 533.85,483.54C540.55,482.14 547.23,480.62 553.91,479.11C559.13,477.93 564.34,476.7 569.34,475.54C571.33,482.96 573.55,490.46 575.28,498.08C575.89,500.78 575.35,503.76 575.25,506.6C575.24,506.89 574.68,507.32 574.31,507.41C571.9,508 569.48,508.62 567.03,509.04C559.05,510.38 551.05,511.57 543.08,512.96C536.84,514.06 530.63,515.38 524.41,516.6C519.6,517.54 514.75,518.33 509.99,519.49C503.96,520.96 498.02,522.8 492.01,524.37C486.96,525.7 481.84,526.81 476.79,528.14C472.4,529.29 468.07,530.71 463.67,531.81C462.12,532.2 460.42,532.01 459.04,532.07V532.07ZM510.33,508.51C509.17,507.08 508.49,505.85 507.45,505.11C506.58,504.48 505.3,504.42 504.2,504.12C504.07,505.31 503.46,506.74 503.91,507.65C504.89,509.65 506.26,511.51 507.75,513.18C508.53,514.06 509.97,514.96 510.99,514.84C512.05,514.72 513.26,513.55 513.89,512.53C515.29,510.28 516.4,507.85 517.55,505.46C519.18,502.09 520.82,498.72 522.31,495.29C522.9,493.95 522.68,492.43 520.96,492.18C520,492.04 518.35,492.48 517.98,493.17C515.34,498.12 512.94,503.19 510.33,508.51V508.51Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M559.82,421.45C560.79,427.15 561.76,432.51 562.61,437.88C563.22,441.78 563.73,445.7 564.21,449.62C564.49,451.89 564.51,453.68 561.84,455.2C555.48,458.83 548.49,460.12 541.55,461.65C528.85,464.45 516.08,466.95 503.4,469.86C494.66,471.86 486.04,474.37 477.34,476.55C468.13,478.86 458.89,481.1 449.64,483.27C447.46,483.78 446.01,482.7 445.44,480.49C444.26,475.91 443.09,471.33 441.84,466.77C441.04,463.83 440.21,460.88 439.22,457.99C437.91,454.21 438.77,452.11 442.67,451.13C450.18,449.26 457.76,447.64 465.28,445.8C470.46,444.53 475.58,443.03 480.74,441.69C488,439.81 495.28,438.03 502.52,436.09C504.45,435.58 506.41,433.78 508.09,434.08C511.29,434.64 513.7,433.05 516.43,432.34C523.19,430.6 529.93,428.81 536.7,427.1C543.21,425.44 549.74,423.85 556.27,422.24C557.31,421.98 558.36,421.77 559.82,421.45V421.45ZM496.67,455.2C496.05,456.83 495.14,458.8 494.64,460.86C494.46,461.6 495.06,463 495.7,463.32C496.27,463.61 497.68,463.08 498.2,462.47C499.38,461.07 500.23,459.4 501.3,457.72C503.52,459.34 505.68,460.92 507.84,462.49C509.11,463.41 510.64,463.67 511.32,462.18C511.73,461.28 511.37,459.51 510.68,458.71C509.12,456.91 507.33,455.16 505.29,453.98C503.22,452.78 503.75,452.12 504.67,450.39C506.18,447.58 508.95,444.6 505.53,441.02C500.95,442.03 502.57,447.68 499.12,449.76C497.73,448.68 496.36,447.39 494.78,446.47C493.91,445.97 492.67,446.11 491.61,445.96C491.58,446.89 491.18,448.08 491.61,448.71C493.08,450.91 494.85,452.91 496.67,455.2H496.67Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M510.33,508.51C512.94,503.19 515.34,498.12 517.98,493.17C518.35,492.48 520,492.04 520.96,492.18C522.68,492.43 522.9,493.95 522.31,495.29C520.82,498.72 519.18,502.09 517.55,505.46C516.4,507.85 515.29,510.28 513.89,512.53C513.26,513.55 512.05,514.72 510.99,514.84C509.97,514.96 508.53,514.06 507.75,513.18C506.26,511.51 504.89,509.65 503.91,507.65C503.46,506.74 504.07,505.31 504.2,504.12C505.3,504.42 506.58,504.48 507.45,505.1C508.49,505.85 509.17,507.08 510.33,508.51V508.51Z" - android:fillColor="#000000"/> - <path - android:pathData="M496.67,455.2C494.85,452.91 493.08,450.91 491.61,448.71C491.18,448.08 491.58,446.89 491.61,445.96C492.67,446.11 493.91,445.97 494.78,446.47C496.36,447.39 497.73,448.68 499.12,449.76C502.57,447.68 500.95,442.03 505.53,441.02C508.95,444.6 506.18,447.58 504.68,450.39C503.75,452.12 503.22,452.78 505.29,453.98C507.33,455.16 509.12,456.91 510.68,458.71C511.37,459.51 511.73,461.28 511.32,462.18C510.64,463.67 509.11,463.41 507.84,462.49C505.68,460.92 503.52,459.34 501.3,457.72C500.24,459.4 499.38,461.07 498.2,462.47C497.68,463.08 496.27,463.61 495.7,463.32C495.06,463 494.46,461.6 494.64,460.86C495.14,458.8 496.05,456.83 496.67,455.2L496.67,455.2Z" - android:fillColor="#000000"/> - <path - android:pathData="M300.64,252.3C299.68,252.11 298.64,252.09 297.77,251.69C289.54,247.88 281.43,243.74 273.07,240.25C268.75,238.45 264.4,236.8 260.33,234.48C257.89,233.09 256.75,231.1 256.88,228.33C257.03,225.32 259.4,223.95 261.59,223.21C263.09,222.7 265.25,223.48 266.89,224.2C274.77,227.67 282.54,231.41 290.43,234.88C297.57,238.03 304.89,240.8 311.99,244.04C318.25,246.88 324.33,250.13 330.47,253.23C332.5,254.26 334.5,255.37 336.5,256.47C338.63,257.65 339.27,260.82 337.76,262.63C335.75,265.04 333.09,265.97 330.11,265.39C325.15,264.42 320.58,262.4 316.17,259.91C313.68,258.5 310.85,257.69 308.19,256.58C307.62,256.34 307.09,255.97 306.6,255.59C305.52,254.75 304.75,253.55 302.94,254.12C302.33,254.31 301.29,253.12 300.45,252.55C300.51,252.47 300.58,252.38 300.64,252.3V252.3ZM261.86,227.59C261.62,228 261.38,228.41 261.14,228.82C262.57,229.86 263.88,231.14 265.44,231.9C270.42,234.31 275.5,236.53 280.53,238.84C283.73,240.31 286.89,241.84 290.09,243.28C294.89,245.43 299.74,247.49 304.53,249.66C311.56,252.84 318.51,256.19 325.59,259.23C327.84,260.2 330.41,260.41 332.83,260.97L333.23,259.81C325.32,255.93 317.47,251.91 309.48,248.21C301.67,244.59 293.73,241.21 285.79,237.88C277.79,234.53 270.17,230.2 261.86,227.59L261.86,227.59Z" - android:fillColor="#000000"/> - <path - android:pathData="M306.6,554.66C306.28,541.28 305.97,528.41 305.65,515.06C296.78,522.81 287.12,526.58 276.02,527.32C270.65,527.67 265.58,526.97 260.49,525.72C256.49,524.73 256.47,524.64 255.93,528.73C255.57,531.43 255.45,534.17 255.05,536.87C253.78,545.48 252.51,554.09 251.08,562.68C250.02,569.06 248.67,575.4 247.55,581.77C246.96,585.12 246.61,588.51 246.12,591.87C245.5,596.15 243.2,599.72 241.07,603.31C238.41,607.78 234.65,611.36 229.61,612.7C219.34,615.43 208.56,614.93 202.28,603.29C198.7,596.63 197.42,589.37 198.24,581.98C198.55,579.14 200.64,576.38 202.27,573.81C206.54,567.06 213.69,564.18 220.56,561.3C225.04,559.43 230.21,558.4 234.84,561.07C237.81,562.78 240.3,565.32 243.32,567.74C243.54,567.02 244.1,565.81 244.26,564.55C244.91,559.67 245.41,554.77 246,549.88C246.84,542.84 247.72,535.8 248.55,528.76C249.31,522.23 250.04,515.7 250.73,509.17C251,506.56 251.1,503.94 251.29,501.32C251.54,497.91 253.42,496.86 256.3,498.66C263.99,503.47 272.41,505.26 281.24,503.83C285.23,503.18 289.17,501.38 292.8,499.45C297.94,496.73 302.73,493.36 307.73,490.35C310.26,488.83 312.62,490.29 312.76,493.42C312.92,497.03 312.98,500.64 313.07,504.26C313.23,510.79 313.39,517.33 313.51,523.86C313.65,530.95 313.69,538.03 313.86,545.11C314.02,551.59 314.37,558.05 314.5,564.53C314.56,567.1 314.98,569.4 315.81,571.93C316.58,574.25 314.54,577.56 313.53,580.36C313.24,581.15 312.02,581.56 311.56,582.34C308,588.28 301.83,590.72 296.08,593.44C290.31,596.17 279.43,593.44 276.02,589.31C270.46,582.57 268.91,575.09 271.36,566.69C273.63,558.94 277.79,552.66 285.44,549.55C291.61,547.03 297.65,548.2 303.16,551.89C304.23,552.61 305.18,553.5 306.6,554.66L306.6,554.66Z" - android:fillColor="#000000"/> - <path - android:pathData="M470.14,162.21C470.14,166.62 470.16,171.03 470.14,175.44C470.12,181.69 472.73,186.77 476.71,191.45C478.34,193.36 479.82,195.87 480.18,198.28C480.73,202.02 478.7,205.09 475.29,206.84C468.03,210.57 460.67,214.02 452.24,214.22C451.29,214.24 450.29,215.32 449.43,216.05C444.23,220.56 438.47,222.87 431.69,220.22C429.8,219.48 427.74,218.24 426.62,216.63C424.77,213.96 422.25,213.48 419.49,213.21C416.73,212.95 413.93,213 411.19,212.61C409.66,212.39 408.15,211.68 406.76,210.95C404.27,209.63 401.68,208.37 399.48,206.65C395.98,203.92 396.46,199.4 399.07,195.91C402.59,191.2 406.32,186.49 407.37,180.29C409.16,169.66 410.88,159 413.32,148.5C415.65,138.5 421.46,130.61 429.89,124.52C436.53,119.72 447.14,120.13 452.41,123.86C459.23,128.67 464.65,134.87 466.85,143.12C468.5,149.34 469.47,155.74 470.74,162.06C470.54,162.11 470.35,162.16 470.14,162.21L470.14,162.21ZM463.57,175.08C463.57,170.57 463.57,166.49 463.57,162.4C463.56,153.64 462.54,145.13 458.04,137.32C455.34,132.63 451.31,129.88 446.2,128.73C443.21,128.06 440.08,127.94 437.01,127.71C435.87,127.63 434.46,127.6 433.59,128.17C429.64,130.75 426.39,134.12 424.2,138.31C422.18,142.18 419.38,145.72 419.26,150.45C419.18,153.39 418.6,156.32 418.18,159.25C417.66,162.87 417.65,166.71 416.34,170.03C415.41,172.39 415.86,174.4 415.41,176.93C431.48,172.75 447.18,170.08 463.57,175.08V175.08ZM408.53,192.2C428.5,190.57 448.2,186.5 467.96,192.03C466.94,190.22 466.07,188.59 465.11,187C464.67,186.28 464.21,185.35 463.52,185.05C456.49,181.94 448.92,180.65 441.4,180.12C434.65,179.65 427.75,180.35 420.99,181.2C417.82,181.6 414.03,181.81 411.91,185.06C410.65,186.99 409.61,189.07 408.55,191.13C408.35,191.53 408.53,192.11 408.53,192.2L408.53,192.2ZM451.63,193.95C454.9,198.26 456.31,202.82 454.55,208.4C462.46,207.25 468.91,204.51 474.87,199.22C467,196.55 459.69,194.26 451.63,193.95V193.95ZM425.22,195.07C418.47,195.67 411.9,196.49 405.68,199.06C405.15,199.27 404.61,200.46 404.72,201.07C405.21,203.57 409.19,207.15 411.75,207.16C415.22,207.17 418.69,206.78 421.75,206.59C422.93,202.67 424.03,199.02 425.22,195.07L425.22,195.07Z" - android:fillColor="#000000"/> - <path - android:pathData="M308.08,333.83C308.08,343.25 308.19,351.61 308.05,359.96C307.92,367.34 307.99,374.77 307.12,382.07C306.15,390.07 303.47,397.69 299.03,404.57C297.67,406.67 296.45,408.87 295.03,410.94C293.07,413.8 291.08,416.66 288.92,419.38C287.07,421.72 285.09,423.98 282.94,426.05C280.15,428.76 277.31,431.49 274.11,433.66C273.05,434.38 270.29,434.01 269.25,433.09C265.95,430.14 263.08,426.71 260.08,423.43C257.93,421.09 255.84,418.7 253.72,416.33C250.2,412.38 246.72,408.4 243.16,404.48C240.78,401.86 238,399.54 235.94,396.7C233.12,392.79 230.68,388.6 228.32,384.39C223.7,376.15 221.89,367.18 221.32,357.81C220.91,351.14 219.78,344.52 219.13,337.86C218.95,336 218.87,333.9 219.55,332.25C220.25,330.57 221.83,329.18 223.23,327.89C226.21,325.14 229.11,322.21 232.46,319.97C235.2,318.12 238.45,316.94 241.62,315.86C245.35,314.58 249.2,313.67 253.04,312.75C254.58,312.37 256.25,312.55 257.81,312.22C266.97,310.31 276.23,309.99 285.5,310.83C289.47,311.2 293.64,311.7 297.2,313.3C299.37,314.29 301.99,314.92 303.69,316.33C305.55,317.87 306.88,320.68 307.36,323.14C308.1,326.96 307.92,330.96 308.08,333.84L308.08,333.83ZM225.31,333.88C226.02,338.13 226.78,342.17 227.34,346.24C227.83,349.79 228.26,353.36 228.41,356.93C228.55,360.36 229.64,363.63 229.74,367.08C229.79,368.98 230.91,370.84 231.14,372.76C231.87,378.63 234.43,383.7 237.74,388.42C240.45,392.27 243.42,395.92 246.27,399.66C247.05,400.68 247.79,401.71 248.63,402.67C250.71,405.04 252.79,407.4 254.95,409.7C256.46,411.3 258.14,412.73 259.63,414.33C260.92,415.71 261.93,417.37 263.3,418.65C265.83,421.01 268.63,423.08 271.13,425.47C272.19,426.48 272.68,426.62 273.63,425.44C275.16,423.52 276.92,421.79 278.45,419.86C283.47,413.56 288.64,407.36 293.32,400.82C296.23,396.76 298.8,392.34 300.74,387.75C302.83,382.81 303.75,377.45 303.82,371.99C303.94,362.78 304.36,353.62 302.78,344.41C301.67,337.92 301.77,331.23 301.42,324.62C301.26,321.58 299.73,319.21 297.44,319.02C294.42,318.77 291.39,318.4 288.37,318.45C279.45,318.62 270.46,317.51 261.69,320.49C257.01,322.08 251.99,322.68 247.21,324.04C243.06,325.21 239.03,326.81 234.95,328.22C234.7,328.31 234.38,328.28 234.17,328.41C231.28,330.18 228.4,331.97 225.31,333.88V333.88Z" - android:fillColor="#000000"/> - <path - android:pathData="M546.49,150.6C546.11,144.81 547.14,139.19 550.09,134.31C554.24,127.46 560.43,123.07 568.65,122.51C574.6,122.1 580.65,121.91 586.15,124.92C590.84,127.49 595.61,129.95 598.91,134.46C599.68,135.53 601.63,135.84 602.2,136.94C603.36,139.2 605.69,140.18 607.02,142.22C609.45,145.95 612.5,149 616.08,151.82C619.35,154.4 621.66,158.38 623.89,162.06C628.37,169.44 632.65,176.96 636.73,184.58C638.02,186.98 639.82,189.55 638.74,192.66C638.09,194.56 637.79,196.81 636.57,198.27C632.99,202.54 629.22,206.59 624.22,209.49C616.58,213.92 609.3,218.96 601.81,223.64C598.76,225.55 595.71,227.73 592.35,228.82C588.2,230.15 584.33,227.98 581.97,224.8C577.04,218.13 572.71,211.01 568.13,204.08C566.11,201.02 563.91,198.07 562.07,194.9C559.82,191.05 557.66,187.13 555.83,183.07C553.41,177.73 550.97,172.33 549.21,166.74C547.58,161.55 546.82,156.08 545.67,150.73C545.95,150.69 546.22,150.65 546.49,150.6L546.49,150.6ZM611.23,153.43C608.43,154.94 605.9,156.08 603.61,157.6C599.98,160.02 596.52,162.71 592.96,165.25C590.79,166.8 588.56,168.24 586.39,169.78C582.12,172.81 577.85,175.84 573.62,178.92C570.35,181.31 567.07,183.7 563.93,186.25C562.94,187.05 562.69,187.89 563.82,189.49C568.96,196.76 573.64,204.34 578.58,211.74C580.93,215.26 583.31,218.78 586.06,221.98C587.09,223.18 589.41,224.32 590.77,223.98C593.52,223.3 596.16,221.81 598.61,220.27C605.86,215.71 612.94,210.89 620.18,206.32C625.33,203.08 630.13,199.52 633.27,194.19C633.77,193.33 634.07,191.9 633.7,191.06C631.51,186.03 629.39,180.93 626.68,176.17C622.99,169.7 618.85,163.48 614.79,157.22C613.92,155.88 612.58,154.85 611.23,153.43V153.43ZM567.26,177.64C578.75,169.46 589.93,161.51 601.65,153.16C598.14,150.55 595.07,148.1 591.83,145.9C588.2,143.42 584.58,140.86 580.68,138.9C576.26,136.68 571.41,135.85 566.59,137.67C561.52,139.59 558.51,145.72 558.9,152.25C559.45,161.48 563.21,169.58 567.26,177.64V177.64ZM560.97,182.62C561.2,182.63 561.44,182.64 561.67,182.64C561.98,181.76 562.68,180.79 562.51,180.01C562.16,178.37 561.47,176.77 560.72,175.26C557.13,167.99 554.82,160.26 554.67,152.24C554.58,147.43 554.64,142.37 558.54,137.98C560.32,135.98 561.92,134.34 564.26,133.5C571.28,130.95 578.06,132.18 584.43,135.62C588.2,137.66 591.65,140.28 595.33,142.51C598.79,144.61 602.28,146.6 604.61,150.1C604.85,150.46 605.93,150.27 606.62,150.33C606.34,149.41 606.03,149.23 605.84,148.95C604.2,146.73 602.79,144.3 600.92,142.31C598.49,139.71 595.72,137.43 593.05,135.07C589.29,131.74 584.99,129.34 580.27,127.65C576.89,126.45 573.48,127.04 570.05,127.41C558.87,128.61 553.5,134.73 551.46,144.18C549.84,151.65 551.75,159.08 554.01,166.26C555.03,169.5 556.72,172.53 558.07,175.67C559.06,177.98 560,180.3 560.97,182.62V182.62Z" - android:fillColor="#000000"/> - <path - android:pathData="M696.03,467.66C695.64,466.39 695.19,465.13 694.88,463.85C694.09,460.65 693.78,457.52 695.01,454.24C695.48,452.99 694.51,451.27 694.55,449.78C694.66,446.22 695.6,442.58 695.07,439.15C694.44,434.98 695.6,431.01 695.45,426.93C695.39,425.45 696.89,423.91 697.71,422.42C698.74,420.54 700.48,421.46 701.97,421.36C707.6,420.99 713.24,420.13 718.84,420.39C721.56,420.52 724.1,419.63 726.95,420.08C730.7,420.67 734.02,418.6 736.79,415.58C740.33,411.71 744.05,407.86 748.29,404.83C753.02,401.44 758.46,398.89 764.54,399.3C765.88,399.39 767.22,401.11 768.34,402.3C769.46,403.49 768.84,404.6 768.05,405.96C767.17,407.48 766.75,409.43 766.66,411.23C766.36,416.92 766.58,422.66 766.05,428.33C765.81,430.98 766.62,433.82 764.8,436.44C764.09,437.46 765.09,439.55 764.97,441.12C764.75,443.98 765.15,447.12 764.59,449.61C763.78,453.18 764.97,456.79 763.4,460.32C762.47,462.41 763.23,465.23 763.11,467.71C762.95,471.17 762.85,474.65 762.4,478.09C762.08,480.59 761.18,483.02 760.64,485.51C760.3,487.07 760.03,488.67 759.95,490.27C759.72,494.66 754.81,497.47 750.92,495.34C748.85,494.21 746.05,493.53 744.93,491.78C743.14,488.96 739.39,489.63 737.72,486.52C736.78,484.75 733.75,484.13 731.71,482.91C729.42,481.55 727.29,479.9 724.9,478.77C722.43,477.59 720.09,476.06 716.94,476.57C715.34,476.83 713.31,474.83 711.81,475.2C709.21,475.86 706.75,474.8 704.06,475.48C702.19,475.96 699.35,473.83 697.38,472.3C696.25,471.43 695.98,469.43 695.32,467.94C695.56,467.85 695.79,467.75 696.03,467.66L696.03,467.66ZM700.23,426.3C700.23,427.34 700.21,428.17 700.24,429C700.35,433.21 700.65,437.42 700.55,441.62C700.4,447.81 699.94,453.99 699.64,460.17C699.53,462.49 701.56,465.85 703.11,465.9C705.67,465.98 708.24,465.86 710.79,466.01C715.43,466.27 720.25,465.83 724.52,468.15C727.77,469.91 730.86,471.98 733.95,474.01C736.2,475.49 738.17,477.48 740.56,478.63C744.55,480.56 747.81,483.27 750.9,486.35C751.56,487.01 753.11,487.4 753.96,487.1C754.74,486.81 755.44,485.49 755.63,484.51C755.94,482.86 755.79,481.12 755.89,479.42C756.1,475.56 756.28,471.68 756.61,467.83C756.82,465.34 757.86,462.78 757.47,460.42C757.05,457.85 758.74,455.86 758.22,453.2C757.58,449.97 758.34,446.46 758.53,443.07C758.83,437.75 760.06,432.55 760.03,427.13C760.01,423.93 760.8,420.5 761.24,417.17C761.63,414.19 760.19,411.89 759.22,409.41C758.24,410.14 757.52,410.75 756.73,411.23C753.97,412.91 751.15,414.48 748.42,416.22C746.77,417.27 745.26,418.55 743.68,419.71C742.84,420.33 741.99,420.92 741.14,421.52C739.64,422.57 738.15,423.65 736.61,424.65C735.14,425.62 733.71,427 732.09,427.31C729.77,427.74 727.29,427.3 724.88,427.36C720.4,427.46 715.9,427.88 711.42,427.72C707.71,427.59 704.02,426.81 700.23,426.3H700.23Z" - android:fillColor="#000000"/> - <path - android:pathData="M700.16,284.83C698.78,287.36 697.21,290.82 695.12,293.94C692.43,297.95 689.5,301.82 686.35,305.48C683.42,308.89 680.03,311.9 676.91,315.16C675.28,316.86 673.77,318.69 672.23,320.49C668.19,325.23 664.39,330.2 660.06,334.66C656.15,338.7 652,342.6 646.83,345.14C645.16,345.95 643.62,347.37 641.88,347.66C638.18,348.29 636.1,345.45 634.17,342.94C631.48,339.45 629.77,335.52 628.41,331.24C626.82,326.25 623.97,321.67 621.7,316.9C619.76,312.79 617.84,308.67 615.95,304.54C613.96,300.17 611.84,295.84 610.13,291.36C609.22,288.97 608.53,286.26 608.66,283.75C608.93,278.84 613.29,275.17 618.49,274.7C624.65,274.15 630.79,273.13 636.95,273.04C642.95,272.95 648.96,273.76 654.97,274.17C657.79,274.37 660.62,274.52 663.44,274.76C671.79,275.49 680.15,276.27 688.5,276.99C689.73,277.1 690.96,277 692.19,277.03C696.51,277.13 699.95,280.08 700.16,284.83V284.83ZM639.79,342.35C641.28,341.97 643.3,342.07 644.26,341.11C647.78,337.6 650.91,333.7 654.27,330.02C656.72,327.33 659.01,324.37 661.9,322.24C668.33,317.49 673.51,311.65 678.21,305.31C680.13,302.72 681.81,299.94 683.93,297.52C687.23,293.76 690.95,290.35 693.08,285.66C694.01,283.61 693.6,282.14 691.48,281.96C688.98,281.75 686.46,281.8 683.94,281.73C678.49,281.56 673.03,281.54 667.58,281.17C663.11,280.86 658.68,279.97 654.22,279.65C648.73,279.27 643.22,279.12 637.72,279.05C633.16,279 628.53,278.83 624.03,279.44C620.86,279.88 616.93,278.55 614.55,282.6C615.6,284.7 616.89,287.04 617.96,289.48C619.38,292.71 620.67,296 621.93,299.3C624.37,305.65 626.7,312.04 629.15,318.39C631.2,323.71 633.25,329.03 635.5,334.27C636.64,336.94 638.22,339.43 639.79,342.35H639.79Z" - android:fillColor="#000000"/> - <path - android:pathData="M330.68,190.71C336.07,192.94 341.05,194.83 345.84,197.09C347.23,197.74 348.17,199.43 349.19,200.73C350.56,202.49 349.65,204.03 348.55,205.52C345.89,209.12 341.91,210.95 338.2,213.1C330.8,217.42 323.38,221.74 315.8,225.75C310.98,228.29 305.93,230.46 300.85,232.43C298.69,233.26 296.34,231.95 295.66,229.88C294.11,225.11 293.02,220.18 291.88,215.27C291.02,211.54 290.48,207.75 289.63,204.02C288.1,197.26 286.43,190.53 284.87,183.78C284.61,182.68 284.59,181.52 284.57,180.38C284.51,177.19 287.84,174.9 291.67,175.98C296.51,177.34 301.24,179.1 305.97,180.83C307.93,181.54 309.4,180.68 310.26,178.34C311.89,173.92 313.72,169.57 315.43,165.18C315.91,163.95 316.05,162.54 316.7,161.41C317.92,159.29 319.29,157.22 320.85,155.34C321.31,154.79 322.74,154.63 323.54,154.88C328.26,156.35 332.99,157.82 337.57,159.64C340.27,160.71 341.04,163.66 340,166.35C338.2,171.03 336.56,175.77 334.74,180.45C333.77,182.95 332.56,185.36 331.52,187.85C331.13,188.79 330.94,189.81 330.68,190.71H330.68ZM301.58,225.85C303.53,224.86 305.53,223.83 307.55,222.84C313.13,220.1 318.69,217.3 324.32,214.66C330.03,211.99 335.63,209.2 338.89,203.43C339.21,202.87 338.9,201.28 338.5,201.12C336.83,200.44 335.01,200.15 333.26,199.69C331.16,199.15 329.05,198.65 327.01,197.98C325.23,197.39 323.5,194.3 324.08,192.85C325.58,189.13 327.17,185.44 328.68,181.72C331.05,175.86 333.39,169.98 335.92,163.63C331.58,162.27 327.75,161.06 323.49,159.73C323.28,160.04 322.58,160.74 322.23,161.6C319.09,169.29 316.03,177.02 312.9,184.73C311.91,187.17 308.91,188.54 306.46,187.66C301.37,185.83 296.29,183.93 291.27,182.08C290.96,183.77 290.35,185.37 290.46,186.92C290.56,188.18 291.78,189.32 292.04,190.6C293.32,196.89 294.19,203.28 295.7,209.51C297.04,215.02 297.81,220.81 301.58,225.85H301.58Z" - android:fillColor="#000000"/> - <path - android:pathData="M797.47,487.65C798.29,486.62 799.64,484.81 801.11,483.11C802.74,481.23 804.47,479.43 806.16,477.61C807.5,476.17 808.86,474.75 810.21,473.33C814.72,468.61 817.82,463.07 819.81,456.86C821.3,452.2 821.97,447.41 822.14,442.58C822.23,439.83 821.99,436.92 821.13,434.33C820.16,431.38 818.41,428.66 816.85,425.93C814.52,421.84 811.75,418.11 808.19,414.92C807.17,414 806.59,412.02 806.69,410.58C806.8,409 807.55,406.82 808.74,406.13C809.84,405.49 812.01,406.19 813.48,406.81C817.97,408.69 820.77,412.63 823.62,416.25C826.09,419.39 828.27,422.94 829.78,426.63C831.59,431.07 833.12,435.69 832.67,440.73C832.34,444.52 832.72,448.38 832.49,452.18C832.34,454.86 831.29,457.53 831.41,460.16C831.51,462.12 830.83,463.61 830.32,465.31C828.82,470.26 826.14,474.59 823.53,478.96C822.3,481.02 821.12,483.12 819.8,485.12C816.57,490.05 812.07,493.59 806.58,495.43C801.46,497.15 797.4,493.89 797.47,487.65V487.65Z" - android:fillColor="#000000"/> - <path - android:pathData="M639,360.23C638.73,355.34 641.87,353.84 644.06,351.96C646.72,349.69 649.84,347.95 652.82,346.07C658.42,342.54 664,338.97 669.7,335.59C676.54,331.54 683.43,327.56 690.43,323.77C693.13,322.31 696.17,321.51 699.04,320.35C703.57,318.52 708.2,316.89 712.57,314.74C717.26,312.43 723.27,314.29 724.82,319.15C726.13,323.23 725.6,325.84 720.93,328.56C716.69,331.02 712.82,334.11 708.66,336.71C705.23,338.86 701.6,340.67 698.09,342.69C695.04,344.44 692.1,346.38 689,348.03C684.82,350.23 680.51,352.17 676.31,354.34C672.37,356.39 668.48,358.55 664.61,360.74C661.26,362.64 658.12,364.99 654.62,366.52C651.18,368.04 647.4,369.5 643.56,367.93C639.69,366.34 639.57,362.51 639,360.23L639,360.23ZM643.51,360.64C644.21,364.01 646.99,364.61 649.8,363.02C650.48,362.63 651.25,362.38 651.94,362C656.71,359.38 661.45,356.69 666.24,354.12C672.75,350.64 679.37,347.38 685.8,343.77C690.89,340.93 695.73,337.64 700.73,334.66C705.55,331.78 710.44,329.03 715.3,326.23C716.53,325.52 717.83,324.92 718.98,324.11C719.53,323.73 720.2,322.91 720.13,322.39C719.78,319.97 717.99,318.88 715.49,319.46C714.16,319.76 712.8,320.09 711.58,320.67C708.46,322.15 705.41,323.79 702.33,325.36C700.87,326.1 699.34,326.73 697.96,327.59C694.33,329.84 690.84,332.34 687.14,334.48C681.88,337.52 676.46,340.28 671.17,343.27C668.72,344.65 666.45,346.32 664.07,347.81C662.82,348.59 661.49,349.23 660.25,350.01C654.77,353.47 649.3,356.96 643.51,360.64V360.64Z" - android:fillColor="#000000"/> - <path - android:pathData="M785.62,424.14C786.17,422.77 786.66,422.09 786.69,421.39C786.84,418.33 790.12,416.53 792.83,417.95C794.09,418.61 795.89,418.51 796.84,419.4C799.68,422.05 804.05,423.13 804.97,427.85C805.33,429.75 806.8,431.62 808.19,433.1C812.42,437.61 812.37,443.27 812.9,448.83C813.32,453.36 811.07,457.39 810.46,461.74C810.17,463.74 808.33,465.57 807.04,467.36C804.64,470.72 802.66,474.67 799.53,477.14C796.11,479.84 792.21,482.55 787.38,482.69C784.36,482.77 782.64,480.21 783.98,477.42C784.55,476.23 785.26,475.04 786.13,474.05C790.4,469.2 792.88,463.26 796.03,457.73C799.16,452.23 799.81,446.45 796.92,440.53C795.2,436.98 793.65,433.36 791.91,429.82C791.47,428.93 790.66,428.15 789.89,427.49C788.41,426.23 786.83,425.08 785.62,424.14V424.14Z" - android:fillColor="#000000"/> - <path - android:pathData="M772.82,432.71C775.49,431.81 777.6,429.6 780.28,431.64C781.63,432.67 783.21,433.47 784.32,434.71C787.47,438.23 789.02,442.58 788.06,447.15C787.07,451.88 785.73,456.72 783.45,460.92C781.5,464.51 779.38,468.58 775.13,470.26C774.09,470.67 772.34,470.43 771.46,469.76C770.37,468.93 768.55,467.85 769.75,465.84C770.1,465.25 770.74,464.83 771.15,464.27C774.75,459.34 777.68,454 777.85,447.83C777.95,444.21 777.05,440.48 774.88,437.24C773.97,435.88 773.49,434.23 772.82,432.71V432.71Z" - android:fillColor="#000000"/> - <path - android:pathData="M264.75,374.59C266.14,371.8 267.3,369.86 268.1,367.77C269.22,364.87 269.96,361.82 271.07,358.91C272.72,354.59 274.55,350.36 276.29,346.08C277.64,342.74 279.17,339.45 280.23,336.02C280.93,333.77 282.47,333.51 284.26,333.37C288.33,333.06 290.09,335.08 289.55,339.07C289.29,340.97 289.99,343.1 289.4,344.84C287.82,349.5 285.62,353.95 283.95,358.59C282.36,363.01 281.08,367.54 279.73,372.05C278.56,375.95 277.83,380.01 276.29,383.75C274.52,388.05 272.26,392.17 269.87,396.17C268.44,398.58 263.94,397.29 262.38,394.52C260.76,391.65 258.69,389.05 256.89,386.28C255.51,384.17 254.6,381.62 252.84,379.93C251.01,378.18 249.67,376.28 249.03,373.99C248.33,371.46 247.05,368.63 249.4,366.29C250.84,364.86 252.71,362.78 254.27,362.86C256,362.96 257.87,364.99 259.2,366.58C261.2,368.96 262.78,371.7 264.75,374.59L264.75,374.59Z" - android:fillColor="#000000"/> - <path - android:pathData="M590.72,175.13C592.77,177.85 595.03,180.52 596.9,183.45C598.54,186.02 600.56,187.33 603.62,187.55C610.57,188.06 611.1,195.5 609.11,199.91C607.82,202.76 605.63,204.73 602.43,204.99C598.57,205.29 596.13,202.88 594.54,199.78C593.54,197.82 592.8,195.64 593.68,193.17C594.03,192.21 593.2,190.68 592.6,189.57C591.11,186.77 589.29,184.14 587.89,181.3C586.38,178.25 587.1,176.79 590.72,175.13V175.13Z" - android:fillColor="#000000"/> - <path - android:pathData="M462.26,173.13C445.87,168.14 430.17,170.81 414.1,174.98C414.55,172.45 414.1,170.45 415.03,168.09C416.34,164.77 416.35,160.93 416.87,157.3C417.29,154.38 417.87,151.44 417.95,148.5C418.07,143.77 420.87,140.23 422.89,136.36C425.08,132.17 428.33,128.8 432.28,126.22C433.15,125.65 434.56,125.68 435.7,125.76C438.77,125.99 441.9,126.12 444.89,126.79C450,127.93 454.03,130.69 456.73,135.38C461.23,143.19 462.25,151.7 462.26,160.46C462.26,164.54 462.26,168.62 462.26,173.13Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M407.22,190.26C407.22,190.17 407.04,189.58 407.24,189.19C408.3,187.13 409.34,185.05 410.6,183.11C412.72,179.86 416.51,179.65 419.68,179.25C426.44,178.41 433.34,177.71 440.1,178.18C447.61,178.7 455.18,179.99 462.21,183.1C462.9,183.41 463.36,184.34 463.8,185.06C464.76,186.64 465.63,188.28 466.65,190.09C446.89,184.55 427.19,188.62 407.22,190.26Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M450.32,192.01C458.38,192.31 465.69,194.6 473.56,197.28C467.6,202.56 461.15,205.31 453.24,206.45C455,200.88 453.6,196.31 450.32,192.01Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M423.91,193.12C422.72,197.07 421.62,200.73 420.44,204.64C417.38,204.84 413.91,205.23 410.44,205.21C407.88,205.21 403.9,201.63 403.41,199.13C403.3,198.52 403.84,197.33 404.37,197.11C410.59,194.54 417.16,193.73 423.91,193.12Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M224,331.94C227.09,330.02 229.97,328.24 232.86,326.47C233.07,326.33 233.38,326.36 233.64,326.27C237.72,324.87 241.75,323.26 245.9,322.09C250.68,320.74 255.7,320.14 260.38,318.55C269.15,315.57 278.14,316.67 287.06,316.51C290.08,316.45 293.11,316.82 296.13,317.07C298.42,317.27 299.95,319.64 300.11,322.67C300.46,329.28 300.36,335.98 301.47,342.47C303.05,351.67 302.63,360.84 302.51,370.05C302.44,375.51 301.52,380.86 299.43,385.8C297.49,390.39 294.92,394.82 292.01,398.87C287.33,405.42 282.16,411.61 277.14,417.92C275.61,419.84 273.85,421.58 272.32,423.49C271.37,424.67 270.88,424.54 269.82,423.52C267.32,421.13 264.52,419.06 261.99,416.7C260.62,415.43 259.61,413.77 258.32,412.39C256.83,410.79 255.15,409.35 253.64,407.75C251.49,405.46 249.4,403.09 247.32,400.73C246.48,399.77 245.74,398.73 244.96,397.72C242.11,393.98 239.13,390.32 236.43,386.47C233.13,381.75 230.56,376.68 229.83,370.82C229.6,368.89 228.48,367.04 228.43,365.13C228.33,361.69 227.24,358.42 227.1,354.98C226.95,351.41 226.52,347.84 226.03,344.3C225.47,340.23 224.71,336.19 224,331.94ZM263.44,372.64C261.47,369.75 259.89,367.02 257.89,364.63C256.56,363.04 254.69,361.02 252.96,360.92C251.4,360.83 249.53,362.92 248.09,364.35C245.74,366.68 247.02,369.51 247.72,372.05C248.36,374.33 249.71,376.23 251.53,377.98C253.29,379.67 254.2,382.22 255.58,384.33C257.38,387.1 259.45,389.7 261.07,392.57C262.63,395.34 267.13,396.63 268.56,394.23C270.95,390.23 273.21,386.1 274.98,381.8C276.52,378.06 277.25,374 278.42,370.1C279.77,365.6 281.05,361.06 282.64,356.64C284.31,352.01 286.51,347.55 288.09,342.89C288.68,341.16 287.98,339.02 288.24,337.12C288.78,333.14 287.02,331.11 282.95,331.43C281.16,331.57 279.62,331.83 278.92,334.08C277.86,337.51 276.33,340.79 274.98,344.13C273.24,348.41 271.41,352.65 269.76,356.96C268.65,359.87 267.91,362.92 266.79,365.83C265.99,367.91 264.83,369.86 263.44,372.64Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M609.92,151.48C611.27,152.9 612.61,153.94 613.48,155.28C617.54,161.53 621.68,167.75 625.37,174.23C628.08,178.99 630.2,184.09 632.39,189.12C632.76,189.95 632.46,191.39 631.96,192.24C628.82,197.57 624.02,201.13 618.88,204.37C611.63,208.94 604.55,213.77 597.3,218.33C594.85,219.87 592.21,221.36 589.46,222.04C588.1,222.37 585.78,221.23 584.75,220.03C582,216.84 579.62,213.31 577.27,209.8C572.33,202.4 567.65,194.81 562.51,187.55C561.38,185.95 561.63,185.11 562.62,184.31C565.76,181.76 569.04,179.36 572.31,176.98C576.54,173.89 580.81,170.86 585.08,167.84C587.25,166.3 589.48,164.85 591.65,163.31C595.21,160.77 598.67,158.07 602.3,155.65C604.59,154.13 607.13,152.99 609.92,151.48ZM589.42,173.19C585.79,174.84 585.07,176.3 586.58,179.36C587.98,182.2 589.8,184.83 591.29,187.62C591.89,188.73 592.72,190.26 592.37,191.22C591.49,193.7 592.23,195.87 593.23,197.84C594.82,200.94 597.26,203.35 601.13,203.04C604.32,202.79 606.51,200.82 607.8,197.96C609.79,193.56 609.26,186.12 602.31,185.61C599.25,185.38 597.23,184.07 595.59,181.5C593.73,178.57 591.46,175.9 589.42,173.19Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M559.66,180.68C558.69,178.36 557.75,176.03 556.76,173.72C555.41,170.58 553.72,167.55 552.7,164.31C550.44,157.14 548.53,149.71 550.15,142.23C552.19,132.79 557.56,126.67 568.74,125.47C572.17,125.1 575.58,124.5 578.96,125.71C583.68,127.39 587.98,129.79 591.74,133.12C594.41,135.49 597.18,137.77 599.61,140.36C601.48,142.36 602.89,144.79 604.53,147.01C604.72,147.28 605.03,147.47 605.31,148.39C604.62,148.32 603.54,148.52 603.3,148.16C600.97,144.65 597.48,142.66 594.02,140.57C590.34,138.34 586.89,135.71 583.12,133.68C576.75,130.24 569.97,129 562.95,131.55C560.61,132.4 559.01,134.04 557.23,136.04C553.33,140.42 553.27,145.48 553.36,150.29C553.51,158.32 555.82,166.04 559.41,173.31C560.16,174.83 560.85,176.43 561.2,178.07C561.37,178.85 560.67,179.82 560.36,180.7C560.13,180.69 559.89,180.68 559.66,180.68Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M698.92,424.36C702.71,424.86 706.4,425.64 710.11,425.78C714.59,425.94 719.09,425.51 723.57,425.41C725.98,425.36 728.46,425.8 730.78,425.36C732.4,425.06 733.83,423.67 735.3,422.71C736.84,421.7 738.33,420.62 739.83,419.57C740.68,418.98 741.53,418.38 742.37,417.77C743.95,416.6 745.46,415.32 747.11,414.27C749.84,412.54 752.66,410.96 755.42,409.29C756.21,408.8 756.93,408.19 757.91,407.46C758.88,409.94 760.32,412.24 759.93,415.22C759.49,418.55 758.7,421.98 758.72,425.18C758.75,430.61 757.52,435.8 757.22,441.13C757.03,444.51 756.27,448.02 756.91,451.25C757.43,453.91 755.74,455.91 756.16,458.47C756.55,460.83 755.51,463.39 755.3,465.88C754.97,469.74 754.79,473.61 754.58,477.48C754.48,479.18 754.63,480.91 754.32,482.57C754.13,483.54 753.43,484.86 752.65,485.15C751.8,485.46 750.25,485.07 749.59,484.4C746.5,481.32 743.24,478.61 739.25,476.69C736.86,475.53 734.89,473.54 732.64,472.06C729.55,470.03 726.46,467.97 723.21,466.2C718.94,463.88 714.13,464.33 709.48,464.06C706.93,463.91 704.36,464.04 701.8,463.95C700.25,463.9 698.22,460.54 698.33,458.23C698.63,452.04 699.09,445.86 699.24,439.68C699.34,435.48 699.04,431.27 698.93,427.06C698.9,426.23 698.92,425.39 698.92,424.36Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M638.48,340.4C636.91,337.48 635.33,335 634.19,332.32C631.94,327.09 629.89,321.76 627.84,316.45C625.39,310.1 623.06,303.71 620.62,297.36C619.36,294.06 618.07,290.77 616.65,287.53C615.58,285.1 614.29,282.76 613.24,280.65C615.62,276.6 619.55,277.93 622.72,277.5C627.22,276.88 631.85,277.05 636.41,277.11C641.91,277.17 647.42,277.32 652.91,277.71C657.38,278.02 661.8,278.92 666.27,279.22C671.72,279.59 677.18,279.61 682.63,279.78C685.15,279.86 687.67,279.8 690.17,280.02C692.29,280.2 692.7,281.66 691.77,283.71C689.64,288.41 685.92,291.81 682.62,295.58C680.5,297.99 678.82,300.78 676.9,303.37C672.2,309.71 667.02,315.55 660.59,320.29C657.7,322.42 655.41,325.39 652.96,328.08C649.6,331.75 646.47,335.66 642.95,339.17C641.99,340.13 639.97,340.02 638.48,340.4Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M300.27,223.9C296.5,218.87 295.73,213.07 294.39,207.56C292.88,201.33 292.01,194.95 290.73,188.66C290.47,187.37 289.25,186.23 289.15,184.98C289.04,183.43 289.65,181.82 289.96,180.13C294.98,181.98 300.05,183.88 305.15,185.71C307.6,186.6 310.6,185.23 311.59,182.78C314.72,175.08 317.78,167.35 320.92,159.65C321.27,158.8 321.97,158.09 322.18,157.78C326.44,159.12 330.27,160.32 334.61,161.69C332.08,168.03 329.74,173.91 327.37,179.77C325.86,183.5 324.27,187.18 322.77,190.91C322.19,192.36 323.92,195.45 325.7,196.03C327.74,196.71 329.85,197.2 331.94,197.75C333.7,198.21 335.52,198.5 337.19,199.17C337.59,199.33 337.89,200.93 337.58,201.49C334.32,207.25 328.72,210.04 323.01,212.72C317.38,215.35 311.82,218.15 306.24,220.9C304.22,221.89 302.22,222.92 300.27,223.9Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M642.2,358.7C647.99,355.02 653.46,351.52 658.94,348.06C660.18,347.28 661.51,346.64 662.76,345.86C665.14,344.37 667.41,342.71 669.86,341.33C675.15,338.34 680.57,335.58 685.83,332.53C689.53,330.39 693.02,327.9 696.65,325.64C698.03,324.79 699.56,324.16 701.02,323.42C704.1,321.85 707.15,320.21 710.27,318.72C711.49,318.14 712.85,317.82 714.18,317.51C716.68,316.94 718.47,318.02 718.82,320.45C718.89,320.97 718.22,321.79 717.67,322.17C716.52,322.98 715.22,323.58 713.99,324.28C709.13,327.08 704.24,329.83 699.42,332.71C694.42,335.7 689.58,338.98 684.49,341.83C678.06,345.43 671.44,348.69 664.93,352.17C660.14,354.74 655.4,357.43 650.63,360.05C649.94,360.43 649.17,360.68 648.49,361.07C645.68,362.66 642.9,362.07 642.2,358.7Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M260.55,225.65C268.86,228.26 276.48,232.59 284.48,235.94C292.42,239.27 300.35,242.65 308.17,246.27C316.16,249.97 324.01,253.98 331.92,257.86L331.52,259.02C329.1,258.47 326.53,258.25 324.28,257.29C317.2,254.24 310.25,250.89 303.22,247.71C298.43,245.54 293.58,243.49 288.78,241.33C285.58,239.9 282.42,238.36 279.22,236.9C274.19,234.58 269.11,232.37 264.13,229.95C262.57,229.19 261.26,227.91 259.83,226.88C260.07,226.46 260.31,226.05 260.55,225.65Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="224" - android:startY="124.99" - android:endX="759.99" - android:endY="124.99" - android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features.xml deleted file mode 100644 index c5eeaffcf10fe2410f74820fc69cbc7b3f849705..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features.xml +++ /dev/null @@ -1,423 +0,0 @@ -<vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android" android:height="320dp" android:viewportHeight="193.94" android:viewportWidth="200" android:width="329.99896dp"> - - <path android:fillColor="#ab71ff" android:pathData="M179.44,129.92c-17.11,7.31 -23.09,39.17 -26.65,46.24 -7.44,15.67 -41.53,6.53 -54.54,6.53s-26.96,10.45 -47.73,11.23c-20.76,0.78 -33.16,-20.38 -33.16,-46.76S0,106.93 0,88.9s20.14,-16.72 33.16,-23.77c13.02,-7.05 23.55,-56.43 60.74,-63.48 37.19,-7.05 59.5,9.93 81.51,23.25 22,13.32 26.65,40.49 23.86,55.64 -2.79,15.15 1.55,40.23 -19.83,49.37Z" android:strokeWidth="0"/> - - <path android:fillColor="#f9f9fb" android:pathData="M7.27,36.97c0,-3.35 2.71,-6.06 6.06,-6.06h173.33c3.35,0 6.06,2.71 6.06,6.06v112.73c0,3.35 -2.71,6.06 -6.06,6.06H13.33c-3.35,0 -6.06,-2.71 -6.06,-6.06V36.97Z" android:strokeColor="#ededf0" android:strokeWidth="1"/> - - <path android:fillColor="#5b5b66" android:pathData="M19.06,49.9l-0.05,-1.69h0.24l2.86,-3.36h1.48l-2.84,3.28 -0.72,0.64 -0.97,1.13ZM17.87,52.12v-7.26h1.3v7.26h-1.3ZM22.23,52.12l-2.38,-3.36 0.92,-0.87 3.05,4.22h-1.58Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M26.75,52.23c-0.55,0 -1.02,-0.12 -1.41,-0.35 -0.39,-0.23 -0.69,-0.56 -0.9,-0.99s-0.32,-0.93 -0.32,-1.51v-0c0,-0.58 0.1,-1.08 0.31,-1.51 0.21,-0.43 0.51,-0.76 0.9,-1 0.39,-0.24 0.84,-0.36 1.36,-0.36 0.52,0 0.97,0.12 1.35,0.35 0.38,0.23 0.67,0.55 0.88,0.96 0.2,0.41 0.31,0.9 0.31,1.45v0.41h-4.47v-0.84h3.85l-0.59,0.78v-0.5c0,-0.37 -0.06,-0.67 -0.17,-0.91 -0.11,-0.24 -0.26,-0.42 -0.46,-0.54 -0.19,-0.12 -0.42,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.12 -0.36,0.31 -0.47,0.55 -0.11,0.24 -0.17,0.54 -0.17,0.89v0.5c0,0.34 0.06,0.63 0.17,0.87 0.11,0.24 0.28,0.42 0.48,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.42,-0.03 0.58,-0.1 0.16,-0.07 0.3,-0.15 0.4,-0.24 0.1,-0.09 0.17,-0.18 0.21,-0.27l0.02,-0.04h1.19l-0.01,0.05c-0.04,0.18 -0.12,0.36 -0.24,0.54 -0.11,0.18 -0.27,0.35 -0.47,0.51 -0.19,0.15 -0.43,0.28 -0.71,0.38 -0.28,0.09 -0.61,0.14 -0.98,0.14Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M30.88,54.05c-0.08,0 -0.16,-0 -0.24,-0 -0.08,-0 -0.16,-0.01 -0.24,-0.02v-0.96c0.05,0.01 0.11,0.01 0.18,0.01 0.07,0 0.13,0 0.2,0 0.26,0 0.46,-0.06 0.62,-0.17 0.16,-0.11 0.27,-0.29 0.34,-0.54l0.07,-0.25 -1.97,-5.5h1.37l1.45,4.87 -0.34,-0.57h0.43l-0.33,0.57 1.45,-4.87h1.32l-1.97,5.62c-0.16,0.46 -0.34,0.82 -0.55,1.08 -0.2,0.26 -0.45,0.45 -0.73,0.56 -0.29,0.11 -0.63,0.17 -1.04,0.17Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M39.3,52.12v-4.53h-0.9v-0.97h0.9v-0.54c0,-0.37 0.06,-0.67 0.19,-0.92 0.13,-0.24 0.32,-0.42 0.59,-0.54 0.26,-0.12 0.6,-0.18 1.01,-0.18 0.13,0 0.26,0 0.37,0.02 0.11,0.01 0.22,0.02 0.32,0.04v0.88c-0.05,-0.01 -0.11,-0.01 -0.18,-0.02 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.3,0 -0.5,0.07 -0.63,0.21 -0.12,0.13 -0.19,0.33 -0.19,0.6v0.47h1.19v0.97h-1.17v4.53h-1.25Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M45.04,52.23c-0.55,0 -1.02,-0.12 -1.41,-0.35 -0.39,-0.23 -0.69,-0.56 -0.9,-0.99s-0.32,-0.93 -0.32,-1.51v-0c0,-0.58 0.1,-1.08 0.31,-1.51 0.21,-0.43 0.51,-0.76 0.9,-1 0.39,-0.24 0.84,-0.36 1.36,-0.36 0.52,0 0.97,0.12 1.35,0.35 0.38,0.23 0.67,0.55 0.88,0.96 0.2,0.41 0.31,0.9 0.31,1.45v0.41h-4.47v-0.84h3.85l-0.59,0.78v-0.5c0,-0.37 -0.06,-0.67 -0.17,-0.91s-0.26,-0.42 -0.46,-0.54c-0.19,-0.12 -0.42,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.12 -0.36,0.31 -0.47,0.55 -0.11,0.24 -0.17,0.54 -0.17,0.89v0.5c0,0.34 0.06,0.63 0.17,0.87 0.11,0.24 0.28,0.42 0.48,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.42,-0.03 0.58,-0.1 0.16,-0.07 0.3,-0.15 0.4,-0.24 0.1,-0.09 0.17,-0.18 0.21,-0.27l0.02,-0.04h1.19l-0.01,0.05c-0.04,0.18 -0.12,0.36 -0.24,0.54 -0.11,0.18 -0.27,0.35 -0.47,0.51 -0.19,0.15 -0.43,0.28 -0.71,0.38 -0.28,0.09 -0.61,0.14 -0.98,0.14Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M50.22,52.21c-0.35,0 -0.66,-0.07 -0.93,-0.2 -0.27,-0.13 -0.49,-0.32 -0.64,-0.57 -0.15,-0.25 -0.23,-0.54 -0.23,-0.88v-0.01c0,-0.33 0.08,-0.61 0.24,-0.84 0.16,-0.24 0.4,-0.42 0.71,-0.56 0.31,-0.13 0.69,-0.21 1.14,-0.24l2.03,-0.13v0.83l-1.86,0.12c-0.35,0.02 -0.61,0.09 -0.78,0.22 -0.17,0.13 -0.25,0.31 -0.25,0.53v0.01c0,0.23 0.09,0.42 0.27,0.55 0.18,0.13 0.41,0.2 0.69,0.2 0.25,0 0.48,-0.05 0.67,-0.15 0.2,-0.1 0.35,-0.24 0.47,-0.41 0.11,-0.17 0.17,-0.37 0.17,-0.59v-1.74c0,-0.28 -0.09,-0.48 -0.26,-0.63 -0.17,-0.15 -0.43,-0.22 -0.77,-0.22 -0.29,0 -0.52,0.05 -0.7,0.15 -0.18,0.1 -0.3,0.24 -0.37,0.42l-0.01,0.02h-1.18l0,-0.05c0.04,-0.31 0.16,-0.58 0.36,-0.81 0.2,-0.23 0.47,-0.41 0.8,-0.54 0.33,-0.13 0.71,-0.19 1.15,-0.19 0.48,0 0.88,0.07 1.21,0.22 0.33,0.14 0.58,0.36 0.75,0.63 0.17,0.28 0.26,0.61 0.26,0.99v3.76h-1.24v-0.75h-0.09c-0.1,0.17 -0.23,0.33 -0.39,0.45 -0.16,0.13 -0.34,0.22 -0.54,0.29 -0.2,0.07 -0.43,0.1 -0.67,0.1Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M56.78,52.15c-0.63,0 -1.08,-0.12 -1.36,-0.35s-0.42,-0.61 -0.42,-1.14v-3.07h-0.86v-0.97h0.86v-1.35h1.27v1.35h1.16v0.97h-1.16v2.77c0,0.27 0.06,0.47 0.17,0.6 0.12,0.12 0.31,0.19 0.56,0.19 0.09,0 0.16,-0 0.22,-0 0.06,-0.01 0.13,-0.01 0.2,-0.02v0.97c-0.09,0.02 -0.19,0.03 -0.3,0.04 -0.11,0.01 -0.23,0.02 -0.35,0.02Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M60.45,52.23c-0.41,0 -0.75,-0.08 -1.03,-0.24 -0.28,-0.16 -0.49,-0.39 -0.63,-0.7 -0.14,-0.31 -0.21,-0.68 -0.21,-1.12v-3.56h1.25v3.27c0,0.43 0.08,0.75 0.25,0.96 0.17,0.21 0.44,0.32 0.82,0.32 0.2,0 0.38,-0.03 0.53,-0.09 0.16,-0.06 0.29,-0.15 0.39,-0.27 0.1,-0.12 0.18,-0.26 0.24,-0.42 0.05,-0.17 0.08,-0.36 0.08,-0.56v-3.2h1.25v5.5h-1.25v-0.84h-0.09c-0.08,0.19 -0.2,0.36 -0.35,0.51 -0.15,0.14 -0.33,0.25 -0.54,0.33 -0.21,0.07 -0.45,0.11 -0.71,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M64.89,52.12v-5.5h1.25v0.85h0.09c0.09,-0.3 0.26,-0.52 0.5,-0.69 0.24,-0.16 0.55,-0.25 0.91,-0.25 0.09,0 0.19,0.01 0.28,0.02 0.09,0.01 0.17,0.02 0.23,0.04v1.12c-0.1,-0.02 -0.2,-0.04 -0.31,-0.05 -0.1,-0.01 -0.21,-0.02 -0.32,-0.02 -0.28,0 -0.52,0.05 -0.73,0.16 -0.21,0.1 -0.37,0.25 -0.48,0.45 -0.11,0.19 -0.17,0.42 -0.17,0.68v3.19h-1.25Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M71.34,52.23c-0.55,0 -1.02,-0.12 -1.41,-0.35 -0.39,-0.23 -0.69,-0.56 -0.9,-0.99 -0.21,-0.43 -0.32,-0.93 -0.32,-1.51v-0c0,-0.58 0.1,-1.08 0.31,-1.51 0.21,-0.43 0.51,-0.76 0.9,-1 0.39,-0.24 0.84,-0.36 1.36,-0.36 0.52,0 0.97,0.12 1.35,0.35 0.38,0.23 0.67,0.55 0.88,0.96 0.2,0.41 0.31,0.9 0.31,1.45v0.41h-4.47v-0.84h3.85l-0.59,0.78v-0.5c0,-0.37 -0.06,-0.67 -0.17,-0.91 -0.11,-0.24 -0.26,-0.42 -0.46,-0.54 -0.19,-0.12 -0.42,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.12 -0.36,0.31 -0.47,0.55 -0.11,0.24 -0.17,0.54 -0.17,0.89v0.5c0,0.34 0.06,0.63 0.17,0.87 0.11,0.24 0.28,0.42 0.48,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.42,-0.03 0.58,-0.1 0.16,-0.07 0.3,-0.15 0.4,-0.24 0.1,-0.09 0.17,-0.18 0.21,-0.27l0.02,-0.04h1.19l-0.01,0.05c-0.04,0.18 -0.12,0.36 -0.24,0.54 -0.11,0.18 -0.27,0.35 -0.47,0.51 -0.19,0.15 -0.43,0.28 -0.71,0.38 -0.28,0.09 -0.61,0.14 -0.98,0.14Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M77.1,52.23c-0.47,0 -0.87,-0.07 -1.21,-0.2 -0.34,-0.13 -0.6,-0.32 -0.79,-0.55 -0.19,-0.24 -0.31,-0.51 -0.35,-0.83v-0.01h1.24l0,0.01c0.07,0.19 0.19,0.35 0.38,0.47 0.18,0.12 0.43,0.18 0.74,0.18 0.21,0 0.39,-0.03 0.55,-0.09 0.16,-0.06 0.28,-0.14 0.37,-0.25 0.09,-0.1 0.14,-0.22 0.14,-0.36v-0.01c0,-0.16 -0.07,-0.3 -0.2,-0.4 -0.13,-0.11 -0.35,-0.2 -0.65,-0.27l-0.89,-0.2c-0.35,-0.08 -0.64,-0.18 -0.87,-0.32 -0.23,-0.14 -0.4,-0.31 -0.51,-0.51 -0.11,-0.2 -0.17,-0.44 -0.17,-0.7v-0.01c0,-0.33 0.09,-0.62 0.28,-0.88 0.19,-0.25 0.45,-0.45 0.78,-0.59 0.33,-0.14 0.71,-0.21 1.15,-0.21 0.45,0 0.83,0.07 1.15,0.2 0.32,0.13 0.57,0.32 0.75,0.55 0.18,0.23 0.29,0.5 0.31,0.8v0.01h-1.18l-0,-0.02c-0.05,-0.17 -0.16,-0.32 -0.34,-0.44 -0.17,-0.12 -0.41,-0.19 -0.7,-0.19 -0.18,0 -0.35,0.03 -0.5,0.09 -0.14,0.06 -0.26,0.14 -0.34,0.24 -0.08,0.1 -0.12,0.22 -0.12,0.36v0c0,0.11 0.03,0.2 0.08,0.28 0.06,0.08 0.15,0.15 0.27,0.21 0.12,0.06 0.28,0.11 0.48,0.16l0.89,0.2c0.54,0.12 0.94,0.3 1.2,0.54 0.26,0.24 0.39,0.56 0.39,0.96v0.01c0,0.35 -0.1,0.65 -0.3,0.92 -0.2,0.26 -0.48,0.47 -0.83,0.61 -0.35,0.14 -0.75,0.22 -1.2,0.22Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M18.19,81.82v-0.71h1.98c0.48,0 0.85,-0.1 1.1,-0.29 0.25,-0.19 0.37,-0.47 0.37,-0.84v-0.01c0,-0.25 -0.06,-0.45 -0.17,-0.62 -0.12,-0.17 -0.29,-0.29 -0.52,-0.37 -0.23,-0.08 -0.51,-0.12 -0.85,-0.12h-1.9v-0.69h1.68c0.49,0 0.85,-0.09 1.09,-0.26 0.25,-0.17 0.37,-0.43 0.37,-0.76v-0.01c0,-0.33 -0.11,-0.58 -0.33,-0.75 -0.22,-0.18 -0.53,-0.27 -0.92,-0.27h-1.88v-0.71h2.05c0.39,0 0.73,0.07 1.01,0.2 0.28,0.13 0.5,0.32 0.65,0.55 0.15,0.24 0.23,0.52 0.23,0.84v0.01c0,0.22 -0.05,0.43 -0.15,0.63 -0.1,0.2 -0.23,0.36 -0.4,0.49 -0.17,0.13 -0.35,0.22 -0.56,0.26v0.07c0.29,0.04 0.55,0.12 0.76,0.26 0.21,0.14 0.38,0.32 0.49,0.54 0.12,0.22 0.18,0.47 0.18,0.75v0.01c0,0.37 -0.09,0.69 -0.26,0.96 -0.17,0.27 -0.42,0.47 -0.74,0.62 -0.32,0.14 -0.71,0.21 -1.17,0.21h-2.1ZM17.79,81.82v-6.41h0.8v6.41h-0.8Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M23.69,81.82v-6.69h0.77v6.69h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M27.89,81.9c-0.45,0 -0.84,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.76,-0.86 -0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.51 0.09,-0.95 0.27,-1.32 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.3 1.18,-0.3 0.46,0 0.85,0.1 1.18,0.3 0.33,0.2 0.58,0.48 0.76,0.85 0.18,0.37 0.27,0.81 0.27,1.32v0.01c0,0.51 -0.09,0.95 -0.27,1.32 -0.18,0.37 -0.43,0.66 -0.76,0.86 -0.33,0.2 -0.72,0.3 -1.18,0.3ZM27.89,81.22c0.3,0 0.56,-0.07 0.77,-0.21 0.21,-0.14 0.37,-0.35 0.48,-0.61 0.11,-0.27 0.17,-0.59 0.17,-0.96v-0.01c0,-0.38 -0.06,-0.7 -0.17,-0.97 -0.11,-0.27 -0.27,-0.47 -0.48,-0.61 -0.21,-0.14 -0.47,-0.21 -0.77,-0.21 -0.3,0 -0.56,0.07 -0.77,0.21 -0.21,0.14 -0.37,0.34 -0.48,0.61 -0.11,0.27 -0.16,0.59 -0.16,0.97v0.01c0,0.38 0.05,0.7 0.16,0.96 0.11,0.27 0.27,0.47 0.48,0.61 0.21,0.14 0.47,0.21 0.77,0.21Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M33.23,81.9c-0.45,0 -0.83,-0.1 -1.16,-0.31 -0.33,-0.2 -0.58,-0.49 -0.76,-0.87 -0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.5 0.09,-0.93 0.27,-1.3 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.31 1.16,-0.31 0.39,0 0.72,0.07 1,0.2 0.28,0.14 0.51,0.32 0.67,0.55 0.17,0.23 0.28,0.48 0.32,0.77l0,0.03h-0.77l-0,-0.01c-0.06,-0.24 -0.19,-0.44 -0.4,-0.6 -0.21,-0.17 -0.49,-0.25 -0.83,-0.25 -0.29,0 -0.54,0.07 -0.75,0.22 -0.21,0.14 -0.37,0.35 -0.49,0.62 -0.11,0.26 -0.17,0.58 -0.17,0.94v0.01c0,0.37 0.06,0.69 0.17,0.96 0.12,0.27 0.28,0.48 0.49,0.63 0.21,0.15 0.46,0.22 0.74,0.22 0.32,0 0.59,-0.07 0.79,-0.21 0.2,-0.14 0.35,-0.34 0.44,-0.61l0.01,-0.03 0.76,-0 -0.01,0.05c-0.07,0.29 -0.18,0.54 -0.35,0.77 -0.17,0.22 -0.38,0.4 -0.66,0.52 -0.27,0.13 -0.6,0.19 -0.99,0.19Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M36.38,81.82v-6.69h0.77v6.69h-0.77ZM39.4,81.82l-1.87,-2.34 0.57,-0.49 2.27,2.84h-0.97ZM37.06,80.1l-0.04,-0.97h0.2l2.07,-2.09h0.94l-2.27,2.19 -0.19,0.18 -0.71,0.69Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M42.72,81.9c-0.36,0 -0.67,-0.05 -0.94,-0.16 -0.27,-0.11 -0.49,-0.26 -0.66,-0.46 -0.16,-0.2 -0.26,-0.42 -0.29,-0.69h0.79c0.07,0.2 0.19,0.36 0.38,0.48 0.19,0.12 0.44,0.18 0.74,0.18 0.22,0 0.41,-0.03 0.57,-0.09 0.17,-0.07 0.3,-0.15 0.39,-0.26 0.09,-0.11 0.14,-0.24 0.14,-0.39v-0.01c0,-0.16 -0.07,-0.3 -0.2,-0.41 -0.13,-0.12 -0.34,-0.21 -0.64,-0.28l-0.74,-0.18c-0.3,-0.07 -0.54,-0.16 -0.74,-0.28 -0.19,-0.12 -0.33,-0.26 -0.43,-0.42 -0.09,-0.17 -0.14,-0.37 -0.14,-0.59v-0c0,-0.27 0.08,-0.5 0.23,-0.71 0.16,-0.21 0.37,-0.38 0.64,-0.5 0.27,-0.12 0.57,-0.18 0.91,-0.18 0.33,0 0.63,0.05 0.89,0.16 0.26,0.1 0.47,0.25 0.63,0.44 0.16,0.19 0.26,0.42 0.29,0.68h-0.76c-0.05,-0.19 -0.17,-0.34 -0.35,-0.46 -0.18,-0.12 -0.42,-0.18 -0.71,-0.18 -0.19,0 -0.36,0.03 -0.51,0.09 -0.15,0.06 -0.26,0.14 -0.35,0.25 -0.09,0.11 -0.13,0.23 -0.13,0.37v0.01c0,0.11 0.03,0.2 0.08,0.28 0.06,0.08 0.14,0.16 0.26,0.22 0.12,0.06 0.27,0.12 0.46,0.16l0.74,0.18c0.45,0.11 0.78,0.27 1,0.47 0.22,0.2 0.33,0.48 0.33,0.82v0.01c0,0.28 -0.08,0.54 -0.25,0.75 -0.17,0.22 -0.4,0.38 -0.69,0.51 -0.29,0.12 -0.61,0.18 -0.98,0.18Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M48.39,81.82v-6.69h0.77v6.69h-0.77ZM51.41,81.82l-1.87,-2.34 0.57,-0.49 2.27,2.84h-0.97ZM49.07,80.1l-0.04,-0.97h0.2l2.07,-2.09h0.94l-2.27,2.19 -0.19,0.18 -0.71,0.69Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M53.26,81.82v-4.79h0.77v0.72h0.07c0.12,-0.25 0.3,-0.45 0.52,-0.59 0.23,-0.14 0.52,-0.21 0.87,-0.21 0.54,0 0.95,0.15 1.24,0.46 0.29,0.3 0.44,0.74 0.44,1.31v3.1h-0.77v-2.91c0,-0.43 -0.09,-0.75 -0.28,-0.96 -0.18,-0.21 -0.46,-0.32 -0.84,-0.32 -0.25,0 -0.47,0.05 -0.66,0.16 -0.19,0.11 -0.33,0.26 -0.44,0.47 -0.1,0.2 -0.15,0.44 -0.15,0.72v2.83h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M60.52,81.9c-0.45,0 -0.84,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.76,-0.86 -0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.51 0.09,-0.95 0.27,-1.32 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.3 1.18,-0.3 0.46,0 0.85,0.1 1.18,0.3 0.33,0.2 0.58,0.48 0.76,0.85 0.18,0.37 0.27,0.81 0.27,1.32v0.01c0,0.51 -0.09,0.95 -0.27,1.32 -0.18,0.37 -0.43,0.66 -0.76,0.86 -0.33,0.2 -0.72,0.3 -1.18,0.3ZM60.52,81.22c0.3,0 0.56,-0.07 0.77,-0.21 0.21,-0.14 0.37,-0.35 0.48,-0.61 0.11,-0.27 0.17,-0.59 0.17,-0.96v-0.01c0,-0.38 -0.06,-0.7 -0.17,-0.97 -0.11,-0.27 -0.27,-0.47 -0.48,-0.61 -0.21,-0.14 -0.47,-0.21 -0.77,-0.21 -0.3,0 -0.56,0.07 -0.77,0.21 -0.21,0.14 -0.37,0.34 -0.48,0.61 -0.11,0.27 -0.16,0.59 -0.16,0.97v0.01c0,0.38 0.05,0.7 0.16,0.96 0.11,0.27 0.27,0.47 0.48,0.61 0.21,0.14 0.47,0.21 0.77,0.21Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M64.65,81.82l-1.34,-4.79h0.77l0.94,3.83h0.07l1.07,-3.83h0.73l1.07,3.83h0.07l0.94,-3.83h0.77l-1.34,4.79h-0.78l-1.07,-3.7h-0.07l-1.07,3.7h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M70.74,81.82v-4.79h0.77v0.72h0.07c0.12,-0.25 0.3,-0.45 0.52,-0.59 0.23,-0.14 0.52,-0.21 0.87,-0.21 0.54,0 0.95,0.15 1.24,0.46 0.29,0.3 0.44,0.74 0.44,1.31v3.1h-0.77v-2.91c0,-0.43 -0.09,-0.75 -0.28,-0.96 -0.18,-0.21 -0.46,-0.32 -0.84,-0.32 -0.25,0 -0.47,0.05 -0.66,0.16 -0.19,0.11 -0.33,0.26 -0.44,0.47 -0.1,0.2 -0.15,0.44 -0.15,0.72v2.83h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M80.27,81.85c-0.49,0 -0.85,-0.1 -1.07,-0.3 -0.22,-0.2 -0.33,-0.53 -0.33,-0.98v-2.9h-0.75v-0.64h0.75v-1.24h0.8v1.24h1.05v0.64h-1.05v2.71c0,0.28 0.05,0.48 0.16,0.61 0.11,0.12 0.28,0.18 0.53,0.18 0.07,0 0.13,-0 0.17,-0 0.05,-0 0.11,-0.01 0.18,-0.01v0.66c-0.07,0.01 -0.15,0.02 -0.22,0.03 -0.07,0.01 -0.15,0.01 -0.23,0.01Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M81.85,81.82v-4.79h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59 0.22,-0.14 0.49,-0.21 0.81,-0.21 0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.24,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.97h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M86.61,81.9c-0.3,0 -0.57,-0.06 -0.82,-0.17 -0.24,-0.12 -0.43,-0.28 -0.57,-0.49 -0.14,-0.21 -0.21,-0.46 -0.21,-0.75v-0.01c0,-0.28 0.07,-0.53 0.2,-0.73 0.14,-0.2 0.33,-0.36 0.59,-0.48 0.26,-0.12 0.58,-0.18 0.95,-0.2l1.76,-0.11v0.62l-1.66,0.11c-0.36,0.02 -0.63,0.1 -0.8,0.23 -0.17,0.13 -0.25,0.31 -0.25,0.55v0.01c0,0.24 0.09,0.43 0.28,0.57 0.18,0.13 0.41,0.2 0.69,0.2 0.26,0 0.5,-0.05 0.7,-0.16 0.2,-0.11 0.36,-0.25 0.48,-0.43 0.12,-0.18 0.18,-0.38 0.18,-0.61v-1.49c0,-0.3 -0.09,-0.52 -0.27,-0.67 -0.18,-0.16 -0.45,-0.24 -0.8,-0.24 -0.29,0 -0.52,0.05 -0.71,0.16 -0.18,0.1 -0.31,0.24 -0.37,0.43l-0,0.01h-0.77l0,-0.03c0.04,-0.25 0.14,-0.47 0.31,-0.66 0.17,-0.19 0.39,-0.34 0.65,-0.44 0.27,-0.11 0.57,-0.16 0.91,-0.16 0.39,0 0.72,0.06 0.99,0.19 0.27,0.13 0.48,0.31 0.62,0.55 0.14,0.24 0.21,0.52 0.21,0.85v3.28h-0.77v-0.71h-0.07c-0.1,0.17 -0.22,0.31 -0.37,0.43 -0.14,0.12 -0.3,0.21 -0.48,0.27 -0.18,0.06 -0.38,0.09 -0.59,0.09Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M92.24,81.9c-0.45,0 -0.83,-0.1 -1.16,-0.31s-0.58,-0.49 -0.76,-0.87c-0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.5 0.09,-0.93 0.27,-1.3 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.31 1.16,-0.31 0.39,0 0.72,0.07 1,0.2 0.28,0.14 0.51,0.32 0.67,0.55 0.17,0.23 0.28,0.48 0.32,0.77l0,0.03h-0.77l-0,-0.01c-0.06,-0.24 -0.19,-0.44 -0.4,-0.6 -0.21,-0.17 -0.49,-0.25 -0.83,-0.25 -0.29,0 -0.54,0.07 -0.75,0.22 -0.21,0.14 -0.37,0.35 -0.49,0.62 -0.11,0.26 -0.17,0.58 -0.17,0.94v0.01c0,0.37 0.06,0.69 0.17,0.96 0.12,0.27 0.28,0.48 0.49,0.63 0.21,0.15 0.46,0.22 0.74,0.22 0.32,0 0.59,-0.07 0.79,-0.21 0.2,-0.14 0.35,-0.34 0.44,-0.61l0.01,-0.03 0.76,-0 -0.01,0.05c-0.07,0.29 -0.18,0.54 -0.35,0.77 -0.17,0.22 -0.38,0.4 -0.66,0.52 -0.27,0.13 -0.6,0.19 -0.99,0.19Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M95.4,81.82v-6.69h0.77v6.69h-0.77ZM98.41,81.82l-1.87,-2.34 0.57,-0.49 2.27,2.84h-0.97ZM96.07,80.1l-0.04,-0.97h0.2l2.07,-2.09h0.94l-2.27,2.19 -0.19,0.18 -0.71,0.69Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M102,81.9c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.32,-0.2 -0.58,-0.49 -0.75,-0.85 -0.17,-0.37 -0.26,-0.8 -0.26,-1.3v-0c0,-0.49 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.87 0.32,-0.21 0.7,-0.32 1.13,-0.32 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.78 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.12 -0.36,0.31 -0.48,0.55 -0.12,0.25 -0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.87 0.12,0.24 0.28,0.42 0.49,0.55 0.21,0.13 0.47,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23 0.1,-0.09 0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.47 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.23,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M105.22,81.82v-4.79h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59 0.22,-0.14 0.49,-0.21 0.81,-0.21 0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.23,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.97h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M110.21,81.9c-0.35,0 -0.67,-0.05 -0.94,-0.16 -0.27,-0.11 -0.49,-0.26 -0.66,-0.46 -0.16,-0.2 -0.26,-0.42 -0.29,-0.69h0.79c0.06,0.2 0.19,0.36 0.38,0.48 0.19,0.12 0.44,0.18 0.74,0.18 0.22,0 0.41,-0.03 0.57,-0.09 0.17,-0.07 0.3,-0.15 0.39,-0.26 0.09,-0.11 0.14,-0.24 0.14,-0.39v-0.01c0,-0.16 -0.06,-0.3 -0.19,-0.41 -0.13,-0.12 -0.34,-0.21 -0.64,-0.28l-0.74,-0.18c-0.3,-0.07 -0.54,-0.16 -0.74,-0.28 -0.19,-0.12 -0.33,-0.26 -0.43,-0.42 -0.09,-0.17 -0.14,-0.37 -0.14,-0.59v-0c0,-0.27 0.08,-0.5 0.23,-0.71 0.16,-0.21 0.37,-0.38 0.64,-0.5 0.27,-0.12 0.57,-0.18 0.91,-0.18 0.34,0 0.63,0.05 0.89,0.16 0.26,0.1 0.47,0.25 0.63,0.44 0.16,0.19 0.26,0.42 0.29,0.68h-0.76c-0.05,-0.19 -0.17,-0.34 -0.35,-0.46 -0.18,-0.12 -0.42,-0.18 -0.71,-0.18 -0.19,0 -0.36,0.03 -0.51,0.09 -0.15,0.06 -0.26,0.14 -0.35,0.25 -0.09,0.11 -0.13,0.23 -0.13,0.37v0.01c0,0.11 0.03,0.2 0.08,0.28s0.14,0.16 0.26,0.22c0.12,0.06 0.27,0.12 0.46,0.16l0.74,0.18c0.45,0.11 0.78,0.27 1,0.47 0.22,0.2 0.33,0.48 0.33,0.82v0.01c0,0.28 -0.08,0.54 -0.25,0.75 -0.17,0.22 -0.4,0.38 -0.69,0.51 -0.29,0.12 -0.61,0.18 -0.98,0.18Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M17.58,111.52v-0.71h1.98c0.48,0 0.85,-0.1 1.1,-0.29 0.25,-0.19 0.37,-0.47 0.37,-0.84v-0.01c0,-0.25 -0.06,-0.45 -0.17,-0.62s-0.29,-0.29 -0.52,-0.37c-0.23,-0.08 -0.51,-0.12 -0.85,-0.12h-1.9v-0.69h1.68c0.49,0 0.85,-0.09 1.09,-0.26 0.25,-0.17 0.37,-0.43 0.37,-0.76v-0.01c0,-0.33 -0.11,-0.58 -0.33,-0.75 -0.22,-0.18 -0.53,-0.27 -0.92,-0.27h-1.88v-0.7h2.05c0.39,0 0.73,0.06 1.01,0.19 0.28,0.13 0.5,0.31 0.65,0.56 0.15,0.24 0.23,0.52 0.23,0.84v0.01c0,0.22 -0.05,0.43 -0.15,0.63 -0.1,0.19 -0.23,0.36 -0.4,0.49 -0.17,0.13 -0.35,0.22 -0.56,0.26v0.07c0.29,0.04 0.55,0.12 0.76,0.26 0.21,0.14 0.38,0.32 0.49,0.54 0.12,0.22 0.18,0.47 0.18,0.75v0.01c0,0.37 -0.09,0.69 -0.26,0.96 -0.17,0.27 -0.42,0.47 -0.74,0.62 -0.32,0.14 -0.71,0.21 -1.17,0.21h-2.1ZM17.18,111.52v-6.41h0.8v6.41h-0.8Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M23.04,111.52v-4.78h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59s0.49,-0.21 0.81,-0.21c0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.24,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.96h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M28.31,111.6c-0.45,0 -0.84,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.76,-0.86 -0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.51 0.09,-0.95 0.27,-1.32 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.3 1.18,-0.3 0.46,0 0.85,0.1 1.18,0.3s0.58,0.48 0.76,0.85c0.18,0.37 0.27,0.81 0.27,1.32v0.01c0,0.51 -0.09,0.95 -0.27,1.32 -0.18,0.37 -0.43,0.66 -0.76,0.86 -0.33,0.2 -0.72,0.3 -1.18,0.3ZM28.31,110.92c0.3,0 0.56,-0.07 0.77,-0.21 0.21,-0.14 0.37,-0.35 0.48,-0.61 0.11,-0.27 0.17,-0.59 0.17,-0.96v-0.01c0,-0.38 -0.06,-0.7 -0.17,-0.97 -0.11,-0.27 -0.27,-0.47 -0.48,-0.61 -0.21,-0.14 -0.47,-0.21 -0.77,-0.21 -0.3,0 -0.56,0.07 -0.77,0.21 -0.21,0.14 -0.37,0.34 -0.48,0.61 -0.11,0.27 -0.16,0.59 -0.16,0.97v0.01c0,0.38 0.05,0.7 0.16,0.96 0.11,0.27 0.27,0.47 0.48,0.61 0.21,0.14 0.47,0.21 0.77,0.21Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M32.44,111.52l-1.34,-4.78h0.77l0.94,3.83h0.07l1.07,-3.83h0.73l1.07,3.83h0.07l0.94,-3.83h0.77l-1.34,4.78h-0.78l-1.07,-3.7h-0.07l-1.07,3.7h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M40.05,111.6c-0.36,0 -0.67,-0.05 -0.94,-0.16 -0.27,-0.11 -0.49,-0.26 -0.66,-0.46 -0.16,-0.19 -0.26,-0.42 -0.29,-0.69h0.79c0.07,0.2 0.19,0.36 0.38,0.48 0.19,0.12 0.44,0.18 0.74,0.18 0.22,0 0.41,-0.03 0.57,-0.09 0.17,-0.06 0.3,-0.15 0.39,-0.26 0.09,-0.11 0.14,-0.24 0.14,-0.39v-0.01c0,-0.16 -0.07,-0.3 -0.2,-0.41 -0.13,-0.12 -0.34,-0.21 -0.64,-0.28l-0.74,-0.18c-0.3,-0.07 -0.54,-0.16 -0.74,-0.28 -0.19,-0.12 -0.33,-0.26 -0.43,-0.42 -0.09,-0.17 -0.14,-0.37 -0.14,-0.6v-0c0,-0.27 0.08,-0.5 0.23,-0.71 0.16,-0.21 0.37,-0.38 0.64,-0.5 0.27,-0.12 0.57,-0.18 0.91,-0.18 0.33,0 0.63,0.05 0.89,0.16 0.26,0.1 0.47,0.25 0.63,0.44 0.16,0.19 0.26,0.42 0.29,0.68h-0.76c-0.05,-0.19 -0.17,-0.34 -0.35,-0.46 -0.18,-0.12 -0.42,-0.18 -0.71,-0.18 -0.19,0 -0.36,0.03 -0.51,0.09 -0.15,0.06 -0.26,0.14 -0.35,0.25 -0.09,0.11 -0.13,0.23 -0.13,0.37v0.01c0,0.11 0.03,0.2 0.08,0.28 0.06,0.08 0.14,0.16 0.26,0.22 0.12,0.06 0.27,0.12 0.46,0.17l0.74,0.18c0.45,0.11 0.78,0.27 1,0.47 0.22,0.2 0.33,0.48 0.33,0.82v0.01c0,0.28 -0.08,0.54 -0.25,0.75 -0.17,0.22 -0.4,0.38 -0.69,0.51 -0.29,0.12 -0.61,0.18 -0.98,0.18Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M45.09,111.6c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.48 -0.75,-0.85 -0.17,-0.37 -0.26,-0.81 -0.26,-1.3v-0c0,-0.49 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.87 0.32,-0.21 0.7,-0.32 1.13,-0.32 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.77 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.13 -0.36,0.31 -0.48,0.56 -0.12,0.25 -0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.88 0.12,0.24 0.28,0.42 0.49,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23 0.1,-0.09 0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.47 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.22,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M48.31,111.52v-4.78h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59s0.49,-0.21 0.81,-0.21c0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.24,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.96h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M56.24,111.6c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.48 -0.75,-0.85 -0.17,-0.37 -0.26,-0.81 -0.26,-1.3v-0c0,-0.49 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.87 0.32,-0.21 0.7,-0.32 1.13,-0.32 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.77 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18s-0.49,0.06 -0.69,0.19c-0.2,0.13 -0.36,0.31 -0.48,0.56 -0.12,0.25 -0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.88 0.12,0.24 0.28,0.42 0.49,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23 0.1,-0.09 0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.47 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.22,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M58.9,111.52l1.64,-2.39 -1.66,-2.39h0.91l1.14,1.78h0.07l1.12,-1.78h0.87l-1.62,2.36 1.65,2.42h-0.91l-1.13,-1.81h-0.07l-1.14,1.81h-0.87Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M65.73,111.55c-0.49,0 -0.85,-0.1 -1.07,-0.3 -0.22,-0.2 -0.33,-0.52 -0.33,-0.98v-2.9h-0.75v-0.64h0.75v-1.24h0.8v1.24h1.05v0.64h-1.05v2.71c0,0.28 0.05,0.48 0.16,0.61 0.11,0.12 0.28,0.18 0.53,0.18 0.07,0 0.13,-0 0.17,-0 0.05,-0 0.11,-0.01 0.18,-0.01v0.66c-0.07,0.01 -0.15,0.02 -0.22,0.03 -0.07,0.01 -0.15,0.01 -0.23,0.01Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M69.21,111.6c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.48 -0.75,-0.85 -0.17,-0.37 -0.26,-0.81 -0.26,-1.3v-0c0,-0.49 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.87 0.32,-0.21 0.7,-0.32 1.13,-0.32 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.77 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.13 -0.36,0.31 -0.48,0.56 -0.12,0.25 -0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.88 0.12,0.24 0.28,0.42 0.49,0.55 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23s0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.47 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.22,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M72.43,111.52v-4.78h0.77v0.72h0.07c0.12,-0.25 0.3,-0.45 0.52,-0.59 0.23,-0.14 0.52,-0.21 0.87,-0.21 0.54,0 0.95,0.15 1.24,0.46 0.29,0.31 0.44,0.74 0.44,1.31v3.1h-0.77v-2.91c0,-0.43 -0.09,-0.75 -0.28,-0.96 -0.18,-0.21 -0.46,-0.31 -0.84,-0.31 -0.25,0 -0.47,0.05 -0.66,0.16 -0.19,0.11 -0.33,0.26 -0.44,0.47 -0.1,0.2 -0.15,0.44 -0.15,0.72v2.83h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M79.36,111.6c-0.36,0 -0.67,-0.05 -0.94,-0.16 -0.27,-0.11 -0.49,-0.26 -0.66,-0.46 -0.16,-0.19 -0.26,-0.42 -0.29,-0.69h0.79c0.07,0.2 0.19,0.36 0.38,0.48 0.19,0.12 0.44,0.18 0.74,0.18 0.22,0 0.41,-0.03 0.57,-0.09 0.17,-0.06 0.3,-0.15 0.39,-0.26 0.09,-0.11 0.14,-0.24 0.14,-0.39v-0.01c0,-0.16 -0.07,-0.3 -0.2,-0.41 -0.13,-0.12 -0.34,-0.21 -0.64,-0.28l-0.74,-0.18c-0.3,-0.07 -0.54,-0.16 -0.74,-0.28 -0.19,-0.12 -0.33,-0.26 -0.43,-0.42 -0.09,-0.17 -0.14,-0.37 -0.14,-0.6v-0c0,-0.27 0.08,-0.5 0.23,-0.71 0.16,-0.21 0.37,-0.38 0.64,-0.5 0.27,-0.12 0.57,-0.18 0.91,-0.18 0.33,0 0.63,0.05 0.89,0.16 0.26,0.1 0.47,0.25 0.63,0.44 0.16,0.19 0.26,0.42 0.29,0.68h-0.76c-0.05,-0.19 -0.17,-0.34 -0.35,-0.46 -0.18,-0.12 -0.42,-0.18 -0.71,-0.18 -0.19,0 -0.36,0.03 -0.51,0.09 -0.15,0.06 -0.26,0.14 -0.35,0.25 -0.09,0.11 -0.13,0.23 -0.13,0.37v0.01c0,0.11 0.03,0.2 0.08,0.28 0.06,0.08 0.14,0.16 0.26,0.22 0.12,0.06 0.27,0.12 0.46,0.17l0.74,0.18c0.45,0.11 0.78,0.27 1,0.47 0.22,0.2 0.33,0.48 0.33,0.82v0.01c0,0.28 -0.08,0.54 -0.25,0.75 -0.17,0.22 -0.4,0.38 -0.69,0.51 -0.29,0.12 -0.61,0.18 -0.98,0.18Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M82.47,111.52v-4.78h0.77v4.78h-0.77ZM82.86,105.81c-0.14,0 -0.27,-0.05 -0.38,-0.16 -0.1,-0.11 -0.16,-0.23 -0.16,-0.38 0,-0.15 0.05,-0.27 0.16,-0.38 0.11,-0.1 0.23,-0.16 0.38,-0.16 0.15,0 0.27,0.05 0.38,0.16 0.1,0.1 0.16,0.23 0.16,0.38 0,0.14 -0.05,0.27 -0.16,0.38 -0.1,0.1 -0.23,0.16 -0.38,0.16Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M86.64,111.6c-0.45,0 -0.84,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.76,-0.86 -0.18,-0.37 -0.27,-0.81 -0.27,-1.32v-0.01c0,-0.51 0.09,-0.95 0.27,-1.32 0.18,-0.37 0.44,-0.65 0.76,-0.85 0.33,-0.2 0.72,-0.3 1.18,-0.3 0.46,0 0.85,0.1 1.18,0.3 0.33,0.2 0.58,0.48 0.76,0.85 0.18,0.37 0.27,0.81 0.27,1.32v0.01c0,0.51 -0.09,0.95 -0.27,1.32 -0.18,0.37 -0.43,0.66 -0.76,0.86 -0.33,0.2 -0.72,0.3 -1.18,0.3ZM86.64,110.92c0.3,0 0.56,-0.07 0.77,-0.21 0.21,-0.14 0.37,-0.35 0.48,-0.61 0.11,-0.27 0.17,-0.59 0.17,-0.96v-0.01c0,-0.38 -0.06,-0.7 -0.17,-0.97 -0.11,-0.27 -0.27,-0.47 -0.48,-0.61 -0.21,-0.14 -0.47,-0.21 -0.77,-0.21 -0.3,0 -0.56,0.07 -0.77,0.21 -0.21,0.14 -0.37,0.34 -0.48,0.61 -0.11,0.27 -0.16,0.59 -0.16,0.97v0.01c0,0.38 0.05,0.7 0.16,0.96 0.11,0.27 0.27,0.47 0.48,0.61 0.21,0.14 0.47,0.21 0.77,0.21Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M90.03,111.52v-4.78h0.77v0.72h0.07c0.12,-0.25 0.3,-0.45 0.52,-0.59 0.23,-0.14 0.52,-0.21 0.87,-0.21 0.54,0 0.95,0.15 1.24,0.46 0.29,0.31 0.44,0.74 0.44,1.31v3.1h-0.77v-2.91c0,-0.43 -0.09,-0.75 -0.27,-0.96 -0.18,-0.21 -0.46,-0.31 -0.84,-0.31 -0.25,0 -0.47,0.05 -0.66,0.16 -0.19,0.11 -0.33,0.26 -0.44,0.47 -0.1,0.2 -0.15,0.44 -0.15,0.72v2.83h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M96.96,111.6c-0.36,0 -0.67,-0.05 -0.94,-0.16 -0.27,-0.11 -0.49,-0.26 -0.66,-0.46 -0.16,-0.19 -0.26,-0.42 -0.29,-0.69h0.79c0.06,0.2 0.19,0.36 0.38,0.48 0.19,0.12 0.44,0.18 0.74,0.18 0.22,0 0.41,-0.03 0.57,-0.09 0.17,-0.06 0.3,-0.15 0.39,-0.26 0.09,-0.11 0.14,-0.24 0.14,-0.39v-0.01c0,-0.16 -0.06,-0.3 -0.19,-0.41 -0.13,-0.12 -0.34,-0.21 -0.64,-0.28l-0.74,-0.18c-0.3,-0.07 -0.54,-0.16 -0.74,-0.28 -0.19,-0.12 -0.33,-0.26 -0.43,-0.42 -0.09,-0.17 -0.14,-0.37 -0.14,-0.6v-0c0,-0.27 0.08,-0.5 0.23,-0.71 0.16,-0.21 0.37,-0.38 0.64,-0.5 0.27,-0.12 0.57,-0.18 0.91,-0.18 0.33,0 0.63,0.05 0.89,0.16 0.26,0.1 0.47,0.25 0.63,0.44 0.16,0.19 0.26,0.42 0.29,0.68h-0.76c-0.05,-0.19 -0.17,-0.34 -0.35,-0.46 -0.18,-0.12 -0.42,-0.18 -0.71,-0.18 -0.19,0 -0.36,0.03 -0.51,0.09 -0.15,0.06 -0.26,0.14 -0.35,0.25 -0.09,0.11 -0.13,0.23 -0.13,0.37v0.01c0,0.11 0.03,0.2 0.08,0.28s0.14,0.16 0.26,0.22c0.12,0.06 0.27,0.12 0.46,0.17l0.74,0.18c0.45,0.11 0.78,0.27 1,0.47 0.22,0.2 0.33,0.48 0.33,0.82v0.01c0,0.28 -0.08,0.54 -0.25,0.75 -0.17,0.22 -0.4,0.38 -0.69,0.51 -0.29,0.12 -0.61,0.18 -0.98,0.18Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M18.19,140.61v-0.71h1.98c0.48,0 0.85,-0.1 1.1,-0.29 0.25,-0.19 0.37,-0.47 0.37,-0.84v-0.01c0,-0.25 -0.06,-0.45 -0.17,-0.62 -0.12,-0.17 -0.29,-0.29 -0.52,-0.37 -0.23,-0.08 -0.51,-0.13 -0.85,-0.13h-1.9v-0.69h1.68c0.49,0 0.85,-0.08 1.09,-0.26 0.25,-0.17 0.37,-0.43 0.37,-0.76v-0.01c0,-0.33 -0.11,-0.58 -0.33,-0.75 -0.22,-0.18 -0.53,-0.27 -0.92,-0.27h-1.88v-0.71h2.05c0.39,0 0.73,0.07 1.01,0.2 0.28,0.13 0.5,0.31 0.65,0.56 0.15,0.24 0.23,0.52 0.23,0.84v0.01c0,0.22 -0.05,0.43 -0.15,0.63 -0.1,0.2 -0.23,0.36 -0.4,0.49 -0.17,0.13 -0.35,0.22 -0.56,0.26v0.07c0.29,0.04 0.55,0.12 0.76,0.26 0.21,0.14 0.38,0.32 0.49,0.54 0.12,0.22 0.18,0.47 0.18,0.75v0.01c0,0.37 -0.09,0.69 -0.26,0.96 -0.17,0.27 -0.42,0.47 -0.74,0.62 -0.32,0.14 -0.71,0.21 -1.17,0.21h-2.1ZM17.79,140.61v-6.41h0.8v6.41h-0.8Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M25.25,140.69c-0.36,0 -0.66,-0.07 -0.91,-0.2 -0.25,-0.14 -0.43,-0.34 -0.55,-0.6 -0.12,-0.27 -0.18,-0.59 -0.18,-0.96v-3.1h0.77v2.91c0,0.43 0.08,0.75 0.25,0.96 0.17,0.21 0.44,0.32 0.83,0.32 0.21,0 0.4,-0.03 0.55,-0.09 0.16,-0.06 0.3,-0.15 0.41,-0.27 0.11,-0.12 0.19,-0.26 0.24,-0.43 0.06,-0.17 0.08,-0.36 0.08,-0.57v-2.83h0.77v4.78h-0.77v-0.71h-0.07c-0.08,0.17 -0.18,0.31 -0.32,0.44 -0.13,0.12 -0.29,0.21 -0.48,0.27 -0.18,0.06 -0.39,0.09 -0.63,0.09Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M28.95,140.61v-4.78h0.77v4.78h-0.77ZM29.34,134.9c-0.15,0 -0.27,-0.05 -0.38,-0.16 -0.1,-0.11 -0.16,-0.23 -0.16,-0.38 0,-0.15 0.05,-0.27 0.16,-0.38 0.11,-0.1 0.23,-0.16 0.38,-0.16 0.15,0 0.27,0.05 0.38,0.16 0.1,0.1 0.16,0.23 0.16,0.38 0,0.14 -0.05,0.27 -0.16,0.38 -0.1,0.1 -0.23,0.16 -0.38,0.16Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M31.2,140.61v-6.68h0.77v6.68h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M35.14,140.64c-0.49,0 -0.85,-0.1 -1.07,-0.3 -0.22,-0.2 -0.33,-0.52 -0.33,-0.98v-2.9h-0.75v-0.64h0.75v-1.24h0.8v1.24h1.05v0.64h-1.05v2.71c0,0.28 0.05,0.48 0.16,0.61 0.11,0.12 0.28,0.18 0.53,0.18 0.07,0 0.13,-0 0.17,-0 0.05,-0 0.11,-0.01 0.18,-0.01v0.66c-0.07,0.01 -0.15,0.02 -0.22,0.03s-0.15,0.01 -0.23,0.01Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M36.47,138.39v-0.72h2.98v0.72h-2.98Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M40.82,140.61v-4.78h0.77v4.78h-0.77ZM41.21,134.9c-0.14,0 -0.27,-0.05 -0.38,-0.16 -0.1,-0.11 -0.16,-0.23 -0.16,-0.38 0,-0.15 0.05,-0.27 0.16,-0.38 0.11,-0.1 0.23,-0.16 0.38,-0.16 0.15,0 0.27,0.05 0.38,0.16 0.1,0.1 0.16,0.23 0.16,0.38 0,0.14 -0.05,0.27 -0.16,0.38 -0.1,0.1 -0.23,0.16 -0.38,0.16Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M43.03,140.61v-4.78h0.77v0.72h0.07c0.12,-0.25 0.3,-0.45 0.52,-0.59 0.23,-0.14 0.52,-0.21 0.87,-0.21 0.54,0 0.95,0.15 1.24,0.46 0.29,0.31 0.44,0.74 0.44,1.31v3.1h-0.77v-2.91c0,-0.43 -0.09,-0.75 -0.28,-0.96 -0.18,-0.21 -0.46,-0.31 -0.84,-0.31 -0.25,0 -0.47,0.06 -0.66,0.16 -0.19,0.11 -0.33,0.26 -0.44,0.47 -0.1,0.2 -0.15,0.44 -0.15,0.72v2.83h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M51.35,138.32v-0.71h1.81c0.46,0 0.81,-0.12 1.07,-0.36 0.25,-0.24 0.38,-0.57 0.38,-0.99v-0.01c0,-0.42 -0.13,-0.75 -0.38,-0.99 -0.25,-0.24 -0.61,-0.36 -1.07,-0.36h-1.81v-0.71h2.02c0.4,0 0.76,0.09 1.07,0.26 0.31,0.17 0.55,0.41 0.72,0.72 0.18,0.31 0.27,0.66 0.27,1.07v0.01c0,0.41 -0.09,0.76 -0.27,1.07 -0.17,0.31 -0.42,0.55 -0.72,0.73 -0.31,0.17 -0.66,0.26 -1.07,0.26h-2.02ZM50.95,140.61v-6.41h0.8v6.41h-0.8Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M56.71,140.61v-6.41h2.2c0.63,0 1.17,0.13 1.62,0.38 0.45,0.25 0.8,0.62 1.04,1.09 0.24,0.48 0.36,1.05 0.36,1.72v0.01c0,0.67 -0.12,1.25 -0.36,1.73 -0.24,0.48 -0.58,0.84 -1.03,1.1 -0.45,0.25 -0.99,0.38 -1.63,0.38h-2.2ZM57.51,139.89h1.35c0.48,0 0.88,-0.1 1.22,-0.29 0.34,-0.2 0.59,-0.48 0.77,-0.85 0.18,-0.37 0.27,-0.81 0.27,-1.33v-0.01c0,-0.52 -0.09,-0.97 -0.27,-1.34 -0.18,-0.37 -0.44,-0.66 -0.77,-0.85 -0.34,-0.2 -0.74,-0.3 -1.22,-0.3h-1.35v4.97Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M63.3,140.61v-6.41h3.89v0.72h-3.09v2.2h2.84v0.71h-2.84v2.78h-0.8Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M70.92,140.61v-4.78h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59 0.22,-0.14 0.49,-0.21 0.81,-0.21 0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.24,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.96h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M76.18,140.69c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.75,-0.85 -0.17,-0.37 -0.26,-0.8 -0.26,-1.3v-0c0,-0.5 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.88 0.32,-0.21 0.7,-0.31 1.13,-0.31 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.77 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18 -0.26,0 -0.49,0.06 -0.69,0.19 -0.2,0.12 -0.36,0.31 -0.48,0.55 -0.12,0.25 -0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.87 0.12,0.24 0.28,0.43 0.49,0.56 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23 0.1,-0.09 0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.48 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.22,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M80.71,140.69c-0.3,0 -0.57,-0.06 -0.82,-0.17 -0.24,-0.11 -0.43,-0.28 -0.57,-0.49 -0.14,-0.21 -0.21,-0.46 -0.21,-0.75v-0.01c0,-0.28 0.07,-0.53 0.2,-0.73 0.14,-0.2 0.33,-0.36 0.59,-0.48 0.26,-0.11 0.58,-0.18 0.95,-0.2l1.76,-0.11v0.62l-1.66,0.11c-0.36,0.02 -0.63,0.1 -0.8,0.23 -0.17,0.13 -0.25,0.31 -0.25,0.55v0.01c0,0.24 0.09,0.43 0.28,0.57 0.18,0.13 0.41,0.2 0.69,0.2 0.26,0 0.5,-0.05 0.7,-0.16 0.2,-0.11 0.36,-0.25 0.48,-0.43 0.12,-0.18 0.18,-0.39 0.18,-0.61v-1.49c0,-0.3 -0.09,-0.52 -0.27,-0.68 -0.18,-0.16 -0.45,-0.23 -0.8,-0.23 -0.29,0 -0.52,0.05 -0.71,0.16 -0.18,0.1 -0.31,0.24 -0.37,0.43l-0,0.01h-0.77l0,-0.03c0.04,-0.25 0.14,-0.47 0.31,-0.66 0.17,-0.19 0.39,-0.34 0.65,-0.44 0.27,-0.11 0.57,-0.16 0.91,-0.16 0.39,0 0.72,0.06 0.99,0.19 0.27,0.13 0.48,0.31 0.62,0.55 0.14,0.24 0.21,0.52 0.21,0.85v3.28h-0.77v-0.71h-0.07c-0.1,0.17 -0.22,0.31 -0.37,0.43 -0.14,0.12 -0.3,0.21 -0.48,0.27 -0.18,0.06 -0.38,0.09 -0.59,0.09Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M86.16,140.69c-0.4,0 -0.75,-0.1 -1.06,-0.31 -0.3,-0.2 -0.54,-0.49 -0.7,-0.86 -0.17,-0.37 -0.25,-0.81 -0.25,-1.3v-0.01c0,-0.5 0.08,-0.94 0.25,-1.3 0.17,-0.37 0.4,-0.66 0.7,-0.86 0.3,-0.2 0.66,-0.31 1.06,-0.31 0.22,0 0.42,0.04 0.62,0.11 0.2,0.07 0.37,0.16 0.52,0.29 0.15,0.13 0.27,0.27 0.36,0.44h0.07v-2.65h0.77v6.68h-0.77v-0.76h-0.07c-0.1,0.18 -0.22,0.33 -0.37,0.46 -0.15,0.13 -0.32,0.22 -0.51,0.29 -0.19,0.07 -0.4,0.1 -0.62,0.1ZM86.34,140.01c0.29,0 0.54,-0.07 0.75,-0.22s0.37,-0.35 0.48,-0.62c0.11,-0.27 0.17,-0.59 0.17,-0.95v-0.01c0,-0.37 -0.06,-0.69 -0.17,-0.95 -0.11,-0.27 -0.27,-0.47 -0.48,-0.62 -0.21,-0.14 -0.46,-0.22 -0.75,-0.22s-0.54,0.07 -0.75,0.22c-0.21,0.14 -0.37,0.35 -0.48,0.61 -0.11,0.27 -0.16,0.59 -0.16,0.96v0.01c0,0.37 0.05,0.69 0.16,0.96 0.11,0.27 0.27,0.47 0.48,0.62 0.21,0.14 0.46,0.21 0.75,0.21Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M91.91,140.69c-0.46,0 -0.85,-0.1 -1.18,-0.3 -0.33,-0.2 -0.58,-0.49 -0.75,-0.85 -0.17,-0.37 -0.26,-0.8 -0.26,-1.3v-0c0,-0.5 0.09,-0.93 0.26,-1.3 0.18,-0.37 0.43,-0.66 0.75,-0.88 0.32,-0.21 0.7,-0.31 1.13,-0.31 0.44,0 0.81,0.1 1.12,0.3 0.31,0.2 0.55,0.48 0.72,0.84 0.17,0.36 0.25,0.77 0.25,1.25v0.3h-3.84v-0.62h3.44l-0.38,0.56v-0.31c0,-0.38 -0.06,-0.69 -0.17,-0.93 -0.11,-0.24 -0.27,-0.42 -0.47,-0.54 -0.2,-0.12 -0.43,-0.18 -0.68,-0.18s-0.49,0.06 -0.69,0.19c-0.2,0.12 -0.36,0.31 -0.48,0.55s-0.18,0.55 -0.18,0.91v0.31c0,0.34 0.06,0.63 0.17,0.87 0.12,0.24 0.28,0.43 0.49,0.56 0.21,0.13 0.46,0.19 0.75,0.19 0.22,0 0.4,-0.03 0.56,-0.09 0.16,-0.06 0.29,-0.13 0.4,-0.23 0.1,-0.09 0.18,-0.19 0.22,-0.28l0.02,-0.04h0.77l-0.01,0.04c-0.04,0.16 -0.12,0.32 -0.22,0.48 -0.1,0.15 -0.24,0.29 -0.4,0.41 -0.17,0.12 -0.36,0.22 -0.59,0.29 -0.22,0.07 -0.48,0.11 -0.76,0.11Z" android:strokeWidth="0"/> - - <path android:fillColor="#5b5b66" android:pathData="M95.13,140.61v-4.78h0.77v0.71h0.07c0.09,-0.25 0.25,-0.45 0.47,-0.59 0.22,-0.14 0.49,-0.21 0.81,-0.21 0.07,0 0.15,0 0.22,0.01 0.07,0.01 0.13,0.01 0.17,0.02v0.75c-0.08,-0.01 -0.16,-0.03 -0.23,-0.03 -0.07,-0.01 -0.15,-0.01 -0.24,-0.01 -0.25,0 -0.46,0.05 -0.65,0.15 -0.19,0.1 -0.34,0.23 -0.45,0.41 -0.11,0.17 -0.16,0.38 -0.16,0.61v2.96h-0.77Z" android:strokeWidth="0"/> - - <path android:fillColor="#00000000" android:pathData="M126.97,30.91v124.85M159.09,30.91v124.85M192.73,60.91H7.27M192.73,94.14H7.27M192.73,121.96H7.27" android:strokeColor="#ededf0" android:strokeWidth="1"/> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M149.7,74.77l-7.04,7.04c-0.1,0.1 -0.23,0.16 -0.38,0.16 -0.14,0 -0.28,-0.06 -0.38,-0.16l-4.33,-4.33 0.75,-0.75 3.96,3.96 6.66,-6.67 0.75,0.75Z" android:strokeWidth="0"/> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M149.7,104.87l-7.04,7.04c-0.1,0.1 -0.23,0.16 -0.38,0.16 -0.14,0 -0.28,-0.06 -0.38,-0.16l-4.33,-4.33 0.75,-0.75 3.96,3.96 6.66,-6.67 0.75,0.75Z" android:strokeWidth="0"/> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M149.7,135.16l-7.04,7.04c-0.1,0.1 -0.23,0.16 -0.38,0.16 -0.14,0 -0.28,-0.06 -0.38,-0.16l-4.33,-4.33 0.75,-0.75 3.96,3.96 6.66,-6.67 0.75,0.75Z" android:strokeWidth="0"/> - - <path android:fillColor="#000000" android:pathData="M176.53,76.97l3.59,-3.59 -0.77,-0.77 -3.59,3.59 -3.59,-3.59 -0.77,0.77 3.59,3.59 -3.59,3.59 0.77,0.77 3.59,-3.59 3.59,3.59 0.77,-0.77 -3.59,-3.59Z" android:strokeWidth="0"/> - - <path android:fillColor="#000000" android:pathData="M176.53,108.24l3.59,-3.59 -0.77,-0.77 -3.59,3.59 -3.59,-3.59 -0.77,0.77 3.59,3.59 -3.59,3.59 0.77,0.77 3.59,-3.59 3.59,3.59 0.77,-0.77 -3.59,-3.59Z" android:strokeWidth="0"/> - - <path android:fillColor="#000000" android:pathData="M176.53,138.53l3.59,-3.59 -0.77,-0.77 -3.59,3.59 -3.59,-3.59 -0.77,0.77 3.59,3.59 -3.59,3.59 0.77,0.77 3.59,-3.59 3.59,3.59 0.77,-0.77 -3.59,-3.59Z" android:strokeWidth="0"/> - - <path android:pathData="M150.46,43.2c-0.33,-0.79 -0.99,-1.63 -1.51,-1.9 0.42,0.83 0.67,1.66 0.76,2.28 0,0 0,0 0,0.01 -0.85,-2.12 -2.29,-2.97 -3.46,-4.83 -0.06,-0.09 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.08,-0.16 -0.05,-0.09 -0.09,-0.19 -0.11,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0,0 0,-0 0,-0 0,-0 -1.89,1.1 -2.53,3.15 -2.59,4.17 -0.75,0.05 -1.47,0.33 -2.07,0.8 -0.06,-0.05 -0.13,-0.1 -0.19,-0.15 -0.17,-0.6 -0.18,-1.23 -0.02,-1.84 -0.77,0.35 -1.37,0.91 -1.81,1.4h-0c-0.3,-0.38 -0.28,-1.62 -0.26,-1.88 -0,-0.02 -0.22,0.11 -0.25,0.13 -0.26,0.19 -0.51,0.4 -0.73,0.63 -0.26,0.26 -0.49,0.54 -0.7,0.84v0,-0c-0.48,0.68 -0.82,1.46 -1.01,2.28 -0,0.02 -0.01,0.03 -0.01,0.05 -0.01,0.07 -0.06,0.4 -0.07,0.47 0,0.01 -0,0.01 -0,0.02 -0.07,0.34 -0.11,0.69 -0.12,1.04 0,0.01 -0,0.03 -0,0.04 0,4.15 3.36,7.51 7.51,7.51 3.72,0 6.8,-2.7 7.4,-6.24 0.01,-0.1 0.02,-0.19 0.03,-0.29 0.15,-1.29 -0.02,-2.64 -0.49,-3.77ZM141.8,49.08c0.04,0.02 0.07,0.04 0.1,0.05 0,0 0,0 0,0 -0.04,-0.02 -0.07,-0.04 -0.11,-0.05ZM149.72,43.59l-0,-0.01c0,0 0,0.01 0,0.01v-0Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="137.21" android:endY="52.22" android:startX="149.27" android:startY="40.59" android:type="linear"> - - <item android:color="#FFFFF44F" android:offset="0.05"/> - - <item android:color="#FFFF980E" android:offset="0.37"/> - - <item android:color="#FFFF3647" android:offset="0.53"/> - - <item android:color="#FFE31587" android:offset="0.7"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M150.46,43.2c-0.33,-0.79 -0.99,-1.63 -1.51,-1.9 0.42,0.83 0.67,1.66 0.76,2.28 0,-0 0,0 0,0.01 0,0 0,0.01 0,0.01 0.71,1.92 0.32,3.87 -0.23,5.07 -0.86,1.85 -2.94,3.74 -6.2,3.65 -3.52,-0.1 -6.63,-2.71 -7.21,-6.14 -0.11,-0.54 0,-0.81 0.05,-1.25 -0.06,0.34 -0.09,0.44 -0.12,1.04 0,0.01 -0,0.03 -0,0.04 0,4.15 3.36,7.51 7.51,7.51 3.72,0 6.8,-2.7 7.4,-6.24 0.01,-0.1 0.02,-0.19 0.03,-0.29 0.15,-1.29 -0.02,-2.64 -0.49,-3.77Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="146.39" android:centerY="39.73" android:gradientRadius="15.36" android:type="radial"> - - <item android:color="#FFFFBD4F" android:offset="0.13"/> - - <item android:color="#FFFF980E" android:offset="0.28"/> - - <item android:color="#FFFF3750" android:offset="0.47"/> - - <item android:color="#FFEB0878" android:offset="0.78"/> - - <item android:color="#FFE50080" android:offset="0.86"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M150.46,43.2c-0.33,-0.79 -0.99,-1.63 -1.51,-1.9 0.42,0.83 0.67,1.66 0.76,2.28 0,-0 0,0 0,0.01 0,0 0,0.01 0,0.01 0.71,1.92 0.32,3.87 -0.23,5.07 -0.86,1.85 -2.94,3.74 -6.2,3.65 -3.52,-0.1 -6.63,-2.71 -7.21,-6.14 -0.11,-0.54 0,-0.81 0.05,-1.25 -0.06,0.34 -0.09,0.44 -0.12,1.04 0,0.01 -0,0.03 -0,0.04 0,4.15 3.36,7.51 7.51,7.51 3.72,0 6.8,-2.7 7.4,-6.24 0.01,-0.1 0.02,-0.19 0.03,-0.29 0.15,-1.29 -0.02,-2.64 -0.49,-3.77Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="141.94" android:centerY="46.18" android:gradientRadius="15.74" android:type="radial"> - - <item android:color="#FF960E18" android:offset="0.3"/> - - <item android:color="#BCB11927" android:offset="0.35"/> - - <item android:color="#56DB293D" android:offset="0.43"/> - - <item android:color="#16F5334B" android:offset="0.5"/> - - <item android:color="#00FF3750" android:offset="0.53"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M146.81,44.08c0.02,0.01 0.03,0.02 0.05,0.03 -0.19,-0.33 -0.42,-0.64 -0.7,-0.91 -2.33,-2.33 -0.61,-5.06 -0.32,-5.2 0,-0 0,-0 0,-0 -1.89,1.1 -2.53,3.15 -2.58,4.17 0.09,-0.01 0.17,-0.01 0.26,-0.01 1.41,0 2.63,0.77 3.29,1.92Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="144.98" android:centerY="37.27" android:gradientRadius="5.04" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.13"/> - - <item android:color="#FFFF980E" android:offset="0.53"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M143.52,44.55c-0.01,0.19 -0.67,0.83 -0.9,0.83 -2.14,0 -2.48,1.29 -2.48,1.29 0.09,1.09 0.85,1.98 1.77,2.46 0.04,0.02 0.08,0.04 0.13,0.06 0.07,0.03 0.15,0.06 0.22,0.09 0.31,0.11 0.64,0.17 0.98,0.19 3.74,0.18 4.47,-4.47 1.77,-5.83 0.69,-0.12 1.41,0.16 1.81,0.44 -0.66,-1.15 -1.88,-1.92 -3.29,-1.92 -0.09,0 -0.18,0.01 -0.26,0.01 -0.75,0.05 -1.47,0.33 -2.07,0.8 0.11,0.1 0.24,0.23 0.52,0.49 0.51,0.5 1.82,1.02 1.82,1.08Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="141.66" android:centerY="50.21" android:gradientRadius="6.67" android:type="radial"> - - <item android:color="#FF3A8EE6" android:offset="0.35"/> - - <item android:color="#FF9059FF" android:offset="0.67"/> - - <item android:color="#FFC139E6" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M143.52,44.55c-0.01,0.19 -0.67,0.83 -0.9,0.83 -2.14,0 -2.48,1.29 -2.48,1.29 0.09,1.09 0.85,1.98 1.77,2.46 0.04,0.02 0.08,0.04 0.13,0.06 0.07,0.03 0.15,0.06 0.22,0.09 0.31,0.11 0.64,0.17 0.98,0.19 3.74,0.18 4.47,-4.47 1.77,-5.83 0.69,-0.12 1.41,0.16 1.81,0.44 -0.66,-1.15 -1.88,-1.92 -3.29,-1.92 -0.09,0 -0.18,0.01 -0.26,0.01 -0.75,0.05 -1.47,0.33 -2.07,0.8 0.11,0.1 0.24,0.23 0.52,0.49 0.51,0.5 1.82,1.02 1.82,1.08Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="142.8" android:centerY="44.57" android:gradientRadius="3.54" android:type="radial"> - - <item android:color="#009059FF" android:offset="0.21"/> - - <item android:color="#996E008B" android:offset="0.97"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M140.84,42.72c0.05,0.03 0.1,0.07 0.16,0.1 -0.17,-0.6 -0.18,-1.23 -0.02,-1.84 -0.77,0.35 -1.37,0.91 -1.81,1.4 0.04,-0 1.13,-0.02 1.67,0.34Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="143.01" android:centerY="39.15" android:gradientRadius="5.3" android:type="radial"> - - <item android:color="#FFFFE226" android:offset="0.1"/> - - <item android:color="#FFFF7139" android:offset="0.79"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M136.07,46.17c0.58,3.42 3.68,6.04 7.21,6.14 3.26,0.09 5.34,-1.8 6.2,-3.65 0.56,-1.19 0.94,-3.15 0.23,-5.07v-0l-0,-0.01c-0,-0.01 -0,-0.01 -0,-0.01 0,0 0,0 0,0.01 0.27,1.74 -0.62,3.42 -2,4.56l-0,0.01c-2.69,2.19 -5.27,1.32 -5.8,0.97 -0.04,-0.02 -0.07,-0.04 -0.11,-0.05 -1.57,-0.75 -2.22,-2.18 -2.08,-3.41 -1.33,0 -1.78,-1.12 -1.78,-1.12 0,0 1.19,-0.85 2.76,-0.11 1.45,0.68 2.82,0.11 2.82,0.11 -0,-0.06 -1.31,-0.58 -1.82,-1.08 -0.27,-0.27 -0.4,-0.4 -0.52,-0.49 -0.06,-0.05 -0.13,-0.1 -0.19,-0.15 -0.05,-0.04 -0.1,-0.07 -0.16,-0.1 -0.55,-0.36 -1.64,-0.34 -1.67,-0.34h-0c-0.3,-0.38 -0.28,-1.62 -0.26,-1.88 -0,-0.02 -0.22,0.11 -0.25,0.13 -0.26,0.19 -0.51,0.4 -0.73,0.63 -0.26,0.26 -0.49,0.54 -0.7,0.84v0,-0c-0.48,0.68 -0.82,1.46 -1.01,2.28 -0,0.02 -0.27,1.18 -0.14,1.79Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="147.85" android:centerY="35.66" android:gradientRadius="25.32" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.11"/> - - <item android:color="#FFFF980E" android:offset="0.46"/> - - <item android:color="#FFFF3647" android:offset="0.72"/> - - <item android:color="#FFE31587" android:offset="0.9"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M146.16,43.21c0.27,0.27 0.51,0.58 0.7,0.91 0.04,0.03 0.08,0.06 0.11,0.09 1.7,1.57 0.81,3.79 0.74,3.95 1.38,-1.14 2.27,-2.82 2,-4.56 -0.85,-2.12 -2.29,-2.97 -3.46,-4.83 -0.06,-0.09 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.08,-0.16 -0.05,-0.09 -0.09,-0.19 -0.11,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0.01,0 -0.29,0.14 -2.01,2.87 0.32,5.2Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="138.45" android:centerY="42.68" android:gradientRadius="8.03" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0"/> - - <item android:color="#FFFF980E" android:offset="0.3"/> - - <item android:color="#FFFF3647" android:offset="0.57"/> - - <item android:color="#FFE31587" android:offset="0.74"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M146.97,44.21c-0.03,-0.03 -0.07,-0.06 -0.11,-0.09 -0.01,-0.01 -0.03,-0.02 -0.05,-0.03 -0.4,-0.28 -1.12,-0.56 -1.81,-0.44 2.7,1.35 1.98,6 -1.77,5.83 -0.33,-0.01 -0.66,-0.08 -0.98,-0.19 -0.07,-0.03 -0.15,-0.06 -0.22,-0.09 -0.04,-0.02 -0.08,-0.04 -0.13,-0.06 0,0 0,0 0,0 0.52,0.36 3.1,1.23 5.8,-0.97l0,-0.01c0.07,-0.16 0.96,-2.38 -0.74,-3.95Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="143.06" android:centerY="41.07" android:gradientRadius="14.54" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.14"/> - - <item android:color="#FFFF980E" android:offset="0.48"/> - - <item android:color="#FFFF3647" android:offset="0.66"/> - - <item android:color="#FFE31587" android:offset="0.9"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M140.14,46.67s0.35,-1.29 2.48,-1.29c0.23,0 0.89,-0.64 0.9,-0.83 0.01,-0.19 -1.37,0.57 -2.82,-0.11 -1.57,-0.74 -2.76,0.11 -2.76,0.11 0,0 0.45,1.12 1.78,1.12 -0.14,1.23 0.51,2.66 2.08,3.41 0.04,0.02 0.07,0.04 0.1,0.05 -0.92,-0.47 -1.67,-1.37 -1.77,-2.46Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="146.83" android:centerY="41.9" android:gradientRadius="17.47" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.09"/> - - <item android:color="#FFFF980E" android:offset="0.63"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M150.46,43.2c-0.33,-0.79 -0.99,-1.63 -1.51,-1.9 0.42,0.83 0.67,1.66 0.76,2.28 0,0 0,0 0,0.01 -0.85,-2.12 -2.29,-2.97 -3.46,-4.83 -0.06,-0.09 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.08,-0.16 -0.05,-0.09 -0.09,-0.19 -0.11,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0,0 0,-0 0,-0 0,-0 -1.89,1.1 -2.53,3.15 -2.59,4.17 0.09,-0.01 0.17,-0.01 0.26,-0.01 1.41,0 2.63,0.77 3.29,1.92 -0.4,-0.28 -1.12,-0.56 -1.81,-0.44 2.7,1.35 1.98,6 -1.77,5.83 -0.33,-0.01 -0.66,-0.08 -0.98,-0.19 -0.08,-0.03 -0.15,-0.06 -0.22,-0.09 -0.04,-0.02 -0.08,-0.04 -0.13,-0.06 0,0 0,0 0,0 -0.04,-0.02 -0.07,-0.04 -0.11,-0.05 0.04,0.02 0.07,0.04 0.11,0.05 -0.92,-0.47 -1.67,-1.37 -1.77,-2.46 0,0 0.35,-1.29 2.48,-1.29 0.23,0 0.89,-0.64 0.9,-0.83 -0,-0.06 -1.31,-0.58 -1.82,-1.08 -0.27,-0.27 -0.4,-0.4 -0.52,-0.49 -0.06,-0.05 -0.13,-0.1 -0.19,-0.15 -0.17,-0.6 -0.18,-1.23 -0.02,-1.84 -0.77,0.35 -1.37,0.91 -1.81,1.4h-0c-0.3,-0.38 -0.28,-1.62 -0.26,-1.88 -0,-0.02 -0.22,0.11 -0.25,0.13 -0.26,0.19 -0.51,0.4 -0.73,0.63 -0.26,0.26 -0.49,0.54 -0.7,0.84v0,-0c-0.48,0.68 -0.82,1.46 -1.01,2.28 -0,0.02 -0.01,0.03 -0.01,0.05 -0.01,0.07 -0.08,0.4 -0.09,0.47 -0,0.01 0,-0.01 0,0 -0.06,0.35 -0.09,0.7 -0.11,1.05 0,0.01 -0,0.03 -0,0.04 0,4.15 3.36,7.51 7.51,7.51 3.72,0 6.8,-2.7 7.4,-6.24 0.01,-0.1 0.02,-0.19 0.03,-0.29 0.15,-1.29 -0.02,-2.64 -0.49,-3.77ZM149.71,43.58c0,0 0,0.01 0,0.01v-0l-0,-0.01Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="138.88" android:endY="51.19" android:startX="148.53" android:startY="40.65" android:type="linear"> - - <item android:color="#CCFFF44F" android:offset="0.17"/> - - <item android:color="#00FFF44F" android:offset="0.6"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:fillColor="#fff" android:pathData="M174.88,49.5c1.93,0 3.5,-1.57 3.5,-3.5 0,-1.93 -1.57,-3.5 -3.5,-3.5 -1.93,0 -3.5,1.57 -3.5,3.5 0,1.93 1.57,3.5 3.5,3.5Z" android:strokeWidth="0"/> - - <path android:pathData="M174.88,42.5h6.06c-1.93,-3.35 -6.21,-4.49 -9.56,-2.56 -1.06,0.61 -1.95,1.5 -2.56,2.56l3.03,5.25 0,-0c-0.97,-1.67 -0.4,-3.81 1.27,-4.78 0.53,-0.31 1.14,-0.47 1.76,-0.47Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="180.94" android:endY="43.37" android:startX="168.82" android:startY="43.37" android:type="linear"> - - <item android:color="#FFD93025" android:offset="0"/> - - <item android:color="#FFEA4335" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:fillColor="#1a73e8" android:pathData="M174.88,48.77c1.53,0 2.77,-1.24 2.77,-2.77 0,-1.53 -1.24,-2.77 -2.77,-2.77s-2.77,1.24 -2.77,2.77c0,1.53 1.24,2.77 2.77,2.77Z" android:strokeWidth="0"/> - - <path android:pathData="M177.91,47.75l-3.03,5.25c3.87,0 7,-3.13 7,-7 0,-1.23 -0.32,-2.44 -0.94,-3.5h-6.06l-0,0c1.93,-0 3.5,1.56 3.5,3.49 0,0.62 -0.16,1.22 -0.47,1.76Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="179.98" android:endY="42.41" android:startX="173.92" android:startY="52.91" android:type="linear"> - - <item android:color="#FFFCC934" android:offset="0"/> - - <item android:color="#FFFBBC04" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M171.85,47.75l-3.03,-5.25c-1.93,3.35 -0.79,7.63 2.56,9.56 1.06,0.61 2.27,0.94 3.5,0.94l3.03,-5.25 -0,-0c-0.96,1.67 -3.1,2.25 -4.77,1.29 -0.53,-0.31 -0.98,-0.75 -1.29,-1.29Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="169.57" android:endY="42.07" android:startX="175.64" android:startY="52.56" android:type="linear"> - - <item android:color="#FF1E8E3E" android:offset="0"/> - - <item android:color="#FF34A853" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml deleted file mode 100644 index 820fd340e36083141b0bd22ba06f294fc33c873a..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml +++ /dev/null @@ -1,307 +0,0 @@ -<vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android" android:height="320dp" android:viewportHeight="193.94" android:viewportWidth="200" android:width="329.99896dp"> - - <group> - - <clip-path android:pathData="M0,0h200v193.94h-200z"/> - - <path android:fillColor="#ab71ff" android:pathData="M179.44,129.92c-17.11,7.31 -23.09,39.17 -26.65,46.24 -7.44,15.67 -41.53,6.53 -54.54,6.53s-26.96,10.45 -47.73,11.23c-20.76,0.78 -33.16,-20.38 -33.16,-46.76S0,106.93 0,88.9s20.14,-16.72 33.16,-23.77c13.02,-7.05 23.55,-56.43 60.74,-63.48 37.19,-7.05 59.5,9.93 81.51,23.25 22,13.32 26.65,40.49 23.86,55.64 -2.79,15.15 1.55,40.23 -19.83,49.37Z" android:strokeWidth="0"/> - - <path android:fillColor="#f9f9fb" android:pathData="M150.3,21.21H51.51c-3.35,0 -6.06,2.71 -6.06,6.06v138.79c0,3.35 2.71,6.06 6.06,6.06h98.79c3.35,0 6.06,-2.71 6.06,-6.06V27.27c0,-3.35 -2.71,-6.06 -6.06,-6.06Z" android:strokeColor="#ededf0" android:strokeWidth="1"/> - - <path android:fillColor="#00000000" android:pathData="M90.61,21.21v150.91M122.12,21.21v150.91M156.36,63.33H45.45M156.36,99.7H46.67M156.36,136.06H45.45" android:strokeColor="#ededf0" android:strokeWidth="1"/> - - <path android:pathData="M112.73,39.96c-0.33,-0.8 -1.01,-1.67 -1.54,-1.94 0.43,0.85 0.68,1.69 0.78,2.33 0,0 0,0 0,0.01 -0.87,-2.16 -2.34,-3.03 -3.54,-4.93 -0.06,-0.1 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.09,-0.16 -0.05,-0.1 -0.09,-0.2 -0.12,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0.01,0 0,-0 0,-0 0,-0 -1.93,1.13 -2.58,3.22 -2.64,4.26 -0.77,0.05 -1.5,0.34 -2.11,0.81 -0.06,-0.05 -0.13,-0.1 -0.2,-0.15 -0.17,-0.61 -0.18,-1.26 -0.02,-1.87 -0.79,0.36 -1.4,0.93 -1.85,1.43h-0c-0.3,-0.39 -0.28,-1.66 -0.27,-1.92 -0,-0.02 -0.23,0.12 -0.26,0.14 -0.27,0.19 -0.52,0.41 -0.75,0.64 -0.26,0.27 -0.5,0.55 -0.72,0.86 0,0 0,0 -0,0 0,-0 0,-0 0,-0 -0.49,0.7 -0.84,1.49 -1.03,2.32 -0,0.02 -0.01,0.03 -0.01,0.05 -0.01,0.07 -0.07,0.41 -0.08,0.48 -0,0.01 -0,0.01 -0,0.02 -0.07,0.35 -0.11,0.7 -0.12,1.06 0,0.01 -0,0.03 -0,0.04 0,4.24 3.43,7.67 7.67,7.67 3.79,0 6.95,-2.75 7.56,-6.37 0.01,-0.1 0.02,-0.2 0.04,-0.3 0.15,-1.32 -0.02,-2.7 -0.5,-3.85ZM103.88,45.97c0.04,0.02 0.07,0.04 0.11,0.05 0,0 0,0 0,0 -0.04,-0.02 -0.08,-0.04 -0.11,-0.06ZM111.97,40.36v-0.01c0,0 0,0.01 0,0.01l-0,-0Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="99.19" android:endY="49.18" android:startX="111.51" android:startY="37.3" android:type="linear"> - - <item android:color="#FFFFF44F" android:offset="0.05"/> - - <item android:color="#FFFF980E" android:offset="0.37"/> - - <item android:color="#FFFF3647" android:offset="0.53"/> - - <item android:color="#FFE31587" android:offset="0.7"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M112.73,39.96c-0.33,-0.8 -1.01,-1.67 -1.54,-1.94 0.43,0.85 0.68,1.69 0.78,2.33 0,-0 0,0 0,0.01 0,0 0,0.01 0,0.01 0.72,1.96 0.33,3.96 -0.24,5.18 -0.88,1.89 -3.01,3.82 -6.34,3.73 -3.6,-0.1 -6.77,-2.77 -7.36,-6.27 -0.11,-0.55 0,-0.83 0.05,-1.28 -0.07,0.35 -0.09,0.44 -0.12,1.06 0,0.01 -0,0.03 -0,0.04 0,4.24 3.43,7.67 7.67,7.67 3.79,0 6.95,-2.75 7.56,-6.37 0.01,-0.1 0.02,-0.2 0.04,-0.3 0.15,-1.32 -0.02,-2.7 -0.5,-3.85Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="108.57" android:centerY="36.42" android:gradientRadius="15.69" android:type="radial"> - - <item android:color="#FFFFBD4F" android:offset="0.13"/> - - <item android:color="#FFFF980E" android:offset="0.28"/> - - <item android:color="#FFFF3750" android:offset="0.47"/> - - <item android:color="#FFEB0878" android:offset="0.78"/> - - <item android:color="#FFE50080" android:offset="0.86"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M112.73,39.96c-0.33,-0.8 -1.01,-1.67 -1.54,-1.94 0.43,0.85 0.68,1.69 0.78,2.33 0,-0 0,0 0,0.01 0,0 0,0.01 0,0.01 0.72,1.96 0.33,3.96 -0.24,5.18 -0.88,1.89 -3.01,3.82 -6.34,3.73 -3.6,-0.1 -6.77,-2.77 -7.36,-6.27 -0.11,-0.55 0,-0.83 0.05,-1.28 -0.07,0.35 -0.09,0.44 -0.12,1.06 0,0.01 -0,0.03 -0,0.04 0,4.24 3.43,7.67 7.67,7.67 3.79,0 6.95,-2.75 7.56,-6.37 0.01,-0.1 0.02,-0.2 0.04,-0.3 0.15,-1.32 -0.02,-2.7 -0.5,-3.85Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="104.02" android:centerY="43.01" android:gradientRadius="16.08" android:type="radial"> - - <item android:color="#FF960E18" android:offset="0.3"/> - - <item android:color="#BCB11927" android:offset="0.35"/> - - <item android:color="#56DB293D" android:offset="0.43"/> - - <item android:color="#16F5334B" android:offset="0.5"/> - - <item android:color="#00FF3750" android:offset="0.53"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M109,40.86c0.02,0.01 0.03,0.02 0.05,0.04 -0.19,-0.34 -0.43,-0.65 -0.71,-0.93 -2.38,-2.38 -0.63,-5.17 -0.33,-5.31 0,-0 0,-0 0,-0 -1.93,1.13 -2.58,3.22 -2.64,4.26 0.09,-0.01 0.18,-0.01 0.27,-0.01 1.44,0 2.69,0.79 3.36,1.96Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="107.13" android:centerY="33.9" android:gradientRadius="5.15" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.13"/> - - <item android:color="#FFFF980E" android:offset="0.53"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M105.64,41.34c-0.01,0.19 -0.69,0.85 -0.92,0.85 -2.18,0 -2.54,1.32 -2.54,1.32 0.1,1.11 0.87,2.03 1.81,2.51 0.04,0.02 0.09,0.04 0.13,0.06 0.07,0.03 0.15,0.06 0.22,0.09 0.32,0.11 0.66,0.18 1,0.19 3.82,0.18 4.56,-4.57 1.8,-5.95 0.71,-0.12 1.44,0.16 1.85,0.45 -0.67,-1.17 -1.92,-1.96 -3.36,-1.96 -0.09,0 -0.18,0.01 -0.27,0.01 -0.77,0.05 -1.5,0.34 -2.11,0.81 0.12,0.1 0.25,0.23 0.53,0.51 0.52,0.51 1.86,1.04 1.86,1.11Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="103.73" android:centerY="47.13" android:gradientRadius="6.81" android:type="radial"> - - <item android:color="#FF3A8EE6" android:offset="0.35"/> - - <item android:color="#FF9059FF" android:offset="0.67"/> - - <item android:color="#FFC139E6" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M105.64,41.34c-0.01,0.19 -0.69,0.85 -0.92,0.85 -2.18,0 -2.54,1.32 -2.54,1.32 0.1,1.11 0.87,2.03 1.81,2.51 0.04,0.02 0.09,0.04 0.13,0.06 0.07,0.03 0.15,0.06 0.22,0.09 0.32,0.11 0.66,0.18 1,0.19 3.82,0.18 4.56,-4.57 1.8,-5.95 0.71,-0.12 1.44,0.16 1.85,0.45 -0.67,-1.17 -1.92,-1.96 -3.36,-1.96 -0.09,0 -0.18,0.01 -0.27,0.01 -0.77,0.05 -1.5,0.34 -2.11,0.81 0.12,0.1 0.25,0.23 0.53,0.51 0.52,0.51 1.86,1.04 1.86,1.11Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="104.9" android:centerY="41.37" android:gradientRadius="3.62" android:type="radial"> - - <item android:color="#009059FF" android:offset="0.21"/> - - <item android:color="#996E008B" android:offset="0.97"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M102.9,39.47c0.05,0.03 0.11,0.07 0.16,0.11 -0.17,-0.61 -0.18,-1.26 -0.02,-1.87 -0.79,0.36 -1.4,0.93 -1.85,1.43 0.04,-0 1.15,-0.02 1.71,0.34Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="105.11" android:centerY="35.83" android:gradientRadius="5.42" android:type="radial"> - - <item android:color="#FFFFE226" android:offset="0.1"/> - - <item android:color="#FFFF7139" android:offset="0.79"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M98.03,43c0.59,3.5 3.76,6.17 7.36,6.27 3.33,0.09 5.46,-1.84 6.34,-3.73 0.57,-1.22 0.96,-3.21 0.24,-5.18v-0l-0,-0.01c-0,-0.01 -0,-0.01 -0,-0.01 0,0 0,0 0,0.01 0.27,1.78 -0.63,3.5 -2.05,4.66l-0,0.01c-2.75,2.24 -5.39,1.35 -5.92,0.99 -0.04,-0.02 -0.08,-0.04 -0.11,-0.06 -1.61,-0.77 -2.27,-2.23 -2.13,-3.48 -1.36,0 -1.82,-1.14 -1.82,-1.14 0,0 1.22,-0.87 2.82,-0.11 1.49,0.7 2.88,0.11 2.88,0.11 -0,-0.06 -1.34,-0.59 -1.86,-1.11 -0.28,-0.27 -0.41,-0.41 -0.53,-0.51 -0.06,-0.05 -0.13,-0.1 -0.2,-0.15 -0.05,-0.04 -0.11,-0.07 -0.16,-0.11 -0.56,-0.36 -1.67,-0.34 -1.71,-0.34h-0c-0.3,-0.39 -0.28,-1.66 -0.26,-1.92 -0,-0.02 -0.23,0.12 -0.26,0.14 -0.27,0.19 -0.52,0.41 -0.75,0.64 -0.26,0.27 -0.5,0.55 -0.72,0.86 -0.49,0.7 -0.84,1.49 -1.03,2.32 -0,0.02 -0.28,1.21 -0.14,1.83Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="110.06" android:centerY="32.26" android:gradientRadius="25.87" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.11"/> - - <item android:color="#FFFF980E" android:offset="0.46"/> - - <item android:color="#FFFF3647" android:offset="0.72"/> - - <item android:color="#FFE31587" android:offset="0.9"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M108.33,39.97c0.28,0.27 0.52,0.59 0.71,0.93 0.04,0.03 0.08,0.06 0.12,0.09 1.74,1.6 0.83,3.87 0.76,4.03 1.41,-1.16 2.32,-2.89 2.05,-4.66 -0.87,-2.16 -2.34,-3.03 -3.54,-4.93 -0.06,-0.1 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.08,-0.16 -0.05,-0.1 -0.09,-0.2 -0.12,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0.01,0 -0.3,0.14 -2.06,2.93 0.33,5.31Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="100.45" android:centerY="39.43" android:gradientRadius="8.21" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0"/> - - <item android:color="#FFFF980E" android:offset="0.3"/> - - <item android:color="#FFFF3647" android:offset="0.57"/> - - <item android:color="#FFE31587" android:offset="0.74"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M109.16,40.99c-0.03,-0.03 -0.07,-0.06 -0.12,-0.09 -0.02,-0.01 -0.03,-0.02 -0.05,-0.04 -0.41,-0.29 -1.14,-0.57 -1.85,-0.45 2.76,1.38 2.02,6.13 -1.8,5.95 -0.34,-0.01 -0.68,-0.08 -1,-0.19 -0.08,-0.03 -0.15,-0.06 -0.22,-0.09 -0.04,-0.02 -0.09,-0.04 -0.13,-0.06 0,0 0,0 0.01,0 0.53,0.36 3.17,1.25 5.92,-0.99l0,-0.01c0.07,-0.16 0.98,-2.43 -0.76,-4.03Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="105.17" android:centerY="37.79" android:gradientRadius="14.85" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.14"/> - - <item android:color="#FFFF980E" android:offset="0.48"/> - - <item android:color="#FFFF3647" android:offset="0.66"/> - - <item android:color="#FFE31587" android:offset="0.9"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M102.18,43.51s0.35,-1.32 2.54,-1.32c0.23,0 0.91,-0.66 0.92,-0.85s-1.39,0.59 -2.88,-0.11c-1.6,-0.75 -2.82,0.11 -2.82,0.11 0,0 0.46,1.14 1.82,1.14 -0.14,1.25 0.52,2.72 2.13,3.48 0.04,0.02 0.07,0.04 0.11,0.05 -0.94,-0.48 -1.71,-1.4 -1.81,-2.51Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:centerX="109.02" android:centerY="38.64" android:gradientRadius="17.85" android:type="radial"> - - <item android:color="#FFFFF44F" android:offset="0.09"/> - - <item android:color="#FFFF980E" android:offset="0.63"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M112.73,39.96c-0.33,-0.8 -1.01,-1.67 -1.54,-1.94 0.43,0.85 0.68,1.69 0.78,2.33 0,0 0,0 0,0.01 -0.87,-2.16 -2.34,-3.03 -3.54,-4.93 -0.06,-0.1 -0.12,-0.19 -0.18,-0.29 -0.03,-0.05 -0.06,-0.1 -0.09,-0.16 -0.05,-0.1 -0.09,-0.2 -0.12,-0.3 0,-0 -0,-0.01 -0,-0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 -0,-0 -0.01,-0 -0.01,0 -0,0 -0,0 -0,0 -0,0 -0,0 -0.01,0 0,-0 0,-0 0,-0 -1.93,1.13 -2.58,3.22 -2.64,4.26 0.09,-0.01 0.18,-0.01 0.27,-0.01 1.44,0 2.69,0.79 3.36,1.96 -0.41,-0.29 -1.14,-0.57 -1.85,-0.45 2.76,1.38 2.02,6.13 -1.8,5.95 -0.34,-0.01 -0.68,-0.08 -1,-0.19 -0.08,-0.03 -0.15,-0.06 -0.22,-0.09 -0.04,-0.02 -0.09,-0.04 -0.13,-0.06 0,0 0,0 0.01,0 -0.04,-0.02 -0.08,-0.04 -0.11,-0.06 0.04,0.02 0.07,0.04 0.11,0.05 -0.94,-0.48 -1.71,-1.4 -1.81,-2.51 0,0 0.35,-1.32 2.54,-1.32 0.24,0 0.91,-0.66 0.92,-0.85 -0,-0.06 -1.34,-0.59 -1.86,-1.11 -0.28,-0.27 -0.41,-0.41 -0.53,-0.51 -0.06,-0.05 -0.13,-0.1 -0.2,-0.15 -0.17,-0.61 -0.18,-1.26 -0.02,-1.87 -0.79,0.36 -1.4,0.93 -1.85,1.43h-0c-0.3,-0.39 -0.28,-1.66 -0.26,-1.92 -0,-0.02 -0.23,0.12 -0.26,0.14 -0.27,0.19 -0.52,0.41 -0.75,0.64 -0.26,0.27 -0.5,0.55 -0.72,0.86 -0.49,0.7 -0.84,1.49 -1.03,2.32 -0,0.02 -0.01,0.03 -0.01,0.05 -0.01,0.07 -0.08,0.41 -0.09,0.48 0,-0.01 -0,0.01 0,0 -0.06,0.35 -0.1,0.71 -0.11,1.07 0,0.01 -0,0.03 -0,0.04 0,4.24 3.43,7.67 7.67,7.67 3.79,0 6.95,-2.75 7.56,-6.37 0.01,-0.1 0.02,-0.2 0.04,-0.3 0.15,-1.32 -0.02,-2.7 -0.5,-3.85ZM111.97,40.36c0,0 0,0.01 0,0.01l-0,-0v-0.01Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="100.9" android:endY="48.12" android:startX="110.75" android:startY="37.36" android:type="linear"> - - <item android:color="#CCFFF44F" android:offset="0.17"/> - - <item android:color="#00FFF44F" android:offset="0.6"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M113.03,113.31l-8.8,8.8c-0.12,0.12 -0.29,0.19 -0.47,0.19s-0.34,-0.07 -0.47,-0.19l-5.41,-5.41 0.94,-0.94 4.94,4.95 8.33,-8.33 0.94,0.94Z" android:strokeWidth="0"/> - - <path android:fillColor="#9591af" android:pathData="M139.75,117.58l4.49,-4.49 -0.97,-0.96 -4.49,4.49 -4.49,-4.49 -0.96,0.96 4.49,4.49 -4.49,4.49 0.96,0.96 4.49,-4.49 4.49,4.49 0.96,-0.96 -4.49,-4.49Z" android:strokeWidth="0"/> - - <path android:fillColor="#FF000000" android:fillType="evenOdd" android:pathData="M69.47,111.33c-0.73,0 -1.33,0.59 -1.33,1.33v1.8c0,0.37 -0.3,0.66 -0.66,0.66h-2.56c-0.31,0 -0.57,0.25 -0.57,0.57v1.14h1.14c1.46,0 2.65,1.19 2.65,2.65s-1.19,2.65 -2.65,2.65h-1.14v1.14c0,0.31 0.25,0.57 0.57,0.57h9.09c0.31,0 0.57,-0.25 0.57,-0.57v-7.58c0,-0.31 -0.25,-0.57 -0.57,-0.57h-2.56c-0.37,0 -0.66,-0.3 -0.66,-0.66v-1.8c0,-0.73 -0.59,-1.33 -1.33,-1.33ZM66.82,112.65c0,-1.47 1.19,-2.65 2.65,-2.65 1.46,0 2.65,1.19 2.65,2.65v1.14h1.89c1.05,0 1.89,0.85 1.89,1.89v7.58c0,1.04 -0.85,1.89 -1.89,1.89h-9.09c-1.05,0 -1.89,-0.85 -1.89,-1.89v-1.8c0,-0.37 0.3,-0.66 0.66,-0.66h1.8c0.73,0 1.33,-0.59 1.33,-1.33s-0.59,-1.33 -1.33,-1.33h-1.8c-0.37,0 -0.66,-0.3 -0.66,-0.66v-1.8c0,-1.05 0.85,-1.89 1.89,-1.89h1.89v-1.14Z" android:strokeWidth="0"/> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M113.03,78.77l-8.8,8.8c-0.12,0.12 -0.29,0.19 -0.47,0.19s-0.34,-0.07 -0.47,-0.19l-5.41,-5.41 0.94,-0.94 4.94,4.94 8.33,-8.33 0.94,0.94Z" android:strokeWidth="0"/> - - <path android:fillColor="#9591af" android:pathData="M139.75,83.03l4.49,-4.49 -0.97,-0.96 -4.49,4.49 -4.49,-4.49 -0.96,0.96 4.49,4.49 -4.49,4.49 0.96,0.96 4.49,-4.49 4.49,4.49 0.96,-0.96 -4.49,-4.49Z" android:strokeWidth="0"/> - - <path android:fillColor="#FF000000" android:pathData="M69.09,90.61c-0.39,0 -0.77,-0.1 -1.11,-0.29 -1.58,-0.88 -3.02,-2.24 -4.08,-3.85 -0.54,-0.82 -0.92,-1.8 -1.13,-2.95l-0.54,-2.92c-0.18,-0.97 0.29,-1.94 1.15,-2.41l4.56,-2.47c0.67,-0.36 1.48,-0.36 2.16,0l4.67,2.52c0.87,0.47 1.34,1.44 1.16,2.42l-0.54,2.87c-0.21,1.14 -0.59,2.12 -1.12,2.93 -1.06,1.61 -2.51,2.97 -4.08,3.86 -0.34,0.19 -0.73,0.29 -1.11,0.29ZM69.03,76.78c-0.15,0 -0.31,0.04 -0.45,0.11l-4.56,2.47c-0.36,0.2 -0.55,0.6 -0.48,1.01l0.54,2.92c0.17,0.96 0.49,1.79 0.93,2.45 0.94,1.42 2.23,2.64 3.62,3.42 0.29,0.16 0.64,0.16 0.92,0 1.39,-0.78 2.68,-1.99 3.62,-3.42 0.44,-0.67 0.75,-1.48 0.92,-2.45l0.54,-2.87c0.08,-0.41 -0.12,-0.81 -0.48,-1.01l-4.67,-2.52c-0.14,-0.08 -0.3,-0.11 -0.45,-0.11l-0.01,-0.01Z" android:strokeWidth="0"/> - - <path android:fillColor="#2ac3a2" android:fillType="evenOdd" android:pathData="M113.03,149.07l-8.8,8.8c-0.12,0.12 -0.29,0.19 -0.47,0.19s-0.34,-0.07 -0.47,-0.19l-5.41,-5.41 0.94,-0.94 4.94,4.94 8.33,-8.33 0.94,0.94Z" android:strokeWidth="0"/> - - <path android:fillColor="#9591af" android:pathData="M139.75,153.33l4.49,-4.49 -0.97,-0.96 -4.49,4.49 -4.49,-4.49 -0.96,0.96 4.49,4.49 -4.49,4.49 0.96,0.96 4.49,-4.49 4.49,4.49 0.96,-0.96 -4.49,-4.49Z" android:strokeWidth="0"/> - - <path android:fillColor="#FF000000" android:pathData="M75.91,150.79l-4.09,-4.09c-0.14,-0.14 -0.34,-0.22 -0.54,-0.22h-5.37c-1.13,0 -2.05,0.91 -2.05,2.04v11.25c0,1.13 0.92,2.05 2.05,2.05h8.18c1.13,0 2.05,-0.91 2.05,-2.05v-8.44c0,-0.2 -0.08,-0.4 -0.22,-0.54ZM74.6,151.65v8.12c0,0.28 -0.23,0.51 -0.51,0.51h-8.18c-0.28,0 -0.51,-0.23 -0.51,-0.51v-11.25c0,-0.28 0.23,-0.51 0.51,-0.51h5.05l0.06,0.06v3.01c0,0.28 0.23,0.51 0.51,0.51h3.01l0.06,0.06Z" android:strokeWidth="0"/> - - <path android:fillColor="#fff" android:pathData="M138.3,46.4c2.01,0 3.63,-1.63 3.63,-3.64s-1.63,-3.64 -3.63,-3.64 -3.64,1.63 -3.64,3.64 1.63,3.64 3.64,3.64Z" android:strokeWidth="0"/> - - <path android:pathData="M138.3,39.13h6.3c-2.01,-3.48 -6.45,-4.67 -9.93,-2.66 -1.11,0.64 -2.02,1.56 -2.66,2.66l3.15,5.45 0,-0c-1.01,-1.73 -0.42,-3.96 1.32,-4.96 0.55,-0.32 1.18,-0.49 1.83,-0.49Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="144.6" android:endY="40.04" android:startX="132.01" android:startY="40.04" android:type="linear"> - - <item android:color="#FFD93025" android:offset="0"/> - - <item android:color="#FFEA4335" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:fillColor="#1a73e8" android:pathData="M138.3,45.65c1.59,0 2.88,-1.29 2.88,-2.88 0,-1.59 -1.29,-2.88 -2.88,-2.88s-2.88,1.29 -2.88,2.88c0,1.59 1.29,2.88 2.88,2.88Z" android:strokeWidth="0"/> - - <path android:pathData="M141.45,44.59l-3.15,5.45c4.01,0 7.27,-3.25 7.27,-7.27 0,-1.28 -0.34,-2.53 -0.97,-3.64h-6.3v0c2.01,-0 3.63,1.62 3.64,3.62 0,0.64 -0.17,1.27 -0.49,1.83Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="143.61" android:endY="39.04" android:startX="137.31" android:startY="49.94" android:type="linear"> - - <item android:color="#FFFCC934" android:offset="0"/> - - <item android:color="#FFFBBC04" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - <path android:pathData="M135.16,44.59l-3.15,-5.45c-2.01,3.48 -0.82,7.92 2.66,9.93 1.11,0.64 2.36,0.97 3.64,0.97l3.15,-5.45 -0,-0c-1,1.74 -3.22,2.34 -4.96,1.34 -0.56,-0.32 -1.02,-0.78 -1.34,-1.34Z" android:strokeWidth="0"> - - <aapt:attr name="android:fillColor"> - - <gradient android:endX="132.79" android:endY="38.68" android:startX="139.09" android:startY="49.59" android:type="linear"> - - <item android:color="#FF1E8E3E" android:offset="0"/> - - <item android:color="#FF34A853" android:offset="1"/> - - </gradient> - - </aapt:attr> - - </path> - - </group> - -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_search_widget.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_search_widget.xml deleted file mode 100644 index 75dc5ee5ebbdf9878f0955b082a58ab34230bf99..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_search_widget.xml +++ /dev/null @@ -1,293 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="312dp" - android:height="323dp" - android:viewportWidth="312" - android:viewportHeight="323"> - <group> - <clip-path - android:pathData="M0.37,0h310.83v323h-310.83z"/> - <path - android:pathData="M311.15,203.98C311.23,202.4 311.18,200.8 311.05,199.23C309.6,181.96 299.64,172.1 288.12,160.57C287.96,160.4 287.8,160.24 287.64,160.08C285.33,158.45 283.01,156.81 280.7,155.18C279.88,154.57 279.06,153.96 278.24,153.35C276.48,151.95 274.71,150.56 272.95,149.16C272.79,149.01 272.63,148.85 272.48,148.7C268.98,145.58 265.82,142.2 264.09,137.72C264.05,137.64 264,137.56 263.95,137.49C263.85,137.11 263.75,136.74 263.65,136.36C263.61,136.28 263.56,136.19 263.52,136.11C263.43,135.66 263.34,135.21 263.25,134.77C263.21,134.69 263.17,134.6 263.13,134.52C263.13,134.38 263.13,134.24 263.14,134.1C263.1,134.02 263.06,133.94 263.02,133.85C262.97,133.12 262.92,132.38 262.86,131.65C262.83,131.5 262.8,131.34 262.77,131.19C262.79,130.91 262.82,130.62 262.84,130.34C262.83,130.12 262.81,129.89 262.8,129.66C262.82,129.38 262.84,129.09 262.86,128.81C262.87,128.73 262.88,128.66 262.89,128.59C262.97,128.1 263.05,127.6 263.13,127.1C263.21,126.75 263.3,126.4 263.38,126.05C263.47,125.85 263.55,125.64 263.64,125.43C263.71,125.08 263.79,124.74 263.87,124.39C263.94,124.25 264.01,124.11 264.09,123.97C264.39,123.08 264.7,122.19 265.01,121.3C265.08,121.16 265.16,121.02 265.23,120.89C265.3,120.68 265.36,120.48 265.42,120.28C265.59,119.93 265.76,119.6 265.93,119.25C266.1,118.85 266.26,118.44 266.43,118.04C266.49,117.96 266.55,117.89 266.61,117.82L267.68,115.62C267.75,115.55 267.81,115.48 267.88,115.41C267.88,115.34 267.92,115.28 267.97,115.24C268.09,115.05 268.21,114.86 268.34,114.68C268.42,114.46 268.51,114.24 268.59,114.03C268.66,113.96 268.72,113.9 268.79,113.83L269.47,112.64C269.53,112.57 269.6,112.51 269.67,112.45L270.32,111.47C270.48,111.21 270.65,110.94 270.81,110.67C271.37,109.89 271.93,109.11 272.49,108.32C272.75,108.03 273,107.74 273.25,107.44C273.58,106.96 273.91,106.47 274.24,105.99C274.31,105.93 274.38,105.88 274.44,105.82C276.16,103.97 277.89,102.11 279.61,100.25C284.43,95.02 288.13,89.42 289.68,82.34C289.43,82.44 289.19,82.53 288.94,82.62C289.57,82.68 289.87,81.87 289.92,81.25C290.34,76.11 287.63,71.1 284.96,66.88C282.29,62.67 278.74,58.86 274.26,56.47C268.02,53.15 261.57,49.93 254.57,48.91C252.63,48.63 250.68,48.52 248.73,48.33C242.54,47.71 236.4,46.21 230.79,43.51C223.38,39.94 218.09,33.35 211.26,28.92C204.07,24.27 195.83,21.48 187.65,19.12C172.16,14.66 156.26,11.52 140.17,10.31C126.49,9.27 107.97,7.24 96.19,15.94C90.75,19.96 85.97,24.88 82.04,30.38C74.01,41.6 69.43,55.36 69.71,69.2C69.9,78.41 72.07,87.58 71.38,96.77C70.7,105.86 67.13,116.28 60.23,122.53C51.3,130.6 40.38,136.1 30.08,142.29C21.71,147.31 13.16,152.5 7.15,160.18C1.14,167.86 -1.85,178.7 2.25,187.54C4,191.3 6.87,194.43 9.94,197.22C18.25,204.78 28.2,210.23 38.5,214.58C46.56,217.98 57.59,223.84 66.31,224.64C66.38,224.65 66.45,224.65 66.53,224.66C66.87,224.79 67.21,224.92 67.55,225.05C67.62,225.06 67.69,225.06 67.76,225.07C68.11,225.2 68.45,225.34 68.79,225.47C69.41,225.66 70.03,225.85 70.65,226.04C70.79,226.12 70.92,226.19 71.06,226.26L71.9,226.45C72.03,226.53 72.17,226.6 72.3,226.68C72.58,226.75 72.86,226.81 73.13,226.88C73.27,226.95 73.41,227.02 73.55,227.1C73.82,227.16 74.1,227.23 74.37,227.3C74.51,227.37 74.65,227.45 74.79,227.52C75.07,227.58 75.34,227.65 75.62,227.72C75.75,227.79 75.89,227.86 76.03,227.94C76.1,227.94 76.17,227.95 76.24,227.96C76.59,228.09 76.92,228.22 77.27,228.35C77.34,228.36 77.41,228.37 77.48,228.37C77.82,228.51 78.17,228.64 78.51,228.77C78.58,228.78 78.65,228.78 78.72,228.79C79.06,228.92 79.41,229.05 79.74,229.19C79.82,229.19 79.89,229.2 79.96,229.2C80.31,229.34 80.64,229.47 80.99,229.6C81.26,229.66 81.54,229.73 81.82,229.79C81.96,229.87 82.09,229.94 82.23,230.02C82.51,230.08 82.78,230.15 83.06,230.21C83.2,230.29 83.34,230.36 83.47,230.43C83.75,230.5 84.03,230.57 84.3,230.63C84.44,230.7 84.57,230.78 84.71,230.85C84.78,230.86 84.86,230.86 84.93,230.87C85.27,231 85.61,231.14 85.95,231.27C86.02,231.28 86.1,231.28 86.17,231.29C86.44,231.41 86.71,231.53 86.98,231.65C87.54,231.82 88.09,232 88.64,232.17C88.85,232.25 89.05,232.34 89.26,232.43C89.46,232.49 89.66,232.55 89.87,232.61C90.01,232.68 90.15,232.74 90.29,232.81C90.43,232.85 90.56,232.88 90.71,232.93C90.84,233.01 90.97,233.09 91.1,233.18C91.17,233.18 91.25,233.19 91.32,233.2C91.59,233.31 91.86,233.42 92.13,233.54C92.28,233.58 92.41,233.62 92.55,233.66C92.69,233.73 92.82,233.8 92.95,233.88C94.18,234.39 95.4,234.91 96.62,235.42C96.76,235.49 96.89,235.56 97.03,235.63C97.84,236 98.64,236.37 99.44,236.74C99.51,236.81 99.58,236.88 99.65,236.94C99.78,236.98 99.91,237.02 100.04,237.05C100.11,237.12 100.18,237.19 100.25,237.26C101.18,237.79 102.12,238.31 103.05,238.84L103.24,239.05C103.5,239.18 103.76,239.31 104.02,239.44C104.09,239.51 104.16,239.58 104.23,239.65C104.75,239.96 105.27,240.28 105.8,240.6C105.87,240.67 105.93,240.74 106.01,240.81C106.79,241.31 107.58,241.81 108.36,242.31C108.43,242.39 108.5,242.46 108.57,242.53C109.82,243.39 111.06,244.25 112.31,245.12C112.37,245.18 112.42,245.26 112.48,245.32C121.63,253.11 129.16,262.32 137.8,270.62C144.82,277.36 153.14,283.28 162.71,285C173.61,286.96 188.65,283.28 196.9,275.58C200.12,272.58 203.61,269.81 206.49,266.51C225.73,244.55 253.54,229.57 282.22,224.67C287.2,223.82 292.26,223.25 297.03,221.6C301.8,219.96 306.35,217.07 308.84,212.67C310.33,210.03 310.97,207.03 311.13,203.98L311.15,203.98Z" - android:fillColor="#C6ADFF"/> - <path - android:pathData="M213.4,87.58C213.34,87.58 213.33,87.55 213.34,87.5C213.35,87.45 213.35,87.41 213.36,87.37C213.63,85.68 213.9,83.99 214.17,82.3C214.19,82.19 214.23,82.09 214.06,82.08C214.01,82.08 214.01,82.02 214.02,81.98C214.02,81.92 214.03,81.86 214.04,81.79C214.12,81.33 214.19,80.87 214.26,80.41C214.28,80.32 214.28,80.25 214.17,80.23C214.1,80.22 214.09,80.18 214.1,80.12C214.12,79.99 214.14,79.85 214.16,79.72C214.18,79.65 214.16,79.61 214.09,79.6C213.99,79.59 213.98,79.53 214,79.45C214.02,79.36 214.02,79.27 214.03,79.18C214.04,79.09 214.03,79.01 213.95,78.95C213.91,78.91 213.89,78.85 213.89,78.8C213.89,78.66 213.84,78.55 213.75,78.44C213.52,78.14 213.3,77.84 213.09,77.54C213.02,77.44 212.94,77.37 212.84,77.32C212.66,77.23 212.53,77.07 212.34,77C212.33,77 212.32,76.99 212.32,76.98C212.25,76.79 212.07,76.79 211.91,76.76C211.67,76.71 211.44,76.68 211.2,76.64C211.13,76.63 211.08,76.61 211.1,76.52C211.12,76.46 211.09,76.43 211.03,76.42C210.96,76.41 210.9,76.39 210.84,76.38C209.62,76.18 208.4,75.99 207.18,75.79C207.09,75.78 207,75.77 207.04,75.65C207.06,75.6 207.02,75.58 206.98,75.57C206.9,75.55 206.83,75.53 206.76,75.52C202.45,74.83 198.13,74.14 193.82,73.45C193.75,73.43 193.7,73.42 193.64,73.42C193.57,73.41 193.54,73.39 193.56,73.32C193.59,73.23 193.53,73.2 193.46,73.18C193.4,73.18 193.35,73.16 193.29,73.15C189.86,72.6 186.43,72.05 182.99,71.5C182.94,71.5 182.88,71.48 182.83,71.48C182.76,71.47 182.72,71.44 182.74,71.37C182.77,71.29 182.73,71.26 182.66,71.24C182.6,71.23 182.53,71.22 182.47,71.21C179.03,70.66 175.59,70.11 172.16,69.56C172.11,69.55 172.06,69.54 172.01,69.53C171.94,69.53 171.91,69.5 171.93,69.44C171.95,69.36 171.91,69.33 171.84,69.31C171.77,69.3 171.7,69.28 171.63,69.27C168.41,68.75 165.18,68.23 161.95,67.72C161.9,67.71 161.85,67.7 161.81,67.69C161.75,67.69 161.71,67.66 161.72,67.6C161.74,67.51 161.68,67.48 161.61,67.47C161.53,67.46 161.44,67.43 161.36,67.42C158.57,66.97 155.78,66.52 152.99,66.08C152.97,66.08 152.95,66.07 152.93,66.06C152.79,66.04 152.74,65.96 152.78,65.82L144.39,64.48C144.4,64.8 144.2,64.58 144.03,64.64C143.92,64.67 143.96,64.77 143.87,64.81C143.77,64.86 143.6,64.75 143.49,64.76C143.36,64.78 143.28,64.87 143.17,64.9C143.02,64.95 142.93,64.94 142.79,65.02C142.5,65.21 142.15,65.43 141.93,65.69C141.73,65.93 141.53,66.21 141.36,66.46C141.21,66.7 141,66.91 140.86,67.14C140.67,67.42 140.71,67.86 140.66,68.18C140.63,68.41 140.6,68.45 140.37,68.42L138.88,77.69C139.03,77.72 139.1,77.82 139.07,77.97C139.02,78.28 138.97,78.6 138.92,78.91C138.9,79.02 138.91,79.12 139,79.2C139.04,79.24 139.05,79.29 139.05,79.34C139.05,79.48 139.1,79.58 139.18,79.69C139.36,79.93 139.54,80.17 139.72,80.41C139.78,80.49 139.86,80.56 139.96,80.59C140.11,80.63 140.18,80.76 140.24,80.88C140.31,81.03 140.42,81.08 140.59,81.1C140.78,81.12 140.98,81.16 141.18,81.19C141.25,81.2 141.29,81.23 141.27,81.31C141.25,81.38 141.27,81.42 141.35,81.43C141.55,81.46 141.75,81.49 141.95,81.53C142.03,81.54 142.06,81.5 142.07,81.43C142.08,81.35 142.12,81.34 142.2,81.35C142.74,81.45 143.29,81.53 143.84,81.62C143.92,81.63 143.95,81.66 143.93,81.74C143.91,81.81 143.93,81.85 144.01,81.85C144.04,81.85 144.07,81.86 144.11,81.87C149.44,82.72 154.77,83.58 160.1,84.43C160.14,84.44 160.18,84.44 160.22,84.45C160.26,84.46 160.29,84.48 160.27,84.53C160.23,84.66 160.31,84.67 160.41,84.69C162.55,85.03 164.69,85.37 166.83,85.71C169.63,86.16 172.43,86.61 175.23,87.06C175.33,87.07 175.43,87.09 175.38,87.23C175.37,87.27 175.39,87.29 175.43,87.3C175.48,87.31 175.52,87.31 175.56,87.32C178.98,87.87 182.39,88.42 185.81,88.96C185.85,88.97 185.89,88.98 185.93,88.98C185.98,88.99 186.02,89.01 186,89.07C185.96,89.19 186.03,89.21 186.12,89.22C187.12,89.38 188.11,89.54 189.1,89.7C192.03,90.16 194.95,90.64 197.88,91.1C197.98,91.12 198.08,91.13 198.03,91.27C198.02,91.31 198.05,91.34 198.09,91.35C198.13,91.35 198.18,91.36 198.23,91.37C201.64,91.92 205.05,92.46 208.46,93.01C208.57,93.03 208.66,93.05 208.7,93.17C208.7,93.19 208.72,93.21 208.73,93.24C208.83,93.43 208.97,93.53 209.2,93.55C209.5,93.58 209.8,93.64 210.1,93.69C210.23,93.71 210.36,93.72 210.47,93.62C210.48,93.61 210.49,93.6 210.49,93.6C210.71,93.59 210.88,93.47 211.09,93.43C211.17,93.42 211.24,93.4 211.31,93.35C211.46,93.25 211.61,93.14 211.76,93.05C212.03,92.87 212.17,92.59 212.35,92.35C212.38,92.3 212.4,92.25 212.44,92.21C212.56,92.13 212.61,92.01 212.63,91.87C212.65,91.71 212.68,91.54 212.7,91.38C212.73,91.25 212.8,91.2 212.92,91.23C213.12,90.02 213.31,88.8 213.51,87.59C213.47,87.59 213.43,87.58 213.39,87.58L213.4,87.58Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M135.98,123.65C135.98,123.65 135.98,123.68 135.98,123.7C136.01,123.7 136.05,123.71 136.08,123.71C136.29,123.8 136.51,123.89 136.72,123.99C137.24,124.08 137.77,124.18 138.3,124.27C138.46,124.3 138.64,124.34 138.8,124.37C138.86,124.36 138.91,124.34 138.97,124.33C139,124.34 139.04,124.35 139.07,124.36C139.29,124.39 139.51,124.43 139.73,124.46C140.32,124.61 140.86,124.69 141.46,124.74L142.59,124.86C142.62,124.86 142.65,124.86 142.68,124.86C142.76,124.87 142.84,124.87 142.92,124.88C143,124.89 143.07,124.9 143.15,124.91C143.36,124.94 143.57,124.97 143.77,124.99H143.99C143.99,124.99 144.03,124.98 144.04,124.98L144.15,124.96C144.15,124.96 144.18,124.96 144.2,124.98C144.39,124.96 144.57,124.93 144.76,124.92C144.84,124.92 144.93,124.96 145.01,124.98C145.07,124.97 145.14,124.97 145.2,124.96L145.36,124.96C145.39,124.94 145.43,124.94 145.47,124.93C145.58,124.9 145.68,124.88 145.79,124.86C145.81,124.83 145.84,124.8 145.86,124.77C145.89,124.71 145.92,124.64 145.95,124.58C145.96,124.47 145.97,124.37 145.98,124.27C145.99,124.25 145.99,124.24 146,124.22C146.01,124.18 146.01,124.15 146.01,124.12C146.01,124.05 146.01,123.97 146.01,123.91C146.03,123.79 146.05,123.67 146.07,123.55C146.09,123.36 146.12,123.17 146.15,122.99C146.2,122.74 146.26,122.5 146.29,122.26C146.38,121.63 146.7,121.06 146.7,120.41L146.78,120.27C146.84,120.02 146.89,119.76 146.95,119.51C146.99,119.28 147.02,119.04 147.06,118.8C147.13,118.5 147.2,118.2 147.26,117.89C147.31,117.59 147.35,117.28 147.4,116.98C147.4,116.89 147.4,116.8 147.4,116.72L147.45,116.36C147.45,116.26 147.45,116.15 147.45,116.05C147.43,115.96 147.42,115.87 147.4,115.78C147.36,115.67 147.32,115.56 147.28,115.45C147.27,115.42 147.26,115.4 147.25,115.37C147.15,115.26 147.05,115.15 146.95,115.03C146.87,114.96 146.79,114.89 146.71,114.82C146.69,114.82 146.68,114.83 146.66,114.83C146.65,114.82 146.65,114.8 146.64,114.79C146.63,114.79 146.62,114.79 146.61,114.78C146.55,114.77 146.48,114.76 146.41,114.75L146.15,114.71C146.12,114.69 146.09,114.68 146.06,114.66C145.5,114.56 144.94,114.46 144.38,114.36C144.33,114.33 144.28,114.31 144.24,114.28L144.13,114.26C143.93,114.23 143.73,114.2 143.52,114.17C143.2,114.09 142.89,114.01 142.57,113.93C142.43,113.92 142.29,113.9 142.15,113.89C142.07,113.86 141.99,113.84 141.9,113.81C141.85,113.81 141.8,113.79 141.75,113.79C141.65,113.77 141.54,113.75 141.45,113.73C141.16,113.68 140.87,113.64 140.58,113.59C140.4,113.6 140.23,113.6 140.05,113.61C140.02,113.61 139.99,113.61 139.95,113.61C139.93,113.58 139.92,113.57 139.91,113.54C139.53,113.5 139.15,113.46 138.77,113.42C138.58,113.4 138.4,113.38 138.21,113.36C138,113.35 137.79,113.35 137.59,113.34C137.41,113.34 137.23,113.35 137.06,113.35C137.04,113.36 137.02,113.36 137.01,113.38C136.91,113.41 136.81,113.45 136.71,113.49L136.68,113.45L136.66,113.55C136.66,113.55 136.68,113.56 136.69,113.56C136.68,113.57 136.66,113.58 136.65,113.6L136.43,114.97C136.45,115.01 136.46,115.05 136.47,115.08C136.46,115.04 136.45,115.01 136.43,114.97L136.38,115.28L136.37,115.38L136.35,115.48L136.33,115.63L136.32,115.68L136.3,115.83L136.28,115.99L135.46,121.07L135.2,122.7C135.24,122.72 135.29,122.75 135.33,122.77C135.33,122.81 135.32,122.84 135.32,122.88C135.31,122.88 135.3,122.88 135.3,122.89C135.3,122.9 135.3,122.92 135.31,122.93C135.42,123.11 135.54,123.28 135.65,123.46L135.98,123.66L135.98,123.65Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M176.79,150.36C176.79,150.36 176.82,150.33 176.83,150.31C176.67,149.64 176.18,149.03 175.93,148.37C175.71,147.77 175.34,147.27 174.99,146.73C174.98,146.72 174.98,146.7 174.96,146.69L174.95,146.68C174.93,146.67 174.93,146.66 174.93,146.64C174.53,146.1 174.14,145.55 173.75,145C173.68,144.9 173.6,144.8 173.53,144.7C173.47,144.63 173.41,144.57 173.35,144.51C172.81,144.69 172.27,144.85 171.72,145.03C171.71,145.06 171.7,145.09 171.68,145.13C171.62,145.5 171.56,145.87 171.5,146.24C171.49,146.41 171.49,146.59 171.48,146.76C171.45,147.03 171.42,147.31 171.39,147.58C171.39,147.7 171.38,147.82 171.38,147.95C171.37,148.24 171.37,148.54 171.36,148.83C171.35,148.95 171.33,149.07 171.32,149.19C171.27,149.46 171.24,149.73 171.19,150.01C171.2,150.13 171.2,150.25 171.21,150.38C171.26,150.52 171.31,150.67 171.36,150.81L171.66,151.17L171.84,151.31C171.91,151.32 171.98,151.34 172.04,151.35C172.32,151.41 172.58,151.47 172.85,151.53C172.94,151.55 173.02,151.56 173.11,151.57C173.54,151.68 173.98,151.78 174.41,151.87C174.58,151.91 174.76,151.9 174.94,151.92C175.04,151.91 175.13,151.9 175.24,151.9L175.42,151.88C175.59,151.87 175.77,151.87 175.94,151.86C175.98,151.86 176.01,151.86 176.04,151.86C176.15,151.86 176.27,151.86 176.38,151.87C176.56,151.81 176.73,151.75 176.91,151.7C176.93,151.67 176.95,151.64 176.97,151.61C176.98,151.59 176.99,151.58 177,151.56C177.01,151.53 177.03,151.51 177.04,151.49C177.2,151.05 177.06,150.68 176.83,150.31C176.81,150.33 176.8,150.35 176.78,150.36H176.79Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M173.18,144.2L173.17,144.18C173.13,144.14 173.1,144.1 173.06,144.05L172.98,143.93C172.81,143.77 172.6,143.74 172.38,143.75C172.33,143.75 172.28,143.73 172.22,143.72C172.15,143.75 172.04,143.76 172.01,143.82C171.92,143.99 171.87,144.18 171.79,144.36C171.79,144.4 171.79,144.43 171.78,144.46C171.77,144.56 171.75,144.67 171.74,144.77C171.73,144.82 171.72,144.87 171.71,144.92C171.71,144.96 171.71,144.99 171.72,145.03C172.26,144.85 172.8,144.69 173.35,144.51C173.29,144.4 173.23,144.3 173.17,144.2H173.18Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M144.22,139.21C144.21,139.16 144.2,139.11 144.19,139.05C144.14,138.9 144.09,138.74 144.05,138.59C144.01,138.52 143.97,138.46 143.93,138.39C143.19,137.23 141.13,137.41 139.96,137.14C139.19,136.97 138.45,136.9 137.67,136.81C137.12,136.74 136.51,136.34 135.98,136.44L135.88,136.42C135.81,136.41 135.74,136.4 135.67,136.39C135.2,136.31 134.72,136.24 134.24,136.16C134.02,136.06 133.85,136.21 133.68,136.3C133.65,136.41 133.63,136.51 133.6,136.62C133.59,136.67 133.57,136.72 133.56,136.77L133.54,136.88C133.51,136.94 133.47,137 133.43,137.07C133.49,137.19 133.55,137.32 133.61,137.45C133.59,137.44 133.56,137.44 133.54,137.43C133.43,137.76 133.39,138.01 133.38,138.36C133.37,138.4 133.37,138.43 133.36,138.46C133.32,138.79 133.28,139.11 133.24,139.44C133.24,139.48 133.26,139.51 133.26,139.55C133.24,139.72 133.21,139.89 133.19,140.06C133.16,140.24 133.13,140.43 133.1,140.62C133.1,140.67 133.1,140.72 133.1,140.77C132.99,141.38 132.88,141.99 132.77,142.6L132.68,142.9C132.66,143.02 132.65,143.14 132.64,143.26L132.48,143.91C132.44,144.22 132.41,144.53 132.38,144.83C132.38,144.85 132.37,144.87 132.37,144.88C132.36,144.92 132.35,144.95 132.34,144.98C132.33,145.05 132.32,145.12 132.31,145.19C132.35,145.32 132.38,145.44 132.41,145.57C132.44,145.63 132.46,145.69 132.49,145.75C132.53,145.82 132.57,145.89 132.62,145.97C132.63,145.99 132.65,146 132.66,146.02C132.7,146.07 132.75,146.1 132.79,146.15L132.99,146.24C133.2,146.33 133.41,146.41 133.63,146.5C133.81,146.55 134,146.6 134.18,146.64C134.38,146.67 134.59,146.7 134.79,146.73C135.3,146.79 135.82,146.86 136.33,146.92C136.36,146.94 136.39,146.94 136.43,146.96C136.63,147 136.83,147.05 137.03,147.1C137.24,147.15 137.44,147.22 137.65,147.24C138.09,147.3 138.54,147.33 138.98,147.37C139.29,147.41 139.59,147.46 139.9,147.51C140.41,147.59 140.92,147.66 141.43,147.74C141.55,147.76 141.67,147.79 141.79,147.81C141.97,147.84 142.16,147.87 142.35,147.9C142.48,147.86 142.6,147.83 142.73,147.79C142.75,147.77 142.78,147.75 142.8,147.73C142.81,147.72 142.82,147.71 142.83,147.7C142.88,147.67 142.92,147.65 142.97,147.62C143.24,147.04 143.25,146.3 143.34,145.67C143.47,144.85 143.59,144.04 143.73,143.22C143.95,141.92 144.43,140.54 144.22,139.21H144.22Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M204.37,125.79C204.37,125.75 204.38,125.72 204.38,125.68C204.4,125.54 204.41,125.41 204.43,125.28C204.43,125.1 204.43,124.93 204.43,124.75C204.45,124.36 204.46,123.96 204.48,123.57C204.41,123.43 204.33,123.29 204.26,123.16C204.04,122.84 203.72,122.75 203.36,122.69C202.71,122.6 202.06,122.45 201.4,122.33C201.15,122.27 200.9,122.21 200.65,122.15C200.68,122.09 200.7,122.03 200.73,121.96L199.15,121.71C199.15,121.78 199.16,121.85 199.17,121.92C198.75,121.88 198.34,121.85 197.93,121.82H197.9L197.88,121.81C196.72,121.68 195.58,121.35 194.41,121.2C194.3,121.19 194.2,121.18 194.09,121.17L194,121.19C193.78,121.25 193.56,121.3 193.35,121.36C193.27,121.42 193.2,121.48 193.13,121.54C193.06,121.63 192.99,121.72 192.91,121.81L192.73,122.87C192.7,122.97 192.67,123.07 192.64,123.17C192.62,123.32 192.59,123.46 192.56,123.61C192.55,123.61 192.53,123.62 192.52,123.63C192.52,123.66 192.51,123.69 192.51,123.73L192.49,123.72L192.31,124.42C192.27,124.58 192.24,124.72 192.2,124.88L192.2,125.03C192.12,125.46 192.04,125.89 191.99,126.32C191.97,126.45 192.04,126.58 192.07,126.71C192.12,126.78 192.16,126.87 192.21,126.94C192.4,127.15 192.59,127.36 192.78,127.56C192.83,127.63 192.89,127.7 192.95,127.76L193.09,127.92C193.13,127.97 193.17,128.02 193.21,128.07C193.39,128.26 193.57,128.46 193.75,128.66C193.84,128.76 193.93,128.87 194.02,128.97C194.09,129.06 194.16,129.15 194.23,129.23L194.27,129.28C194.33,129.34 194.39,129.4 194.46,129.45C194.79,129.86 195.12,130.27 195.46,130.68C195.69,130.94 195.92,131.21 196.16,131.46C196.22,131.55 196.29,131.64 196.35,131.73C196.39,131.77 196.43,131.8 196.47,131.84C196.47,131.84 196.47,131.86 196.47,131.87C196.59,131.99 196.71,132.12 196.83,132.24C196.85,132.27 196.86,132.3 196.88,132.33C197,132.45 197.11,132.57 197.23,132.68C197.23,132.7 197.23,132.71 197.23,132.72C197.3,132.81 197.38,132.9 197.45,132.99C197.61,133.07 197.77,133.13 197.93,133.21C197.99,133.2 198.04,133.19 198.1,133.18C198.39,133.23 198.67,133.28 198.96,133.33C198.98,133.33 198.99,133.32 199.01,133.32C199.25,133.38 199.49,133.43 199.72,133.48C199.98,133.52 200.23,133.57 200.49,133.6C200.55,133.62 200.62,133.64 200.69,133.65C200.99,133.68 201.31,133.71 201.61,133.73C201.74,133.74 201.86,133.74 201.98,133.75C202.22,133.68 202.45,133.61 202.69,133.55C202.78,133.5 202.86,133.45 202.94,133.4C202.98,133.38 203.01,133.36 203.04,133.35C203.07,133.29 203.1,133.25 203.13,133.19H203.11C203.13,133.16 203.15,133.13 203.18,133.1C203.19,133.08 203.2,133.07 203.21,133.05C203.23,132.97 203.25,132.88 203.27,132.8C203.29,132.75 203.3,132.7 203.32,132.65C203.33,132.58 203.34,132.51 203.35,132.45C203.4,132.21 203.46,131.98 203.51,131.74C203.93,129.81 204.22,127.75 204.37,125.78V125.79Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M155.22,125.79C155.28,125.86 155.34,125.94 155.4,126.03C155.47,126.09 155.54,126.16 155.62,126.22C155.65,126.25 155.69,126.26 155.72,126.29C156.45,126.73 157.21,127.11 158.08,127.25C158.21,127.26 158.35,127.28 158.49,127.29C158.79,127.35 159.1,127.4 159.4,127.46C159.49,127.46 159.57,127.47 159.66,127.48C159.86,127.51 160.07,127.55 160.27,127.59C160.29,127.58 160.31,127.57 160.33,127.56C160.35,127.56 160.37,127.56 160.38,127.56C160.66,127.57 160.93,127.58 161.21,127.59C161.35,127.63 161.48,127.66 161.61,127.7C161.63,127.69 161.65,127.68 161.67,127.67C161.72,127.68 161.77,127.68 161.82,127.69C161.84,127.68 161.86,127.68 161.88,127.67C161.91,127.67 161.95,127.66 161.99,127.65C162.03,127.66 162.08,127.67 162.13,127.67L162.22,127.59C162.22,127.59 162.25,127.59 162.26,127.57C162.33,127.51 162.41,127.45 162.49,127.39C162.51,127.26 162.53,127.13 162.55,126.99C162.55,126.96 162.54,126.93 162.53,126.9C162.51,126.86 162.5,126.83 162.49,126.79C162.44,126.73 162.39,126.66 162.35,126.6C162.35,126.6 162.34,126.56 162.32,126.56C162.32,126.56 162.32,126.52 162.32,126.5C162.31,126.5 162.29,126.5 162.27,126.5L162.28,126.48C162.28,126.48 162.26,126.45 162.25,126.44C161.95,125.85 161.64,125.25 161.34,124.66C161.3,124.58 161.27,124.5 161.24,124.42C161.22,124.36 161.19,124.3 161.17,124.24H161.17C161.17,124.24 161.15,124.2 161.14,124.18C161.04,124 160.95,123.83 160.86,123.66C160.74,123.38 160.62,123.1 160.5,122.82C160.46,122.75 160.41,122.67 160.37,122.6C160.31,122.47 160.25,122.34 160.18,122.21L159.86,121.57C159.82,121.51 159.79,121.45 159.75,121.39C159.72,121.33 159.7,121.28 159.66,121.22C159.57,121.05 159.47,120.89 159.38,120.71C159.33,120.64 159.28,120.56 159.23,120.47C159.17,120.36 159.11,120.25 159.05,120.14C159.04,120.12 159.03,120.1 159.02,120.08C159.01,120.05 159.01,120.03 159,120L158.73,119.51C158.67,119.41 158.62,119.31 158.57,119.22L158.21,118.53L158.13,118.38C157.99,118.14 157.85,117.91 157.71,117.67C157.64,117.68 157.56,117.69 157.49,117.7C157.29,117.73 157.13,117.76 156.98,117.82C157.13,117.76 157.29,117.72 157.49,117.7C157.56,117.69 157.63,117.68 157.71,117.67C157.72,117.65 157.72,117.64 157.72,117.63C157.68,117.55 157.64,117.48 157.6,117.4C157.58,117.34 157.55,117.28 157.52,117.23C157.48,117.15 157.45,117.07 157.41,116.99C157.4,116.96 157.38,116.93 157.36,116.9C157.28,116.78 157.2,116.65 157.12,116.53C157.05,116.49 156.99,116.44 156.93,116.39C156.91,116.39 156.9,116.39 156.88,116.38L156.42,116.32C156.32,116.37 156.23,116.43 156.14,116.49C156.06,116.66 155.98,116.83 155.89,117.01C156.11,117.21 155.84,117.8 155.79,118.04C155.69,118.51 155.6,118.99 155.5,119.46C155.46,119.68 155.42,119.9 155.37,120.11C155.36,120.16 155.35,120.21 155.34,120.26C155.29,120.52 155.24,120.77 155.2,121.02C155.19,121.09 155.18,121.16 155.18,121.23C155.17,121.35 155.17,121.47 155.16,121.59L155.09,121.95C155.09,122.03 155.09,122.12 155.09,122.21C155.07,122.5 155.04,122.79 155.02,123.08C154.98,123.29 154.95,123.49 154.92,123.69C154.91,123.72 154.9,123.76 154.9,123.79C154.9,123.81 154.91,123.83 154.92,123.85L154.91,124.11V124.32C154.91,124.47 154.91,124.63 154.91,124.79C154.99,125.09 155.08,125.4 155.16,125.7C155.18,125.72 155.19,125.74 155.21,125.77L155.22,125.79ZM159.87,125.49C159.54,125.42 159.19,125.38 158.88,125.28C159.19,125.38 159.54,125.42 159.87,125.49Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M163.1,142.55C163.06,142.49 163.02,142.43 162.98,142.38C162.9,142.12 162.83,141.87 162.73,141.63C162.46,141 161.87,140.89 161.3,140.75C160.62,140.28 159.67,140.28 158.92,139.95C158.71,139.91 158.51,139.88 158.3,139.84L157.38,139.7C157.3,139.69 157.21,139.67 157.13,139.66C156.9,139.65 156.67,139.63 156.45,139.61C156.16,139.57 155.88,139.53 155.59,139.49C155.52,139.49 155.45,139.49 155.38,139.5C155.24,139.45 155.11,139.4 155.05,139.38C154.72,139.42 154.47,139.4 154.15,139.34C153.87,139.28 153.58,139.2 153.3,139.18C153.18,139.16 153.06,139.28 152.93,139.33C152.93,139.35 152.91,139.35 152.9,139.35C152.88,139.42 152.87,139.49 152.85,139.55C152.85,139.57 152.86,139.59 152.86,139.61C152.84,139.73 152.82,139.84 152.79,139.96C152.8,139.96 152.82,139.97 152.84,139.97C152.84,140.01 152.84,140.04 152.84,140.07C152.8,140.38 152.76,140.69 152.73,140.99C152.68,141.31 152.62,141.62 152.58,141.93C152.57,142.06 152.58,142.2 152.58,142.33C152.39,143.84 152.09,145.31 151.99,146.83C151.99,146.86 151.98,146.9 151.98,146.93C151.98,147.18 151.98,147.42 151.98,147.66C152.06,147.99 152.07,148.35 152.36,148.59C152.38,148.6 152.39,148.61 152.4,148.62C152.43,148.64 152.44,148.66 152.47,148.67C152.64,148.77 152.81,148.86 152.98,148.96C153.07,149.01 153.17,149.06 153.26,149.12C153.43,149.16 153.6,149.21 153.76,149.26L154.07,149.32C154.1,149.33 154.13,149.34 154.17,149.35C156.2,149.64 158.23,149.94 160.26,150.2C160.34,150.21 160.43,150.22 160.51,150.24L160.82,150.29C160.85,150.29 160.89,150.3 160.92,150.3C160.98,150.31 161.03,150.31 161.08,150.32C161.17,150.29 161.26,150.27 161.35,150.25C161.41,150.18 161.48,150.1 161.54,150.03C161.56,150.03 161.57,150.03 161.59,150.02C161.6,149.99 161.6,149.96 161.61,149.94C161.62,149.94 161.63,149.94 161.65,149.94C161.66,149.92 161.66,149.91 161.66,149.89C161.67,149.86 161.68,149.83 161.7,149.8L161.87,148.93C161.9,148.76 161.92,148.6 161.95,148.43C161.98,148.36 162.02,148.29 162.04,148.22C162.13,147.93 162.21,147.63 162.3,147.34C162.3,147.3 162.31,147.27 162.32,147.23C162.36,146.96 162.4,146.69 162.44,146.42C162.46,146.34 162.47,146.25 162.49,146.16C162.5,146.1 162.51,146.03 162.52,145.96C162.58,145.62 162.63,145.28 162.69,144.94C162.71,144.84 162.73,144.74 162.74,144.64C162.75,144.59 162.76,144.53 162.77,144.48C162.8,144.29 162.83,144.11 162.85,143.93C162.86,143.89 162.86,143.86 162.87,143.82C162.89,143.75 162.91,143.69 162.93,143.62C162.92,143.53 162.9,143.44 162.88,143.35L162.91,143.2C162.91,143.17 162.91,143.13 162.91,143.1C162.98,142.92 163.04,142.74 163.11,142.56L163.1,142.55ZM157.15,148.84C157.15,148.84 157.13,148.82 157.12,148.81C157.13,148.82 157.14,148.82 157.15,148.84Z" - android:fillColor="#9958F6"/> - <path - android:pathData="M224.18,77.48C224.13,76.87 224,76.25 224.07,75.65C224.38,73.02 224.75,70.41 225.1,67.79C225.5,64.86 226.03,61.95 226.26,59.01C226.92,50.94 228.58,43.03 229.7,35.03C229.99,32.95 229.97,30.83 230.11,28.73C230.19,27.65 230.2,26.54 230.43,25.48C231.03,22.89 230.25,20.58 229.01,18.41C227.88,16.43 226.26,14.82 224.2,13.83C222.46,12.99 220.6,12.35 218.73,11.8C216.39,11.11 214,10.61 211.63,10.01C211.45,9.97 211.3,9.84 211.14,9.75L208.28,9.29C207.6,9.31 206.91,9.43 206.25,9.33C204.3,9.04 202.36,8.67 200.42,8.32C199.14,8.09 197.87,7.87 196.6,7.62C196.26,7.55 195.94,7.38 195.62,7.26L193.58,6.93C193.43,6.98 193.26,7.09 193.12,7.07C191.09,6.75 189.06,6.43 187.03,6.09C186.89,6.07 186.76,5.91 186.63,5.82L182.34,5.13C182.23,5.19 182.11,5.3 182.01,5.29C179.89,4.96 177.77,4.63 175.65,4.28C175.56,4.26 175.48,4.11 175.39,4.02L174.58,3.89C174.4,3.93 174.21,4.03 174.04,4.01C171.32,3.66 168.61,3.27 165.89,2.94C163.11,2.6 160.34,2.23 157.56,2.03C154.9,1.84 152.23,1.85 149.57,1.76C147.2,1.68 145.2,2.69 143.27,3.9C139.98,5.97 138.17,9.05 137.34,12.76C136.92,14.63 136.59,16.52 136.21,18.4C135.88,20.08 135.54,21.75 135.18,23.42C135.15,23.55 134.88,23.62 134.73,23.72L134.63,24.34C134.75,24.44 134.99,24.56 134.98,24.65C134.88,25.84 134.8,27.03 134.62,28.21C134.46,29.22 134.11,30.2 133.96,31.21C133.72,32.83 133.6,34.47 133.37,36.09C132.59,41.53 131.76,46.98 130.98,52.42C130.81,53.6 130.73,54.79 130.62,55.98C130.42,58.01 130.24,60.04 130.05,62.07C130.01,62.6 129.95,63.13 129.94,63.67C129.91,64.74 130.09,65.86 129.86,66.88C129.64,67.8 129.45,68.64 129.42,69.62C129.32,72.3 128.91,74.98 128.6,77.66C128.47,78.68 128.26,79.69 128.09,80.71C128.07,80.8 127.97,80.88 127.95,80.97C127.77,81.84 127.59,82.72 127.42,83.59C127.53,83.82 127.64,84.05 127.75,84.28C127.73,84.41 127.69,84.55 127.71,84.69C127.84,86.84 128.05,89 128.1,91.16C128.15,93.21 128.08,95.27 127.96,97.32C127.83,99.38 127.59,101.44 127.39,103.5C127.26,104.75 127.09,106 127.03,107.25C127.01,107.54 127.3,108.04 127.55,108.11C128.21,108.29 128.18,107.68 128.25,107.26C129.32,101.02 130.39,94.77 131.45,88.53C132.95,79.62 134.44,70.72 135.93,61.81C136.65,57.49 137.32,53.16 138.04,48.84C139.18,42.08 140.33,35.33 141.5,28.57C141.73,27.26 142.11,25.98 142.32,24.67C142.57,23.02 142.69,21.34 142.93,19.69C143.06,18.85 143.6,17.98 143.46,17.22C143.24,16.04 143.45,15.03 143.83,13.96C144.58,11.85 145.93,10.25 147.94,9.28C150.51,8.03 153.25,7.82 156.02,8.27C162.75,9.35 169.48,10.4 176.28,10.94C179.81,11.22 183.29,12.01 186.8,12.58C187,12.66 187.2,12.75 187.4,12.83C187.76,12.91 188.13,12.99 188.51,13.04C192.5,13.63 196.49,14.2 200.49,14.78C200.61,14.85 200.75,14.92 200.88,14.99C204.17,15.53 207.46,16.08 210.75,16.6C211.3,16.69 211.89,16.6 212.44,16.73C213.22,16.91 214,17.15 214.73,17.47C216.7,18.31 218.63,19.2 220.59,20.08C220.65,20.14 220.71,20.21 220.77,20.27C221.58,21.4 222.4,22.52 223.21,23.64L223.34,23.87C223.52,24.33 223.8,24.77 223.88,25.25C224.06,26.34 224.17,27.45 224.24,28.56C224.27,28.93 224.09,29.3 224.01,29.68C223.75,30.96 223.49,32.23 223.23,33.51C223.48,33.68 223.72,33.85 223.97,34.03C223.81,34.15 223.66,34.27 223.51,34.4C223.28,35.89 223.05,37.38 222.81,38.87C222.67,39.79 222.46,40.69 222.4,41.61C222.38,42.03 221.55,42.27 222.16,42.78L222.3,43.22C222.01,45.1 221.72,46.97 221.43,48.84C221.29,49.76 221.15,50.68 221.02,51.6C221.04,51.75 221.07,51.89 221.1,52.04C220.68,54.63 220.27,57.22 219.85,59.81C219.89,60.03 219.93,60.24 219.96,60.46C219.62,62.63 219.26,64.8 218.95,66.98C218.89,67.33 218.98,67.7 219.01,68.06C219.09,68.14 219.18,68.23 219.27,68.31C219.16,68.36 219.05,68.42 218.94,68.47C218.55,71.26 218.16,74.04 217.78,76.83C217.39,79.68 217,82.54 216.62,85.39C216.19,88.52 215.75,91.65 215.33,94.78C214.99,97.3 214.66,99.81 214.32,102.33C213.93,105.25 213.54,108.18 213.12,111.1C212.34,116.48 211.54,121.85 210.75,127.23C210.74,127.3 210.7,127.37 210.72,127.43C210.8,127.7 210.84,128.11 211.01,128.18C211.28,128.29 211.78,128.29 211.95,128.12C213.01,127 214.07,125.88 215.01,124.66C216.59,122.6 216.95,120.16 216.86,117.63C216.18,116.87 216.24,116.5 217.13,116C217.49,114.19 217.91,112.4 218.21,110.58C218.54,108.56 218.69,106.51 219.02,104.49C219.48,101.72 220.04,98.97 220.55,96.22C220.65,95.95 220.75,95.68 220.85,95.41C221.22,93.14 221.56,90.86 221.99,88.6C222.14,87.8 222.5,87.05 222.76,86.28L222.93,85.26C222.9,85.05 222.87,84.84 222.84,84.63C222.9,84.29 222.95,83.95 223.01,83.62C223.22,82.25 223.41,80.88 223.64,79.51C223.68,79.3 223.84,79.11 223.94,78.92L224.17,77.48L224.18,77.48Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M218.31,69.3C218.26,69.64 218.2,69.97 218.15,70.31C218.17,70.52 218.2,70.73 218.23,70.94L218.33,70.32L218.49,69.3C218.74,67.74 218.99,66.17 219.24,64.6C219.14,64.8 218.98,64.98 218.95,65.19C218.72,66.56 218.52,67.93 218.31,69.3L218.31,69.3Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M157.6,188.9C156.58,188.65 155.66,188.33 154.73,188.2C150.79,187.68 146.85,187.28 142.93,186.69C139.54,186.18 136.17,185.52 132.8,184.87C131.41,184.6 130.04,184.18 128.67,183.81C127.22,183.44 125.78,183.06 124.33,182.67C123.69,182.49 123.35,182.73 123.06,183.31C122.25,184.92 121.4,186.51 120.55,188.09C120.01,189.1 120.15,189.83 121.16,190.31C121.97,190.69 122.85,190.99 123.72,191.17C126.14,191.67 128.56,192.08 130.98,192.56C134.3,193.22 137.6,193.95 140.92,194.56C143.87,195.1 146.83,195.57 149.8,195.96C151.81,196.23 153.84,196.28 155.87,196.45C156.7,196.52 157.53,196.6 158.35,196.74C159.62,196.97 160.09,196.49 159.7,195.28C159.01,193.15 158.3,191.02 157.6,188.89V188.9Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M212.17,103.31L212.43,101.68C211.54,102.18 211.48,102.56 212.17,103.31Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M219.27,19.71C219.03,19.54 218.78,19.36 218.54,19.19C218.63,19.48 218.73,19.78 218.82,20.07C218.97,19.95 219.12,19.83 219.27,19.7V19.71Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M214.26,54.15C214.37,54.1 214.47,54.04 214.58,53.99C214.49,53.91 214.41,53.82 214.32,53.74C214.3,53.88 214.28,54.01 214.26,54.15Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M286.67,287.65C286.51,287.29 286.35,286.93 286.18,286.57C285.53,285.05 284.87,283.54 284.21,282.02C284.06,281.65 283.9,281.29 283.74,280.92C283.15,279.89 282.56,278.85 281.96,277.82C279.93,274.29 278.01,270.7 277.21,266.67C276.33,262.11 275.58,257.52 274.86,252.93C274.5,250.63 274.32,248.3 274.06,245.99C274.01,245.58 273.96,245.16 273.91,244.74C273.91,244.37 273.91,244 273.91,243.63C273.83,243.37 273.75,243.11 273.67,242.85C273.38,239.07 273.1,235.3 272.81,231.52C272.76,231.11 272.71,230.69 272.66,230.28C272.61,229.91 272.55,229.54 272.52,229.17C272.03,223.97 271.55,218.77 271.04,213.58C270.76,210.74 270.43,207.91 270.13,205.08C270.17,204.81 270.21,204.54 270.26,204.27C270.08,203.49 269.92,202.71 269.75,201.93C269.77,201.83 269.78,201.74 269.8,201.64C269.8,201.4 269.87,201.15 269.81,200.94C269.44,199.6 269.05,198.26 268.66,196.92C268.68,196.83 268.7,196.73 268.71,196.64C268.54,196.13 268.35,195.62 268.19,195.11C267.33,192.34 266.45,189.58 265.62,186.81C265.46,186.27 265.63,185.61 265.41,185.12C264.65,183.48 263.79,181.88 262.95,180.28C262.04,178.52 261.13,176.76 260.16,175.04C259.85,174.49 259.39,173.99 258.91,173.56C257.25,172.03 255.49,170.66 253.25,170.04C252.8,169.92 252.4,169.48 252.03,170.07C251.76,170.51 251.33,170.93 252.02,171.48C252.29,171.69 252.24,172.31 252.34,172.74C252.2,172.79 252.07,172.83 251.94,172.88C250.7,171.05 249.45,169.22 248.21,167.38C247.13,165.76 246.2,164.01 244.98,162.5C242.62,159.59 239.78,157.21 236.63,155.15C234.58,153.81 232.5,152.63 230.16,151.93C229.86,151.84 229.23,151.92 229.17,152.07C229.05,152.39 229.08,152.92 229.28,153.18C230.49,154.79 231.76,156.34 233,157.92C233.99,159.19 234.99,160.46 235.94,161.76C236.17,162.07 236.25,162.5 236.5,163.13C236.1,162.88 235.93,162.82 235.83,162.71C234.59,161.3 233.28,159.94 232.12,158.47C229.67,155.37 227.17,152.29 224.02,149.92C221.87,148.3 219.5,146.71 216.98,145.93C213.72,144.91 210.21,144.71 206.81,144.18C206.57,144.14 206.15,144.2 206.08,144.34C205.97,144.57 206,144.96 206.14,145.17C206.53,145.76 207.05,146.27 207.45,146.86C208.76,148.81 210.04,150.8 211.36,152.75C213.49,155.89 215.67,159.01 217.77,162.18C218.22,162.87 218.4,163.73 218.71,164.51C218.68,164.61 218.65,164.71 218.63,164.81C218.45,164.65 218.23,164.52 218.09,164.33C215.7,160.96 213.34,157.56 210.94,154.2C208.42,150.68 205.87,147.18 203.31,143.7C203,143.28 202.43,143.05 202.1,142.65C201.36,141.71 200.77,140.66 199.99,139.76C197.78,137.2 195.48,134.72 193.27,132.17C191.83,130.51 190.49,128.77 189.09,127.08C187.26,124.85 185.39,122.65 183.58,120.42C182.73,119.38 182.01,118.24 181.15,117.22C179.36,115.12 177.37,113.18 175.73,110.97C173.69,108.24 171.64,105.55 169.16,103.19C168.62,102.68 168.24,102.76 167.75,103.17C167.06,103.75 166.4,104.38 165.64,104.84C163.27,106.3 160.84,105.85 159.26,103.56C158.26,102.1 157.45,100.5 156.58,98.95C156.07,98.05 155.5,97.17 155.18,96.21C154.57,94.39 155.32,92.75 156.18,91.18C156.71,90.2 156.6,90.1 155.51,89.77C153.7,89.2 152.53,89.64 151.68,91.41C150.8,93.24 149.76,95.06 149.85,97.1C149.96,99.52 150.45,101.93 150.78,104.35C150.92,104.65 151.06,104.95 151.21,105.25C151.8,106.61 152.4,107.96 152.99,109.32C153.17,109.67 153.35,110.01 153.53,110.36C153.87,110.94 154.22,111.52 154.56,112.1C154.6,112.16 154.65,112.24 154.69,112.3C154.8,112.54 154.92,112.78 155.04,113.01C155.08,113.08 155.12,113.15 155.17,113.22C155.66,114.15 156.16,115.07 156.65,115.99C156.7,116.07 156.74,116.14 156.79,116.21C157.21,117.13 157.64,118.04 158.07,118.95L158.2,119.16C158.54,119.78 158.87,120.4 159.2,121.01C159.25,121.09 159.29,121.16 159.34,121.23L161.58,125.8C161.63,125.87 161.67,125.95 161.71,126.02C162.31,127.05 162.87,128.09 163.5,129.09C164.67,130.96 165.89,132.8 167.09,134.66C167.13,134.73 167.18,134.8 167.22,134.87C167.34,135.1 167.45,135.34 167.57,135.57C167.62,135.64 167.66,135.72 167.7,135.79C167.82,136.02 167.94,136.26 168.06,136.49C168.1,136.56 168.15,136.63 168.19,136.7C168.31,136.94 168.43,137.17 168.54,137.4C168.59,137.48 168.63,137.54 168.67,137.62L169.19,138.55C169.24,138.63 169.28,138.7 169.33,138.77C170.31,140.33 171.27,141.9 172.27,143.45C173.36,145.11 174.49,146.75 175.6,148.39C175.64,148.46 175.68,148.54 175.72,148.6C176.31,149.82 176.9,151.04 177.49,152.26C177.53,152.33 177.58,152.4 177.62,152.47C177.74,152.71 177.86,152.95 177.97,153.18C178.02,153.25 178.06,153.32 178.1,153.39C178.67,154.67 179.24,155.96 179.81,157.24C179.91,157.45 180.01,157.67 180.12,157.88C180.34,158.77 180.56,159.65 180.78,160.54C180.86,160.83 180.93,161.11 181.01,161.4C181.08,161.6 181.15,161.79 181.2,161.98C182.37,166.11 183.5,170.26 184.72,174.37C185.72,177.73 186.89,181.02 187.85,184.38C189.32,189.55 190.06,194.87 190.79,200.18C190.84,200.52 190.71,201.06 190.46,201.23C190.24,201.39 189.65,201.29 189.4,201.08C188.08,199.96 186.77,198.81 185.52,197.6C183.05,195.21 181.02,192.56 180.08,189.13C179.2,185.95 178.08,182.84 177,179.73C176.03,176.95 174.91,174.25 173.25,171.79C171.01,168.49 169.35,164.84 166.63,161.82C164.23,159.15 161.68,156.89 158.18,155.86C156.74,155.44 155.06,155.83 154.25,156.93C154.14,157.19 154.01,157.45 153.9,157.7C153.71,158.59 154.27,158.74 154.91,158.63C155.9,158.44 156.47,158.85 157.05,159.61C158.2,161.07 159.05,162.67 159.6,164.41C160.43,167.02 161.19,169.65 161.98,172.26C161.77,172.56 161.55,172.86 161.35,173.16C160.24,174.51 158.71,175.15 157.11,175.67C157.04,175.71 156.96,175.76 156.89,175.8C156.67,175.88 156.45,175.99 156.21,176.04C154.76,176.36 154.56,176.62 154.92,178.08C155.21,179.25 155.66,180.39 155.98,181.56C156.57,183.7 157.04,185.88 157.72,187.99C158.23,189.55 159.11,191 159.64,192.55C160.78,195.85 161.85,199.17 162.87,202.51C165.05,209.63 167.18,216.77 169.32,223.91C169.59,224.78 169.75,225.68 169.97,226.57C169.93,226.57 169.9,226.57 169.87,226.58C169.85,226.6 169.82,226.65 169.83,226.66C170.08,227.01 170.34,227.35 170.59,227.71L170.68,228.56C170.84,228.86 171,229.16 171.16,229.46C171.57,230.41 171.97,231.37 172.38,232.32C173.77,235.51 175.16,238.7 176.55,241.88C176.59,241.95 176.64,242.02 176.68,242.09C177.02,242.71 177.35,243.33 177.68,243.95C177.73,244.02 177.77,244.09 177.82,244.17C177.99,244.48 178.16,244.79 178.34,245.1C178.38,245.18 178.43,245.25 178.47,245.32C178.64,245.63 178.82,245.95 178.99,246.26L179.13,246.48C179.47,247.1 179.82,247.71 180.16,248.33C180.31,248.57 180.45,248.81 180.6,249.04C181.47,250.16 182.33,251.27 183.2,252.39L183.58,252.83C184.1,253.42 184.64,254 185.16,254.59L185.53,255.02C190.35,259.32 195.47,263.21 200.83,266.81C201.08,266.97 201.33,267.14 201.59,267.31C204.62,269.36 207.73,271.31 210.67,273.48C212.23,274.63 213.59,276.08 214.89,277.53C218.62,281.7 220.29,286.86 221.72,292.12C221.8,292.42 221.88,292.71 221.96,293C222.05,293.3 222.19,293.59 222.21,293.89C222.62,298.58 223.01,303.28 223.41,307.98C223.48,308.79 223.29,309.79 224.31,310.14C225.34,310.48 226.42,310.73 227.5,310.86C229.46,311.1 231.43,311.26 233.4,311.39C235.16,311.5 236.93,311.67 238.68,311.58C241.11,311.45 243.54,311.18 245.95,310.85C253.18,309.86 260.22,308.15 267.02,305.46C271.41,303.72 275.7,301.76 279.68,299.2C281.18,298.24 282.63,297.2 284.03,296.12C285.6,294.91 287.09,293.62 288.62,292.36L288.78,291.34C288.07,290.11 287.36,288.87 286.65,287.64L286.67,287.65Z" - android:fillColor="#85583D"/> - <path - android:pathData="M165.09,211.94C163.87,208.12 162.63,204.29 161.4,200.47C160.91,198.97 160.77,198.96 159.21,198.91C158.15,198.87 157.11,198.6 156.04,198.42C155.68,198.52 155.22,198.76 154.77,198.74C153.53,198.67 152.28,198.58 151.07,198.36C145.96,197.44 140.87,196.47 135.77,195.51C133.24,195.03 130.71,194.54 128.18,194.08C127.13,193.88 126.06,193.79 125.01,193.56C123.56,193.23 122.07,192.92 120.89,191.88C120.28,191.33 119.83,191.49 119.42,192.18C118.94,193 118.38,193.76 117.86,194.55C116.55,196.16 115.36,197.88 113.71,199.15C113.62,199.07 113.51,198.99 113.42,198.9C114.58,197.39 115.74,195.87 116.9,194.35C117.3,193.68 117.74,193.03 118.11,192.34C118.96,190.7 119.75,189.02 120.61,187.39C120.88,186.88 121.44,186.49 121.63,185.96C122.21,184.38 122.66,182.76 123.18,181.15C123.43,180.42 123.65,179.61 123.96,178.97C124.24,178.36 124.36,177.97 124.29,177.43C124.52,177.03 124.62,176.6 124.72,176.18C124.78,175.98 124.82,175.79 124.87,175.6C125.16,174.51 125.47,173.42 125.71,172.32C125.75,172.12 125.29,171.73 125.36,171.64C126.27,170.41 125.79,169.09 125.65,167.81C125.58,167.07 125.2,166.33 125.27,165.62C125.36,164.7 125.75,163.81 126.01,162.91C125.9,162.68 125.79,162.45 125.68,162.22C125.68,161.88 125.72,161.54 125.69,161.2C125.46,158.22 125.22,155.24 124.98,152.25C125.01,152.05 125.04,151.84 125.06,151.63C125.07,151.57 125.09,151.5 125.11,151.43C124.99,151.27 124.87,151.11 124.76,150.95C124.67,150.23 124.57,149.53 124.49,148.82C124.51,148.61 124.54,148.4 124.56,148.19C124.58,148.13 124.59,148.06 124.61,148C124.5,147.83 124.38,147.67 124.26,147.51C124.02,144.85 123.74,142.19 123.56,139.53C123.44,137.74 123.48,135.94 123.46,134.15C123.44,132.71 124.31,131.3 123.56,129.84C123.53,129.8 123.58,129.71 123.59,129.65C123.9,127.67 124.24,125.68 124.48,123.69C124.61,122.63 124.5,121.53 124.6,120.46C124.77,118.65 125.01,116.85 125.24,115.05C125.29,114.61 125.42,114.17 125.46,113.73C125.75,109.79 126,105.85 126.33,101.92C126.53,99.46 127.04,97.01 127.02,94.56C126.99,91.26 126.6,87.97 126.36,84.68C126.11,81.31 125.08,78.12 124.11,74.92C124,74.78 123.89,74.63 123.78,74.49C123.37,73.85 122.97,73.21 122.57,72.57C122.49,72.35 122.4,72.12 122.32,71.9C122.26,71.83 122.2,71.77 122.14,71.7C121.36,70.75 120.61,69.77 119.79,68.86C119.04,68.03 118.28,67.18 117.38,66.54C116.57,65.97 115.6,65.58 114.65,65.3C113.46,64.93 112.22,64.59 111,65.26C110.69,65.49 110.37,65.72 110.06,65.95C109.57,66.57 109.06,67.18 108.61,67.82C108.15,68.46 108.58,69.55 109.29,69.59C111.62,69.74 112.05,70.06 112.78,72.25C112.87,72.62 112.97,72.98 113.06,73.35C113.26,76.71 113.57,80.07 113.63,83.43C113.67,85.58 113.25,87.69 111,88.8C110.93,88.84 110.85,88.88 110.78,88.92C110.07,89.1 109.35,89.26 108.64,89.47C108.38,89.55 108.01,89.71 107.93,89.92C107.59,90.89 107.28,91.88 107.07,92.88C106.77,94.28 106.7,95.75 106.29,97.11C105.64,99.29 104.79,101.41 104.02,103.55C103.8,103.73 103.57,103.91 103.35,104.09L103.33,104.29C103.36,104.44 103.4,104.58 103.43,104.72C102.7,106.49 102.06,108.31 101.2,110.01C100.07,112.25 98.76,114.39 97.53,116.58C97.42,116.84 97.32,117.1 97.21,117.36C95.96,119.95 94.71,122.54 93.45,125.11C93.23,125.54 92.89,125.92 92.61,126.33C92.55,126.37 92.49,126.42 92.42,126.46C92.42,126.53 92.41,126.59 92.4,126.66L92.5,127.1C91.43,129.38 90.37,131.66 89.3,133.94C89.24,134.36 89.21,134.81 88.58,134.65C88.58,135.02 88.68,135.43 88.56,135.75C87.74,137.96 86.9,140.16 86,142.34C85.78,142.89 85.21,143.29 85.01,143.85C84.42,145.49 83.95,147.18 83.37,148.82C83.15,149.47 82.66,150.03 82.48,150.68C81.95,152.58 81.55,154.5 81.03,156.4C80.77,157.37 80.3,158.26 80.15,159.3C79.88,161.14 79.27,162.94 78.91,164.77C78.36,167.56 77.88,170.37 77.39,173.17C77.29,173.71 77.3,174.27 77.2,174.81C76.26,180.02 75.32,185.24 74.36,190.44C74.08,191.96 73.79,193.47 73.41,194.96C73.2,195.77 72.8,196.52 72.42,197.46C72.97,198.27 72.2,199.14 71.97,200.06C71.57,201.67 71.14,203.28 70.63,204.85C70.4,205.57 69.7,206.21 69.69,206.89C69.66,208.67 68.82,210.16 68.16,211.68C66.11,216.4 63.87,221.04 61.82,225.75C60.07,229.77 57.79,233.49 55.28,237.03C52.9,240.38 50.08,243.4 47.47,246.59C46.96,247.21 46.34,247.87 46.81,248.79C48.13,251.36 49.35,254 50.85,256.46C52.22,258.7 53.85,260.79 55.47,262.85C57.03,264.82 58.73,266.67 60.37,268.58C60.43,268.64 60.49,268.71 60.54,268.77L62.53,270.81C62.58,270.88 62.64,270.94 62.7,271.01C62.89,271.19 63.07,271.37 63.26,271.56C63.31,271.62 63.37,271.68 63.42,271.75C63.55,271.85 63.67,271.96 63.8,272.07C63.85,272.13 63.91,272.2 63.97,272.26C65.19,273.38 66.41,274.5 67.63,275.62C67.69,275.68 67.75,275.75 67.81,275.81C67.93,275.92 68.06,276.02 68.18,276.13C68.24,276.19 68.3,276.26 68.35,276.32C68.6,276.52 68.85,276.71 69.1,276.91C69.16,276.97 69.22,277.03 69.28,277.1C69.53,277.29 69.78,277.49 70.03,277.68C70.09,277.75 70.15,277.81 70.21,277.87C70.46,278.07 70.71,278.27 70.96,278.46C71.02,278.52 71.07,278.58 71.13,278.64C71.63,279.02 72.13,279.4 72.63,279.78C72.69,279.84 72.75,279.9 72.81,279.97C73.44,280.43 74.06,280.9 74.69,281.37C74.75,281.43 74.81,281.49 74.86,281.55C74.93,281.58 75,281.61 75.06,281.64L75.24,281.82C75.3,281.85 75.37,281.88 75.44,281.91C75.5,281.97 75.56,282.03 75.62,282.09C75.68,282.12 75.75,282.15 75.81,282.18C75.87,282.24 75.93,282.3 75.99,282.36C76.06,282.39 76.12,282.42 76.19,282.45C76.25,282.51 76.31,282.57 76.37,282.63C76.56,282.75 76.75,282.87 76.94,282.99L77.12,283.17C77.19,283.2 77.25,283.23 77.32,283.26C77.38,283.32 77.44,283.38 77.5,283.44C78.83,284.3 80.16,285.16 81.48,286.02C81.55,286.08 81.61,286.14 81.67,286.2C81.85,286.3 82.03,286.39 82.21,286.49C84.92,287.98 87.61,289.54 90.37,290.96C93.77,292.7 97.36,294.01 101.04,295.05C101.11,295.07 101.12,295.32 101.17,295.47L101.98,295.6C102.14,295.26 102.29,294.92 102.45,294.58C103.02,292.84 103.5,291.07 104.18,289.37C105.08,287.1 106.14,284.89 107.11,282.65C107.72,281.25 108.29,279.84 108.88,278.44C109.03,278.12 109.17,277.79 109.32,277.48C109.52,277.01 109.68,276.52 109.94,276.09C111.83,272.9 113.64,269.65 115.68,266.56C118.72,261.95 122.6,258.13 127.3,255.16C127.55,255 127.79,254.83 128.04,254.66C130.81,253.01 133.58,251.35 136.35,249.69C136.75,249.45 137.14,249.21 137.54,248.96C139.91,247.46 142.32,246 144.66,244.43C147.18,242.74 149.64,240.95 152.13,239.2C152.44,238.98 152.75,238.75 153.06,238.53C153.32,238.3 153.58,238.07 153.83,237.84C154.06,237.66 154.29,237.48 154.53,237.3C154.66,237.12 154.76,236.92 154.92,236.76C156.97,234.69 159.02,232.62 161.08,230.55C161.21,230.46 161.34,230.38 161.48,230.29L161.55,230.26C161.7,230.07 161.85,229.88 162,229.7C162.37,229.27 162.74,228.84 163.1,228.41C163.34,228.17 163.57,227.92 163.8,227.68C164.73,226.36 165.65,225.04 166.58,223.72C166.75,223.46 166.91,223.21 167.08,222.96C168.05,221.21 167.4,219.52 166.87,217.83C166.25,215.87 165.69,213.88 165.07,211.93L165.09,211.94Z" - android:fillColor="#85583D"/> - <path - android:pathData="M222.09,101.58C224.41,100.69 226.58,99.54 228.68,98.18C231.43,96.41 233.7,94.2 235.64,91.58C236.93,89.85 237.12,87.83 237.09,85.89C237.05,83.77 235.54,82.31 233.79,81.23C232.98,80.72 232.08,80.34 231.22,79.91L227.34,79.28C226.72,79.32 226.1,79.34 225.48,79.42C225.17,79.46 224.63,79.54 224.6,79.69C224.39,80.59 224.26,81.52 224.21,82.45C224.19,82.64 224.55,82.95 224.81,83.05C226.06,83.56 226.2,83.73 226,85.11C225.8,86.47 225.55,87.83 225.33,89.19C225.05,90.92 225.04,90.91 223.29,91.07C222.98,91.1 222.51,91.42 222.45,91.67C221.8,94.54 221.19,97.42 220.62,100.31C220.33,101.77 220.72,102.12 222.1,101.59L222.09,101.58Z" - android:fillColor="#85583D"/> - <path - android:pathData="M212.85,143.86C213.13,143.94 213.69,143.88 213.76,143.72C213.88,143.45 213.8,143.01 213.65,142.72C212.78,140.96 211.8,139.27 211.51,137.29C211.2,135.15 211.22,134.44 212.93,133.35C214.03,132.66 215.14,131.91 216.35,131.51C218.39,130.84 220.55,130.44 222.51,131.78C223.35,132.36 224.15,133.08 224.78,133.89C226.46,136.05 227.42,137.46 226.11,140.31C225.65,141.33 224.81,142.17 224.21,143.14C224.02,143.43 224.07,143.88 224,144.25C224.34,144.28 224.77,144.45 225,144.31C228.03,142.36 230.63,139.97 232.27,136.69C233.41,134.42 234.38,132.05 234.14,129.46C233.99,127.88 233.87,126.12 233.11,124.82C231.9,122.79 230.18,121.04 228.62,119.22C226.19,116.36 223.01,114.52 219.68,112.93C219.04,112.63 218.59,112.74 218.46,113.59C218.28,114.7 218.06,115.82 217.72,116.88C217.22,118.44 217.83,119.71 218.46,121.06C218.8,121.81 219.23,122.02 219.95,122.18C220.91,122.39 221.84,122.79 222.78,123.1C222.74,123.2 222.71,123.3 222.68,123.39C221.58,123.09 220.49,122.8 219.4,122.47C218.06,122.07 217.09,122.6 216.4,123.83C215.65,125.16 214.79,126.45 213.82,127.62C212.6,129.08 211.2,130.39 209.91,131.8C209.49,132.26 208.98,132.79 208.85,133.37C208.29,135.78 208.27,138.22 209.34,140.52C210.05,142.05 211.1,143.36 212.84,143.86L212.85,143.86Z" - android:fillColor="#85583D"/> - <path - android:pathData="M88.94,133.9L88.22,134.61C88.85,134.76 88.88,134.32 88.94,133.9Z" - android:fillColor="#85583D"/> - <path - android:pathData="M225.72,135.09C225.19,134.37 224.66,133.65 224.13,132.93C223.32,132.3 222.51,131.68 221.7,131.05C220.96,130.95 220.22,130.86 219.48,130.76C217.14,131.08 214.92,131.77 212.93,133.03C212.53,133.29 212.27,133.77 211.95,134.14C211.5,134.91 212.09,135.46 212.36,136.07C212.8,137.26 213.24,138.45 213.68,139.63C214.05,140.33 214.41,141.02 214.78,141.71C214.95,141.89 215.12,142.07 215.3,142.25C215.86,142.68 216.43,143.1 216.99,143.52C217.88,143.9 218.79,144.23 219.65,144.66C220.48,145.08 221.18,145.11 221.83,144.36C223.02,142.99 224.23,141.64 225.43,140.28C225.69,140.04 225.95,139.81 226.21,139.57L226.51,137.73C226.25,136.85 225.98,135.97 225.73,135.09L225.72,135.09Z" - android:fillColor="#AE7D5F"/> - <path - android:pathData="M161.04,169.77C160.86,168.98 160.68,168.18 160.5,167.39C160.35,167.02 160.2,166.64 160.05,166.27C159.96,166.04 159.87,165.81 159.78,165.57C159.83,165.55 159.88,165.53 159.93,165.5C159.89,165.47 159.84,165.44 159.79,165.41L159.78,165.39C159.73,165.24 159.68,165.1 159.63,164.95C159.59,164.8 159.54,164.65 159.49,164.51C159.4,164.34 159.29,164.18 159.2,164.01C159.1,163.79 159,163.57 158.91,163.35C158.9,163.25 158.89,163.16 158.88,163.06C158.51,162.34 158.15,161.61 157.79,160.89C157.44,160.35 157.08,159.83 156.75,159.28C156.37,158.66 155.83,158.51 155.18,158.73C153.81,159.18 152.47,159.68 152.44,161.48C152.4,161.68 152.37,161.88 152.34,162.09C152.29,162.43 152.23,162.77 152.18,163.11C152.14,163.32 152.11,163.52 152.08,163.72C152.18,164.64 152.27,165.55 152.37,166.47C152.54,167.13 152.7,167.79 152.87,168.44C153.46,170.36 154.04,172.27 154.63,174.19L155.65,174.35C155.99,174.41 156.33,174.46 156.67,174.52C156.83,174.26 156.98,174 157.14,173.75C157.31,173.69 157.48,173.64 157.64,173.58L158.77,173.15C159.4,172.7 160.04,172.26 160.67,171.81C161.57,171.27 160.71,170.42 161.04,169.77V169.77Z" - android:fillColor="#AE7D5F"/> - <path - android:pathData="M113,79.01C112.96,78.4 112.91,77.79 112.86,77.17C112.76,75.84 112.66,74.5 112.56,73.17C112.87,72.43 112.38,71.86 112.16,71.24C112.14,71.21 112.1,71.19 112.09,71.16C111.69,69.83 110.72,69.36 109.4,69.31C108.14,69.27 108.59,70.42 108.16,70.95C108.14,70.97 108.1,70.97 108.07,70.98L107.87,72.21C107.97,72.46 108.14,72.71 108.15,72.97C108.22,74 108.24,75.02 108.28,76.04C108.25,76.67 108.21,77.29 108.18,77.91C108.18,78.75 108.19,79.59 108.2,80.43C108.17,81.05 108.14,81.68 108.11,82.3C108.11,83.14 108.12,83.98 108.12,84.82C108.09,85.44 108.06,86.06 108.03,86.69C107.89,87.49 108.35,87.68 109.02,87.64C109.28,87.63 109.54,87.58 109.8,87.55C110.48,87.25 111.16,86.94 111.83,86.63C112.22,85.66 112.6,84.68 112.98,83.71C113.02,82.79 113.05,81.88 113.08,80.97C113.05,80.32 113.03,79.66 113,79.01L113,79.01Z" - android:fillColor="#AE7D5F"/> - <path - android:pathData="M162.51,103.78C164.51,103.83 166.21,103.03 167.56,101.54C168,101.05 167.92,100.57 167.5,100.09C167.15,99.68 166.82,99.25 166.47,98.83C165.94,98.25 165.41,97.66 164.87,97.08C164.11,96.18 163.35,95.27 162.59,94.37C161.59,93.23 160.58,92.08 159.58,90.94C159.09,90.58 158.62,90.2 158.12,89.85C157.6,89.49 157.15,89.44 156.97,90.2C156.66,91.59 156.36,92.99 156.05,94.38C156.25,95.04 156.45,95.69 156.64,96.35C156.8,96.59 156.94,96.83 157.1,97.07C157.85,98.45 158.61,99.82 159.37,101.2C160.19,102.33 160.85,103.74 162.51,103.78L162.51,103.78Z" - android:fillColor="#AE7D5F"/> - <path - android:pathData="M209.9,140.6C209.85,140.55 209.82,140.49 209.79,140.43C209.48,139.55 209.08,138.71 208.88,137.81C208.64,136.69 208.39,135.53 208.46,134.4C208.54,133.2 209.02,132.04 209.3,130.85C209.54,129.9 209.81,128.95 209.94,127.99C210.14,126.5 210.23,124.99 210.37,123.48C210.45,122.94 210.53,122.39 210.62,121.85C210.91,119.59 211.21,117.32 211.51,115.06C211.24,114.78 211.14,114.52 211.18,114.28C211.14,114.52 211.25,114.78 211.51,115.06C211.58,114.59 211.66,114.11 211.73,113.63C212.19,109.99 212.65,106.34 213.12,102.69C213.21,101.93 213.36,101.19 213.47,100.44C214.1,96.08 214.73,91.71 215.34,87.35C215.75,84.46 216.13,81.56 216.53,78.66C216.95,75.59 217.38,72.52 217.79,69.45C218.19,66.56 218.59,63.66 218.98,60.76C219.17,59.3 219.34,57.83 219.52,56.37C219.55,56.16 219.58,55.96 219.61,55.76C220.07,52.38 220.53,49.01 220.99,45.63C221.55,41.61 222.16,37.6 222.68,33.58C222.96,31.43 223.23,29.28 223.3,27.12C223.36,25.29 222.8,23.58 221.8,21.96C220.41,19.7 218.18,18.74 215.88,17.84C215.22,17.58 214.5,17.45 213.81,17.26C207.53,16.32 201.26,15.39 194.99,14.45C189.22,13.47 183.47,12.41 177.69,11.53C172.6,10.74 167.47,10.18 162.37,9.45C160.37,9.16 158.4,8.59 156.4,8.32C153.12,7.88 150.04,8.51 147.3,10.46C145.45,11.79 144.82,13.77 144.55,15.9C144.49,16.41 144.52,16.94 144.44,17.44C143.3,24.56 142.18,31.67 141,38.79C139.8,46 138.55,53.19 137.32,60.4C137.26,60.8 137.19,61.21 137.12,61.62C136.42,65.7 135.73,69.78 135.03,73.87C135.08,73.94 135.15,74 135.22,74.06C135.15,74 135.08,73.94 135.03,73.87C134.8,75.23 134.59,76.59 134.36,77.95C133.18,84.96 131.98,91.97 130.79,98.99C131.04,99.4 131.08,99.95 130.96,100.45C131.08,99.95 131.04,99.4 130.79,98.99C130.66,99.8 130.53,100.62 130.39,101.43C129.93,104.23 129.46,107.02 128.99,109.81L127.38,118.99C127.74,119.43 127.83,120.04 127.68,120.62C127.83,120.04 127.74,119.42 127.38,118.99C127.22,119.95 127.07,120.9 126.91,121.85C126.58,123.87 126.27,125.89 125.89,127.9C125.8,128.41 125.48,128.87 125.26,129.35L125.03,130.78C125.07,131.07 125.1,131.35 125.14,131.64C125.41,131.99 125.5,132.32 125.42,132.62C125.5,132.32 125.42,131.99 125.14,131.64C125.05,132.18 124.97,132.73 124.89,133.27C124.43,138.81 125.53,144.21 126.28,149.65C126.61,152.02 126.76,154.43 126.89,156.83C127.11,160.97 127.33,165.11 127.42,169.26C127.49,172.34 126.71,175.3 125.68,178.19C125.58,178.48 125.54,178.79 125.46,179.09C125.25,179.2 125.03,179.3 124.81,179.4C124.81,179.47 124.81,179.55 124.81,179.61C124.77,179.82 124.73,180.02 124.69,180.22C124.68,180.7 124.66,181.18 124.64,181.66C124.98,181.73 125.31,181.8 125.65,181.87C126.51,182.16 127.36,182.51 128.24,182.73C128.82,182.89 129.45,182.84 130.04,182.96C133.71,183.67 137.37,184.46 141.05,185.13C142.9,185.46 144.78,185.59 146.65,185.82L146.72,185.83C146.69,185.83 146.65,185.82 146.65,185.82C146.68,185.82 146.7,185.82 146.72,185.83H146.74C147.31,185.85 147.89,185.87 148.47,185.88C148.61,185.66 148.73,185.55 148.83,185.57C148.88,185.57 148.93,185.61 148.97,185.68C148.93,185.61 148.88,185.57 148.83,185.57C148.73,185.55 148.61,185.66 148.47,185.88C148.67,185.92 148.88,185.95 149.08,185.98C151.53,186.37 153.98,186.76 156.43,187.15C156.8,187.01 157.16,186.87 157.52,186.74C157.47,186.27 157.49,185.78 157.37,185.34C156.16,181.11 154.82,176.92 153.77,172.65C153.39,171.07 152.84,169.58 152.34,168.05C151.6,165.82 151.22,163.6 151.75,161.28C151.52,161.13 151.42,161.01 151.44,160.91C151.42,161.01 151.52,161.13 151.75,161.28C151.78,161.07 151.82,160.87 151.85,160.67C152.08,158.16 153.57,156.25 155.07,154.45C155.57,153.86 156.82,153.69 157.72,153.68C160.14,153.67 162.32,154.58 164.11,156.16C166.03,157.84 167.87,159.65 169.55,161.57C170.6,162.76 171.3,164.27 172.14,165.64C172.79,166.69 173.42,167.74 174.05,168.8C174.27,169.19 174.49,169.59 174.7,169.98C174.93,170.36 175.15,170.75 175.37,171.13C176.35,173.24 177.47,175.29 178.26,177.46C179.51,180.87 180.68,184.33 181.6,187.84C182.1,189.72 183.07,191.26 183.99,192.88C184.24,193.07 184.5,193.25 184.75,193.43C185.82,194.61 186.89,195.79 187.95,196.97C188.19,197.24 188.43,197.53 188.66,197.81L189.68,197.98C189.8,197.42 190.06,196.85 190,196.31C189.36,191.04 188.32,185.86 186.72,180.79C186.28,179.39 185.94,177.96 185.54,176.54C185.5,176.48 185.45,176.41 185.4,176.35C184.6,173.48 183.78,170.61 182.97,167.74C182.93,167.67 182.88,167.61 182.84,167.54C182.07,164.85 181.39,162.13 180.52,159.48C179.81,157.32 178.87,155.23 178.03,153.11C177.64,152.93 177.25,152.74 176.86,152.55C176.44,152.49 176.02,152.42 175.6,152.36C175.48,152.27 175.37,152.19 175.25,152.1C174.41,151.96 173.65,152.43 172.7,152.12C170.54,151.42 169.76,150.51 170.23,148.28C170.41,147.44 170.62,146.65 170.35,145.81C170.05,145.58 169.95,145.39 170.06,145.23C169.95,145.39 170.04,145.58 170.35,145.81C170.4,145.54 170.45,145.27 170.49,144.99C170.45,144.12 171.11,143.48 171.12,142.5C171.13,140.99 170.25,140.07 169.65,138.99C168.13,136.23 166.5,133.52 164.89,130.8C164.44,130.03 163.95,129.27 163.41,128.57C163.18,128.29 162.76,128.04 162.4,127.99C161.42,127.86 160.42,127.76 159.43,127.79C157.62,127.84 156.06,127.21 154.7,126.09C153.82,125.36 153.79,124.25 153.93,123.23C154.22,121.04 154.57,118.86 155,116.7C155.18,115.82 155.64,115 155.97,114.15C155.91,114.01 155.85,113.86 155.79,113.72C154.36,110.98 152.85,108.29 151.55,105.5C150.21,102.59 149.68,99.48 149.75,96.26C149.81,93.06 151.09,90.36 153.38,88.21C153.98,87.65 155.16,87.72 156.08,87.5C156.28,87.53 156.48,87.56 156.69,87.59C159.32,88.64 161.27,90.51 163.11,92.6C166.52,96.49 170.03,100.29 173.51,104.12C173.55,104.17 173.63,104.17 173.7,104.2C173.93,104.52 174.16,104.83 174.39,105.15C176.04,107.3 177.67,109.46 179.35,111.58C181.68,114.5 184.05,117.39 186.41,120.29L186.97,120.81C187.96,122.03 188.92,123.28 189.96,124.46C190.43,124.99 191.07,124.75 191.26,124.07C191.4,123.58 191.54,123.08 191.68,122.59C191.82,122.19 191.95,121.8 192.09,121.4C192.42,120.21 192.97,119.99 194.21,120.21C195.6,120.46 197.02,120.49 198.42,120.67C199.07,120.76 199.7,121.01 200.35,121.12C201.29,121.27 202.25,121.3 203.17,121.52C203.61,121.62 203.97,122.04 204.37,122.31C204.4,122.46 204.44,122.6 204.48,122.74C204.6,123.25 204.74,123.77 204.86,124.28C204.78,124.48 204.68,124.67 204.6,124.86C204.66,125.29 204.72,125.72 204.78,126.15C205.03,126.37 205.14,126.56 205.11,126.73C205.14,126.56 205.03,126.37 204.78,126.15C204.73,126.49 204.68,126.83 204.62,127.17C204.39,128.65 204.21,130.15 203.91,131.62C203.34,134.31 202.43,133.9 200.49,134.09C200.09,134.13 199.5,134.2 199.36,134.46C199.21,134.72 199.39,135.32 199.63,135.62C201.02,137.35 202.45,139.05 203.91,140.73C204.15,141.01 204.59,141.19 204.97,141.26C206.42,141.53 207.89,141.73 209.35,141.95C209.66,141.73 209.98,141.51 210.29,141.29L210.39,140.68C210.23,140.66 210.08,140.63 209.92,140.61L209.9,140.6ZM152.72,138.22C155.61,138.2 158.48,138.3 161.19,139.5C162.85,140.24 163.54,141.36 163.26,143.18C162.98,144.98 162.69,146.78 162.38,148.58C162.08,150.38 161.15,151.02 159.33,150.74C158.44,150.6 157.56,150.46 156.68,150.31C156.66,150.38 156.64,150.45 156.62,150.52C155.05,150.04 153.49,149.59 151.94,149.06C151.24,148.81 150.81,148.19 150.88,147.45C151.14,144.58 151.46,141.71 151.83,138.86C151.86,138.6 152.41,138.22 152.73,138.22H152.72ZM185.43,17.57C186.83,17.86 187.76,19.25 187.49,20.67C187.22,22.14 185.83,23.13 184.4,22.88C183.01,22.64 182.15,21.36 182.38,19.91C182.6,18.55 184.21,17.32 185.43,17.57ZM143.44,146.83C143.14,148.23 142.6,148.43 141.18,148.25C140.88,148.22 140.57,148.18 140.26,148.14C139.92,148.09 139.58,148.03 139.24,147.98L138.83,147.92C138.63,147.88 138.42,147.85 138.22,147.82C137.95,147.77 137.67,147.73 137.4,147.69C137.2,147.65 136.99,147.62 136.79,147.58C135.45,147.29 134.09,147.06 132.78,146.68C131.65,146.37 131.08,145.56 131.2,144.35C131.18,144.34 131.17,144.32 131.15,144.31C131.17,144.32 131.18,144.33 131.2,144.35C131.24,144.14 131.27,143.94 131.3,143.74C131.76,141.37 132.23,139 132.7,136.63C132.8,136.29 132.91,135.96 133.02,135.63C133.45,135.48 133.89,135.2 134.32,135.23C135.71,135.3 137.1,135.49 138.49,135.63L138.74,135.4C138.65,135.48 138.58,135.55 138.49,135.63C138.63,135.65 138.76,135.67 138.9,135.69C139.51,135.79 140.13,135.89 140.74,135.99C140.94,135.71 141.11,135.6 141.26,135.66C141.11,135.6 140.94,135.71 140.74,135.99C141.01,136.04 141.28,136.08 141.55,136.12C143.83,136.67 144.74,137.9 144.44,140.24C144.17,142.44 143.9,144.66 143.43,146.83H143.44ZM147.67,116.28C147.48,117.61 147.27,118.93 147.07,120.26C147.35,120.44 147.44,120.58 147.34,120.69C147.44,120.58 147.35,120.44 147.07,120.26C147.04,120.46 147,120.67 146.97,120.87C146.79,121.89 146.63,122.91 146.44,123.93C146.21,125.17 145.75,125.47 144.51,125.3C142.16,124.98 139.81,124.69 137.45,124.37C137.15,124.33 136.84,124.29 136.54,124.19C134.3,123.42 134,122.55 134.59,120.16C135.14,117.96 135.43,115.69 135.74,113.43C135.85,112.61 136.18,112.26 136.96,112.25C138.1,112.25 139.23,112.24 140.36,112.23C140.99,111.68 141.88,111.67 142.51,112.12C141.88,111.67 140.99,111.68 140.36,112.23C141.24,112.37 142.13,112.52 143.01,112.66C143.94,112.89 144.87,113.1 145.8,113.35C147.12,113.72 147.86,114.88 147.67,116.28ZM210.25,92.02C209.75,92.16 209.15,92.04 208.61,91.94C206.34,91.53 204.09,91.07 201.83,90.66C200.2,90.36 198.57,90.11 196.93,89.84C196.73,89.81 196.53,89.77 196.33,89.73C192.13,89 187.94,88.28 183.76,87.54C181.97,87.22 180.19,86.86 178.41,86.52C178.05,86.79 177.72,86.88 177.42,86.79C177.72,86.88 178.05,86.79 178.41,86.52C177.86,86.43 177.32,86.34 176.78,86.25C173.11,85.6 169.45,84.94 165.78,84.28C164.97,84.15 164.15,84.02 163.34,83.89C158.38,83.02 153.42,82.16 148.46,81.3C148,81.68 147.52,81.81 147.06,81.69C147.51,81.81 148,81.68 148.46,81.3C147.64,81.17 146.83,81.03 146.01,80.9C144.86,80.7 143.72,80.48 142.56,80.31C140.01,79.94 139.15,78.85 139.4,76.25C139.32,76.17 139.24,76.08 139.16,76C139.24,76.08 139.32,76.16 139.4,76.25C139.41,76.11 139.43,75.98 139.45,75.84L140.24,70.94C140.3,70.59 140.36,70.24 140.41,69.9C140.77,68.69 141.02,67.43 141.52,66.28C142.18,64.78 143.66,64.24 145.41,64.41C146.27,64.5 147.12,64.67 147.97,64.79C148.37,64.51 148.74,64.42 149.07,64.52C148.73,64.42 148.36,64.52 147.97,64.79C148.58,64.89 149.19,65 149.8,65.09C152.77,65.65 155.74,66.23 158.72,66.76C163.94,67.68 169.17,68.57 174.39,69.49C177.78,70.08 181.16,70.71 184.54,71.32C188.23,71.99 191.92,72.66 195.61,73.33C195.81,73.37 196.01,73.4 196.22,73.44C197.32,73.67 198.43,73.95 199.54,74.13C202.6,74.65 205.68,75.04 208.71,75.65C209.91,75.9 211.16,76.42 212.13,77.17C213.34,78.1 213.3,79.72 213.18,81.1C212.91,83.94 212.48,86.77 212.05,89.59C211.89,90.67 211.42,91.68 210.26,92.02L210.25,92.02Z" - android:fillColor="#C6ADFF"/> - <path - android:pathData="M210.2,141.7L210.26,141.29C209.95,141.51 209.64,141.73 209.32,141.95C209.61,141.86 209.91,141.78 210.2,141.7V141.7Z" - android:fillColor="#C6ADFF"/> - <path - android:pathData="M157.5,186.73C157.14,186.87 156.78,187.01 156.42,187.15C156.88,187.26 157.36,187.44 157.5,186.73Z" - android:fillColor="#C6ADFF"/> - <path - android:pathData="M154.51,72.16C154.4,71.56 154.06,70.86 153.73,70.59C153.91,71.24 153.96,71.86 153.93,72.31C153.93,72.31 153.93,72.31 153.93,72.32C153.65,70.71 152.76,69.89 152.21,68.41C152.18,68.33 152.15,68.26 152.12,68.18C152.11,68.14 152.1,68.1 152.09,68.06C152.07,67.99 152.06,67.91 152.05,67.84C152.05,67.83 152.05,67.82 152.04,67.82C152.04,67.82 152.04,67.82 152.03,67.82C152.03,67.82 152.03,67.82 152.03,67.82C150.54,68.32 149.79,69.66 149.59,70.37C149.05,70.3 148.51,70.39 148.02,70.63C147.99,70.58 147.94,70.54 147.91,70.5C147.88,70.05 147.96,69.6 148.16,69.2C147.56,69.33 147.06,69.64 146.68,69.91C146.53,69.6 146.73,68.73 146.78,68.55C146.78,68.54 146.6,68.6 146.58,68.61C146.37,68.7 146.16,68.81 145.97,68.94C145.75,69.09 145.55,69.25 145.35,69.43C144.91,69.84 144.55,70.33 144.31,70.88C144.3,70.89 144.3,70.9 144.29,70.91C144.27,70.96 144.19,71.18 144.17,71.23C144.17,71.23 144.17,71.24 144.17,71.24C144.07,71.48 143.99,71.71 143.93,71.96C143.93,71.96 143.93,71.97 143.92,71.98C143.31,74.9 145.18,77.76 148.1,78.38C150.71,78.93 153.28,77.49 154.23,75.08C154.26,75.02 154.28,74.95 154.3,74.89C154.6,74 154.68,73.02 154.52,72.16H154.51ZM147.55,75.02C147.57,75.03 147.59,75.05 147.61,75.07C147.59,75.05 147.57,75.03 147.54,75.02H147.55Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="152.36" - android:startY="78.02" - android:endX="145.74" - android:endY="67.92" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M154.51,72.16C154.4,71.56 154.06,70.86 153.73,70.59C153.91,71.24 153.96,71.86 153.93,72.31C153.93,72.31 153.93,72.31 153.93,72.32C153.93,72.32 153.93,72.32 153.93,72.32C154.15,73.78 153.59,75.1 153.02,75.85C152.14,77.03 150.39,78.05 148.11,77.5C145.65,76.91 143.85,74.62 143.95,72.12C143.95,71.72 144.07,71.54 144.17,71.24C144.07,71.47 144.04,71.54 143.93,71.96C143.93,71.96 143.93,71.97 143.92,71.98C143.31,74.9 145.18,77.76 148.1,78.38C150.71,78.93 153.28,77.49 154.23,75.08C154.26,75.02 154.28,74.95 154.3,74.89C154.6,74 154.68,73.02 154.52,72.16H154.51Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="148.34" - android:centerY="67.74" - android:gradientRadius="11.68" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M154.51,72.16C154.4,71.56 154.06,70.86 153.73,70.59C153.91,71.24 153.96,71.86 153.93,72.31C153.93,72.31 153.93,72.31 153.93,72.32C153.93,72.32 153.93,72.32 153.93,72.32C154.15,73.78 153.59,75.1 153.02,75.85C152.14,77.03 150.39,78.05 148.11,77.5C145.65,76.91 143.85,74.62 143.95,72.12C143.95,71.72 144.07,71.54 144.17,71.24C144.07,71.47 144.04,71.54 143.93,71.96C143.93,71.96 143.93,71.97 143.92,71.98C143.31,74.9 145.18,77.76 148.1,78.38C150.71,78.93 153.28,77.49 154.23,75.08C154.26,75.02 154.28,74.95 154.3,74.89C154.6,74 154.68,73.02 154.52,72.16H154.51Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="144.45" - android:centerY="70.08" - android:gradientRadius="11.97" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#56DB293D"/> - <item android:offset="0.5" android:color="#16F5334B"/> - <item android:offset="0.53" android:color="#00FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M151.81,72.24C151.81,72.24 151.83,72.26 151.84,72.27C151.75,72.01 151.63,71.76 151.48,71.53C150.18,69.54 151.8,67.87 152.02,67.82C150.53,68.32 149.78,69.66 149.59,70.37C149.65,70.38 149.71,70.39 149.77,70.4C150.76,70.61 151.51,71.34 151.81,72.24L151.81,72.24Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="149.13" - android:centerY="66.58" - android:gradientRadius="3.5" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M149.43,72.08C149.39,72.21 148.83,72.57 148.67,72.53C147.16,72.22 146.73,73.08 146.73,73.08C146.64,73.86 147.04,74.6 147.61,75.07C147.64,75.09 147.67,75.11 147.69,75.13C147.74,75.16 147.79,75.19 147.83,75.22C148.04,75.35 148.26,75.44 148.49,75.5C151.1,76.18 152.3,73.01 150.6,71.66C151.11,71.68 151.57,71.98 151.81,72.24C151.52,71.34 150.77,70.61 149.78,70.4C149.71,70.39 149.65,70.38 149.59,70.37C149.05,70.29 148.5,70.39 148.02,70.62C148.08,70.71 148.15,70.82 148.3,71.05C148.59,71.48 149.43,72.04 149.43,72.08H149.43Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="144.01" - android:centerY="74.6" - android:gradientRadius="4.87" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M149.43,72.08C149.39,72.21 148.83,72.57 148.67,72.53C147.16,72.22 146.73,73.08 146.73,73.08C146.64,73.86 147.04,74.6 147.61,75.07C147.64,75.09 147.67,75.11 147.69,75.13C147.74,75.16 147.79,75.19 147.83,75.22C148.04,75.35 148.26,75.44 148.49,75.5C151.1,76.18 152.3,73.01 150.6,71.66C151.11,71.68 151.57,71.98 151.81,72.24C151.52,71.34 150.77,70.61 149.78,70.4C149.71,70.39 149.65,70.38 149.59,70.37C149.05,70.29 148.5,70.39 148.02,70.62C148.08,70.71 148.15,70.82 148.3,71.05C148.59,71.48 149.43,72.04 149.43,72.08H149.43Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="146.3" - android:centerY="70.6" - android:gradientRadius="2.19" - android:type="radial"> - <item android:offset="0.21" android:color="#009059FF"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M147.81,70.4C147.84,70.43 147.87,70.46 147.9,70.49C147.87,70.04 147.96,69.6 148.16,69.2C147.56,69.33 147.06,69.63 146.68,69.91C146.71,69.91 147.47,70.06 147.81,70.39V70.4Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="148.8" - android:centerY="68.31" - android:gradientRadius="3.78" - android:type="radial"> - <item android:offset="0.1" android:color="#FFFFE226"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M143.94,72.12C143.84,74.62 145.64,76.92 148.11,77.51C150.39,78.06 152.14,77.03 153.01,75.86C153.58,75.1 154.14,73.78 153.93,72.33V72.32C153.93,72.32 153.93,72.31 153.93,72.32C153.93,72.32 153.93,72.32 153.93,72.32C153.86,73.59 152.98,74.64 151.84,75.24V75.25C149.62,76.39 147.93,75.4 147.62,75.07C147.59,75.05 147.57,75.04 147.55,75.02C146.55,74.26 146.31,73.15 146.59,72.31C145.65,72.11 145.5,71.26 145.5,71.26C145.5,71.26 146.47,70.84 147.46,71.59C148.38,72.29 149.43,72.09 149.43,72.09C149.44,72.05 148.59,71.48 148.31,71.06C148.16,70.83 148.09,70.72 148.02,70.63C147.99,70.59 147.94,70.54 147.91,70.5C147.88,70.47 147.85,70.43 147.81,70.4C147.48,70.07 146.71,69.93 146.68,69.92C146.53,69.61 146.73,68.74 146.78,68.56C146.78,68.55 146.6,68.6 146.58,68.61C146.37,68.71 146.16,68.82 145.97,68.95C145.75,69.09 145.55,69.26 145.35,69.44C144.91,69.85 144.55,70.34 144.31,70.89C144.3,70.9 143.94,71.68 143.95,72.13L143.94,72.12Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="148.37" - android:centerY="64.52" - android:gradientRadius="18.82" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M151.48,71.53C151.63,71.75 151.76,72 151.84,72.27C151.86,72.3 151.89,72.33 151.9,72.35C152.87,73.71 151.92,75.14 151.84,75.24C152.98,74.64 153.86,73.59 153.93,72.32C153.64,70.71 152.76,69.9 152.2,68.41C152.17,68.34 152.14,68.27 152.12,68.19C152.11,68.14 152.09,68.11 152.08,68.06C152.06,67.99 152.05,67.92 152.05,67.84C152.05,67.83 152.05,67.82 152.04,67.82C152.04,67.82 152.03,67.82 152.03,67.82C152.03,67.82 152.03,67.82 152.03,67.82C151.8,67.88 150.19,69.54 151.48,71.53V71.53Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="157.75" - android:centerY="-2.96" - android:gradientRadius="12.19" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M151.9,72.35C151.88,72.32 151.86,72.3 151.84,72.27C151.83,72.26 151.82,72.25 151.81,72.24C151.57,71.98 151.11,71.68 150.6,71.66C152.31,73.01 151.11,76.18 148.5,75.5C148.27,75.44 148.04,75.35 147.84,75.22C147.79,75.19 147.74,75.16 147.7,75.13C147.67,75.11 147.64,75.09 147.62,75.07C147.93,75.39 149.62,76.39 151.84,75.24V75.23C151.92,75.13 152.87,73.7 151.9,72.35V72.35Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="146.87" - android:centerY="69.82" - android:gradientRadius="10.38" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M146.73,73.08C146.73,73.08 147.16,72.22 148.67,72.53C148.83,72.57 149.39,72.21 149.43,72.08C149.47,71.95 148.38,72.28 147.46,71.59C146.47,70.83 145.5,71.26 145.5,71.26C145.5,71.26 145.65,72.11 146.59,72.3C146.31,73.15 146.55,74.25 147.55,75.01C147.57,75.03 147.59,75.04 147.61,75.06C147.04,74.6 146.64,73.85 146.73,73.07V73.08Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="149.76" - android:centerY="70.37" - android:gradientRadius="12.9" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M154.51,72.16C154.4,71.56 154.06,70.86 153.73,70.59C153.91,71.24 153.96,71.86 153.93,72.31C153.93,72.31 153.93,72.31 153.93,72.32C153.65,70.71 152.76,69.89 152.21,68.41C152.18,68.33 152.15,68.26 152.12,68.18C152.11,68.14 152.1,68.1 152.09,68.06C152.07,67.99 152.06,67.91 152.05,67.84C152.05,67.83 152.05,67.82 152.04,67.82C152.04,67.82 152.04,67.82 152.03,67.82C152.03,67.82 152.03,67.82 152.03,67.82C150.54,68.32 149.79,69.66 149.59,70.37C149.65,70.38 149.72,70.39 149.78,70.4C150.77,70.61 151.52,71.34 151.81,72.24C151.57,71.99 151.11,71.69 150.6,71.67C152.31,73.02 151.11,76.18 148.5,75.51C148.27,75.45 148.04,75.35 147.84,75.23C147.79,75.2 147.74,75.16 147.7,75.13C147.67,75.11 147.64,75.09 147.62,75.07C147.6,75.05 147.57,75.04 147.55,75.02C147.57,75.03 147.59,75.05 147.61,75.07C147.04,74.6 146.64,73.86 146.73,73.08C146.73,73.08 147.16,72.22 148.67,72.54C148.83,72.57 149.39,72.21 149.43,72.08C149.44,72.04 148.59,71.48 148.31,71.05C148.16,70.83 148.09,70.72 148.02,70.63C147.99,70.58 147.94,70.54 147.91,70.5C147.88,70.05 147.96,69.6 148.16,69.2C147.56,69.33 147.06,69.64 146.68,69.91C146.53,69.6 146.73,68.73 146.78,68.55C146.78,68.54 146.6,68.6 146.58,68.61C146.37,68.7 146.16,68.81 145.97,68.94C145.75,69.09 145.55,69.25 145.35,69.43C144.91,69.84 144.55,70.33 144.31,70.88C144.3,70.89 144.3,70.9 144.29,70.91C144.27,70.96 144.18,71.18 144.16,71.23C144.07,71.47 143.99,71.71 143.93,71.96C143.93,71.96 143.93,71.97 143.92,71.98C143.31,74.9 145.18,77.76 148.1,78.38C150.71,78.93 153.28,77.49 154.23,75.08C154.26,75.02 154.28,74.95 154.3,74.89C154.6,74 154.68,73.02 154.52,72.16H154.51ZM153.93,72.32C153.93,72.32 153.93,72.32 153.93,72.32V72.32Z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="151.76" - android:startY="77.72" - android:endX="146.76" - android:endY="68.93" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.6" android:color="#00FFF44F"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M217.59,323C216.12,321.34 216.19,319.59 215.88,318.08C214.77,312.74 215.35,307.38 216.31,302.07C216.67,300.04 218.54,299.34 220.08,298.64C221.53,297.98 222,297.27 221.74,295.71C220.28,287.07 217.69,279.09 210.31,273.43C205.63,269.84 200.46,267 195.75,263.46C190.3,259.37 184.71,255.37 180.82,249.65C177.43,244.65 174.84,239.21 172.54,233.61C171.09,230.07 169.74,226.47 168.3,222.52C167.46,223.77 166.92,224.79 166.2,225.64C160.24,232.66 154.01,239.35 146.02,244.17C140.52,247.49 135.08,250.89 129.59,254.21C124.32,257.38 119.99,261.58 116.55,266.78C113.79,270.95 111.49,275.33 109.27,279.78C108.6,281.14 108.71,282.16 109.64,283.49C112.33,287.33 113.56,291.41 111.8,296.23C110.91,298.69 110.82,301.5 110.36,304.16C110.08,305.72 109.66,307.23 108.96,308.66C108.75,309.1 108.72,309.8 107.96,309.6C107.1,309.36 107.41,308.64 107.52,308.12C108.07,305.61 108.66,303.13 109.24,300.63C109.27,300.51 109.33,300.39 109.37,300.26C110.33,297.04 110.28,297.09 107.07,296.57C100.49,295.51 94.23,293.5 88.37,290.23C85.81,288.79 83.12,287.55 80.67,285.93C72.9,280.8 65.68,275.02 59.35,268.14C56.09,264.6 53.04,260.92 50.47,256.89C47.07,251.59 44.04,246.06 43.64,239.54C43.62,239.22 43.54,238.9 43.16,238.59C40.6,240.05 39.27,242.67 37.51,244.9C34.93,248.18 32.8,251.84 29.41,254.42C28.99,254.74 28.58,255.05 28.14,255.33C27.71,255.6 27.38,255.38 27.15,255.02C26.9,254.64 27.21,254.41 27.45,254.2C28.14,253.6 28.78,252.95 29.43,252.31C33.23,248.56 35.82,243.85 39.33,239.9C42.42,236.43 46.03,233.65 50.97,233.31C51.84,233.25 52.73,233.24 53.49,233.55C54.75,234.08 55.37,233.77 56.12,232.6C58.84,228.34 60.99,223.8 63.04,219.21C64.37,216.23 65.68,213.25 67.1,210.31C68.52,207.36 69.41,204.19 70.33,201.04C73.35,190.67 74.77,179.98 76.62,169.38C78.06,161.16 80.19,153.14 83.13,145.3C86.25,136.98 89.7,128.82 93.6,120.85C95.92,116.1 98.73,111.59 100.96,106.81C103.8,100.7 106.26,94.41 106.86,87.58C107.23,83.4 107.26,79.2 107.15,75.01C107.08,72.37 107.21,69.75 107.74,67.18C108.55,63.33 112.11,61.71 115.69,63.29C121.78,65.97 124.76,71.01 126.49,77.07C126.56,77.3 126.72,77.51 127.07,78.14C127.43,75.88 127.9,74.01 128,72.13C128.3,66.75 129.24,61.43 129.49,56.06C129.99,45.07 132.34,34.32 133.83,23.47C134.54,18.37 135.25,13.18 137.54,8.43C138.62,6.21 140.13,4.47 142.11,2.93C146.21,-0.25 150.76,-0.16 155.54,0.14C166.45,0.81 177.2,2.64 187.96,4.36C197.04,5.81 206.11,7.35 215.15,9.05C219.45,9.86 223.74,11.36 227.26,13.92C230.85,16.53 232.54,20.58 232.07,25.16C231.43,31.36 230.62,37.55 229.84,43.73C229.68,45.03 229.35,46.32 229.04,47.59C228.17,51.19 228.32,54.91 227.62,58.53C227.51,59.14 227.52,59.7 228.13,60.09C229.21,60.77 229.35,61.8 229.37,62.99C229.44,66.69 229.13,70.33 227.99,73.88C227.7,74.79 227.46,75.67 226.26,75.69C225.65,75.7 225.49,76.11 225.53,76.62C225.57,77.24 225.99,77.33 226.51,77.27C228.23,77.08 229.89,77.36 231.56,77.79C238.77,79.65 240.78,84.93 237.16,91.09C234.79,95.13 231.07,97.92 226.88,99.98C225.15,100.83 223.59,102.21 221.46,102.09C220.96,102.07 220.87,102.49 220.74,102.87C219.95,105.21 219.99,107.66 219.75,110.08C219.69,110.69 220.14,110.79 220.6,110.95C226.68,113.03 230.88,117.39 234.24,122.6C236.29,125.78 236.68,129.31 235.42,132.97C233.64,138.14 230.43,142.09 225.65,144.79C225.01,145.15 223.9,145.34 223.99,146.26C224.08,147.23 225.11,147.87 225.93,148C228.38,148.38 230.51,149.55 232.79,150.35C237.32,151.95 240.96,154.94 244.38,158.2C246.09,159.83 247.42,161.75 248.79,163.68C249.74,165.03 251.43,165.96 252.96,166.85C255.39,168.25 258.04,169.28 260.14,171.23C260.78,171.81 261.42,172.34 261.86,173.09C265.07,178.54 267.39,184.35 269.18,190.4C271.14,197 272.06,203.76 272.79,210.59C273.57,217.85 274.18,225.13 274.87,232.4C275.4,238.06 275.57,243.75 276.47,249.37C277.45,255.42 277.82,261.58 279.63,267.49C280.74,271.09 282.76,274.26 284.4,277.61C285.46,279.8 286.56,280.5 289.23,279.82C293.84,278.63 296.39,280.58 297.84,285.83C298.67,288.84 299.95,291.73 300.18,294.92C300.27,296.13 300.97,297.27 301.32,298.46C301.48,299.02 301.59,299.8 300.92,300.02C300.12,300.27 300.13,299.4 299.86,298.91C297.83,295.21 298.11,290.87 296.55,287.05C296.4,286.68 296.42,286.25 296.24,285.91C295.88,285.22 295.45,284.71 294.93,285.81C293.38,289.08 290.89,291.59 288.3,294.03C286.3,295.92 284.07,297.54 281.74,299.02C276.64,302.28 271.2,304.88 265.5,306.86C259.56,308.93 253.45,310.36 247.19,311.24C239.91,312.27 232.7,312.21 225.5,310.82C223.04,310.34 220.64,309.65 218.47,308.41C217.35,307.77 217.07,308.18 217,309.19C216.84,311.68 217.17,314.14 217.34,316.61C217.47,318.6 218.13,320.57 217.59,323ZM154.03,157.98C156.22,157.04 157.55,157.81 158.38,159.3C160.44,162.96 161.95,166.85 162.69,171.01C162.8,171.61 162.37,171.97 162.06,172.37C160.68,174.14 158.65,174.75 156.64,175.35C155.8,175.6 155.39,175.56 155.72,176.81C157.48,183.53 159.85,190.04 161.95,196.65C164.22,203.75 166.61,210.82 168.58,218.02C169.49,221.36 170.48,224.69 171.69,227.94C172.87,231.11 174.42,234.15 175.74,237.29C178.92,244.87 183.11,251.66 189.65,256.93C195.26,261.46 201.17,265.53 207.23,269.41C211.76,272.31 215.76,275.78 218.42,280.48C220.38,283.95 221.72,287.75 222.58,291.67C223.68,296.74 224.01,301.89 224.13,307.06C224.16,308.52 224.69,309.29 226.26,309.52C230.03,310.08 233.77,310.34 237.61,310.27C244.46,310.15 251.14,309.2 257.75,307.5C264.95,305.65 271.8,302.95 278.25,299.24C281.85,297.17 285.19,294.75 288.24,291.92C288.92,291.29 289.12,290.89 288.59,289.98C287.17,287.55 286.05,284.96 285.03,282.33C283.86,279.32 282.06,276.64 280.55,273.8C277.58,268.21 276.43,262.07 275.67,255.91C274.67,247.8 273.7,239.7 273.09,231.54C272.5,223.74 271.94,215.92 270.72,208.16C270.03,203.78 269.81,199.35 268.68,195.02C266.8,187.9 264.61,180.93 260.76,174.6C258.91,171.57 256.05,169.88 252.71,168.9C252.37,169.62 252.89,170.01 253.01,170.49C253.15,171.02 253.27,171.68 252.79,171.94C252.21,172.27 251.85,171.64 251.64,171.2C250.62,169.05 248.92,167.35 247.8,165.25C246.63,163.06 245.08,161.13 243.28,159.36C240.02,156.14 236.33,153.61 232.15,151.79C231.12,151.34 230.2,150.57 228.58,150.44C231.77,154.45 235.18,157.88 237.55,162.5C235.99,162.23 235.54,161.39 234.98,160.68C231.96,156.81 228.84,153.02 225.2,149.68C222.89,147.56 220.13,146.03 217.28,145.04C214.34,144.02 211.1,143.89 207.98,143.38C207.62,143.32 207.17,143.15 206.92,143.58C206.66,144.01 207.02,144.32 207.24,144.62C208.2,145.94 209.24,147.21 210.15,148.57C212.9,152.72 215.48,157 218.43,161.03C219.09,161.94 219.49,162.89 219.39,164.22C219,163.99 218.72,163.9 218.58,163.72C217.03,161.61 215.38,159.57 213.99,157.33C212.5,154.96 211.02,152.56 209.41,150.27C207.32,147.28 204.97,144.5 202.56,141.74C200.3,139.14 198.14,136.4 195.92,133.74C190.75,127.56 185.4,121.54 180.31,115.3C178.9,113.58 177.27,112.03 176.07,110.16C174.47,107.67 172.43,105.57 170.52,103.33C169.5,102.14 168.74,101.91 167.66,103.2C167.27,103.68 166.61,103.96 166.03,104.27C163.42,105.65 161.39,105.06 159.54,102.65C158.12,100.8 157.38,98.59 156.12,96.69C155.32,95.47 155.1,94.33 155.5,92.98C155.78,92.05 155.72,91.04 156.31,90.17C156.6,89.75 156.75,89.08 156.02,88.88C155.07,88.63 154,88.45 153.31,89.41C152.59,90.41 151.83,91.38 151.4,92.59C149.38,98.15 151.27,103.2 153.67,108.02C154.88,110.46 156.26,112.86 157.56,115.28C159.82,119.47 161.77,123.83 164.26,127.92C165.51,129.98 167.04,131.88 168.09,134.08C169.56,137.15 171.37,140.05 173.29,142.87C177.28,148.68 180.76,154.72 182.05,161.79C182.09,162.04 182.15,162.3 182.23,162.55C184.54,169.01 186.19,175.68 188.29,182.21C189.99,187.48 190.89,193 191.47,198.54C191.54,199.24 191.71,200.13 190.94,200.5C190.22,200.86 189.5,200.32 188.99,199.85C187.45,198.43 185.92,196.99 184.52,195.43C183.26,194.02 181.98,192.54 181.29,190.76C180.08,187.65 178.93,184.5 178.04,181.29C177.2,178.23 176.07,175.32 174.5,172.59C172.58,169.24 170.7,165.84 168.42,162.74C166.26,159.81 163.74,157.08 160.22,155.65C157.09,154.38 156.1,154.71 154.02,157.98L154.03,157.98ZM113.68,198.2C113.62,197.89 113.54,197.73 113.59,197.64C113.76,197.29 113.95,196.95 114.18,196.64C118.14,191.47 121.51,185.99 123.54,179.75C124.41,177.08 125.58,174.46 125.68,171.63C125.81,168.04 125.66,164.44 125.71,160.85C125.74,158.54 124.98,156.35 124.96,154.05C124.92,150.32 124.48,146.6 123.8,142.95C123.31,140.35 123.13,137.73 123.29,135.18C123.75,127.85 124.58,120.54 125.14,113.22C125.71,105.65 127.03,98.14 126.8,90.51C126.6,83.9 126.16,77.34 122.35,71.56C120.36,68.53 118.36,65.63 114.61,64.42C112.23,63.66 109.61,64.83 109.11,67.27C108.98,67.91 109.09,68.35 109.83,68.31C112.17,68.18 112.75,69.76 113.22,71.61C114.19,75.39 114.03,79.26 114.09,83.09C114.14,85.97 112.67,87.77 109.9,88.49C108.87,88.76 108.38,89.17 108.18,90.25C107.2,95.95 105.07,101.29 102.8,106.58C102.1,108.19 101.43,109.87 100.46,111.32C96.75,116.84 94.58,123.14 91.44,128.94C88.86,133.69 87.45,139 85.31,143.98C82.87,149.63 81.31,155.59 79.98,161.63C78.4,168.75 77.08,175.92 76.03,183.12C75.22,188.74 73.58,194.11 72.28,199.58C71.75,201.8 71.02,203.98 70.28,206.14C68.79,210.46 66.75,214.56 64.99,218.76C60.84,228.71 55.42,237.78 47.92,245.55C46.82,246.68 46.91,247.75 47.63,248.9C48.99,251.06 50.06,253.38 51.42,255.56C56.37,263.48 62.78,270.08 69.83,276.1C73.81,279.5 78.08,282.54 82.53,285.32C88.07,288.78 93.93,291.45 100.06,293.61C101.95,294.28 102.26,294.19 102.73,292.32C103.9,287.71 106.27,283.61 107.97,279.22C110.44,272.85 114.12,267.1 118.4,261.78C120.58,259.06 123.25,256.77 126.03,254.71C128.34,253.01 130.97,251.75 133.44,250.25C138.53,247.14 143.59,244 148.56,240.71C151.04,239.07 153.36,237.25 155.4,235.18C158.52,232.01 161.87,229.02 164.55,225.46C166.29,223.17 168.26,220.93 167.07,217.5C165.1,211.81 163.44,206.01 161.61,200.27C160.88,197.98 160.71,197.8 158.27,197.95C153.82,198.22 149.52,197.27 145.17,196.62C137.89,195.53 130.84,193.28 123.55,192.23C122.89,192.14 122.23,192.04 121.73,191.56C120.54,190.42 119.77,191.1 119.15,192.17C118.25,193.71 117.09,195.06 116.01,196.46C115.43,197.21 114.89,198.1 113.67,198.21L113.68,198.2ZM157.09,187.2C157.02,185.69 156.6,184.32 156.1,182.99C154.89,179.66 153.96,176.26 153.19,172.81C152.96,171.78 152.66,170.8 152.29,169.82C150.49,165.1 150.55,160.54 153.33,156.09C154.66,153.96 156.37,153.34 158.63,153.75C162.14,154.38 164.81,156.4 167.24,158.92C170.19,161.98 172.15,165.7 174.37,169.24C175.52,171.06 176.64,172.95 177.41,174.95C178.79,178.55 180.11,182.2 181.08,185.93C182.3,190.64 184.88,194.35 188.46,197.49C188.79,197.78 189.09,198.32 189.59,198.07C190.18,197.77 189.74,197.28 189.64,196.86C189.49,196.22 189.24,195.59 189.21,194.94C188.89,189.39 187.18,184.16 185.63,178.88C184.05,173.49 182.31,168.14 180.81,162.71C180.15,160.32 179.62,157.92 178.69,155.59C178.04,153.95 177.28,152.91 175.36,152.91C174.19,152.91 173.01,152.64 171.86,152.39C170.17,152.04 169.53,151.15 169.69,149.46C169.89,147.31 169.82,145.12 170.59,143.05C170.92,142.18 170.74,141.39 170.14,140.68C169.03,139.36 168.33,137.81 167.52,136.3C166.32,134.04 164.92,131.9 163.57,129.73C163.02,128.84 162.29,128.38 161.12,128.51C159.68,128.67 158.23,128.35 156.83,128C154.63,127.45 153.18,125.87 153.39,124.07C153.69,121.47 153.77,118.7 154.75,116.34C155.49,114.59 154.9,113.57 154.31,112.27C154.12,111.86 153.81,111.49 153.59,111.09C151.41,107.11 149.55,103.06 149.21,98.41C148.97,94.96 149.87,91.98 151.82,89.2C152.61,88.07 153.58,87.55 154.95,87.5C157.88,87.4 160.08,89.02 161.68,91.03C165.88,96.31 170.75,100.97 175.09,106.11C176.33,107.57 177.25,109.25 178.49,110.69C181.26,113.93 184.01,117.18 186.63,120.54C187.81,122.05 189.14,123.45 190.42,124.92C191.03,124.31 190.94,123.67 191.06,123.12C191.69,120.04 192.41,119.55 195.55,120.07C197.76,120.44 199.96,120.79 202.17,121.15C204.34,121.51 205.15,122.44 204.96,124.62C204.78,126.71 204.54,128.8 204.18,130.87C203.57,134.34 202.98,134.76 199.52,134.65C199.43,134.65 199.33,134.8 199.14,134.95C199.83,136.29 201.22,137.1 201.94,138.38C203.31,140.82 205.39,141.82 208.08,141.91C209.73,141.97 209.68,142.03 209.11,140.56C208.09,137.94 207.49,135.2 208.39,132.49C209.01,130.63 209.45,128.83 209.73,126.87C210.82,119.39 211.47,111.86 212.51,104.38C214.15,92.59 215.8,80.81 217.35,69.02C219.1,55.73 221.07,42.47 222.85,29.18C223.17,26.84 222.87,24.58 221.42,22.45C219.39,19.47 216.46,18.22 213.17,17.67C206.17,16.49 199.1,15.73 192.13,14.38C179.86,12.01 167.39,11.01 155.12,8.71C154.92,8.68 154.73,8.64 154.53,8.64C149.64,8.76 145.19,10.71 144.63,15.88C143.98,21.83 142.86,27.71 141.86,33.61C136.58,64.84 131.32,96.09 126.1,127.33C125.89,128.59 125.11,129.62 125.06,130.87C124.86,135.51 124.87,140.13 125.58,144.76C125.97,147.32 126.52,149.86 126.69,152.46C127.03,157.54 127.39,162.63 127.36,167.72C127.35,170.26 127.88,172.88 126.74,175.29C125.92,177.02 125.72,178.95 124.84,180.64C124.48,181.33 124.57,181.71 125.39,181.89C129.3,182.76 133.18,183.74 137.1,184.54C143.42,185.83 149.91,185.88 156.22,187.21C156.46,187.26 156.73,187.2 157.09,187.18L157.09,187.2ZM126.95,108.77C128.08,107.98 128.01,107.27 128.11,106.65C128.86,102.17 129.55,97.7 130.3,93.22C134.37,68.79 138.45,44.35 142.53,19.92C142.7,18.88 143.13,17.85 143.08,16.83C142.8,10.77 147.51,7.58 152.64,7.42C155.96,7.32 159.31,7.81 162.58,8.61C163.79,8.9 164.99,9.22 166.24,9.35C173.88,10.12 181.53,10.55 189.08,12.19C195.75,13.64 202.54,14.5 209.3,15.48C212.45,15.93 215.43,16.72 218.31,18.09C223.15,20.4 225.48,24.79 224.36,29.95C224.22,30.59 224.12,31.24 224.04,31.89C223.43,36.91 222.94,41.95 222.22,46.95C220.69,57.62 219.29,68.3 217.85,78.98C215.92,93.37 213.84,107.74 211.82,122.12C211.61,123.62 211.4,125.11 211.2,126.61C211.12,127.24 211.31,127.87 211.99,127.33C214.34,125.46 216.24,123.19 216.6,120.11C217.47,112.8 218.64,105.55 220.04,98.33C221.34,91.56 223.04,84.84 223.74,77.98C224.6,69.42 225.87,60.91 226.87,52.37C227.95,43.19 229.91,34.12 230.46,24.86C230.67,21.28 229.52,18.28 226.99,15.88C223.52,12.59 218.99,11.51 214.55,10.36C209.53,9.07 204.3,8.99 199.22,7.92C192.47,6.5 185.6,5.66 178.8,4.52C170.96,3.21 163.07,2.32 155.16,1.61C152.68,1.39 150.18,1.35 147.72,1.95C143.28,3.02 139.95,5.56 138.43,9.89C136.71,14.79 135.9,19.93 135.16,25.07C134.37,30.59 133.73,36.14 132.73,41.63C132.12,44.93 131.74,48.25 131.35,51.57C130.65,57.37 130.13,63.19 129.68,69.01C129.34,73.47 128.63,77.87 127.94,82.28C127.87,82.73 127.85,83.2 127.92,83.64C129.06,90.12 128.54,96.56 127.53,102.99C127.25,104.78 127.16,106.6 126.95,108.77ZM224.11,123.08C223.37,123.36 223.05,122.79 222.59,122.6C219,121.07 218.1,121.39 216.11,124.77C215.07,126.52 213.71,128.03 212.21,129.41C209.16,132.22 208.38,136.45 210.38,140.08C211.15,141.48 212.23,142.73 214.31,142.53C213.18,140.24 212.28,138.02 211.77,135.66C211.6,134.85 211.52,134.05 211.96,133.38C213.45,131.07 219.07,129.11 221.71,129.92C226.96,131.51 228.85,137.35 225.53,141.71C225.05,142.34 224.29,142.81 224.08,143.63C224.44,143.9 224.68,143.81 224.9,143.66C227.91,141.63 230.62,139.3 232.3,135.98C233.27,134.07 234.56,132.23 234.55,129.99C234.54,126.4 233.2,123.32 230.91,120.5C228.21,117.18 224.89,114.75 221.28,112.6C219.91,111.78 219.5,111.92 219.15,113.43C218.96,114.26 218.72,115.08 218.5,115.9C217.85,118.41 219.03,120.43 221.52,121.03C222.71,121.32 223.61,121.9 224.12,123.07L224.11,123.08ZM141.99,194.55C143.09,194.73 144,194.87 144.91,195.02C149.57,195.8 154.21,196.63 158.97,196.61C160.23,196.6 160.29,196.32 159.94,195.29C159.43,193.74 158.94,192.16 158.63,190.56C158.38,189.28 157.67,188.9 156.51,188.72C152.1,188.02 147.69,187.38 143.24,186.91C137.23,186.28 131.34,184.92 125.57,183.1C124.67,182.81 123.98,182.94 123.71,183.89C123.27,185.43 122.38,186.75 121.6,188.09C120.88,189.34 121.37,189.92 122.33,190.44C122.79,190.68 123.32,190.81 123.83,190.9C129.99,191.94 136.08,193.29 141.99,194.55V194.55ZM222.17,95.47C222.14,95.47 222.1,95.46 222.07,95.46C221.89,96.56 221.71,97.66 221.54,98.76C221.26,100.49 221.62,100.81 223.26,100.11C228.27,97.96 232.68,95.03 235.91,90.53C237.66,88.08 237.81,84.65 236.17,82.34C234.5,79.99 229.18,78.01 226.29,78.66C225.74,78.78 225.27,79 225.25,79.64C225.23,80.37 224.66,81.3 225.62,81.76C226.94,82.4 226.88,83.41 226.68,84.57C226.42,85.99 226.18,87.41 225.96,88.83C225.85,89.54 225.61,90.2 224.81,90.19C222.98,90.15 222.78,91.4 222.6,92.75C222.49,93.66 222.32,94.56 222.18,95.47L222.17,95.47ZM220.74,131.1C218.1,130.93 215.5,131.78 213.12,133.43C212.66,133.75 212.65,134.17 212.67,134.63C212.9,139.25 215.77,142.94 220.3,144.49C220.89,144.7 221.3,144.64 221.71,144.25C223.04,142.99 224.38,141.77 225.33,140.18C227.33,136.84 224.9,131.73 220.74,131.1H220.74ZM198.34,121.96C198.34,121.96 198.35,121.93 198.35,121.92C197.06,121.71 195.76,121.49 194.47,121.3C193.82,121.21 193.04,121.11 192.71,121.81C192.1,123.12 191.75,124.52 191.67,125.97C191.62,126.93 192.6,127.16 193.06,127.76C193.57,128.44 194.1,129.1 194.59,129.79C196.04,131.84 197.87,133.26 200.57,133.27C201.82,133.28 202.57,132.91 202.82,131.64C203.28,129.19 203.56,126.72 203.7,124.23C203.75,123.26 203.36,122.75 202.42,122.61C201.06,122.4 199.71,122.18 198.35,121.96H198.34ZM152.66,162.35C152.32,163.59 152.24,164.8 152.64,165.91C153.44,168.18 154.15,170.49 154.6,172.86C154.79,173.88 155.39,174.16 156.29,173.92C157.7,173.56 158.88,172.73 160.14,172.05C161.35,171.41 161.51,170.45 161.06,169.45C159.71,166.49 159.35,163.13 157.45,160.39C157.01,159.75 156.77,158.64 155.65,158.95C154.54,159.26 153.32,159.55 152.91,160.88C152.76,161.38 152.74,161.91 152.66,162.35V162.35ZM162.8,103.33C164.25,103.49 165.5,102.92 166.66,102.15C167.61,101.54 167.97,100.78 167.08,99.75C164.95,97.28 162.87,94.76 160.73,92.28C160.1,91.54 159.38,90.86 158.65,90.2C158.27,89.86 157.71,89.45 157.44,90.28C156.88,92.02 156.23,93.87 157.01,95.62C157.93,97.7 158.92,99.78 160.27,101.65C160.92,102.54 161.65,103.22 162.8,103.33V103.33ZM108.68,70.76C108.68,70.96 108.67,71.15 108.66,71.35C108.36,76.36 109.25,81.37 108.53,86.37C108.39,87.31 108.93,87.47 109.75,87.23C111.8,86.65 113.11,84.92 113.01,82.73C112.88,79.88 112.75,77.02 112.48,74.19C112.36,72.84 112.18,71.46 111.47,70.23C111.02,69.47 110.33,69.37 109.61,69.45C108.88,69.53 108.74,70.14 108.69,70.76L108.68,70.76ZM106.56,295.08C107.14,295.17 107.72,295.25 108.3,295.36C109.75,295.65 110.36,295.1 110.66,293.61C111.34,290.29 110.41,287.45 108.61,284.75C107.91,283.7 107.51,283.87 107.05,284.92C106.09,287.13 105.16,289.35 104.37,291.63C103.32,294.67 103.31,294.67 106.56,295.08ZM46.3,245.09C48.86,242.27 51.3,239.82 53.14,236.88C53.43,236.41 54.16,236.09 53.79,235.39C53.42,234.7 52.65,234.69 52.03,234.76C49.76,235.03 47.51,235.41 45.55,236.76C44.8,237.28 44.54,237.91 44.64,238.76C44.88,240.84 45.47,242.83 46.29,245.09H46.3ZM155.7,116.32C155.14,119.05 154.68,121.65 154.46,124.29C154.4,125.09 154.9,125.7 155.71,126.11C157.16,126.84 158.71,126.94 160.27,127.16C161.66,127.35 161.7,126.81 161.13,125.74C159.79,123.2 158.54,120.61 157.23,118.06C156.91,117.46 156.65,116.78 155.7,116.32ZM292.34,281.17C290.68,280.88 289.12,281.34 287.56,281.78C286.84,281.98 286.64,282.37 286.99,283.08C287.83,284.83 288.62,286.6 289.43,288.37C289.84,289.27 290.19,289.54 291.09,288.65C292.38,287.38 293.2,285.86 293.95,284.28C294.87,282.35 294.42,281.52 292.34,281.17ZM217.47,303.62C217.63,304.55 216.75,305.91 218.02,306.7C219.17,307.41 220.49,307.88 221.76,308.36C222.48,308.64 222.78,308.32 222.76,307.48C222.71,305.19 222.37,302.94 222.15,300.67C222.09,300.14 221.96,299.8 221.35,299.84C220.1,299.92 217.68,302.19 217.47,303.62H217.47ZM171.66,143.77C171.47,144.67 171.32,145.3 171.21,145.94C171.09,146.71 170.99,147.49 170.92,148.27C170.69,150.86 171.28,151.53 173.87,151.63C174.51,151.66 175.16,151.61 175.82,151.61C176.3,151.61 176.68,151.34 176.41,150.91C174.94,148.59 174.23,145.75 171.67,143.77H171.66ZM226.44,68.62C226.28,69.64 225.99,71.39 225.72,73.15C225.67,73.46 225.61,73.86 226,74C226.51,74.18 226.71,73.76 226.81,73.4C227.86,69.71 228.29,65.93 228.33,62.11C228.33,61.72 228.19,61.26 227.68,61.31C227.18,61.37 227.17,61.81 227.18,62.22C227.25,64.14 226.57,65.98 226.44,68.63V68.62ZM225.26,86.01C225.29,86.02 225.33,86.03 225.36,86.03C225.49,85.26 225.63,84.49 225.73,83.71C225.77,83.32 225.76,82.87 225.24,82.81C224.87,82.76 224.65,83.05 224.58,83.39C224.24,84.99 223.91,86.59 223.59,88.19C223.51,88.53 223.55,88.86 223.93,88.99C224.37,89.13 224.74,88.96 224.84,88.52C225.03,87.7 225.13,86.85 225.26,86.02L225.26,86.01Z" - android:fillColor="#000000"/> - <path - android:pathData="M174.8,86.15C166.95,84.89 159.1,83.65 151.26,82.37C147.9,81.81 144.55,81.15 141.19,80.52C139.62,80.22 138.69,79.08 138.91,77.38C139.35,74.06 139.82,70.74 140.53,67.47C141.08,64.93 142.87,64 145.66,64.49C158.91,66.85 172.15,69.25 185.4,71.61C193.1,72.98 200.8,74.32 208.49,75.68C209.2,75.8 209.91,75.95 210.59,76.18C212.46,76.81 213.38,78.03 213.38,79.98C213.38,83.54 212.68,87.03 212.07,90.52C211.78,92.14 210.4,92.88 208.85,92.58C202.6,91.39 196.34,90.21 190.08,89.07C184.98,88.14 179.82,87.5 174.8,86.15ZM174.96,85.21C186.26,86.87 197.13,89.16 208.09,90.91C210.11,91.24 210.54,90.98 210.84,88.97C211.14,86.97 211.21,84.93 211.58,82.92C212.43,78.2 211.9,77.53 207.13,76.68C200.08,75.41 193.02,74.21 185.98,72.91C178.75,71.58 171.47,70.5 164.24,69.1C157.93,67.88 151.56,66.9 145.21,65.85C143.1,65.5 142.29,65.93 141.66,67.97C140.75,70.92 140.34,73.98 140.15,77.07C140.08,78.34 140.63,78.94 141.95,79.13C153.13,80.77 164.16,83.21 174.96,85.2L174.96,85.21Z" - android:fillColor="#000000"/> - <path - android:pathData="M137.08,148.07C135.85,147.87 134.61,147.7 133.38,147.47C130.99,147.02 130.3,145.89 130.81,143.57C131.32,141.33 131.81,139.08 132.14,136.81C132.33,135.45 133.05,134.92 134.24,135.07C136.91,135.41 139.57,135.83 142.22,136.32C143.51,136.56 144.21,137.53 144.4,138.81C144.82,141.74 143.99,144.55 143.43,147.37C143.22,148.43 142.37,148.96 141.17,148.72C139.81,148.46 138.45,148.27 137.08,148.06C137.08,148.06 137.08,148.07 137.08,148.07V148.07ZM132.57,140.71H132.59C132.4,141.87 132.24,143.04 132.02,144.2C131.8,145.31 132.27,146.07 133.32,146.21C135.9,146.55 138.4,147.38 141.03,147.38C141.74,147.38 142.13,147.19 142.24,146.45C142.55,144.38 142.93,142.33 143.2,140.25C143.43,138.45 143.01,137.9 141.19,137.57C139.01,137.16 136.8,136.88 134.62,136.48C133.62,136.3 133.15,136.57 133.05,137.61C132.95,138.65 132.74,139.68 132.57,140.71L132.57,140.71Z" - android:fillColor="#000000"/> - <path - android:pathData="M162.8,146.38C162.64,147.35 162.52,148.33 162.32,149.29C162.01,150.87 161.28,151.45 159.73,151.24C157.58,150.96 155.43,150.66 153.31,150.25C150.94,149.79 150.11,148.85 150.29,146.47C150.46,144.06 150.97,141.67 151.29,139.26C151.41,138.31 152.08,138.09 152.82,138.11C155.69,138.22 158.58,138.19 161.26,139.52C162.83,140.29 163.53,141.34 163.33,143.08C163.2,144.18 162.99,145.28 162.81,146.38H162.8L162.8,146.38ZM156.51,149.36C157.61,149.54 158.71,149.72 159.81,149.89C160.41,149.98 160.78,149.82 160.95,149.15C161.46,147.18 161.95,145.21 162.16,143.19C162.28,142.1 161.93,141.41 160.76,140.97C158.38,140.07 155.89,139.94 153.44,139.52C152.69,139.39 152.4,139.7 152.32,140.46C152.1,142.54 151.86,144.63 151.54,146.7C151.35,147.95 151.94,148.49 153.01,148.84C154.15,149.21 155.35,149.15 156.51,149.37V149.36Z" - android:fillColor="#000000"/> - <path - android:pathData="M146.99,120.32C146.78,121.68 146.57,123.04 146.34,124.4C146.12,125.64 145.44,126.21 144.11,125.99C141.59,125.56 139.04,125.23 136.52,124.78C134.26,124.37 133.56,123.27 133.87,121.03C134.24,118.44 135.29,115.97 135.2,113.3C135.17,112.58 135.86,112.33 136.45,112.26C139.5,111.86 142.48,112.24 145.37,113.23C147.31,113.89 147.88,114.97 147.59,117.02C147.43,118.12 147.24,119.22 147.06,120.33C147.04,120.33 147.01,120.32 146.99,120.32H146.99ZM141.39,113.99C141.39,113.99 141.39,113.99 141.39,114C140.16,113.8 138.92,113.64 137.69,113.39C136.51,113.15 135.92,113.6 135.93,114.79C135.93,116.91 135.57,118.98 134.99,121.01C134.6,122.39 135.12,123.26 136.43,123.49C138.75,123.89 141.1,124.19 143.45,124.41C144.07,124.47 144.95,124.47 145.1,123.44C145.45,121.24 146.31,119.14 146.53,116.9C146.68,115.25 146.4,114.84 144.7,114.53C143.6,114.33 142.49,114.17 141.39,113.99L141.39,113.99Z" - android:fillColor="#000000"/> - <path - android:pathData="M187.63,20.76C187.39,22.45 185.93,23.6 184.31,23.39C182.74,23.17 181.76,21.78 182,20.12C182.26,18.37 183.66,17.22 185.25,17.45C186.77,17.68 187.86,19.19 187.64,20.76L187.63,20.76ZM185.59,22.12C186.98,21.33 187.03,20.46 186.42,19.49C185.96,18.75 185.37,18.17 184.34,18.84C185.53,19.65 185.95,20.74 185.59,22.12Z" - android:fillColor="#000000"/> - <path - android:pathData="M152.37,67.43C150.18,67.21 150.12,68.83 149.41,70.12C148.13,70.07 148.93,68.84 148.25,68.53C147.66,68.26 147.29,69.81 146.83,68.94C146.79,68.88 147.13,67.5 145.93,68.03C145.79,68.13 145.61,68.24 145.46,68.38C143.62,70.05 143.08,72.49 143.57,74.86C144.03,77.09 145.77,77.83 147.53,78.32C147.66,78.36 147.8,78.38 147.93,78.43C149.88,79.2 151.62,78.06 153.09,76.9C154.68,75.64 154.63,73.05 154.14,71.31C153.79,70.11 152.8,68.58 152.37,67.43H152.37ZM149.09,72.63C150.16,71.84 149.57,71.5 151.05,72.41C150.67,74.24 148.55,75.42 147.59,74.04C146.94,73.11 148.19,73.3 149.09,72.63ZM152.66,76.45C149.85,78.42 147.54,78.39 145.28,76.41C144.24,75.49 143.9,72.9 144.54,71.6C144.84,70.98 145.42,69.65 145.76,69.07C146.51,69.2 146.38,69.93 146.95,69.86C147.26,69.83 148.1,69.07 148.01,69.58C147.8,70.64 148.73,71.69 149.12,71.92C148.41,72.71 146.29,72.24 146.41,73.44C146.46,73.99 147.15,74.98 147.53,75.28C148.73,76.23 150.06,75.71 151.2,74.5C152.35,73.27 151.85,72.17 150.12,70.3C150.4,69.55 150.62,68.24 151.38,67.97C152.09,68.31 152.66,70.03 152.9,70.56C154.05,73.09 154.23,75.36 152.67,76.44L152.66,76.45Z" - android:fillColor="#000000"/> - <path - android:pathData="M202.09,81.68C202.44,80.48 203.12,79.48 204.37,79.26C205.7,79.03 206.92,79.35 207.73,80.7C208.46,81.92 208.35,82.9 207.29,83.8C206.19,84.73 206.79,85.64 207.27,86.58C207.52,87.07 208.1,87.68 207.33,88.09C206.52,88.53 206.09,87.83 205.94,87.2C205.58,85.68 204.75,84.77 203.25,84.2C202.32,83.85 202.05,82.73 202.09,81.68L202.09,81.68ZM204.9,83.64C205.72,83.65 206.57,83.46 206.73,82.44C206.89,81.45 206.48,80.61 205.35,80.52C204.38,80.45 203.54,80.75 203.38,81.92C203.23,83.02 203.92,83.4 204.9,83.64Z" - android:fillColor="#000000"/> - </group> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_sync.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_sync.xml deleted file mode 100644 index 72bad6deca231622a769172715de959e2ae92ef9..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_sync.xml +++ /dev/null @@ -1,21 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="235dp" android:height="298dp" android:viewportWidth="235" android:viewportHeight="298"> - <path android:pathData="M89.1 218.91l4.15-41.59 83.68-2.25 4.9 4.87v14.61l-4.9 37.85-53.53 22.85-22.99-2.62-14.7-10.86-18.09-22.86v-5.24l21.48 5.24zM8.43 111L2.02 84.77l21.87-8.24 4.14 13.49-8.67 7.87L8.43 111zm30.91 13.49l-5.28 2.62 2.65-9.74 2.64 7.11-0.01 0.01z"> - <aapt:attr name="android:fillColor"> - <gradient android:startX="182" android:startY="213" android:endX="-5.14" android:endY="138.72" android:type="linear"> - <item android:offset="0" android:color="#FF7662AB"/> - <item android:offset="0.52" android:color="#FFEE4F9C"/> - <item android:offset="1" android:color="#FFFDBD50"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M83.63 98.18l3.22-15.2 9.69-3.23 7.37-8.75 8.76 15.2 7.84 3.69-4.61 10.13-8.76 3.69-10.6 2.76-7.84-2.76-5.07-5.53z" android:fillColor="#86573C"/> - <path android:pathData="M57.34 60.87V41.53l9.22-4.15 29.98-7.83 22.58 18.43-16.59 26.25-17.06 9.21-14.75-5.06-13.37-17.51h-0.01zm-44.26 53.89l4.61 29.48 4.61 1.38 12.91-5.99v-12.44l3.69-5.99-5.99-17.51v-9.67l-0.93-3.22-9.68 7.83-9.22 16.12v0.01zm122.18 154.77l-3.69 19.35 23.05 3.22 3.23-19.81-22.59-2.76zM91 278.74v13.36l20.29-5.99-5.07-4.15L91 278.74z" android:fillColor="#86573C"/> - <path android:strokeWidth="1" android:pathData="M102.53 74.23l6.91 2.76 9.68 11.98v8.29l-14.75 8.3H92.39l-8.3-6.91 3.23-12.44m15.21-11.98l-17.06 9.21-14.75-5.06-13.37-17.51V41.53l9.22-4.15 29.97-7.83 22.59 18.43-16.6 26.25zm-84.84 70.01l-4.61-29.48 9.22-16.12 9.68-7.83 0.93 3.22v9.68l5.99 17.5-3.69 5.99v12.44l-12.91 5.99-4.61-1.38v-0.01zm113.88 144.64l3.69-19.35 22.59 2.76-3.23 19.81-23.05-3.22zM91 292.1v-13.36l15.21 3.22 5.07 4.15L91 292.1z" android:strokeColor="#010101"/> - <path android:pathData="M183.53 211.94c2.01-0.74 3.7-1.41 5.41-2.02 2.3-0.79 4.66-1.03 7.01-1.42 2.1-0.37 4.15-0.92 6.24-1.3 1.24-0.22 2.54-0.48 3.76-0.34 1.71 0.19 3.46 0 5.17 0.4 0.58 0.13 1.22 0.03 1.81 0.27 3.2 1.36 6.82 1.62 9.79 3.48 3.82 2.38 6.91 5.51 8.43 9.88 0.76 2.17 2.04 4.15 2.52 6.39 0.78 3.56 1.01 7.18 0.25 10.76-1.02 4.81-2.93 9.3-5.65 13.42-1.93 2.93-4.41 5.36-6.82 7.83-1.06 1.06-2.49 1.58-3.94 2.04-2.11 0.68-3.98 1.64-4.61 4.05-0.23 0.86-1.23 1.15-1.92 1.65-0.83 0.58-1.64 1.24-2.61 1.64-0.52 0.2-0.57 0.38-0.07 0.82 2.61 2.28 4.74 4.96 6.3 8.04 0.7 1.36 0.72 2.95 0.87 4.46 0.03 0.25 0.11 0.62-0.36 0.63-0.18 0-0.4 0.07-0.26 0.27 1.06 1.34-0.36 2.22-0.81 3.03-1.56 2.81-3.61 5.32-6.41 7.01-0.95 0.56-2.03 0.93-3.19 1.21-1.12 0.26-2.3 0.69-3.44 0.7-5.23 0.09-10.3 1.51-15.53 1.67-4.44 0.13-8.88 0.34-13.3-0.09-3.54-0.36-7.03-1.12-10.57-1.41-4.51-0.38-8.88-1.81-13.41-1.86-2.71-0.02-5.37-0.4-7.95-1.02-2.33-0.57-4.76-0.98-6.94-2.15-0.68-0.36-0.87 0-1.01 0.48-0.2 0.72 0 1.58-0.93 1.99-1.07 0.47-2.11 0.26-3.11-0.1-4.56-1.64-9.12-3.29-13.64-4.99-0.71-0.28-1.37-0.09-1.88 0.17-4.81 2.36-9.95 3.49-15.15 4.49-3.32 0.63-6.57 1.59-9.9 2.05-2.47 0.35-4.94 0.54-7.45 0.66-5.27 0.24-10.54 0.43-15.8 0.2-1.7-0.07-3.4 0-5.1-0.1-5.41-0.37-10.62-1.28-14.39-5.76-2.45-2.92-3.78-6.28-3.87-10.09-0.03-1.79 0.64-3.42 1.42-5.01 0.93-1.89 1.95-3.74 3.26-5.39 0.38-0.48 0.54-1.35 1.54-0.92 0.14 0.05-0.05-0.76 0.59-0.84-6.1-1.73-11.89-3.94-17.61-6.31-0.58-0.25-1.1-0.57-1.48-1.08-1.5-2.03-3.61-3.06-5.96-3.78-2.15-0.66-4.15-1.65-5.67-3.38-2.52-2.85-4.95-5.82-6.51-9.33-0.98-2.2-1.63-4.47-1.91-6.94-0.32-2.86-0.3-5.61 0.24-8.4 0.62-3.34 1.88-6.39 4.23-8.92 1.07-1.16 1.66-2.62 2.66-3.83 2.37-2.86 5.28-4.77 8.72-6.18 2.17-0.9 4.39-1.5 6.62-2.1 1.2-0.33 0.95-0.57 0.33-1.24-1.73-1.88-2.94-4.12-4.2-6.3-1.5-2.6-2.51-5.39-3.56-8.16-1.66-4.31-3.04-8.7-4.16-13.18-0.87-3.46-1.5-6.97-2.02-10.5-0.6-4.1-1.25-8.19-1.52-12.31-0.17-2.6 0.04-5.26-0.07-7.89-0.09-2.18 0.11-4.35-0.1-6.54-0.33-3.5-0.87-6.97-1.61-10.38-1.05-4.98-2.42-9.89-3.73-14.79-0.31-1.19-0.71-2.45-1.42-3.42-1.43-1.89-1.45-4.2-2.16-6.3-1.1-3.28-1.85-6.7-2.77-10.07-0.69-2.52-1.4-5.01-2.09-7.53-0.71-2.61 1.56-5.61 4.22-6.04 2.02-0.33 4.02-0.84 5.94-1.71 2.35-1.06 4.6-2.48 7.17-2.97 1.64-0.33 3.34-0.71 5.03-0.52 2.01 0.22 2.73 1.79 3.35 3.46 1.09 2.86 1.68 5.85 2.46 8.82 0.15 0.6 0.22 0.84 1.03 0.62 1.1-0.33 2.39-0.72 3.46 0.24 1.1 1 1.34 2.47 0.65 3.86-0.45 0.92-0.85 1.89-1.57 2.62-1.28 1.27-0.53 2.56-0.26 3.91 0.19 0.91 0.92 1.39 1.35 2.09 0.58 0.95 1 2.1 1.17 3.2 0.61 3.88 1.99 7.47 3.58 11.04 1 2.24 1.74 4.65 2.19 7.06 0.4 2.05-0.45 4.7-3.35 5.53-0.52 0.14-0.97 0.38-1.47 0.54-1.68 0.53-1.74 0.67-1.52 2.46 0.24 1.87 0.24 3.77 0.29 5.67 0.02 0.87 0 1.75-0.12 2.61-0.08 0.62 0.65 0.54 0.66 1 0.27-1.45 1.02-2.71 1.54-4.01 1.83-4.62 3.44-9.33 5.8-13.72 0.94-1.73 1.82-3.48 2.87-5.13 2-3.12 4-6.25 6.2-9.25 1.14-1.55 2.09-3.24 3.47-4.59 2.03-2.02 4.68-2.71 7.29-3.53 2.74-0.88 5.54-1.58 8.32-2.29 2.73-0.69 5.44-1.47 8.23-1.91 0.69-0.11 1.34-0.16 1.76 0.69 0.64-0.85 0.21-1.9 0.81-2.79 1.21-1.83 1.79-4 2.06-6.18 0.1-0.86 0.05-1.73 0.1-2.59 0.03-0.38-0.1-0.57-0.46-0.53-2.24 0.13-4.15-0.83-6.2-1.42-2.97-0.86-5.55-2.36-8.1-3.87-2.66-1.58-4.61-3.96-6.42-6.49-2.27-3.17-4.05-6.56-5.6-10.09-0.78-1.8-1.71-3.58-2.14-5.46-0.38-1.69-1.16-3.31-1.14-5.12 0-0.58-0.5-1.08 0.4-1.34-0.09-0.26-0.11-0.64-0.28-0.77-0.72-0.59-0.89-1.31-0.81-2.19 0.05-0.46 0-0.98-0.13-1.43-0.3-0.91-0.02-1.67 0.57-2.41-3.61-1.44-6.7-3.67-9.62-6.04-1.74-1.42-2.5-3.65-3.18-5.82-0.15-0.48 0.54-0.19 0.42-0.61-1.61-0.14-1.02-1.5-1.02-2.27 0.04-3.15 1.31-5.96 2.64-8.75 0.43-0.91 0.74-1.89 1.16-2.82 1.1-2.57 2.47-4.97 4.87-6.55 1.88-1.22 3.87-2.32 6.17-2.51 0.69-0.05 1.34-0.12 2.02-0.25 0.72-0.11 1.48-0.17 2.14 0.37 0.31 0.25 0.67 0.18 0.95-0.18 1.11-1.44 2.66-1.19 4.18-1.12 0.31 0 0.42 0.12 0.42 0.45 0 0.09 0.4 0.31 0.47 0.25 1.41-0.85 2.84 0 4.28-0.05 0.61-0.03 1.09-0.31 1.37-0.7 1.41-1.96 3.16-3.62 5.09-4.99 1.09-0.77 2.37-1.73 3.98-1.35 0.1 0.02 0.31 0.05 0.31 0.04 0.5-1.64 1.99-1.05 2.85-0.93 3.92 0.56 7.93 1.02 11.06 3.91 0.71 0.66 1.73 0.81 2.63 0.93 2.9 0.43 5.63 1.33 8.38 2.29 1.83 0.64 3.9 0.48 5.77-0.17 4.57-1.6 8.93-0.76 13.25 0.91 1.03 0.4 2.03 0.85 3.09 1.17 2.28 0.71 4.06 2.29 6.13 3.36 2.33 1.19 4.64 2.45 6.99 3.65 3.15 1.62 4.61 4.63 6.31 7.47 2.1 3.53 3.85 7.23 5.75 10.86 1.79 3.44 4.07 6.58 7.39 8.82 0.34 0.22 0.57 0.46 0.92 0.05 0.51-0.63 1.02-0.54 1.69-0.11 2.54 1.62 5.1 3.22 7.74 4.7 1.72 0.97 3.35 2.05 5.11 2.95 2.4 1.2 4.89 2.22 7.33 3.35 3.76 1.76 6.84 4.29 9.79 7.08 1.9 1.79 3.75 3.6 5.05 5.91 1.21 2.17 2.1 4.42 2.71 6.85 0.26 1.04 0.64 2.09 1.38 3.03 1.38 1.81 2.14 4.03 2.35 6.27 0.2 2.28 0.8 4.5 0.83 6.79 0.05 2.67 0.08 5.3-0.92 7.9-0.58 1.53-0.69 3.26-1.05 4.89-0.71 3.18-1.85 6.2-3.38 9.07-1.4 2.61-2.33 5.4-3.22 8.21-0.93 2.96-2.5 5.59-4.73 7.78-0.69 0.67-1.63 1.21-2.54 1.55-3.39 1.28-6.91 2.07-10.46 2.72-1.47 0.27-3.07 0.43-4.47-0.53-0.14-0.11-0.4-0.21-0.55-0.02-0.18 0.2-0.07 0.45 0.01 0.7 0.88 2.5 1.77 4.99 2.62 7.49 1.6 4.75 3.02 9.56 4.49 14.36 0.87 2.91 1.97 5.77 3.17 8.57 1.68 3.9 3.06 7.86 3.98 11.99 0.52 2.32 1.16 4.63 1.78 6.94 1.28 4.75 0.29 9.21-1.52 13.63-1.05 2.57-1.79 5.29-2.73 7.91-0.73 2.03-1.61 4.03-2.14 6.13-0.11 0.36-0.11 0.78-0.47 1.42l0.02-0.09-0.04 0.05zm-0.88-8.59c1.35-3.89 2.58-7.82 4.1-11.64 1.31-3.32 0.72-6.44-0.3-9.64-0.72-2.25-1.07-4.61-1.63-6.91-0.47-1.91-0.94-3.8-1.72-5.61-1.16-2.77-2.23-5.6-3.49-8.34-1.86-4.11-2.76-8.54-4.14-12.81-1.68-5.17-3.57-10.23-5.56-15.25-1.25-3.13-2.06-6.41-3.27-9.54-0.86-2.25-2.01-4.32-3.05-6.44-1.56-3.15-3.44-6.14-5.53-8.97-1.4-1.89-2.87-3.71-4.56-5.37-1.61-1.57-3.38-2.88-5.23-4.12-2.28-1.55-4.72-2.87-7.34-3.71-2.14-0.69-4.3-1.42-6.57-1.67-1.62-0.19-3.21-0.62-4.85-0.49-0.21 0.02-0.66-0.32-0.62 0.25 0.05 1.24-0.78 2.09-1.23 3.15-1.14 2.6-2.48 5.06-4.44 7.11-1.17 1.22-2.33 2.53-3.42 3.77-1.85 2.12-3.94 3.7-6.33 5.06-2.5 1.43-5.23 2.19-7.93 3.03-1.85 0.59-3.86 0.57-5.82 0.48-2.99-0.1-5.87-0.84-8.75-1.51-5.95-1.38-10.23-4.81-12.99-10.16-0.45-0.86-0.71-1.1-1.7-0.66-0.58 0.26-1.33 0.47-2.02 0.66-1.53 0.43-3.17 0.43-4.61 1.15-1.25 0.65-2.67 0.92-3.97 1.01-3.71 0.33-6.34 2.25-8.83 4.77-2.88 2.93-3.99 6.79-5.52 10.35-1.19 2.77-2.46 5.55-3.6 8.35-1.21 2.96-2.61 5.87-3.83 8.85-0.94 2.25-2.15 4.35-3.76 6.2-0.31 0.36-0.22 0.54-0.1 0.94 0.26 0.86 1.12 1.21 1.43 2.02 0.59 1.5 1.75 2.72 2.64 4 1.57 2.22 3.22 4.41 4.67 6.7 2.35 3.68 3.62 7.87 4.89 12 0.85 2.79 2.11 5.4 3.09 8.12 1.02 2.84 1.59 5.77 1.86 8.75 0.21 2.36 0.23 4.72 0.47 7.08 0.11 1.01-0.61 2.12-1.52 2.36-1.16 0.29-2.01-0.14-2.35-1.45-0.43-1.6-0.74-3.23-1-4.87-0.45-2.79-0.64-5.62-1.25-8.35-0.53-2.41-1.43-4.75-2.32-7.08-1.43-3.8-2.48-7.8-4.52-11.36-0.76-1.33-1.05-2.86-2.05-4.07-1.61-1.94-2.68-4.27-4.23-6.28-1.09-1.41-1.89-3.03-2.8-4.56-0.18-0.29-0.42-0.79-0.78-0.45-1.07 1-2.5 1.22-3.69 1.93-3.46 2.03-7.22 2.9-11.16 3.05-1.12 0.04-1.3 0.34-1.21 1.35 0.29 3.37 0.57 6.76 1.07 10.12 0.38 2.56 0.47 5.17 1.12 7.68 0.81 3.1 1.47 6.25 2.33 9.33 1.23 4.36 2.8 8.59 4.87 12.64 1.01 1.96 2.22 3.8 3.49 5.55 0.85 1.18 1.49 2.48 2.63 3.5 1.24 1.1 2.33 2.22 4.21 1.91 0.83-0.14 1.75-0.11 2.58 0.04 4.18 0.74 8.17 2.06 12.02 3.82 0.72 0.33 1.54 0.7 2.32 0.43 1.69-0.59 2.95-1.91 4.13-3.12 1.72-1.78 3.02-3.96 4.18-6.18 0.5-0.97 0.83-1.86 0.6-3.02-0.31-1.66-0.43-3.39-0.5-5.09-0.13-3.24-0.07-6.48-0.31-9.7-0.22-2.94-0.5-5.89-0.88-8.83-0.69-5.24-1.12-10.5-1.92-15.72-0.33-2.24-0.64-4.48-0.98-6.7-0.38-2.51-0.67-5.03-1.18-7.53-0.38-1.87 0.02-2.34 1.87-2.65 2-0.34 2.41-0.19 2.54 1.45 0.1 1.48 0.38 2.87 0.88 4.27 0.48 1.37 0.57 2.89 1.03 4.29 0.33 0.99 0.31 2.09 0.71 2.99 0.71 1.55 0.78 3.22 0.93 4.79 0.28 2.72 0.23 5.51 0.37 8.25 0.17 3.18 0.29 6.4 0.74 9.57 0.69 4.72 1.09 9.49 1.36 14.22 0.21 3.77 0.47 7.58 0.43 11.36 0 1.15-0.24 2.36-0.07 3.41 0.25 1.52 0.14 3.07 0.47 4.55 0.16 0.72-0.38 1.86 0.87 2.1 2.59 0.53 5.2 1.03 7.86 1.22 0.72 0.05 1.52 0.58 2.14 0.2 0.95-0.58 1.69-0.1 2.5 0.16 0.59 0.17 1.16 0.48 1.75 0.58 1.59 0.28 2.04-0.18 2.14-1.77 0.23-4.03 0.5-8.05 0.78-12.07 0.29-4.41 0.83-8.82 0.74-13.24-0.05-2.86-0.24-5.74 0.13-8.58 0.36-2.94 2.66-5.01 5.59-5.23 1.47-0.12 2.92 0.48 4.39 0.13 0.07-0.01 0.18 0 0.24 0.05 1.28 1.06 2.83 0.78 4.29 0.78 2.62 0 5.23-0.18 7.86-0.21 3.78-0.05 7.56 0 11.35-0.07 4.38-0.08 8.77-0.08 13.14-0.31 3.84-0.19 7.67-0.2 11.52-0.22 3.85 0 7.69 0.24 11.54 0.05 3.93-0.19 7.87-0.3 11.8-0.14 1.38 0.05 3.11-0.43 4.21 1.08 0.09 0.12 0.4 0.19 0.57 0.14 1.86-0.55 3.23 0.55 4.2 1.72 2.23 2.68 3.44 5.87 3.26 9.39-0.18 3.87-0.69 7.71-1 11.56-0.16 1.93-0.67 3.81-0.5 5.77l0.04 0.07-0.01 0.03zm-83.9-24.43v-0.02h-1.29c-1.49 0.04-1.75 0.31-1.75 1.79 0 0.9 0.11 1.8-0.02 2.67-0.44 2.88-0.72 5.79-1.05 8.68-0.29 2.62-0.43 5.24-0.64 7.85-0.14 1.85-0.12 3.71-0.47 5.53-0.29 1.55-0.5 3.15-0.81 4.68-0.33 1.58-0.38 3.43-0.4 5.15 0 0.83-0.67 1.57-0.58 2.22 0.24 1.69-0.31 3.27-0.49 4.88-0.34 3.15-0.58 6.3-0.91 9.45-0.05 0.47-0.07 1.29-0.42 1.27-0.54-0.03-0.55 0.28-0.36 0.39 0.86 0.41 0.47 1.08 0.31 1.58-0.43 1.41 0.24 3.03-0.81 4.3 0.65 0.62 0.17 1.08-0.22 1.53-1.18 1.28-1.18 1.43 0.11 2.68 0.59 0.57 1.18 1.14 1.82 1.64 2.61 1.98 5.51 3.44 8.32 5.1 1.67 0.98 3.2 1.91 5.15 0.86 0.08-0.05 0.24 0 0.36 0 1.64 0.12 3.28 0.48 4.9 0.22 1.34-0.2 2.51 0.88 3.94 0.25 0.35-0.16 1.47 0.03 2.23 0.15 2.58 0.4 5.17 0.69 7.76 1.02 1.05 0.13 2.12 0.39 3.14 0.29 1.08-0.12 2.13-0.57 3.16-0.93 4.86-1.72 9.54-3.78 14.22-5.91 1.9-0.86 3.75-1.8 5.63-2.67 3.47-1.58 7-3.06 10.33-4.94 3.3-1.84 6.58-3.72 9.92-5.46 0.69-0.36 1.81-0.57 2.03-1.84 0.5-2.68 1.39-5.29 1.84-7.96 0.36-2.16 1.09-4.22 1.33-6.39 0.24-2.2 0.58-4.37 0.79-6.57 0.24-2.52 1.05-4.93 1.4-7.42 0.23-1.67 0.81-3.26 0.92-4.98 0.1-1.63 0.94-3.17 1.12-4.83 0.09-0.81 0.6-1.85 0.45-2.38-0.49-1.6-0.09-3.17-0.03-4.7 0.06-2.31-0.07-4.5-1.01-6.58-0.26-0.59-0.73-1.24-1.59-0.63-0.48 0.35-1.07 0.32-1.65 0.3-1.32-0.04-2.58-0.47-3.93-0.45-2.1 0.04-4.21-0.18-6.34-0.14-2.37 0.05-4.73 0.21-7.11 0.36-4.17 0.28-8.34-0.18-12.53 0.03-4.31 0.23-8.65-0.39-13-0.1-2.2 0.15-4.41-0.26-6.64-0.14-2.16 0.11-4.35-0.05-6.53-0.07-3.66-0.03-7.32-0.32-10.98-0.15-3.21 0.13-6.43 0.27-9.64 0.41l0.02-0.03v0.01zm-86.11 55.06c-0.04 2.89 0.57 5.58 1.86 8.16 0.88 1.76 2.2 3.21 3.27 4.81 1.26 1.89 2.66 3.66 4.54 4.97 2.16 1.51 4.32 3.05 6.7 4.25 1.57 0.79 3.09 1.69 4.74 2.34 2.26 0.9 4.52 1.8 6.82 2.59 2.05 0.7 4.13 1.34 6.25 1.77 1.68 0.34 3.35 0.67 5.03 1.02 3.56 0.72 6.96 1.94 10.4 3.03 3.93 1.25 7.98 2.04 11.98 2.99 3.51 0.83 6.81 2.12 10.09 3.53 3.09 1.33 6.27 2.45 9.47 3.49 1.95 0.64 3.92 1.16 5.87 1.8 2.8 0.91 5.6 1.82 8.34 2.98 4.58 1.94 9.49 3.06 14.1 4.99 1.92 0.81 3.89 1.51 5.84 2.26 0.5 0.19 1.16 0.41 1.05-0.52-0.17-1.84 0.38-3.65 0.72-5.37 0.83-4.16 2.32-8.15 3.84-12.11 0.21-0.56 0.26-0.85-0.48-1.01-1.82-0.38-3.67-0.83-5.22-1.78-2.93-1.8-6.34-2.39-9.32-4.02-1.73-0.95-3.69-1.48-5.5-2.31-1.86-0.86-3.54-2.26-5.56-2.69-2.61-0.55-4.74-1.94-7.02-3.15-2.21-1.17-4.13-2.8-6.34-3.97-2.76-1.49-5.23-3.34-7.36-5.62-1.74-1.86-3.45-3.63-4.49-6.16-0.86-2.1-2.88-3.74-4.49-5.49-2.61-2.88-5.92-5.05-7.93-8.51-1.26-2.18-3.35-3.84-4.28-6.21-0.52-1.31-0.88-2.52-2.3-3.28-1.04-0.55-1.95-1.28-3.09-1.7-1.97-0.69-3.84-1.81-5.86-2.26-4.28-0.98-8.58-1.99-12.9-2.87-3.23-0.66-6.39-0.43-9.48 0.24-3.63 0.79-7.22 1.98-10.21 4.32-1.52 1.19-3.27 1.94-4.36 3.87-2.76 4.93-4.33 10.1-4.71 15.67l-0.02-0.05h0.01zM178.47 228c0.22-0.07 0.38-0.09 0.51-0.14 1.8-0.74 3.39-1.89 5.06-2.84 3.85-2.16 7.91-3.84 11.98-5.53 1.52-0.64 3.21-1.54 4.61 0.36 0.05 0.06 0.24 0.03 0.34 0.08 0.55 0.21 1.09 0.52 1.02 1.19-0.09 0.81-0.67 1.02-1.41 1.03-1.33 0.02-2.58 0.52-3.82 0.93-2.02 0.68-3.96 1.6-5.91 2.43-1.7 0.72-3.31 1.6-4.89 2.55-3.31 1.98-6.6 4.03-9.93 6.01-4.25 2.54-8.24 5.5-12.87 7.42-0.88 0.36-1.83 0.7-2.64 1.19-3.08 1.79-6.06 3.71-9.38 5.04-1.47 0.58-3.01 1.12-4.39 1.86-3.06 1.64-6.21 2.99-9.47 4.13-4.61 1.62-9.29 3.02-14.11 3.93-1.74 0.33-3.5 0.79-5.4 1.65 0.72 0.36 1.19 0.6 1.65 0.81 3.32 1.39 6.6 2.83 9.95 4.13 2.64 1.04 5.2 2.33 8.05 2.77 0.38 0.05 0.76 0.21 0.74 0.48-0.07 1.16 0.83 0.86 1.35 0.86 3.12 0 6.23 0.45 9.34 0.69 2.97 0.25 5.94 0.16 8.85-0.17 1.74-0.19 3.52-0.55 5.3-0.84 3.33-0.54 6.68-0.97 10-1.48 2.68-0.41 5.37-0.83 8.07-1.29 3.52-0.61 7.08-0.74 10.65-0.72 2.39 0 4.72 0.49 7.11 0.43 1.57-0.05 2.81 1.06 4.28 1.46 0.64 0.17 1.66 0.7 1.86 0.31 0.87-1.75 2.17-1.33 3.61-0.95-0.19-0.87 0.29-1.29 0.94-1.75 3.43-2.46 7.04-4.65 10.12-7.61 3.28-3.15 6.24-6.49 8.12-10.69 1.05-2.34 2.01-4.74 2.55-7.19 0.4-1.83 0.54-3.76 0.54-5.69 0-4.47-1.46-8.34-4.43-11.65-0.57-0.64-1.29-1.16-1.76-1.83-1.83-2.67-4.89-3.89-7.11-6.11-1.54-1.55-3.85-1.73-5.9-2.19-4.42-1.01-8.88-0.44-13.21 0.45-3.47 0.72-6.89 1.81-10.23 3.1-2.44 0.95-5.05 1.57-6.82 3.72-0.11 0.12-0.29 0.25-0.42 0.24-1.38-0.12-1.54 0.79-1.66 1.83-0.29 2.53-0.89 5.03-0.86 7.66v-0.05l0.02-0.02zm-68.3-177.79c-0.09-1.72-0.42-3.37-1.71-4.65-0.72-0.7-1.47-1.44-2.33-1.96-0.4-0.22-0.76-0.65-1.37-0.65-1.93-0.04-3.8 1.39-4.21 3.3-0.09 0.4-0.31 0.74-0.4 1.14-0.23 0.9-0.8 1.21-1.7 1.19-1-0.02-1.4-0.67-1.48-1.48-0.09-0.92-0.4-1.73-0.7-2.57-0.29-0.84-0.51-1.7-0.6-2.61-0.29-3.01-0.78-3.58-3.63-4.41-1.45-0.41-2.97-0.58-4.42-1-2.62-0.74-5.01 0-7.13 1.33-1.86 1.17-3.54 2.58-5.95 2.24-0.17-0.02-0.41 0.07-0.57 0.18-2.43 1.7-5.37 2.01-8.07 2.96-0.29 0.11-0.64 0.05-0.96 0.09-1.7 0.17-3.38 0.33-5.08 0.55-0.31 0.04-0.83 0.11-0.78 0.57 0.25 1.95-0.08 3.91 0.25 5.87 0.11 0.72 0.34 1.01 1 1.08 0.74 0.07 1.34 0.31 1.76 1.04 0.45 0.79 1.3 0.92 2.08 0.63 0.77-0.31 1.52-0.79 2.19-1.29 0.57-0.43 2.88-0.58 3.38-0.07 0.67 0.69 1.37 1.69 0.71 2.46-0.83 0.97-1.47 2.24-2.85 2.67-1.76 0.55-3.53 0.83-5.39 0.45-1.5-0.31-1.76 0.05-1.41 1.51 0.11 0.56 0.74 1.36 0.2 1.66-0.74 0.41-0.4 0.77-0.26 1.15 0.69 1.88 1.69 3.62 2.73 5.32 2.57 4.28 5.27 8.46 9.64 11.11 1.17 0.72 2.16 1.76 3.54 2.14 3.76 1.03 7.55 1.82 11.49 1.25 1.34-0.19 2.66-0.43 3.89-1.03 1.48-0.74 2.57-2.03 3.98-2.89 0.99-0.61 1.8-1.49 2.46-2.4 1.96-2.68 3.42-5.68 5.04-8.57 1.32-2.32 2.42-4.75 1.99-7.54-0.05-0.31 0.14-0.45 0.29-0.62 0.56-0.6 1.09-1.22 1.64-1.8 1.7-1.8 2.8-3.81 2.71-6.36l0.02 0.04 0.01-0.03zM23.06 142.6c0.95-0.29 2.02 0.3 3.06-0.25 1.12-0.6 2.38-0.9 3.43-1.65 1.46-1.05 3.53-1.53 3.16-4.11-0.34-2.54-0.41-5.1-0.48-7.67-0.05-2.07 0.07-4.11 1.19-5.99 0.64-1.07 1.36-2.03 2.26-2.86 0.48-0.44 0.88-1.06 0.55-1.63-0.31-0.56-0.86 0.08-1.31 0.13-0.36 0.05-0.71 0.19-1.05 0.32-1.04 0.34-2.3 0-2.51-0.68-0.27-0.92 0.42-2.24 1.35-2.63 0.57-0.24 1.16-0.52 1.59-0.93 0.49-0.47 1.05-1.05 0.48-1.84-0.6-0.84-1.21-0.97-1.92-0.07-0.29 0.38-0.69 0.72-1.09 1-0.86 0.56-1.88 0.74-2.7 0.13-0.79-0.58-0.77-1.48-0.26-2.39 0.43-0.77 1.07-1.31 1.73-1.85 1.94-1.56 2.37-2.67 1.76-4.51-0.48-1.43-0.74-1.48-1.85-0.4-2 1.96-3.68 4.17-5.21 6.51-0.54 0.84-1.5 1.35-2.42 0.98-0.92-0.38-1.16-1.31-0.71-2.34 0.34-0.77 0.65-1.57 1.21-2.2 1.52-1.76 2.9-3.72 3.85-5.74 1.07-2.31 2.26-4.59 3.11-7.01 0.13-0.38 0.48-0.81 0.08-1.1-0.43-0.34-0.87-0.17-1.29 0.23-2.35 2.22-4.44 4.68-6.44 7.21-0.99 1.24-1.64 2.69-2.63 3.93-0.24 0.31-0.48 0.91-0.84 0.76-0.56-0.23-0.66-0.34-0.38 0.31 0.12 0.27-0.02 0.47-0.2 0.72-0.89 1.46-1.71 2.97-2.52 4.48-1.12 2.1-2.3 4.15-1.26 6.72 0.28 0.67 0.38 1.48 0.52 2.24 0.57 2.94 1.18 5.87 1.92 8.76 0.81 3.22 1.41 6.48 1.43 9.83 0.02 3.38 0.52 3.76 3.98 3.62h0.33l0.06-0.02 0.02-0.01zm81.76-66.7c-0.35 0.02-0.49 0.25-0.65 0.43-2.64 3.47-6.15 5.65-10.19 7.11-1.62 0.59-3.28 1.02-4.91 1.6-0.46 0.18-0.94 0.57-0.83 0.78 0.81 1.53 0.33 3.1 0.3 4.65-0.05 2.53-0.63 4.87-2.06 6.99-0.36 0.53-0.43 1.05 0.05 1.68 1.14 1.52 2.61 2.61 4.22 3.5 3.57 1.98 7.44 2.18 11.4 1.51 1.95-0.32 3.83-0.91 5.44-2.05 1.67-1.17 3.37-2.34 5.02-3.55 2.75-1.98 4.08-4.82 5.57-7.8-2.08 0.47-3.51-0.45-5.03-1.41-3.25-2.07-5.41-4.91-6.65-8.49-0.57-1.65-1.14-3.32-1.7-4.96l0.02 0.01zm-92.28 34.48c1.85-5.12 5.05-9.08 8.48-12.83 1.97-2.15 3.64-4.61 6.1-6.32 0.34-0.24 0.15-0.55 0.07-0.88-0.87-3.06-1.7-6.13-2.56-9.19-0.31-1.1-1.05-1.15-2.03-0.88-3.09 0.88-6.1 2.02-9.06 3.24-2.39 0.99-5.04 1.17-7.37 2.38-0.64 0.33-0.78 0.62-0.62 1.2 0.34 1.19 0.72 2.38 1.03 3.58 0.6 2.24 1.18 4.48 1.69 6.73 0.68 2.91 1.56 5.79 2.46 8.65 0.45 1.44 0.93 2.92 1.78 4.32h0.04-0.01zm143.39 162.54c-0.78-0.46-1.27-0.99-1.85-0.13-0.07 0.1-0.36 0.15-0.45 0.09-0.83-0.68-1.71-0.21-2.57-0.18-4.08 0.19-8.14-0.07-12.11-0.84-1.63-0.33-1.77 0.83-1.83 1.44-0.32 2.78-1.47 5.34-1.87 8.08-0.23 1.55-0.85 3.03-1.26 4.54-0.11 0.37-0.56 0.79-0.09 1.11 0.47 0.31 1.05 0.53 1.66 0.27 0.69-0.29 1.28-0.12 1.9 0.24 0.96 0.56 2 0.93 3.11 1.24 1.19 0.33 2.39 0.27 3.59 0.47 2.73 0.43 5.48 0.85 8.31 0.4-3.09-1.95-4.49-4.79-4.18-8.2 0.4-4.43 3.13-7.17 7.62-8.54l0.02 0.01zm-74.86-170.4c0.98 2.1 2.54 3.55 4.18 4.9 0.98 0.83 1.88 1.8 3.12 2.26 3.32 1.25 6.83 1.79 10.3 2.41 0.95 0.17 1.97 0.13 2.92 0 1.47-0.23 2.92-0.61 4.29-1.21 2.01-0.88 4.18-1.38 5.97-2.68 2.02-1.49 4.1-2.88 6.07-4.39 1.03-0.81 2.08-1.72 2.86-2.72 1.88-2.41 3.45-5.05 5.13-7.6 0.25-0.38 0.3-0.94-0.33-0.81-0.93 0.21-1.81 0.05-2.68-0.12-1.41-0.29-1.81 0.48-2.05 1.6-0.66 3.02-2.52 5.33-4.77 7.25-2.55 2.2-5.8 3.34-8.84 4.61-3.3 1.38-6.82 2.18-10.54 1.73-2.26-0.28-4.51-0.4-6.58-1.53-1.75-0.97-3.58-1.85-5.03-3.24-0.57-0.55-1-1.29-1.61-2.1-0.22 1.57-1.36 1.44-2.39 1.65l-0.02-0.02v0.01zm4.25 134.11c0.06-2.34 0.2-4.48 0.46-6.59 0.36-2.95 0.61-5.91 1.02-8.84 0.12-0.82 0-1.14-0.79-1.32-3.22-0.81-6.46-1.64-9.65-2.54-1.8-0.49-3.58-0.81-5.45-0.69-0.5 0.04-1.07-0.05-1.33 0.47-0.26 0.55 0.17 1.14 0.47 1.44 1.74 1.65 3.16 3.6 4.71 5.41 3.53 4.07 6.93 8.28 10.54 12.65h0.02v0.01zm116.47 33.54c1.8 1.98 2.78 4.36 3.31 6.94 0.7 3.38-0.15 6.62-0.96 9.84-0.31 1.2-1.02 2.22-1.73 3.21-0.15 0.23-0.43 0.57-0.22 0.9 0.24 0.38 0.57 0.11 0.88 0.02 4.38-1.09 7.01-4.1 8.31-8.18 0.55-1.74 0.55-3.91-0.56-5.49-2.26-3.28-4.91-6.24-9.07-7.25l0.04 0.02v-0.01zM50.68 287.92c-1.14-3.44-2.24-6.94-1.3-10.54 0.94-3.53 2.73-6.64 6-8.61-0.9-0.51-1.99-0.6-3.06-0.79-0.12-0.02-0.31-0.1-0.38 0.12-0.16 0.43-0.92 1.17-1.26 1.24-1.73 0.4-2.82 1.74-3.56 3.08-1.31 2.41-2.05 5.04-1.78 7.91 0.27 2.94 2.21 6.54 5.34 7.57v0.02zm57.35-2.53c-1.16-0.54-2.28-0.55-3.13-1.31-0.64-0.55-1.5-0.76-2.45-0.5-0.47 0.12-1.04-0.15-1.56-0.31-0.65-0.19-1.28-0.51-1.94-0.67-0.62-0.16-1.17-0.14-1.57-0.88-0.4-0.7-1.27-0.14-1.92-0.09-0.55 0.05-0.2 0.64-0.18 0.92 0.07 1.46-0.31 2.79-0.87 4.13-0.36 0.9-1.28 1.45-1.43 2.45 4.96-1.34 9.98-2.12 15.04-3.77v0.03h0.01zm-41.84-82.85c-1.97 3.27-4.18 6.27-7.58 8.21 1.25 0.77 2.42 1.1 3.58 1.48 0.96 0.33 1.98 0.65 2.69 1.42 0.78 0.82 1.16 0.99 1.54-0.3 0.21-0.72 0.97-1.25 0.88-2.16-0.19-1.95-0.24-3.91-0.49-5.84-0.11-0.9 0.07-1.88-0.6-2.81h-0.02zm-42.63-53.12c3.89 0 7.15-1.96 10.54-3.51 0.39-0.19 0.81-0.55 0.6-1.19-0.19-0.57-0.27-1.14-0.05-1.77 0.09-0.26 0.11-1.17-0.74-0.71-1.94 1.06-3.92 2.03-5.75 3.24-2.32 1.51-4.79 2.31-7.53 2.02-0.63-0.07-1.12-0.12-1.14 0.6 0 0.64 0.08 1.28 1.07 1.24 1-0.03 1.99 0.17 3 0.07v0.02-0.01zm128.77-51.99c3.63 2.63 6.29 6.18 9.07 9.6-1.9-4.7-4.51-8.23-9.07-9.6zm-43.7 157.47c-0.27-0.1-0.2 0.11-0.2 0.25 0 0.18 0 0.53 0.26 0.39 0.49-0.22 0.76 0.12 1.09 0.26 1.41 0.63 2.82 1.28 4.23 1.9 0.27 0.12 0.74 0.46 0.85 0.2 0.38-1.03 1.45-1.08 2.14-1.69 0.43-0.37 0.07-0.26-0.07-0.49-0.57-1.06-1.1 0.05-1.66-0.04-2.19-0.36-4.45-0.2-6.63-0.79v0.02l-0.01-0.01zM38.54 124.99c0-0.67 0-1.1-0.31-1.22-0.35-0.12-0.49 0.31-0.7 0.55-0.33 0.38-0.48 0.83-0.65 1.28-0.09 0.22 0.04 0.5 0.24 0.4 0.58-0.33 1.32-0.5 1.42-1v-0.01zm69.87-60.15c1.18-0.45 0.07-1.59 0.85-2.05-0.05-0.07-0.09-0.16-0.16-0.18-0.21-0.07-0.27 0.09-0.38 0.23-0.38 0.58-0.36 1.22-0.31 2.01v-0.01z" android:fillColor="#17161B"/> - <path android:pathData="M158.71 165.14c-1.04 0.62 0.03 1.1 0.26 1.69 0.62 1.62 0.9 3.29 0.88 5.03 0 0.63-0.31 1.1-0.85 1.13-0.45 0.04-0.83-0.34-0.9-0.93-0.05-0.58-0.12-1.01-1.02-0.72-0.76 0.25-1.43-0.48-1.86-1.13-0.85-1.28-1.16-2.76-1.52-4.19-0.81-3.35-1.48-6.74-2.56-10.03-0.96-3.03-1.81-6.09-2.71-9.16-0.56-1.96-1.14-3.92-1.72-5.89-0.29-0.96-0.04-1.7 0.81-2.24 0.96-0.58 1.76-0.62 2.48 0.48 1.42 2.16 2.08 4.61 2.82 7.01 1.36 4.37 2.62 8.78 4.13 13.11 0.57 1.65 1.09 3.32 1.61 4.99 0.07 0.22 0.09 0.48 0.13 0.84l0.02 0.02v-0.01zm-15.29 43.94c-0.31 3.46-0.88 7.33-3.89 10.3-2.37 2.34-4.69 2.79-7.8 1.03-1.49-0.84-2.33-2.41-2.6-4.04-0.48-3.11-0.7-6.24 0.18-9.32 0.47-1.6 1.05-3.17 1.92-4.61 0.47-0.77 1.07-1.46 2.21-1.19 0.36 0.09 0.95 0.02 1.16-0.21 1-1.12 2.09-0.82 3.3-0.49 1.23 0.34 2.16 1.08 3 1.94 1.64 1.69 2.31 3.41 2.51 6.59h0.02-0.01zm-10.95 4.32c-0.02 1.04-0.07 2.07 0.34 3.1 0.69 1.71 2.63 2.18 3.78 0.69 2.09-2.68 3.51-5.66 3.13-9.21-0.16-1.5-0.65-2.86-1.88-3.84-0.45-0.36-1.16-0.85-1.47-0.4-0.43 0.62-1.11 0.93-1.52 1.55-1.7 2.45-2.28 5.2-2.37 8.11h-0.02 0.01zM80.41 62.46c-0.26 0.2-0.5-0.38-0.76 0 1.12 0.87 1.09 1.79-0.28 3.17-0.65 0.67-1.31 1.27-2.33 1.61-2.69 0.93-5.44-0.82-5.14-3.63 0.26-2.35 0.55-4.68 0.56-7.05 0-0.57 0.63-1.24 1.46-1.18 0.77 0.07 1.63-0.2 1.76 1.19 0.2 2.05-0.29 4.05-0.09 6.07 0.02 0.2-0.53 0.53 0.12 0.72 0.4 0.12 0.8 0.22 0.98-0.11 0.35-0.6 0.94-0.87 1.47-1.24 0.96-0.63 1.46-0.53 2.22 0.45h0.03zm0.88 9.1c2.21 0.11 3.23-0.99 2.92-2.92-0.07-0.45-0.05-0.88 0-1.29 0.05-0.63 0.21-1.41 0.92-1.55 0.78-0.16 1.62-0.17 2.25 0.65 1.02 1.36 1.14 2.86 0.76 4.41-0.21 0.84-0.38 1.73-1.11 2.39-0.33 0.29-0.47 0.78-1.02 0.74-0.31-0.02-0.4 0.16-0.47 0.45-0.49 1.78-2.07 1.86-3.47 2.07-1.14 0.17-2.17-0.34-2.9-1.21-0.66-0.77-0.63-1.77-0.25-2.67 0.5-1.19 1.57-1.24 2.39-1.05l-0.02-0.02zm0.29-19.21c-1.2-0.09-2.57-0.59-3.69-1.6-0.42-0.38-0.85-0.92 0.14-1.24 0.19-0.07 0.31-0.31-0.07-0.36-0.97-0.18-0.12-0.59-0.04-0.64 0.9-0.41 1.75-1.12 2.85-0.7 0.7 0.25 1.39 0.17 2.08 0.14 0.83-0.05 1.48-0.38 1.76-1.28 0.21-0.67 0.61-1.15 1.38-0.59 0.23 0.16 0.43 0.07 0.56-0.05 0.98-0.84 1.34 0.61 2.1 0.55-0.08 0.57 0.3 1.07-0.04 1.73-1.26 2.36-3.53 4.02-7.02 4.06v-0.02h-0.01zM12.95 90.8c0 1.6-1.38 3.27-2.69 3.25-1.25-0.04-3.08-1.58-2.93-2.6 0.28-2.03 1.04-3.42 2.77-3.44 1.5-0.02 2.85 1.32 2.87 2.8l-0.02-0.01zm-2.9-0.88c-0.34 0.22-0.55 0.56-0.59 1.03-0.03 0.48 0.05 0.98 0.59 1.03 0.42 0.05 0.8-0.34 0.78-0.77 0-0.5-0.07-1.06-0.78-1.3v0.01zm3.06-2.22c0.29 0.25 0.96 0.03 0.91 0.63-0.03 0.31-0.2 0.78-0.71 0.64-0.33-0.09-0.79-0.18-0.74-0.64 0.04-0.24 0.07-0.7 0.56-0.62l-0.02-0.01z" android:fillColor="#17161B"/> - <path android:strokeWidth="1" android:pathData="M233.28 227.49c-0.3-1.39-0.89-2.68-1.47-3.93-0.38-0.81-0.76-1.65-1.06-2.5-1.41-4.05-4.21-7.34-8.56-10.05-1.8-1.12-3.86-1.68-5.84-2.21-1.34-0.36-2.71-0.74-4-1.29-0.39-0.16-0.79-0.18-1.17-0.21-0.24-0.02-0.47-0.03-0.69-0.08-1.07-0.25-2.15-0.27-3.21-0.3-0.65-0.01-1.34-0.03-1.99-0.1-0.24-0.03-0.49-0.04-0.76-0.04-0.96 0-1.94 0.18-2.88 0.35l-0.22 0.04c-0.99 0.18-1.99 0.4-2.96 0.61-1.07 0.24-2.18 0.49-3.27 0.68l-1.56 0.24c-1.81 0.28-3.69 0.58-5.51 1.2-1.03 0.36-2.05 0.75-3.14 1.16-0.5 0.2-1.02 0.4-1.57 0.6 0.05-0.15 0.07-0.28 0.1-0.41 0.02-0.1 0.04-0.19 0.07-0.29 0.37-1.46 0.92-2.9 1.45-4.3 0.23-0.6 0.46-1.2 0.68-1.8 0.35-0.99 0.68-2 0.99-2.99 0.53-1.62 1.07-3.31 1.74-4.9 2.19-5.35 2.66-9.62 1.53-13.84l-0.23-0.82c-0.54-1.99-1.1-4.05-1.55-6.1-0.85-3.84-2.16-7.78-3.99-12.04-1.33-3.07-2.36-5.87-3.17-8.54-0.32-1.05-0.64-2.09-0.95-3.13-1.13-3.7-2.29-7.52-3.54-11.24-0.88-2.59-1.78-5.13-2.61-7.49v-0.02l-0.03-0.06c-0.07-0.23-0.08-0.28-0.06-0.32 0.02 0 0.07 0.01 0.12 0.05 0.01 0 0.02 0.01 0.03 0.02 0.78 0.53 1.69 0.79 2.76 0.79 0.71 0 1.42-0.11 1.95-0.21 3.15-0.58 6.86-1.36 10.5-2.74 1.03-0.38 1.98-0.96 2.66-1.62 2.23-2.19 3.84-4.85 4.8-7.91 0.84-2.69 1.79-5.53 3.19-8.15 1.57-2.94 2.72-6.02 3.42-9.16 0.13-0.58 0.22-1.17 0.32-1.73 0.17-1.06 0.35-2.14 0.72-3.12 1.04-2.68 0.98-5.39 0.94-8.02-0.03-1.37-0.24-2.73-0.46-4.04-0.14-0.9-0.29-1.84-0.38-2.76-0.23-2.44-1.05-4.66-2.41-6.44-0.61-0.76-1.01-1.66-1.32-2.91-0.62-2.45-1.51-4.72-2.75-6.92-1.29-2.31-3.07-4.07-5.1-5.99-2.61-2.47-5.83-5.24-9.87-7.13-0.93-0.43-1.86-0.85-2.8-1.26-1.49-0.66-3.04-1.35-4.52-2.09-1.05-0.53-2.07-1.15-3.06-1.74-0.68-0.41-1.35-0.81-2.04-1.2-2.75-1.54-5.43-3.23-7.72-4.69-0.43-0.27-0.76-0.39-1.07-0.39-0.38 0-0.73 0.18-1.04 0.56-0.08 0.1-0.12 0.11-0.12 0.11-0.05 0-0.17-0.09-0.25-0.14l-0.12-0.09c-2.9-1.94-5.21-4.71-7.3-8.7-0.57-1.09-1.13-2.19-1.69-3.29-1.28-2.51-2.59-5.11-4.07-7.58-0.2-0.34-0.4-0.68-0.59-1.01-1.46-2.51-2.98-5.11-5.84-6.58-1.05-0.55-2.11-1.11-3.16-1.66-1.28-0.67-2.55-1.34-3.83-1.99-0.76-0.39-1.49-0.86-2.2-1.32-1.23-0.79-2.51-1.61-3.99-2.06-0.71-0.23-1.39-0.5-2.1-0.79l-0.97-0.38c-3.16-1.22-5.8-1.79-8.31-1.79-1.79 0-3.47 0.29-5.15 0.88-1.06 0.37-2.13 0.56-3.16 0.56-0.86 0-1.67-0.13-2.41-0.39-2.49-0.88-5.39-1.85-8.43-2.31-0.95-0.12-1.85-0.28-2.46-0.84-3.08-2.85-6.98-3.4-10.75-3.93l-0.47-0.06c-0.12-0.02-0.25-0.05-0.4-0.08C82.63 1.07 82.28 1 81.92 1c-0.81 0-1.38 0.37-1.68 1.11h-0.03c-0.27-0.06-0.53-0.1-0.8-0.1-1.34 0-2.41 0.76-3.35 1.44L75.99 3.5c-2.06 1.47-3.8 3.17-5.17 5.07-0.24 0.34-0.65 0.54-1.12 0.57h-0.13c-0.43 0-0.85-0.08-1.3-0.16-0.46-0.09-0.93-0.17-1.41-0.17-0.55 0-1.03 0.12-1.49 0.37-0.03-0.02-0.07-0.04-0.1-0.06-0.04-0.42-0.28-0.64-0.71-0.64l-0.45-0.02c-0.34-0.01-0.67-0.03-0.99-0.03-0.99 0-2.12 0.15-3.01 1.3-0.09 0.13-0.21 0.2-0.31 0.2-0.06 0-0.12-0.03-0.19-0.08-0.42-0.35-0.93-0.51-1.54-0.51-0.31 0-0.62 0.04-0.85 0.08-0.58 0.1-1.2 0.18-2 0.23-2.38 0.21-4.43 1.35-6.31 2.57-2.59 1.71-3.97 4.34-4.98 6.68-0.2 0.43-0.37 0.89-0.55 1.34-0.18 0.49-0.38 1-0.6 1.48-1.18 2.46-2.64 5.51-2.67 8.87 0 0.15-0.03 0.31-0.05 0.49-0.07 0.51-0.15 1.14 0.21 1.6 0.13 0.16 0.3 0.28 0.51 0.36-0.01 0.02-0.03 0.05-0.04 0.07-0.07 0.13-0.07 0.28-0.02 0.45 0.72 2.33 1.52 4.54 3.28 5.97 2.55 2.08 5.64 4.4 9.33 5.94-0.52 0.79-0.64 1.55-0.38 2.36 0.13 0.41 0.17 0.89 0.13 1.31C52.97 50.23 53.26 51 54 51.6c0.03 0.05 0.08 0.23 0.1 0.33v0.01c-0.61 0.3-0.48 0.82-0.4 1.14 0.03 0.14 0.07 0.27 0.07 0.4-0.02 1.25 0.34 2.42 0.69 3.54 0.16 0.54 0.33 1.09 0.45 1.63 0.34 1.49 0.99 2.93 1.62 4.31 0.18 0.41 0.37 0.81 0.54 1.22 1.77 4.01 3.56 7.24 5.63 10.14 1.75 2.45 3.75 4.93 6.52 6.57 2.25 1.34 5.04 3 8.18 3.91 0.53 0.16 1.05 0.33 1.57 0.51 1.35 0.46 2.76 0.93 4.28 0.93 0.15 0 0.3 0 0.46-0.01 0 0 0.06 0 0.06-0.01 0.03 0 0.05 0.01 0.05 0.01 0.01 0.01 0.03 0.07 0.02 0.2-0.03 0.35-0.03 0.7-0.03 1.05-0.01 0.52-0.02 1.01-0.07 1.51-0.3 2.49-0.96 4.46-2.01 6.05-0.34 0.51-0.39 1.05-0.44 1.53-0.03 0.3-0.06 0.58-0.14 0.83-0.28-0.31-0.66-0.45-1.14-0.45-0.22 0-0.44 0.02-0.64 0.05-2.19 0.36-4.37 0.92-6.47 1.46-0.59 0.16-1.19 0.31-1.78 0.46l-0.39 0.1c-2.62 0.67-5.33 1.36-7.96 2.2l-0.71 0.22c-2.36 0.74-4.8 1.5-6.7 3.38-0.98 0.97-1.76 2.11-2.51 3.21-0.32 0.48-0.65 0.97-1 1.43-2.13 2.92-4.11 6-6.04 8.99l-0.17 0.28c-0.81 1.26-1.52 2.6-2.21 3.9-0.22 0.42-0.44 0.83-0.66 1.24-1.84 3.4-3.24 7.04-4.59 10.56-0.41 1.07-0.82 2.14-1.24 3.2-0.16 0.39-0.34 0.79-0.52 1.18-0.32 0.73-0.66 1.47-0.88 2.26-0.18-0.11-0.21-0.14-0.19-0.27 0.13-0.92 0.13-1.86 0.13-2.67l-0.03-1.09c-0.04-1.51-0.08-3.07-0.27-4.61-0.14-1.09 0.3-1.8 1.31-2.13 0.22-0.06 0.44-0.15 0.66-0.24 0.26-0.11 0.51-0.21 0.79-0.28 3.07-0.88 4-3.67 3.57-5.89-0.46-2.45-1.22-4.92-2.21-7.13-1.41-3.15-2.93-6.91-3.56-10.95-0.18-1.18-0.61-2.36-1.21-3.32-0.16-0.27-0.36-0.5-0.55-0.73-0.33-0.38-0.65-0.76-0.76-1.27-0.05-0.27-0.13-0.53-0.2-0.79-0.28-1.04-0.53-1.94 0.38-2.84 0.64-0.65 1.04-1.48 1.42-2.28l0.2-0.42c0.76-1.52 0.48-3.14-0.72-4.22-0.52-0.46-1.11-0.69-1.83-0.69-0.65 0-1.31 0.2-1.92 0.38-0.17 0.05-0.3 0.07-0.39 0.07-0.12 0-0.13 0-0.26-0.47-0.21-0.81-0.41-1.63-0.61-2.44-0.52-2.12-1.06-4.32-1.86-6.41-0.64-1.72-1.44-3.42-3.6-3.66l-0.35-0.03c-0.03-0.07-0.09-0.14-0.16-0.17-0.04-0.02-0.09-0.03-0.13-0.03-0.04 0-0.08 0-0.12 0.02l-0.44 0.17c-1.17 0.02-2.32 0.25-3.44 0.46l-0.48 0.1c-1.93 0.38-3.68 1.26-5.37 2.1-0.63 0.31-1.24 0.62-1.87 0.91-1.71 0.76-3.63 1.31-5.86 1.68-1.47 0.23-2.86 1.2-3.75 2.57l-0.65 0.25c-0.15 0.05-0.23 0.21-0.19 0.36l0.19 0.78c-0.12 0.39-0.18 0.77-0.2 1.13-0.02 0.21-0.01 0.42 0 0.58 0.02 0.27 0.07 0.51 0.13 0.76l1.05 3.75c0.34 1.25 0.7 2.51 1.04 3.77 0.29 1.07 0.57 2.15 0.84 3.23 0.58 2.27 1.17 4.61 1.93 6.86 0.22 0.67 0.38 1.38 0.53 2.07 0.19 0.84 0.39 1.7 0.7 2.49l0.19 0.81c0.04 0.12 0.12 0.21 0.24 0.23 0.01 0.01 0.03 0.01 0.04 0.01 0.15 0.28 0.32 0.53 0.5 0.78 0.68 0.92 1.06 2.13 1.37 3.3l0.52 1.94c1.13 4.19 2.29 8.52 3.21 12.84 0.73 3.36 1.27 6.85 1.6 10.34 0.12 1.27 0.11 2.57 0.09 3.82 0 0.89-0.02 1.8 0.02 2.71 0.04 1.15 0.02 2.34 0.01 3.5-0.03 1.45-0.04 2.94 0.05 4.4 0.25 3.75 0.81 7.54 1.36 11.2l0.16 1.13c0.58 3.9 1.24 7.35 2.03 10.53 1.13 4.51 2.53 8.96 4.17 13.21l0.34 0.89c0.93 2.44 1.89 4.97 3.25 7.31l0.38 0.67c1.12 1.95 2.28 3.98 3.85 5.69l0.04 0.05c0.15 0.16 0.34 0.35 0.39 0.45-0.05 0.04-0.21 0.12-0.6 0.23-2.18 0.59-4.43 1.19-6.66 2.11-3.78 1.55-6.59 3.54-8.84 6.27-0.48 0.57-0.86 1.21-1.24 1.81-0.44 0.72-0.86 1.4-1.41 2-2.21 2.38-3.62 5.34-4.31 9.08-0.51 2.62-0.59 5.39-0.25 8.49 0.27 2.42 0.91 4.72 1.94 7.03 1.62 3.64 4.24 6.77 6.56 9.41 1.39 1.56 3.29 2.69 5.82 3.47 1.85 0.57 4.19 1.5 5.8 3.68 0.38 0.49 0.89 0.86 1.61 1.17 6.64 2.75 11.93 4.67 17.04 6.15-0.06 0.11-0.09 0.23-0.12 0.33-0.09-0.03-0.18-0.03-0.27-0.03-0.6 0-0.88 0.47-1.09 0.82-0.06 0.11-0.13 0.22-0.21 0.31-1.44 1.83-2.52 3.88-3.3 5.45-0.77 1.58-1.48 3.3-1.44 5.16 0.08 3.81 1.41 7.26 3.94 10.28 4.02 4.78 9.64 5.53 14.6 5.86 0.96 0.06 1.93 0.07 2.88 0.07 0.74 0 1.48 0 2.23 0.04 1.57 0.06 3.19 0.1 4.95 0.1 3.77 0 7.59-0.16 10.88-0.31 2.94-0.14 5.31-0.36 7.47-0.66 2-0.27 3.99-0.73 5.92-1.18 1.31-0.31 2.66-0.62 4-0.87 4.99-0.96 10.28-2.1 15.23-4.52 0.37-0.18 0.7-0.27 1.02-0.27 0.21 0 0.41 0.04 0.61 0.11 4.65 1.76 9.3 3.43 13.66 4.99 0.73 0.27 1.33 0.4 1.9 0.4 0.51 0 0.98-0.1 1.44-0.3 0.84-0.38 0.93-1.08 1-1.65 0.02-0.2 0.05-0.38 0.1-0.54 0.12-0.41 0.19-0.41 0.23-0.41 0.05 0 0.14 0.01 0.32 0.11 1.84 0.98 3.84 1.45 5.78 1.89 0.42 0.1 0.83 0.19 1.24 0.29 2.73 0.66 5.43 1 8.02 1.02 2.54 0.03 5.08 0.51 7.55 0.97 1.89 0.36 3.86 0.73 5.83 0.89 1.9 0.16 3.82 0.46 5.68 0.74 1.6 0.25 3.25 0.51 4.89 0.68 1.79 0.17 3.75 0.26 5.99 0.26 2.06 0 4.14-0.08 6.17-0.14l1.18-0.04c2.57-0.08 5.13-0.46 7.62-0.84 2.58-0.38 5.25-0.79 7.9-0.83 0.85-0.01 1.71-0.24 2.54-0.46 0.32-0.09 0.64-0.17 0.97-0.25 1.37-0.34 2.41-0.73 3.28-1.25 2.57-1.54 4.7-3.87 6.52-7.11 0.1-0.18 0.25-0.36 0.41-0.56 0.5-0.6 1.23-1.49 0.54-2.59 0.17-0.03 0.3-0.1 0.4-0.21 0.19-0.23 0.15-0.53 0.12-0.76-0.02-0.25-0.05-0.51-0.07-0.77-0.11-1.29-0.22-2.61-0.82-3.79-1.57-3.08-3.72-5.82-6.38-8.14-0.12-0.1-0.18-0.17-0.21-0.21 0.04-0.02 0.09-0.05 0.19-0.09 0.82-0.34 1.52-0.85 2.21-1.34 0.15-0.11 0.31-0.22 0.47-0.33 0.18-0.14 0.38-0.25 0.59-0.37 0.58-0.33 1.24-0.71 1.44-1.46 0.62-2.33 2.48-3.22 4.41-3.83 1.45-0.46 2.96-1 4.06-2.13l0.55-0.56c2.22-2.25 4.51-4.57 6.31-7.3 2.76-4.18 4.68-8.73 5.7-13.53 0.31-1.49 0.47-3.05 0.47-4.66 0-1.99-0.24-4.03-0.72-6.23zm-0.06 10.82c-1.02 4.82-2.92 9.3-5.65 13.43-1.93 2.93-4.4 5.36-6.82 7.81-1.05 1.08-2.48 1.59-3.94 2.05-2.11 0.67-3.97 1.64-4.61 4.05-0.23 0.86-1.22 1.15-1.91 1.65-0.84 0.59-1.65 1.24-2.61 1.64-0.52 0.21-0.58 0.38-0.07 0.82 2.61 2.28 4.73 4.97 6.3 8.05 0.69 1.36 0.71 2.94 0.87 4.46 0.03 0.25 0.1 0.62-0.37 0.63-0.17 0-0.39 0.07-0.26 0.26 1.06 1.35-0.36 2.22-0.81 3.03-1.57 2.8-3.61 5.32-6.41 7.01-0.95 0.56-2.04 0.93-3.19 1.2-1.13 0.26-2.3 0.69-3.44 0.71-5.23 0.09-10.3 1.52-15.53 1.67-4.44 0.14-8.88 0.35-13.3-0.08-3.54-0.37-7.03-1.12-10.57-1.42-4.51-0.38-8.88-1.81-13.41-1.86-2.71-0.02-5.37-0.39-7.94-1.01-2.33-0.57-4.77-0.99-6.95-2.16-0.67-0.36-0.86 0-1 0.49-0.21 0.72 0 1.58-0.93 1.99-1.07 0.47-2.11 0.26-3.11-0.1-4.56-1.64-9.12-3.29-13.65-4.99-0.71-0.28-1.36-0.09-1.88 0.17-4.8 2.36-9.95 3.49-15.15 4.49-3.31 0.62-6.56 1.59-9.9 2.05-2.46 0.35-4.94 0.53-7.44 0.66-5.27 0.24-10.54 0.43-15.81 0.2-1.69-0.06-3.4 0-5.09-0.1-5.41-0.36-10.62-1.28-14.39-5.75-2.46-2.93-3.78-6.28-3.87-10.09-0.03-1.79 0.64-3.43 1.41-5.01 0.94-1.89 1.96-3.74 3.27-5.39 0.38-0.48 0.53-1.34 1.54-0.91 0.13 0.05-0.05-0.76 0.59-0.85-6.1-1.73-11.89-3.94-17.61-6.32-0.58-0.24-1.1-0.56-1.48-1.06-1.51-2.04-3.61-3.07-5.96-3.79-2.14-0.66-4.14-1.65-5.67-3.38-2.52-2.85-4.95-5.82-6.51-9.33-0.98-2.2-1.64-4.47-1.92-6.93-0.31-2.86-0.29-5.62 0.24-8.41 0.63-3.34 1.89-6.39 4.24-8.92 1.07-1.15 1.66-2.62 2.66-3.82 2.36-2.86 5.28-4.77 8.72-6.18 2.18-0.9 4.39-1.5 6.62-2.1 1.21-0.33 0.94-0.57 0.32-1.24-1.72-1.88-2.93-4.12-4.19-6.3-1.51-2.6-2.51-5.39-3.56-8.16-1.66-4.3-3.04-8.7-4.17-13.18-0.86-3.46-1.5-6.97-2.01-10.5-0.61-4.1-1.25-8.19-1.52-12.31-0.18-2.6 0.03-5.27-0.07-7.89-0.09-2.18 0.1-4.35-0.11-6.54-0.33-3.49-0.86-6.97-1.61-10.38-1.05-4.98-2.41-9.88-3.73-14.79-0.31-1.19-0.7-2.44-1.41-3.41-0.25-0.33-0.46-0.67-0.63-1.02l-0.1 0.12-0.2-0.81c-0.57-1.48-0.73-3.09-1.23-4.59-1.11-3.29-1.85-6.7-2.76-10.07-0.69-2.52-1.4-5.01-2.1-7.53-0.06-0.23-0.1-0.46-0.11-0.69-0.02-0.18-0.02-0.36 0-0.53 0.01-0.39 0.08-0.77 0.21-1.15l-0.21-0.86 0.74-0.28c0.79-1.29 2.13-2.29 3.59-2.53 2.02-0.33 4.03-0.85 5.94-1.7 2.35-1.08 4.6-2.48 7.17-2.99 1.29-0.25 2.6-0.54 3.92-0.56l0.5-0.18 0.05 0.19c0.19 0 0.37 0.02 0.56 0.04 2 0.22 2.72 1.79 3.35 3.46 1.09 2.86 1.67 5.86 2.45 8.81 0.16 0.61 0.23 0.85 1.04 0.63 1.11-0.33 2.38-0.73 3.45 0.24 1.11 1 1.35 2.46 0.66 3.85-0.45 0.92-0.85 1.9-1.57 2.62-1.28 1.27-0.54 2.57-0.26 3.91 0.19 0.91 0.91 1.39 1.35 2.1 0.58 0.95 0.99 2.1 1.17 3.2 0.6 3.87 1.99 7.47 3.57 11.04 1.01 2.23 1.75 4.65 2.2 7.06 0.4 2.05-0.45 4.7-3.35 5.53-0.52 0.13-0.97 0.37-1.47 0.53-1.67 0.53-1.74 0.67-1.52 2.46 0.24 1.88 0.24 3.77 0.3 5.67 0.01 0.87 0 1.75-0.13 2.61-0.09 0.62 0.64 0.54 0.66 1 0.27-1.45 1.02-2.7 1.53-4.01 1.83-4.61 3.44-9.33 5.81-13.72 0.93-1.73 1.81-3.48 2.86-5.13 2.01-3.12 4.02-6.25 6.21-9.25 1.14-1.55 2.09-3.24 3.47-4.6 2.04-2.01 4.68-2.7 7.29-3.53 2.75-0.88 5.54-1.58 8.33-2.29 2.73-0.68 5.44-1.46 8.22-1.91 0.69-0.1 1.35-0.16 1.76 0.69 0.64-0.85 0.21-1.89 0.81-2.79 1.21-1.82 1.8-4 2.06-6.18 0.1-0.86 0.05-1.72 0.1-2.58 0.04-0.38-0.1-0.57-0.46-0.53-2.23 0.13-4.15-0.83-6.21-1.42-2.97-0.86-5.54-2.36-8.1-3.87-2.66-1.59-4.61-3.96-6.42-6.49-2.27-3.17-4.05-6.56-5.6-10.09-0.78-1.8-1.71-3.58-2.14-5.46-0.38-1.69-1.16-3.31-1.14-5.11 0-0.59-0.5-1.09 0.4-1.35-0.09-0.25-0.11-0.63-0.28-0.77-0.73-0.59-0.9-1.31-0.81-2.19 0.05-0.46 0-0.98-0.14-1.43-0.29-0.91-0.02-1.67 0.57-2.41-3.61-1.44-6.71-3.66-9.62-6.04-1.75-1.42-2.51-3.65-3.18-5.82-0.15-0.48 0.54-0.19 0.41-0.6-1.61-0.14-1.01-1.5-1.01-2.28 0.03-3.15 1.3-5.95 2.64-8.74 0.43-0.92 0.74-1.9 1.16-2.83 1.1-2.56 2.46-4.96 4.87-6.54 1.88-1.22 3.87-2.32 6.16-2.52 0.69-0.04 1.35-0.11 2.02-0.24 0.73-0.12 1.49-0.17 2.15 0.37 0.31 0.25 0.67 0.19 0.94-0.17 1.11-1.45 2.66-1.19 4.18-1.13 0.32 0 0.42 0.12 0.42 0.45 0 0.09 0.4 0.31 0.47 0.26 1.41-0.86 2.85 0 4.28-0.05 0.6-0.03 1.09-0.31 1.36-0.71 1.42-1.96 3.17-3.61 5.1-4.99 1.09-0.78 2.37-1.72 3.97-1.34 0.11 0.02 0.31 0.05 0.31 0.03 0.5-1.63 1.99-1.05 2.86-0.93 3.92 0.55 7.92 1.02 11.05 3.91 0.71 0.65 1.72 0.81 2.63 0.93 2.89 0.43 5.63 1.32 8.37 2.29 1.83 0.64 3.91 0.48 5.78-0.17 4.57-1.61 8.92-0.76 13.24 0.91 1.04 0.4 2.04 0.85 3.1 1.17 2.28 0.71 4.05 2.29 6.12 3.36 2.33 1.18 4.65 2.44 7 3.65 3.15 1.62 4.61 4.63 6.31 7.47 2.1 3.53 3.85 7.23 5.75 10.86 1.8 3.45 4.08 6.58 7.39 8.82 0.35 0.22 0.57 0.47 0.92 0.06 0.51-0.63 1.02-0.54 1.69-0.11 2.54 1.62 5.1 3.22 7.74 4.7 1.72 0.97 3.35 2.05 5.11 2.95 2.4 1.2 4.89 2.22 7.33 3.35 3.76 1.76 6.84 4.29 9.79 7.08 1.9 1.79 3.75 3.6 5.04 5.91 1.22 2.16 2.11 4.42 2.72 6.85 0.25 1.03 0.63 2.08 1.38 3.03 1.38 1.8 2.14 4.03 2.35 6.27 0.2 2.27 0.79 4.49 0.83 6.78 0.05 2.67 0.08 5.3-0.92 7.9-0.58 1.53-0.69 3.26-1.05 4.89-0.71 3.19-1.85 6.2-3.39 9.08-1.4 2.61-2.33 5.4-3.21 8.21-0.93 2.96-2.51 5.59-4.73 7.78-0.69 0.67-1.63 1.21-2.55 1.55-3.38 1.28-6.9 2.07-10.44 2.72-1.47 0.27-3.08 0.43-4.48-0.53-0.05-0.04-0.1-0.07-0.16-0.1-0.13-0.04-0.28-0.05-0.39 0.08-0.17 0.21-0.07 0.44 0.01 0.71 0.07 0.18 0.13 0.38 0.2 0.56 0.82 2.31 1.63 4.62 2.41 6.93 1.61 4.75 3.02 9.55 4.49 14.35 0.88 2.92 1.97 5.77 3.18 8.58 1.68 3.89 3.06 7.85 3.98 11.98 0.51 2.33 1.15 4.64 1.78 6.94 1.28 4.76 0.29 9.21-1.52 13.64-1.06 2.56-1.8 5.29-2.73 7.9-0.73 2.03-1.61 4.03-2.14 6.13-0.1 0.35-0.11 0.73-0.42 1.32 1.99-0.74 3.67-1.41 5.37-2.01 2.3-0.79 4.66-1.03 7.01-1.43 2.1-0.36 4.15-0.91 6.24-1.29 1.25-0.22 2.54-0.48 3.77-0.34 1.7 0.19 3.45 0 5.16 0.39 0.59 0.14 1.23 0.04 1.82 0.28 3.19 1.36 6.82 1.62 9.79 3.47 3.82 2.38 6.91 5.52 8.43 9.89 0.76 2.17 2.03 4.15 2.52 6.39 0.45 2.05 0.71 4.11 0.71 6.17 0 1.53-0.14 3.06-0.47 4.59z" android:fillColor="#F9F9FB" android:strokeColor="#F9F9FB"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_welcome.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_welcome.xml deleted file mode 100644 index b16b2dfdaf91ad3469ce3033e8a4779fc45b6742..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_onboarding_welcome.xml +++ /dev/null @@ -1,137 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="223dp" android:height="345dp" android:viewportWidth="223" android:viewportHeight="345"> - <path android:pathData="M221.98 126.34c-0.19-2.6-0.34-5.19-0.68-7.76-0.19-1.47-0.4-2.95-0.23-4.45 0.06-0.51-0.11-0.95-0.51-1.35-0.92-0.93-1.87-1.83-1.77-3.33 0-0.21-0.04-0.61-0.17-0.65-1.55-0.57-1.09-1.92-1.18-3.04-0.08-1.04-0.04-2.07-0.25-3.1-0.76-3.88-1.52-7.74-2.21-11.64-0.42-2.36-1.1-4.63-1.86-6.89-1.43-4.21-3.12-8.33-5.06-12.35-1.28-2.7-2.53-5.4-4.18-7.89-2.04-3.08-4.28-5.98-7.02-8.54-2.36-2.19-4.93-4.09-7.55-5.92-1.64-1.18-3.54-2.03-5.22-3.17-0.85-0.54-1.75-0.9-2.43-0.22-0.8 0.77-0.59 1.93 0.17 2.69 0.93 0.91 1.52 1.98 1.98 3.14 1.48 3.63 2.53 7.39 3.36 11.2 0.07 0.33 0.45 0.69 0.12 1.08-5.97-10.23-13.06-18.3-20.33-26.59-6.87-7.83-13.91-15.85-20.37-26.09-0.21-0.33-0.41-0.66-0.61-0.99-0.61-1-1.22-2-1.8-3-0.14-0.21-0.26-0.42-0.38-0.62V6.84c-0.25-1.06-0.46-2.14-0.66-3.22-0.16-0.85-0.4-1.46-1.22-1.71-0.09-0.03-0.18-0.06-0.27-0.08-0.05-0.17-0.09-0.34-0.14-0.52 0-0.14-0.1-0.27-0.23-0.29-0.06-0.03-0.13-0.03-0.2 0H141c-8.96 5.54-16.53 12.83-22.34 21.3-1-2.55-2.61-4.77-4.31-6.9-1.92-2.4-4.56-3.96-7.22-5.48-1.45-0.84-3.03-1.35-4.53-2.09-1.79-0.88-3.69-1.43-5.63-1.79-2.17-0.4-4.41-0.55-6.6-0.93-3.08-0.55-6.05 0.04-8.83 1.22-3.52 1.5-7.02 3.09-10.63 4.37-0.86 0.32-1.43 0.78-1.96 1.47-3.24 4.28-6.94 8.04-11.85 10.54-2.21 1.15-4.17 2.83-5.23 5.34-0.84 2.01-1.68 3.99-1.86 6.16-0.04 0.67-0.37 1.08-0.67 1.58 0.8 0.44 0.43 1.2 0.38 1.77-0.19 3.08 0.07 6.05 1.1 9 0.44 1.29 1.26 2.51 1.16 3.92-0.13 1.78-0.27 3.48 1.01 4.45-0.78 0.93-1.62 1.8-2.28 2.79-0.31 0.44-0.63 0.73-1.07 0.96-0.19-0.4-0.44-0.79-0.57-1.22-1.18-4.19-1.79-8.47-2.05-12.81-0.15-2.68-0.15-5.36-0.61-8.02-0.02-0.14-0.1-0.3-0.22-0.47 0.02-0.26 0.04-0.53 0.07-0.79-0.19 0.08-0.37 0.16-0.56 0.24-0.8-0.74-2.02-1.45-2.58-1.25-0.97 0.34-2.05 0.65-2.78 1.3-2.3 2.09-4.47 4.32-6.66 6.54-1.65 1.66-3.29 3.33-4.81 5.08-0.89 1.01-1.79 2.02-2.68 2.99-0.86 0.95-1.43 2.21-2.42 2.95-2.24 1.67-3.48 4.03-5 6.22-1.75 2.53-3.02 5.36-4.11 8.22-0.88 2.31-1.47 4.73-2.25 7.09-0.64 1.94-1.42 3.86-1.99 5.82-0.65 2.27-1.62 4.45-2 6.83-0.36 2.25-1.18 4.43-1.46 7.18-0.29-0.96-0.61-1.47-1.11-1.32-0.44 0.12-0.85 0.4-1.12 1.01-1.41 3.08-2.44 6.28-3.12 9.57-0.61 2.91-0.76 5.87-0.46 8.9 0.27 2.67 0.69 5.35 0.92 8.03 0.19 2.45 0.98 4.72 1.84 6.98 1.03 2.7 2.5 5.19 3.16 8.1 1.16 5.01 2.81 9.9 4.51 14.76 1.16 3.27 2.11 6.63 3.6 9.75 1.65 3.44 3.25 6.92 5.49 10.08 1.81 2.58 3.56 5.19 5.78 7.44 1.2 1.25 2.49 2.48 3.69 3.72 2.71 2.78 5.73 5.16 8.75 7.57 1.35 1.07 2.94 1.81 4.38 2.8 2.64 1.83 5.52 3.27 8.37 4.75 1.95 1.01 3.9 2.06 5.89 3.02 0.9 0.54 1.81 1.05 2.72 1.55 0.01 0 0.02 0.01 0.03 0.01 1.07 0.8 2.11 1.66 3.55 1.84 0.56 0.29 1.13 0.56 1.7 0.83 0.08 0.31-0.11 0.73-0.75 1.28-0.24 0.21 0.06 0.46 0.1 0.7 0.13 0.65 0.27 1.28 0.15 1.98-0.32 1.88-0.61 3.75-0.72 5.65-0.1 2.1-0.25 4.24-0.19 6.37 0.09 2.88-0.46 5.78-0.38 8.66 0.13 5.37-1.1 10.6-1.58 15.92-0.19 2.21-0.4 4.49-0.88 6.72-0.65 3.06-0.53 6.26-1.23 9.36-1.18 5.19-2.23 10.42-2.86 15.71-0.2 1.56-1.01 3.23 0.1 4.73 0.53 0.71 0.61 1.49 0.95 2.33-0.68 0.13-1.39-0.67-1.81 0.24-0.36 0.74 0.14 1.47 0.52 1.72 1.02 0.7 1.76 1.69 2.72 2.43 0.3 0.21 0.51 0.21 0.81 0.21 1.05-0.04 1.87 0.46 2.72 1.03 2.42 1.67 4.48 3.84 7.1 5.25 0.42 0.22 0.86 0.61 0.63 1.08-0.36 0.78-0.18 1.58-0.18 2.34 0.06 2.65-0.57 5.22-0.64 7.86-0.13 5.25 0.42 10.43 1.05 15.64 0.3 2.49 1.21 4.62 2.91 6.52 2.07 2.3 4.36 4.24 6.87 6.03 1.44 1.04 2.92 1.94 4.37 2.91 1.77 1.16 3.69 2.01 5.68 2.72 2.12 0.78 4.61 0.91 6.36 2.28 2.19 1.7 4.64 1.87 7.06 1.87 4.24-0.02 8.02-1.69 11.43-4.18 1.16-0.83 1.84-1.91 2.22-3.3 0.33-1.24 0.21-2.53 0.56-3.79 0.62-2.22-0.19-4.45-0.74-6.59-0.27-1.07-1.49-1.81-1.83-3.12-0.57-2.29-1.9-4.23-3.08-6.28-1.7-2.99-4.15-5.39-6.19-8.09-1.16-1.54-2.88-2.75-3.93-4.47-0.37-0.59-1.2-0.59-1.43-1.38-0.61-1.96-2.25-3.24-3.36-4.86-0.52-0.76-0.39-0.98 0.41-1.23 2.21-0.71 4.38-1.69 6.64-2.21 2.38-0.55 3.12-2.26 3.46-4.24 0.35-2.23 0.02-4.51 0.21-6.76 0.31-3.93 0.16-7.89 0.46-11.82 0.11-1.51-1.06-2.94-0.1-4.42 0.31-0.51 0.25-1.06 0.29-1.6 0.08-1.31-0.17-2.64 0.02-3.9 0.49-3.15 0.55-6.31 0.6-9.45 0.05-3.69 0.29-7.35 0.29-11.04-0.02-4.66-0.22-9.34-0.09-14.02 0.07-2.58 0.13-5.15 0.34-7.72 0.12-1.71 0.87-3.4 0.41-5.31 0.54 0 1.07-0.01 1.6-0.04 0.27 0 0.54 0.01 0.81 0.01 0.07-1.13 0.13-2.09 0.13-2.35 0-0.44 0.26 0.98 0.58 2.36-0.24 0-0.48 0-0.71-0.01-0.12 1.87-0.29 4.21-0.33 4.6-0.19 2.13-0.34 4.28-0.5 6.41-0.22 2.66-0.79 5.27-0.47 7.97 0.04 0.34 0.19 0.84 0.15 0.97-1.01 3.16-0.59 6.41-0.53 9.62 0 0.35 0.4 0.9 0.27 1.03-1.3 1.37-0.44 3.03-0.65 4.53-0.23 1.56 0.12 3.23-0.08 4.78-0.41 2.79-0.51 5.61-0.51 8.37 0 3.76-0.47 7.49-0.8 11.18-0.43 4.77-0.72 9.53-0.78 14.3-0.02 1.66 0.94 2.48 2.64 2.86 2.04 0.46 4.08 0.15 6.13 0.23 1.66 0.07 1.85 0.93 1.92 2.15 0.27 5.06 0.42 10.12 1.39 15.12 0.23 1.22 0.72 2.36 1.03 3.54 0.59 2.26 2.24 3.9 4.05 5.31 1.71 1.35 3.69 2.26 5.5 3.42 2.6 1.66 5.4 2.81 8.27 3.69 2.8 0.89 5.73 1.35 8.62 1.96 1.23 0.28 2.49 0.63 3.74 0.4 2.27-0.44 4.5-0.99 6.36-2.58 1.77-1.51 4.18-2.33 5.1-4.84 0.63-1.69 0.76-3.44 1.08-5.15 0.13-0.65-0.53-1.55-1.41-1.94-0.11-0.04-0.13-0.35-0.13-0.54-0.05-3.06-1.47-5.55-3.17-7.93-0.44-0.61-0.46-1.5-1.15-1.9-1.9-1.09-3.54-2.51-5.19-3.96-2.99-2.66-5.92-5.35-8.62-8.31-0.63-0.7-0.8-1.6-1.06-2.4-0.16-0.51 0.8-0.76 1.21-1.18 1.03-1.07 2.06-2.18 3.01-3.31 0.65-0.79 0.99-1.73 0.99-2.74 0.08-5.15-0.17-10.31 0.25-15.48 0.3-3.5 0.27-7.02 0.47-10.54 0.17-3.16 0.46-6.34 0.63-9.51 0.25-4.42 0.52-8.87 1.11-13.28 0.59-4.38 1.11-8.79 1.48-13.2 0.34-3.75-0.13-7.52 0.55-11.27 0.15-0.81 0.44-1.31 1.18-1.44 1.69-0.3 3.05-1.35 4.6-1.98 1.98-0.81 3.86-1.86 5.73-2.89 2.81-1.54 5.59-3.1 8.31-4.77 2.42-1.47 4.8-2.99 7.06-4.69 1.5-1.12 3.19-1.99 4.5-3.42 1.32-1.48 2.92-2.75 4.4-4.07 1.98-1.8 4.05-3.59 5.61-5.65 2-2.68 3.97-5.42 5.69-8.33 2.68-4.51 5.02-9.13 6.77-14.04 0.67-1.9 1.56-3.6 3.39-4.53 0.86-0.42 1.42-1.18 2.41-1.5 1.3-0.42 1.28-2.11 2-3.16 1.05-1.58 2.42-2.91 3.1-4.79 0.94-2.68 2.09-5.24 2.49-8.14 0.29-2.13 0.91-4.19 0.76-6.36zM5.82 124.25L7 127.49c-0.49-1.04-0.88-2.13-1.18-3.24z" android:strokeWidth="2" android:strokeColor="#F9F9FB"/> - <path android:pathData="M183.48 46.77c9.23 6.47 16.35 15.53 20.5 26.05 6.45 16.37 8.73 34.1 6.63 51.58-0.07 0.53-0.13 1.06-0.19 1.59-0.08 0.8-0.17 1.59-0.27 2.39-9.03 52.52-56.53 89.38-109.38 84.85-52.84-4.52-93.46-48.92-93.51-102.22v-0.53c0.21-4.76 0.77-9.49 1.67-14.16v-0.23c0.12-0.99 0.82-5.51 1.02-6.41l0.13-0.69c2.5-11.18 7.17-21.75 13.76-31.11 2.86-4.09 6.06-7.93 9.55-11.49 3.07-3.16 6.41-6.04 9.99-8.6 1.07-0.73 2.21-1.34 3.4-1.83-0.83 8.73 0.38 17.54 3.53 25.73 6.8-8.01 15.17-14.52 24.6-19.11-2.14 8.24-2.04 16.91 0.29 25.09 1 0.69 1.79 1.3 2.64 2.02 8.07-6.39 17.87-10.19 28.13-10.89 2.11-23.54 15.14-44.69 35.17-57.07h0.08c0.06-0.02 0.13-0.02 0.19 0 0.14 0.02 0.24 0.15 0.24 0.29 0.34 1.41 0.85 2.77 1.52 4.05 0.31 0.65 0.67 1.35 1.13 2.09 0.58 1 1.19 1.99 1.8 2.99l0.6 0.99c6.43 10.19 13.45 18.19 20.29 25.98 10.16 11.58 19.94 22.72 26.83 39.99v-0.17c-1.82-10.86-5.31-21.38-10.34-31.17zM86.21 153.2c0.13 0.07 0.27 0.14 0.4 0.2l-0.4-0.2zm0.4 0.2c0.07 0.04 0.13 0.07 0.2 0.1 0.27 0.14 0.53 0.28 0.82 0.41l-1.02-0.51z" android:fillType="evenOdd"> - <aapt:attr name="android:fillColor"> - <gradient android:startX="111.24" android:startY="-53.48" android:endX="-64.29" android:endY="104.43" android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.11" android:color="#FFFFE847"/> - <item android:offset="0.23" android:color="#FFFFC830"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.4" android:color="#FFFF8B16"/> - <item android:offset="0.46" android:color="#FFFF672A"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M203.98 72.81c-4.15-10.51-11.27-19.57-20.5-26.04 5.03 9.79 8.52 20.3 10.34 31.17v0.21c7.89 22.65 6.76 47.48-3.14 69.3-15.45 32.29-48.78 52-84.37 49.88-48.24-1.35-89.05-36.25-98.11-83.88-0.88-5.71-0.63-11.53 0.72-17.13-1 4.65-1.55 9.39-1.66 14.16v0.53c0.05 53.3 40.67 97.7 93.51 102.22 52.85 4.53 100.35-32.33 109.38-84.85 0.17-1.33 0.3-2.65 0.46-3.98 2.1-17.48-0.18-35.22-6.63-51.59z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="182.62" android:centerY="25.25" android:gradientRadius="213.01" android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.19" android:color="#FFFFAC31"/> - <item android:offset="0.25" android:color="#FFFF9D17"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.4" android:color="#FFFF563B"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.71" android:color="#FFF5156C"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M203.98 72.81c-4.15-10.51-11.27-19.57-20.5-26.04 5.03 9.79 8.52 20.3 10.34 31.17v0.21c7.89 22.65 6.76 47.48-3.14 69.3-15.45 32.29-48.78 52-84.37 49.88-48.24-1.35-89.05-36.25-98.11-83.88-0.88-5.71-0.63-11.53 0.72-17.13-1 4.65-1.55 9.39-1.66 14.16v0.53c0.05 53.3 40.67 97.7 93.51 102.22 52.85 4.53 100.35-32.33 109.38-84.85 0.17-1.33 0.3-2.65 0.46-3.98 2.1-17.48-0.18-35.22-6.63-51.59z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="104.78" android:centerY="112.77" android:gradientRadius="213.01" android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#57DB293D"/> - <item android:offset="0.5" android:color="#17F5334B"/> - <item android:offset="0.53" android:color="#02FF3750"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M154.32 84.88l0.64 0.48c-2.56-4.57-5.76-8.76-9.49-12.44-19.98-18.79-21.9-49.99-4.37-71.11-19.99 12.37-33.01 33.49-35.13 56.99 1.18-0.08 2.37-0.19 3.58-0.19 18.54 0.04 35.63 10.07 44.77 26.27z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="130.46" android:centerY="-23.33" android:gradientRadius="154.32" android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.25" android:color="#FFFFDC3E"/> - <item android:offset="0.51" android:color="#FFFF9D12"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M109.62 91.27c-2.66 5.1-7.01 9.12-12.29 11.35-29 0-33.77 17.68-33.77 17.68 1.84 14.58 10.9 27.23 24.07 33.61 0.57 0.29 1.15 0.55 1.71 0.82 1.01 0.45 2.01 0.86 3.01 1.23 4.28 1.55 8.76 2.44 13.3 2.65 20.04 1.93 38.66-10.61 44.5-29.98 5.83-19.36-2.73-40.18-20.47-49.75 8.67-1.13 17.45 1 24.64 6-9.15-16.22-26.27-26.25-44.82-26.27-1.21 0-2.4 0.11-3.58 0.19-10.26 0.7-20.06 4.5-28.14 10.89 1.57 1.32 3.33 3.1 7.03 6.77 7.81 5.67 16.12 10.63 24.81 14.81z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="81.21" android:centerY="168.69" android:gradientRadius="101.42" android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.47" android:color="#FF5C79F0"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M109.62 91.27c-2.66 5.1-7.01 9.12-12.29 11.35-29 0-33.77 17.68-33.77 17.68 1.84 14.58 10.9 27.23 24.07 33.61 0.57 0.29 1.15 0.55 1.71 0.82 1.01 0.45 2.01 0.86 3.01 1.23 4.28 1.55 8.76 2.44 13.3 2.65 20.04 1.93 38.66-10.61 44.5-29.98 5.83-19.36-2.73-40.18-20.47-49.75 8.67-1.13 17.45 1 24.64 6-9.15-16.22-26.27-26.25-44.82-26.27-1.21 0-2.4 0.11-3.58 0.19-10.26 0.7-20.06 4.5-28.14 10.89 1.57 1.32 3.33 3.1 7.03 6.77 7.81 5.67 16.12 10.63 24.81 14.81zm-36.54-25l2.12 1.4c-2.33-8.18-2.43-16.85-0.29-25.09-9.43 4.59-17.8 11.1-24.6 19.11 7.84-0.28 15.64 1.29 22.77 4.58z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="107.62" android:centerY="87.69" android:gradientRadius="53.78" android:type="radial"> - <item android:offset="0.21" android:color="#029059FF"/> - <item android:offset="0.28" android:color="#108C4FF3"/> - <item android:offset="0.75" android:color="#727716A8"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M8.2 113.45c9.03 47.64 49.82 82.55 98.06 83.94 35.62 2.13 68.98-17.61 84.41-49.94 9.92-21.82 11.07-46.65 3.2-69.3v-0.16 0.18c2.46 24.16-7.88 47.86-27.24 62.41l-0.07 0.13c-36.66 30.01-71.75 18.11-78.85 13.25l-1.49-0.74c-18.46-7.79-29.89-26.59-28.34-46.65-10.36 0.15-19.84-5.85-24.19-15.3 11.41-7.03 25.63-7.61 37.57-1.52 12.1 5.52 25.86 6.07 38.36 1.52-8.68-4.18-16.96-9.14-24.76-14.81-3.7-3.67-5.45-5.45-7.02-6.77-0.85-0.72-1.64-1.33-2.64-2.02l-2.12-1.4c-7.13-3.29-14.93-4.86-22.77-4.58-3.15-8.19-4.36-17-3.53-25.73-1.19 0.49-2.33 1.1-3.4 1.83-3.58 2.56-6.92 5.44-9.99 8.6-3.49 3.56-6.69 7.4-9.55 11.49-6.59 9.36-11.26 19.93-13.76 31.11-1.92 8-2.56 16.26-1.88 24.46z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="159.45" android:centerY="-30.02" android:gradientRadius="311.31" android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.62" android:color="#FFFF5634"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M145.47 72.92c3.73 3.68 6.93 7.87 9.49 12.44 0.56 0.42 1.08 0.85 1.53 1.33 13.96 14.25 17.96 35.57 10.13 53.96 19.38-14.57 29.72-38.29 27.23-62.48-11.56-28.95-31.15-40.67-47.15-66.03-0.8-1.33-1.62-2.65-2.4-3.98-0.46-0.74-0.82-1.44-1.13-2.09-0.67-1.28-1.18-2.64-1.52-4.05 0-0.14-0.1-0.27-0.24-0.29-0.06-0.02-0.13-0.02-0.2 0h-0.07c-17.6 21.12-15.69 52.38 4.33 71.19z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="129.98" android:centerY="4.81" android:gradientRadius="229.3" android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.06" android:color="#FFFFE847"/> - <item android:offset="0.17" android:color="#FFFFC830"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.36" android:color="#FFFF8B16"/> - <item android:offset="0.46" android:color="#FFFF672A"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M156.49 86.62c-0.44-0.41-0.97-0.84-1.53-1.33l-0.64-0.47c-7.19-5-15.97-7.14-24.64-6 17.65 9.61 26.14 30.37 20.32 49.68-5.83 19.3-24.36 31.83-44.35 29.98-4.54-0.21-9.02-1.1-13.3-2.65-1-0.37-2-0.79-3.01-1.23-0.56-0.27-1.14-0.54-1.71-0.83 7.11 4.88 42.18 16.77 78.86-13.25l0.06-0.13c7.77-18.32 3.8-39.54-10.06-53.77z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="100.36" android:centerY="43.66" android:gradientRadius="194.35" android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.59" android:color="#FFFF5634"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M63.56 120.29s4.72-17.67 33.77-17.67c5.28-2.23 9.63-6.25 12.29-11.35-12.49 4.55-26.26 4-38.36-1.52-11.94-6.09-26.16-5.51-37.57 1.52 4.35 9.45 13.83 15.45 24.19 15.3-1.55 20.05 9.86 38.84 28.31 46.63 0.48 0.23 0.93 0.48 1.43 0.7-13.17-6.38-22.23-19.03-24.06-33.61z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="151.67" android:centerY="55.09" android:gradientRadius="212.72" android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.23" android:color="#FFFFE141"/> - <item android:offset="0.51" android:color="#FFFFAF1E"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M203.98 72.82c-4.15-10.52-11.27-19.58-20.5-26.05 5.03 9.79 8.52 20.31 10.34 31.17v0.17C182.29 49.22 162.7 37.5 146.7 12.14c-0.8-1.33-1.62-2.65-2.4-3.98-0.46-0.74-0.82-1.44-1.13-2.09-0.67-1.28-1.18-2.64-1.52-4.05 0-0.14-0.1-0.27-0.24-0.29-0.06-0.02-0.13-0.02-0.19 0h-0.08c-20.03 12.38-33.06 33.53-35.17 57.07 1.18-0.08 2.37-0.19 3.58-0.19 18.56 0.02 35.67 10.05 44.82 26.27-7.19-5-15.97-7.13-24.64-6 17.65 9.61 26.14 30.38 20.32 49.68-5.83 19.31-24.36 31.84-44.35 29.98-4.54-0.2-9.02-1.1-13.3-2.65-1-0.37-2-0.78-3-1.23-0.57-0.26-1.15-0.53-1.72-0.82l-1.49-0.74c0.48 0.22 0.93 0.47 1.43 0.7-13.14-6.36-22.19-18.97-24.06-33.5 0 0 4.72-17.68 33.77-17.68 5.28-2.23 9.63-6.25 12.29-11.35-8.68-4.18-16.96-9.14-24.76-14.81-3.7-3.67-5.45-5.45-7.02-6.77-0.85-0.72-1.64-1.33-2.64-2.02-2.33-8.18-2.43-16.85-0.29-25.09-9.43 4.59-17.8 11.1-24.6 19.11-3.15-8.19-4.36-17-3.53-25.73-1.19 0.49-2.33 1.1-3.4 1.83-3.58 2.56-6.92 5.44-9.99 8.6-3.49 3.56-6.69 7.4-9.55 11.49-6.59 9.36-11.26 19.93-13.76 31.11l-0.13 0.69c-0.2 0.9-1.07 5.48-1.19 6.48 0 0 0-0.08 0 0-0.78 4.74-1.28 9.52-1.5 14.32v0.53c0.05 53.3 40.67 97.7 93.51 102.22 52.85 4.53 100.35-32.33 109.38-84.85 0.17-1.33 0.3-2.65 0.46-3.98 2.1-17.48-0.18-35.21-6.63-51.58z"> - <aapt:attr name="android:fillColor"> - <gradient android:startX="118.56" android:startY="-41.25" android:endX="-31" android:endY="98.2" android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.27" android:color="#A1FFF44F"/> - <item android:offset="0.49" android:color="#37FFF44F"/> - <item android:offset="0.6" android:color="#02FFF44F"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M72.92 54.82l2.35 11.79 13.59-6.6 19.68-2.83 2.82-20.75-8.91-6.14-5.15 6.14-8.44-2.36-7.5 6.13h-8.44v14.62zm51.56 92.43l14.06 8.02h-12.65l-9.38-5.19h-5.15l-3.75 2.83 3.75 3.3-1.88 4.72 4.69 3.77v5.66l11.72 4.25 1.4 4.71 28.13-2.83 24.37-9.43 20.63-11.79 13.59-8.02 5.62-12.73v-15.09l-3.74-7.07-15.47 20.27-46.88 22.64-19.22-10.84-10.31-0.95 0.47 3.77zM12.92 109.06L9.17 98.21H6.83l-4.22 15.56 8.44 23.11 25.78 20.28 34.22 15.09h5.15l4.22-1.89 6.09-0.94v-4.71l6.57-2.83 0.93-4.72 4.69-4.25v-3.77h-5.62l-14.07 1.89-5.15-3.77 7.5-5.66 2.81-6.14-3.75-1.41-6.56 2.83-14.06 6.6-5.63-2.83-16.4-9.9-12.19-8.49-7.97-6.13-4.69-7.07zM73.39 310.9v-14.62h22.5l5.62 9.91-9.37 1.88-1.41 10.38-17.34-7.55zm49.69-14.62v-4.24l7.5-0.94 11.71-3.78 5.16 8.96h-7.97l-5.62 6.61-10.78-6.61z" android:fillColor="#EEC8A6"/> - <path android:pathData="M95.84 109.96l0.71-8.49 6.37-4.96 4.6-7.43v-4.95l-3.89-5.31 1.41-2.48 4.6 2.48 3.9-2.48V72.1l6.01-2.83 6.37-1.77 2.48 3.89 5.31 1.77 4.95-2.83 7.79 8.49-11.68-3.89-5.66 2.12 8.49 5.31-0.36 3.54v7.78l4.61 0.36 2.47-2.83 5.31 8.49-6.01-1.77h-2.84l-0.35 2.83 3.89 2.83 1.06 3.19-2.47 2.83-3.54-1.06-1.77 2.47 3.89 2.13 1.77 2.12-5.66 7.43-1.42 7.08 5.67 0.71v3.18l-3.19 5.66-2.48-6.72-4.95 8.14h-5.31l-5.31 1.06-2.12-4.6-1.42-11.68-4.6-7.43h-7.43l-6.37-1.77-2.83-6.37zM82.39 67.85l1.42 5.31 3.54 3.89 5.31-3.89 7.78-3.89 5.31-2.84v-3.18l-5.31-1.42-9.55 1.42-5.66 1.06-2.84 3.54zm-16.98 56.27l-4.25-1.77 1.42-6.02 4.24-4.6 5.67 3.54 5.66 6.02 5.31 3.53 1.41 4.25-2.48 4.25h-6.01l-7.43 3.89-3.19-7.43-0.35-5.66z" android:fillColor="#381879" android:fillAlpha="0.5"/> - <path android:pathData="M116.5 215.79c0.78 4.3-0.21 8.59-0.27 12.87 0 0.96 0.46 2.16-0.76 3.02-0.31 0.21-0.27 1.56-0.08 2.12 0.96 2.96 0.06 5.88 0.06 8.8 0 2.39 0.09 4.79-0.06 7.2-0.13 1.81-0.23 3.63-0.25 5.46-0.05 3.44-0.19 6.89-0.49 10.31-0.19 2.31-0.44 4.62-0.63 6.93-0.27 3.78-0.79 7.56-0.67 11.38 0 0.29 0.11 0.63 0 0.9-0.63 1.62 0.4 1.62 1.49 1.6 1.51-0.02 3.01-0.02 4.52-0.02 0.98 0 1.97-0.05 2.87 0.56 0.93 0.61 2.08 0.25 2.86 0.04 2.56-0.69 5.14-0.54 7.73-0.54 2.96 0 5.43-1.14 7.81-2.86 1.61-1.17 3.1-2.48 4.53-3.84 0.72-0.69 0.91-1.45 0.78-2.41-0.36-3.3-0.11-6.58-0.04-9.87 0.1-5.63 0.63-11.24 0.88-16.86 0.17-3.82 0.38-7.67 0.63-11.49 0.33-4.95 0.99-9.87 1.55-14.78 0.51-4.34 0.61-8.69 1.09-13.02 0.13-1.05-0.1-2.12 0.09-3.23 0.15-0.84-0.51-1.51-1.51-1.07-2.84 1.26-5.82 2.02-8.74 3-1.03 0.34-0.15 0.65-0.12 0.99-4.79-0.17-9.33 1.32-13.99 1.99-3.34 0.49-6.74 0.34-10.12 0.55-1.47 0.08-2.94 0-4.41 0 0.48 1.93-0.27 3.63-0.4 5.35-0.21 2.56-0.27 5.13-0.33 7.69-0.13 4.66 0.06 9.32 0.08 13.96 0 3.68-0.23 7.33-0.29 11-0.05 3.13-0.11 6.28-0.59 9.41-0.19 1.26 0.06 2.58-0.02 3.88-0.04 0.55 0.02 1.09-0.3 1.6-0.94 1.47 0.21 2.9 0.11 4.41-0.3 3.9-0.15 7.85-0.46 11.76-0.19 2.24 0.14 4.51-0.21 6.74-0.34 1.97-1.07 3.67-3.45 4.22-2.24 0.52-4.41 1.49-6.61 2.2-0.8 0.25-0.92 0.46-0.4 1.22 1.09 1.62 2.73 2.9 3.34 4.85 0.23 0.77 1.05 0.77 1.43 1.36 1.05 1.72 2.75 2.92 3.9 4.45 2.04 2.69 4.48 5.08 6.18 8.07 1.17 2.03 2.49 3.96 3.06 6.25 0.34 1.31 1.56 2.04 1.83 3.11 0.54 2.12 1.34 4.35 0.73 6.55-0.35 1.26-0.23 2.54-0.56 3.78-0.38 1.39-1.05 2.46-2.21 3.3-3.4 2.47-7.16 4.13-11.38 4.15-2.41 0-4.85-0.16-7.03-1.86-1.75-1.37-4.22-1.49-6.34-2.27-1.98-0.72-3.89-1.56-5.65-2.71-1.45-0.97-2.92-1.87-4.35-2.9-2.5-1.78-4.79-3.71-6.84-6-1.7-1.89-2.61-4.01-2.9-6.49-0.63-5.19-1.18-10.35-1.05-15.58 0.06-2.62 0.69-5.19 0.63-7.83 0-0.76-0.17-1.55 0.19-2.33 0.23-0.46-0.21-0.86-0.63-1.07-2.61-1.41-4.66-3.57-7.08-5.23-0.84-0.57-1.66-1.07-2.71-1.03-0.29 0-0.5 0-0.8-0.21-0.96-0.73-1.7-1.72-2.7-2.41-0.38-0.26-0.89-0.99-0.53-1.73 0.42-0.9 1.14-0.1 1.81-0.23-0.34-0.84-0.42-1.61-0.95-2.33-1.11-1.49-0.29-3.15-0.1-4.7 0.63-5.27 1.68-10.48 2.85-15.64 0.7-3.09 0.57-6.28 1.22-9.32 0.48-2.23 0.69-4.5 0.88-6.7 0.49-5.29 1.7-10.5 1.58-15.85-0.09-2.88 0.46-5.76 0.38-8.63-0.07-2.12 0.08-4.24 0.18-6.34 0.11-1.89 0.4-3.76 0.72-5.63 0.12-0.69-0.02-1.32-0.15-1.97-0.04-0.24-0.33-0.49-0.1-0.7 1.74-1.49 0.12-1.97-0.82-2.08-2.23-0.23-3.49-2.05-5.34-2.89-2.35-1.1-4.64-2.33-6.93-3.53-2.83-1.47-5.71-2.9-8.33-4.73-1.43-0.98-3.02-1.72-4.37-2.79-3-2.39-6-4.76-8.71-7.53-1.2-1.24-2.48-2.46-3.68-3.7-2.2-2.25-3.94-4.85-5.75-7.41-2.23-3.15-3.82-6.62-5.46-10.04-1.49-3.11-2.43-6.46-3.59-9.72-1.7-4.83-3.34-9.7-4.49-14.7-0.65-2.89-2.12-5.37-3.15-8.06-0.86-2.25-1.64-4.51-1.83-6.95-0.23-2.67-0.65-5.33-0.92-8-0.3-3.02-0.15-5.96 0.46-8.86 0.67-3.27 1.7-6.47 3.11-9.53 0.27-0.61 0.67-0.88 1.11-1.01 0.5-0.15 0.82 0.36 1.11 1.32 0.28-2.75 1.09-4.91 1.45-7.16 0.38-2.37 1.34-4.53 2-6.8 0.56-1.95 1.34-3.86 1.97-5.79 0.78-2.36 1.36-4.77 2.25-7.06 1.09-2.85 2.35-5.67 4.09-8.19 1.51-2.18 2.75-4.53 4.98-6.19 0.98-0.74 1.55-2 2.41-2.94 0.88-0.97 1.79-1.97 2.67-2.98 1.51-1.74 3.15-3.4 4.79-5.06 2.18-2.21 4.34-4.43 6.63-6.51 0.74-0.65 1.81-0.97 2.77-1.3 0.82-0.3 3.13 1.4 3.28 2.27 0.46 2.64 0.46 5.31 0.61 7.97 0.25 4.33 0.86 8.59 2.03 12.77 0.13 0.42 0.38 0.82 0.57 1.22 0.44-0.23 0.76-0.53 1.07-0.97 0.65-0.99 1.49-1.85 2.27-2.77-1.28-0.97-1.14-2.67-1.01-4.43 0.11-1.41-0.71-2.62-1.15-3.91-1.03-2.93-1.28-5.9-1.1-8.96 0.05-0.57 0.42-1.32-0.37-1.76 0.29-0.51 0.63-0.91 0.67-1.58 0.17-2.16 1.01-4.14 1.85-6.13 1.05-2.5 3-4.18 5.2-5.31 4.9-2.5 8.57-6.24 11.8-10.5 0.53-0.69 1.1-1.16 1.96-1.47 3.59-1.28 7.07-2.86 10.58-4.35 2.77-1.17 5.73-1.76 8.8-1.21 2.18 0.37 4.41 0.52 6.57 0.92 1.93 0.36 3.82 0.9 5.6 1.78 1.5 0.74 3.07 1.24 4.52 2.08 2.65 1.51 5.27 3.07 7.18 5.46 2.06 2.56 3.97 5.25 4.83 8.51 0.06 0.27 0.23 0.52 0.44 0.96 1.18-2.29 2.48-4.32 3.93-6.23 1.45-1.92 3.19-3.55 4.76-5.32 2.17-2.41 4.83-4.24 6.93-6.69 1.3-1.54 3.07-2.63 4.33-4.25 0.48-0.63 1.43-0.71 2.24-0.44 0.82 0.26 1.05 0.86 1.22 1.7 0.53 2.86 1.09 5.8 2.54 8.23 2.15 3.62 4.43 7.19 7.08 10.5 2.52 3.15 4.76 6.51 7.26 9.68 3.95 5.02 7.69 10.19 12.16 14.78 2.42 2.5 4.81 5.02 6.99 7.77 1.75 2.21 3.66 4.33 5.53 6.47 0.82 0.92 1.46 2.01 2.2 3.04 0.65-0.46 0.17-0.88 0.08-1.26-0.82-3.8-1.86-7.53-3.33-11.15-0.47-1.15-1.05-2.22-1.98-3.12-0.75-0.76-0.96-1.91-0.17-2.69 0.68-0.67 1.58-0.32 2.42 0.23 1.68 1.13 3.57 1.97 5.21 3.15 2.6 1.83 5.16 3.72 7.51 5.9 2.73 2.54 4.96 5.44 6.99 8.5 1.64 2.48 2.88 5.17 4.16 7.85 1.93 4.02 3.61 8.11 5.04 12.31 0.76 2.25 1.43 4.51 1.85 6.86 0.69 3.89 1.45 7.73 2.2 11.59 0.21 1.03 0.17 2.06 0.26 3.09 0.08 1.11-0.38 2.46 1.17 3.02 0.13 0.05 0.17 0.44 0.17 0.65-0.1 1.5 0.84 2.4 1.76 3.32 0.4 0.4 0.57 0.84 0.51 1.35-0.17 1.49 0.04 2.96 0.23 4.43 0.34 2.56 0.48 5.14 0.67 7.72 0.15 2.17-0.46 4.22-0.76 6.34-0.39 2.88-1.53 5.44-2.47 8.11-0.67 1.87-2.04 3.19-3.09 4.76-0.71 1.05-0.69 2.73-2 3.15-0.98 0.32-1.53 1.07-2.39 1.49-1.83 0.93-2.71 2.63-3.38 4.52-1.74 4.89-4.07 9.49-6.74 13.98-1.72 2.9-3.67 5.63-5.67 8.3-1.55 2.05-3.61 3.84-5.58 5.62-1.47 1.33-3.07 2.58-4.39 4.05-1.3 1.43-2.98 2.29-4.47 3.41-2.25 1.7-4.62 3.21-7.04 4.68-2.71 1.66-5.48 3.21-8.27 4.74-1.87 1.03-3.74 2.08-5.71 2.88-1.53 0.63-2.9 1.68-4.58 1.97-0.73 0.13-1.03 0.63-1.17 1.43-0.68 3.74-0.22 7.5-0.55 11.23-0.38 4.39-0.88 8.78-1.47 13.15-0.59 4.39-0.86 8.82-1.11 13.23-0.17 3.14-0.47 6.31-0.63 9.46-0.19 3.51-0.17 7.02-0.47 10.5-0.41 5.15-0.16 10.29-0.25 15.41 0 1.01-0.33 1.96-0.98 2.73-0.95 1.14-1.98 2.23-3.01 3.3-0.4 0.42-1.36 0.67-1.19 1.17 0.25 0.8 0.42 1.71 1.05 2.4 2.68 2.94 5.6 5.63 8.58 8.27 1.64 1.45 3.28 2.86 5.17 3.95 0.69 0.4 0.71 1.28 1.15 1.89 1.68 2.37 3.11 4.85 3.15 7.89 0 0.19 0.02 0.51 0.13 0.55 0.88 0.38 1.53 1.28 1.41 1.93-0.32 1.7-0.45 3.44-1.07 5.12-0.93 2.5-3.32 3.32-5.09 4.83-1.84 1.58-4.07 2.12-6.34 2.56-1.24 0.24-2.5-0.12-3.71-0.39-2.88-0.61-5.8-1.08-8.59-1.96-2.86-0.88-5.65-2.01-8.23-3.67-1.81-1.16-3.78-2.06-5.48-3.4-1.81-1.41-3.45-3.05-4.03-5.29-0.32-1.18-0.8-2.31-1.03-3.53-0.97-4.98-1.12-10.02-1.39-15.06-0.06-1.21-0.25-2.08-1.91-2.14-2.04-0.08-4.07 0.23-6.11-0.23-1.68-0.38-2.64-1.19-2.62-2.85 0.06-4.75 0.35-9.49 0.77-14.24 0.34-3.67 0.8-7.39 0.8-11.13 0-2.75 0.11-5.56 0.51-8.33 0.2-1.56-0.15-3.21 0.08-4.77 0.21-1.49-0.65-3.15 0.65-4.51 0.13-0.13-0.27-0.68-0.27-1.03-0.07-3.19-0.49-6.43 0.52-9.58 0.04-0.12-0.1-0.63-0.15-0.96-0.31-2.69 0.26-5.29 0.47-7.94 0.16-2.12 0.31-4.26 0.5-6.38 0.06-0.63 0.38-1.13 0.38-1.81 0-0.77 0.9-0.82 1.45-0.54 0.52 0.27 0.9 0.1 1.26 0h0.08zm70.82-163.46c0.93 2.92 1.75 5.55 2.55 8.15 0.37 1.24 1 2.5 0.08 3.78-0.11 0.15-0.06 0.31 0.1 0.31 1.41-0.04 1.39 1.24 1.47 1.96 0.28 2.35 1.1 4.53 1.72 6.76 0.34 1.19 0.28 2.45 0.97 3.63 0.38 0.63 0.59 1.95-0.75 2.48-1.24 0.48-1.79-0.13-2.38-1.1-1.72-2.75-2.71-5.85-4.39-8.65-1.74-2.89-3.88-5.45-5.92-8.1-1.7-2.23-3.59-4.33-5.43-6.45-3.09-3.52-6.58-6.67-9.45-10.41-1.14-1.47-2.54-2.73-3.66-4.24-2.2-3-4.39-6.05-6.72-8.97-3.13-3.94-6.21-7.91-8.94-12.15-2.52-3.91-5.04-7.81-6.2-12.54-0.46 0.59-0.79 1.18-1.28 1.58-4.36 3.67-8.56 7.53-12.3 11.86-1.74 2.02-3.13 4.26-4.39 6.59-0.44 0.82-0.46 1.83-1.03 2.58-2.87 3.87-4.99 8.13-6.55 12.69-0.1 0.33-0.25 0.84-0.48 0.9-1.07 0.27-1.03 1.2-1.33 1.95-0.56 1.49-0.35 3.15-0.79 4.64-0.69 2.27-1.03 4.56-1.03 6.91 0 0.52 0.13 0.71 0.73 0.84 4.37 0.86 8.8 1.34 13.06 2.69 2.19 0.69 4.22 1.66 6.22 2.68 2.04 1.05 3.9 2.44 5.86 3.66 3.48 2.18 6.8 4.62 9.8 7.43 2.06 1.95 4.31 3.74 6.01 6.05 0.78 1.05 1.74 1.97 2.25 3.25 0.31 0.8 0.14 1.43-0.45 1.85-0.58 0.42-1.21 0.44-1.89-0.15-1.34-1.19-2.66-2.39-4.22-3.4-3.13-2.04-6.44-3.48-10.1-3.95-1.32-0.16-2.81-0.4-4.43 0.17 0.61 0.32 1.03 0.17 1.41 0.42 5.35 3.55 9.83 7.88 13.06 13.54 2.79 4.9 5.27 9.81 6.34 15.44 1.3 6.76 0.51 13.22-1.91 19.56-0.94 2.46-2.06 4.94-3.55 7.1-2.52 3.68-4.97 7.43-8.35 10.44-0.78 0.69-0.42 1.13 0.04 1.32 3.04 1.22 5.69 3.25 8.75 4.41 1.89 0.71 3.87 1.68 5.86 1.38 2.33-0.33 4.62-1.11 6.85-1.95 2.77-1.05 5.41-2.41 8.17-3.48 2.24-0.89 4.26-2.21 6.48-3.15 2.4-1.01 4.45-2.77 6.95-3.72 0.88-0.33 1.89-0.78 2.5-1.26 2.37-1.91 5.17-3.09 7.58-4.89 2.08-1.53 4.41-2.75 6.34-4.45 2.92-2.56 5.86-5.11 8.38-8.11 1.49-1.76 3.17-3.42 4.12-5.54 0.67-1.49 1.55-2.96 1.38-4.79-0.44-4.85-1.32-9.61-2.12-14.4-0.52-3.11-1.22-6.15-2.16-9.15-0.65-2.04-1.24-4.12-2.12-6.05-0.59-1.28-0.76-2.73-1.43-3.91-0.9-1.57-1.58-3.25-2.44-4.85-0.94-1.76-1.7-3.67-2.77-5.35-2.26-3.57-4.97-6.78-8.21-9.51-1.8-1.51-3.53-3.17-5.92-4.39l0.06 0.06zM11.54 137.45c0.84 2.69 1.53 5.25 2.41 7.75 0.97 2.77 1.47 5.65 2.65 8.38 0.67 1.55 1.09 3.31 1.8 4.82 1.37 2.88 2.8 5.72 4.45 8.47 2.46 4.05 5.09 7.87 8.61 11.1 2.84 2.61 5.34 5.55 8.55 7.69 2.37 1.59 4.51 3.48 7.16 4.74 2.83 1.35 5.44 3.22 8.25 4.62 2.73 1.39 5.4 2.94 8.15 4.24 2.98 1.41 6.02 2.69 9.07 4.01 3.13 1.37 6.38 2.42 9.59 3.45 3.22 1.02 6.66 1.47 9.98 2.27 0.77 0.18 1.57 0.25 2.37 0.33 3.32 0.31 6.63 0.57 9.93 0.94 2.98 0.34 6.01 0.32 8.97 0.26 2.52-0.04 5.12 0 7.66-0.44 2.73-0.46 5.54-0.57 8.27-1.12 2.8-0.54 5.57-1.19 8.34-1.95 3.17-0.84 6.43-1.41 9.45-2.64 1.28-0.53 2.77-0.82 3.63-2.06 0.74-1.07 1.53-1.66 2.73-0.69 0.32 0.25 0.57 0.06 0.82-0.05 2.1-0.94 4.24-1.82 6.32-2.85 2.79-1.39 5.63-2.73 8.23-4.41 2.94-1.89 6.03-3.61 8.86-5.65 3.11-2.25 6.11-4.68 9.01-7.26 2.5-2.25 4.85-4.58 6.86-7.23 3.58-4.66 6.83-9.57 9.12-15.01 0.54-1.3 1.36-2.58 1.55-4.2-2.06 0.72-3.76 1.87-5.29 2.92-2.56 1.74-5.42 2.83-8.04 4.39-1.13 0.67-2.33 1.68-3.45 1.85-2.16 0.33-3.8 1.61-5.71 2.33-4.09 1.51-7.83 3.8-11.75 5.67-5.15 2.45-10.57 3.75-16.07 4.83-1.28 0.25-2.56 0.54-3.94 0.56-1.83 0.04-3.7-0.17-5.51 0.25-4.85 1.18-9.8 1.12-14.74 0.97-1.63-0.04-3.17-0.76-3.71-2.41-0.32-0.99-0.86-1.98-0.63-3.09-3.55-0.04-6.78-1.16-10.04-2.12-1.7-0.51-2.94-3.17-2.46-4.85 0.28-0.95 0.8-1.81 1.26-2.8-1.44 0.05-2.28-1.13-3.48-1.63-1.09-0.49-2.52-1.26-2.21-3.07 0.11-0.59-0.37-0.31-0.71-0.33-3.7-0.05-7.39-0.11-11.07-0.21-0.58 0-0.79 0.23-1.11 0.67-1.01 1.4-2.06 2.96-3.82 3.36-1.91 0.44-2.96 2.05-3.19 3.38-0.46 2.6-2.35 3.25-4.18 4.13-1.53 0.74-3.15 0.82-4.81 0.59-0.54-0.08-1.19-0.33-1.64 0.57-0.84 1.72-2.66 2.5-4.53 2.16-0.55-0.08-1.07-0.19-1.62-0.31-2.69-0.65-5.46-1.07-7.96-2.42-1.34-0.71-2.66-1.51-4.05-2.12-1.32-0.57-2.81-0.8-4.09-1.43-3.34-1.64-6.93-2.79-10.02-4.87-0.98-0.67-2.12-0.82-3.06-1.47-1.24-0.86-2.46-1.74-3.78-2.43-3.34-1.73-6.43-3.85-9.51-5.97-2.48-1.7-5-3.36-7.4-5.18-1.89-1.43-3.54-3.09-5.31-4.64-1.74-1.51-3.08-3.45-5.16-4.83v0.04zm7.95-21.77c0.95-1.05 1.52-0.49 2.08 0.17 0.47 0.52 0.86 1.17 1.45 1.47 2.54 1.21 4.18 3.59 6.64 4.89 1.4 0.75 2.56 2.03 3.92 2.73 2.59 1.3 4.92 2.94 7.27 4.53 2.81 1.91 5.75 3.68 8.54 5.63 2 1.39 4.31 2.64 6.68 3.59 0.59 0.25 1.28 0.34 1.79 0.61 1.32 0.71 3.12 0.42 4.07 2.01 0-0.54 0.5-0.92 0.23-1.47-0.19-0.35-0.08-0.63 0.34-0.58 1.28 0.14 2.12-0.86 3.19-1.14 1.01-0.25 0.9-0.69 0.63-1.38-0.84-2.06-1.62-4.14-2.56-6.13-1.1-2.31-1.79-4.75-2.5-7.16-0.25-0.84-0.17-1.68 0.14-2.54 0.82-2.19 1.58-4.37 2.67-6.45 1.07-2.04 2.18-3.97 4.24-5 1.58-0.77 3.03-1.74 4.54-2.58 2.48-1.39 5.14-1.97 7.81-2.73 1.87-0.54 3.93-0.25 5.69-1.01 3.46-1.47 7.18-2.14 10.69-3.46 2.41-0.9 4.3-2.37 5.96-4.26 0.46-0.55 0.55-0.99 0.06-1.7-0.8-1.22-1.34-2.57-0.44-4.1 0.53-0.86 0.17-1.85-0.82-2.16-1.8-0.55-3.44-1.45-5.18-2.08-1.93-0.71-3.87-1.64-5.53-2.73-3.31-2.18-6.15-5.08-9.02-7.87-1.75-1.68-3.22-3.72-5.44-4.79-1.96-0.92-2.35-2.6-3.05-4.43-1.05-2.71-1.47-5.56-1.76-8.34-0.36-3.29-0.32-6.69 0.13-10.03 0.06-0.46 0.33-1.16-0.19-1.37-0.4-0.16-0.95-0.06-1.47 0.38-0.95 0.84-2.06 1.49-3.13 2.16-3.28 2.04-6.01 4.73-8.93 7.18-2.64 2.25-5.16 4.65-7.03 7.65-0.76 1.22-2.46 0.92-3.11-0.38-0.48-0.95-0.5-2.04-0.94-2.98-1.47-3.19-1.66-6.68-2.25-10.04-0.42-2.35-0.23-4.83-0.48-7.26-0.17-1.56-0.23-3.11-0.34-4.92-1.24 1.2-2.58 1.75-3.55 2.88-1.24 1.45-2.73 2.69-3.99 4.14-1.63 1.89-3.63 3.4-5.2 5.33-2.4 2.94-5.15 5.58-7.42 8.65-1.38 1.89-2.64 3.93-3.98 5.84-0.87 1.22-1.39 3.02-1.92 4.62-1.99 6.02-3.98 12.03-5.85 18.09-0.61 2-1.22 4.18-1.05 6.2 0.16 1.91 0.31 3.88 0.9 5.81 0.88 2.88 1.18 5.97 2.71 8.64 0.27 0.48-0.04 1.19 0.15 1.34 1.99 1.28 2.81 3.67 4.78 4.95 0.72 0.47-0.21 0.72-0.19 1.47l0.02 0.11zm67.38 176.7c2.99-0.48 5.95-0.94 8.93-1.43 2.69-0.42 5.2-1.36 7.62-2.56 0.78-0.38 1.55-0.99 1.55-2.2 0-3.42 0.26-6.87 0.4-10.27 0.15-3.13 0.13-6.26 0.25-9.38 0.17-4.08 0.59-8.15 0.61-12.25 0-2.62 0.53-5.25 0.4-7.85-0.12-2.67 0.09-5.33 0.06-8 0-2.9-0.2-5.81-0.12-8.73 0.08-2.21 0-4.43 0.11-6.64 0.1-2.94 0.5-5.83 1.21-8.69 0.19-0.73 0.11-1.13-0.8-1.11-1.88 0.04-3.8 0.08-5.69 0-3.67-0.17-7.28-0.86-10.89-1.58-3.05-0.59-6.01-1.51-9.01-2.26-2.25-0.57-4.41-1.41-6.68-1.94-1.15-0.27-2.52-0.96-3.74-1.59-1.42-0.76-1.86-0.38-1.86 1.28 0 0.88 0.08 1.76 0 2.62-0.84 7.65-0.68 15.37-1.39 23.04-0.4 4.22-0.9 8.42-1.34 12.64-0.38 3.61-0.97 7.22-1.12 10.87-0.04 1.03 0.05 2.14-0.31 3.07-0.51 1.32 0.1 2.66-0.46 3.99-0.23 0.52-0.09 1.4-0.19 2.12-0.3 1.99-0.86 4.11-0.13 5.98 0.61 1.51 0.11 2.67-0.19 3.95-0.25 1.11-0.69 2.18-1.11 3.23-0.25 0.63-0.13 1.22 0.48 1.3 1.6 0.19 2.19 1.52 3.19 2.44 2.33 2.12 4.9 4.01 7.58 5.67 3.07 1.89 5.78 4.6 9.87 4.26 0.91-0.08 1.87-0.21 2.84 0.04l-0.07-0.02zm24.55-133.89c1.26 2.22 3.8 2.73 5.86 3.5 2.01 0.78 4.11 1.62 6.28 2.15 2.87 0.71 5.75 1.05 8.65 0.75 1.7-0.17 3.46-0.12 5.12-0.75 0.67-0.26 1.45 0.04 1.81 0.79 0.42 0.86-0.24 1.18-0.87 1.47-0.35 0.17-0.73 0.3-1.07 0.51-0.94 0.57-2.1 0.04-2.94 0.48-2.12 1.11-4.34 0.97-6.55 0.69-3.44-0.42-6.63-1.82-9.89-3-0.44-0.17-1.15-1.07-1.47 0.11-0.29 1.05-1.42 2.37 0.17 3.17 3.05 1.55 6.38 2.1 9.74 2.2 2.67 0.09 5.36 0 8.03-0.31 1.28-0.15 2.58-0.19 3.86-0.13 1.53 0.06 2.29 1.11 1.85 2.29-0.36 0.97-1.18 0.67-1.85 0.65-2.86-0.06-5.73-0.1-8.59 0.19-0.9 0.08-1.6 0.46-1.57 1.2 0.02 0.63 0.81 0.94 1.59 1.09 2.58 0.48 5.13 0.48 7.75 0.23 5.86-0.55 11.63-1.47 17.39-2.65 0.69-0.14 1.26-0.52 1.97-0.69 2.44-0.55 4.93-0.9 7.14-2.2 0.44-0.26 0.99-0.3 1.28-0.13 1.45 0.86 2.62-0.17 3.61-0.73 1.93-1.1 4.07-1.66 5.96-2.86 0.93-0.59 1.94-1.41 2.98-1.55 1.75-0.24 3.13-1.31 4.75-1.81 1.81-0.57 3.57-1.72 5.4-2.56 2.39-1.07 4.62-2.52 7.01-3.63 1.03-0.49 2.27-0.93 3.05-1.58 1.63-1.38 3.65-2.12 5.29-3.44 1.76-1.45 3.9-2.35 5.71-3.78 1.26-1.01 1.82-2.6 3.21-3.47 1.05-0.65 1.7-1.61 2.16-2.73 1.45-3.48 2.31-7.13 3.03-10.81 0.58-2.96 1.4-5.92 1.26-8.98-0.07-1.37-0.57-2.8-0.42-4.04 0.21-1.67-1.07-2.7-1.05-4.2-1.05 1.79-2.23 3.36-3.34 5.02-0.51 0.76-1.35 1.39-1.51 2.33-0.36 2.19-1.92 3.61-3.34 4.94-1.72 1.59-3.99 2.6-5.82 4.11-1.62 1.35-3.42 2.52-4.87 4.05-0.9 0.97-2.12 0.78-3.05 1.39-2.09 1.35-4.15 2.73-6.34 3.95-2.87 1.62-5.81 3.17-8.69 4.81-1.7 0.96-3.53 1.76-5.35 2.54-1.51 0.63-2.98 1.72-4.54 2.39-3.69 1.62-7.43 3.09-11.32 4.2-3.59 1.03-3.65 1.13-6.93-0.04-0.98-0.36-2.03-0.36-3-0.93-2.54-1.51-5.27-2.7-7.87-4.13-0.88-0.49-1.79-1.37-2.54-1.58-1.83-0.52-3.21-1.74-4.85-2.47-2.29-1.01-4.6-1.83-7.18-1.75-0.44 0-0.8 0.15-0.7 0.47 0.3 0.79 0.55 1.82 1.18 2.26 1.37 0.97 2.77 1.89 4.18 2.82 2.81 1.86 6 3.04 8.8 4.97 1.23 0.84 1.09 1.83 0.69 2.86-0.44 1.11-1.41 0.52-2.12 0.31-1.98-0.57-4.14-0.84-6.03-0.69-2.62 0.21-4.85-0.82-7.2-1.28-2.23-0.44-4.24-1.93-6.34-2.94-1.7-0.8-3.36-1.68-5.25-2.02-0.59-0.1-3.15 0.99-3.42 1.45-0.15 0.23-0.07 0.42 0.1 0.49 1.05 0.39 1.7 1.34 2.63 1.91 1.13 0.71 2.58 0.67 3.65 1.36 2.25 1.47 4.64 2.67 7.06 3.82 2.77 1.35 5.52 2.67 8.73 2.48 1.93-0.13 3.88 0 5.84 0 0.33 0 0.75-0.25 0.92 0.4 0.13 0.5 0.27 1.03-0.08 1.41-0.42 0.44-1.01 0.58-1.64 0.58-1.51 0-3.02 0-4.51 0.09-4.33 0.29-8.24-1.03-11.87-3.15-3.08-1.83-6.17-3.13-9.68-1.85l-0.04-0.02zm-25.45 6.28c-1.32-0.55-2.73-0.3-3.88-0.26-2.06 0.11-4.16 0.47-6.22 0.32-2.43-0.19-4.91 0-7.14-1.62-1.17-0.84-2.5-1.68-3.88-2.12-1.64-0.52-0.53-1.57-0.59-2.24-0.04-0.53 0.97-0.74 1.66-0.26 1.13 0.78 2.39 1.66 3.57 2 1.91 0.56 3.71 1.66 5.86 1.57 3.5-0.17 7.03 0.25 10.52-0.56 1.89-0.45 3.61-1.41 5.41-1.89 1.37-0.36 0.89-1.6 1.75-1.94-0.76-0.42-1.56-0.73-2.46-0.58-0.04 0-0.08 0.06-0.13 0.06-3.12 0.34-6.25 0.76-9.38 0.99-4.37 0.33-8.61-0.51-12.68-1.96-1.24-0.44-2.88-0.06-3.7-1.57-0.23-0.44-0.78-0.8-0.25-1.28 0.44-0.42 0.94-1.05 1.64-0.78 1.42 0.55 2.96 0.72 4.36 1.24 5.11 1.91 10.31 1.81 15.6 1.11 2.17-0.29 4.29-0.75 6.35-1.36 2.03-0.59 4.11-1.32 5.79-2.77 0.44-0.38 0.88-0.72 0.63-1.37-0.29-0.67-0.76-1.19-1.55-1.21-1.7-0.05-3.38-0.07-5.04 0.52-2.88 1.03-5.9 1.53-8.93 1.68-3.67 0.19-7.22-0.63-10.56-2.27-0.94-0.46-2.14-1.07-2.01-2.24 0.08-0.78 1.17-1.16 2.03-1.39 0.19-0.04 0.36-0.19 0.55-0.23 0.84-0.25 1.62-0.51 2.33-1.13 1.03-0.89 1.89-1.89 2.88-2.82 1.26-1.17 2.73-2.2 3.48-3.8 0.27-0.59 1.28-1.05 0.84-1.7-0.61-0.88-1.76-0.73-2.73-0.63-0.67 0.06-1.3 0.48-1.97 0.65-1.41 0.38-2.52 1.3-3.82 1.89-0.53 0.23-1.12-0.23-1.3 0.13-0.78 1.38-2 1.89-3.47 2.35-1.11 0.35-2.35 0.71-3.32 1.36-1.57 1.07-3.36 1.49-5.04 2.23-0.84 0.35-1.8 0.35-2.64-0.04-2.88-1.37-5.78-2.69-8.53-4.29-3.27-1.91-6.42-4.07-9.59-6.15-2.82-1.85-5.52-3.88-8.42-5.54-3.11-1.76-5.99-3.84-8.76-6.01-2.52-1.97-5-4.07-7.39-6.25-0.75-0.7-1.36-1.54-1.97-2.4-0.34-0.46 0.35-0.77-0.17-1.15-1.95-1.41-2.63-3.66-3.42-5.75-0.61-1.58-1.1-3.17-1.18-4.9-0.02-0.58-0.44-1.34-1.22-1.28-0.69 0.07-1.21 0.49-1.42 1.3-0.8 3.26-1.54 6.49-1.56 9.89 0 2.17 0.06 4.39 0.3 6.47 0.27 2.44 0.6 4.96 1.23 7.37 0.51 1.97 1.29 3.88 2.44 5.58 1.74 2.55 3.97 4.69 6.11 6.89 2.23 2.29 4.64 4.39 6.99 6.57 2.42 2.23 5.27 3.87 7.79 5.95 1.16 0.96 2.5 1.7 3.74 2.54 1.74 1.21 3.86 2.05 5.56 3.31 2.59 1.87 5.74 2.65 8.13 4.77 1.32 1.18 3.02 0.94 4.56 1.36 2.1 0.59 3.88 2.06 6.02 2.67 2.06 0.59 3.61 2.14 5.61 2.92 1.36 0.52 2.92 0.69 4.07 1.72 0.82 0.74 1.2 0.71 1.35-0.52 0.08-0.78 0.48-1.79 1.42-1.75 0.95 0.05 1.91-0.08 2.9 0.17 2.5 0.63 5 1.32 7.6 1.39 2.21 0.04 4.37-0.53 5.21-3.01l0.04 0.05zM99.58 72.8c-1.12-0.71-1.51 0.53-2.27 0.82-2.18 0.91-4.16 2.21-6.22 3.32-1.11 0.61-0.75 1.39-0.08 1.78 0.99 0.57 1.79 1.39 2.79 1.94 2.19 1.21 4.48 2.16 6.81 3.06 2.41 0.95 4.76 2.04 7.2 2.94 1.91 0.69 1.95 0.59 2.66 1.97 0.36 0.7 0.34 0.66-0.18 1.05-0.34 0.28-0.76 0.26-1.05 0.82-0.97 1.98-1.83 3.99-2.99 5.88-1.07 1.77-2.2 3.3-3.99 4.45-0.88 0.57-2.09 0.78-2.47 2.02-0.7 2.22-1.22 4.41-0.93 6.8 0.4 3.15 2.14 6.68 5.69 7.35 2.59 0.48 4.92-0.17 7.33-0.46 2.58-0.32 5.5 1.4 5.78 3.59 0.29 2.31 0.86 4.58 2.26 6.53 0.53 0.73 0.57 1.55 0.63 2.46 0.13 1.61-0.29 3.25 0.23 4.89 0.44 1.36 0.55 2.85 0.72 4.28 0.23 2.2 1.32 2.96 3.25 1.87 1.64-0.95 3.15-0.46 4.62-0.02 1.89 0.57 2.27 0.48 2.98-1.39 0.82-2.16 1.39-4.47 3.68-5.77 0.42-0.23 1.05-0.78 0.94-1.83-0.37-3.65-0.12-7.26 2.38-10.29 1.11-1.36 2.14-2.77 3.02-4.3 0.84-1.47 1.15-1.66-0.84-2.29-1.3-0.42-2.44-1.05-2.98-2.27-0.44-0.96-0.36-1.8 0.57-2.79 0.98-1.05 1.57-1.81 2.87-1.17 1.11 0.54 1.95 0.73 2.52-0.66 0.09-0.2 0.29-0.46 0.5-0.52 1.54-0.55 0.59-1.22 0.13-1.89-0.4-0.55-0.9-0.92-1.57-1.07-1.37-0.32-2.08-1.26-2.48-2.5-0.84-2.6 1.11-4.85 3.8-4.51 1.28 0.16 2.39 0.58 3.63 1.59-0.46-2.04-1.62-3.38-2.35-4.91-0.17-0.36-0.71-0.42-0.84 0-0.61 2.18-2.73 1.49-4.12 2.14-0.96 0.46-1.86-0.59-2.56-1.34-1.05-1.14-1.07-2.5-0.77-3.91 0.37-1.76-0.42-3.57 0.25-5.29 0.4-1.01 0-1.57-0.74-2.12-2.66-1.93-5.67-3.23-8.52-4.83-0.69-0.38-1.03 0.11-1.16 0.4-0.48 1.13-1.34 1.24-2.33 1.05-0.52-0.11-0.98 0.15-1.42 0.19-1.12 0.06-2.1 0.94-3.41 0.08-1.66-1.09-1.05-2.69-1.21-4.03-0.19-1.51 1.15-3.61 2.05-3.63 1.47 0 3.07-0.06 4.27 0.94 2.2 1.85 4.51 1.14 7.09 0.61-0.67-0.52-0.94-1.07-1.78-0.92-0.74 0.15-1.43-0.32-1.91-0.93-0.68-0.86-1.28-1.74-1.93-2.6-0.51-0.67-0.99-1.01-1.81-0.25-0.67 0.63-1.6 0.97-2.37 1.51-1.66 1.16-3.7 1.05-5.52 1.66-1.12 0.38-1.31 0.9-0.95 1.87 0.61 1.61 0.31 2.96-1.18 3.99-0.63 0.42-1.23 0.86-1.78 1.36-1.13 1.01-2.31 1.09-3.55 0.23-0.57-0.4-1.26-0.58-1.72-1.17-0.29-0.38-0.78-0.59-1.2-0.3-0.46 0.32-0.23 0.86-0.08 1.24 0.52 1.43 1.87 2.25 2.79 3.38 0.57 0.7 0.38 1.58 1.05 2.19 0.21 0.21-0.59 0.75-1.15 0.82 0.16-1.29-1.41-0.24-1.7-1.33-0.21-0.75-1.39-1.22-1.96-1.93-1.36-1.74-2.66-3.55-1.17-5.9 0.12-0.19 0.29-0.42 0.04-0.65-4.94 0.21-5.94-0.42-5.23-3.34l-0.06 0.04zm10.96 82.2c-1.33-0.63-2.73-1.99-3.11-3.21-0.11-0.33-0.19-1.03 0.15-1.05 1.19-0.12 0.84-1.01 0.98-1.68 0.05-0.23 0-0.48 0.19-0.69 1.2-1.22 5.8-2.21 7.27-1.37 2.45 1.41 5.06 2.46 7.64 3.59 1.41 0.61 2.69 0.32 3.95-0.39 0.44-0.26 0.31-0.4-0.06-0.7-1.18-0.86-2.44-1.68-3.34-2.79-0.63-0.78-1.85-1.49-1.28-2.94 0.21-0.5-0.38-0.53-0.72-0.67-1.99-0.97-3.32-2.65-3.48-4.72-0.19-2.19-0.72-4.33-0.76-6.51-0.02-2.1 0.13-4.2-1.22-6.03-0.69-0.95-0.96-2.04-1.24-3.17-0.77-3.21-2.26-4.05-5.54-3.28-0.29 0.07-0.57 0.15-0.84 0.24-5.44 1.8-11.63-2.4-12.58-7.84-0.5-2.85-0.5-5.62 0.21-8.54-1.07 0.25-2.03 0.36-2.87 0.71-3.4 1.41-7.04 1.97-10.59 2.77-1.05 0.23-2.1 0.49-3.19 0.55-1.43 0.08-2.73 0.94-4.01 1.45-1.17 0.46-2.33 1.57-3.55 2.24-1.89 1.03-1.99 1.35-0.25 2.63 0.53 0.38 1.14 0.65 1.66 1.03 0.53 0.38 1.6 0.31 1.24 1.45 0 0.04 0.25 0.25 0.31 0.23 1.2-0.59 1.6 0.48 1.94 1.11 1.21 2.25 3.08 3.38 5.5 4.14 3.92 1.21 5.88 6.38 4.2 10.1-0.38 0.83-1.45 1.44-1.37 2.14 0.38 3.15-1.55 5.16-3.36 7.14-1.4 1.53-2.77 3.21-4.6 4.32-0.9 0.55-0.67 1.24 0.09 1.41 0.9 0.21 1.55 0.84 2.56 1.01 3.44 0.56 6.61-0.51 9.83-1.1 2.29-0.42 4.53-1.15 6.9-0.94 1.54 0.15 3.24 0.46 4.01 1.81 1.54 2.7 0.72 4.93-2.01 6.57-0.46 0.27-0.9 0.56-1.64 1.02 4.6 0.4 8.84 0.43 13.1-0.02l-0.12-0.02zm-1.39-107.2c1.16-1.49 0.65-3.38 1.39-4.98 0.56-1.26 1.36-2.6-0.51-3.55-0.08-0.04-0.14-0.12-0.16-0.21-0.74-2.33-1.89-4.43-3.32-6.4-0.99-1.39-2.56-1.26-3.8-0.08-1.01 0.96-1.47 2.24-2.52 3.21-2.31 2.1-3.72 2.6-6.6 1.13-2.07-1.05-3.75-0.73-5.35 0.88-1.2 1.22-2.37 2.46-3.82 3.38-0.99 0.65-1.91 1.58-3.17 1.58-1.45 0-2.92 0.29-4.35-0.13-0.56-0.17-0.82 0.11-1.03 0.63-0.5 1.26-0.69 2.65-0.82 3.91-0.16 1.7-1.26 3.61 0.32 5.27 0.21 0.23 0.34 0.56-0.11 0.69-0.69 0.19-0.56 0.74-0.58 1.22-0.07 2.94 0.54 5.77 1.21 8.63 0.38 1.61 1.31 1.15 2.02 0.71 3.13-1.95 6.53-3.27 9.97-4.53 3.03-1.12 6.09-2.08 9.07-3.32 2.13-0.88 4.39-1.79 6.79-0.86 1.21 0.46 2.47 0.21 3.71 0.29 0.42 0.02 0.89-0.08 0.93-0.56 0.14-1.89 0.25-3.78 0.4-5.88-3.49 3-7.25 2.7-11.09 1.72-0.55-0.15-1.11-0.72-0.88-1.39 0.19-0.63 0.31-1.55 1.09-1.64 1.34-0.16 2.73-0.14 4.09-0.1 1.6 0.04 3.09 0.15 3.89-1.72 0.25-0.59 0.94-1.66 1.87-0.93 0.86 0.7 2.1 1.43 1.36 3.03zM78.66 295.97c-1.05 0.51-1.76 0.42-2.43-0.04-0.27-0.19-0.76-0.51-0.88-0.21-0.23 0.61-0.57 1.7-0.46 1.89 0.77 1.38-0.11 2.66 0 3.97 0.12 1.74-0.36 3.61 1.15 5.08 0.42 0.42 0.99 0.48 1.39 0.92 1.19 1.32 2.39 2.67 3.77 3.8 1.66 1.37 3.24 2.84 4.92 4.2 1.26 1.01 2.14 1.41 4.22 0.34 0.57-0.3 0.92-0.36 0.46-1.26-0.55-1.03-0.94-2.21-1.3-3.36-0.59-1.93-0.51-3.93 0.67-5.59 1.13-1.57 2.67-2.75 4.45-3.65 0.82-0.42 2.42 0.08 2.42-1.16 0-0.94-0.93-1.86-1.43-2.81-0.13-0.21-0.23-0.44-0.34-0.65-0.5-0.99-1.21-1.2-2.33-0.92-1.53 0.35-3.08 0.63-4.7 0.33-1.26-0.21-2.5 0.26-3.63 0.78-1.05 0.48-2.08 0.92-3.2 1.24-1.26 0.38-2.3 1.36-2.89-0.86-0.19-0.67-0.59-1.16 0.12-2.02l0.02-0.02zm13.63-234c2.69-0.06 4.96 0.06 7.27-0.27 2.03-0.28 4.15-0.78 6.23-0.09 1.43 0.49 2.94 1.03 3.32 2.69 0.44 1.91-0.42 3.28-2.33 4.37-1.03 0.61-2.33 0.69-3.38 1.85 1.53-0.26 2.69-0.07 3.38 1.28 0.67 1.34-0.21 2.41-0.67 3.69 1.64-0.12 2.89 0.44 3.95 1.43 0.69 0.65 1.65 1.13 2.22 0.52 0.63-0.67 1.76-1.15 1.49-2.6-0.57-3.04 0.78-5.21 3.82-5.44 3.03-0.23 5.29-2.52 8.46-2.41 1.91 0.06 3.43 0 4.04 2.01 0.81 2.63 3.23 2.27 4.95 3.07 1.09 0.5 1.76-1.03 2.86-1.39-0.55-0.46-0.99-0.77-1.35-1.17-0.4-0.42-0.96-0.44-1.42-0.78-4.67-3.21-9.58-5.9-15.25-6.8-5.12-0.8-10.2-1.98-15.41-1.98-3.99 0-8.04-0.06-12.18 2v0.02zm-7.62 67.94c0-1.07 0.21-2.01-0.04-2.83-0.4-1.28-0.63-2.65-2.52-3-2.92-0.57-5.31-2.17-6.68-4.94-0.4-0.82-0.94-1.4-1.7-1.78-1.76-0.88-3.51-1.75-4.75-3.34-0.39-0.51-0.73-0.44-1.02 0.06-1.08 1.83-2.21 3.66-2.8 5.71-0.42 1.49-0.08 2 1.47 2.23 0.36 0.06 0.63 0.21 0.95 0.44 1.53 1.03 1.22 2.69 1.3 3.99 0.17 2.22 0.73 4.2 1.91 6.04 0.32 0.49 0.61 1.03 0.71 1.58 0.15 0.67 0.26 0.88 0.8 0.53 1.64-1.08 3.36-1.85 5.25-2.36 1.89-0.5 3.78-0.9 5.65-0.23 1.24 0.44 1.53-0.04 1.45-1.09-0.04-0.4-0.09-0.78 0-0.99l0.02-0.02zm60.58 4.47c0.54-1.21 1.42-2.18 2.05-3.31 1.43-2.61 2.8-5.19 3.7-8.06 1.26-4.01 1.49-7.88 0.06-11.8-0.19-0.55-0.16-1.1-0.25-1.62-0.5-3.91-1.72-7.39-4.89-10.08-0.86-0.73-1.22 0.23-1.81-0.04-0.25-0.11-0.63 0.31-0.54 0.73 0.1 0.53 0.23 1.05 0.86 1.26 1.47 0.49 2.52 1.47 3.36 2.8 0.77 1.23 0.86 4.11-0.21 4.62-1.16 0.52-1.96 1.38-2.82 2.16-1.17 1.09-2.16-0.25-3.27-0.23-0.11 0.96 0.58 0.86 1.15 1.05 2.21 0.71 3.47 1.84 2.75 4.6-0.48 1.82-1.66 3.21-2.73 4.57-2.01 2.56-3.4 5.21-3 8.55 0.15 1.21-0.19 2.39-0.34 3.59-0.04 0.25-0.44 0.52-0.04 0.77 1.22 0.74 1.24 1.64 0.53 2.76-0.21 0.31-0.07 0.67 0.46 1.07 0.86-2.12 2.44-3.91 2.48-6.49-0.8 0.4-1.3 0.9-2.08 0.75 0.49-1.1 0.29-1.65-0.61-1.63 0.63-1.96 2.56-1.43 3.4-1.1 2.19 0.86 1.74 3.13 1.81 5.08h-0.02zm-50.63-71.3c-0.4 1.68-1.45 1.89-2.52 1.87-2.66-0.06-4.62 1.26-6.36 3.09-0.23 0.23-0.48 0.59-0.13 0.69 1.24 0.36 0.26 1.03 0.24 1.51-0.03 0.38-0.26 0.63 0.12 1.03 0.8 0.86 1.22 1.95 1.16 3.15-0.02 0.61 0.25 0.84 0.73 1.13 0.63 0.4 0.76-0.14 1.07-0.4 0.61-0.44 1.18-0.94 1.83-1.3 3.06-1.66 6.15-3.31 9.26-4.89 1.64-0.84 3.09-2.08 4.87-2.58 0.8-0.23 1.55-0.57 1.51-1.34-0.04-0.93-1.03-0.89-1.74-1.03-2.06-0.4-4.01 0.5-6.03 0.46-1.36-0.02-2.9 0.5-3.99-1.39h-0.02zm5.86 273.98c1.03 0.04 2.06 0.11 3.07 0.13 0.77 0 1.59-0.13 2.31 0.33 0.27-0.82 1.68-0.92 1.42-2.03-0.21-0.88-0.88-1.26-1.8-1.41-1.93-0.32-3.89-0.25-5.82-0.53-2.39-0.31-4.26-1.76-6.36-2.58-1.87-0.73-3.7-2.04-5.5-3.19-1.58-0.99-3.45-1.6-4.79-2.81-1.85-1.68-3.72-3.3-5.77-4.73-0.23-0.16-0.59-0.14-0.65-0.52-0.05-0.27 0-0.72-0.4-0.67-0.36 0.04-0.42 0.37-0.47 0.77-0.14 1.47 0.34 2.78 1.03 3.95 0.8 1.34 2.52 1.78 3.45 3.05 1.38-0.97 1.17 0.52 1.43 1.02 0.44 0.89 1.38 0.55 2.01 1.09 1.11 0.97 2.5 2.25 3.78 2.25 1.57 0.02 1.74 2.17 3.32 1.58 1.45 1.97 4.01 2.14 5.81 3.5 1.24 0.95 2.59 0.84 3.97 0.76l-0.04 0.04zm22.42-46.8c1.01 0.46 1.83 1.05 2.44 1.97 0.69 1.03 1.99 1.33 2.98 2 1.85 1.26 3.74 2.45 5.65 3.65 0.23 0.15 0.69 0.7 0.8 0.17 0.15-0.76 0.77-1.16 0.99-1.81 0.92-2.72 2.89-4.26 5.69-4.72 0.84-0.13 1.28-0.31 0.65-1.2-0.26-0.35-0.44-0.77-0.67-1.15-0.47-0.76-0.91-1.03-1.85-0.48-1.37 0.77-5.92 1.63-6.83 1.53-3.23-0.36-6.49-0.11-9.87 0.04h0.02zm37.32 27.04c-0.38-0.14-0.59-0.02-0.82 0.09-2.27 1.03-4.77 1.59-7.14 1.47-2.16-0.13-4.37 0.12-6.61-0.53-2.23-0.63-4.58-1.03-6.81-1.8-0.96-0.34-1.87-1.37-2.64-1.3-1.77 0.14-2.57-1.27-3.76-1.9-2.19-1.11-4.01-2.89-5.99-4.38-0.23-0.17-0.48-0.51-0.75-0.28-0.34 0.3-0.02 0.61 0.08 0.93 1.01 2.77 3.26 4.32 5.57 5.83 0.88 0.59 1.91 0.66 2.85 1.14 2.1 1.05 4.12 2.29 6.47 2.79 2.12 0.44 4.16 1.18 6.26 1.68 1.51 0.38 3.06 0.72 4.61 0.92 0.84 0.13 1.83 0.21 2.53-0.12 1.78-0.9 3.4-2.14 5.16-3.11 0.61-0.34 0.95-0.67 0.99-1.43zM86.94 63.52c-2.96 0.44-5.36 1.91-7.92 2.98-0.34 0.15-0.92 0.09-0.94 0.59 0 0.51 0.37 0.82 0.86 0.99 1.47 0.5 2.54 1.53 3.57 2.62 0.25 0.28 0.44 0.65 0.96 0.68 0-3.11 0-6.22 3.45-7.88l0.02 0.02zm50.26 72.06c-0.25 0.13-0.44 0.15-0.52 0.25-1.22 1.64-1.36 3.78-2.52 5.44-0.13 0.17 0 0.49 0.19 0.49 1.03 0.04 1.57 0.92 2.39 1.28 0.44 0.2 1.05 0.35 1.51-0.42 0.4-0.66 1.24-1.03 2.02-1.62-2.81-1.11-3.09-3.13-3.09-5.44l0.02 0.02zm3.15-49.25c0.65 1.97-0.48 3.61-0.1 5.33 0.29 1.34 1.13 2.01 2.29 1.57 0.9-0.33 1-1.95 0.84-2.16-1.14-1.41-0.86-3.61-3.01-4.77l-0.02 0.03zm3.57-10.92c-0.67-1.37-1.93-1.96-3.04-2.75-0.53-0.38-0.9-0.86-1.43-0.17-0.44 0.59-1.57 0.71-1.51 1.49 0.1 1.01 1.05 0.17 1.6 0.38 0.62 0.27 1.34 0.38 1.99 0.63 0.69 0.27 1.36 0.63 2.41 0.42h-0.02zm-17.84 1.55c-0.95-1.2-2.15-1.55-3.15-1.95-0.8-0.32-1.12 0.82-1.24 1.49-0.11 0.54 0.14 0.8 0.96 0.94 1.26 0.23 2.08-0.69 3.43-0.46v-0.02zm-50.65 92.95c-1.43-0.42-2.64-0.69-3.8-1.15-0.46-0.19-0.92-0.11-1.05 0.12-0.21 0.38 0.19 0.65 0.57 0.84 1.34 0.65 2.73 0.65 4.28 0.19zm54.26-17.15c0.96 0.14 1.91 0.25 2.81 0.46 0.34 0.08 0.61 0.13 0.76-0.17 0.14-0.34-0.23-0.34-0.42-0.48-1.35-1.14-1.79-1.11-3.17 0.19h0.02zm-64.86-28.22c0.42 1.17 0.59 2.41 1.42 3.59 0.21-3.15 0.07-3.51-1.42-3.59z" android:fillColor="#000000"/> - <path android:pathData="M120.66 89.29c0.25-1.35 2.31-1.96 3.63-0.89 0.86 0.7 1.35 0.76 2.29 0.15 1.16-0.73 2.43-0.88 3.57 0.44 0.99 1.16 2.6 1.66 3.53 2.96 1.36 1.93 1.19 3.05-0.95 4.03-2.29 1.05-4.62 0.99-6.8-0.48-1.01-0.69-2.06-1.11-3.36-0.71-2.23 0.65-4.1 0.04-5.4-1.98-0.48-0.77-1.09-1.07-2.01-0.82-0.97 0.28-1.87 0.19-2.42-0.88-0.48-0.96-0.29-1.72 0.55-2.37 0.5-0.4 0.29-1.01 0.4-1.53 0.21-1.12 0.44-2.29 1.7-2.73 1.05-0.38 2.25-0.23 2.85 0.59 0.95 1.3 1.98 2.58 2.44 4.24l-0.02-0.02zm9.15 4.59c0.53-0.04 1.31 0.21 1.51-0.35 0.22-0.57-0.58-0.82-0.96-1.2-0.34-0.36-0.84-0.55-1.2-0.88-1.11-0.99-1.91-0.15-2.79 0.4-0.55 0.33-0.61 0.65-0.04 0.9 1.11 0.5 2.14 1.32 3.5 1.11l-0.02 0.02zm-10.58-2.91c0.69 1.55 2.69 1.78 5.42 0.65-1.45-2.12-3.51-0.63-5.42-0.65zm-0.8-0.76c0.53-1.87-1.53-1.93-1.93-3.11-0.52 1.83 0.82 2.37 1.93 3.11zM81.5 55.57c-1.13-0.38-2.52 0.25-3.68-0.84-0.65-0.61-1.36-1.12-1.09-2 0.38-1.17 1.56-1.34 2.52-1.03 1.79 0.57 3.51 0.28 5.21-0.14 0.69-0.17 1.41-0.51 1.99-0.93 1.6-1.15 2.27-1.15 3.15 0.21 0.61 0.93-0.06 2.54-1.36 3.3-2.08 1.22-4.37 1.28-6.76 1.45l0.02-0.02z" android:fillColor="#000000"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_onion_pattern.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_onion_pattern.xml new file mode 100644 index 0000000000000000000000000000000000000000..3aa3b9493fa5e4ccd9bad6cd450fd36f11f9cbb4 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/ic_onion_pattern.xml @@ -0,0 +1,806 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="778dp" + android:height="243dp" + android:viewportWidth="778" + android:viewportHeight="243"> + <path + android:pathData="M122.853,121m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M122.353,120.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M122.353,120.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M122.353,120.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M250.853,202m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M250.353,201.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M251.353,202.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M250.353,201.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M325.853,41m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M325.353,41.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M325.353,41.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M325.353,41.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M579.853,202m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M579.353,201.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M580.353,202.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M579.353,201.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M653.853,41m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M653.353,41.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M654.353,41.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M653.353,41.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M452.853,121m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M453.353,120.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M453.353,120.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M453.353,120.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M415.853,202m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M415.353,201.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M415.353,202.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M415.353,201.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M489.853,41m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M490.353,41.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M490.353,41.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M490.353,41.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M618.853,121m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M618.353,120.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M618.353,120.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M618.353,120.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M86.853,202m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M86.353,201.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M87.353,202.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M86.353,201.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M159.853,41m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M159.353,41.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M160.353,41.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M159.353,41.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M286.853,121m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M287.353,120.5m-29.5,0a29.5,29.5 0,1 1,59 0a29.5,29.5 0,1 1,-59 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M287.353,120.5m-20.5,0a20.5,20.5 0,1 1,41 0a20.5,20.5 0,1 1,-41 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M287.353,120.5m-11.5,0a11.5,11.5 0,1 1,23 0a11.5,11.5 0,1 1,-23 0" + android:strokeAlpha="0.1" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M332.853,241C354.392,241 371.853,223.539 371.853,202C371.853,180.461 354.392,163 332.853,163C311.314,163 293.853,180.461 293.853,202C293.853,223.539 311.314,241 332.853,241Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M333.353,231C349.645,231 362.853,217.792 362.853,201.5C362.853,185.208 349.645,172 333.353,172C317.061,172 303.853,185.208 303.853,201.5C303.853,217.792 317.061,231 333.353,231Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M333.353,223C344.675,223 353.853,213.822 353.853,202.5C353.853,191.178 344.675,182 333.353,182C322.031,182 312.853,191.178 312.853,202.5C312.853,213.822 322.031,223 333.353,223Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M333.353,213C339.704,213 344.853,207.851 344.853,201.5C344.853,195.149 339.704,190 333.353,190C327.002,190 321.853,195.149 321.853,201.5C321.853,207.851 327.002,213 333.353,213Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M407.853,80C429.392,80 446.853,62.539 446.853,41C446.853,19.461 429.392,2 407.853,2C386.314,2 368.853,19.461 368.853,41C368.853,62.539 386.314,80 407.853,80Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M407.353,71C423.645,71 436.853,57.792 436.853,41.5C436.853,25.208 423.645,12 407.353,12C391.061,12 377.853,25.208 377.853,41.5C377.853,57.792 391.061,71 407.353,71Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M408.353,62C419.675,62 428.853,52.822 428.853,41.5C428.853,30.178 419.675,21 408.353,21C397.031,21 387.853,30.178 387.853,41.5C387.853,52.822 397.031,62 408.353,62Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M407.353,53C413.704,53 418.853,47.851 418.853,41.5C418.853,35.149 413.704,30 407.353,30C401.002,30 395.853,35.149 395.853,41.5C395.853,47.851 401.002,53 407.353,53Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M74.853,81C96.392,81 113.853,63.539 113.853,42C113.853,20.461 96.392,3 74.853,3C53.314,3 35.853,20.461 35.853,42C35.853,63.539 53.314,81 74.853,81Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M74.353,71C90.645,71 103.853,57.792 103.853,41.5C103.853,25.208 90.645,12 74.353,12C58.061,12 44.853,25.208 44.853,41.5C44.853,57.792 58.061,71 74.353,71Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M75.353,63C86.675,63 95.853,53.822 95.853,42.5C95.853,31.178 86.675,22 75.353,22C64.031,22 54.853,31.178 54.853,42.5C54.853,53.822 64.031,63 75.353,63Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M74.353,53C80.704,53 85.853,47.851 85.853,41.5C85.853,35.149 80.704,30 74.353,30C68.002,30 62.853,35.149 62.853,41.5C62.853,47.851 68.002,53 74.353,53Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M661.853,241C683.392,241 700.853,223.539 700.853,202C700.853,180.461 683.392,163 661.853,163C640.314,163 622.853,180.461 622.853,202C622.853,223.539 640.314,241 661.853,241Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M662.353,231C678.645,231 691.853,217.792 691.853,201.5C691.853,185.208 678.645,172 662.353,172C646.061,172 632.853,185.208 632.853,201.5C632.853,217.792 646.061,231 662.353,231Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M662.353,223C673.675,223 682.853,213.822 682.853,202.5C682.853,191.178 673.675,182 662.353,182C651.031,182 641.853,191.178 641.853,202.5C641.853,213.822 651.031,223 662.353,223Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M662.353,213C668.704,213 673.853,207.851 673.853,201.5C673.853,195.149 668.704,190 662.353,190C656.002,190 650.853,195.149 650.853,201.5C650.853,207.851 656.002,213 662.353,213Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M736.853,80C758.392,80 775.853,62.539 775.853,41C775.853,19.461 758.392,2 736.853,2C715.314,2 697.853,19.461 697.853,41C697.853,62.539 715.314,80 736.853,80Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M736.353,71C752.645,71 765.853,57.792 765.853,41.5C765.853,25.208 752.645,12 736.353,12C720.061,12 706.853,25.208 706.853,41.5C706.853,57.792 720.061,71 736.353,71Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M737.353,62C748.675,62 757.853,52.822 757.853,41.5C757.853,30.178 748.675,21 737.353,21C726.031,21 716.853,30.178 716.853,41.5C716.853,52.822 726.031,62 737.353,62Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M736.353,53C742.704,53 747.853,47.851 747.853,41.5C747.853,35.149 742.704,30 736.353,30C730.002,30 724.853,35.149 724.853,41.5C724.853,47.851 730.002,53 736.353,53Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M496.853,241C518.392,241 535.853,223.539 535.853,202C535.853,180.461 518.392,163 496.853,163C475.314,163 457.853,180.461 457.853,202C457.853,223.539 475.314,241 496.853,241Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M497.353,231C513.645,231 526.853,217.792 526.853,201.5C526.853,185.208 513.645,172 497.353,172C481.061,172 467.853,185.208 467.853,201.5C467.853,217.792 481.061,231 497.353,231Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M497.353,223C508.675,223 517.853,213.822 517.853,202.5C517.853,191.178 508.675,182 497.353,182C486.031,182 476.853,191.178 476.853,202.5C476.853,213.822 486.031,223 497.353,223Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M497.353,213C503.704,213 508.853,207.851 508.853,201.5C508.853,195.149 503.704,190 497.353,190C491.002,190 485.853,195.149 485.853,201.5C485.853,207.851 491.002,213 497.353,213Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M571.853,80C593.392,80 610.853,62.539 610.853,41C610.853,19.461 593.392,2 571.853,2C550.314,2 532.853,19.461 532.853,41C532.853,62.539 550.314,80 571.853,80Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M572.353,71C588.645,71 601.853,57.792 601.853,41.5C601.853,25.208 588.645,12 572.353,12C556.061,12 542.853,25.208 542.853,41.5C542.853,57.792 556.061,71 572.353,71Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M572.353,62C583.675,62 592.853,52.822 592.853,41.5C592.853,30.178 583.675,21 572.353,21C561.031,21 551.853,30.178 551.853,41.5C551.853,52.822 561.031,62 572.353,62Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M572.353,53C578.704,53 583.853,47.851 583.853,41.5C583.853,35.149 578.704,30 572.353,30C566.002,30 560.853,35.149 560.853,41.5C560.853,47.851 566.002,53 572.353,53Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M204.853,160C226.392,160 243.853,142.539 243.853,121C243.853,99.461 226.392,82 204.853,82C183.314,82 165.853,99.461 165.853,121C165.853,142.539 183.314,160 204.853,160Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M204.353,150C220.645,150 233.853,136.792 233.853,120.5C233.853,104.208 220.645,91 204.353,91C188.061,91 174.853,104.208 174.853,120.5C174.853,136.792 188.061,150 204.353,150Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M205.353,141C216.675,141 225.853,131.822 225.853,120.5C225.853,109.178 216.675,100 205.353,100C194.031,100 184.853,109.178 184.853,120.5C184.853,131.822 194.031,141 205.353,141Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M204.353,132C210.704,132 215.853,126.851 215.853,120.5C215.853,114.149 210.704,109 204.353,109C198.002,109 192.853,114.149 192.853,120.5C192.853,126.851 198.002,132 204.353,132Z" + android:strokeAlpha="0.1" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1" + android:strokeLineCap="round"/> + <path + android:pathData="M740.853,81C740.853,103.091 723.168,121 701.353,121C679.538,121 661.853,103.091 661.853,81L661.853,81Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:fillAlpha="0.020000001" + android:fillType="evenOdd" + android:strokeColor="#00000000"/> + <path + android:pathData="M740.853,121C740.853,143.091 723.168,161 701.353,161C679.538,161 661.853,143.091 661.853,121L661.853,121Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M207.853,162C207.853,184.091 190.168,202 168.353,202C146.538,202 128.853,184.091 128.853,162L128.853,162Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:fillAlpha="0.020000001" + android:fillType="evenOdd" + android:strokeColor="#00000000"/> + <path + android:pathData="M207.853,202C207.853,224.091 190.168,242 168.353,242C146.538,242 128.853,224.091 128.853,202L128.853,202Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M281.853,2C281.853,24.091 264.168,42 242.353,42C220.538,42 202.853,24.091 202.853,2L202.853,2Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M281.853,43C281.853,65.091 264.168,83 242.353,83C220.538,83 202.853,65.091 202.853,43L202.853,43Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:fillAlpha="0.020000001" + android:fillType="evenOdd" + android:strokeColor="#00000000"/> + <path + android:pathData="M575.853,117C575.853,94.909 558.168,77 536.353,77C514.538,77 496.853,94.909 496.853,117L496.853,117Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M575.853,158C575.853,135.909 558.168,118 536.353,118C514.538,118 496.853,135.909 496.853,158L496.853,158Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:fillAlpha="0.020000001" + android:fillType="evenOdd" + android:strokeColor="#00000000"/> + <path + android:pathData="M79.853,121C79.853,98.909 62.168,81 40.353,81C18.538,81 0.853,98.909 0.853,121L0.853,121Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M79.853,161C79.853,138.909 62.168,121 40.353,121C18.538,121 0.853,138.909 0.853,161L0.853,161Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#00000000" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> + <path + android:pathData="M329.353,81.5C351.444,81.5 369.353,99.185 369.353,121C369.353,142.815 351.444,160.5 329.353,160.5L329.353,160.5Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:fillAlpha="0.020000001" + android:fillType="evenOdd" + android:strokeColor="#00000000"/> + <path + android:pathData="M370.353,81.5C392.444,81.5 410.353,99.185 410.353,121C410.353,142.815 392.444,160.5 370.353,160.5L370.353,160.5Z" + android:strokeAlpha="0.1" + android:strokeWidth="1" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:fillType="evenOdd" + android:fillAlpha="0.1"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_pocket.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_pocket.xml deleted file mode 100644 index f2e00d1929f78acf133d34114beea6dc5b5bafcf..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_pocket.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:fillColor="#EF4056" - android:pathData="M21.7684 2H2.31579C1.05263 2 0 2.95079 0 4.19094V11.2598C0 17.6673 5.38947 23 12.0421 23C18.6526 23 24 17.6673 24 11.2598V4.19094C24 2.95079 22.9895 2 21.7684 2Z" /> - <path - android:fillColor="#FFFFFF" - android:pathData="M18.5749 10.9349L13.0682 16.52C12.7848 16.8691 12.3394 17 12.0154 17C11.6105 17 11.2056 16.8691 10.8817 16.52L5.45602 10.9349C4.88916 10.2804 4.80818 9.18956 5.45602 8.49142C6.06337 7.88055 7.07563 7.79328 7.68298 8.49142L12.0154 12.9857L16.4289 8.49142C16.9957 7.79328 18.008 7.88055 18.5749 8.49142C19.1417 9.18956 19.1417 10.2804 18.5749 10.9349Z" /> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_scan.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_scan.xml deleted file mode 100644 index 47fffd545f3488695516847fa90f873dc064de60..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_scan.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="187dp" android:height="171dp" android:viewportWidth="187" android:viewportHeight="171"> - <path android:pathData="M17 11.5L20 7l5.5-2.5h36l55-1L149 5l0.5 21v34.5L127 62l-2.5 5.5V98h-102L18 91.5V53l-1-41.5z" android:fillColor="#592ACB" android:fillAlpha="0.3"/> - <path android:pathData="M58.93 31.45l2.37-5.67h49.09V72l-1.97 6.45H61.3l-2.37-4.74V31.45zm72.72 37.79l7.48-1.58 0.92 5.26h23.5L166.7 72l0.92-4.34h4.2l4.46 1.58 1.45 9.21-1.45 14.36 2.37 38.31-0.92 24.76-1.45 5.53-4.46 2.5h-42V78.45l1.83-9.21z"> - <aapt:attr name="android:fillColor"> - <gradient android:startX="58.93" android:startY="25.78" android:endX="178.65" android:endY="25.78" android:type="linear"> - <item android:offset="0" android:color="#FF9059FF"/> - <item android:offset="0.52" android:color="#FFFF4AA2"/> - <item android:offset="1" android:color="#FFFFBD4F"/> - </gradient> - </aapt:attr> - </path> - <path android:pathData="M4.68 99.37c0-1.03 0.67-1.11 1.29-1.09 1.75 0.1 3.34-0.55 4.99-0.88 1.18-0.24 2.21-1.11 3.37-1 1 0.1 1.75-0.47 2.64-0.51 1.1-0.06 0.66-0.79 0.38-1-0.83-0.57-0.83-1.43-0.9-2.22-0.28-3.21-0.35-6.41-0.28-9.62 0.06-2.28 0.02-4.58 0.04-6.87 0-1.73-0.39-3.59 0.09-5.17 0.7-2.3 0.41-4.55 0.41-6.82 0-3.57-0.28-7.14-0.37-10.72-0.04-1.84 0.17-3.66 0.28-5.5 0.16-2.99 0.05-5.95 0.05-8.92 0-3.13 0.06-6.26 0.08-9.41 0-0.6 0.47-1.53-0.89-1.29-0.31 0.06-0.22-0.44-0.2-0.62 0.13-1.09-0.24-2.25 0.24-3.24 0.9-1.85-0.22-3.67 0.18-5.51 0.48-2.14-0.2-4.33-0.02-6.48 0.15-1.79-0.01-3.61 1.04-5.36 0.49-0.83 0.59-1.97 1.49-2.67 0.7-0.54 1.62-0.59 2.35-0.7 3.5-0.57 6.98-1.31 10.59-1.13 2.56 0.13 5.16-0.16 7.74-0.22 2.38-0.03 4.77 0.08 7.15 0 2.57-0.09 5.12 0.43 7.71 0.26 2.3-0.15 4.62 0.33 6.93 0.35 1.65 0.02 3.31-0.28 4.97-0.5 1.79-0.24 3.61-0.29 5.4-0.14 3.92 0.29 7.82-0.15 11.73-0.17 2.82 0 5.63-0.09 8.4 0.2 2.21 0.24 4.4 0.02 6.59 0.21 1.27 0.11 2.41-0.37 3.66-0.3 3.52 0.22 7.04-0.39 10.56-0.31 2.24 0.03 4.51 0.05 6.77 0.16 1.29 0.06 2.64 0.06 3.96-0.09 1.4-0.15 2.82-0.46 4.26 0.02 0.55 0.18 1.12-0.29 1.79-0.26 2.22 0.13 4.45 0.26 6.68 0.13 2.58-0.15 5.16-0.16 7.74-0.11 1.41 0.04 2.81 0.24 4.19 0.88 0.7 0.34 1.68 0.21 2.42 0.74 0.66 0.48 1.19 1.03 1.12 1.95-0.24 2.88 0.74 5.66 0.59 8.53-0.06 1.22-0.11 2.43-0.13 3.65-0.07 2.91 0.09 5.84-0.26 8.74-0.18 1.52 0.11 3.08-0.16 4.52-0.39 2.04 0.26 4.05-0.11 6.04-0.24 1.32 0.22 2.56 0.07 3.85-0.15 1.34-0.24 2.69-0.26 4.03-0.02 1.4 0.06 2.8 0.09 4.18 0.06 2.76 0.24 5.53 0.11 8.29-0.07 1.45 0.61 1.64 1.66 1.64 6.93-0.04 13.85-0.13 20.78-0.06 1.8 0.02 3.57 0.7 5.06 1.84 0.2 0.17 0.39 0.39 0.63 0.48 2.37 0.8 3.5 2.58 3.76 4.92 0.22 2.01 1.06 3.92 1.16 5.89 0.12 2.82 0.27 5.64 0.27 8.46 0 2.28 0.06 4.6 0.11 6.89 0.11 5.59-0.07 11.19-0.55 16.77-0.13 1.38 0 2.8 0.05 4.2 0.08 2.47 0.24 4.96 0.26 7.42 0.02 3.98 0.06 7.96-0.09 11.92-0.11 2.62 0.06 5.23 0.02 7.85-0.02 2.28-0.15 4.56-0.17 6.83-0.03 2.74 0.19 5.49 0.21 8.21 0.01 2.54-0.35 5.05-0.61 7.57-0.11 1.05-0.15 2.1-0.24 3.15-0.37 4.27-3.87 5.75-7.26 6.15-3.28 0.41-6.59 0.56-9.89 0.67-1.1 0.03-2.19 1.03-3.3-0.04-1.47 1.47-3.27 0.35-4.89 0.64-1.57 0.3-3.13-0.11-4.66-0.03-2.56 0.11-5.09 0-7.63-0.11-0.26 0-0.59 0.11-0.68-0.23-0.42-1.52-1.1-0.64-1.66-0.14-0.49 0.46-0.88 0.7-1.34 0-0.11-0.17-0.26-0.06-0.41-0.06-0.95 0-1.91 0.92-2.87 0-0.26-0.26-0.68-0.18-1.01-0.05-2.75 1.05-5.47 0.75-8.18-0.06-3.22-0.96-4.01-3.87-4.92-6.54-1.43-4.27-0.97-8.74-1.08-13.15-0.04-1.75-0.45-3.53-0.22-5.25 0.18-1.36-0.21-2.67 0.09-4.06 0.22-1.02-0.17-2.31-0.09-3.43 0.09-1.6 0.14-3.22 0.27-4.81 0.11-1.53 0.04-3.2-0.09-4.8-0.18-2.23-0.09-4.44 0.09-6.67 0.09-1.14 0-2.28-0.02-3.41-0.03-1.71 0-3.42 0.17-5.14 0.07-0.73-0.11-1.08-0.89-1.03-3.95 0.26-7.91-0.2-11.87 0.2-1.31 0.13-2.69-0.33-4.02-0.25-1.67 0.09-3.37 0.07-5.01 0.09-1.62 0-3.29-0.07-4.95-0.09-4.57-0.06-9.12-0.04-13.69-0.19-1.84-0.05-3.68 0.15-5.5 0-3.28-0.26-6.56 0.06-9.84-0.03-2.58-0.08-5.15 0.05-7.73-0.04-3.54-0.13-7.07 0.07-10.59-0.04-3.24-0.11-6.48-0.03-9.73-0.07-3.16-0.04-6.31-0.04-9.48-0.06-4.18-0.02-8.36-0.22-12.54-0.03-3.3 0.14-6.61 0.16-9.91 0.35-0.7 0.03-1.47 0.07-2.21-0.37-0.79-0.48-1.73 0.16-2.6-0.02-1.03-0.22-1.08-0.87-0.88-1.9 0.22-1.08-0.06-2.28-0.2-3.4-0.15-1.13-0.59-2.2-0.47-3.38 0.15-1.14 1.07-1.32 1.88-1.69 0.52-0.24 0.8 0 0.96 0.63l-0.02-0.04zm94.48-2.14c0.33-2.02 1.53-0.53 2.36-0.7 0.2-0.03 0.31 0.5 0.46 0.26 0.7-1.09 1.42-0.22 2.12-0.07 0.16 0.03 0.31 0.09 0.48 0.13 0-0.08 0-0.15-0.04-0.21-0.48-0.71 0.15-0.44 0.4-0.44 1.44-0.03 2.88 0.26 4.33-0.03 1.72-0.37 3.45-0.39 5.2-0.32 2.41 0.11 4.84 0.11 7.25 0.08 1.7-0.04 2.05-0.52 1.73-2.16-0.11-0.53-0.11-1.01 0-1.55 0.23-1.14 0.41-2.37 0.37-3.44-0.07-2.21 0.17-4.38 0.21-6.57 0.03-1.94 0.23-3.85 0.22-5.77 0-2.36-0.39-4.71-0.54-7.07-0.11-1.84-0.13-3.85 0.79-5.36 1.64-2.74 4.42-4.05 7.61-4.22 0.83-0.03 1.68-0.09 2.45-0.24 2.37-0.4 4.77-0.16 7.15-0.53 1.65-0.26 3.38-0.2 5.08-0.17 0.62 0 0.9-0.03 0.88-0.72-0.16-5.98 0.3-11.99-0.24-17.97-0.11-1.22-0.09-2.47 0.04-3.7 0.26-2.34 0.39-4.66 0.28-7.02-0.08-1.62-0.08-3.26-0.08-4.9 0-0.61 0.68-1.08 0.65-1.58-0.24-3.8-0.69-7.57-0.7-11.37 0-0.97-0.28-1.98-0.63-2.91-0.4-1.1-1.25-1.8-2.54-1.65-1.69 0.2-3.33-0.32-5.01-0.46-1.09-0.1-2.32 0.6-3.3-0.41-0.81 0.98-1.99 0.65-2.87 0.5-1.82-0.3-3.67-0.04-5.51-0.52-0.68-0.18-1.54-0.48-2.24-0.37-2.2 0.35-4.37 0.17-6.56 0.24-2.36 0.08-4.68 0.3-7.05 0-2.78-0.33-5.62-0.12-8.42-0.22-4.46-0.14-8.93-0.42-13.39 0.17-0.29 0.04-0.72 0.09-0.9-0.07-1.22-1.07-2.38-0.15-3.54 0.05-0.61 0.11-1.2 0.31-1.8 0.31-6.91 0-13.82 0-20.72-0.03-1.18 0-2.34-0.37-3.54-0.26-1.01 0.09-2.01-0.74-3.07 0-0.48 0.33-0.45-0.61-1.07-0.55-2.06 0.24-4.11-0.34-6.19-0.26-1.99 0.07-4-0.31-6 0-0.26 0.04-0.56 0.05-0.8 0-1.93-0.57-3.83-0.22-5.69 0.22-1.8 0.42-3.62 0.88-5.43 0.53-1.86-0.35-3.61-0.33-5.4 0.28-0.93 0.33-1.95 0.66-2.91 0.57-1.4-0.13-2.59 0.24-3.13 1.49-1.06 2.45-1.38 5.18-1.27 7.68 0.13 2.86-0.18 5.69 0.09 8.55 0.13 1.29-0.09 2.65-0.11 3.94-0.01 1.58 0.1 3.22 0.15 4.82 0.09 2.62 0.3 5.25 0.2 7.87-0.07 1.99 0.06 3.94 0.06 5.93 0 1.77 0.5 3.55 0 5.28-0.52 1.77-0.44 3.54-0.5 5.33-0.09 3.16 0.48 6.31 0.26 9.5 0 0.2 0.11 0.42 0.13 0.64 0.15 1.75 0.51 3.5 0.35 5.24-0.44 5-1.01 10.01-0.2 15.04 0.36 2.34 1.21 4.53 2.57 6.5 0.65 0.92 1.46 1.75 2.69 0.89 0.54-0.37 1.09-0.3 1.59-0.28 2.04 0.07 4.09 0.26 6.13 0.39 0.79 0.05 1.34 0.35 1.46 1.36 0-1.1 0.64-0.55 1.08-0.64 0.92-0.23 1.81-0.58 2.8-0.28 0.81 0.24 1.79-0.41 2.54 0.37 0.41-0.55 1-0.52 1.57-0.5 2.37 0.07 4.75 0.17 7.11 0.24 0.66 0.02 1.4 0.18 1.93 0.09 2.63-0.42 5.31-0.42 7.92-0.44 2.16-0.02 4.27-0.39 6.41-0.28 1.14 0.06 2.36 0.17 3.39 0.1 1.62-0.1 3.26-0.11 4.86 0 0.81 0.05 2.06 0.47 2.49 0.33 2.19-0.81 4.29 0 6.41 0 1.38 0 2.85-0.26 4.14 0.53 0.22 0.13 0.2-0.07 0.2-0.16 0.11-0.72 0.67-0.43 1.03-0.43 1.75 0.02 3.5 0.04 5.25 0.17 0.7 0.05 1.62-0.32 1.99 0.75 0.07 0.19 0.41 0.13 0.41 0 0-0.94 0.92-0.7 1.17-0.66 0.96 0.13 2.2-0.31 2.88 1.11l0.07 0.01zm24.7 9.23c0-1.95-0.44-3.83-0.3-5.73 0.06-0.88-0.25-1.25-1.21-1.18-1.6 0.13-3.21 0.58-4.81 0-0.22-0.07-0.51 0-0.77 0.08-1.92 0.57-3.89 0-5.8 0.31-0.79 0.13-1.57-0.09-2.34-0.04-2.36 0.15-4.7 0.13-7.04 0-0.92-0.05-1.93 0.41-2.72-0.09-0.87-0.57-1.49 0.13-2.21 0.11-0.89-0.02-1.79-0.44-2.67-0.4-2.91 0.13-5.79 0.51-8.75-0.09-1.38-0.28-3.06-0.1-4.53 0.05-1.86 0.18-3.7 0.06-5.55 0.15-0.97 0.05-2.13-0.67-2.68-0.48-1.5 0.53-2.86 0-4.26 0.05-1.44 0.08-2.85-0.24-4.33-0.05-1.27 0.16-2.48-0.41-3.9 0-1.29 0.37-2.84 0.39-4.27 0.37-1.48-0.02-2.97 0-4.44 0.09-1.31 0.09-2.53-0.44-3.93-0.28-0.84 0.1-2.02 0.19-2.96-0.11-1.36-0.44-2.91-0.31-4 0.04-1.76 0.55-3.46 0.4-5.17 0.5-2.34 0.11-4.68-1.07-7.02 0.03-0.07 0.04-0.18 0.04-0.26 0-1.4-0.75-2.83 0.28-4.29-0.07-0.92-0.22-2.01 0.28-2.93 0.18-0.86-0.09-1.54 0.28-2.33 0.3-0.59 0-1.18 0.29-1.75-0.06-0.61-0.36-1.24-0.24-1.9-0.22-1.18 0-2.25 0.24-3.37 0.59-1.16 0.37-2.41 0.42-3.57 0.9-0.69 0.3-1.5 0.56-2.03-0.36-0.15-0.26-0.61-0.37-0.59-0.15 0.06 0.99-0.77 0.68-1.22 0.92-0.29 0.17-0.55 0.22-0.33 0.66 0.57 1.22 0.65 2.54 0.76 3.85 0.05 0.7 0.55 0.92 0.92 0.81 0.77-0.2 1.51-0.05 2.26-0.11 3.01-0.2 5.99-0.35 8.99-0.5 0.94-0.05 1.86-0.03 2.8-0.03 2.62 0 5.21-0.04 7.83-0.04 2.19 0 4.42 0.2 6.59 0.04 3.11-0.24 6.21 0 9.3-0.17 2.05-0.11 4.07 0.33 6.17 0.22 3.19-0.18 6.41 0.13 9.63 0.17 0.85 0 1.62 0.29 2.56 0.2 2.6-0.28 5.22 0.2 7.85-0.11 0.7-0.09 1.62 0.42 2.14 0.28 1.93-0.56 3.81-0.1 5.69-0.04 2.04 0.06 4.09 0 6.13 0.18 1.29 0.11 2.76 0.11 4.12-0.07 0.37-0.05 0.65-0.28 0.59 0.39-0.03 0.35 0.23 0.07 0.41 0.03 1.91-0.4 3.85-0.88 5.78 0 0.44 0.21 1.31 0.26 1.33 0.06 0.11-1.51 1.27-0.66 1.69-0.63 0.68 0.06 1.61 0.26 2.1 0.13 2.14-0.57 4.24-0.13 6.34-0.13 2.41 0 4.84 0.17 7.24 0.37 0.69 0.06 1.52-0.77 2.13 0.26 0.11 0.18 0.17-0.02 0.19-0.13 0.2-0.74 0.88-0.42 1.3-0.52 2.42-0.49 4.87-0.36 7.32-0.47l0.07-0.06zm1.42 22.28c1.45 0.34 0.88 1.24 0.86 1.99-0.07 1.98-0.14 3.93-0.22 5.9-0.09 2.41-0.22 4.82 0.08 7.25 0.35 2.86 0.53 5.73 0.27 8.62-0.09 1.16-0.22 2.41 0.04 3.5 0.62 2.52 1.14 5.1 2.26 7.48 0.32 0.66 0.81 1.22 1.81 1.45 1.49 0.37 2.98 0.92 4.47 0.72 1.18-0.16 2.14 0.54 3.32 0.3 1.32-0.26 2.76-0.3 4.11-0.24 2.19 0.09 4.4 0.26 6.57 0.31 3.96 0.11 7.96 0.35 11.95-0.11 2.69-0.31 5.44-0.02 8.16-0.17 2.91-0.16 5.84-0.11 8.69-0.86 1.92-0.52 2.99-1.81 3.37-3.78 0.3-1.51 0-2.98 0.15-4.45 0.15-1.77 0.35-3.54 0.35-5.34 0-2.6-0.07-5.18-0.16-7.78-0.1-2.7-0.11-5.43-0.15-8.15-0.02-1.31-0.3-2.67-0.15-3.89 0.22-1.82 0.06-3.59 0.15-5.4 0.07-1.53 0.13-3.05-0.02-4.56-0.13-1.31 0-2.6-0.05-3.85-0.12-1.92 0.03-3.82-0.1-5.73-0.13-2.03 0.06-4.03-0.36-6.1-0.39-1.84-0.11-3.81-0.17-5.72-0.07-1.98-0.09-3.91 0.15-5.9 0.11-0.94 0.2-1.95 0.13-2.91-0.15-2.12-0.08-4.23 0-6.35 0.05-1.57 0.11-3.17 0-4.7-0.08-1.31-0.28-2.71-0.37-4.03-0.08-1.07-0.06-2.16-0.15-3.24-0.15-1.51-0.46-2.99-0.4-4.53 0.03-1.4-0.24-2.84-1.64-3.72-1.13-0.72-2.23-1.59-3.61-1.53-1.09 0.05-2.2 0.03-3.28 0.14-1.27 0.13-2.51 0-3.74-0.11-1.92-0.12-3.81 0.13-5.73-0.18-0.99-0.17-2.24-0.42-3.02-0.07-1.29 0.59-2.45 0.29-3.68 0.36-1.35 0.1-2.64-0.6-3.85-0.47-2.03 0.2-3.98 0.11-5.95-0.24-1.64-0.3-3.28 0.13-4.94 0.05-0.92-0.04-1.82-0.4-2.76-0.24-0.7 0.13-1.45 0.06-2.13 0.24-1.31 0.35-2.55-0.24-3.82-0.13-0.86 0.08-1.75 0.35-2.57 0.54-1.77 0.38-3.03 1.18-3.21 2.94-0.18 1.79-0.4 3.61-0.22 5.4 0.28 2.69 0.53 5.38 0.52 8.08 0 2.21 0.16 4.46 0.03 6.65-0.07 1.38-0.05 2.8 0.06 4.11 0.16 1.71-0.15 3.37-0.09 5.05 0.03 1.23 0.58 2.61 0.09 3.72-0.65 1.41-0.33 2.83-0.37 4.2-0.06 3.24 0.18 6.48 0.11 9.76-0.06 2-0.06 4.12 0.24 6.07 0.42 2.82-0.13 5.59 0.13 8.35 0.05 0.64 0.09 1.43-1.15 1.36l-0.01-0.06zm24.58-109.87c0.28 0.86-0.97 1.49-0.48 2.25 0.47 0.7 0.19 1.25-0.01 1.84-0.32 0.9-0.21 2.02 0.29 2.85 0.55-2.24 0.26-4.58 0.22-6.92l-0.02-0.02zM56.47 97.58c-0.02-0.64-0.72-0.66-0.97-1.08-0.21 0.2-0.67 0.09-0.61 0.55 0.07 0.64 0.48 0.9 1.07 0.96 0.29 0.02 0.53-0.04 0.51-0.41v-0.02zm93.45-83.11c0.61-1.84 0.48-2.95-0.28-3.63 0.1 1.1 0.17 2.21 0.28 3.63z" android:fillColor="#000000"/> - <path android:pathData="M186.3 116.67v-0.98c0-1.54-0.07-3.09-0.15-4.64-0.03-0.94-0.09-1.87-0.11-2.83l-0.05-1c-0.06-1.05-0.1-2.04 0-2.96 0.49-5.56 0.68-11.29 0.57-16.98-0.06-2.3-0.1-4.61-0.11-6.87 0-2.16-0.1-4.33-0.19-6.43l-0.09-2.12c-0.05-1.25-0.37-2.41-0.66-3.55-0.22-0.85-0.43-1.66-0.52-2.45-0.33-3.15-1.97-5.36-4.75-6.37-0.09-0.1-0.18-0.19-0.33-0.3-1.9-1.4-4.02-2.17-6.15-2.21h-5.05c-3.3 0-6.61 0-9.91 0.06l-5.65 0.03c0.07-1.91 0-3.85-0.06-5.72-0.03-0.8-0.05-1.61-0.07-2.38 0-0.57-0.02-1.16-0.06-1.73 0-0.81-0.05-1.6-0.03-2.38 0.03-1.49 0.13-2.74 0.24-3.88 0.09-0.79 0.01-1.53-0.06-2.18-0.05-0.6-0.11-1.12-0.04-1.56 0.24-1.2 0.15-2.32 0.1-3.41-0.08-0.92-0.13-1.8 0.01-2.59 0.19-0.98 0.17-1.92 0.15-2.82-0.02-0.67-0.02-1.29 0.04-1.84 0.26-2.09 0.26-4.17 0.26-6.19 0-0.9 0-1.81 0.02-2.75 0-1.16 0.07-2.32 0.12-3.57 0.08-1.55-0.12-3.02-0.33-4.44-0.18-1.42-0.37-2.74-0.26-4.03 0.17-2.12-1.38-3.22-1.87-3.59-0.8-0.57-1.62-0.72-2.23-0.81-0.19-0.04-0.44-0.08-0.46-0.09-1.83-0.89-3.59-1.04-4.94-1.07-0.99-0.02-1.97-0.04-2.96-0.04-1.7 0-3.35 0.04-4.96 0.13-0.66 0.04-1.32 0.05-1.99 0.05-1.49 0-3.02-0.07-4.66-0.16-0.55 0-0.99 0.15-1.32 0.24-0.02 0.02-0.04 0.02-0.06 0.02-0.64-0.17-1.32-0.26-2.06-0.26s-1.42 0.07-2.06 0.16l-0.65 0.08c-0.73 0.07-1.51 0.11-2.32 0.11-0.44 0-0.9 0-1.34-0.04-1.73-0.07-3.46-0.11-5.2-0.13h-2.15c-1.45-0.02-2.91 0.08-4.33 0.17-1.4 0.09-2.72 0.18-4.07 0.18-0.51 0-1.03-0.02-1.56-0.05h-0.39c-0.64 0-1.25 0.09-1.79 0.16-0.4 0.08-0.81 0.15-1.25 0.15h-0.2c-0.89-0.09-1.79-0.09-2.71-0.09h-1.03c-0.85 0-1.84-0.02-2.78-0.11-1.95-0.22-3.85-0.24-5.45-0.24-0.68 0-3.17 0.02-3.17 0.02-1.46 0-2.91 0.07-4.37 0.13-1.47 0.07-2.94 0.12-4.43 0.12-0.92 0-1.85-0.01-2.77-0.09-0.7-0.05-1.41-0.07-2.13-0.07-1.22 0-2.45 0.07-3.67 0.24l-0.96 0.13c-1.25 0.18-2.45 0.35-3.73 0.35-0.93-0.02-1.85-0.11-2.77-0.19-1.08-0.11-2.21-0.2-3.35-0.2h-0.96c-0.33 0.02-0.66 0.04-0.97 0.04-0.96 0-1.92-0.08-2.86-0.15-1.05-0.07-2.08-0.17-3.13-0.17-0.24 0-0.48 0.02-0.72 0.02-0.62 0.02-1.25 0.04-1.87 0.04-0.7 0-1.4-0.02-2.1-0.02-0.72-0.02-1.44-0.02-2.16-0.02h-0.98c-1.03 0.02-2.04 0.08-3.05 0.13-1.13 0.06-2.25 0.13-3.35 0.13-0.41 0-0.81 0-1.2-0.04-0.46-0.01-0.9-0.03-1.35-0.03-2.74 0-5.39 0.46-7.97 0.9l-1.66 0.28-0.31 0.03c-0.81 0.11-1.92 0.26-2.87 1.02-1.04 0.77-1.42 1.8-1.72 2.54-0.07 0.24-0.14 0.46-0.27 0.66-1.07 1.8-1.14 3.55-1.22 5.12-0.02 0.33-0.04 0.68-0.07 1.03-0.08 1.07 0 2.06 0.09 3.04 0.09 1.14 0.18 2.23-0.04 3.19-0.24 1.12-0.09 2.15 0.02 3.03 0.15 0.96 0.2 1.57-0.02 2.05-0.53 1.07-0.49 2.12-0.44 2.95 0 0.29 0.04 0.6-0.02 0.97-0.03 0.33-0.13 1.25 0.52 1.97 0.15 0.17 0.35 0.3 0.57 0.41l-0.04 3.4c-0.02 1.9-0.03 3.8-0.03 5.7v2.56c0.01 2.06 0.03 4.19-0.08 6.26-0.04 0.61-0.07 1.19-0.11 1.8-0.09 1.24-0.18 2.53-0.16 3.85 0.03 1.47 0.11 2.95 0.16 4.42 0.09 2.06 0.19 4.18 0.2 6.26 0 0.48 0 0.98 0.04 1.46 0.06 1.69 0.11 3.28-0.37 4.8-0.42 1.44-0.31 2.9-0.22 4.19 0.04 0.51 0.08 1.03 0.08 1.52v1.4c0 1.83 0 3.63-0.04 5.46-0.08 3.46 0.02 6.66 0.27 9.81v0.2c0.06 0.37 0.11 0.91 0.3 1.48-0.15 0.03-0.28 0.07-0.39 0.07-0.13-0.02-0.26-0.02-0.38-0.02-1.02 0-1.86 0.37-2.55 0.67-0.36 0.16-0.71 0.31-1.01 0.36-0.5 0.11-0.99 0.24-1.49 0.37-0.98 0.26-1.92 0.5-2.82 0.5H5.78c-0.61 0-1.13 0.11-1.57 0.37H4.08c-0.37 0-0.75 0.09-1.09 0.24L2.7 97.19c-0.77 0.31-2.43 0.95-2.65 3.03-0.15 1.11 0.07 2.05 0.26 2.88 0.07 0.33 0.14 0.64 0.18 0.96l0.11 0.73c0.11 0.79 0.22 1.53 0.13 2.08-0.59 2.95 1.18 3.8 2.26 4.04 0.24 0.05 0.52 0.07 0.78 0.07 0.37 0 0.75-0.05 1.12-0.13 0.11 0 0.2-0.03 0.31-0.05 0.91 0.51 1.81 0.57 2.42 0.57 0.24 0 0.48-0.02 0.72-0.02 1.82-0.11 3.66-0.15 5.48-0.2 1.46-0.04 2.91-0.1 4.39-0.15 1.34-0.07 2.69-0.09 4.03-0.09 1.49 0 2.97 0.03 4.46 0.05 1.32 0.02 2.63 0.06 3.94 0.06h3.07c2.14 0.02 4.28 0.03 6.41 0.05 0.81 0 1.62 0.02 2.43 0.02h2.51c1.58-0.02 3.17 0 4.73 0.06 0.96 0.03 1.9 0.03 2.84 0.03s1.82 0 2.72-0.01c0.91 0 1.79-0.02 2.69-0.02 0.8 0 1.59 0.02 2.36 0.03 0.77 0.02 1.55 0.04 2.32 0.04h3.61c0.61-0.02 1.22-0.02 1.82 0 0.46 0.02 0.92 0.02 1.39 0.02 0.93 0 1.86-0.02 2.79-0.04 0.89-0.03 1.79-0.05 2.69-0.05 0.96 0 1.92 0.03 2.88 0.11 0.55 0.03 1.1 0.05 1.65 0.05 0.56 0 1.15 0 1.7-0.03 0.53-0.02 1.07-0.04 1.6-0.04 0.22 0 0.42 0.02 0.65 0.02 3.14 0.11 6.29 0.13 9.44 0.14 1.42 0 2.84 0 4.26 0.04 0.66 0 1.32 0.02 1.97 0.04 0.86 0.03 1.73 0.05 2.58 0.05h1.67c1.29-0.02 2.58-0.02 3.85-0.09h0.2c0.45 0 0.91 0.06 1.37 0.13 0.57 0.07 1.18 0.17 1.84 0.17 0.24 0 0.5-0.02 0.74-0.06 1.12-0.11 2.37-0.17 3.92-0.17 0.83 0 1.64 0.02 2.47 0.02 0.83 0.02 1.67 0.04 2.5 0.04 0.57 0 1.16 0 1.73-0.02-0.09 1.31-0.13 2.75-0.09 4.33l0.04 0.83c0.03 0.83 0.07 1.62 0 2.37-0.17 2.07-0.32 4.5-0.1 6.97 0.15 1.86 0.19 3.29 0.1 4.51-0.08 1.07-0.13 2.15-0.19 3.24l-0.09 1.6c-0.04 0.63 0.04 1.27 0.09 1.83 0.04 0.49 0.11 1.04 0.04 1.36-0.2 0.97-0.15 1.88-0.09 2.67 0.03 0.57 0.05 1.05 0 1.51-0.17 1.32-0.06 2.58 0.07 3.81 0.06 0.57 0.11 1.16 0.13 1.71 0.02 0.98 0.02 1.97 0 2.95 0 3.52-0.06 7.15 1.16 10.76l0.17 0.46c0.9 2.7 2.02 6.07 5.98 7.27 1.83 0.53 3.45 0.81 4.99 0.81 1.42 0 2.8-0.24 3.98-0.7 0.52 0.33 1.11 0.5 1.71 0.5 0.61 0 1.16-0.17 1.55-0.3 0 0 0.04 0 0.06-0.02 0.49 0.36 0.99 0.43 1.3 0.43 0.57 0 1.07-0.22 1.44-0.48 0.35 0.28 0.81 0.42 1.31 0.42 0.03 0 0.2-0.01 0.24-0.01 1.75 0.09 3.62 0.16 5.52 0.16 0.77 0 1.53 0 2.3-0.04h0.32c0.44 0 0.88 0.04 1.32 0.06 0.56 0.06 1.11 0.09 1.64 0.09 0.59 0 1.13-0.05 1.64-0.15 0.09-0.01 0.2-0.01 0.3-0.01 0.31 0 0.6 0.03 0.92 0.07 0.44 0.06 0.9 0.11 1.36 0.11 0.77 0 1.46-0.15 2.06-0.44 0.33 0.11 0.68 0.16 1.03 0.16 0.67 0 1.22-0.18 1.68-0.33 0.18-0.05 0.46-0.15 0.55-0.15 3.04-0.11 6.58-0.23 10.06-0.68 5.34-0.64 8.49-3.4 8.87-7.8 0.04-0.56 0.08-1.09 0.11-1.64 0.04-0.52 0.06-1.02 0.1-1.5 0.07-0.6 0.14-1.19 0.2-1.8 0.22-1.94 0.46-3.92 0.44-5.97-0.02-1.2-0.05-2.37-0.11-3.57-0.05-1.53-0.13-3.08-0.11-4.6 0-1 0.06-1.99 0.08-2.99 0.03-1.29 0.07-2.58 0.09-3.87v-3.44c-0.02-1.45-0.06-2.89 0-4.35 0.14-3.68 0.13-7.4 0.11-11.03h-0.02zm-2.1-8.38c0.07 2.47 0.24 4.96 0.26 7.42 0.02 3.98 0.05 7.96-0.11 11.92-0.09 2.63 0.05 5.23 0 7.85 0 2.28-0.13 4.56-0.17 6.83-0.02 2.74 0.19 5.49 0.22 8.23 0 2.54-0.37 5.05-0.62 7.57-0.1 1.05-0.13 2.1-0.23 3.15-0.36 4.29-3.88 5.75-7.25 6.15-3.3 0.41-6.59 0.55-9.89 0.66-1.11 0.04-2.21 1.05-3.3-0.02-1.47 1.48-3.28 0.34-4.9 0.65-1.56 0.29-3.13-0.11-4.66-0.04-2.56 0.11-5.1 0-7.64-0.13-0.26-0.02-0.59 0.11-0.68-0.22-0.43-1.53-1.11-0.64-1.64-0.15-0.52 0.47-0.9 0.71-1.34-0.01-0.12-0.17-0.26-0.06-0.43-0.06-0.94 0.02-1.89 0.92-2.87 0-0.26-0.26-0.68-0.2-1.01-0.07-2.73 1.05-5.45 0.75-8.16-0.06-3.24-0.97-4.04-3.88-4.94-6.55-1.44-4.28-0.98-8.73-1.07-13.15-0.05-1.75-0.44-3.54-0.22-5.25 0.19-1.36-0.2-2.67 0.08-4.07 0.22-1-0.17-2.31-0.1-3.43 0.1-1.6 0.15-3.22 0.28-4.8 0.11-1.55 0.04-3.21-0.09-4.81-0.21-2.23-0.09-4.46 0.09-6.67 0.09-1.14 0-2.26-0.04-3.41-0.03-1.71 0-3.42 0.19-5.13 0.07-0.74-0.11-1.09-0.9-1.04-3.95 0.24-7.91-0.22-11.87 0.21-1.32 0.14-2.68-0.33-4.03-0.26-1.66 0.09-3.35 0.07-5.01 0.09-1.62 0.02-3.29-0.07-4.95-0.09-4.55-0.06-9.12-0.04-13.67-0.18-1.84-0.06-3.68 0.14-5.5 0-3.28-0.26-6.56 0.05-9.84-0.04-2.58-0.07-5.16 0.05-7.73-0.04-3.54-0.11-7.08 0.09-10.61-0.03-3.24-0.12-6.49-0.04-9.73-0.08-3.15-0.04-6.31-0.04-9.48-0.05-4.18-0.02-8.36-0.22-12.54-0.02-3.3 0.15-6.6 0.16-9.89 0.35-0.7 0.03-1.49 0.07-2.21-0.37-0.8-0.5-1.73 0.17-2.62-0.04-1.01-0.22-1.07-0.85-0.86-1.88 0.2-1.08-0.08-2.28-0.22-3.4-0.15-1.13-0.59-2.19-0.45-3.37 0.13-1.16 1.05-1.35 1.86-1.7 0.52-0.24 0.8 0 0.98 0.63-0.02-1.05 0.66-1.13 1.29-1.09 1.75 0.07 3.33-0.55 4.99-0.9 1.18-0.24 2.21-1.11 3.37-1 0.99 0.1 1.75-0.47 2.63-0.51 1.11-0.06 0.67-0.81 0.39-1-0.83-0.59-0.83-1.45-0.9-2.22-0.28-3.21-0.35-6.41-0.28-9.62 0.06-2.3 0.04-4.58 0.04-6.89 0-1.73-0.41-3.57 0.07-5.17 0.7-2.3 0.43-4.55 0.41-6.82-0.02-3.57-0.28-7.14-0.37-10.71-0.04-1.85 0.18-3.67 0.27-5.51 0.17-2.97 0.06-5.95 0.06-8.91 0-3.14 0.06-6.27 0.07-9.42 0-0.58 0.46-1.52-0.88-1.28-0.29 0.05-0.22-0.45-0.2-0.63 0.13-1.09-0.24-2.25 0.26-3.24 0.88-1.83-0.24-3.67 0.16-5.51 0.48-2.14-0.18-4.33 0-6.48 0.15-1.79-0.02-3.59 1.03-5.36 0.5-0.83 0.59-1.97 1.51-2.67 0.7-0.55 1.62-0.59 2.36-0.7 3.5-0.57 6.98-1.33 10.59-1.12 2.58 0.12 5.16-0.19 7.73-0.23 2.4-0.03 4.77 0.1 7.17 0 2.58-0.09 5.12 0.43 7.72 0.26 2.28-0.13 4.62 0.33 6.92 0.37 1.68 0.02 3.32-0.28 4.97-0.5 1.79-0.24 3.63-0.29 5.42-0.14 3.9 0.29 7.81-0.15 11.71-0.17 2.82-0.02 5.64-0.09 8.42 0.2 2.21 0.24 4.4 0.02 6.57 0.21 1.29 0.09 2.43-0.37 3.67-0.3 3.52 0.22 7.03-0.37 10.55-0.31 2.27 0.03 4.51 0.03 6.78 0.14 1.27 0.08 2.63 0.06 3.96-0.09 1.4-0.14 2.81-0.44 4.25 0.04 0.54 0.18 1.12-0.3 1.77-0.26 2.23 0.13 4.48 0.24 6.68 0.11 2.58-0.15 5.16-0.16 7.76-0.09 1.42 0.04 2.82 0.22 4.18 0.88 0.7 0.32 1.67 0.21 2.41 0.74 0.67 0.48 1.2 1.03 1.12 1.95-0.23 2.88 0.74 5.66 0.59 8.53-0.05 1.22-0.11 2.43-0.12 3.65-0.08 2.91 0.09 5.83-0.26 8.73-0.19 1.51 0.11 3.09-0.17 4.53-0.38 2.04 0.26 4.05-0.11 6.02-0.24 1.33 0.22 2.58 0.07 3.87-0.14 1.32-0.22 2.69-0.25 4.03 0 1.38 0.07 2.78 0.09 4.18 0.05 2.76 0.24 5.54 0.11 8.29-0.07 1.45 0.61 1.64 1.68 1.64 6.92-0.04 13.84-0.15 20.77-0.08 1.8 0.04 3.55 0.72 5.07 1.85 0.2 0.16 0.38 0.4 0.6 0.47 2.38 0.8 3.5 2.58 3.76 4.92 0.22 2.01 1.07 3.92 1.16 5.9 0.11 2.81 0.28 5.63 0.28 8.45 0 2.28 0.05 4.6 0.11 6.9 0.11 5.6-0.08 11.2-0.57 16.78-0.12 1.38 0 2.8 0.07 4.2z" android:fillColor="#F9F9FB" android:fillAlpha="0.5"/> - <path android:pathData="M92.25 41.49s-0.24 0-0.24 0.02c-0.4 2.01-1.99 1.95-3.52 2.08-0.71 0.06-1.49-0.18-1.25 1.36 0.28 1.86 0.3 3.83 0.24 5.75 0 0.48-0.26 0.92 0.77 0.75 2.4-0.38 2.44-0.25 2.12-2.68-0.07-0.59 0.08-1.09 0.22-1.64 0.08-0.3 0.24-0.43 0.41-0.32 1.34 0.81 2.67-0.33 4.05-0.03 1.25 0.27 2.08 0.92 1.97 2.19v0.13c-0.37 3-0.2 3.15 2.76 2.8 0.58-0.08 0.81-0.17 0.7-0.78-0.07-0.46-0.05-0.94-0.05-1.41-0.06-1.81 0.26-2.27 2.06-2.51 1.33-0.18 2.69-0.2 4.04-0.2 0.33 0 0.95 0 0.88 0.83-0.08 0.99 0.13 2 0.13 3.02 0 2.02-0.68 2.72-2.65 2.82-1.94 0.09-1.94 0.31-1.72 2.24 0.19 1.59 0.68 3.17 0.37 4.79-0.13 0.64 0.2 0.87 0.7 0.99 0.13 0.04 0.26 0 0.39 0 2.5 0.1 3.04 0.56 3.15 2.95 0.09 2.1 0.14 4.2-0.15 6.28-0.26 1.79-1.62 2.62-3.31 1.99-0.43-0.16-0.65 0.11-0.96 0.26-1.83 0.83-2.78 0.2-2.82-1.77-0.03-1.56-0.82-2.58-2.38-3.06-0.27-0.09-0.49-0.4-0.94-0.22-0.29 1.03 0.32 2.06 0.21 3.19-0.24 2.3-1.03 3.22-3.36 3.02-0.36-0.04-0.73-0.02-1.1-0.04-2.08-0.11-2.32-0.4-2.56-2.72-0.06-0.56-0.31-1.11-0.26-1.64 0.08-0.72-0.4-0.78-0.81-0.94-0.11-0.04-0.24-0.04-0.37-0.04-1.27 0-1.93 0.77-1.97 2.32-0.05 1.92-0.4 2.05-2.24 2.23-1.37 0.13-2.6-0.5-3.95-0.28-0.57 0.1-0.49-0.68-0.51-0.99-0.06-2.62-0.04-5.23 0-7.85 0.04-1.25 0.83-1.97 1.99-2 2.45-0.1 4.9-0.32 7.33-0.21 1.23 0.06 1.25-0.86 1.1-1.29-0.29-0.81-0.18-1.52-0.09-2.32 0.07-0.62-0.39-1.05-0.86-0.73-1.55 1.03-3.25 0.55-4.79 0.33-1.24-0.17-2.43 0.24-3.67-0.11-1.07-0.31-1.31-0.98-1.32-1.88 0-0.39 0.2-0.79 0.16-1.16-0.2-1.49-0.2-1.57-2.13-2.23-0.54-0.18-1-0.48-1.52-0.68l0.04 0.04c0-1.33 0.04-2.67 0-4-0.04-1.07 0.28-1.68 1.48-1.36 0.12 0.03 0.25 0.13 0.36 0.09 0.67-0.17 1.4-0.24 1.99-0.55 0.67-0.37 0.06-1.07 0.13-1.62 0.22-1.66 0.59-2.1 2.29-2.14 0.12 0 0.25-0.09 0.36-0.07 1.51 0.27 2.08-0.34 1.75-1.85-0.05-0.2-0.07-0.46 0-0.64 0.48-1.33-0.16-1.34-1.18-1.09-2.3 0.56-3.64-0.55-3.66-2.96 0-0.96 0-1.94 0.13-2.89 0.05-0.39 0.16-0.81 0.9-0.92 1.12-0.19 2.19-0.39 3.35-0.35 1.38 0.05 2.03 0.86 2.4 2.04 0.07 0.2 0.11 0.42 0.14 0.63 0.19 0.81 0.15 1.75 0.43 2.43 0.31 0.73 1.42-0.02 2.17 0.14 1.58 0.34 1.95 1.04 2.25 2.53 0.13 0.62-0.11 1.34 0.46 1.84v0.15l-0.04-0.06zm2.97 12.97c-0.08-0.11 0.35-0.91-0.5-1-0.65-0.07-1.38-0.13-1.97 0.09-1.22 0.46-0.11 1.75-0.74 2.51-0.15 0.16-0.07 0.51 0.17 0.72 0.24 0.18 0.42-0.17 0.59-0.08 0.49 0.28 1.05-0.36 1.49 0.04 0.99 0.92 0.9 0 0.96-0.57 0.05-0.46 0-0.92 0-1.73v0.02zM92.47 65.6c0.04 1.04 0.52 1.56 1.44 1.55 0.13 0 0.28-0.15 0.35-0.11 1.18 0.46 1.2-0.28 1.14-1.09-0.02-0.3-0.04-0.61-0.07-0.9-0.13-1.22-0.76-1.73-2.16-1.66-1.05 0.05-0.57 0.94-0.72 1.51-0.05 0.26-0.22 0.48 0 0.7h0.02zm-27.79 2.93c0-1.94-0.09-3.89 0.02-5.82 0.15-2.32 0.96-3.1 3.11-2.89 2.54 0.22 5.07 0.2 7.61 0.11 2.02-0.08 2.74 0.7 2.98 3.33 0.22 2.47 0.5 4.95 0.26 7.46-0.2 2.26-1.16 3.37-3.41 3.41-2.12 0.03-4.21-0.39-6.33-0.3-0.17 0-0.41 0-0.48-0.11-0.68-1.03-1.24-1.12-2.03 0-0.42 0.61-1.34 0.02-1.45-0.98-0.15-1.39-0.33-2.79-0.3-4.21h0.02zm2.06-2.97c-0.22 1.81 0.13 3.61 0.24 5.4 0.02 0.39-0.07 1.84 1.22 0.86 0.15-0.11 0.31 0.06 0.46 0.06 2.3 0.15 4.6 0.26 6.91 0.4 0.55 0.04 0.9-0.05 1.05-0.68 0.27-1.18 0.46-2.43 0.4-3.55-0.07-1.71-0.37-3.45-0.46-5.2-0.02-0.46-0.15-1.01-0.9-1.01-2.6 0-5.18 0.02-7.77-0.03-0.74 0-1.04-0.04-1.05 0.92 0 0.94-0.22 1.89-0.11 2.85l0.01-0.02z" android:fillColor="#000000"/> - <path android:pathData="M76.47 52.08c0.74 1.14 0.44 2.43 0.31 3.59-0.2 1.95-0.2 2.41-2.5 2.34-0.63 0-1.27 0.26-1.92 0.28-1.71 0.05-2.25-0.41-2.23-2.1 0-0.85-0.14-1.68-0.14-2.51 0-0.57-0.1-0.72-0.78-0.55-0.97 0.24-1.99 0.55-3.04 0.35-0.77-0.17-1.27-0.5-1.23-1.38 0.05-1.22-0.11-2.45 0.11-3.63 0.2-1.16 2.34-2.17 3.68-1.97 0.52 0.07 1 0.3 1.51 0.35 1.09 0.15 1.53 0.81 1.51 1.84 0 0.2-0.14 0.43-0.13 0.61 0.08 0.61-0.09 1.31 0.1 1.79 0.25 0.66 1.1 0.03 1.6 0.24 1.03 0.4 2.34-0.32 3.17 0.79l-0.04-0.04h0.02zm2.71-13.35c0.16 1.73-0.17 3.33-0.5 4.93-0.3 1.46-1.12 1.88-2.67 1.96-2.18 0.09-4.35 0.35-6.52 0.48-1.03 0.05-2.1 0.03-3.08-0.37-1.42-0.59-1.78-1.51-1.67-3.02 0.07-1.05-0.22-2.1-0.21-3.19 0.06-1.97 0.1-3.94 0.35-5.89 0.04-0.21 0.1-0.33-0.16-0.54-0.46-0.35-0.22-1.08 0.05-1.12 0.91-0.11 1.77-0.77 2.56-0.64 2.45 0.42 4.87 0.4 7.32 0.16 0.7-0.07 1.43-0.02 2.13 0.11 1.29 0.26 2.12 1.24 2.17 2.89 0.04 1.44 0.52 2.86 0.23 4.24zm-12.84-6.01s-0.07 0.21-0.07 0.32c-0.04 3-0.13 6-0.12 8.99 0 1.86 1.77 2.96 3.65 2.48 0.77-0.2 1.57-0.48 2.41-0.33 1.31 0.2 2.58 0.02 3.87-0.33 0.9-0.26 1.13-0.76 1.2-1.55 0.22-2.5 0.16-4.99-0.11-7.49-0.11-1.07-0.66-1.46-1.55-1.51-1.12-0.06-2.26-0.1-3.39 0-2 0.18-3.99 0.2-5.89-0.61v0.03zm25.91 8.77v-0.15c0.06-1.89 0.11-3.81 0.15-5.71 0.02-1.89 1.18-2.7 3-3.14 1.93-0.48 3.83-0.45 5.75-0.59 1.19-0.08 2.34 0.09 3.5 0.12 0.95 0.04 1.41 0.83 1.64 1.7 0.6 2.41 0.62 4.9 0.81 7.37 0.05 0.81 0.25 1.56-0.28 2.43-0.96 1.51-2.34 2.34-3.92 2.48-2.42 0.22-4.87 0.17-7.3 0.02-2.11-0.13-2.78-0.94-3.02-3.28-0.05-0.44-0.16-0.84-0.29-1.25h-0.04zM94.22 40c-0.18 1.18-0.15 2.36 0.3 3.48 0.13 0.29 0.07 0.57 0.68 0.64 1.42 0.17 2.87-0.18 4.18 0.17 1.38 0.37 2.58 0.15 3.85-0.09 1.12-0.2 1.95-1.38 2.04-2.53 0.19-2.17-0.31-4.29-0.37-6.44-0.01-0.92-0.53-1.7-1.62-1.6-1.29 0.09-2.56 0.14-3.83 0-1.49-0.17-2.93 0.48-4.34 0.38-0.85-0.03-0.89 0.24-0.89 0.74-0.03 1.75 0 3.5 0 5.25zM71.51 70.61c-1.65-0.04-2.37-0.65-2.59-2.21-0.13-0.96-0.3-1.92-0.44-2.87-0.19-1.17 0.42-2.01 1.62-2.2 1.38-0.22 2.78-0.13 4.12 0.22 1 0.26 1.18 1.31 1.22 2.03 0.03 1.09 0.38 2.14 0.16 3.24-0.18 1-0.53 1.64-1.71 1.59-0.79-0.04-1.58 0.12-2.38 0.2z" android:fillColor="#000000"/> - <path android:pathData="M71.02 43.13c-2.38 0.26-3.1-0.5-3.39-3.2-0.09-0.83-0.66-1.77 0.29-2.53 0.04-0.02-0.75-0.53-0.42-1.03 0.46-0.72 0.59-1.86 2.03-1.25 0.6 0.26 1.45 0.09 2.17 0 2.54-0.33 2.72-0.13 3.68 2.17 0.44 1.05 0.48 2.05 0.35 3.04-0.29 2.19-1.53 2.43-4.36 2.87-0.11 0-0.26-0.07-0.35-0.09v0.02zm29.35-8.49c1 0.59 1.68 1.29 2.44 1.84 1.78 1.31 0.8 4.99-1.44 5.8-3.11 1.15-5.67-0.94-5.21-4.23 0.18-1.37 0.81-1.9 2.1-1.75 0.35 0.03 0.55 0.22 0.59 0.59 0.01 0.22 0 0.51 0.12 0.62 0.76 0.61 1.72 1.11 0 1.79-0.33 0.13-0.14 0.77 0.34 0.9 0.46 0.11 0.94 0.15 1.34-0.27 0.41-0.43 0.5-0.91 0.15-1.29-0.48-0.52-0.24-1.66-1.4-1.62-0.37 0-0.3-0.37-0.06-0.57 0.55-0.45 1-0.96 1.05-1.77l-0.02-0.04z" android:fillColor="#000000"/> - <group> - <clip-path android:pathData="M57 21h57v60H57z"/> - <path android:pathData="M58.39 43c-0.73-0.15-0.98-0.27-0.97-1.11 0.04-1.41 0-2.85 0-4.26 0.1-4.12-0.65-8.18-0.34-12.3 0.13-1.81 0.94-2.35 2.37-3.04 2.88-1.4 5.81-0.23 8.66-0.62 2.53-0.34 5.06 0.31 7.61 0.24 2.14-0.06 4.24-0.41 6.36-0.33 3.56 0.11 7.11-0.02 10.66-0.08 3.58-0.04 7.21 0.08 10.8-0.44 1.06-0.16 2.18-0.06 3.3 0.23 0.56 0.13 1.43 0.1 2.12-0.04 1.64-0.35 3.21 0.62 3.92 2.1 0.62 1.31 0.29 2.58 0.35 3.89 0.08 1.59 0.29 3.19 0.17 4.77-0.35 5.24 0.1 10.45 0.02 15.69-0.06 3.87 0.19 7.72 0.21 11.59 0 3.15-0.03 6.33 0.1 9.49 0.06 1.17 0.64 2.31-0.17 3.58-0.27 0.42 0.19 1.65 0.13 2.56-0.19 2.94-1.14 4.33-3.97 5.23-1.24 0.41-2.45 0.5-3.9 0.23-2.32-0.44-4.85 0.24-7.26 0.12-5.55-0.29-11.09 0.73-16.67 0.1-2.06-0.23-4.24 0.42-6.29 0.15-1.81-0.25-3.55 0.15-5.32 0.12-1.93-0.04-3.9 0.19-5.81 0.13-3.77-0.1-5.75-2.21-6.22-6.06-0.38-3.16-0.59-6.34-0.59-9.51 0-1.68-0.14-3.39 0.13-5.05 0.35-2.13-0.27-4.19-0.19-6.31 0.08-2.16 0.13-4.35-0.1-6.52-0.09-0.95 0-1.95-0.06-2.91-0.03-0.66 0.45-1.04 0.97-1.66L58.39 43zm1.14 23.87c-0.33 2.06 0.73 4.41 0.69 6.91-0.04 2.54 2.72 4.37 5.1 4.31 7.81-0.13 15.65-0.05 23.48-0.05 3.14 0 6.29-0.02 9.44 0 0.86 0 1.83-0.66 2.6 0.28 1.08-0.82 2.37-0.59 3.57-0.55 1.45 0.04 2.82-0.25 4.19-0.6 1.12-0.29 2.83-2.02 2.74-2.83-0.33-2.69 0.05-5.45-0.33-8.12-0.18-1.22 0.46-2.27 0.21-3.45-0.44-2.1-0.19-4.23-0.33-6.37-0.03-0.52 0.99-0.56 0.43-1.04-0.56-0.46-0.39-1-0.39-1.52 0.1-6.16-0.29-12.32 0-18.48 0.08-1.79-0.31-3.6 0.25-5.35 0.41-1.27-0.61-3.27-1.93-3.49-1.56-0.25-3.12-0.57-4.74-0.63-2.18-0.06-4.36 0.29-6.56 0.06-1.72-0.18-3.44-0.27-5.21-0.2-1.84 0.08-3.73-0.34-5.6-0.42-2.28-0.09-4.52 0.54-6.75 0.27-3.53-0.44-7.01-0.11-10.52 0.04-0.77 0.04-1.56-0.17-2.32-0.19-2.02-0.06-4.36-1.56-6 0.96-0.03 0.06-0.17 0.04-0.27 0.06-1.83 0.44-2.72 1.67-2.27 3.52 0.29 1.19 0.21 2.37 0.19 3.56-0.04 2.48-0.19 4.97-0.08 7.43 0.23 4.54 0.08 9.11 0.31 13.65 0.19 3.93 0.04 7.85 0.04 12.22l0.06 0.02z" android:fillColor="#000000"/> - </group> - <path android:pathData="M146.76 51.35c-0.09-3.04-0.66-5.99-0.25-8.99 0.64 3 0.2 6.02 0.25 8.99zm-61.27 53.19c-0.66 0.71-1.05-1.33-2.01-0.13-0.29 0.37-1.71 0.46-2.65 0.51-2.08 0.13-4.16-0.37-6.24 0-1.44 0.26-2.89 0.44-4.2-0.55-0.07-0.05-0.5 0.18-0.39-0.24 0.09-0.28 0.37-0.68 0.61-0.7 1.18-0.11 2.27-1.32 3.54-0.29 0.29-0.87 0.84-0.35 1.38-0.37 2.39-0.06 4.79-0.39 7.16-0.37 1.24 0 2.49 0 3.74 0.04 0.59 0.01 1.05 0.27 1.05 0.68 0 0.38 0 1.05-0.74 1.2-0.42 0.09-0.81 0.29-1.25 0.22zm91.48 56.42c-0.65-0.07-0.32 0.54-0.52 0.8-0.44 0.55-0.7 0.94-1.62 0.86-0.86-0.09-1.78 0.41-2.72 0.57-2.07 0.37-4.13 0.11-6.19 0.15-1.64 0.04-3.32 0.11-4.92 0.46-1.79 0.39-3.48-0.04-5.21-0.13-1.58-0.09-3.17-0.4-4.79-0.07-0.94 0.18-1.95 0.02-2.89 0-1.86-0.06-3.67 0.28-5.51 0.31-1.21 0.04-2.28-0.59-3.48-0.48-1.29 0.13-2.6 0.48-3.85 0.39-1.71-0.13-3.48-0.24-5.06-1.07-0.11-0.05-0.22-0.2-0.22-0.31-0.04-1.79-1.62-3.19-1.37-5.03 0.19-1.44-0.14-2.87 0.15-4.33 0.2-0.97-0.5-2.01-0.31-3.09 0.33-1.9 0.15-3.83-0.04-5.69-0.2-2.19 0.02-4.33 0.04-6.48 0-2.36-0.41-4.76-0.52-7.11-0.11-2.58-0.03-5.23 0.04-7.83 0.06-2.16 0.13-4.46-0.33-6.67-0.11-0.55 0-1.27 0.02-1.91 0.07-1.22 0.68-2.43 0.24-3.7-0.13-0.35-0.23-0.91 0.33-1.17 0.13-0.05 0.4-0.12 0.2-0.35-0.83-0.88-0.15-1.82-0.13-2.72 0-1.95 0.28-3.89 0.33-5.84 0.06-1.55-0.11-3.06-0.13-4.6 0-2.75-0.92-5.47-0.16-8.25 0.13-0.46-0.3-1.07 0.64-1.02-0.03-0.44-0.72-0.13-0.61-0.84 0.39-2.42 0.32-4.9 0.24-7.32-0.01-1.08-0.14-2.39-0.44-3.57-0.11-0.4-0.46-1.29 0.57-1.4-0.46-0.92 0.28-1.82 0.06-2.72-0.02-0.08-0.15-0.21-0.13-0.23 1.09-1.06 0.81-2.87 2.04-3.84 1.2-0.94 2.67-1.31 4.13-1.48 1.36-0.15 2.74-0.24 4.12-0.24 1.05 0 1.24 0.32 1.15 1.09-0.06 0.44 0 0.9-0.06 1.34-0.15 1.77 1.03 2.8 3.37 2.82 2.05 0 4.07-0.39 6.17-0.18 1.81 0.18 3.67-0.08 5.51-0.35 2.19-0.32 4.42-0.08 6.59 0.33 1.31 0.26 2.52-0.22 3.79-0.3 0.81-0.03 1.2-1.21 1.11-1.93-0.11-0.92 0.9-1.51 0.46-2.41 0-0.04 0.11-0.2 0.15-0.19 1.16 0.24 2.26-0.84 3.44-0.18 0.42 0.24 0.81 0 1.2-0.09 2.01-0.44 4.64 1.45 5.27 3.37 0.71 2.19 0.95 4.42 1.4 6.65 0.14 0.77 0.24 1.52 0.09 2.26-0.3 1.47 0.62 2.95 0 4.4-0.89 2.1 0.57 4.57-1.13 6.56-0.46 0.53 0 1.25 0.17 1.77 0.42 1.36 0 2.76 0.26 3.96 0.24 1.1 0.29 2.15 0.33 3.26 0.05 1.21 0.15 2.43 0.26 3.64 0.11 1.38 0.07 2.84 0.15 4.22 0.11 2.1 0.62 4.2 0.49 6.34 0 0.07 0.13 0.22 0.11 0.22-1.18 0.81-1.14 1.56 0.13 2.23-0.68 0.68 0.17 1.78-0.73 2.45-0.76 0.55 0.53 0.16 0.38 0.71-0.22 0.8 0.13 1.77-0.15 2.53-0.35 0.94 0.08 1.76 0.08 2.61v6.26c0 1.13-0.15 2.27 0 3.39 0.25 2.1-0.39 4.15-0.24 6.25 0.15 2.06 0.13 4.14 0 6.2-0.09 1.2 0.64 2.51-0.37 3.63-0.02 0.02 0.57 0.53 0.5 1.11-0.06 0.4 0.2 0.86-0.32 1.16-0.07 0.03-0.27 0-0.16 0.22 0.4 0.81 0.72 3.13 0.59 4.18-0.13 0.99 0.14 1.99-0.17 2.98-0.22 0.7-0.61 1.07-1.36 1-0.17 0.6 0.57 0.22 0.64 0.62-0.66 0.39-0.6 1.27-1.08 1.82 0.02-0.31-0.02-0.6-0.24-0.86-0.81-1.05-1.18-2.19-0.98-3.57 0.52-3.56 0.7-7.11 0.48-10.7-0.13-1.99-0.24-3.96-0.05-5.99 0.18-1.93-0.1-3.88 0.53-5.78-0.9-0.39 0.87-0.52 0.09-0.89 0.59-0.92-0.57-1.58-0.31-2.59 0.24-0.94 0.35-2.19 0.13-3.02-0.43-1.57 0.68-3.1-0.21-4.55 1.05-1.2 0.15-2.58 0.15-3.82 0-1.28 0.3-2.66-0.05-3.94-0.33-1.16 0.31-2.28 0.03-3.35-0.64-2.45 0.11-4.91-0.25-7.35-0.06-0.33 0.84-0.57 0.22-0.92-0.74-0.4-0.5-1.01-0.46-1.52 0.07-1.17 0.13-2.42-0.02-3.49-0.22-1.71-0.33-3.4-0.44-5.12-0.12-1.73-0.8-3.5 0.38-5.13 0.04-0.06-0.05-0.24-0.09-0.35-0.28-0.81-0.18-1.63-0.11-2.47 0.09-1.09 0.53-2.25 0.33-3.21-0.42-2.11 0.09-4.2-0.07-6.3-0.13-1.82-0.28-3.64-0.35-5.47-0.06-1.76-1.07-2.91-2.29-3.94-0.25-0.22-0.55-0.46-0.92-0.24-0.92 0.56-1.91 0.19-2.87 0.24-0.77 0.04-1.09 0.24-1.34 1.07-0.35 1.13-0.04 2.49-1.66 3.28-1.31 0.63-2.49 0.77-3.83 0.88-1.51 0.13-2.93-0.33-4.4-0.38-2.9-0.09-5.71 0.51-8.59 0.42-1.64-0.05-3.28-0.15-4.95 0.11-1.46 0.22-3.04-0.39-4.57-0.55-0.9-0.11-1.23-0.74-1.47-1.42-0.33-1.01-0.46-2.08-0.43-3.17 0-0.37-0.11-1.1-0.71-0.6-0.46 0.38-0.79 0.4-1.35 0.47-0.77 0.11-1.71 0.32-2.36 0.78-2.06 1.45-2.87 3.68-2.94 6.08-0.06 1.52 0.55 3.05 0.2 4.65-0.07 0.34-0.39 0.52-0.33 0.89 0.31 2.01 0.68 4.01-0.61 5.86-0.13 0.18-0.13 0.42 0 0.62 0.19 0.33 0.57 1.82 0.55 2.06-0.09 0.81-0.27 1.62-0.25 2.44 0 0.53 0.35 1.03 0.37 1.6 0.03 1.91 0 3.83 0.25 5.72 0.35 2.6 0.41 2.84-0.81 5.05-0.04 0.06-0.04 0.17 0 0.2 0.9 0.91 0.15 1.88 0.19 2.82 0.13 2.99-0.06 5.91-0.3 8.86-0.04 0.53-0.53 1.14-0.24 1.49 0.79 0.98-0.61 2.36 0.65 3.19 0.02 0-0.04 0.16-0.06 0.24-0.46 1.14-0.29 2.3-0.16 3.46 0.07 0.75-0.45 1.53-0.26 2.12 0.61 1.97 0.14 3.99 0.51 5.97 0.28 1.49 0.19 3.03 0.48 4.56 0.15 0.68 0.81 2.42-0.96 2.84-0.29 0.07-0.11 0.2-0.05 0.37 0.09 0.26 0.22 0.33 0.44 0.14 0.33-0.27 0.63-0.27 0.54 0.23-0.41 2.35 0.07 4.73 0 7.1-0.04 1 0.14 1.83-1.11 2.43 0.66-0.07 0.74 0.26 1.05 1.02 0.79 1.84-0.51 3.68 0.11 5.56 0.2 0.63 0.06 1.51 0 2.26-0.05 1.02 0.35 2.01 0.06 3.06-0.13 0.44 0.07 1.25 0.57 1.36 0.79 0.19 1.66 0.15 2.47 0.02 0.84-0.13 1.45-0.16 1.21 1.16 0.46-0.62 0.68-1.47 1.36-1.27 2.03 0.63 4.02-0.05 6.03 0.04 3.37 0.15 6.74-0.17 10.11 0 1.75 0.09 3.48-0.04 5.21 0 1.45 0 2.93 0.37 4.33 0.05 1.65-0.36 3.46-0.47 4.99-0.31 2.24 0.24 4.27-0.95 6.44-0.46 0.11 0.02 0.3-0.16 0.43-0.29 0.97-1.05 1.78-0.98 2.56 0.25h-0.02z" android:fillColor="#000000"/> - <path android:pathData="M155.51 67.04c-2.56-0.04-4.82 0.42-7.13 0.07-0.47-0.07-1.06 0.35-1.58-0.18-0.26-0.26-0.53-0.43-0.33-0.87 0.17-0.35 0.18-0.77 0.76-0.72 1.6 0.11 3.18-0.16 4.78-0.09 1.09 0.06 2.18-0.26 3.32-0.24 0.9 0 1.4 0.48 1.36 1.14-0.04 0.65-0.77 0.85-1.16 0.89h-0.02zm5.09-2.45c1.06-0.17 1.49 0.75 1.49 1.38 0 1.16-1.44 0.99-2.08 1.64-0.08 0.07-0.96-0.79-0.87-1.16 0.2-0.74 0.15-1.9 1.44-1.86h0.02zm-21.99 30.48c0 1.99-0.02 3.96 0 5.95 0 0.48-0.19 0.7-0.59 0.66-0.37-0.02-0.76 0.06-1.03-0.48-0.36-0.68-0.32-1.36-0.37-2.04-0.17-1.86-0.22-3.74 0.13-5.56 0.51-2.64 1.49-3.41 4.42-3.54 2.5-0.11 5.02-0.2 7.53-0.13 0.68 0 1.31 0.2 1.99-0.11 0.59-0.26 0.31 0.46 0.53 0.63 0.52 0.35 0.15 0.6-0.09 0.79-1.11 0.86-2.5 1.27-3.79 1.1-2.34-0.29-4.57-0.11-6.82 0.45-0.98 0.23-1.69 1.21-1.93 2.28h0.02zm28.95 23.9c-0.04-2.26-0.24-4.1 0.07-5.89 0.08-0.39 0.06-1.2 0.87-1.38 1.08-0.24 1.41 0.81 1.56 1.25 0.78 2.12 0.48 4.22 0 6.45-0.4 1.89-1.67 2.78-2.89 3.64-0.7 0.52-2.08 0.15-3.13 0.06-1-0.09-1.95-0.39-2.98-0.22-0.87 0.15-1.53-0.98-1.2-1.81 0.07-0.16 0.15-0.44 0.27-0.36 1.07 0.6 2.05-0.39 2.93-0.21 1.04 0.22 1.97 0 2.95 0.04 1.57 0.04 1.33-1.09 1.53-1.55l0.02-0.02zm-30.32-1.62c-0.18-0.68 0.43-1.51 0.19-1.88-0.43-0.64-0.32-1.19-0.28-1.78 0.04-0.98 0.79-1.27 1.59-1.33 0.35-0.02 1.1-0.03 0.73 0.87-0.4 1.03 0.19 2.12-0.11 3.24-0.22 0.86-0.13 1.86 0.07 2.82 0.24 1.05 1.04 2.08 2.05 1.93 1.03-0.15 2.01 0.11 3.02 0 0.83-0.07 1.58-0.09 2.23-0.68 0.46-0.4 0.96-0.29 1.29 0.18 0.29 0.41 0.33 0.81 0.05 1.33-0.68 1.27-1.62 1.49-3 1.29-0.83-0.11-1.82-0.06-2.69 0.18-2.3 0.61-5.23-1.45-5.1-4.27 0.04-0.63-0.33-1.23-0.05-1.88l0.01-0.02zm24.88-27.68c1.35-0.24 2.78-0.26 4.22-0.24 1.01 0 2.71 1.11 2.86 2.18 0.12 1.01 0.6 1.95 0.59 2.96-0.04 1.66 0.29 3.33-0.13 4.99-0.11 0.46 0.13 1.14-0.87 1.11-0.92-0.04-0.81-0.45-0.86-1.13-0.11-1.49-0.13-2.98-0.17-4.49-0.05-2.06-2.19-3.68-4.25-3.15-1.31 0.33-2.33-0.13-3.41-0.59-0.81-0.35-0.67-0.72-0.04-1.12 0.61-0.41 1.25-0.68 2.08-0.52h-0.02z" android:fillColor="#000000"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_screenshot.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_screenshot.xml new file mode 100644 index 0000000000000000000000000000000000000000..13b02088e392f6dfc0792cc463b5b457ff1c2ede --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/ic_screenshot.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="18dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M3,4V1h2v3h3v2H5v3H3V6H0V4H3zM6,10V7h3V4h7l1.83,2H21c1.1,0 2,0.9 2,2v12c0,1.1 -0.9,2 -2,2H5c-1.1,0 -2,-0.9 -2,-2V10H6zM13,19c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5s-5,2.24 -5,5S10.24,19 13,19zM9.8,14c0,1.77 1.43,3.2 3.2,3.2s3.2,-1.43 3.2,-3.2s-1.43,-3.2 -3.2,-3.2S9.8,12.23 9.8,14z" + android:fillColor="#ffffff"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_sign_in.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_sign_in.xml deleted file mode 100644 index 27cd49ef344e6fc40382cd6fe02f1d593645b0b4..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_sign_in.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:pathData="M12 2.5c-5.238 0-9.5 4.262-9.5 9.5s4.262 9.5 9.5 9.5 9.5-4.262 9.5-9.5-4.262-9.5-9.5-9.5zM12 7a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm0 12c-2.353 0-4.395-1.277-5.525-3.162A2.451 2.451 0 0 1 8.314 15h7.373c0.734 0 1.386 0.328 1.839 0.838C16.395 17.723 14.353 19 12 19z" - android:fillColor="?attr/textPrimary" /> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_signed_out.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_signed_out.xml deleted file mode 100644 index 8616a490d625d978df980fe678946bc32132e2c4..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_signed_out.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <path - android:fillColor="?attr/textPrimary" - android:pathData="M12 6.5a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" /> - <path - android:fillColor="?attr/textPrimary" - android:pathData="M12 21.5c-5.238 0-9.5-4.262-9.5-9.5S6.762 2.5 12 2.5s9.5 4.262 9.5 9.5-4.262 9.5-9.5 9.5zM12 4c-4.411 0-8 3.589-8 8s3.589 8 8 8 8-3.589 8-8-3.589-8-8-8z" /> - <path - android:fillColor="?attr/textPrimary" - android:pathData="M8.314 14c-0.652 0-1.232 0.269-1.672 0.684A6.014 6.014 0 0 0 12 18a6.355 6.355 0 0 0 1.084-0.104c0.083-0.014 0.165-0.033 0.247-0.051a6.014 6.014 0 0 0 4.027-3.162A2.43 2.43 0 0 0 15.686 14H8.314z" /> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_status_logo.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_status_logo.xml deleted file mode 100644 index 7c8de0a09b6739288b9928ca985d174ab9023a69..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_status_logo.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="32" - android:viewportHeight="32"> - <path android:fillColor="@android:color/white" - android:pathData="M30 10.4a8.5 8.5 0 0 0-3-3.8c0.7 1.4 1.2 3 1.4 4.6-1.7-4.2-4.5-6-6.9-9.6-0.1-0.2-0.6-1-0.7-1.5a10.9 10.9 0 0 0-5.2 7.5c-1 0-2 0.3-3 0.7-0.2 0.1-0.3 0.3-0.2 0.5 0 0.2 0.2 0.3 0.4 0.3 0.3 0 1.2-0.7 3.2-0.8 4 0 6 2.8 6.6 3.9-1-0.8-2.3-1-3.6-1A6.2 6.2 0 0 1 16.1 23c-4.8 0-6.6-3.5-6.9-5.6-0.2-2.1 0.7-2.6 5-2.6 0.8-0.3 1.4-0.9 1.8-1.6 0-0.2-2.6-1.2-3.6-2.2l-1-1-0.4-0.3A6.8 6.8 0 0 1 11 6c-1.4 0.7-2.7 1.6-3.7 2.8-0.6-0.8-0.5-3.2-0.5-3.8-0.2 0.1-5.7 3.2-5.7 11.2a15 15 0 0 0 15 15c7.4 0 14-6 14.9-13.4 0.2-2.1-0.1-5-1-7.4z"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_sync_disconnected.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_sync_disconnected.xml deleted file mode 100644 index 8176893c920167b3a88457c294b6a4cea7872fd1..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_sync_disconnected.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:fillColor="?attr/textPrimary" - android:pathData="M10.07 20.336l1.198-2.089A6.364 6.364 0 0 1 9.5 18.5c-2.353 0-4.395-1.277-5.525-3.162a2.451 2.451 0 0 1 1.84-0.838h7.372c0.075 0 0.144 0.017 0.217 0.024l1.28-2.231c0.916-1.596 3.218-1.596 4.134 0l0.12 0.208a9.71 9.71 0 0 0-0.07-2.613c-0.65-3.933-3.823-7.105-7.756-7.755C4.62 1.06-0.94 6.62 0.133 13.111c0.65 3.933 3.822 7.105 7.755 7.755a9.794 9.794 0 0 0 1.93 0.111c0.052-0.217 0.132-0.432 0.251-0.641zM9.5 6.5a3 3 0 1 1 0 6 3 3 0 0 1 0-6z" /> - <path - android:fillColor="?attr/textPrimary" - android:pathData="M21.58 20.073l-3.68-6.414c-0.504-0.879-1.795-0.879-2.299 0l-3.679 6.414C11.427 20.935 12.062 22 13.072 22h7.358c1.008 0 1.643-1.065 1.15-1.927zM16.75 21a0.75 0.75 0 1 1 0-1.5 0.75 0.75 0 0 1 0 1.5zM16 15.725a0.75 0.75 0 0 1 1.5 0V17.9a0.75 0.75 0 0 1-1.5 0v-2.175z" /> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_synced_tabs.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_synced_tabs.xml deleted file mode 100644 index d1d5e12705060f2fa335345bf3ac7ecbdb9281ab..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/ic_synced_tabs.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:pathData="M20.5 19h-2a2.5 2.5 0 0 0 2.5-2.5v-7A2.5 2.5 0 0 0 18.5 7h-1v1.5h1.2l0.8 0.8v7.4l-0.8 0.8H7.3l-0.8-0.8V13H5v3.5A2.5 2.5 0 0 0 7.5 19h-2a1.5 1.5 0 0 0 0 3h15a1.5 1.5 0 0 0 0-3zm-6.75 1.5h-1.5a0.75 0.75 0 0 1 0-1.5h1.5a0.75 0.75 0 0 1 0 1.5z" - android:fillColor="?attr/textPrimary"/> - <path - android:pathData="M13.5 2.5h-9A2.5 2.5 0 0 0 2 5v4a2.5 2.5 0 0 0 2.5 2.5h9A2.5 2.5 0 0 0 16 9V5a2.5 2.5 0 0 0-2.5-2.5zM11 10H4.3L3.5 9.2V4.8L4.3 4H11v6zm3.25-2.25a0.75 0.75 0 0 1-1.5 0v-1.5a0.75 0.75 0 0 1 1.5 0v1.5z" - android:fillColor="?attr/textPrimary"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_tor_config_bridge.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_tor_config_bridge.xml new file mode 100644 index 0000000000000000000000000000000000000000..838a2d0085b936570b53315b83742a538ed8ef49 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/ic_tor_config_bridge.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="18dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z" + android:fillColor="#ffffff"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_tor_network_settings.xml b/mobile/android/fenix/app/src/main/res/drawable/ic_tor_network_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ffd3259ef51a33fa7ba4c75ff3e4076654dbbdd --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/ic_tor_network_settings.xml @@ -0,0 +1,14 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,0.75C18.2132,0.75 23.25,5.7865 23.25,11.9997C23.25,18.2132 18.2132,23.25 12,23.25C5.7865,23.25 0.75,18.2132 0.75,11.9997C0.75,5.7865 5.7865,0.75 12,0.75ZM12.0231,2.7958L12.0231,4.1596C16.3429,4.172 19.8408,7.677 19.8408,11.9997C19.8408,16.3227 16.3429,19.8277 12.0231,19.8401L12.0231,19.8401L12.0231,21.2039C17.0961,21.1914 21.2042,17.0758 21.2042,11.9997C21.2042,6.9239 17.0961,2.8086 12.0231,2.7958L12.0231,2.7958ZM12.0231,6.2057L12.0231,7.5691C14.4596,7.5819 16.4318,9.56 16.4318,11.9997C16.4318,14.4397 14.4596,16.4178 12.0231,16.4306L12.0231,16.4306L12.0231,17.794C15.2131,17.7816 17.7956,15.1928 17.7956,11.9997C17.7956,8.8069 15.2131,6.2181 12.0231,6.2057L12.0231,6.2057ZM12.0231,9.6146L12.0231,14.3851C13.3301,14.3726 14.3863,13.3101 14.3863,11.9997C14.3863,10.6896 13.3301,9.6271 12.0231,9.6146L12.0231,9.6146Z" + android:strokeAlpha="0.8" + android:strokeWidth="1" + android:fillColor="?attr/textPrimary" + android:fillType="evenOdd" + android:strokeColor="#00000000" + android:fillAlpha="0.8"/> +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_logo.webp b/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_logo.webp deleted file mode 100644 index 64d343791b927878c757be1f2baeb6f050e9206f..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_logo.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_normal.webp b/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_normal.webp deleted file mode 100644 index a18fa108eb09cb961aae180e5a2de918891f01c0..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_private.webp b/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_private.webp deleted file mode 100644 index fd2a18801d80941d266c767bcf17f12e74345ec9..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/drawable/microsurvey_success.xml b/mobile/android/fenix/app/src/main/res/drawable/microsurvey_success.xml deleted file mode 100644 index 2dc804118119c8b868a1a9874c6313895092bbe7..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/microsurvey_success.xml +++ /dev/null @@ -1,81 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="149dp" - android:height="136dp" - android:viewportWidth="149" - android:viewportHeight="136"> - <path - android:pathData="M29.01,94.78C27.83,93.06 29.31,87.17 29.4,86.72C29.43,86.41 30.76,79.47 30.83,79.11C30.89,78.92 34.6,71.13 37.02,67.92C39.53,64.6 43.16,61.26 46.71,59.19C53.48,55.22 60.85,52.75 68.97,52.89C70.48,52.92 74.9,53.81 75.26,52.89C75.35,52.68 73.95,49.51 73.95,49.51C73.37,47.95 72.37,46.37 72.89,44.68C73.49,42.75 75.8,40.63 77.07,39.08C79.88,35.66 79.11,33.47 79.04,29.35C78.97,25.11 80.12,20.34 80.92,16.17C81.77,11.78 86.13,-5.44 92.2,3.05C94.42,6.15 96,10.53 97.4,14.07C98.11,15.86 99.13,18.72 99.94,20.47C101.07,22.91 103.7,20.78 106.24,20.95C109.91,21.2 111.91,21.75 115.49,22.61C116.56,22.87 119.37,23.79 120.27,23.37C121.4,22.84 122.79,19.73 123.57,18.67C125.69,15.77 128.32,13.09 130.87,10.56C132.45,9 137.29,4.86 139.76,5.96C142.26,7.08 142.98,14.87 143.41,17.18C144.31,21.95 143.23,33.53 142.53,38.37C141.86,43 140.92,41.29 143.02,45.63C144.02,47.72 146.37,49.94 146.85,52.15C147.34,54.4 145.88,55.45 144.46,57.24C144.32,57.41 144.17,57.59 144.03,57.77C141.75,60.79 139.73,63.12 136.72,65.47C136.46,65.69 130.74,69.63 130.4,70.27C130.4,70.27 129.78,70.84 129.83,71.02C130.05,71.86 131.55,91.47 131.38,91.81C131.12,92.36 130.89,92.92 131.6,93.33C131.71,93.47 131.82,93.61 131.93,93.75L132.59,94.53C133.02,94.99 133.45,95.45 133.88,95.91L134.34,96.41L134.35,96.41C134.73,96.83 135.11,97.25 135.49,97.68C135.57,97.76 135.65,97.84 135.73,97.93C136.13,98.57 136.54,99.21 136.95,99.85C137.13,100.08 137.31,100.3 137.48,100.53C138.02,101.44 138.55,102.35 139.09,103.26L139.27,103.63C139.78,104.55 140.29,105.48 140.8,106.4C140.85,106.52 140.91,106.65 140.96,106.77C141.54,108.1 142.08,109.44 142.73,110.73C143.23,111.74 145.32,117.03 145.43,117.25C146.78,121.04 147.43,126.63 147.37,126.93C147.13,127.32 145.86,127.31 145.74,127.31C145.45,127.16 145.16,127.02 144.86,126.88C143.95,126.53 143.03,126.18 142.12,125.83C141.9,125.77 141.69,125.71 141.48,125.65C141.03,125.52 140.57,125.39 140.11,125.27C139.68,125.14 139.26,125.02 138.82,124.89L137.74,124.68C137.56,124.61 137.39,124.54 137.21,124.48C136.99,124.46 136.76,124.43 136.54,124.41C136.18,124.31 135.81,124.22 135.46,124.11C135.16,124.09 134.85,124.07 134.55,124.04C133.96,123.93 133.37,123.81 132.78,123.69C131.77,123.75 130.77,123.8 129.76,123.86C129.34,123.92 128.92,123.98 128.5,124.04C123.67,125.09 119.04,126.99 114.47,128.86C112.21,129.79 109.86,130.68 107.5,131.2C104.89,131.78 102.27,132.29 99.61,132.64C89.02,134.04 78.94,133.53 68.35,132.16C63.43,131.52 59.03,129.96 54.38,128.32C49.97,126.78 45.09,125.18 41.77,121.7C34.5,114.09 29.77,106.12 29.01,94.76L29.01,94.78Z" - android:fillColor="#FEA619"/> - <path - android:pathData="M141.57,42.25C140.83,43.32 139.26,43.75 138.24,43.4C136.95,42.95 136,42.92 135.38,41.49C134.93,40.49 135.63,38.17 134.93,37.43C134.22,36.69 132.46,37.24 131.54,36.24C130.38,34.97 129.22,33.1 129.47,31.6C130.09,27.71 134.11,17.12 134.79,15.15C135.33,13.57 136.39,9.98 137.69,8.85C141.08,5.94 141.88,11.21 142.75,13.67C144.24,17.87 144.95,28.21 141.57,42.25Z" - android:fillColor="#FE6D2E"/> - <path - android:pathData="M79.31,31.56C80.13,25.51 80.61,19.28 81.99,13.34C82.67,10.44 83.41,7.16 85.25,4.76C87.03,2.44 88.2,4.22 88.81,6.44C90.26,11.76 90.26,15.15 91.17,23.74C89.78,26.28 88.95,27.78 86.97,29.56C84.73,31.56 81.74,34.94 79.12,36.44C78.82,35.16 79.39,31.56 79.3,31.56H79.31Z" - android:fillColor="#FE6D2E"/> - <path - android:pathData="M85.42,133.72C80.63,132.59 75.65,132.78 70.78,132.01C65.74,131.21 61.2,130.46 56.38,128.74C52.09,127.22 47.43,125.97 43.66,123.32C40.64,121.2 36.93,116.88 35.61,113.45C38.29,113.94 40.36,115.4 43.18,115.7C45.73,115.97 47.88,115.94 50.36,115.21C55.69,113.65 59.66,110.51 64.23,107.46C73.96,100.94 84.22,96.12 95.98,94.9C98.9,94.59 100.45,94.43 103.02,95.77C105.76,97.2 108.07,97.55 111.13,97.34C117.22,96.92 123.35,96.77 129.43,96.24C132.84,95.95 134.08,95.73 136.01,98.74C137.59,101.2 139.05,103.72 140.42,106.29C141.71,108.7 142.98,111.13 144.14,113.6C145.24,115.94 145.82,119.65 147.37,121.62V122.58C146.25,124.12 147.11,126.43 145.09,126.81C143.17,127.18 139.39,124.8 137.42,124.36C131.57,123.03 126.87,123.54 121.22,125.41C118.6,126.27 115.99,127.24 113.42,128.25C111.04,129.19 108.91,130.53 106.4,131.09C100.75,132.37 94.93,132.43 89.29,133.71H89.05C88.08,133.19 87.11,133.25 86.15,133.71H85.42L85.42,133.72Z" - android:fillColor="#FE7C01"/> - <path - android:pathData="M125.07,72.66C121.55,73.24 118.08,71.95 114.64,71.42C111.08,70.87 107.45,70.95 103.87,70.74C106.41,66.51 111.35,63.65 115.18,60.73C119.05,57.78 122.9,54.61 125.71,50.59C128.55,46.51 130.01,41.71 129.64,36.74C129.48,34.65 128.05,31.34 130.01,29.71C131.67,28.34 133.35,29.51 134.16,31.13C134.7,32.19 134.67,33.43 135.27,34.54C135.8,35.52 136.57,36.45 137.22,37.35C138.93,39.73 140.77,42.12 142.25,44.65C143.57,46.9 144.68,49.4 145.83,51.74C147.21,54.57 145.66,55.64 143.82,57.96C140.57,62.08 130.44,70.6 129.99,70.69C129.61,71 130.45,71.96 129.13,72.67C128.35,73.08 125.96,72.66 125.06,72.66H125.07Z" - android:fillColor="#FE7C01"/> - <path - android:pathData="M95.5,10.01C96.68,12.88 97.82,15.79 99.04,18.65C99.65,20.1 100.75,21.02 101.88,21.44C103.09,21.89 104.42,20.37 105.75,20.95C100.91,22.4 98.36,23.53 96.29,21C94.01,18.2 94.87,13.32 95.14,10.04C95.26,10.03 95.38,10.02 95.5,10.01Z" - android:fillColor="#FE7C01"/> - <path - android:pathData="M146.4,127.91C142.78,127.43 129.88,124.14 129.5,123.85C128.79,123.3 129.16,123.12 129.03,122.24C128.65,119.76 129,117.89 127.36,115.69C124.59,111.98 119.25,110.18 114.88,109.35C111.75,108.76 112.29,108.53 110.22,106.25C108.69,104.56 106.69,103.35 104.65,102.36C102.25,101.2 99.66,99.91 97.16,99.03C94.38,98.05 91.75,98.9 89,98.49C91.25,95.39 96.22,93.28 99.66,91.79C103.16,90.26 106.37,89.3 110.52,88.41C110.85,88.33 111,87.95 110.8,87.67C109.01,85.25 104.64,80.8 97.52,79.03C97.52,79.03 87.84,77.58 69.45,86.77C70.11,84.31 76.81,77.54 78.99,75.47C85.91,68.86 87.84,68.38 86.87,66.93C86.71,66.77 77.36,55.96 77.19,55.8L73.31,45.89L73.32,44.67C73.65,44.5 77.46,44.79 79.02,45.17C79.49,45.29 86.99,49.06 89.29,50.96C90.3,51.79 94.76,54.96 95.59,56.28C98,49.51 105.64,49.73 108.06,50.08C110.17,50.39 115.87,51.8 118.06,58.27C118.2,58.7 118.69,58.9 119.09,58.68C123.53,56.16 138.08,53.54 139.15,53.38C139.39,53.38 146.69,53.43 146.78,54.34C146.9,55.5 143.02,59.17 142.33,59.92C139.33,63.18 131.08,70.08 130.92,70.08C129.82,70.27 129.56,71.15 129.47,71.77C129.47,71.77 132.85,85.32 130.92,93.06C130.92,93.06 135.12,97.26 135.27,97.42C135.27,97.42 147.63,110.98 146.41,127.91H146.4Z" - android:fillColor="#FEEDD3"/> - <path - android:pathData="M91.46,25.31C89.78,27.24 86.77,29.77 84.94,31.6C83.32,33.21 82.52,32.73 82.52,30.15C83.25,22.4 85.42,17.64 85.42,17.56C87.04,16.47 88.81,19.5 88.81,19.5C88.81,19.5 89.87,18.13 90.74,18.05C90.82,18.45 91.38,24.66 91.46,25.31Z" - android:fillColor="#FEEDD3"/> - <path - android:pathData="M146.89,127.91C145.1,128.01 140.2,125.58 138.32,125.12C135.71,124.47 133.12,123.75 130.42,123.98C130.42,123.98 124.94,124.93 122.33,125.6C119.34,126.36 109.42,131.25 107.21,131.79C102.2,132.99 97.53,133.72 92.21,133.6C92.17,133.49 100.41,128.52 104.31,125.62C106.18,124.23 108,122.71 109.54,120.95C111.31,118.93 111.08,119.69 107.24,118.58C102.3,117.23 97.29,116.1 92.36,114.74C89.26,113.88 89.79,113.88 92.51,111.42C94.09,109.98 96.57,108.07 97.66,106.68C96.14,105.88 88.09,103.68 85.18,102.92C84.86,102.84 84.75,102.44 84.97,102.2C86.03,101.07 88.47,98.48 89.23,97.83C90.1,97.08 91.33,95.86 92.21,95.48C93.66,94.99 95.53,95.08 96.57,94.99C101.5,94.6 104.61,95.2 109.52,95.81C116.63,97.26 118.49,97.4 121.82,98.53C122.17,98.64 122.46,98.25 122.25,97.95C121.22,96.53 120.1,95.15 119.1,93.72C118.83,93.33 119.21,92.82 119.66,92.96C122.66,93.88 125.61,94.84 128.51,96.08C131.57,97.39 135.58,98.91 137.82,101.46C140.04,104.01 141.3,108 142.79,111.02C144.51,114.52 148.71,127.8 146.89,127.9L146.89,127.91Z" - android:fillColor="#FE9A94"/> - <path - android:pathData="M130.41,91.79C128.32,90.65 120.6,85.95 118.75,84.73C115.96,82.9 114.93,78.46 112.35,76.03C109.48,73.32 105.33,73.24 102.15,70.92C99.16,68.74 96.02,64.83 95.94,60.97C98,64.03 101.16,66.92 105.86,67.48C109.24,67.88 114.26,65.68 114.95,64.99C118.33,61.61 117.78,60 118.33,59.19C119.4,57.62 127.64,55.25 132.85,54.35C134.27,54.1 144.7,52.74 145.91,53.5C147.53,54.52 144.04,57.57 143.17,58.64C140.17,62.32 130.44,69.75 129.95,71.14C129.65,71.97 133.51,92.11 130.41,91.78V91.79Z" - android:fillColor="#FE9A94"/> - <path - android:pathData="M129.95,29.66C130.38,27.76 131.48,21.9 132.85,20.47C133.75,21.38 134.79,24.34 134.79,24.34C135.92,24.36 137.82,21.36 138.66,21.92C140.44,23.09 140.88,29.33 140.6,31.12C140.44,32.08 139.26,37.19 138.18,37.41C137.26,37.59 135.19,35.39 134.93,34.62C132.85,28.21 133.34,27.73 129.95,29.66Z" - android:fillColor="#FE9A94"/> - <path - android:pathData="M91.23,25.31C89.78,27.24 87.22,30.01 86.88,29.66C86.39,29.18 88.28,25.15 88.51,24.45C89,22.92 89.96,20.9 90.75,19.5C91.72,21.08 91.23,23.47 91.23,25.31Z" - android:fillColor="#FE9A94"/> - <path - android:pathData="M144.95,112.95C142.22,105.54 138.07,99 132.12,93.52C132.98,86 131.4,78.57 130.27,71.13C130.78,70.79 131.36,70.45 131.87,70.03C133.4,68.73 134.85,67.32 136.45,66.1C140.29,63.17 143.41,59.54 146.41,55.82C147.4,54.6 148.05,53.13 146.94,51.32C145.36,48.77 144.1,46.01 142.74,43.33C142.53,42.92 142.26,42.34 142.4,42C143.38,39.59 143.65,37.04 144.03,34.51C144.63,30.39 145.01,26.26 144.65,22.13C144.16,16.61 143.58,11.09 141.6,5.83C141.11,4.53 140.34,3.82 139.02,4.1C138.02,4.31 136.93,4.62 136.12,5.21C132.85,7.59 129.95,10.39 127.36,13.48C124.89,16.42 122.5,19.42 119.92,22.59C113.98,21.09 107.9,19.47 101.57,20.81C99.17,14.27 96.27,8.07 92.45,2.33C91.87,1.46 90.81,0.76 89.81,0.33C88.15,-0.38 87.11,0.06 86.11,1.53C84.17,4.37 82.59,7.38 81.55,10.67C80.21,14.89 79.18,19.19 78.68,23.6C78.24,27.49 78.16,31.59 78.38,35.35C78.26,35.51 78.11,35.7 77.97,35.89C76.26,38.21 74.53,40.51 72.86,42.86C72,44.07 71.79,45.41 72.35,46.85C72.87,48.16 73.31,49.5 73.8,50.83C73.95,51.26 74.14,51.67 74.41,52.29C73.82,52.25 73.48,52.21 73.13,52.2C71.03,52.13 68.93,52.01 66.83,52.04C65.54,52.05 64.25,52.16 62.98,52.35C60.51,52.71 58.01,53.01 55.63,53.68C49.9,55.3 45.05,58.56 40.74,62.57C37.03,66.02 34.04,70.04 32.21,74.84C31.51,76.68 30.52,78.4 29.75,80.21C28.56,82.98 28.44,85.99 27.92,88.91C27.16,93.24 27.71,97.51 28.8,101.67C29.95,106.11 32,110.21 34.43,114.1C36.81,117.89 39.72,121.17 43.33,123.83C46.27,126.01 49.43,127.81 52.89,129.03C55.44,129.92 58.01,130.81 60.61,131.54C64.06,132.51 67.51,133.7 71.04,134.13C76.3,134.76 81.63,134.99 86.93,135.05C90.82,135.09 94.72,134.68 98.59,134.26C101.29,133.97 103.99,133.45 106.63,132.81C109.24,132.18 111.83,131.39 114.34,130.44C116.96,129.45 119.43,128.1 122.04,127.07C123.93,126.33 125.9,125.5 127.89,125.34C132.67,124.96 137.28,126.2 141.84,127.53C143.11,127.9 144.33,128.31 145.62,128.58C147.02,128.87 148.3,127.69 148.15,126.27C147.66,121.8 146.47,117.04 144.96,112.95H144.95ZM144.43,126.32C141.01,125.16 137.51,124.35 133.98,123.61C130.72,122.93 125.59,122.58 115.46,127.74C112.12,129.44 108.48,130.35 104.86,131.23C102.91,131.71 100.9,131.92 98.94,132.32C94.77,133.16 90.54,133.26 86.33,133.17C81.83,133.07 77.33,132.75 72.86,132.33C70.11,132.07 67.35,131.62 64.67,130.94C61.69,130.18 58.77,129.13 55.86,128.1C52.11,126.78 48.48,125.2 45.24,122.83C40.86,119.62 37.41,115.68 34.81,110.89C33.05,107.63 31.49,104.3 30.51,100.74C29.41,96.71 29.49,92.59 29.82,88.43C30.22,83.48 32.24,79.13 34.28,74.75C35.51,72.09 36.71,69.36 38.82,67.28C41.37,64.79 43.98,62.31 46.81,60.16C50.91,57.05 55.63,55.19 60.76,54.56C63.38,54.23 69.46,53.38 74.96,54.21C75.2,54.24 75.45,54.31 75.59,54.52C76.97,56.53 78.3,58.53 79.71,60.47C80.57,61.64 83.98,64.51 84.95,64.51C85.46,64.51 85.27,63.86 84.93,63.47C83.97,62.4 83.13,61.47 82.29,60.52C78.99,56.81 76.61,52.54 74.67,48.02C74.34,47.25 73.99,46.47 73.8,45.65C73.71,45.29 73.89,44.78 74.11,44.45C75.64,42.23 77.23,40.06 78.76,37.85C79.08,37.38 80.16,36.16 80.11,35.95C79.14,32.4 80.86,21.05 81.45,18.57C82.25,15.26 83.22,11.98 84.3,8.75C85.01,6.61 86.24,3.87 87.99,1.94C88.2,1.71 88.54,1.65 88.81,1.78C91.38,2.92 92.63,5.86 93.8,8.24C95.7,12.09 97.4,16.04 99.18,19.94C99.5,20.63 99.82,21.32 100.14,21.97C100.26,22.23 100.51,22.39 100.79,22.39C103.95,22.37 107.08,22.16 110.17,22.45C113.22,22.74 116.23,23.54 119.46,24.18C119.75,24.24 120.02,24.41 120.19,24.66L120.25,24.73C120.36,24.89 120.59,24.9 120.72,24.75C124.28,20.43 127.61,16.27 131.1,12.24C132.56,10.54 134.36,9.15 136.01,7.62C136.12,7.53 136.79,6.82 137.71,6.42C138.84,5.93 140.16,6.55 140.49,7.74C143.5,18.33 143.91,29.45 140.98,40.28C140.89,40.62 140.65,40.91 140.32,41.03C140.31,41.03 140.31,41.03 140.3,41.04C139.88,41.19 139.68,41.66 139.89,42.05C141.84,45.79 143.73,49.43 145.66,53.15C145.79,53.4 145.76,53.69 145.6,53.92C140.83,60.29 134.77,65.2 128.59,70.45C128.39,70.61 128.3,70.86 128.34,71.12C129.39,77.31 130.82,83.69 130.48,90.42C130.45,90.98 129.83,91.3 129.37,90.99C129.1,90.81 128.84,90.64 128.59,90.47C126.95,89.39 125.3,88.33 123.69,87.22C122.21,86.2 120.74,85.14 119.31,84.04C116.33,81.73 112.84,80.6 109.29,79.53C104.95,78.23 100.5,78.03 96.03,78.01C90.59,77.98 85.2,79 80.15,81.04C76.81,82.39 73.43,83.69 70.16,85.22C66.25,87.05 62.77,89.57 59.49,92.4C55.83,95.58 51.88,98.41 47.01,99.37C44.88,99.79 42.64,99.79 40.46,99.72C39.52,99.69 38.95,99.68 38.55,99.9C38.04,100.17 38.1,100.93 38.63,101.17C39.92,101.76 41.35,101.74 42.73,101.75C49.19,101.85 54.55,99.06 59.35,95.06C62.87,92.11 66.4,89.18 70.57,87.21C74.24,85.47 77.97,83.87 81.76,82.44C85.16,81.15 88.71,80.12 92.37,79.97C95.61,79.84 98.88,80.11 102.13,80.26C107.19,80.49 112.13,81.69 116.31,84.44C121.38,87.78 126.78,90.68 131.11,95.15C134.41,98.56 137.34,102.14 139.7,106.24C142.62,111.3 144.55,116.71 145.72,122.41C145.91,123.32 146.15,124.21 146.32,125.12C146.37,125.38 146.4,125.64 146.43,125.92C146.48,126.45 145.96,126.85 145.47,126.67C145.11,126.54 144.77,126.42 144.44,126.31L144.43,126.32Z" - android:fillColor="#000000"/> - <path - android:pathData="M98.4,64.68C102.43,67.77 106.84,69.03 111.93,67.07C114.47,66.1 116.35,64.6 117.7,62.35C117.94,61.94 118.21,60.58 117.86,60.15C117.73,60.1 117.44,60.98 117.37,61.12C115.73,64.95 112.21,66.59 108.54,67.02C104.23,67.51 100.31,65.93 97.55,62.45C95.76,60.2 94.76,57.59 96.56,54.83C96.7,54.61 97.53,52.89 96.63,53.83C96.24,54.39 95.84,54.95 95.45,55.49C93.22,53.69 91.01,51.9 88.79,50.12C85.13,47.15 81.08,45.15 75.27,44.66C74.7,44.61 73.33,44.66 73.33,45.15C82.53,45.15 89.32,50.75 95.11,56.28C94.63,59.66 95.85,62.71 98.41,64.67L98.4,64.68Z" - android:fillColor="#000000"/> - <path - android:pathData="M131.96,29.15C132.08,29.04 132.27,29.01 132.4,29.1C132.72,29.34 132.94,29.9 133.05,30.49C133.19,31.27 133.44,32.05 133.71,32.8C133.85,33.16 134.3,34.02 134.79,34.02C134.97,33.92 134.79,33.54 134.79,33.54C134.24,31.98 133.86,30.34 133.29,28.79C133.02,28.05 132.46,27.99 131.82,28.33C131.62,28.44 131.09,28.85 130.74,29.06C130.63,29.13 130.48,29.03 130.52,28.89C131.01,26.76 131.93,23.63 132.85,21.44C133.34,21.93 134.14,23.33 134.3,23.86C134.75,25.28 134.76,25.22 135.91,24.31C136.61,23.74 137.36,23.23 138.21,22.63C138.33,22.55 138.51,22.57 138.58,22.7C138.86,23.15 139.55,24.46 139.63,24.83C139.92,26.12 141.08,30.64 138.58,36.27C138.4,36.69 138.18,37.9 138.45,37.7C138.57,37.72 139.53,36.16 139.63,35.96C140.6,34.02 141.55,29.11 140.51,24.85C140.27,23.91 139.88,22.91 139.27,22.18C138.56,21.34 138.48,21.42 137.21,22.41C136.76,22.76 135.76,23.38 135.27,23.86C134.64,22.69 133.85,21.36 133.26,20.28C134.23,17.75 135.28,15.06 136.3,12.36C136.49,11.84 136.56,11.27 136.69,10.73C136.73,9.83 135.71,11.36 135.53,11.78C133.07,17.56 130.97,23.45 129.58,29.59C129.53,29.83 129.49,30.17 129.57,30.5C129.64,30.84 130.04,30.94 130.28,30.72C130.89,30.15 131.39,29.69 131.96,29.16L131.96,29.15Z" - android:fillColor="#000000"/> - <path - android:pathData="M82.91,31.74C82.88,26.97 83.59,22.39 85.89,18.12C86.05,17.82 86.46,17.78 86.69,18.02C87.41,18.79 88.05,19.5 88.71,20.21C89.09,19.63 90.08,18.5 90.27,18.53C90.75,23.37 90.74,23.35 90.88,24.34C90.99,25.08 90.75,25.53 90.14,25.96C89.71,26.27 88.81,27.73 89.47,27.58C90.1,27.13 90.73,26.68 91.37,26.22C91.76,25.95 91.97,25.49 91.93,25.02C91.79,23.45 91.69,21.86 91.47,20.28C90.92,16.31 90.32,12.34 89.69,8.37C89.61,7.88 88.81,5.95 88.59,7.09C89.19,10.59 89.29,10.78 90.26,17.56C89.45,18.05 89.29,18.53 88.81,19.01C88.57,18.68 87.96,18.01 87.75,17.72C86.67,16.23 85.67,16.26 84.86,17.87C82.83,21.89 82.01,26.21 81.91,30.69C81.9,31.09 82.51,32.56 82.9,31.74L82.91,31.74Z" - android:fillColor="#000000"/> - <path - android:pathData="M118.82,58.7C119.3,59.19 121.88,57.86 122.21,57.73C126.08,56.28 128.24,55.55 132.37,54.83C143.5,52.89 146.4,53.86 146.89,53.38C146.87,53.26 146.51,52.89 143.98,52.89C140.11,52.89 135.97,53.61 132.29,54.21C127.84,54.93 123.56,56.27 119.45,58.16C119.09,58.32 118.71,58.6 118.82,58.7Z" - android:fillColor="#000000"/> - <path - android:pathData="M109.14,55.04C109.79,54.06 109.35,53.05 108.17,52.89C107.5,52.81 106.72,52.41 105.27,52.41C103.82,52.41 103.67,52.53 102.85,52.89C101.53,53.48 102.23,54.38 103.33,55.31C104.97,56.69 107.98,56.8 109.14,55.04Z" - android:fillColor="#000000"/> - <path - android:pathData="M98.97,48.05C100.43,48.05 100.51,48.03 100.91,47.57C101.37,47.03 101.68,45.39 101.71,44.66C101.76,43.8 101.88,43.22 101.24,42.11C100.75,41.25 99.46,40.8 98.15,41.99C97.04,44.19 97.53,44.87 97.53,46.12C97.53,46.61 98.25,48.06 98.98,48.06L98.97,48.05Z" - android:fillColor="#000000"/> - <path - android:pathData="M116.4,49.02C117.37,48.54 117.85,47.57 117.92,46.63C118,45.69 118.33,44.67 117.9,43.77C116.89,42.25 114.5,42.92 114.26,44.75C114.14,45.7 113.91,46.61 113.98,47.57C114.07,48.85 115.33,49.56 116.4,49.02Z" - android:fillColor="#000000"/> - <path - android:pathData="M100.91,60.64C103.42,62.55 106.09,63.02 109.17,62.75C109.78,62.69 110.59,62.09 110.91,61.64C110.99,61.53 110.83,61.4 110.7,61.43C106.83,62.32 103.34,61.74 100.39,58.9C100.29,58.8 100.18,58.88 100.09,58.99C99.95,59.19 100.22,60.11 100.92,60.64L100.91,60.64Z" - android:fillColor="#000000"/> - <path - android:pathData="M101.53,50.69C101.76,50.67 102,50.63 102.24,50.58C104.88,49.97 107.45,49.81 110.13,50.71C110.95,50.98 111.75,51.34 112.75,51.89C112.91,51.98 114.83,53.45 113.49,51.92C111.22,49.32 103.86,48.55 101.36,50.55C101.42,50.6 101.48,50.69 101.53,50.68V50.69Z" - android:fillColor="#000000"/> - <path - android:pathData="M30.25,21.19C32.19,21.19 34.12,21.19 36.06,21.19C43.66,23.1 50.13,24.8 55.96,30.49C61.78,36.17 64.4,43.12 65.82,50.96V56.77C63.93,64.39 62.19,70.9 56.48,76.72C50.82,82.51 43.86,85.1 36.06,86.53H30.25C22.65,84.63 16.18,82.93 10.35,77.24C4.53,71.56 1.91,64.6 0.49,56.77C0.49,54.83 0.49,52.89 0.49,50.96C2.39,43.34 4.12,36.83 9.83,31C15.5,25.22 22.45,22.63 30.25,21.19Z" - android:fillColor="#84D09A"/> - <path - android:pathData="M9.97,30.48C15.84,24.33 24.42,20.69 32.94,20.47C41.42,20.25 49.75,24.04 55.93,29.69C58.86,32.37 68.96,42.73 66.79,57.73C66.54,59.18 64.63,85.14 35.09,87.25C21.54,88.22 12.57,80.81 9.65,77.7C3.61,71.26 0.24,64.99 0,54.83C0.24,44.66 3.95,36.77 9.96,30.47L9.97,30.48ZM64.65,55.33C65.58,40.52 54.62,27.1 40.53,23.4C27.94,20.1 13.9,26.48 7.23,37.35C0.41,48.46 0.85,62.4 8.41,72.96C16.03,83.62 31.61,87.99 43.94,83.65C55.59,79.55 64.96,67.96 64.64,55.33H64.65Z" - android:fillColor="#354158"/> - <path - android:pathData="M48.64,36.92C50.58,38.86 51.26,39.57 52.6,40.93C53.57,41.9 53.97,42.73 56.39,45.39C46.22,54.83 37.03,64.51 26.87,74.43C26.82,74.43 14.69,62.32 8.72,56.28C8.72,56.2 12.25,52.65 13.9,50.98C15.09,49.79 17.19,48.05 17.19,48.05C17.19,48.05 21.28,52.29 22.67,53.73C23.44,54.52 26.87,58.22 26.87,58.22C26.87,58.22 31.23,53.83 32.13,52.96C33.97,51.18 35.8,49.39 37.62,47.58C41.25,43.99 45.08,40.59 48.64,36.92Z" - android:fillColor="#E5FEEC"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/new_circuit.xml b/mobile/android/fenix/app/src/main/res/drawable/new_circuit.xml new file mode 100644 index 0000000000000000000000000000000000000000..87399ed6ba59e725a589f6cf92eb1accfb7bd6e5 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/new_circuit.xml @@ -0,0 +1,7 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="16dp" android:viewportHeight="16" android:viewportWidth="16" android:width="16dp"> + + <path android:fillColor="#5B5B66" android:fillType="evenOdd" android:pathData="M10.599,2.897C9.522,2.349 8.298,2.155 7.104,2.344C6.642,2.417 6.195,2.546 5.769,2.726C5.822,2.91 5.85,3.105 5.85,3.307C5.85,4.48 4.898,5.432 3.725,5.432C2.551,5.432 1.6,4.48 1.6,3.307C1.6,2.133 2.551,1.182 3.725,1.182C4.238,1.182 4.708,1.363 5.075,1.666C5.654,1.399 6.271,1.21 6.908,1.109C8.363,0.879 9.854,1.115 11.167,1.784C12.479,2.452 13.547,3.52 14.216,4.832C14.885,6.145 15.121,7.635 14.891,9.09C14.837,9.431 14.517,9.664 14.176,9.61C13.835,9.556 13.602,9.236 13.656,8.895C13.845,7.701 13.651,6.477 13.102,5.4C12.553,4.322 11.677,3.446 10.599,2.897ZM4.65,3.307C4.65,3.818 4.235,4.232 3.725,4.232C3.214,4.232 2.8,3.818 2.8,3.307C2.8,2.796 3.214,2.382 3.725,2.382C4.235,2.382 4.65,2.796 4.65,3.307Z"/> + + <path android:fillColor="#5B5B66" android:fillType="evenOdd" android:pathData="M1.824,6.39C2.165,6.444 2.398,6.764 2.344,7.105C2.155,8.299 2.349,9.523 2.898,10.6C3.447,11.678 4.323,12.554 5.401,13.103C6.478,13.651 7.702,13.845 8.896,13.656C9.356,13.583 9.803,13.455 10.227,13.276C10.173,13.088 10.144,12.891 10.144,12.686C10.144,11.512 11.096,10.561 12.269,10.561C13.443,10.561 14.394,11.512 14.394,12.686C14.394,13.86 13.443,14.811 12.269,14.811C11.76,14.811 11.293,14.632 10.927,14.333C10.347,14.601 9.73,14.79 9.092,14.891C7.637,15.121 6.146,14.885 4.833,14.216C3.52,13.548 2.453,12.481 1.784,11.168C1.115,9.855 0.879,8.365 1.109,6.91C1.163,6.569 1.483,6.336 1.824,6.39ZM13.194,12.686C13.194,13.197 12.78,13.611 12.269,13.611C11.759,13.611 11.344,13.197 11.344,12.686C11.344,12.175 11.759,11.761 12.269,11.761C12.78,11.761 13.194,12.175 13.194,12.686Z"/> + +</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_default_browser.xml b/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_default_browser.xml deleted file mode 100644 index 299326f670f810eed73390fbcf2af8cba4ebb873..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_default_browser.xml +++ /dev/null @@ -1,111 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="316dp" - android:height="304dp" - android:viewportWidth="316" - android:viewportHeight="304"> - <group> - <clip-path - android:pathData="M264.6,0L6.81,8.52L0,113.4L6.81,270.98L169.83,281.1H307.19V128.3L315.17,0H264.6Z"/> - <path - android:pathData="M0,-15h328v319h-328z" - android:fillColor="#FFBDC5"/> - <path - android:pathData="M386.98,179.29L307.53,179.29A38.63,38.63 0,0 1,268.9 140.66L268.9,140.66A38.63,38.63 0,0 1,307.53 102.04L386.98,102.04A38.63,38.63 0,0 1,425.61 140.66L425.61,140.66A38.63,38.63 0,0 1,386.98 179.29z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,141.37m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M386.98,297.21L307.53,297.21A38.63,38.63 0,0 1,268.9 258.59L268.9,258.59A38.63,38.63 0,0 1,307.53 219.96L386.98,219.96A38.63,38.63 0,0 1,425.61 258.59L425.61,258.59A38.63,38.63 0,0 1,386.98 297.21z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,259.28m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M386.98,61.35L307.53,61.35A38.63,38.63 45,0 1,268.9 22.72L268.9,22.72A38.63,38.63 135,0 1,307.53 -15.9L386.98,-15.9A38.63,38.63 135,0 1,425.61 22.72L425.61,22.72A38.63,38.63 45,0 1,386.98 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M307.67,23.43m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M197.61,297.21L118.16,297.21A38.63,38.63 0,0 1,79.53 258.59L79.53,258.59A38.63,38.63 0,0 1,118.16 219.96L197.61,219.96A38.63,38.63 0,0 1,236.24 258.59L236.24,258.59A38.63,38.63 0,0 1,197.61 297.21z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M118.29,259.28m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M197.61,61.35L118.16,61.35A38.63,38.63 45,0 1,79.53 22.72L79.53,22.72A38.63,38.63 135,0 1,118.16 -15.9L197.61,-15.9A38.63,38.63 135,0 1,236.24 22.72L236.24,22.72A38.63,38.63 45,0 1,197.61 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M118.29,23.43m31.09,-2.14a31.16,31.16 131.07,1 1,-62.18 4.28a31.16,31.16 131.07,1 1,62.18 -4.28" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M6.24,297.22L-73.21,297.22A38.63,38.63 0,0 1,-111.84 258.59L-111.84,258.59A38.63,38.63 0,0 1,-73.21 219.96L6.24,219.96A38.63,38.63 0,0 1,44.87 258.59L44.87,258.59A38.63,38.63 0,0 1,6.24 297.22z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M192.4,92.73L109.07,107.42A41.21,41.21 80.09,0 0,75.64 155.17L75.64,155.17A41.21,41.21 80.09,0 0,123.38 188.6L206.72,173.91A41.21,41.21 80.09,0 0,240.15 126.16L240.15,126.16A41.21,41.21 80.09,0 0,192.4 92.73z" - android:strokeWidth="2.19" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M198.57,132.74m33.08,-3.51a33.26,33.26 128.94,1 0,-66.16 7.03a33.26,33.26 128.94,1 0,66.16 -7.03" - android:strokeWidth="2.19" - android:fillColor="#2AC3A2" - android:strokeColor="#000000"/> - <path - android:pathData="M205.3,124.39m2.66,-0.28a2.68,2.68 128.94,1 0,-5.32 0.57a2.68,2.68 128.94,1 0,5.32 -0.57" - android:fillColor="#000000"/> - <path - android:pathData="M191.1,125.9m2.66,-0.28a2.68,2.68 128.94,1 0,-5.32 0.57a2.68,2.68 128.94,1 0,5.32 -0.57" - android:fillColor="#000000"/> - <path - android:pathData="M177.98,129.09C179.18,140.37 189.29,148.53 200.56,147.34C211.83,146.14 220,136.03 218.8,124.75" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="M6.24,179.29L-73.21,179.29A38.63,38.63 0,0 1,-111.84 140.66L-111.84,140.66A38.63,38.63 0,0 1,-73.21 102.04L6.24,102.04A38.63,38.63 0,0 1,44.87 140.66L44.87,140.66A38.63,38.63 0,0 1,6.24 179.29z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="M6.24,61.35L-73.21,61.35A38.63,38.63 45,0 1,-111.84 22.72L-111.84,22.72A38.63,38.63 135,0 1,-73.21 -15.9L6.24,-15.9A38.63,38.63 0,0 1,44.87 22.72L44.87,22.72A38.63,38.63 0,0 1,6.24 61.35z" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - </group> - <path - android:pathData="M185.29,263.99L193.01,244.47L37.44,240.82L33.38,265.98L24.27,270.75L29.86,300.24L187.19,304L198.89,295.67L197.17,265.98L185.29,263.99Z" - android:fillColor="#181818"/> - <path - android:pathData="M52.58,271.72C47.67,271.72 44.41,268.07 44.41,263.53C44.41,258.87 47.89,255.33 52.58,255.33C55.67,255.33 58.27,256.9 59.69,259.26L56.34,261.38C55.62,259.96 54.36,259.07 52.61,259.07C50.07,259.07 48.3,261.06 48.3,263.53C48.3,265.95 50.03,267.94 52.56,267.94C54.46,267.94 55.78,266.85 56.43,265.34L59.95,267.22C58.6,269.86 55.99,271.72 52.58,271.72ZM70.19,271.5V265.36H64.97V271.5H61.14V255.55H64.97V261.6H70.19V255.55H74.01V271.5H70.19ZM74.94,271.5L80.84,255.55H84.51L90.41,271.5H86.54L85.71,269.12H79.61L78.78,271.5H74.94ZM82.67,260.44L80.79,265.8H84.55L82.67,260.44ZM91.32,271.5V255.55H95.14V267.85H102.1V271.5H91.32ZM103.67,271.5V255.55H107.49V267.85H114.44V271.5H103.67ZM116.01,271.5V255.55H127.03V259.09H119.82V261.71H127.03V265.25H119.82V267.96H127.03V271.5H116.01ZM128.9,271.5V255.55H132.87L138.88,265.12V255.55H142.51V271.5H138.82L132.54,261.47V271.5H128.9ZM152.46,271.72C147.26,271.72 144.09,267.94 144.09,263.53C144.09,258.89 147.5,255.33 152.31,255.33C155.37,255.33 157.62,256.6 159.13,258.54L155.94,260.79C155.17,259.61 153.95,258.94 152.33,258.94C149.86,258.94 147.9,260.9 147.9,263.53C147.9,266.24 149.75,268.09 152.4,268.09C154.23,268.09 155.52,267.17 156.07,265.6H151.63V262.06H160.2V263.88C160.2,268.09 157.07,271.72 152.46,271.72ZM161.83,271.5V255.55H172.84V259.09H165.63V261.71H172.84V265.25H165.63V267.96H172.84V271.5H161.83Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M97.56,291.61V275.65H103.22C108.18,275.65 111.52,279.11 111.52,283.63C111.52,288.18 108.03,291.61 103.29,291.61H97.56ZM103.04,279.19H101.36V288.04H103.11C105.91,288.04 107.68,286.1 107.68,283.63C107.68,281.12 106.04,279.19 103.04,279.19ZM113.11,291.61V275.65H124.12V279.19H116.91V281.82H124.12V285.36H116.91V288.07H124.12V291.61H113.11ZM125.99,291.61V275.65H136.96V279.24H129.79V282.08H136.96V285.6H129.79V291.61H125.99ZM136.37,291.61L142.27,275.65H145.94L151.84,291.61H147.97L147.14,289.23H141.05L140.21,291.61H136.37ZM144.1,280.55L142.23,285.9H145.99L144.1,280.55ZM158.17,291.83C154.24,291.83 151.73,289.46 151.73,285.33V275.65H155.6V285.33C155.6,287.11 156.6,288.11 158.15,288.11C159.68,288.11 160.75,287.11 160.75,285.33V275.65H164.62V285.33C164.62,289.46 162.11,291.83 158.17,291.83ZM166.53,291.61V275.65H170.35V287.96H177.3V291.61H166.53ZM179.33,291.61V279.17H175.01V275.65H187.33V279.17H183.05V291.61H179.33Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M50.88,291.61V279.17H46.55V275.65H58.88V279.17H54.59V291.61H50.88ZM69.59,291.61V285.47H64.37V291.61H60.55V275.65H64.37V281.71H69.59V275.65H73.42V291.61H69.59ZM75.39,291.61V275.65H86.41V279.19H79.19V281.82H86.41V285.36H79.19V288.07H86.41V291.61H75.39Z" - android:fillColor="#ffffff"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_notification.xml b/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_notification.xml deleted file mode 100644 index 11c10ed905139c308035c3e93b78ab6e20985ddb..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_notification.xml +++ /dev/null @@ -1,50 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="317dp" - android:height="288dp" - android:viewportWidth="317" - android:viewportHeight="288"> - <group> - <clip-path - android:pathData="M37.92,281.65L313.38,288L317,285.05L317,256.96L313.38,2.95L8.92,0L-0,96.3L-0,281.65L37.92,281.65Z"/> - <path - android:pathData="M-13,-11h341v311h-341z" - android:fillColor="#FFBDC5"/> - </group> - <path - android:pathData="M61.96,85.78L83.74,220.24C84.32,223.81 87.68,226.24 91.25,225.66L192.99,209.18L197.17,234.99L215.59,205.52L246.11,200.57C249.68,200 252.1,196.63 251.52,193.07L229.75,58.61C229.17,55.04 225.81,52.61 222.24,53.19L67.38,78.27C63.81,78.85 61.38,82.21 61.96,85.78Z" - android:strokeWidth="2.19" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M95.13,113.41L207.7,95.18" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="M106.03,180.69L218.6,162.46" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="M213.46,130.76L100.89,148.99" - android:strokeWidth="2.19" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="M181.58,169.33m-15.85,2.57a16.05,16.05 125.8,1 1,31.7 -5.13a16.05,16.05 125.8,1 1,-31.7 5.13" - android:strokeWidth="2.19" - android:fillColor="#2AC3A2" - android:strokeColor="#000000"/> - <path - android:pathData="M137.91,142.11m15.85,-2.57a16.05,16.05 125.8,1 1,-31.7 5.13a16.05,16.05 125.8,1 1,31.7 -5.13" - android:strokeWidth="2.19" - android:fillColor="#2AC3A2" - android:strokeColor="#000000"/> - <path - android:pathData="M189.17,86.55C184.63,83.27 178.36,84.29 175.16,88.82C170.62,85.54 164.35,86.56 161.15,91.09C157.95,95.62 158.89,101.9 163.42,105.1L179.7,116.84L191.44,100.56C194.72,96.02 193.7,89.75 189.17,86.55Z" - android:strokeLineJoin="round" - android:strokeWidth="2.19" - android:fillColor="#2AC3A2" - android:strokeColor="#000000" - android:strokeLineCap="round"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_sync.xml b/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_sync.xml deleted file mode 100644 index 463495d486b69cb2873c833ff2a6efab61ae4131..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/onboarding_ctd_sync.xml +++ /dev/null @@ -1,38 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="309dp" - android:height="288dp" - android:viewportWidth="309" - android:viewportHeight="288"> - <group> - <clip-path - android:pathData="M272.04,2.32L0,-0V19.21L3.53,284.16L153.42,288L296.96,273.6L309,129.05V2.32H272.04Z"/> - <path - android:pathData="M0,-22h324v379h-324z" - android:fillColor="#2AC3A2"/> - </group> - <path - android:pathData="M39.69,127.05C39.08,123.32 41.62,119.8 45.35,119.2L195.96,94.81C199.69,94.2 203.21,96.74 203.82,100.47L218.88,193.52L54.75,220.1L39.69,127.05Z" - android:strokeWidth="2.19377" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M48.79,232.34L228.42,203.25A5.66,5.66 125.8,0 0,233.1 196.76L233.1,196.76A5.66,5.66 125.8,0 0,226.61 192.08L46.98,221.17A5.66,5.66 125.8,0 0,42.3 227.66L42.3,227.66A5.66,5.66 125.8,0 0,48.79 232.34z" - android:strokeWidth="2.19" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M231.98,65.19L276.02,75.77A6.85,6.85 58.5,0 1,281.08 84.03L257.51,182.16A6.85,6.85 58.5,0 1,249.25 187.22L205.21,176.64A6.85,6.85 58.5,0 1,200.15 168.38L223.72,70.26A6.85,6.85 58.5,0 1,231.98 65.19z" - android:strokeWidth="2.19377" - android:fillColor="#ffffff" - android:strokeColor="#000000"/> - <path - android:pathData="M126.05,121.69C126.28,120.83 127.41,120.65 127.9,121.39L141.08,141.4C141.71,142.36 142.8,142.91 143.94,142.85L167.87,141.58C168.76,141.54 169.28,142.56 168.73,143.25L153.77,161.97C153.05,162.86 152.87,164.07 153.28,165.14L161.88,187.5C162.2,188.33 161.38,189.15 160.55,188.84L138.13,180.39C137.06,179.99 135.85,180.19 134.96,180.91L116.35,195.99C115.66,196.55 114.63,196.04 114.68,195.15L115.77,171.21C115.83,170.07 115.27,168.98 114.31,168.36L94.21,155.32C93.46,154.84 93.64,153.7 94.49,153.47L117.6,147.12C118.7,146.81 119.56,145.95 119.86,144.84L126.05,121.69Z" - android:strokeWidth="2.19377" - android:fillColor="#FFBDC5" - android:strokeColor="#000000"/> - <path - android:pathData="M239.59,136.79L238.83,137.59L239.59,136.79C238.96,136.2 238.08,135.99 237.26,136.23L223.1,140.38C223.05,140.39 223.01,140.39 222.98,140.38C222.95,140.37 222.91,140.35 222.88,140.31C222.85,140.28 222.84,140.24 222.83,140.2C222.83,140.18 222.83,140.14 222.85,140.08L229.16,126.75C229.53,125.98 229.46,125.07 228.98,124.37L220.66,112.19C220.63,112.14 220.62,112.1 220.62,112.07C220.62,112.04 220.63,112 220.65,111.96C220.68,111.92 220.71,111.89 220.74,111.88C220.76,111.86 220.8,111.85 220.86,111.86L235.49,113.74C236.34,113.85 237.18,113.5 237.7,112.82L246.71,101.15C246.75,101.1 246.78,101.09 246.81,101.08C246.84,101.07 246.88,101.06 246.93,101.07C246.98,101.08 247.01,101.11 247.04,101.13C247.06,101.15 247.08,101.18 247.09,101.24L249.82,115.73C249.98,116.57 250.57,117.27 251.37,117.55L265.26,122.52C265.32,122.54 265.34,122.57 265.36,122.59C265.38,122.61 265.4,122.65 265.4,122.7C265.4,122.75 265.39,122.79 265.38,122.82C265.37,122.85 265.34,122.88 265.29,122.9L252.35,129.98C251.6,130.39 251.13,131.17 251.1,132.02L250.67,146.76C250.67,146.82 250.65,146.86 250.64,146.88C250.62,146.91 250.58,146.93 250.54,146.95C250.5,146.97 250.46,146.97 250.42,146.97C250.39,146.96 250.36,146.95 250.31,146.91L239.59,136.79Z" - android:strokeWidth="2.19377" - android:fillColor="#FFBDC5" - android:strokeColor="#000000"/> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/onboarding_popup_shape.xml b/mobile/android/fenix/app/src/main/res/drawable/onboarding_popup_shape.xml deleted file mode 100644 index bfa6b0c5c4259aa42771d98197878cd060b9ca41..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/onboarding_popup_shape.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <corners android:radius="12dp" /> - <gradient - android:angle="45" - android:endColor="@color/fx_mobile_layer_color_gradient_end" - android:startColor="@color/fx_mobile_layer_color_gradient_start" /> -</shape> diff --git a/mobile/android/fenix/app/src/main/res/drawable/pocket_vector.xml b/mobile/android/fenix/app/src/main/res/drawable/pocket_vector.xml deleted file mode 100644 index 9c2ad19290eda140fe711b39f6e3078ac1cd0293..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/drawable/pocket_vector.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector - xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="22dp" - android:autoMirrored="true" - android:viewportWidth="24" - android:viewportHeight="22"> - <path - android:fillColor="#EF4056" - android:pathData="M2.0993,0C0.7917,0.0852 -0,0.8317 -0,2.1595V10.1111C-0,16.5695 6.4234,21.6451 11.98,21.605C18.228,21.5599 24,16.2839 24,10.1111V2.1595C24,0.8267 23.1583,0.0751 21.8405,0H2.0993ZM7.1599,6.4685L11.98,11.048L16.805,6.4685C18.9645,5.5616 19.9065,8.0267 19.0196,8.7483L12.7365,14.7457C12.5311,14.9411 11.4338,14.9411 11.2284,14.7457L4.9453,8.7482C4.0985,7.9515 5.2008,5.4463 7.1599,6.4685Z" /> -</vector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/progress_gradient.xml b/mobile/android/fenix/app/src/main/res/drawable/progress_gradient.xml index 76809e6b726d6169f596d04e8df42e394e306e3a..d9808b2fb29ed97bd97af6094fb578052d515739 100644 --- a/mobile/android/fenix/app/src/main/res/drawable/progress_gradient.xml +++ b/mobile/android/fenix/app/src/main/res/drawable/progress_gradient.xml @@ -12,16 +12,10 @@ <item android:id="@android:id/progress"> <scale android:scaleWidth="100%"> <shape> - <corners - android:bottomLeftRadius="0dp" - android:bottomRightRadius="8dp" - android:topLeftRadius="0dp" - android:topRightRadius="8dp"/> <gradient - android:angle="45" - android:centerColor="#F10366" - android:endColor="#FF9100" - android:startColor="#6173FF" /> + android:angle="0" + android:endColor="#00DBDE" + android:startColor="#FC00FF"/> </shape> </scale> </item> diff --git a/mobile/android/fenix/app/src/main/res/drawable/pager_dot.xml b/mobile/android/fenix/app/src/main/res/drawable/rounded_corners.xml similarity index 53% rename from mobile/android/fenix/app/src/main/res/drawable/pager_dot.xml rename to mobile/android/fenix/app/src/main/res/drawable/rounded_corners.xml index 869199def53e80ef571cbdd60414857ed7397756..24af9e5666be92fa40ee1fc1090d484583cb7a58 100644 --- a/mobile/android/fenix/app/src/main/res/drawable/pager_dot.xml +++ b/mobile/android/fenix/app/src/main/res/drawable/rounded_corners.xml @@ -1,12 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="oval"> - <solid android:color="@color/pager_dot"/> + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - <size - android:width="6dp" - android:height="6dp"/> +<!-- Used for rounding the corners of a button --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="#03DAC5" /> + <corners android:radius="4dp" /> </shape> diff --git a/mobile/android/fenix/app/src/main/res/drawable/tor_bootstrap_background_gradient.xml b/mobile/android/fenix/app/src/main/res/drawable/tor_bootstrap_background_gradient.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ec9e0096058fb2be312acdf7fb5dbe37a720c02 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/tor_bootstrap_background_gradient.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <gradient + android:angle="225" + android:startColor="@color/backgroundGradientLight" + android:centerColor="@color/backgroundGradientDark" + android:endColor="@color/backgroundGradientDark" + android:type="linear" /> + </shape> + </item> +</selector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_gradient.xml b/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_gradient.xml new file mode 100644 index 0000000000000000000000000000000000000000..ca20bc39f40288402b97948389dae650bfdbde74 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_gradient.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <gradient + android:angle="45" + android:startColor="#07d1db" + android:endColor="#b240f5" + android:type="linear" /> + </shape> + </item> +</selector> diff --git a/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_rounded_corners.xml b/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_rounded_corners.xml new file mode 100644 index 0000000000000000000000000000000000000000..23be2591b999aaacd001de6a23c523eab02fecc8 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/drawable/tor_onboarding_donate_rounded_corners.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!-- Used for rounding the corners of a button --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="#70efde" /> + <corners android:radius="10dp" /> +</shape> diff --git a/mobile/android/fenix/app/src/main/res/layout/component_cookie_banner_details_panel.xml b/mobile/android/fenix/app/src/main/res/layout/component_cookie_banner_details_panel.xml index 486bb64b6e965337625a9c1d49943053248cf7f5..d6f0805298f3a4f8ffc4463a78cda01e63556ab4 100644 --- a/mobile/android/fenix/app/src/main/res/layout/component_cookie_banner_details_panel.xml +++ b/mobile/android/fenix/app/src/main/res/layout/component_cookie_banner_details_panel.xml @@ -62,7 +62,7 @@ tools:text="Firefox will clear this site’s cookies and refresh the page. Clearing all cookies may sign you out or empty shopping carts." /> - <androidx.appcompat.widget.AppCompatButton + <!--<androidx.appcompat.widget.AppCompatButton android:id="@+id/cancel_button" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -78,9 +78,9 @@ android:textSize="14sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/details" /> + app:layout_constraintTop_toBottomOf="@id/details" />--> - <androidx.appcompat.widget.AppCompatButton + <!--<androidx.appcompat.widget.AppCompatButton android:id="@+id/request_support" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -97,5 +97,5 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toEndOf="@+id/cancel_button" - app:layout_constraintTop_toBottomOf="@id/details" /> + app:layout_constraintTop_toBottomOf="@id/details" />--> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/component_tabstray2.xml b/mobile/android/fenix/app/src/main/res/layout/component_tabstray2.xml index 3379510c5abf25d4619c798b237193c5dc04f37c..2ce772384e7857ae5a51125fdf73d67065981b56 100644 --- a/mobile/android/fenix/app/src/main/res/layout/component_tabstray2.xml +++ b/mobile/android/fenix/app/src/main/res/layout/component_tabstray2.xml @@ -100,14 +100,7 @@ android:contentDescription="@string/tabs_header_private_tabs_title" android:icon="@drawable/ic_private_browsing" /> - <com.google.android.material.tabs.TabItem - android:layout_width="0dp" - android:layout_height="match_parent" - android:contentDescription="@string/tabs_header_synced_tabs_title" - android:foregroundTint="@color/photonWhite" - android:icon="@drawable/ic_synced_tabs" /> - - </com.google.android.material.tabs.TabLayout> + </com.google.android.material.tabs.TabLayout> <ImageButton android:id="@+id/tab_tray_overflow" diff --git a/mobile/android/fenix/app/src/main/res/layout/fenix_snackbar.xml b/mobile/android/fenix/app/src/main/res/layout/fenix_snackbar.xml index a21d0011fc452d1a93ba476b3ee5ed822ede0517..74f1c4751b5b957b6255f488c824894273ba411b 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fenix_snackbar.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fenix_snackbar.xml @@ -21,6 +21,12 @@ android:paddingStart="16dp" android:paddingEnd="16dp"> + <!-- + TextView below changed as part of tor-browser#43229 to match the designs + https://www.figma.com/design/vXrWeiV2IlKx5IIZVLtxBX/Android-Components?node-id=1807-3117&t=8Gc1mpPYPQCLMYH2-1 screenshot shown here + Line spacing eyeballed from screenshot here + https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests/1275#note_3125666 + --> <TextView android:id="@+id/snackbar_text" android:layout_width="0dp" @@ -29,8 +35,9 @@ android:letterSpacing="0.05" android:minHeight="46dp" android:maxLines="2" - android:paddingTop="8dp" - android:paddingBottom="8dp" + android:paddingTop="12dp" + android:paddingBottom="12dp" + android:lineSpacingExtra="8sp" android:textAlignment="textStart" android:textColor="@color/photonWhite" android:textSize="18sp" diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_about.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_about.xml index 53d86a98ed7b6cba8db1c79ca3ce8c85b84fe5c4..ccf17ed60fc07c5f1b12d4548fdfac88b5873bb3 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fragment_about.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_about.xml @@ -19,18 +19,32 @@ <ImageView android:id="@+id/wordmark" - android:layout_width="0dp" - android:layout_height="@dimen/about_header_fenix_logo_height" - android:layout_marginStart="@dimen/about_header_icon_margin_start_end" + android:layout_width="75dp" + android:layout_height="75dp" android:layout_marginTop="@dimen/about_header_icon_margin_top" - android:layout_marginEnd="@dimen/about_header_icon_margin_start_end" + android:layout_marginEnd="130dp" android:contentDescription="@string/app_name" android:importantForAccessibility="no" - app:srcCompat="?fenixLogo" - app:layout_constraintEnd_toEndOf="parent" + app:srcCompat="@mipmap/ic_launcher_foreground" app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/app_name" + style="@style/Header24TextStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/about_header_icon_margin_top" + android:gravity="center_vertical" + android:width="130dp" + android:height="70dp" + android:lines="2" + android:text="@string/app_name" + android:textSize="20sp" + android:lineSpacingMultiplier="1.2" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintWidth_percent="0.75" /> + app:layout_constraintStart_toEndOf="@id/wordmark" /> <TextView android:id="@+id/about_content" @@ -45,7 +59,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/wordmark" app:layout_constraintWidth_percent="0.8" - tools:text="@string/about_content" /> + tools:text="@string/tor_about_content" /> <TextView android:id="@+id/about_text" diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_create_shortcut.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_create_shortcut.xml index 9744a8c1a5c39d4d47ffb5974df0e2531c3128be..1a7d567046a5dd8eed5040b01f92891302da12f5 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fragment_create_shortcut.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_create_shortcut.xml @@ -46,7 +46,7 @@ android:importantForAccessibility="no" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/dialog_title" - tools:src="@drawable/ic_pocket" /> + tools:src="@drawable/mozac_lib_crash_notification" /> <EditText android:id="@+id/shortcut_text" diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_home.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_home.xml index 428e3dc3869509e256b2525c3b2243f9f7e46c95..823ee90fabf8b812c757dc741ced32fa02085b8d 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fragment_home.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_home.xml @@ -48,10 +48,10 @@ app:layout_collapseParallaxMultiplier=".167"/> <!-- This value needs to be 1.67 * the wordmark parallax value as its 24dp vs 40 --> - <LinearLayout + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/wordmark" android:layout_width="wrap_content" - android:layout_height="40dp" + android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="18dp" android:layout_marginBottom="32dp" @@ -59,19 +59,27 @@ android:focusable="false" android:importantForAccessibility="no" android:orientation="horizontal" + app:srcCompat="@mipmap/ic_launcher_foreground" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier=".1"> <ImageView android:id="@+id/wordmarkLogo" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginEnd="10.dp" + android:layout_width="50dp" + android:layout_height="50dp" android:adjustViewBounds="true" android:contentDescription="@null" - app:srcCompat="?fenixWordmarkLogo" - tools:ignore="ImageContrastCheck" /> + app:srcCompat="@mipmap/ic_launcher_foreground" + tools:ignore="ImageContrastCheck" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintEnd_toStartOf="@id/app_name" + android:scaleX="1.5" + android:scaleY="1.5" /> + <!-- + tor-browser#42590 <ImageView android:id="@+id/wordmarkText" android:layout_width="wrap_content" @@ -80,10 +88,50 @@ android:contentDescription="@null" android:layout_marginTop="@dimen/wordmark_text_margin_top" app:srcCompat="?fenixWordmarkText" /> - </LinearLayout> + --> + + <TextView + android:id="@+id/app_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:clickable="false" + android:focusable="false" + android:fontFamily="Roboto-Medium" + android:gravity="start" + android:importantForAccessibility="no" + android:maxLines="2" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:text="@string/app_name" + android:textColor="#DEFFFFFF" + android:textSize="20sp" + app:layout_constrainedWidth="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/wordmarkLogo" + app:layout_constraintTop_toTopOf="parent" /> + + </androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.appbar.CollapsingToolbarLayout> + <TextView + android:id="@+id/exploreprivately" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center|center_vertical" + android:gravity="center_horizontal" + android:clickable="false" + android:ellipsize="end" + android:focusable="false" + android:importantForAccessibility="no" + android:text="@string/tor_explore_privately" + android:fontFamily="Roboto-Medium" + android:textColor="#DEFFFFFF" + android:textSize="40sp" + android:lineSpacingMultiplier="1.1" + app:layout_scrollFlags="scroll" /> + </com.google.android.material.appbar.AppBarLayout> <androidx.compose.ui.platform.ComposeView @@ -107,6 +155,17 @@ tools:itemCount="3" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/> + <ImageView + android:id="@+id/onion_pattern_image" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + app:srcCompat="@drawable/ic_onion_pattern" + tools:ignore="ContentDescription" + app:layout_constraintBottom_toTopOf="@id/toolbarLayout" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/toolbarLayout" android:elevation="5dp" diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_locale_settings.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_locale_settings.xml index d235e7043fcbc827e93e5e15f98591808086a2ba..1014505aba6b8bc1803b6ff630a923023bb8c371 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fragment_locale_settings.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_locale_settings.xml @@ -7,13 +7,30 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <FrameLayout + <com.google.android.material.switchmaterial.SwitchMaterial + android:id="@+id/enable_switch" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + android:background="?android:attr/selectableItemBackground" + android:checked="true" + android:clickable="true" + android:focusable="true" + android:layout_marginStart="54dp" + android:padding="16dp" + android:text="@string/tor_spoof_english" + android:textColor="?textPrimary" + android:textSize="16sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/locale_container" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/enable_switch" /> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml new file mode 100644 index 0000000000000000000000000000000000000000..127819de631abd1134f7a1fab2e412d95d6412ac --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/tor_bootstrap_background_gradient" + android:paddingBottom="16dp"> + + <ProgressBar + android:id="@+id/tor_bootstrap_progress_bar" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="6dp" + android:visibility="invisible" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/settings_button" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/settings" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/mozac_ic_settings_24" /> + </androidx.constraintlayout.widget.ConstraintLayout> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/back_button" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" + android:visibility="invisible" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/settings" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/mozac_ic_back_24" /> + </androidx.constraintlayout.widget.ConstraintLayout> + + + <ImageView + android:id="@+id/tor_connect_image" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="24dp" + android:contentDescription="@string/tor_bootstrap_connect" + android:visibility="visible" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/back_button" + app:layout_constraintVertical_bias="0.05" + app:srcCompat="@drawable/connect" /> + + <TextView + android:id="@+id/title_large_text_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:paddingHorizontal="24dp" + android:text="@string/connection_assist_tor_connect_title" + android:textColor="@color/photonLightGrey05" + android:textSize="22sp" + app:layout_constraintTop_toBottomOf="@id/tor_connect_image" /> + + <TextView + android:id="@+id/title_description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:lineSpacingExtra="6dp" + android:paddingHorizontal="24dp" + android:paddingVertical="16dp" + android:text="@string/preferences_tor_network_settings_explanation" + android:textColor="@color/photonLightGrey05" + android:textSize="14sp" + app:layout_constraintTop_toBottomOf="@id/title_large_text_view" /> + + <androidx.appcompat.widget.SwitchCompat + android:id="@+id/quickstart_switch" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingHorizontal="24dp" + android:paddingVertical="8dp" + android:text="@string/connection_assist_always_connect_automatically_toggle_description" + android:textColor="@color/photonLightGrey05" + app:layout_constraintTop_toBottomOf="@id/title_description" /> + + <TextView + android:id="@+id/unblock_the_internet_in_country_description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingHorizontal="24dp" + android:layout_marginTop="24dp" + android:text="@string/connection_assist_unblock_the_internet_in_country_or_region" + android:textColor="@color/photonLightGrey05" + android:visibility="gone" + app:layout_constraintTop_toBottomOf="@id/title_description" /> + + <androidx.appcompat.widget.AppCompatSpinner + android:id="@+id/country_drop_down" + style="@style/Widget.AppCompat.Spinner.Underlined" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="24dp" + android:textColor="@color/photonLightGrey05" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/unblock_the_internet_in_country_description" /> + + <ImageView + android:id="@+id/wordmarkLogo" + android:layout_width="192dp" + android:layout_height="192dp" + android:contentDescription="@string/app_name" + android:scaleX="1.8" + android:scaleY="1.8" + app:srcCompat="@mipmap/ic_launcher_foreground" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <Button + android:id="@+id/tor_bootstrap_button_1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:layout_marginEnd="24dp" + android:layout_marginBottom="8dp" + android:background="@drawable/rounded_corners" + android:backgroundTint="@color/connect_button_purple" + android:minWidth="360dp" + android:text="@string/tor_bootstrap_connect" + android:textAlignment="center" + android:textAllCaps="false" + android:textColor="@color/photonLightGrey05" + android:textSize="14sp" + android:textStyle="bold" + app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_button_2" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + + <Button + android:id="@+id/tor_bootstrap_button_2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:layout_marginEnd="24dp" + android:layout_marginBottom="8dp" + android:background="@drawable/rounded_corners" + android:backgroundTint="@color/configure_connection_button_white" + android:minWidth="360dp" + android:text="@string/connection_assist_configure_connection_button" + android:textAlignment="center" + android:textAllCaps="false" + android:textColor="@color/photonDarkGrey90" + android:textSize="14sp" + android:textStyle="bold" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/fragment_turn_on_sync.xml b/mobile/android/fenix/app/src/main/res/layout/fragment_turn_on_sync.xml index cbac8400062fd0a97a23e1c05877b19debf1a141..5d29134854f5f6c85ea126eb2048d2ff9b9d0d50 100644 --- a/mobile/android/fenix/app/src/main/res/layout/fragment_turn_on_sync.xml +++ b/mobile/android/fenix/app/src/main/res/layout/fragment_turn_on_sync.xml @@ -39,8 +39,9 @@ android:scaleType="fitXY" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/title_sign_in" - app:srcCompat="@drawable/ic_scan" /> + app:layout_constraintTop_toBottomOf="@id/title_sign_in" /> + <!--Removed as part of tor-browser#42386--> + <!--app:srcCompat="@drawable/ic_scan"--> <TextView android:id="@+id/signInInstructions" diff --git a/mobile/android/fenix/app/src/main/res/layout/onboarding_inactive_tabs_cfr.xml b/mobile/android/fenix/app/src/main/res/layout/onboarding_inactive_tabs_cfr.xml index 7548b8b86f54e49058f878ad2f77dd17be319814..0d2ae75e750b32613faae78df8a7328a93e9479d 100644 --- a/mobile/android/fenix/app/src/main/res/layout/onboarding_inactive_tabs_cfr.xml +++ b/mobile/android/fenix/app/src/main/res/layout/onboarding_inactive_tabs_cfr.xml @@ -22,7 +22,7 @@ android:id="@+id/banner_container" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/onboarding_popup_shape"> + android:background="@drawable/mozac_lib_crash_notification"> <TextView android:id="@+id/banner_info_message" diff --git a/mobile/android/fenix/app/src/main/res/layout/preference_quick_start.xml b/mobile/android/fenix/app/src/main/res/layout/preference_quick_start.xml new file mode 100644 index 0000000000000000000000000000000000000000..907e3685e5ff13d32b57288255c663b2c456c0cb --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/layout/preference_quick_start.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<com.google.android.material.switchmaterial.SwitchMaterial xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/switch_widget" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:clickable="false" + android:focusable="false" + android:gravity="center_vertical" + android:orientation="vertical" /> diff --git a/mobile/android/fenix/app/src/main/res/layout/quicksettings_permissions.xml b/mobile/android/fenix/app/src/main/res/layout/quicksettings_permissions.xml index fddc60c641584e1a7a10aca93f3bd620aa746aef..858c554ef81ea0a03cddbd9209c528ddbc4b4644 100644 --- a/mobile/android/fenix/app/src/main/res/layout/quicksettings_permissions.xml +++ b/mobile/android/fenix/app/src/main/res/layout/quicksettings_permissions.xml @@ -180,7 +180,7 @@ app:layout_constraintEnd_toStartOf="@id/mediaKeySystemAccessStatus" app:layout_constraintStart_toStartOf="parent" android:textColor="?attr/textPrimary" - tools:visibility="visible" /> + tools:visibility="gone" /> <TextView android:id="@+id/mediaKeySystemAccessStatus" @@ -192,7 +192,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/mediaKeySystemAccessLabel" tools:text="@string/preference_option_phone_feature_blocked" - tools:visibility="visible" /> + tools:visibility="gone" /> <TextView diff --git a/mobile/android/fenix/app/src/main/res/layout/quicksettings_protections_panel.xml b/mobile/android/fenix/app/src/main/res/layout/quicksettings_protections_panel.xml index cbfa0a812aa701902d663fbedc9d6b62d29d5013..bc821cf324e237d387084f9a8fb2a8d52d351697 100644 --- a/mobile/android/fenix/app/src/main/res/layout/quicksettings_protections_panel.xml +++ b/mobile/android/fenix/app/src/main/res/layout/quicksettings_protections_panel.xml @@ -12,36 +12,38 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/tracking_protection_item_height" - app:layout_constraintBottom_toTopOf="@id/trackingProtectionSwitch" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" /> - <org.mozilla.fenix.trackingprotection.SwitchWithDescription - android:id="@+id/trackingProtectionSwitch" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="16dp" - android:minHeight="@dimen/tracking_protection_item_height" - android:text="@string/preference_enhanced_tracking_protection" - app:layout_constraintBottom_toTopOf="@id/trackingProtectionDetails" - app:layout_constraintTop_toBottomOf="@id/cookieBannerItem" - app:switchDescriptionOff="@string/etp_panel_off" - app:switchDescriptionOn="@string/etp_panel_on" - app:switchIconOff="@drawable/ic_tracking_protection_disabled" - app:switchIconOn="@drawable/ic_tracking_protection_enabled" - app:switchTitle="@string/preference_enhanced_tracking_protection" /> +<!-- Removed as part of Bug_42115: Enhanced Tracking Protection can still be enabled--> +<!-- <org.mozilla.fenix.trackingprotection.SwitchWithDescription--> +<!-- android:id="@+id/trackingProtectionSwitch"--> +<!-- android:layout_width="match_parent"--> +<!-- android:layout_height="wrap_content"--> +<!-- android:layout_marginTop="16dp"--> +<!-- android:minHeight="@dimen/tracking_protection_item_height"--> +<!-- android:text="@string/preference_enhanced_tracking_protection"--> +<!-- app:layout_constraintBottom_toTopOf="@id/trackingProtectionDetails"--> +<!-- app:layout_constraintTop_toBottomOf="@id/cookieBannerItem"--> +<!-- app:switchDescriptionOff="@string/etp_panel_off"--> +<!-- app:switchDescriptionOn="@string/etp_panel_on"--> +<!-- app:switchIconOff="@drawable/ic_tracking_protection_disabled"--> +<!-- app:switchIconOn="@drawable/ic_tracking_protection_enabled"--> +<!-- app:switchTitle="@string/preference_enhanced_tracking_protection" />--> - <TextView - android:id="@+id/trackingProtectionDetails" - style="@style/QuickSettingsText.Icon" - android:layout_width="0dp" - android:layout_height="@dimen/quicksettings_item_height" - android:layout_alignParentEnd="true" - android:gravity="end|center_vertical" - android:text="@string/enhanced_tracking_protection_details" - android:visibility="gone" - app:drawableEndCompat="@drawable/ic_arrowhead_right" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + <!-- Removed as part of Bug_42115: Enhanced Tracking Protection can still be enabled--> +<!-- <TextView--> +<!-- android:id="@+id/trackingProtectionDetails"--> +<!-- style="@style/QuickSettingsText.Icon"--> +<!-- android:layout_width="0dp"--> +<!-- android:layout_height="@dimen/quicksettings_item_height"--> +<!-- android:layout_alignParentEnd="true"--> +<!-- android:gravity="end|center_vertical"--> +<!-- android:text="@string/enhanced_tracking_protection_details"--> +<!-- android:visibility="gone"--> +<!-- app:drawableEndCompat="@drawable/ic_arrowhead_right"--> +<!-- app:layout_constraintBottom_toBottomOf="parent"--> +<!-- app:layout_constraintEnd_toEndOf="parent"--> +<!-- app:layout_constraintStart_toStartOf="parent" />--> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v1.xml b/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v1.xml index 0362d13928476f4d6d142aa19bc649f9cdb18567..fbb85e4e2c07e441c1ab742ff81af33282ce128d 100644 --- a/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v1.xml +++ b/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v1.xml @@ -17,6 +17,8 @@ android:layout_gravity="center" android:contentDescription="@string/search_widget_content_description_2" android:scaleType="centerInside" - tools:src="@drawable/ic_launcher_foreground" /> + tools:src="@mipmap/ic_launcher_foreground" + android:scaleX="1.5" + android:scaleY="1.5"/> </FrameLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v2.xml b/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v2.xml index 6bac1cbcfe4a0128db923efa2f8adb442b3c9efa..51477f41f653200c04619dbed79379ab62183593 100644 --- a/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v2.xml +++ b/mobile/android/fenix/app/src/main/res/layout/search_widget_extra_small_v2.xml @@ -17,5 +17,7 @@ android:layout_gravity="center" android:contentDescription="@string/search_widget_content_description_2" android:scaleType="centerInside" - tools:src="@drawable/ic_launcher_foreground" /> + tools:src="@mipmap/ic_launcher_foreground" + android:scaleX="1.5" + android:scaleY="1.5"/> </FrameLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/search_widget_large.xml b/mobile/android/fenix/app/src/main/res/layout/search_widget_large.xml index 8c003ab2f3885e71ab02bd23d4710289ed798bca..ad69947515a45b89941c1ca14f108dcda63581e6 100644 --- a/mobile/android/fenix/app/src/main/res/layout/search_widget_large.xml +++ b/mobile/android/fenix/app/src/main/res/layout/search_widget_large.xml @@ -15,6 +15,8 @@ android:layout_height="50dp" android:layout_alignParentStart="true" android:contentDescription="@string/search_widget_content_description_2" + android:scaleX="1.5" + android:scaleY="1.5" android:scaleType="centerInside" /> <TextView diff --git a/mobile/android/fenix/app/src/main/res/layout/search_widget_medium.xml b/mobile/android/fenix/app/src/main/res/layout/search_widget_medium.xml index 2a0cab437159cb93a44c13eeb191f668fe03321b..42ad461fba5938a10ac57ca1e724f4b8ef8788d8 100644 --- a/mobile/android/fenix/app/src/main/res/layout/search_widget_medium.xml +++ b/mobile/android/fenix/app/src/main/res/layout/search_widget_medium.xml @@ -15,6 +15,8 @@ android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentStart="true" + android:scaleX="1.5" + android:scaleY="1.5" android:scaleType="centerInside" /> <TextView diff --git a/mobile/android/fenix/app/src/main/res/layout/search_widget_small.xml b/mobile/android/fenix/app/src/main/res/layout/search_widget_small.xml index c4a6df1b61639f85d45e9d4968d754742dfe6bf9..7786d2b38b4cdbfdfab57f180ea576126a6aaaed 100644 --- a/mobile/android/fenix/app/src/main/res/layout/search_widget_small.xml +++ b/mobile/android/fenix/app/src/main/res/layout/search_widget_small.xml @@ -13,6 +13,8 @@ android:layout_width="50dp" android:layout_height="50dp" android:contentDescription="@string/search_widget_content_description_2" + android:scaleX="1.5" + android:scaleY="1.5" android:scaleType="centerInside" /> <ImageView diff --git a/mobile/android/fenix/app/src/main/res/layout/sign_in_preference.xml b/mobile/android/fenix/app/src/main/res/layout/sign_in_preference.xml index bc3d74f3541b1f59308c8dbc6b1e3cb243e6745c..68fda81b5e7c5925dac69d2d382e394dbcf8ffba 100644 --- a/mobile/android/fenix/app/src/main/res/layout/sign_in_preference.xml +++ b/mobile/android/fenix/app/src/main/res/layout/sign_in_preference.xml @@ -18,7 +18,7 @@ android:id="@+id/imageView" android:layout_width="72dp" android:layout_height="72dp" - app:srcCompat="@drawable/ic_fx_accounts_avatar" + app:srcCompat="@drawable/mozac_lib_crash_notification" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index de34ac4858cb2378f15b483eed5200982ae01490..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@color/ic_launcher_background"/> - <foreground android:drawable="@drawable/ic_launcher_foreground"/> - <monochrome android:drawable="@drawable/ic_launcher_monochrome"/> -</adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alternative.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alternative.xml index d5069946391e1eba505828e2cd3ea15a4554612b..805e571b1930812d52d81403dc289feaff5c8f8b 100644 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alternative.xml +++ b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alternative.xml @@ -4,6 +4,6 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@color/photonWhite"/> - <foreground android:drawable="@drawable/ic_launcher_foreground"/> - <monochrome android:drawable="@drawable/ic_launcher_monochrome"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/> </adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml deleted file mode 100644 index 66196fc1d3f2eebf39cfaad9b1d30b135acb3532..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_private_background"/> - <foreground android:drawable="@drawable/ic_launcher_private_foreground"/> -</adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml deleted file mode 100644 index 66196fc1d3f2eebf39cfaad9b1d30b135acb3532..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_private_background"/> - <foreground android:drawable="@drawable/ic_launcher_private_foreground"/> -</adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index de34ac4858cb2378f15b483eed5200982ae01490..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@color/ic_launcher_background"/> - <foreground android:drawable="@drawable/ic_launcher_foreground"/> - <monochrome android:drawable="@drawable/ic_launcher_monochrome"/> -</adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round_alternative.xml b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round_alternative.xml index d5069946391e1eba505828e2cd3ea15a4554612b..805e571b1930812d52d81403dc289feaff5c8f8b 100644 --- a/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round_alternative.xml +++ b/mobile/android/fenix/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round_alternative.xml @@ -4,6 +4,6 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@color/photonWhite"/> - <foreground android:drawable="@drawable/ic_launcher_foreground"/> - <monochrome android:drawable="@drawable/ic_launcher_monochrome"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/> </adaptive-icon> diff --git a/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index 28bfc19008c79ef444729b450f3ba322abf1323b..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index ee00e298f4be7269d8028500cfe2da9f55112223..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 02374ca9ff9a6db2b322558a30f333cb36e2b002..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index e7358ce7b53b710e3c6dd4845b270ea61fddac8d..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 01967505bbfe5c26de4b7065a1176c957cc97546..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 3bf2adcd59b64b05a12f3b193a3f4e4467782d0d..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 196694693e36875c351e2eab6e306843360bf556..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index d4ddb323dd176598f1f32d21fcf179b26f5dc216..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index 6ed20ddc8f860aa4c741a7472bfb45ca87b1ad82..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 77ee63d196ade238a47e1c6e9d0ecdfd22a674a3..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml b/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml index 33f3f5542d05c5f74c44674cc8b889230cff4727..45260046f1093f0a245e20b2744b2d2a4d9dcca5 100644 --- a/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml +++ b/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml @@ -15,6 +15,24 @@ app:popUpTo="@id/startupFragment" app:popUpToInclusive="true" /> + <action + android:id="@+id/action_startup_torbootstrap" + app:destination="@id/torbootstrapFragment" + app:popUpTo="@id/startupFragment" + app:popUpToInclusive="true" /> + + <action + android:id="@+id/action_startup_tor_connection_assist" + app:destination="@+id/torConnectionAssistFragment" + app:popUpTo="@id/startupFragment" + app:popUpToInclusive="true" /> + + <action + android:id="@+id/action_connect_to_tor_before_opening_links" + app:destination="@+id/torConnectionAssistFragment" + app:popUpTo="@id/torConnectionAssistFragment" + app:popUpToInclusive="true"/> + <action android:id="@+id/action_global_home" app:destination="@id/homeFragment" @@ -94,6 +112,9 @@ <action android:id="@+id/action_global_homeSettingsFragment" app:destination="@id/homeSettingsFragment" /> + <action + android:id="@+id/action_global_torSecurityLevelFragment" + app:destination="@id/torSecurityLevelFragment" /> <action android:id="@+id/action_global_privateBrowsingFragment" app:destination="@id/privateBrowsingFragment" /> @@ -175,7 +196,9 @@ <action android:id="@+id/action_global_menuDialogFragment" app:destination="@id/menu_graph" /> - + <action + android:id="@+id/action_global_homeFragment" + app:destination="@id/homeFragment" /> <dialog android:id="@+id/tabsTrayFragment" android:name="org.mozilla.fenix.tabstray.TabsTrayFragment"> @@ -229,6 +252,50 @@ app:popExitAnim="@anim/slide_out_right" /> </fragment> + <fragment + android:id="@+id/torbootstrapFragment" + android:name="org.mozilla.fenix.tor.TorBootstrapFragment" + tools:layout="@layout/fragment_home"> + + <action + android:id="@+id/action_home" + app:destination="@id/homeFragment" + app:popUpTo="@id/torbootstrapFragment" + app:popUpToInclusive="true" /> + <action + android:id="@+id/action_torbootstrapFragment_to_SettingsFragment" + app:destination="@id/settingsFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> + </fragment> + + <fragment + android:id="@+id/torConnectionAssistFragment" + android:name="org.mozilla.fenix.tor.TorConnectionAssistFragment" + tools:layout="@layout/fragment_tor_connection_assist"> + <action + android:id="@+id/action_home" + app:destination="@id/homeFragment" + app:popUpTo="@id/torConnectionAssistFragment" + app:popUpToInclusive="true" /> + <action + android:id="@+id/action_torConnectionAssistFragment_to_SettingsFragment" + app:destination="@id/settingsFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> + <action + android:id="@+id/action_torConnectionAssistFragment_to_TorConnectionSettings" + app:destination="@id/settingsFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> + </fragment> + <dialog android:id="@+id/homeOnboardingDialogFragment" android:name="org.mozilla.fenix.onboarding.HomeOnboardingDialogFragment" /> @@ -600,6 +667,13 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + <action + android:id="@+id/action_settingsFragment_to_torSecurityLevelFragment" + app:destination="@id/torSecurityLevelFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> <action android:id="@+id/action_settingsFragment_to_privateBrowsingFragment" app:destination="@id/privateBrowsingFragment" @@ -614,6 +688,20 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + <action + android:id="@+id/action_settingsFragment_to_torBridgeConfigFragment" + app:destination="@id/torBridgeConfigFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> + <action + android:id="@+id/action_settingsFragment_to_torLogsFragment" + app:destination="@+id/torLogsFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> <action android:id="@+id/action_settingsFragment_to_trackingProtectionFragment" app:destination="@id/trackingProtectionFragment" @@ -663,6 +751,7 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + <!-- <action android:id="@+id/action_settingsFragment_to_openLinksInAppsFragment" app:destination="@id/openLinksInAppsFragment" @@ -670,6 +759,7 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + --> <action android:id="@+id/action_settingsFragment_to_tabsSettingsFragment" app:destination="@id/tabsSettingsFragment" @@ -705,6 +795,13 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + <action + android:id="@+id/action_settingsFragment_to_TorConnectionAssistFragment" + app:destination="@id/torConnectionAssistFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> </fragment> <dialog android:id="@+id/profilerStartDialogFragment" @@ -845,6 +942,10 @@ android:id="@+id/customizationFragment" android:name="org.mozilla.fenix.settings.CustomizationFragment" android:label="@string/preferences_customize" /> + <fragment + android:id="@+id/torSecurityLevelFragment" + android:name="org.mozilla.fenix.settings.TorSecurityLevelFragment" + android:label="@string/preferences_tor_security_level_options" /> <fragment android:id="@+id/privateBrowsingFragment" android:name="org.mozilla.fenix.settings.PrivateBrowsingFragment" @@ -857,6 +958,14 @@ android:id="@+id/sponsoredStoriesSettings" android:name="org.mozilla.fenix.settings.SponsoredStoriesSettingsFragment" android:label="@string/preferences_debug_settings_custom_sponsored_stories_parameters" /> + <fragment + android:id="@+id/torBridgeConfigFragment" + android:name="org.mozilla.fenix.settings.TorBridgeConfigFragment" + android:label="@string/preferences_tor_network_settings_bridge_config" /> + <fragment + android:id="@+id/torLogsFragment" + android:name="org.mozilla.fenix.tor.TorLogsComposeFragment" + android:label="@string/preferences_tor_logs" /> <fragment android:id="@+id/trackingProtectionFragment" android:name="org.mozilla.fenix.settings.TrackingProtectionFragment"> @@ -875,9 +984,11 @@ app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> </fragment> + <!-- <fragment android:id="@+id/openLinksInAppsFragment" android:name="org.mozilla.fenix.settings.OpenLinksInAppsFragment" /> + --> <fragment android:id="@+id/deleteBrowsingDataFragment" android:name="org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataFragment" diff --git a/mobile/android/fenix/app/src/main/res/values-night-v27/styles.xml b/mobile/android/fenix/app/src/main/res/values-night-v27/styles.xml index ce769d9e95cab43d2ee414bdbb5d0f10faec73d2..6df3f87c4bf97c28b7f0fedb3d1295ccfe050800 100644 --- a/mobile/android/fenix/app/src/main/res/values-night-v27/styles.xml +++ b/mobile/android/fenix/app/src/main/res/values-night-v27/styles.xml @@ -6,8 +6,9 @@ <style name="NormalTheme" parent="NormalThemeBase" > <!-- We have to pull in the changes from night/styles.xml to make sure we also get them in night-v27+ --> - <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item> - +<!-- Removed as part of tor-browser#42386--> +<!-- <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item> --> + <item name="android:windowLayoutInDisplayCutoutMode">default</item> </style> </resources> diff --git a/mobile/android/fenix/app/src/main/res/values-night/styles.xml b/mobile/android/fenix/app/src/main/res/values-night/styles.xml index 0baef7182988f6a377b5b136a9a1d6487c1b68f9..00dee8885ac45b27a4082f66598850cb044c030d 100644 --- a/mobile/android/fenix/app/src/main/res/values-night/styles.xml +++ b/mobile/android/fenix/app/src/main/res/values-night/styles.xml @@ -6,7 +6,8 @@ <style name="DialogStyleNormal" parent="DialogStyleDark"/> <style name="NormalTheme" parent="NormalThemeBase" > - <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item> +<!-- Removed as part of tor-browser#42386--> +<!-- <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item>--> </style> </resources> diff --git a/mobile/android/fenix/app/src/main/res/values-v24/styles.xml b/mobile/android/fenix/app/src/main/res/values-v24/styles.xml index 8418254bc1f5b32768bc63b29da0e363aa66f0c3..893a348a0860f939da7d55c382c700d613d345c9 100644 --- a/mobile/android/fenix/app/src/main/res/values-v24/styles.xml +++ b/mobile/android/fenix/app/src/main/res/values-v24/styles.xml @@ -4,6 +4,6 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <style name="SplashScreen" parent="SplashScreenThemeBase"> - <item name="windowSplashScreenAnimatedIcon">@drawable/animated_splash_screen</item> + <item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen</item> </style> </resources> diff --git a/mobile/android/fenix/app/src/main/res/values-v27/styles.xml b/mobile/android/fenix/app/src/main/res/values-v27/styles.xml index 4e0eddedc9f49498fa2997ff2f903e7de8d681a9..45b69dab483610e2487916e102e0b8650009f476 100644 --- a/mobile/android/fenix/app/src/main/res/values-v27/styles.xml +++ b/mobile/android/fenix/app/src/main/res/values-v27/styles.xml @@ -28,7 +28,7 @@ </style> <style name="SplashScreen" parent="SplashScreenThemeBase"> - <item name="windowSplashScreenAnimatedIcon">@drawable/animated_splash_screen</item> + <item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen</item> <!-- Splash screen is animated to maximum 12 seconds --> <item name="windowSplashScreenAnimationDuration">12000</item> <item name="android:windowLayoutInDisplayCutoutMode">default</item> diff --git a/mobile/android/fenix/app/src/main/res/values/attrs.xml b/mobile/android/fenix/app/src/main/res/values/attrs.xml index fef61285a5a26957dca0a142438618a4a492f384..c7019fd5adf8c94b824baf1742d6b6ccdacabdb0 100644 --- a/mobile/android/fenix/app/src/main/res/values/attrs.xml +++ b/mobile/android/fenix/app/src/main/res/values/attrs.xml @@ -66,6 +66,7 @@ <!-- Misc --> <attr name="homeBackground" format="reference"/> + <attr name="torBootstrapBackground" format="reference"/> <attr name="bottomBarBackground" format="reference"/> <attr name="bottomBarBackgroundTop" format="reference"/> <attr name="fenixLogo" format="reference" /> diff --git a/mobile/android/fenix/app/src/main/res/values/colors.xml b/mobile/android/fenix/app/src/main/res/values/colors.xml index b87b7a8c45a4829c103faea2927c539cf249d679..fbaf624fe2808ed17067cb3dfb1a9a79b88bc966 100644 --- a/mobile/android/fenix/app/src/main/res/values/colors.xml +++ b/mobile/android/fenix/app/src/main/res/values/colors.xml @@ -300,6 +300,8 @@ <color name="sync_disconnected_icon_fill_private_theme">@color/photonYellow70</color> <color name="sync_disconnected_background_private_theme">#5B5846</color> <color name="prompt_login_edit_text_cursor_color_private_theme">@color/photonViolet50</color> + <color name="backgroundGradientDark">#FF3A3274</color> + <color name="backgroundGradientLight">#FF7329A4</color> <!-- Normal theme colors for light mode --> <color name="accent_normal_theme">@color/photonInk20</color> @@ -378,4 +380,9 @@ <!-- Private Mode mask icon circle fill colors --> <color name="mozac_ui_private_mode_circle_fill" tools:ignore="UnusedResources">@color/photonPurple60</color> + + <!-- Connection Assist --> + <color name="connect_button_purple">#9059FF</color> + <color name="configure_connection_button_white">#E1E0E7</color> + <color name="warning_yellow">#FFA436</color> </resources> diff --git a/mobile/android/fenix/app/src/main/res/values/ic_launcher_monochrome_background.xml b/mobile/android/fenix/app/src/main/res/values/ic_launcher_monochrome_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..71d80a9056ada38dc05a0fd5a5f7e984a39d1ccf --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/values/ic_launcher_monochrome_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_monochrome_background">#FEFBFF</color> +</resources> \ No newline at end of file diff --git a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml index a39babcf469d45df8304985e292a7a68591c5c7b..a5575254bbd563b3719ad701df7f44d8cb50eebe 100644 --- a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml +++ b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml @@ -14,6 +14,9 @@ <string name="pref_key_accessibility" translatable="false">pref_key_accessibility</string> <string name="pref_key_accessibility_auto_size" translatable="false">pref_key_accessibility_auto_size</string> <string name="pref_key_accessibility_font_scale" translatable="false">pref_key_accessibility_font_scale</string> + <string name="pref_key_privacy" translatable="false">pref_key_privacy</string> + <string name="pref_key_connection" translatable="false">pref_key_connection</string> + <string name="pref_key_quick_start" translatable="false">pref_key_quick_start</string> <string name="pref_key_accessibility_force_enable_zoom" translatable="false">pref_key_accessibility_force_enable_zoom</string> <string name="pref_key_advanced" translatable="false">pref_key_advanced</string> <string name="pref_key_language" translatable="false">pref_key_language</string> @@ -36,6 +39,7 @@ <string name="pref_key_delete_permissions_now" translatable="false">pref_key_delete_permissions_now</string> <string name="pref_key_delete_downloads_now" translatable="false">pref_key_delete_downloads_now</string> <string name="pref_key_delete_browsing_data_on_quit_categories" translatable="false">pref_key_delete_browsing_data_on_quit_categories</string> + <string name="pref_key_disable_normal_mode" translatable="false">pref_key_disable_normal_mode</string> <string name="pref_key_last_known_mode_private" translatable="false">pref_key_last_known_mode_private</string> <string name="pref_key_addons" translatable="false">pref_key_addons</string> <string name="pref_key_install_local_addon" translatable="false">pref_key_install_local_addon</string> @@ -43,6 +47,7 @@ <string name="pref_key_override_amo_collection" translatable="false">pref_key_override_amo_collection</string> <string name="pref_key_enable_gecko_logs" translatable="false">pref_key_enable_gecko_logs</string> <string name="pref_key_rate" translatable="false">pref_key_rate</string> + <string name="pref_key_donate" translatable="false">pref_key_donate</string> <string name="pref_key_about" translatable="false">pref_key_about</string> <string name="pref_key_account" translatable="false">pref_key_account</string> <string name="pref_key_sign_in" translatable="false">pref_key_sign_in</string> @@ -417,4 +422,33 @@ <!-- Bookmarks --> <string name="pref_key_use_new_bookmarks_ui" translatable="false">pref_key_use_new_bookmarks_ui</string> + + <string name="pref_key_noscript_installed" translatable="false">pref_key_noscript_installed</string> + <string name="pref_key_noscript_updated" translatable="false">pref_key_noscript_updated</string> + <string name="pref_key_https_everywhere_removed" translatable="false">pref_key_https_everywhere_removed</string> + + <!-- Security Level Settings --> + <string name="pref_key_tor_security_level_settings" translatable="false">pref_key_tor_security_level_settings</string> + <string name="pref_key_tor_security_level_standard_option" translatable="false">pref_key_tor_security_level_standard_option</string> + <string name="pref_key_tor_security_level_safer_option" translatable="false">pref_key_tor_security_level_safer_option</string> + <string name="pref_key_tor_security_level_safest_option" translatable="false">pref_key_tor_security_level_safest_option</string> + + <string name="pref_key_tor_network_settings_explanation" translatable="false">pref_key_tor_network_settings_explanation</string> + <string name="pref_key_tor_network_settings_bridge_config" translatable="false">pref_key_tor_network_settings_bridge_config</string> + <string name="pref_key_tor_logs" translatable="false">pref_key_tor_logs</string> + <string name="pref_key_use_html_connection_ui" translatable="false">pref_key_use_html_connection_ui</string> <!-- Changing the pref_key should reset it to off for users that had it enabled --> + <string name="pref_key_tor_network_settings_bridge_config_explanation" translatable="false">pref_key_tor_network_settings_bridge_config_explanation</string> + <string name="pref_key_tor_network_settings_bridge_config_toggle" translatable="false">pref_key_tor_network_settings_bridge_config_toggle</string> + <string name="pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4" translatable="false">pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4</string> + <string name="pref_key_tor_network_settings_bridge_config_builtin_bridge_meek_azure" translatable="false">pref_key_tor_network_settings_bridge_config_builtin_bridge_meek_azure</string> + <string name="pref_key_tor_network_settings_bridge_config_builtin_bridge_snowflake" translatable="false">pref_key_tor_network_settings_bridge_config_builtin_bridge_snowflake</string> + <string name="pref_key_tor_network_settings_bridge_config_user_provided_bridge" translatable="false">pref_key_tor_network_settings_bridge_config_user_provided_bridge</string> + <string name="pref_key_tor_network_settings_bridge_config_user_provided_bridge_preference" translatable="false">pref_key_tor_network_settings_bridge_config_user_provided_bridge_preference</string> + <string name="pref_key_tor_network_settings_bridge_config_current_bridge" translatable="false">pref_key_tor_network_settings_bridge_config_current_bridge</string> + <string name="pref_key_tor_network_settings_status">pref_key_tor_network_settings_status</string> + <string name="pref_key_tor_network_settings_tor_ready">pref_key_tor_network_settings_tor_ready</string> + <string name="pref_key_tor_network_settings_state">pref_key_tor_network_settings_state</string> + <string name="pref_key_tor_network_settings_bridges_enabled">pref_key_tor_network_settings_bridges_enabled</string> + + <string name="pref_key_spoof_english" translatable="false">pref_key_spoof_english</string> </resources> diff --git a/mobile/android/fenix/app/src/main/res/values/static_strings.xml b/mobile/android/fenix/app/src/main/res/values/static_strings.xml index 9f722ec5327fcaa531426ac5e96e8dfd45dc35d1..266bbe49d41616b1190e140b606d0b12e8faac70 100644 --- a/mobile/android/fenix/app/src/main/res/values/static_strings.xml +++ b/mobile/android/fenix/app/src/main/res/values/static_strings.xml @@ -4,8 +4,8 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <!-- Name of the application --> - <string name="app_name" translatable="false">Firefox Fenix</string> - <string name="firefox" translatable="false">Firefox</string> + <string name="app_name" translatable="false">Tor Browser Dev</string> + <string name="firefox" translatable="false">Tor Browser</string> <!-- Preference for developers --> <string name="preference_leakcanary" translatable="false">LeakCanary</string> diff --git a/mobile/android/fenix/app/src/main/res/values/styles.xml b/mobile/android/fenix/app/src/main/res/values/styles.xml index 7eb269190db08dc4eff1996c7e1596b308b94723..cb82b52b66a85a6745ab9057c90888baaa282e81 100644 --- a/mobile/android/fenix/app/src/main/res/values/styles.xml +++ b/mobile/android/fenix/app/src/main/res/values/styles.xml @@ -8,7 +8,7 @@ <style name="SplashScreenThemeBase" parent="Theme.SplashScreen"> <item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen</item> - <item name="windowSplashScreenBackground">@color/fx_mobile_layer_color_1</item> + <item name="windowSplashScreenBackground">@color/backgroundGradientDark</item> <item name="postSplashScreenTheme">@style/NormalTheme</item> <!-- Temporarily opt out of edge to edge enforcement. To be removed in https://bugzilla.mozilla.org/show_bug.cgi?id=1916695--> @@ -28,7 +28,7 @@ <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item> <item name="android:progressBarStyleHorizontal">@style/progressBarStyleHorizontal</item> <item name="android:statusBarColor">@android:color/transparent</item> - <item name="android:windowBackground">@color/fx_mobile_layer_color_1</item> + <item name="android:windowBackground">@color/backgroundGradientDark</item> <item name="android:colorEdgeEffect">@color/accent_normal_theme</item> <item name="android:colorAccent">@color/fx_mobile_text_color_primary</item> <item name="android:textColorPrimary">@color/state_list_text_color</item> @@ -133,9 +133,10 @@ <item name="mozac_widget_favicon_border_color">@color/fx_mobile_border_color_primary</item> <!-- Drawables --> - <item name="fenixLogo">@drawable/ic_logo_wordmark_normal</item> - <item name="fenixWordmarkText">@drawable/ic_wordmark_text_normal</item> - <item name="fenixWordmarkLogo">@drawable/ic_wordmark_logo</item> +<!-- Removed as part of tor-browser#42386--> +<!-- <item name="fenixLogo">@drawable/ic_logo_wordmark_normal</item>--> +<!-- <item name="fenixWordmarkText">@drawable/ic_wordmark_text_normal</item>--> +<!-- <item name="fenixWordmarkLogo">@drawable/ic_wordmark_logo</item>--> <item name="homeBackground">@color/fx_mobile_layer_color_1</item> <item name="bottomBarBackground">@drawable/home_bottom_bar_background</item> <item name="bottomBarBackgroundTop">@drawable/home_bottom_bar_background_top</item> @@ -332,10 +333,12 @@ <item name="mozac_widget_favicon_border_color">@color/photonInk50</item> <!-- Drawables --> - <item name="fenixLogo">@drawable/ic_logo_wordmark_private</item> - <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item> - <item name="fenixWordmarkLogo">@drawable/ic_wordmark_logo</item> +<!-- Removed as part of tor-browser#42386--> +<!-- <item name="fenixLogo">@drawable/ic_logo_wordmark_private</item>--> +<!-- <item name="fenixWordmarkText">@drawable/ic_wordmark_text_private</item>--> +<!-- <item name="fenixWordmarkLogo">@drawable/ic_wordmark_logo</item>--> <item name="homeBackground">@drawable/private_home_background_gradient</item> + <item name="torBootstrapBackground">@drawable/tor_bootstrap_background_gradient</item> <item name="bottomBarBackground">@drawable/private_home_bottom_bar_background_gradient</item> <item name="bottomBarBackgroundTop">@drawable/private_home_bottom_bar_background_gradient_top</item> <item name="mozac_ic_private_mode_circle_fill_background_color">@color/photonWhite</item> @@ -424,6 +427,20 @@ <item name="android:fontWeight" tools:ignore="NewApi">@integer/font_weight_medium</item> </style> + <style name="TorHeaderTextStyle" parent="TextAppearance.MaterialComponents.Subtitle1"> + <item name="android:textSize">18sp</item> + <item name="android:textColor">#000000</item> + <item name="android:textFontWeight" tools:ignore="NewApi">@integer/font_weight_medium</item> + <item name="android:fontWeight" tools:ignore="NewApi">@integer/font_weight_medium</item> + </style> + + <style name="Header24TextStyle" parent="TextAppearance.MaterialComponents.Body1"> + <item name="android:textColor">?textPrimary</item> + <item name="android:textSize">24sp</item> + <item name="android:textFontWeight" tools:ignore="NewApi">@integer/font_weight_medium</item> + <item name="android:fontWeight" tools:ignore="NewApi">@integer/font_weight_medium</item> + </style> + <style name="Header20TextStyle" parent="TextAppearance.MaterialComponents.Body1" tools:ignore="UnusedResources"> <item name="android:textColor">?attr/textPrimary</item> <item name="android:textSize">20sp</item> @@ -465,6 +482,10 @@ <item name="android:textAllCaps">false</item> </style> + <style name="TorBody16TextStyle" parent="TextAppearance.MaterialComponents.Body1"> + <item name="android:textColor">#000000</item> + </style> + <style name="Subtitle12TextStyle" parent="TextAppearance.MaterialComponents.Body1"> <item name="android:textColor">?attr/textSecondary</item> <item name="android:textSize">12sp</item> diff --git a/mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml b/mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5b6b123b0d6f1887d1e31345025ce8c28fb051b --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?><!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<resources> + <!-- About content. The first parameter is the name of the application. (For example: Fenix) --> + <string name="tor_about_content">%1$s is produced by the Tor Project, a U.S.-based 501(c)(3) nonprofit.</string> + + <!-- Preference for enabling non-Private Browsing Mode--> + <string name="preferences_disable_normal_mode">Allow Only Private Browsing Mode</string> + <!-- Preference link to donate to The Tor Project--> + <string name="preferences_donate">Donate to The Tor Project</string> + <!-- Preference for allowing screenshots to be taken in the app--> + <string name="preferences_allow_screenshots">Allow screenshots</string> + + <string name="tor_bootstrap_connect">Connect</string> + <string name="tor_bootstrap_connecting">Connecting</string> + <string name="tor_bootstrap_connecting_failed">Connecting Failed</string> + <string name="tor_bootstrap_quick_start_label">Quick Start</string> + <string name="tor_bootstrap_quick_start_disabled">Enable Quick Start to connect automatically in the future</string> + <string name="tor_bootstrap_quick_start_enabled">%s will connect automatically to the Tor Network in the future</string> + <string name="tor_bootstrap_swipe_for_logs">Swipe to the left to see Tor logs</string> + <string name="tor_initializing_log">Initializing Tor Log</string> + + <string name="tor_onboarding_security_level">Set your Security Level</string> + <string name="tor_onboarding_security_level_description">Disable certain web features that can be used to attack you, and harm your security, anonymity, and privacy.</string> + <string name="tor_onboarding_chosen_security_level_label">Current Security Level: %s</string> + <string name="tor_onboarding_security_settings_button">Open Security Settings</string> + <string name="tor_onboarding_donate_header">Donate and keep Tor safe</string> + <string name="tor_onboarding_donate_description">Tor is free to use because of donations from people like you.</string> + <string name="tor_onboarding_donate_button">Donate Now</string> + + <string name="tor_explore_privately">Explore. Privately.</string> + + <string name="library_new_circuit">New circuit</string> + + <string name="preferences_tor_connection_settings_title">Connection</string> + <string name="preferences_tor_network_settings">Tor Network</string> + <string name="preferences_tor_network_settings_explanation">Tor Browser routes your traffic over the Tor Network, run by thousands of volunteers around the world.</string> + <string name="preferences_tor_network_settings_bridge_config">Config Bridge</string> + <string name="preferences_tor_network_settings_bridge_config_description">Use a Bridge to connect to Tor</string> + <string name="preferences_tor_network_settings_bridge_config_description_builtin_transport_enabled">You’re using a built-in bridge to connect to Tor</string> + <string name="preferences_tor_network_settings_bridge_config_description_user_provided_enabled">You provided a bridge to connect to Tor</string> + <string name="preferences_tor_network_settings_bridge_config_explanation">Bridges are unlisted relays that make it more difficult to block connections to the Tor Network. Because of how certain countries try to block Tor, certain bridges work in certain countries but not others.</string> + <string name="preferences_tor_network_settings_bridge_config_toggle">Use a Bridge</string> + <string name="preferences_tor_network_settings_bridge_config_toggle_description">Config a bridge to connect to Tor</string> + <string name="preferences_tor_network_settings_bridge_config_builtin_bridge_obfs4">obfs4</string> + <string name="preferences_tor_network_settings_bridge_config_builtin_bridge_meek_azure">meek-azure</string> + <string name="preferences_tor_network_settings_bridge_config_builtin_bridge_snowflake">snowflake</string> + <string name="preferences_tor_network_settings_bridge_config_user_provided_bridge">Provide a Bridge I know</string> + <string name="preferences_tor_network_settings_bridge_config_user_provided_bridge_description">Enter bridge information from a trusted source</string> + <string name="preferences_tor_network_settings_bridge_config_current_bridge">Current Configured Bridge: %s</string> + <string name="tor_network_settings_bridge_not_configured">Not Configured</string> + <string name="preferences_tor_network_settings_status">Current Status</string> + <string name="preferences_tor_network_settings_tor_ready">Is Tor Ready: %s</string> + <string name="preferences_tor_network_settings_state">State: %s</string> + <string name="preferences_tor_network_settings_yes">Yes</string> + <string name="preferences_tor_network_settings_no">No</string> + <string name="preferences_tor_network_settings_disconnected">Disconnected</string> + <string name="preferences_tor_network_settings_connecting">Connecting</string> + <string name="preferences_tor_network_settings_connected">Connected</string> + <string name="preferences_tor_network_settings_restarting">Restarting</string> + <string name="preferences_tor_network_settings_bridges_enabled">Bridges are enabled: %s</string> + <string name="preferences_tor_logs">Tor Logs</string> + <string name="preferences_tor_logs_description">View and copy your Tor logs</string> + + <!-- Preference title for security level settings --> + <string name="preferences_tor_security_level_settings">Security Settings</string> + <string name="preferences_tor_security_level_options">Security Level</string> + + <!-- Description of security levels --> + <string name="tor_security_level_standard_option">Standard</string> + <string name="tor_security_level_standard_description">All Tor Browser and website features are enabled.</string> + <string name="tor_security_level_safer_option">Safer</string> + <string name="tor_security_level_safer_description">Disable website features that are often dangerous, causing some sites to lose functionality.</string> + <string name="tor_security_level_safest_option">Safest</string> + <string name="tor_security_level_safest_description">Only allow website features required for static sites and basic services. These changes affect images, media, and scripts.</string> + + <string name="btn_cancel">Cancel</string> + + <!-- Spoof locale to English --> + <string name="tor_spoof_english">Request English versions of web pages for enhanced privacy</string> + + <!-- Connection assist. --> + <string name="connection_assist_tor_connect_title">Connect to Tor</string> + <!-- Connection assist. --> + <string name="connection_assist_always_connect_automatically_toggle_description">Always connect automatically</string> + <!-- Connection assist. --> + <string name="connection_assist_configure_connection_button">Configure connection…</string> + + <!-- Connection assist. --> + <string name="connection_assist_connecting_title">Establishing a connection…</string> + + <!-- Connection assist. --> + <string name="connection_assist_internet_error_title">We can’t reach the internet</string> + <!-- Connection assist. %1$s is connection_assist_internet_error_learn_more--> + <string name="connection_assist_internet_error_description">This could be due to a connection issue rather than Tor being blocked. Check your internet connection, proxy, and firewall settings before trying again. %1$s</string> + <!-- Connection assist. --> + <string name="connection_assist_internet_error_learn_more">Learn more</string> + <!-- Connection assist. --> + <string name="connection_assist_internet_error_try_again">Try again</string> + + <!-- Connection assist. --> + <string name="connection_assist_trying_again_waiting_title">Trying again…</string> + + <!-- Connection assist. --> + <string name="connection_assist_cant_connect_to_tor_title">We can’t connect to Tor directly</string> + <!-- Connection assist. %1$s is connection_assist_try_a_bridge_learn_more--> + <string name="connection_assist_try_a_bridge_description">Try connecting via a bridge instead. By providing your location, we can look up the bridge that’s most likely to unblock the internet in your country or region. %1$s</string> + <!-- Connection assist. --> + <string name="connection_assist_unblock_the_internet_in_country_or_region">Unblock the internet in:</string> + <!-- Connection assist. --> + <string name="connection_assist_share_my_location_country_or_region">Share my location</string> + <!-- Connection assist. --> + <string name="connection_assist_try_a_bridge_button">Try a bridge</string> + + <!-- Connection assist. %1$s is connection_assist_choose_a_bridge_manually_link--> + <string name="connection_assist_try_a_bridge_learn_more_description1">Tor Browser will need to establish a brief non-Tor connection to determine your location and look up a bridge. If you don’t want to do that, you can %1$s instead.</string> + <!-- Connection assist. --> + <string name="connection_assist_choose_a_bridge_manually_link">choose a bridge manually</string> + <!-- Connection assist. %s is the error code--> + <string name="connection_assist_try_a_bridge_learn_more_error_code">Error code: %s</string> + + <!-- Connection assist. --> + <string name="connection_assist_trying_a_bridge_title">Trying a bridge…</string> + + <!-- Connection assist. --> + <string name="connection_assist_location_error_title">We couldn’t find your location</string> + <!-- Connection assist. %1$s is connection_assist_find_bridge_location_description, %2$s is connection_assist_select_country_try_again, %3$s is connection_assist_location_error_learn_more_link--> + <string name="connection_assist_location_error_description" translatable="false">%1$s %2$s %3$s</string> + <string name="connection_assist_find_bridge_location_description">To find a bridge that can unblock your internet, we need to know where you’re connecting from.</string> + <string name="connection_assist_select_country_try_again">Select your country or region and try again.</string> + <!-- Connection assist. %1$s is connection_assist_find_bridge_location_description, %2$s is connection_assist_check_location_settings_try_again. %3$s is connection_assist_location_error_learn_more_link--> + <string name="connection_assist_location_error_last_try_description">%1$s %2$s %3$s</string> + <string name="connection_assist_check_location_settings_try_again">Please check your location settings are correct and try again.</string> + + <string name="connection_assist_location_error_learn_more_link">Learn more</string> + + <!-- Connection assist. --> + <string name="connection_assist_location_check_title">We’re still having trouble connecting</string> + + <!-- Connection assist. --> + <string name="connection_assist_last_try_title">Trying one more time…</string> + + <!-- Connection assist. --> + <string name="connection_assist_final_error_title">We weren’t able to connect automatically</string> + <!-- Connection assist. %1$s is connection_assist_final_error_troubleshoot_connection_link. %2$s is connection_assist_final_error_learn_more_link--> + <string name="connection_assist_final_error_description1">Despite our best efforts, we weren’t able to connect to Tor. We recommend %1$s and adding a bridge manually instead. %2$s</string> + <!-- Connection assist. --> + <string name="connection_assist_final_error_troubleshoot_connection_link">troubleshooting your connection</string> + <!-- Connection assist. --> + <string name="connection_assist_final_error_learn_more_link">Learn more</string> + <!-- Connection assist. Description for a shown "Snackbar" (special popup notification) with an action to connect. --> + <string name="connection_assist_connect_to_tor_before_opening_links">Connect to Tor before opening links</string> + <!-- Connection assist. Confirmation button for a shown "Snackbar" (special popup notification). --> + <string name="connection_assist_connect_to_tor_before_opening_links_confirmation">CONNECT</string> + +</resources> diff --git a/mobile/android/fenix/app/src/main/res/xml/logins_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/logins_preferences.xml index 1a8810eca78ddb410f8d7cea13bea83b76924a73..be71a3c17b627e7a6c5de1c4a19740a5a1ba4ed3 100644 --- a/mobile/android/fenix/app/src/main/res/xml/logins_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/logins_preferences.xml @@ -18,6 +18,7 @@ android:title="@string/preferences_android_autofill" android:summary="@string/preferences_android_autofill_description" /> <org.mozilla.fenix.settings.SyncPreference + app:isPreferenceVisible="false" android:key="@string/pref_key_sync_logins" android:title="@string/preferences_passwords_sync_logins_2" /> <Preference diff --git a/mobile/android/fenix/app/src/main/res/xml/preferences.xml b/mobile/android/fenix/app/src/main/res/xml/preferences.xml index 9560b96efda626d5a4b223eba08a633e5b3901a7..d72a27964542d677fd0cd27c67aed9aaf77a964e 100644 --- a/mobile/android/fenix/app/src/main/res/xml/preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/preferences.xml @@ -11,11 +11,13 @@ android:layout="@layout/sign_in_preference" android:summary="@string/preferences_sign_in_description_2" android:title="@string/preferences_sync_2" + app:isPreferenceVisible="false" app:allowDividerBelow="false" /> <androidx.preference.SwitchPreference android:key="@string/pref_key_allow_domestic_china_fxa_server" android:title="@string/preferences_allow_domestic_china_fxa_server" + app:isPreferenceVisible="false" android:defaultValue="true"/> <androidx.preference.PreferenceCategory @@ -25,11 +27,11 @@ android:layout="@layout/preference_category_no_icon_style"> <org.mozilla.fenix.settings.account.AccountPreference - android:icon="@drawable/ic_account" + android:icon="@drawable/mozac_lib_crash_notification" android:key="@string/pref_key_account" /> <org.mozilla.fenix.settings.account.AccountAuthErrorPreference - android:icon="@drawable/ic_account_warning" + android:icon="@drawable/mozac_lib_crash_notification" android:key="@string/pref_key_account_auth_error" /> </androidx.preference.PreferenceCategory> @@ -52,10 +54,10 @@ android:key="@string/pref_key_tabs" android:title="@string/preferences_tabs" /> - <androidx.preference.Preference - app:iconSpaceReserved="false" - android:key="@string/pref_key_home" - android:title="@string/preferences_home_2" /> +<!-- <androidx.preference.Preference--> +<!-- app:iconSpaceReserved="false"--> +<!-- android:key="@string/pref_key_home"--> +<!-- android:title="@string/preferences_home_2" />--> <androidx.preference.Preference android:key="@string/pref_key_customize" @@ -69,6 +71,7 @@ <androidx.preference.Preference app:iconSpaceReserved="false" + app:isPreferenceVisible="false" android:key="@string/pref_key_credit_cards" android:title="@string/preferences_credit_cards_2" /> @@ -96,11 +99,18 @@ <androidx.preference.PreferenceCategory android:title="@string/preferences_category_privacy_security" + android:key="@string/pref_key_privacy" android:layout="@layout/preference_category_no_icon_style"> + <androidx.preference.Preference + android:key="@string/pref_key_tor_security_level_settings" + app:iconSpaceReserved="false" + android:title="@string/preferences_tor_security_level_options" /> + <androidx.preference.Preference android:key="@string/pref_key_private_browsing" app:iconSpaceReserved="false" + app:isPreferenceVisible="false" android:title="@string/preferences_private_browsing_options" /> <androidx.preference.Preference @@ -117,6 +127,7 @@ <androidx.preference.Preference android:key="@string/pref_key_tracking_protection_settings" app:iconSpaceReserved="false" + app:isPreferenceVisible="false" android:title="@string/preference_enhanced_tracking_protection" /> <androidx.preference.Preference @@ -142,14 +153,64 @@ <androidx.preference.Preference android:key="@string/pref_key_data_choices" app:iconSpaceReserved="false" + app:isPreferenceVisible="false" android:title="@string/preferences_data_collection" /> </androidx.preference.PreferenceCategory> + <!-- title="@string/preferences_category_advanced" + key="@string/pref_key_advanced"--> + <PreferenceCategory + android:title="@string/preferences_tor_connection_settings_title" + android:key="@string/pref_key_connection" + android:layout="@layout/preference_category_no_icon_style"> + + <Preference + android:key="@string/pref_key_tor_network_settings_explanation" + app:iconSpaceReserved="false" + android:title="@string/preferences_tor_network_settings_explanation" /> + + <Preference + android:key="@string/pref_key_tor_network_settings_bridge_config" + app:iconSpaceReserved="false" + android:title="@string/preferences_tor_network_settings_bridge_config" + android:summary="@string/preferences_tor_network_settings_bridge_config_description" /> + + <org.mozilla.fenix.tor.QuickStartPreference + android:key="@string/pref_key_quick_start" + android:summary="@string/connection_assist_always_connect_automatically_toggle_description" + android:title="@string/tor_bootstrap_quick_start_label" + app:iconSpaceReserved="false" /> + + <SwitchPreference + android:defaultValue="false" + android:key="@string/pref_key_use_html_connection_ui" + android:summary="Recommended only for debugging" + android:title="Enable HTML connection UI" + app:iconSpaceReserved="false" /> + + <Preference + android:key="@string/pref_key_tor_logs" + app:iconSpaceReserved="false" + android:title="@string/preferences_tor_logs" + android:summary="@string/preferences_tor_logs_description" /> + + <!-- Auto connect --> + + <!-- Tor Logs --> + + </PreferenceCategory> + <PreferenceCategory android:title="@string/preferences_category_advanced" android:key="@string/pref_key_advanced" android:layout="@layout/preference_category_no_icon_style"> + + <SwitchPreference + android:key="@string/pref_key_allow_screenshots_in_private_mode" + app:iconSpaceReserved="false" + android:title="@string/preferences_allow_screenshots" /> + <androidx.preference.Preference android:key="@string/pref_key_addons" app:iconSpaceReserved="false" @@ -165,16 +226,17 @@ android:key="@string/pref_key_override_amo_collection" app:iconSpaceReserved="false" android:title="@string/preferences_customize_extension_collection" /> - + <!-- <androidx.preference.Preference android:key="@string/pref_key_open_links_in_apps" android:title="@string/preferences_open_links_in_apps" app:iconSpaceReserved="false" /> - + --> <androidx.preference.SwitchPreference android:defaultValue="false" android:key="@string/pref_key_external_download_manager" app:iconSpaceReserved="false" + app:isPreferenceVisible="false" android:title="@string/preferences_external_download_manager" /> <androidx.preference.SwitchPreference @@ -210,6 +272,11 @@ app:iconSpaceReserved="false" android:title="@string/preferences_about" /> + <androidx.preference.Preference + android:icon="@drawable/ic_favorite" + android:key="@string/pref_key_donate" + android:title="@string/preferences_donate" /> + <androidx.preference.Preference android:key="@string/pref_key_debug_settings" app:iconSpaceReserved="false" diff --git a/mobile/android/fenix/app/src/main/res/xml/private_browsing_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/private_browsing_preferences.xml index b38305b2cde29ea3ffbd117b37e3e0db36c1d075..68486df5a67d3fd50b820478b3a31a6e1189a575 100644 --- a/mobile/android/fenix/app/src/main/res/xml/private_browsing_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/private_browsing_preferences.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <Preference + android:defaultValue="false" android:key="@string/pref_key_add_private_browsing_shortcut" android:title="@string/preferences_add_private_browsing_shortcut" /> <SwitchPreference diff --git a/mobile/android/fenix/app/src/main/res/xml/search_settings_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/search_settings_preferences.xml index a4de5c17213f7d5a90e377e5b2eafe9f47bfc066..60827ac499c747c37f1eb5a4d69bc6fd7fcf3cc4 100644 --- a/mobile/android/fenix/app/src/main/res/xml/search_settings_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/search_settings_preferences.xml @@ -39,21 +39,11 @@ app:iconSpaceReserved="false" /> </PreferenceCategory> - <PreferenceCategory + <!-- <PreferenceCategory android:title="@string/preference_search_address_bar_fx_suggest" android:selectable="false" app:iconSpaceReserved="false" android:layout="@layout/preference_category_no_icon_style"> - <SwitchPreference - app:iconSpaceReserved="false" - android:defaultValue="true" - android:key="@string/pref_key_search_browsing_history" - android:title='@string/preferences_search_browsing_history' /> - <SwitchPreference - app:iconSpaceReserved="false" - android:defaultValue="true" - android:key="@string/pref_key_search_bookmarks" - android:title='@string/preferences_search_bookmarks' /> <SwitchPreference app:iconSpaceReserved="false" android:defaultValue="true" @@ -73,7 +63,7 @@ app:iconSpaceReserved="false" android:key="@string/pref_key_learn_about_fx_suggest" android:title="@string/preference_search_learn_about_fx_suggest" /> - </PreferenceCategory> + </PreferenceCategory> --> <PreferenceCategory android:title="@string/preferences_settings_address_bar" @@ -85,6 +75,16 @@ android:defaultValue="true" android:key="@string/pref_key_show_clipboard_suggestions" android:title="@string/preferences_show_clipboard_suggestions" /> + <SwitchPreference + app:iconSpaceReserved="false" + android:defaultValue="true" + android:key="@string/pref_key_search_browsing_history" + android:title='@string/preferences_search_browsing_history' /> + <SwitchPreference + app:iconSpaceReserved="false" + android:defaultValue="true" + android:key="@string/pref_key_search_bookmarks" + android:title='@string/preferences_search_bookmarks' /> <SwitchPreference app:iconSpaceReserved="false" android:defaultValue="true" diff --git a/mobile/android/fenix/app/src/main/res/xml/shortcuts.xml b/mobile/android/fenix/app/src/main/res/xml/shortcuts.xml index fb28b5782b451a3c5e570730d626e6b37c36f178..bb69e29a2cf0c1a3387db373a4726a2c7881ad75 100644 --- a/mobile/android/fenix/app/src/main/res/xml/shortcuts.xml +++ b/mobile/android/fenix/app/src/main/res/xml/shortcuts.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- <shortcut android:shortcutId="password_manager" android:enabled="true" @@ -21,7 +22,7 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_TAB" - android:targetPackage="org.mozilla.fenix" + android:targetPackage="org.torproject.torbrowser_dev" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> <shortcut @@ -31,7 +32,8 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_private_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_PRIVATE_TAB" - android:targetPackage="org.mozilla.fenix" + android:targetPackage="org.torproject.torbrowser_dev" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> + --> </shortcuts> diff --git a/mobile/android/fenix/app/src/main/res/xml/site_permissions_details_exceptions_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/site_permissions_details_exceptions_preferences.xml index 6bb8cfbbe633fc2fafa4967912c477f918223340..ac2eaae71d8e9e97f1b448db85893328d1f4cf3d 100644 --- a/mobile/android/fenix/app/src/main/res/xml/site_permissions_details_exceptions_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/site_permissions_details_exceptions_preferences.xml @@ -3,7 +3,8 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <androidx.preference.PreferenceScreen - xmlns:android="http://schemas.android.com/apk/res/android"> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> <androidx.preference.Preference android:icon="@drawable/ic_camera_enabled" android:key="@string/pref_key_phone_feature_camera" @@ -44,6 +45,7 @@ android:icon="@drawable/ic_link" android:key="@string/pref_key_browser_feature_media_key_system_access" android:title="@string/preference_phone_feature_media_key_system_access" + app:isPreferenceVisible="false" android:summary="@string/preference_option_phone_feature_ask_to_allow"/> <androidx.preference.Preference diff --git a/mobile/android/fenix/app/src/main/res/xml/site_permissions_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/site_permissions_preferences.xml index 64c90b599b71f88ea7354be46ae8b513dd306ca6..621f184e68adb321eff5f4a9691260e59d9a82ef 100644 --- a/mobile/android/fenix/app/src/main/res/xml/site_permissions_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/site_permissions_preferences.xml @@ -64,6 +64,7 @@ android:key="@string/pref_key_browser_feature_media_key_system_access" android:title="@string/preference_phone_feature_media_key_system_access" android:summary="@string/preference_option_phone_feature_ask_to_allow" + app:isPreferenceVisible="false" app:allowDividerBelow="true"/> <androidx.preference.Preference diff --git a/mobile/android/fenix/app/src/main/res/xml/sync_problem.xml b/mobile/android/fenix/app/src/main/res/xml/sync_problem.xml index 6d1bd6760c3f9ad9f0c8f44ce625cf1f7e59bf69..1cc02edb84336ee2e88a35ba2288ed6cce28e34d 100644 --- a/mobile/android/fenix/app/src/main/res/xml/sync_problem.xml +++ b/mobile/android/fenix/app/src/main/res/xml/sync_problem.xml @@ -7,7 +7,7 @@ <androidx.preference.Preference android:key="@string/pref_key_sync_sign_in" android:title="@string/preferences_sync_sign_in_to_reconnect" - android:icon="@drawable/ic_sign_in" /> + android:icon="@drawable/mozac_lib_crash_notification" /> <androidx.preference.Preference android:key="@string/pref_key_sign_out" android:title="@string/preferences_sync_remove_account"/> diff --git a/mobile/android/fenix/app/src/main/res/xml/tor_bridge_config_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/tor_bridge_config_preferences.xml new file mode 100644 index 0000000000000000000000000000000000000000..3112f57bdcb9b38e9361d18c883258f825bbf9cd --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/xml/tor_bridge_config_preferences.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <androidx.preference.Preference + android:key="@string/pref_key_tor_network_settings_bridge_config_explanation" + android:summary="@string/preferences_tor_network_settings_bridge_config_explanation" + app:allowDividerBelow="false" /> + <SwitchPreference + android:defaultValue="false" + android:key="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:title="@string/preferences_tor_network_settings_bridge_config_toggle" + android:summary="@string/preferences_tor_network_settings_bridge_config_toggle_description" /> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="false" + android:dependency="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:key="@string/pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4" + android:title="@string/preferences_tor_network_settings_bridge_config_builtin_bridge_obfs4" /> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="false" + android:dependency="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:key="@string/pref_key_tor_network_settings_bridge_config_builtin_bridge_meek_azure" + android:title="@string/preferences_tor_network_settings_bridge_config_builtin_bridge_meek_azure" /> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="false" + android:dependency="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:key="@string/pref_key_tor_network_settings_bridge_config_builtin_bridge_snowflake" + android:title="@string/preferences_tor_network_settings_bridge_config_builtin_bridge_snowflake" /> + <EditTextPreference + android:dependency="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:key="@string/pref_key_tor_network_settings_bridge_config_user_provided_bridge" + android:title="@string/preferences_tor_network_settings_bridge_config_user_provided_bridge" + android:summary="@string/preferences_tor_network_settings_bridge_config_user_provided_bridge_description" /> + <Preference + android:dependency="@string/pref_key_tor_network_settings_bridge_config_toggle" + android:key="@string/pref_key_tor_network_settings_bridge_config_current_bridge" + android:title="@string/preferences_tor_network_settings_bridge_config_current_bridge" /> +</androidx.preference.PreferenceScreen> diff --git a/mobile/android/fenix/app/src/main/res/xml/tor_security_level_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/tor_security_level_preferences.xml new file mode 100644 index 0000000000000000000000000000000000000000..14fd424425c117bc01c6d1a2fc49634a8833eac5 --- /dev/null +++ b/mobile/android/fenix/app/src/main/res/xml/tor_security_level_preferences.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="true" + android:key="@string/pref_key_tor_security_level_standard_option" + android:summary="@string/tor_security_level_standard_description" + android:title="@string/tor_security_level_standard_option" /> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="false" + android:key="@string/pref_key_tor_security_level_safer_option" + android:summary="@string/tor_security_level_safer_description" + android:title="@string/tor_security_level_safer_option" /> + <org.mozilla.fenix.settings.RadioButtonPreference + android:defaultValue="false" + android:key="@string/pref_key_tor_security_level_safest_option" + android:summary="@string/tor_security_level_safest_description" + android:title="@string/tor_security_level_safest_option" /> +</androidx.preference.PreferenceScreen> diff --git a/mobile/android/fenix/app/src/nightly/ic_launcher-playstore.png b/mobile/android/fenix/app/src/nightly/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..53dbdbc88298418594d96f29058fe35a25ee713b Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/ic_launcher-playstore.png differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.png b/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..4af23121eb4c1ba61d871dcbbb54c0eef9664888 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.png differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.webp b/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.webp deleted file mode 100644 index 2e6170d2b4f330880669ca7c5249433090762be7..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/fenix_search_widget.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 80761a5eeb99e81ccb23c265988810074e11ca97..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 61f071c9a3a38f4633d4a8907906b1d1e8330e3f..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-hdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index f37062ce2bd868456992bed4dd621afc52d9f42c..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 5202c774429be8c5a1ad199c824071155da8dc24..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-mdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index c431737e4ee5deed1d6989603cd03c953973181e..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index f0b8d507ed99d4fac651f23076d47263ce8f8f14..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 7361f8e7dc215eb8ab179a023a3a1befd74ae5de..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 4e36e421d326f25e99135fbf44a320319213d1c5..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xxhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 6493f7e46bf90159329de53096469edd4f2d5392..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index a56edb13d0ed737d78511668c8ce3c8c851e086e..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable-xxxhdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/animated_splash_screen.xml b/mobile/android/fenix/app/src/nightly/res/drawable/animated_splash_screen.xml deleted file mode 100644 index 27301cb41de72a5be316b4d82647e789ee6e6735..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/nightly/res/drawable/animated_splash_screen.xml +++ /dev/null @@ -1,552 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" > - <aapt:attr name="android:drawable"> - <vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="432dp" - android:height="432dp" - android:viewportWidth="432" - android:viewportHeight="432"> - <group - android:name="a1_t" - android:pivotX="216" - android:pivotY="216"> - <path - android:pathData="M339.5,170.7c-5.8,-13.9 -17.5,-29 -26.7,-33.7c7.5,14.7 11.8,29.5 13.5,40.5c0,0 0,0.1 0,0.2c-15,-37.5 -40.7,-52.7 -61.5,-85.6c-1.1,-1.7 -2.1,-3.3 -3.1,-5.1c-0.5,-0.9 -1,-1.9 -1.5,-2.8c-0.9,-1.7 -1.6,-3.4 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1c0,0 0,-0.1 0.1,-0.1c-33.5,19.6 -44.8,55.9 -45.9,74.1c-13.4,0.9 -26.1,5.8 -36.6,14.1c-1.1,-0.9 -2.3,-1.8 -3.4,-2.7c-3,-10.6 -3.1,-21.9 -0.4,-32.6c-13.7,6.2 -24.4,16.1 -32.1,24.8h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-0.1,-0.3 -3.9,2 -4.4,2.4c-4.6,3.3 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0c-8.5,12.2 -14.6,25.8 -17.9,40.4c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.2,7.1 -1.3,8.3c0,0.1 0,0.2 0,0.3c-1.2,6.1 -1.9,12.2 -2.2,18.4c0,0.2 0,0.5 0,0.7c0,73.6 59.6,133.3 133.3,133.3c65.9,0 120.6,-47.8 131.3,-110.7c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.8 347.8,190.9 339.5,170.7L339.5,170.7zM185.9,275c0.6,0.3 1.2,0.6 1.9,0.9c0,0 0.1,0 0.1,0.1C187.2,275.7 186.5,275.3 185.9,275L185.9,275zM326.3,177.7L326.3,177.7L326.3,177.7L326.3,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="335.58" - android:startY="149.01" - android:endX="105.04" - android:endY="294.24" - android:type="linear"> - <item android:offset="0" android:color="#FF74DDB2"/> - <item android:offset="0.41" android:color="#FF50AFED"/> - <item android:offset="0.42" android:color="#FF4FACED"/> - <item android:offset="0.82" android:color="#FF5761E0"/> - <item android:offset="1" android:color="#FF6E44DC"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.9 -17.5,-29 -26.7,-33.7c7.5,14.7 11.8,29.5 13.5,40.5c0,0 0,0 0,0.1v0.1c12.6,34.1 5.7,68.8 -4.1,90c-15.2,32.8 -52.2,66.4 -110.1,64.7c-62.6,-1.8 -117.6,-48.1 -127.9,-108.9c-1.9,-9.6 0,-14.4 1,-22.2c-1.2,6 -1.6,7.8 -2.2,18.4c0,0.2 0,0.5 0,0.7c0,73.6 59.6,133.2 133.3,133.2c65.9,0 120.6,-47.8 131.3,-110.7c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.8 347.8,190.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="311.25" - android:centerY="108.94" - android:gradientRadius="277.78" - android:type="radial"> - <item android:offset="0.11" android:color="#FF74DDB2"/> - <item android:offset="0.12" android:color="#FF70D8B4"/> - <item android:offset="0.25" android:color="#FF54AFCE"/> - <item android:offset="0.36" android:color="#FF4496DF"/> - <item android:offset="0.42" android:color="#FF3F8DE5"/> - <item android:offset="0.49" android:color="#FF4280E8"/> - <item android:offset="0.64" android:color="#FF6F65F1"/> - <item android:offset="0.71" android:color="#FF875CF5"/> - <item android:offset="0.8" android:color="#FF764BE3"/> - <item android:offset="0.86" android:color="#FF6E44DC"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.9 -17.5,-29 -26.7,-33.7c7.5,14.7 11.8,29.5 13.5,40.5c0,0 0,0 0,0.1v0.1c12.6,34.1 5.7,68.8 -4.1,90c-15.2,32.8 -52.2,66.4 -110.1,64.7c-62.6,-1.8 -117.6,-48.1 -127.9,-108.9c-1.9,-9.6 0,-14.4 1,-22.2c-1.2,6 -1.6,7.8 -2.2,18.4c0,0.2 0,0.5 0,0.7c0,73.6 59.6,133.2 133.3,133.2c65.9,0 120.6,-47.8 131.3,-110.7c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.8 347.8,190.9 339.5,170.7L339.5,170.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="209.75" - android:centerY="222.48" - android:gradientRadius="277.78" - android:type="radial"> - <item android:offset="0.3" android:color="#FF412887"/> - <item android:offset="0.34" android:color="#C8502A8F"/> - <item android:offset="0.43" android:color="#5C6F2FA2"/> - <item android:offset="0.49" android:color="#198132AE"/> - <item android:offset="0.53" android:color="#008833B2"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M274.7,186.4c0.3,0.2 0.6,0.4 0.8,0.6c-3.3,-5.9 -7.5,-11.4 -12.4,-16.1c-41.4,-41.4 -10.9,-89.8 -5.7,-92.2c0,0 0,-0.1 0.1,-0.1c-33.5,19.6 -44.8,55.9 -45.9,74.1c1.6,-0.1 3.1,-0.2 4.7,-0.2C241.3,152.3 263,166 274.7,186.4L274.7,186.4L274.7,186.4z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="243.24" - android:centerY="45.9" - android:gradientRadius="201.24" - android:type="radial"> - <item android:offset="0.13" android:color="#FF74DDB2"/> - <item android:offset="0.29" android:color="#FF65CCC6"/> - <item android:offset="0.53" android:color="#FF50AFED"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c-0.2,3.3 -11.9,14.7 -16,14.7c-37.9,0 -44,22.9 -44,22.9c1.7,19.3 15.1,35.2 31.4,43.6c0.8,0.4 1.5,0.7 2.3,1.1c1.3,0.6 2.6,1.1 3.9,1.6c5.6,2 11.4,3.1 17.4,3.3c66.4,3.1 79.3,-79.4 31.3,-103.3c12.3,-2.2 25,2.8 32.1,7.8c-11.7,-20.3 -33.4,-34.1 -58.3,-34.1c-1.6,0 -3.1,0.1 -4.7,0.2c-13.4,0.9 -26.1,5.8 -36.6,14.1c2.1,1.8 4.3,4 9.1,8.7C193.2,184.4 216.4,193.6 216.4,194.7L216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="179.02" - android:centerY="295.03" - android:gradientRadius="132.26" - android:type="radial"> - <item android:offset="0.29" android:color="#FF285ED6"/> - <item android:offset="0.42" android:color="#FF3156D8"/> - <item android:offset="0.6" android:color="#FF4E4CDA"/> - <item android:offset="0.75" android:color="#FF6647DB"/> - <item android:offset="0.83" android:color="#FF6E44DC"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c-0.2,3.3 -11.9,14.7 -16,14.7c-37.9,0 -44,22.9 -44,22.9c1.7,19.3 15.1,35.2 31.4,43.6c0.8,0.4 1.5,0.7 2.3,1.1c1.3,0.6 2.6,1.1 3.9,1.6c5.6,2 11.4,3.1 17.4,3.3c66.4,3.1 79.3,-79.4 31.3,-103.3c12.3,-2.2 25,2.8 32.1,7.8c-11.7,-20.3 -33.4,-34.1 -58.3,-34.1c-1.6,0 -3.1,0.1 -4.7,0.2c-13.4,0.9 -26.1,5.8 -36.6,14.1c2.1,1.8 4.3,4 9.1,8.7C193.2,184.4 216.4,193.6 216.4,194.7L216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="217.11" - android:centerY="186.85" - android:gradientRadius="70.12" - android:type="radial"> - <item android:offset="0.21" android:color="#00412887"/> - <item android:offset="0.25" android:color="#0E402784"/> - <item android:offset="0.72" android:color="#9634206B"/> - <item android:offset="0.96" android:color="#CC2F1D60"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M168.8,162.3c0.9,0.6 1.9,1.2 2.8,1.9c-3,-10.6 -3.1,-21.9 -0.4,-32.6c-13.7,6.2 -24.4,16.1 -32.1,24.8C139.7,156.3 159,155.9 168.8,162.3L168.8,162.3L168.8,162.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="206.24" - android:centerY="97.57" - android:gradientRadius="95.15" - android:type="radial"> - <item android:offset="0" android:color="#FF64D9FA"/> - <item android:offset="0.23" android:color="#FF61D2F8"/> - <item android:offset="0.57" android:color="#FF58BFF2"/> - <item android:offset="0.79" android:color="#FF50AFED"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M84.2,223.5c10.3,60.8 65.3,107.2 127.9,108.9c57.8,1.7 94.9,-31.9 110.1,-64.7c9.8,-21.2 16.7,-55.8 4.1,-90l0,0v-0.1c0,-0.1 0,-0.2 0,-0.1c0,0 0,0.1 0,0.2c4.7,30.8 -11,60.8 -35.6,80.9l-0.1,0.2c-47.8,38.9 -93.6,23.5 -102.8,17.2c-0.7,-0.3 -1.3,-0.6 -2,-1c-27.9,-13.4 -39.4,-38.7 -36.9,-60.5c-23.6,0 -31.5,-19.8 -31.5,-19.8s21.1,-15 49,-2c25.8,12.2 50,2 50,2c-0.1,-1.1 -23.3,-10.3 -32.3,-19.2c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-0.9 -2.3,-1.8 -3.4,-2.7c-0.9,-0.6 -1.9,-1.3 -2.8,-1.9c-9.7,-6.3 -29.1,-6 -29.7,-6H139c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-0.1,-0.3 -3.9,2 -4.4,2.4c-4.6,3.3 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0c-8.5,12.2 -14.6,25.8 -17.9,40.4C86.5,192 81.8,212.7 84.2,223.5L84.2,223.5L84.2,223.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="281.04" - android:centerY="37.23" - android:gradientRadius="405.97" - android:type="radial"> - <item android:offset="0.13" android:color="#FF74DDB2"/> - <item android:offset="0.43" android:color="#FF64D9FA"/> - <item android:offset="0.48" android:color="#FF5BBDF8"/> - <item android:offset="0.62" android:color="#FF7177F6"/> - <item android:offset="0.69" android:color="#FF875CF5"/> - <item android:offset="0.9" android:color="#FFA93ED8"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M263.1,170.8c4.8,4.8 9,10.2 12.4,16.1c0.7,0.6 1.4,1.1 2,1.7c30.2,27.8 14.3,67.2 13.2,70c24.6,-20.2 40.3,-50.1 35.6,-80.9c-15,-37.5 -40.7,-52.7 -61.5,-85.6c-1.1,-1.7 -2.1,-3.3 -3.1,-5.1c-0.5,-0.9 -1,-1.9 -1.5,-2.8c-0.9,-1.7 -1.6,-3.4 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1C252.3,81.1 221.8,129.5 263.1,170.8L263.1,170.8L263.1,170.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="241.94" - android:centerY="82.8" - android:gradientRadius="297.34" - android:type="radial"> - <item android:offset="0" android:color="#FF88FBC1"/> - <item android:offset="0.1" android:color="#FF80EFBB"/> - <item android:offset="0.2" android:color="#FF74DDB2"/> - <item android:offset="0.26" android:color="#FF6CD4BD"/> - <item android:offset="0.37" android:color="#FF58BCDC"/> - <item android:offset="0.42" android:color="#FF50AFED"/> - <item android:offset="0.74" android:color="#FF285ED6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M277.6,188.6c-0.6,-0.5 -1.3,-1.1 -2,-1.7c-0.3,-0.2 -0.5,-0.4 -0.8,-0.6c-7.1,-5 -19.8,-9.9 -32.1,-7.8c47.9,24 35.1,106.5 -31.3,103.3c-5.9,-0.2 -11.8,-1.4 -17.4,-3.3c-1.3,-0.5 -2.7,-1 -3.9,-1.6c-0.8,-0.3 -1.5,-0.7 -2.3,-1.1c0,0 0.1,0 0.1,0.1c9.2,6.3 55,21.8 102.8,-17.2l0.1,-0.2C291.9,255.9 307.7,216.5 277.6,188.6L277.6,188.6L277.6,188.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="204" - android:centerY="132.81" - android:gradientRadius="253.45" - android:type="radial"> - <item android:offset="0.14" android:color="#FF74DDB2"/> - <item android:offset="0.43" android:color="#FF64D9FA"/> - <item android:offset="0.48" android:color="#FF5BBDF8"/> - <item android:offset="0.62" android:color="#FF7177F6"/> - <item android:offset="0.69" android:color="#FF875CF5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M156.4,232.3c0,0 6.2,-22.9 44,-22.9c4.1,0 15.8,-11.4 16,-14.7c0.2,-3.3 -24.3,10.2 -50,-2c-27.9,-13.1 -49,2 -49,2s8.1,19.8 31.5,19.8c-2.5,21.8 9,47.1 36.9,60.5c0.6,0.3 1.2,0.6 1.9,0.9C171.5,267.6 158,251.7 156.4,232.3L156.4,232.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="270.9" - android:centerY="147.64" - android:gradientRadius="277.4" - android:type="radial"> - <item android:offset="0.09" android:color="#FF88FBC1"/> - <item android:offset="0.24" android:color="#FF7EF3CD"/> - <item android:offset="0.54" android:color="#FF69DFEF"/> - <item android:offset="0.63" android:color="#FF64D9FA"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.5,170.7c-5.8,-13.9 -17.5,-29 -26.7,-33.7c7.5,14.7 11.8,29.5 13.5,40.5c0,0 0,0.1 0,0.2c-15,-37.5 -40.7,-52.7 -61.5,-85.6c-1.1,-1.7 -2.1,-3.3 -3.1,-5.1c-0.5,-0.9 -1,-1.9 -1.5,-2.8c-0.9,-1.7 -1.6,-3.4 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1c0,0 0,-0.1 0.1,-0.1c-33.5,19.6 -44.8,55.9 -45.9,74.1c1.6,-0.1 3.1,-0.2 4.7,-0.2c24.9,0 46.7,13.8 58.3,34.1c-7.1,-5 -19.8,-9.9 -32.1,-7.8c47.9,24 35.1,106.5 -31.3,103.3c-5.9,-0.2 -11.8,-1.4 -17.4,-3.3c-1.3,-0.5 -2.7,-1 -3.9,-1.6c-0.8,-0.3 -1.5,-0.7 -2.3,-1.1c0,0 0.1,0 0.1,0.1c-0.7,-0.3 -1.3,-0.6 -2,-1c0.6,0.3 1.2,0.6 1.9,0.9c-16.3,-8.4 -29.7,-24.3 -31.4,-43.6c0,0 6.2,-22.9 44,-22.9c4.1,0 15.8,-11.4 16,-14.7c-0.1,-1.1 -23.3,-10.3 -32.3,-19.2c-4.8,-4.7 -7.2,-7.1 -9.1,-8.7c-1.1,-0.9 -2.3,-1.8 -3.4,-2.7c-3,-10.6 -3.1,-21.9 -0.4,-32.6c-13.7,6.2 -24.4,16.1 -32.1,24.8h-0.1c-5.3,-6.7 -4.9,-28.8 -4.6,-33.4c-0.1,-0.3 -3.9,2 -4.4,2.4c-4.6,3.3 -9,7.1 -13.1,11.2c-4.5,4.6 -8.7,9.6 -12.5,14.9l0,0l0,0c-8.5,12.2 -14.6,25.8 -17.9,40.4c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.4,7.2 -1.6,8.4c0,0.1 0,-0.1 0,0c-1,6.2 -1.7,12.4 -2,18.6c0,0.2 0,0.5 0,0.7c0,73.6 59.6,133.2 133.3,133.2c65.9,0 120.6,-47.8 131.3,-110.7c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.8 347.8,190.9 339.5,170.7L339.5,170.7zM326.3,177.6L326.3,177.6L326.3,177.6L326.3,177.6z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="318.99" - android:startY="119.77" - android:endX="130.79" - android:endY="307.97" - android:type="linear"> - <item android:offset="0.17" android:color="#CC88FBC1"/> - <item android:offset="0.24" android:color="#A27FF4CB"/> - <item android:offset="0.36" android:color="#5D72E9DF"/> - <item android:offset="0.47" android:color="#2B6AE0ED"/> - <item android:offset="0.55" android:color="#0B66DBF6"/> - <item android:offset="0.59" android:color="#0064D9FA"/> - </gradient> - </aapt:attr> - </path> - </group> - </vector> - </aapt:attr> - <target - android:name="a1_t"> - <aapt:attr - name="android:animation"> - <set> - <objectAnimator - android:propertyName="scaleX" - android:duration="300" - android:valueFrom="0.75" - android:valueTo="0.75" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleX" - android:duration="700" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="300" - android:valueFrom="0.75002400000000002" - android:valueTo="0.75002400000000002" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleY" - android:duration="700" - android:valueFrom="0.75002400000000002" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - </set> - </aapt:attr> - </target> -</animated-vector> diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_background.xml b/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..a086a9aae981d8d6cd1f13660b734b14c4f06293 --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_background.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="432" + android:viewportHeight="432"> + <path + android:pathData="M0,0h432v432h-432z" + android:fillColor="#E4E0FA"/> +</vector> diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_foreground.xml b/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 77e00350e7d9adaf7367dc30b6332df2733e0999..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,205 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportWidth="108" - android:viewportHeight="108"> - <path - android:pathData="M78.127,44.283c-1.132,-2.722 -3.423,-5.661 -5.223,-6.59 1.465,2.872 2.312,5.753 2.636,7.903l0.005,0.043C72.601,38.3 67.61,35.341 63.533,28.898c-0.206,-0.326 -0.412,-0.652 -0.613,-0.997a8.28,8.28 0,0 1,-0.287 -0.539c-0.312,-0.641 -0.388,-1.03 -0.388,-1.03 -0.005,-0.047 -0.028,-0.065 -0.059,-0.07 -0.015,-0.002 -0.029,-0.007 -0.049,0 -0.004,0.001 -0.009,0.006 -0.013,0.007 -0.006,0.002 -0.013,0.007 -0.019,0.01l0.011,-0.015c-6.54,3.831 -8.759,10.917 -8.963,14.463a13.024,13.024 0,0 0,-7.165 2.762,7.8 7.8,0 0,0 -0.674,-0.509c-0.999,-3.375 -0.073,-6.364 -0.073,-6.364 -2.674,1.218 -4.755,3.143 -6.267,4.843h-0.012c-1.032,-1.307 -0.959,-5.62 -0.9,-6.521 -0.012,-0.056 -0.77,0.393 -0.869,0.461a18.998,18.998 0,0 0,-2.544 2.18,22.815 22.815,0 0,0 -2.431,2.916l-0.001,0.004 0.001,-0.004a21.964,21.964 0,0 0,-3.493 7.888l-0.035,0.172a42.912,42.912 0,0 0,-0.256 1.626l-0.006,0.057a24.867,24.867 0,0 0,-0.422 3.593c0,0.044 -0.003,0.088 -0.003,0.133C28,68.344 39.656,80 54.035,80c12.877,0 23.569,-9.349 25.662,-21.63 0.044,-0.333 0.079,-0.668 0.118,-1.004 0.518,-4.465 -0.057,-9.158 -1.688,-13.083zM48.119,64.663c0.122,0.058 0.236,0.122 0.361,0.178a19.081,19.081 0,0 1,-0.361 -0.178zM54.083,48.96zM75.548,45.645a1.772,1.772 0,0 0,-0.003 -0.025l0.004,0.028 -0.001,-0.003z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="40.059" - android:startX="77.379" - android:endY="68.436" - android:endX="32.331" - android:type="linear"> - <item android:offset="0" android:color="#FF3FE1B0"/> - <item android:offset="0.406" android:color="#FF00B3F4"/> - <item android:offset="0.42" android:color="#FF03B0F4"/> - <item android:offset="0.818" android:color="#FF5561E9"/> - <item android:offset="1" android:color="#FF7542E5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.127,44.283c-1.132,-2.722 -3.423,-5.661 -5.223,-6.59 1.465,2.872 2.312,5.753 2.636,7.903a0.47,0.47 0,0 0,0.004 0.024l0.004,0.028c2.456,6.66 1.118,13.433 -0.81,17.572 -2.983,6.403 -10.207,12.966 -21.512,12.646C41.01,75.52 30.25,66.455 28.241,54.582c-0.366,-1.872 0,-2.823 0.184,-4.343 -0.224,1.172 -0.31,1.51 -0.422,3.593 0,0.044 -0.003,0.088 -0.003,0.133C28,68.344 39.656,80 54.035,80c12.877,0 23.569,-9.349 25.662,-21.63 0.044,-0.333 0.079,-0.668 0.118,-1.004 0.518,-4.465 -0.057,-9.158 -1.688,-13.083z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="54.279427" - android:centerX="72.3032" - android:centerY="31.889864" - android:type="radial"> - <item android:offset="0.108" android:color="#FF3FE1B0"/> - <item android:offset="0.122" android:color="#FF3BDCB3"/> - <item android:offset="0.254" android:color="#FF1BB3D3"/> - <item android:offset="0.358" android:color="#FF0799E6"/> - <item android:offset="0.42" android:color="#FF0090ED"/> - <item android:offset="0.487" android:color="#FF2482F1"/> - <item android:offset="0.639" android:color="#FF7165FB"/> - <item android:offset="0.71" android:color="#FF9059FF"/> - <item android:offset="0.795" android:color="#FF7D49ED"/> - <item android:offset="0.86" android:color="#FF7542E5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.127,44.283c-1.132,-2.722 -3.423,-5.661 -5.223,-6.59 1.465,2.872 2.312,5.753 2.636,7.903a0.47,0.47 0,0 0,0.004 0.024l0.004,0.028c2.456,6.66 1.118,13.433 -0.81,17.572 -2.983,6.403 -10.207,12.966 -21.512,12.646C41.01,75.52 30.25,66.455 28.241,54.582c-0.366,-1.872 0,-2.823 0.184,-4.343 -0.224,1.172 -0.31,1.51 -0.422,3.593 0,0.044 -0.003,0.088 -0.003,0.133C28,68.344 39.656,80 54.035,80c12.877,0 23.569,-9.349 25.662,-21.63 0.044,-0.333 0.079,-0.668 0.118,-1.004 0.518,-4.465 -0.057,-9.158 -1.688,-13.083z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="54.279427" - android:centerX="52.468304" - android:centerY="54.08076" - android:type="radial"> - <item android:offset="0.3" android:color="#FF45278D"/> - <item android:offset="0.371" android:color="#B062289D"/> - <item android:offset="0.475" android:color="#3C872AB1"/> - <item android:offset="0.53" android:color="#00952BB9"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M65.475,47.343c0.057,0.04 0.109,0.08 0.162,0.119 -0.604,-1.09 -1.396,-2.133 -2.417,-3.154 -8.093,-8.093 -2.122,-17.548 -1.115,-18.029l0.011,-0.015c-6.54,3.831 -8.759,10.917 -8.963,14.463 0.303,-0.021 0.606,-0.047 0.914,-0.047 4.881,0.001 9.132,2.685 11.408,6.663z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="39.323143" - android:centerX="59.01298" - android:centerY="19.571066" - android:type="radial"> - <item android:offset="0.132" android:color="#FF3FE1B0"/> - <item android:offset="0.289" android:color="#FF28D0C8"/> - <item android:offset="0.526" android:color="#FF00B3F4"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.084,48.959c-0.043,0.648 -2.331,2.881 -3.131,2.881 -7.403,0 -8.605,4.479 -8.605,4.479 0.328,3.772 2.953,6.877 6.133,8.521a9.771,9.771 0,0 0,0.439 0.21,13.672 13.672,0 0,0 0.765,0.313 11.574,11.574 0,0 0,3.388 0.653c12.976,0.609 15.49,-15.515 6.126,-20.197 2.398,-0.417 4.887,0.547 6.278,1.524 -2.276,-3.978 -6.527,-6.662 -11.408,-6.662 -0.309,0 -0.611,0.025 -0.914,0.047a13.024,13.024 0,0 0,-7.165 2.762c0.397,0.336 0.845,0.785 1.789,1.715 1.764,1.74 6.295,3.543 6.305,3.754z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="25.844818" - android:centerX="46.46577" - android:centerY="68.25843" - android:type="radial"> - <item android:offset="0.287" android:color="#FF0060DF"/> - <item android:offset="0.417" android:color="#FF2357E1"/> - <item android:offset="0.604" android:color="#FF4F4CE3"/> - <item android:offset="0.748" android:color="#FF6B45E4"/> - <item android:offset="0.833" android:color="#FF7542E5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.084,48.959c-0.043,0.648 -2.331,2.881 -3.131,2.881 -7.403,0 -8.605,4.479 -8.605,4.479 0.328,3.772 2.953,6.877 6.133,8.521a9.771,9.771 0,0 0,0.439 0.21,13.672 13.672,0 0,0 0.765,0.313 11.574,11.574 0,0 0,3.388 0.653c12.976,0.609 15.49,-15.515 6.126,-20.197 2.398,-0.417 4.887,0.547 6.278,1.524 -2.276,-3.978 -6.527,-6.662 -11.408,-6.662 -0.309,0 -0.611,0.025 -0.914,0.047a13.024,13.024 0,0 0,-7.165 2.762c0.397,0.336 0.845,0.785 1.789,1.715 1.764,1.74 6.295,3.543 6.305,3.754z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="13.701598" - android:centerX="54.040077" - android:centerY="48.28016" - android:type="radial"> - <item android:offset="0.206" android:color="#0045278D"/> - <item android:offset="0.543" android:color="#5B3C2279"/> - <item android:offset="0.956" android:color="#CC321C64"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M44.773,42.623a33.157,33.157 0,0 1,0.54 0.357c-0.999,-3.375 -0.073,-6.364 -0.073,-6.364 -2.674,1.218 -4.755,3.143 -6.267,4.843 0.125,-0.002 3.901,-0.07 5.8,1.164z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="18.592737" - android:centerX="51.78374" - android:centerY="29.668892" - android:type="radial"> - <item android:offset="0" android:color="#FF00DDFF"/> - <item android:offset="0.235" android:color="#FF00D6FD"/> - <item android:offset="0.572" android:color="#FF00C3F8"/> - <item android:offset="0.792" android:color="#FF00B3F4"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M28.241,54.582C30.25,66.455 41.01,75.52 53.226,75.866c11.306,0.32 18.529,-6.243 21.512,-12.646 1.928,-4.139 3.267,-10.911 0.81,-17.572l-0.001,-0.003a1.772,1.772 0,0 0,-0.003 -0.025c-0.003,-0.019 -0.004,-0.031 -0.004,-0.024l0.005,0.043c0.923,6.031 -2.144,11.873 -6.939,15.824l-0.014,0.034c-9.343,7.609 -18.284,4.591 -20.094,3.355a16.703,16.703 0,0 1,-0.379 -0.189c-5.447,-2.604 -7.698,-7.567 -7.215,-11.824 -4.599,0 -6.168,-3.88 -6.168,-3.88s4.13,-2.945 9.572,-0.384c5.041,2.372 9.775,0.384 9.775,0.384 -0.01,-0.212 -4.541,-2.014 -6.308,-3.755 -0.944,-0.93 -1.392,-1.379 -1.789,-1.715a7.8,7.8 0,0 0,-0.674 -0.509,27.654 27.654,0 0,0 -0.54,-0.357c-1.899,-1.234 -5.675,-1.166 -5.8,-1.163H38.96c-1.032,-1.307 -0.959,-5.62 -0.9,-6.521 -0.012,-0.056 -0.77,0.393 -0.869,0.461a18.998,18.998 0,0 0,-2.544 2.18,22.815 22.815,0 0,0 -2.431,2.916L32.215,40.5l0.001,-0.004a21.964,21.964 0,0 0,-3.493 7.888c-0.014,0.057 -0.938,4.101 -0.482,6.198z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="79.32682" - android:centerX="66.39808" - android:centerY="17.875443" - android:type="radial"> - <item android:offset="0.126" android:color="#FF3FE1B0"/> - <item android:offset="0.429" android:color="#FF00DDFF"/> - <item android:offset="0.479" android:color="#FF1EC1FF"/> - <item android:offset="0.624" android:color="#FF7077FF"/> - <item android:offset="0.69" android:color="#FF9059FF"/> - <item android:offset="0.904" android:color="#FFB833E1"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M63.22,44.308c1.021,1.021 1.813,2.064 2.417,3.154a5.3,5.3 0,0 1,0.391 0.32c5.902,5.439 2.81,13.132 2.579,13.68 4.795,-3.95 7.862,-9.793 6.939,-15.824 -2.945,-7.338 -7.936,-10.297 -12.013,-16.74 -0.206,-0.326 -0.412,-0.652 -0.613,-0.997a8.28,8.28 0,0 1,-0.287 -0.539c-0.312,-0.641 -0.388,-1.03 -0.388,-1.03 -0.005,-0.047 -0.028,-0.065 -0.059,-0.07 -0.015,-0.002 -0.029,-0.007 -0.049,0 -0.004,0.001 -0.009,0.006 -0.013,0.007 -0.006,0.002 -0.013,0.007 -0.019,0.01 -1.007,0.481 -6.978,9.936 1.115,18.029z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="58.109028" - android:centerX="59.84026" - android:centerY="27.248028" - android:type="radial"> - <item android:offset="0" android:color="#FF54FFBD"/> - <item android:offset="0.095" android:color="#FF4CF3B8"/> - <item android:offset="0.197" android:color="#FF3FE1B0"/> - <item android:offset="0.257" android:color="#FF33D8BD"/> - <item android:offset="0.369" android:color="#FF12C0E1"/> - <item android:offset="0.423" android:color="#FF00B3F4"/> - <item android:offset="0.737" android:color="#FF0060DF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M66.027,47.782a5.3,5.3 0,0 0,-0.391 -0.32c-0.053,-0.04 -0.105,-0.08 -0.162,-0.119 -1.39,-0.977 -3.879,-1.941 -6.278,-1.524 9.364,4.682 6.85,20.806 -6.126,20.197a11.58,11.58 0,0 1,-3.388 -0.653,13.672 13.672,0 0,1 -0.765,-0.313 9.771,9.771 0,0 1,-0.421 -0.199c1.81,1.235 10.751,4.253 20.094,-3.355l0.014,-0.034c0.233,-0.547 3.326,-8.24 -2.577,-13.68z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="49.524426" - android:centerX="51.345055" - android:centerY="36.554844" - android:type="radial"> - <item android:offset="0.137" android:color="#FF3FE1B0"/> - <item android:offset="0.435" android:color="#FF00DDFF"/> - <item android:offset="0.484" android:color="#FF1EC1FF"/> - <item android:offset="0.622" android:color="#FF7077FF"/> - <item android:offset="0.685" android:color="#FF9059FF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M42.348,56.32s1.202,-4.479 8.605,-4.479c0.8,0 3.088,-2.234 3.131,-2.881 -0.001,0 -4.735,1.988 -9.775,-0.384 -5.443,-2.561 -9.572,0.384 -9.572,0.384s1.568,3.88 6.168,3.88c-0.482,4.257 1.768,9.22 7.215,11.824 0.122,0.058 0.236,0.122 0.361,0.178 -3.18,-1.645 -5.805,-4.751 -6.133,-8.522z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="54.204857" - android:centerX="64.41828" - android:centerY="39.45366" - android:type="radial"> - <item android:offset="0.093" android:color="#FF54FFBD"/> - <item android:offset="0.242" android:color="#FF41F7CC"/> - <item android:offset="0.543" android:color="#FF0FE3F3"/> - <item android:offset="0.625" android:color="#FF00DDFF"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.127,44.283c-1.132,-2.722 -3.423,-5.661 -5.223,-6.59 1.465,2.872 2.312,5.753 2.636,7.903l0.005,0.043C72.601,38.3 67.61,35.341 63.533,28.898c-0.206,-0.326 -0.412,-0.652 -0.613,-0.997a8.28,8.28 0,0 1,-0.287 -0.539c-0.312,-0.641 -0.388,-1.03 -0.388,-1.03 -0.005,-0.047 -0.028,-0.065 -0.059,-0.07 -0.015,-0.002 -0.029,-0.007 -0.049,0 -0.004,0.001 -0.009,0.006 -0.013,0.007 -0.006,0.002 -0.013,0.007 -0.019,0.01l0.011,-0.015c-6.54,3.831 -8.759,10.917 -8.963,14.463 0.303,-0.021 0.606,-0.047 0.914,-0.047 4.881,0 9.132,2.684 11.408,6.662 -1.39,-0.977 -3.879,-1.941 -6.278,-1.524 9.364,4.682 6.85,20.806 -6.126,20.197a11.58,11.58 0,0 1,-3.388 -0.653,13.672 13.672,0 0,1 -0.765,-0.313 9.771,9.771 0,0 1,-0.421 -0.199,16.703 16.703,0 0,1 -0.379,-0.189c0.122,0.058 0.236,0.122 0.361,0.178 -3.18,-1.643 -5.805,-4.749 -6.133,-8.521 0,0 1.202,-4.479 8.605,-4.479 0.8,0 3.088,-2.234 3.131,-2.881 -0.01,-0.212 -4.541,-2.014 -6.308,-3.755 -0.944,-0.93 -1.392,-1.379 -1.789,-1.715a7.8,7.8 0,0 0,-0.674 -0.509c-0.999,-3.375 -0.073,-6.364 -0.073,-6.364 -2.674,1.218 -4.755,3.143 -6.267,4.843h-0.012c-1.032,-1.307 -0.959,-5.62 -0.9,-6.521 -0.012,-0.056 -0.77,0.393 -0.869,0.461a18.998,18.998 0,0 0,-2.544 2.18,22.815 22.815,0 0,0 -2.431,2.916l-0.001,0.004 0.001,-0.004a21.964,21.964 0,0 0,-3.493 7.888l-0.035,0.172a43.6,43.6 0,0 0,-0.3 1.642c-0.002,0.019 0.002,-0.019 0,0a30.31,30.31 0,0 0,-0.384 3.633c0,0.044 -0.003,0.088 -0.003,0.133C28,68.344 39.656,80 54.035,80c12.877,0 23.569,-9.349 25.662,-21.63 0.044,-0.333 0.079,-0.668 0.118,-1.004 0.518,-4.465 -0.057,-9.158 -1.688,-13.083zM75.544,45.62l0.004,0.028 -0.001,-0.003a1.772,1.772 0,0 0,-0.003 -0.025z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="34.361" - android:startX="74.161" - android:endY="71.137" - android:endX="37.385" - android:type="linear"> - <item android:offset="0.167" android:color="#CC54FFBD"/> - <item android:offset="0.341" android:color="#772BEEDD"/> - <item android:offset="0.5" android:color="#2A0CE2F6"/> - <item android:offset="0.589" android:color="#0000DDFF"/> - </gradient> - </aapt:attr> - </path> -</vector> diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_monochrome_foreground.xml b/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_monochrome_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..2fd30875c394713bb0ae5042048e2b47b38eeb3e --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/drawable/ic_launcher_monochrome_foreground.xml @@ -0,0 +1,15 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="256" + android:viewportHeight="257"> + <group android:scaleX="0.4869866" + android:scaleY="0.4888889" + android:translateX="65.66572" + android:translateY="65.67778"> + <path + android:pathData="M128,256.91C198.69,256.91 256,199.6 256,128.91C256,58.22 198.69,0.91 128,0.91C57.31,0.91 0,58.22 0,128.91C0,199.6 57.31,256.91 128,256.91ZM233,128.91C233,70.92 185.99,23.91 128,23.91V39.91C177.15,39.91 217,79.75 217,128.91C217,178.06 177.15,217.91 128,217.91V233.91C185.99,233.91 233,186.9 233,128.91ZM193.75,128.91C193.75,92.6 164.31,63.16 128,63.16V79.16C155.48,79.16 177.75,101.43 177.75,128.91C177.75,156.38 155.48,178.66 128,178.66V194.66C164.31,194.66 193.75,165.22 193.75,128.91ZM128,101.66C143.05,101.66 155.25,113.86 155.25,128.91C155.25,143.96 143.05,156.16 128,156.16V101.66ZM94.04,61.23C94.36,61.18 94.46,60.77 94.2,60.59C89.25,57.25 83.29,55.31 76.87,55.31C59.75,55.31 45.87,69.16 45.87,86.24C45.87,103.33 59.75,117.18 76.87,117.18C84.6,117.18 91.66,114.35 97.09,109.69C97.34,109.48 97.19,109.08 96.86,109.07C83.98,108.56 73.7,97.99 73.7,85.01C73.7,73 82.52,63.04 94.04,61.23Z" + android:fillColor="#4A454E" + android:fillType="evenOdd"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_logo.webp b/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_logo.webp deleted file mode 100644 index db68f6be4e16fad63ba6ed28388bda0cd6ee05b2..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_logo.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_normal.webp b/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_normal.webp deleted file mode 100644 index 7717adf97c422f8f0e1e0013c4f1e97dbad39efb..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_private.webp b/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_private.webp deleted file mode 100644 index 6fc1357934063463d618cd65eab98820c5e81328..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/drawable/ic_wordmark_text_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/ic_launcher-web.webp b/mobile/android/fenix/app/src/nightly/res/ic_launcher-web.webp deleted file mode 100644 index f209d1315406ae438bb3586ed55b6f4d414d8281..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/nightly/res/ic_launcher-web.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..803115f3476cf8ea75ee5057a6ddd79803549902 --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_launcher_monochrome_foreground" /> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..d372a4fca9b35d26af58c251afcad94bd67642ec --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher.webp index cb42df4063bbd08afe6adf1b5af6dace12f27964..a4f3299482510d7b93acd133250805f5e313d696 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..62e616d691cd7c42bd9d445150a641d611993e49 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..fd1b625ddbe3bf02ba0bd6c5ef2e19b2a212d684 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..5e0f9baee22fd0abf37e0596d9e9929da6b04c90 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_round.webp index 474752e84b01e321d3729dfc34bab0a77e1354b0..5816b4af9c3fd7a189b3889a67fadd9b63960557 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher.webp index e064ff08c2472ba80c4fc47f559b4141c1db7bbd..6010a370d4b412e48cb61f4b9c30daa204d24b51 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..cdd6b6b4135bb7a4f923a4e80199790f43380b81 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..c83a8331dafa72ebf62d59a75aaf044bbe22e29c Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..a9a47e0917446500b0eaa4de550f4f0930cc817b Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_round.webp index 4cc872ca8b51100dff568f526e133bc167e4fbb5..8fda9983408a16534dfceec97047152c418fdc55 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher.webp index 21e418971986d66331f55bf5fc48917fc3ceef25..7d4e5ec20bcca1914b52e3f603d741672714ea27 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..5c651b124d4a6961b95c65d08476c100d4efc4bc Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..fa54c04df3f248ffe57d26c45f8e9fd43b779b16 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..046b668cf0f59ddd2c2d9bbf5a01fbfcc18c157b Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_round.webp index c09e596ae5bf7e810e04f4092fa7225581bc1f24..00e899c1dc1faaba0a14497d5422ed195b27f8e0 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.webp index 6f68c99b5a3f4a0e757912c8359a5bc6b59dfff7..0972805292da5a1d0e4adbc5cb1eff365644a0eb 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..8d3ca2a9772bcd6edb7b1ee12d1c3a4820f66d3f Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..2dec8754336d9ba05a144d7ab95cbf6b33261034 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..8e88ea6e0c7054de5ee7fdf2ff236ff6dfa617dc Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_round.webp index 2acdbd2501b7ffa13ad5193742e6ce46f6d51d75..a2f24571b32be1bc99a941df479ef3b241f8d725 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.webp index 4f9e310f69803ec268dcc7521a93d769c8570a0f..33b2429e648fc4dff82457e2d44f61bac9019af5 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..88b75110b69f6ef1da2e53ced92d3733d1cedd1c Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..e1a6f6d64b746289901c85e8ee0c5d7ee71a03bc Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1e025904e78eb4bdde9844db442d699250a9c064 Binary files /dev/null and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_round.webp index 2e67bd49b80638e1485eb71e6fdc2c33ada65ed4..5efbcb1d62bafacbf7353ce1ad874c8fddf4da15 100644 Binary files a/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/nightly/res/values/ic_launcher_monochrome_background.xml b/mobile/android/fenix/app/src/nightly/res/values/ic_launcher_monochrome_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..70a105458b46dbc72a2bce80b62fa57c36cdbcf1 --- /dev/null +++ b/mobile/android/fenix/app/src/nightly/res/values/ic_launcher_monochrome_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_monochrome_background">#FEFBFF</color> +</resources> diff --git a/mobile/android/fenix/app/src/nightly/res/values/static_strings.xml b/mobile/android/fenix/app/src/nightly/res/values/static_strings.xml index 9e477567e5c7804a32308005afef333f8df93b4b..24b17cb16deef959d3708613983314c3ef15836b 100644 --- a/mobile/android/fenix/app/src/nightly/res/values/static_strings.xml +++ b/mobile/android/fenix/app/src/nightly/res/values/static_strings.xml @@ -4,5 +4,5 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <!-- Name of the application --> - <string name="app_name" translatable="false">Firefox Nightly</string> + <string name="app_name" translatable="false">Tor Browser Nightly</string> </resources> diff --git a/mobile/android/fenix/app/src/nightly/res/xml/shortcuts.xml b/mobile/android/fenix/app/src/nightly/res/xml/shortcuts.xml index fb28b5782b451a3c5e570730d626e6b37c36f178..d8643db576964ef42a81fbf9a4d9f785b06f606d 100644 --- a/mobile/android/fenix/app/src/nightly/res/xml/shortcuts.xml +++ b/mobile/android/fenix/app/src/nightly/res/xml/shortcuts.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- <shortcut android:shortcutId="password_manager" android:enabled="true" @@ -21,7 +22,7 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_TAB" - android:targetPackage="org.mozilla.fenix" + android:targetPackage="org.torproject.torbrowser_nightly" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> <shortcut @@ -31,7 +32,8 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_private_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_PRIVATE_TAB" - android:targetPackage="org.mozilla.fenix" + android:targetPackage="org.torproject.torbrowser_nightly" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> + --> </shortcuts> diff --git a/mobile/android/fenix/app/src/release/ic_launcher-playstore.png b/mobile/android/fenix/app/src/release/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..84a3cbafea1840813013c5b7a6a8e3473b4f1ec5 Binary files /dev/null and b/mobile/android/fenix/app/src/release/ic_launcher-playstore.png differ diff --git a/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.png b/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..721fe17e0cfd43f895b445dab6c7b22240c8fdd9 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.png differ diff --git a/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.webp b/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.webp deleted file mode 100644 index 1b60df35d30854b75b86cec087ad5c3b450c055f..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/release/res/drawable-hdpi/fenix_search_widget.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_normal.webp b/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_normal.webp deleted file mode 100644 index 34ec5df3f8597152210f9eb6ccb3560ab6bd6b41..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_normal.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_private.webp b/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_private.webp deleted file mode 100644 index 22c7f96f173b5a5a6e0171530a6d77af2f536a39..0000000000000000000000000000000000000000 Binary files a/mobile/android/fenix/app/src/release/res/drawable-hdpi/ic_logo_wordmark_private.webp and /dev/null differ diff --git a/mobile/android/fenix/app/src/release/res/drawable/animated_splash_screen.xml b/mobile/android/fenix/app/src/release/res/drawable/animated_splash_screen.xml deleted file mode 100644 index 49ff2d4abb967fb7c71467109ba8c2fb2ad7000f..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/release/res/drawable/animated_splash_screen.xml +++ /dev/null @@ -1,527 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" > - <aapt:attr name="android:drawable"> - <vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="432dp" - android:height="432dp" - android:viewportWidth="432" - android:viewportHeight="432"> - <group - android:name="a1_t" - android:pivotX="216" - android:pivotY="216"> - <path - android:pathData="M339.4,170.8c-5.8,-13.9 -17.5,-28.9 -26.7,-33.6c7.5,14.7 11.9,29.4 13.5,40.4c0,0 0,0.1 0,0.2c-15,-37.5 -40.6,-52.6 -61.4,-85.6c-1.1,-1.6 -2.1,-3.4 -3.2,-5.1c-0.5,-0.9 -1.1,-1.8 -1.4,-2.8c-0.9,-1.6 -1.5,-3.5 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1c0,0 0,-0.1 0.1,-0.1c-33.4,19.6 -44.8,55.8 -45.8,73.9c-13.4,1 -26.1,5.9 -36.6,14.1c-1.1,-1 -2.2,-1.8 -3.5,-2.6c-3,-10.6 -3.2,-21.9 -0.4,-32.5c-13.7,6.3 -24.3,16.1 -32,24.8h-0.1c-5.3,-6.7 -4.9,-28.7 -4.6,-33.4c-0.1,-0.3 -4,2 -4.4,2.3c-4.6,3.3 -9,7 -13,11.2c-4.5,4.6 -8.7,9.6 -12.4,14.9l0,0l0,0c-8.6,12.1 -14.7,25.8 -17.8,40.3c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.2,7 -1.3,8.3c0,0.1 0,0.2 0,0.3c-1.2,6.1 -1.9,12.2 -2.1,18.4c0,0.2 0,0.5 0,0.7c0,73.5 59.6,133.1 133.1,133.1c65.8,0 120.5,-47.8 131.2,-110.6c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.9 347.7,190.9 339.4,170.8zM186,275c0.6,0.3 1.3,0.6 1.8,0.9c0,0 0.1,0 0.1,0.1C187.2,275.6 186.6,275.3 186,275zM326.2,177.8L326.2,177.8L326.2,177.8L326.2,177.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="314.95" - android:startY="121.03" - android:endX="107.97" - android:endY="334.26" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.4,170.8c-5.8,-13.9 -17.5,-28.9 -26.7,-33.6c7.5,14.7 11.9,29.4 13.5,40.4c0,0 0,0 0,0.1v0.1c12.5,34 5.7,68.6 -4.1,89.8c-15.2,32.8 -52.1,66.3 -110,64.7c-62.5,-1.8 -117.5,-48.1 -127.7,-108.8c-1.8,-9.5 0,-14.5 1,-22.2c-1.2,6 -1.5,7.7 -2.1,18.4c0,0.2 0,0.5 0,0.7c0,73.5 59.6,133.1 133.1,133.1c65.8,0 120.5,-47.8 131.2,-110.6c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.9 347.7,190.9 339.4,170.8L339.4,170.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="316.26" - android:centerY="137.18" - android:gradientRadius="272.22" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.4,170.8c-5.8,-13.9 -17.5,-28.9 -26.7,-33.6c7.5,14.7 11.9,29.4 13.5,40.4c0,0 0,0 0,0.1v0.1c12.5,34 5.7,68.6 -4.1,89.8c-15.2,32.8 -52.1,66.3 -110,64.7c-62.5,-1.8 -117.5,-48.1 -127.7,-108.8c-1.8,-9.5 0,-14.5 1,-22.2c-1.2,6 -1.5,7.7 -2.1,18.4c0,0.2 0,0.5 0,0.7c0,73.5 59.6,133.1 133.1,133.1c65.8,0 120.5,-47.8 131.2,-110.6c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.9 347.7,190.9 339.4,170.8L339.4,170.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="213.32" - android:centerY="223.67" - android:gradientRadius="279.03" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#56DB293D"/> - <item android:offset="0.5" android:color="#16F5334B"/> - <item android:offset="0.53" android:color="#00FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M274.7,186.5c0.3,0.2 0.6,0.4 0.9,0.6c-3.4,-6 -7.5,-11.4 -12.3,-16.1c-41.4,-41.4 -10.9,-89.7 -5.7,-92.1c0,0 0,-0.1 0.1,-0.1c-33.4,19.6 -44.8,55.8 -45.8,73.9c1.5,-0.1 3.1,-0.2 4.7,-0.2C241.3,152.4 263.1,166.1 274.7,186.5L274.7,186.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="242.3" - android:centerY="65.88" - android:gradientRadius="89.35" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c-0.2,3.3 -12,14.7 -16,14.7c-37.9,0 -44,22.9 -44,22.9c1.6,19.3 15.1,35.2 31.3,43.6c0.8,0.4 1.4,0.8 2.2,1.1c1.3,0.6 2.6,1.1 4,1.6c5.6,1.9 11.4,3.1 17.4,3.4c66.3,3.1 79.2,-79.3 31.3,-103.2c12.2,-2.1 25,2.8 32.1,7.8c-11.7,-20.3 -33.4,-34 -58.3,-34c-1.5,0 -3.1,0.1 -4.7,0.2c-13.4,1 -26.1,5.9 -36.6,14.1c2,1.7 4.3,4 9.2,8.8C193.3,184.4 216.4,193.7 216.4,194.7L216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="183.35" - android:centerY="295.2" - android:gradientRadius="118.24" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M216.4,194.7c-0.2,3.3 -12,14.7 -16,14.7c-37.9,0 -44,22.9 -44,22.9c1.6,19.3 15.1,35.2 31.3,43.6c0.8,0.4 1.4,0.8 2.2,1.1c1.3,0.6 2.6,1.1 4,1.6c5.6,1.9 11.4,3.1 17.4,3.4c66.3,3.1 79.2,-79.3 31.3,-103.2c12.2,-2.1 25,2.8 32.1,7.8c-11.7,-20.3 -33.4,-34 -58.3,-34c-1.5,0 -3.1,0.1 -4.7,0.2c-13.4,1 -26.1,5.9 -36.6,14.1c2,1.7 4.3,4 9.2,8.8C193.3,184.4 216.4,193.7 216.4,194.7L216.4,194.7L216.4,194.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="211.82" - android:centerY="195.24" - android:gradientRadius="62.78" - android:type="radial"> - <item android:offset="0.21" android:color="#009059FF"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M168.9,162.4c1,0.6 1.8,1.3 2.8,1.8c-3,-10.6 -3.2,-21.9 -0.4,-32.5c-13.7,6.3 -24.3,16.1 -32,24.8C139.9,156.4 159.2,156 168.9,162.4L168.9,162.4L168.9,162.4z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="207.25" - android:centerY="99.16" - android:gradientRadius="94" - android:type="radial"> - <item android:offset="0.1" android:color="#FFFFE226"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M84.4,223.5c10.3,60.7 65.3,107 127.7,108.8c57.8,1.6 94.8,-31.9 110,-64.7c9.8,-21.1 16.7,-55.8 4.1,-89.8l0,0v-0.1c0,-0.1 0,-0.2 0,-0.1c0,0 0,0.1 0,0.2c4.7,30.8 -11,60.7 -35.5,80.9l-0.1,0.2c-47.8,38.9 -93.5,23.4 -102.8,17.2c-0.7,-0.3 -1.3,-0.7 -1.9,-1c-27.9,-13.3 -39.3,-38.7 -36.9,-60.4c-23.5,0 -31.5,-19.9 -31.5,-19.9s21.1,-15 49,-1.9c25.7,12.1 49.9,1.9 49.9,1.9c-0.1,-1.1 -23.2,-10.3 -32.3,-19.2c-4.8,-4.7 -7.1,-7 -9.2,-8.8c-1.1,-1 -2.2,-1.8 -3.5,-2.6c-0.9,-0.6 -1.8,-1.3 -2.8,-1.8c-9.7,-6.3 -29,-6 -29.7,-6h-0.1c-5.3,-6.7 -4.9,-28.7 -4.6,-33.4c-0.1,-0.3 -4,2 -4.4,2.3c-4.6,3.3 -9,7 -13,11.2c-4.5,4.6 -8.7,9.6 -12.4,14.9l0,0l0,0c-8.6,12.1 -14.7,25.8 -17.8,40.3C86.8,192 82,212.8 84.4,223.5L84.4,223.5L84.4,223.5z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="293.13" - android:centerY="37.22" - android:gradientRadius="448.8" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M263.2,170.9c4.8,4.7 9.1,10.2 12.3,16.1c0.8,0.6 1.4,1.1 2,1.6c30.2,27.8 14.4,67.1 13.2,69.9c24.5,-20.1 40.2,-50 35.5,-80.9c-15,-37.5 -40.6,-52.6 -61.4,-85.6c-1.1,-1.6 -2.1,-3.4 -3.2,-5.1c-0.5,-0.9 -1.1,-1.8 -1.4,-2.8c-0.9,-1.6 -1.5,-3.5 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1C252.3,81.3 221.8,129.6 263.2,170.9L263.2,170.9L263.2,170.9z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="255.18" - android:centerY="44.64" - android:gradientRadius="295.03" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M277.5,188.7c-0.6,-0.6 -1.3,-1.1 -2,-1.6c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-7.1,-5 -19.9,-9.9 -32.1,-7.8c47.9,23.9 35,106.3 -31.3,103.2c-5.9,-0.3 -11.8,-1.3 -17.4,-3.4c-1.3,-0.5 -2.6,-1.1 -4,-1.6c-0.8,-0.4 -1.5,-0.7 -2.2,-1.1c0,0 0.1,0 0.1,0.1c9.3,6.4 54.9,21.8 102.8,-17.2l0.1,-0.2C291.9,255.9 307.7,216.5 277.5,188.7L277.5,188.7L277.5,188.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="208.17" - android:centerY="133" - android:gradientRadius="257.65" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M156.5,232.3c0,0 6.2,-22.9 44,-22.9c4,0 15.8,-11.4 16,-14.7c0.2,-3.3 -24.2,10.1 -49.9,-1.9c-27.9,-13.1 -49,1.9 -49,1.9s8,19.9 31.5,19.9c-2.5,21.8 9.1,47.1 36.9,60.4c0.6,0.3 1.3,0.6 1.8,0.9C171.6,267.5 158.1,251.6 156.5,232.3L156.5,232.3z"> - <aapt:attr name="android:fillColor"> - <gradient - android:centerX="275.11" - android:centerY="147.93" - android:gradientRadius="309.71" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M339.4,170.8c-5.8,-13.9 -17.5,-28.9 -26.7,-33.6c7.5,14.7 11.9,29.4 13.5,40.4c0,0 0,0.1 0,0.2c-15,-37.5 -40.6,-52.6 -61.4,-85.6c-1.1,-1.6 -2.1,-3.4 -3.2,-5.1c-0.5,-0.9 -1.1,-1.8 -1.4,-2.8c-0.9,-1.6 -1.5,-3.5 -2,-5.3c0,-0.2 -0.1,-0.3 -0.3,-0.4c-0.1,0 -0.2,0 -0.3,0c0,0 0,0 -0.1,0c0,0 -0.1,0 -0.1,0.1c0,0 0,-0.1 0.1,-0.1c-33.4,19.6 -44.8,55.8 -45.8,73.9c1.5,-0.1 3.1,-0.2 4.7,-0.2c25,0 46.7,13.7 58.3,34c-7.1,-5 -19.9,-9.9 -32.1,-7.8c47.9,23.9 35,106.3 -31.3,103.2c-5.9,-0.3 -11.8,-1.3 -17.4,-3.4c-1.3,-0.5 -2.6,-1.1 -4,-1.6c-0.8,-0.4 -1.5,-0.7 -2.2,-1.1c0,0 0.1,0 0.1,0.1c-0.7,-0.3 -1.3,-0.7 -1.9,-1c0.6,0.3 1.3,0.6 1.8,0.9c-16.3,-8.4 -29.7,-24.3 -31.3,-43.6c0,0 6.2,-22.9 44,-22.9c4,0 15.8,-11.4 16,-14.7c-0.1,-1.1 -23.2,-10.3 -32.3,-19.2c-4.8,-4.7 -7.1,-7 -9.2,-8.8c-1.1,-1 -2.2,-1.8 -3.5,-2.6c-3,-10.6 -3.2,-21.9 -0.4,-32.5c-13.7,6.3 -24.3,16.1 -32,24.8H139c-5.3,-6.7 -4.9,-28.7 -4.6,-33.4c-0.1,-0.3 -4,2 -4.4,2.3c-4.6,3.3 -9,7 -13,11.2c-4.5,4.6 -8.7,9.6 -12.4,14.9l0,0l0,0c-8.6,12.1 -14.7,25.8 -17.8,40.3c-0.1,0.3 -0.1,0.6 -0.2,0.9c-0.3,1.2 -1.3,7.1 -1.5,8.4c0,0.1 0,-0.1 0,0c-1.1,6.2 -1.6,12.3 -1.9,18.6c0,0.2 0,0.5 0,0.7c0,73.5 59.6,133.1 133.1,133.1c65.8,0 120.5,-47.8 131.2,-110.6c0.2,-1.7 0.4,-3.4 0.6,-5.1C350.7,214.9 347.7,190.9 339.4,170.8L339.4,170.8zM326.2,177.7L326.2,177.7L326.2,177.7L326.2,177.7z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startX="301.73" - android:startY="122.57" - android:endX="136.89" - android:endY="314.87" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.6" android:color="#00FFF44F"/> - </gradient> - </aapt:attr> - </path> - </group> - </vector> - </aapt:attr> - <target - android:name="a1_t"> - <aapt:attr - name="android:animation"> - <set> - <objectAnimator - android:propertyName="scaleX" - android:duration="300" - android:valueFrom="0.75" - android:valueTo="0.75" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleX" - android:duration="700" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleX" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="300" - android:valueFrom="0.75002400000000002" - android:valueTo="0.75002400000000002" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear"/> - <objectAnimator - android:propertyName="scaleY" - android:duration="700" - android:valueFrom="0.75002400000000002" - android:valueTo="1" - android:startOffset="300" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="1000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="2000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="3000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="4000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="5000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="6000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="7000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="8000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="9000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="0.75" - android:valueTo="1" - android:startOffset="10000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - <objectAnimator - android:propertyName="scaleY" - android:duration="1000" - android:valueFrom="1" - android:valueTo="0.75" - android:startOffset="11000" - android:valueType="floatType"> - <aapt:attr - name="android:interpolator"> - <pathInterpolator - android:pathData="M0,0 C0.5,0 0.5,1 1,1"/> - </aapt:attr> - </objectAnimator> - </set> - </aapt:attr> - </target> -</animated-vector> diff --git a/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_background.xml b/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f3a4ae6227f1c8ea55a5d55f1547be24a146355 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_background.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="432" + android:viewportHeight="432"> + <path + android:pathData="M0,0h432v432h-432z" + android:fillColor="#F1E5FA"/> +</vector> diff --git a/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_foreground.xml b/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index b3fec7e4833fc8bf495d6a403814904950187d3a..0000000000000000000000000000000000000000 --- a/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,184 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportWidth="108" - android:viewportHeight="108"> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46A12.92,12.92 0,0 0,46 43.49a10.031,10.031 0,0 0,-0.68 -0.51,12 12,0 0,1 -0.07,-6.36A19.21,19.21 0,0 0,39 41.46c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.159,39.159 0,0 0,-0.26 1.62,0.13 0.13,0 0,1 0,0.06 26.47,26.47 0,0 0,-0.5 3.59L28,54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM48.13,64.66l0.36,0.18zM54.13,48.96zM75.6,45.65z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="34.731655" - android:startX="73.6671" - android:endY="77.194664" - android:endX="32.80596" - android:type="linear"> - <item android:offset="0.05" android:color="#FFFFF44F"/> - <item android:offset="0.37" android:color="#FFFF980E"/> - <item android:offset="0.53" android:color="#FFFF3647"/> - <item android:offset="0.7" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64V54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="53.746716" - android:centerX="68.339355" - android:centerY="37.69" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFBD4F"/> - <item android:offset="0.28" android:color="#FFFF980E"/> - <item android:offset="0.47" android:color="#FFFF3750"/> - <item android:offset="0.78" android:color="#FFEB0878"/> - <item android:offset="0.86" android:color="#FFE50080"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91,23.55 23.55,0 0,1 -0.81,17.57c-3,6.4 -10.21,13 -21.51,12.65 -12.22,-0.35 -23,-9.41 -25,-21.29a11.22,11.22 0,0 1,0.18 -4.34,19.61 19.61,0 0,0 -0.4,3.64V54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="55.09038" - android:centerX="48.57382" - android:centerY="55.002163" - android:type="radial"> - <item android:offset="0.3" android:color="#FF960E18"/> - <item android:offset="0.35" android:color="#BCB11927"/> - <item android:offset="0.43" android:color="#56DB293D"/> - <item android:offset="0.5" android:color="#16F5334B"/> - <item android:offset="0.53" android:color="#00FF3750"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M65.47,47.34l0.17,0.12a14.35,14.35 0,0 0,-2.42 -3.15c-8.09,-8.09 -2.12,-17.55 -1.12,-18a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.45 6.57z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="29.610003" - android:centerX="59.1192" - android:centerY="23.771997" - android:type="radial"> - <item android:offset="0.13" android:color="#FFFFF44F"/> - <item android:offset="0.53" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.08,49c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,46 43.49c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="26.21" - android:centerX="48.315395" - android:centerY="69.29355" - android:type="radial"> - <item android:offset="0.35" android:color="#FF3A8EE6"/> - <item android:offset="0.67" android:color="#FF9059FF"/> - <item android:offset="1" android:color="#FFC139E6"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M54.08,49c0,0.65 -2.33,2.88 -3.13,2.88 -7.4,0 -8.6,4.48 -8.6,4.48a11,11 0,0 0,6.13 8.52l0.44,0.21a12.13,12.13 0,0 0,0.76 0.31,11.91 11.91,0 0,0 3.39,0.66c13,0.61 15.49,-15.52 6.13,-20.2a9,9 0,0 1,6.27 1.52,13.13 13.13,0 0,0 -11.4,-6.66h-0.92A12.92,12.92 0,0 0,46 43.49c0.39,0.34 0.84,0.78 1.79,1.71 1.75,1.8 6.28,3.55 6.29,3.8z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="13.917509" - android:centerX="50.381275" - android:centerY="49.283504" - android:type="radial"> - <item android:offset="0.21" android:color="#009059FF"/> - <item android:offset="0.97" android:color="#996E008B"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M44.77,42.62l0.54,0.36a12,12 0,0 1,-0.07 -6.36A19.21,19.21 0,0 0,39 41.46c0.1,0 3.87,-0.07 5.77,1.16z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="18.444002" - android:centerX="52.251003" - android:centerY="30.259998" - android:type="radial"> - <item android:offset="0.1" android:color="#FFFFE226"/> - <item android:offset="0.79" android:color="#FFFF7139"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M28.24,54.58c2,11.88 12.77,20.94 25,21.29 11.3,0.32 18.52,-6.25 21.51,-12.65a23.55,23.55 0,0 0,0.81 -17.57c0.92,6 -2.15,11.87 -6.94,15.82 -9.34,7.61 -18.28,4.59 -20.09,3.35l-0.38,-0.19c-5.45,-2.6 -7.7,-7.56 -7.22,-11.82A6.67,6.67 0,0 1,34.74 49a9.8,9.8 0,0 1,9.57 -0.38A13,13 0,0 0,54.08 49c0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71a10.031,10.031 0,0 0,-0.68 -0.51l-0.54,-0.36c-1.9,-1.23 -5.67,-1.16 -5.8,-1.16 -1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88c-0.02,0.02 -0.95,4.07 -0.49,6.16z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="89.619446" - android:centerX="69.60241" - android:centerY="18.083904" - android:type="radial"> - <item android:offset="0.11" android:color="#FFFFF44F"/> - <item android:offset="0.46" android:color="#FFFF980E"/> - <item android:offset="0.72" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M63.22,44.31a14.35,14.35 0,0 1,2.42 3.15l0.39,0.32c5.9,5.44 2.81,13.13 2.58,13.68 4.79,-4 7.86,-9.79 6.94,-15.82 -3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07H62.1c-1,0.47 -6.97,9.93 1.12,18.02z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="95.36754" - android:centerX="-6.7701335" - android:centerY="37.102222" - android:type="radial"> - <item android:offset="0" android:color="#FFFFF44F"/> - <item android:offset="0.3" android:color="#FFFF980E"/> - <item android:offset="0.57" android:color="#FFFF3647"/> - <item android:offset="0.74" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M66,47.78l-0.39,-0.32 -0.17,-0.12a9,9 0,0 0,-6.27 -1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21c1.81,1.24 10.75,4.26 20.09,-3.35 0.3,-0.58 3.39,-8.27 -2.54,-13.71z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="56.180176" - android:centerX="52.887726" - android:centerY="35.519154" - android:type="radial"> - <item android:offset="0.14" android:color="#FFFFF44F"/> - <item android:offset="0.48" android:color="#FFFF980E"/> - <item android:offset="0.66" android:color="#FFFF3647"/> - <item android:offset="0.9" android:color="#FFE31587"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M42.35,56.32s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88a13,13 0,0 1,-9.77 -0.38,9.8 9.8,0 0,0 -9.57,0.38 6.67,6.67 0,0 0,6.16 3.88c-0.48,4.26 1.77,9.22 7.22,11.82l0.36,0.18a11,11 0,0 1,-6.13 -8.52z"> - <aapt:attr name="android:fillColor"> - <gradient - android:gradientRadius="60.55354" - android:centerX="65.548615" - android:centerY="39.680077" - android:type="radial"> - <item android:offset="0.09" android:color="#FFFFF44F"/> - <item android:offset="0.63" android:color="#FFFF980E"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M78.13,44.28c-1.13,-2.72 -3.43,-5.66 -5.23,-6.59a26.79,26.79 0,0 1,2.64 7.91c-3,-7.34 -7.94,-10.3 -12,-16.74 -0.2,-0.33 -0.41,-0.65 -0.61,-1a5.94,5.94 0,0 1,-0.29 -0.54,4.92 4.92,0 0,1 -0.39,-1 0.07,0.07 0,0 0,-0.05 -0.07h-0.07a19,19 0,0 0,-9 14.46h0.92a13.13,13.13 0,0 1,11.4 6.66,9 9,0 0,0 -6.27,-1.52c9.36,4.68 6.85,20.81 -6.13,20.2a11.91,11.91 0,0 1,-3.39 -0.66,12.13 12.13,0 0,1 -0.76,-0.31l-0.44,-0.21 -0.38,-0.19 0.36,0.18a11,11 0,0 1,-6.13 -8.52s1.2,-4.48 8.6,-4.48c0.8,0 3.09,-2.23 3.13,-2.88 0,-0.21 -4.54,-2 -6.3,-3.76 -1,-0.93 -1.4,-1.37 -1.79,-1.71A10.031,10.031 0,0 0,45.27 43a12,12 0,0 1,-0.07 -6.36,19.21 19.21,0 0,0 -6.2,4.82c-1,-1.31 -1,-5.62 -0.9,-6.52a4.39,4.39 0,0 0,-0.87 0.46,19.37 19.37,0 0,0 -2.54,2.18 22.23,22.23 0,0 0,-2.43 2.92,21.88 21.88,0 0,0 -3.5,7.88v0.18a39.815,39.815 0,0 0,-0.3 1.64A31.77,31.77 0,0 0,28 53.83L28,54a26,26 0,0 0,51.7 4.41l0.12,-1a26.9,26.9 0,0 0,-1.69 -13.13zM75.54,45.62z"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="33.91085" - android:startX="69.86179" - android:endY="72.21511" - android:endX="37.319843" - android:type="linear"> - <item android:offset="0.17" android:color="#CCFFF44F"/> - <item android:offset="0.6" android:color="#00FFF44F"/> - </gradient> - </aapt:attr> - </path> -</vector> diff --git a/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_monochrome_foreground.xml b/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_monochrome_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4a217f9332d38352443d6313e2ee5d3ae0ea572 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/drawable/ic_launcher_monochrome_foreground.xml @@ -0,0 +1,15 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="256" + android:viewportHeight="257"> + <group android:scaleX="0.4869866" + android:scaleY="0.4888889" + android:translateX="65.66572" + android:translateY="65.67778"> + <path + android:pathData="M256,128.91C256,199.6 198.69,256.91 128,256.91C57.31,256.91 0,199.6 0,128.91C0,58.22 57.31,0.91 128,0.91C198.69,0.91 256,58.22 256,128.91ZM128,23.91C185.99,23.91 233,70.92 233,128.91C233,186.9 185.99,233.91 128,233.91V217.91C177.15,217.91 217,178.06 217,128.91C217,79.75 177.15,39.91 128,39.91V23.91ZM128,63.16C164.31,63.16 193.75,92.6 193.75,128.91C193.75,165.22 164.31,194.66 128,194.66V178.66C155.48,178.66 177.75,156.38 177.75,128.91C177.75,101.43 155.48,79.16 128,79.16V63.16ZM155.25,128.91C155.25,113.86 143.05,101.66 128,101.66V156.16C143.05,156.16 155.25,143.96 155.25,128.91Z" + android:fillColor="#4A454E" + android:fillType="evenOdd"/> + </group> +</vector> diff --git a/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..803115f3476cf8ea75ee5057a6ddd79803549902 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_launcher_monochrome_foreground" /> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..729b41c391ca3432e4a4556eb2186947b8e3dc58 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_monochrome_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_monochrome_background"/> + <foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..d372a4fca9b35d26af58c251afcad94bd67642ec --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background"/> + <foreground android:drawable="@mipmap/ic_launcher_foreground"/> +</adaptive-icon> diff --git a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher.webp index 41314eec7045ff2219c592d64e6e43999b77861a..2dfc9f84ebf89f6181b9da37915f5bf466a0da8d 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..f6310d7240b3dcba0108f99c35bb088d9fb60e5d Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..06f41a1877d80065553250803f924d80d1ff9be2 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..c14cd3326eecc0f505f21bd5bb20d22afbc6eb1c Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_round.webp index bfbe0eefe97a505859595068e62c10068e731310..fc0af4e16f8105ff7ee6c1f0747edf39713965cb 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/release/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher.webp index fad41457519e457b486b5e79a0fb6565784338a4..de7c6e47ecacef2041eae88a717784976be755ea 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..b5e24a8bec2822350f898e5cb93d35b226542c42 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..86a41ab7c0aff27e63c3bc35172a0756d93ac61b Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..f4cd8633e28ecd0a3c41cbd53c128b32aa5f8174 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_round.webp index e403ef8ae74d063ceb088c02837526c90cded666..92515bdba17a28262f987bb5095610c5b2b611df 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/release/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher.webp index a9be84f4c0689a490a8d0b394f7fcc40661f8cc0..2755baf2615ad7d0d8238b07b410ea0bd229cd17 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..5d1cbc52a575981c310a6e62afc7196a476967cd Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..4c59d9c1a230da68d1915b8cff2bbce32a0a954d Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..964ca9d190bbf19cf8e71220a2cb754be159c49b Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp index 7fe163d6346c8f1339db20a69fe8c0a52466cfa4..6de4d05fd1d1876677b26f68fe3956cb0efad665 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher.webp index 1dcd39266c518cba9a79a4b75012f7024c8ac289..78a1c8da56c3d30705d6e95c5eee69d76cf99aef 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..63167479be7e34d43ede06bd94ad41a6e674ed76 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..8ef42fc0716c177a410a65ba0df1c5cf7be256f5 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..7e242778e6b309ba549df7459262ca0fac825f89 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp index c946c446789ede359f7d32c8d33849961fd869d8..34774d61fbfc06f37fc98c0139f4067b528004d9 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp index 6d187c7ec8e8a4ca1666377ef58c96b96ef4a56d..4756e3f9d2758dc3ef19a6c95b81e5742c59ca3c 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..6e866742d396226c22e1970bc91eb5dc951a859b Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..93e52cee58f5c82be96b4ab84766c37c89ad3074 Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..5c38f46715f5c4c21bcd913548ae4809518559ca Binary files /dev/null and b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp index 9fa7fac714c9e6d76a83f4661483ee7dd81427ea..2d57d43822506bf78216b2a2869cf347de01520f 100644 Binary files a/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/mobile/android/fenix/app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/mobile/android/fenix/app/src/release/res/values/ic_launcher_monochrome_background.xml b/mobile/android/fenix/app/src/release/res/values/ic_launcher_monochrome_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..70a105458b46dbc72a2bce80b62fa57c36cdbcf1 --- /dev/null +++ b/mobile/android/fenix/app/src/release/res/values/ic_launcher_monochrome_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_monochrome_background">#FEFBFF</color> +</resources> diff --git a/mobile/android/fenix/app/src/release/res/values/static_strings.xml b/mobile/android/fenix/app/src/release/res/values/static_strings.xml index c13e4d45252dee3b08c2cd552d8ffb2a49f32255..7b02526bbe7747a8161f54ed291396a9be59f0a9 100644 --- a/mobile/android/fenix/app/src/release/res/values/static_strings.xml +++ b/mobile/android/fenix/app/src/release/res/values/static_strings.xml @@ -4,5 +4,5 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <!-- Name of the application --> - <string name="app_name" translatable="false">Firefox</string> + <string name="app_name" translatable="false">Tor Browser</string> </resources> diff --git a/mobile/android/fenix/app/src/release/res/xml/shortcuts.xml b/mobile/android/fenix/app/src/release/res/xml/shortcuts.xml index 31d6b91379cbfe57cad0a80a849964a02052abe3..6ff16b224813eb01a801a938a3b5fd48c5ec2d30 100644 --- a/mobile/android/fenix/app/src/release/res/xml/shortcuts.xml +++ b/mobile/android/fenix/app/src/release/res/xml/shortcuts.xml @@ -4,6 +4,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- <shortcut android:shortcutId="password_manager" android:enabled="true" @@ -21,7 +22,7 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_TAB" - android:targetPackage="org.mozilla.firefox" + android:targetPackage="org.torproject.torbrowser" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> <shortcut @@ -31,7 +32,8 @@ android:shortcutShortLabel="@string/home_screen_shortcut_open_new_private_tab_2"> <intent android:action="org.mozilla.fenix.OPEN_PRIVATE_TAB" - android:targetPackage="org.mozilla.firefox" + android:targetPackage="org.torproject.torbrowser" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> </shortcut> + --> </shortcuts> diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/MenuNavigationMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/MenuNavigationMiddlewareTest.kt index 1d758e1f36bf4a253ff3fe681f10ef8470a07556..515d291486afd5b2a35139d52fc3afbc5ed6326f 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/MenuNavigationMiddlewareTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/MenuNavigationMiddlewareTest.kt @@ -228,7 +228,7 @@ class MenuNavigationMiddlewareTest { store.dispatch(MenuAction.Navigate.ReleaseNotes).join() - assertEquals(SupportUtils.WHATS_NEW_URL, params?.url) + assertEquals(SupportUtils.getTorWhatsNewUrl(), params?.url) } @Test diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt index 800c80a2457cdf708913540c22f12510ca56eef2..b3e3ff23bb5a881ac4873a171df3f317629d7e49 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt @@ -6,67 +6,25 @@ package org.mozilla.fenix.components.metrics import android.content.Context import android.util.Base64 -import com.google.android.gms.ads.identifier.AdvertisingIdClient -import com.google.android.gms.common.GooglePlayServicesNotAvailableException -import com.google.android.gms.common.GooglePlayServicesRepairableException import io.mockk.every import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.slot -import io.mockk.unmockkStatic import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test -import java.io.IOException class MetricsUtilsTest { private val context: Context = mockk(relaxed = true) - @Test - fun `getAdvertisingID() returns null if the API throws`() { - mockkStatic("com.google.android.gms.ads.identifier.AdvertisingIdClient") - - val exceptions = listOf( - GooglePlayServicesNotAvailableException(1), - GooglePlayServicesRepairableException(0, "", mockk()), - IllegalStateException(), - IOException(), - ) - - exceptions.forEach { - every { - AdvertisingIdClient.getAdvertisingIdInfo(any()) - } throws it - - assertNull(MetricsUtils.getAdvertisingID(context)) - } - - unmockkStatic("com.google.android.gms.ads.identifier.AdvertisingIdClient") - } - @Test fun `getAdvertisingID() returns null if the API returns null info`() { - mockkStatic(AdvertisingIdClient::class) - every { AdvertisingIdClient.getAdvertisingIdInfo(any()) } returns null - assertNull(MetricsUtils.getAdvertisingID(context)) } - @Test - fun `getAdvertisingID() returns a valid string if the API returns a valid ID`() { - val testId = "test-value-id" - - mockkStatic(AdvertisingIdClient::class) - every { - AdvertisingIdClient.getAdvertisingIdInfo(any()) - } returns AdvertisingIdClient.Info(testId, false) - - assertEquals(testId, MetricsUtils.getAdvertisingID(context)) - } - @Test fun `getHashedIdentifier() returns a hashed identifier`() = runTest { val testId = "test-value-id" diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/ext/ContextTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/ext/ContextTest.kt index cfe0b80c9325c5e486b34de990e4d195039fb3f4..383d8c84d56d026328c17108db44251409abdad9 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/ext/ContextTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/ext/ContextTest.kt @@ -41,7 +41,7 @@ class ContextTest { private lateinit var mockContext: Context private val selectedLocale = Locale("ro", "RO") - private val appName = "Firefox Preview" + private val appName = "Tor Browser Dev" private val mockId: Int = 11 @@ -67,7 +67,7 @@ class ContextTest { val result = mockContext.getStringWithArgSafe(mockId, appName) - assertEquals("Incearca noul Firefox Preview", result) + assertEquals("Incearca noul Tor Browser Dev", result) } @Test @@ -80,7 +80,7 @@ class ContextTest { val result = mockContext.getStringWithArgSafe(mockId, appName) - assertEquals("Try the new Firefox Preview", result) + assertEquals("Try the new Tor Browser Dev", result) } @Test diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/HomeMenuViewTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/HomeMenuViewTest.kt index c5de332cc54981899ff3829b3f58afc8c75742b7..01e54e111ac1b1b688df6d653bb75e913d25dac2 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/HomeMenuViewTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/HomeMenuViewTest.kt @@ -97,21 +97,21 @@ class HomeMenuViewTest { } } - @Test - fun `WHEN Customize Home menu item is tapped THEN navigate to home settings fragment and record metrics`() { - assertNull(HomeScreen.customizeHomeClicked.testGetValue()) - - homeMenuView.onItemTapped(HomeMenu.Item.CustomizeHome) - - assertNotNull(HomeScreen.customizeHomeClicked.testGetValue()) - - verify { - navController.nav( - R.id.homeFragment, - HomeFragmentDirections.actionGlobalHomeSettingsFragment(), - ) - } - } +// @Test +// fun `WHEN Customize Home menu item is tapped THEN navigate to home settings fragment and record metrics`() { +// assertNull(HomeScreen.customizeHomeClicked.testGetValue()) +// +// homeMenuView.onItemTapped(HomeMenu.Item.CustomizeHome) +// +// assertNotNull(HomeScreen.customizeHomeClicked.testGetValue()) +// +// verify { +// navController.nav( +// R.id.homeFragment, +// HomeFragmentDirections.actionGlobalHomeSettingsFragment(), +// ) +// } +// } @Test fun `GIVEN various sync account state WHEN Sync Account menu item is tapped THEN navigate to the appropriate sync fragment`() { @@ -213,7 +213,7 @@ class HomeMenuViewTest { WhatsNew.userViewedWhatsNew(testContext) homeActivity.openToBrowserAndLoad( - searchTermOrURL = SupportUtils.WHATS_NEW_URL, + searchTermOrURL = SupportUtils.getTorWhatsNewUrl(), newTab = true, from = BrowserDirection.FromHome, ) diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt index 4e903157b4ddc2d626196a5a476abb14144ca596..2621099c4ef74e09091097eac5ac2158fa694b38 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingMapperTest.kt @@ -13,7 +13,7 @@ class OnboardingMapperTest { @Test fun `GIVEN a default browser page WHEN mapToOnboardingPageState is called THEN creates the expected OnboardingPageState`() { val expected = OnboardingPageState( - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = "default browser title", description = "default browser body with link text", primaryButton = Action("default browser primary button text", unitLambda), @@ -22,7 +22,7 @@ class OnboardingMapperTest { val onboardingPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = "default browser title", description = "default browser body with link text", primaryButtonLabel = "default browser primary button text", @@ -47,7 +47,7 @@ class OnboardingMapperTest { @Test fun `GIVEN a sync page WHEN mapToOnboardingPageState is called THEN creates the expected OnboardingPageState`() { val expected = OnboardingPageState( - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = "sync title", description = "sync body", primaryButton = Action("sync primary button text", unitLambda), @@ -56,7 +56,7 @@ class OnboardingMapperTest { val onboardingPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = "sync title", description = "sync body", primaryButtonLabel = "sync primary button text", @@ -81,7 +81,7 @@ class OnboardingMapperTest { @Test fun `GIVEN a notification page WHEN mapToOnboardingPageState is called THEN creates the expected OnboardingPageState`() { val expected = OnboardingPageState( - imageRes = R.drawable.ic_notification_permission, + imageRes = R.drawable.mozac_lib_crash_notification, title = "notification title", description = "notification body", primaryButton = Action("notification primary button text", unitLambda), @@ -90,7 +90,7 @@ class OnboardingMapperTest { val onboardingPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, - imageRes = R.drawable.ic_notification_permission, + imageRes = R.drawable.mozac_lib_crash_notification, title = "notification title", description = "notification body", primaryButtonLabel = "notification primary button text", @@ -115,7 +115,7 @@ class OnboardingMapperTest { @Test fun `GIVEN an add search widget page WHEN mapToOnboardingPageState is called THEN creates the expected OnboardingPageState`() { val expected = OnboardingPageState( - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = "add search widget title", description = "add search widget body with link text", primaryButton = Action("add search widget primary button text", unitLambda), @@ -124,7 +124,7 @@ class OnboardingMapperTest { val onboardingPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET, - imageRes = R.drawable.ic_onboarding_search_widget, + imageRes = R.drawable.mozac_lib_crash_notification, title = "add search widget title", description = "add search widget body with link text", primaryButtonLabel = "add search widget primary button text", diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingPageUiDataTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingPageUiDataTest.kt index ef06b4f3c78fc4ff3afaff9dea63c5fa0b0dd5af..97f83d71bafd226c5be80ec09942617060906bc8 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingPageUiDataTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/onboarding/view/OnboardingPageUiDataTest.kt @@ -53,7 +53,7 @@ class OnboardingPageUiDataTest { private val defaultBrowserPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.DEFAULT_BROWSER, - imageRes = R.drawable.ic_onboarding_welcome, + imageRes = R.drawable.mozac_lib_crash_notification, title = "default browser title", description = "default browser body with link text", primaryButtonLabel = "default browser primary button text", @@ -63,7 +63,7 @@ private val defaultBrowserPageUiData = OnboardingPageUiData( private val syncPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.SYNC_SIGN_IN, - imageRes = R.drawable.ic_onboarding_sync, + imageRes = R.drawable.mozac_lib_crash_notification, title = "sync title", description = "sync body", primaryButtonLabel = "sync primary button text", @@ -73,7 +73,7 @@ private val syncPageUiData = OnboardingPageUiData( private val notificationPageUiData = OnboardingPageUiData( type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, - imageRes = R.drawable.ic_notification_permission, + imageRes = R.drawable.mozac_lib_crash_notification, title = "notification title", description = "notification body", primaryButtonLabel = "notification primary button text", diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/SupportUtilsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/SupportUtilsTest.kt index f292038e526e3692391391a8e3522260df0cde1c..378531759b6f911320f1311cda905a11dde19d68 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/SupportUtilsTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/SupportUtilsTest.kt @@ -25,10 +25,10 @@ class SupportUtilsTest { "https://support.mozilla.org/1/mobile/20/Android/fr/tracking-protection-firefox-android", SupportUtils.getSumoURLForTopic(mockContext("2 0"), SupportUtils.SumoTopic.TRACKING_PROTECTION, Locale("fr")), ) - assertEquals( - "https://www.mozilla.org/firefox/android/notes", - SupportUtils.WHATS_NEW_URL, - ) + // assertEquals( + // "https://www.mozilla.org/firefox/android/notes", + // SupportUtils.WHATS_NEW_URL, + // ) } @Test @@ -55,6 +55,18 @@ class SupportUtilsTest { ) } + @Test + fun getTorPageUrl() { + assertEquals( + "https://tb-manual.torproject.org/mobile-tor", + SupportUtils.getTorHelpPageUrl() + ) + assertEquals( + "https://www.torproject.org/releases/", + SupportUtils.getTorWhatsNewUrl() + ) + } + private fun mockContext(versionName: String): Context { val context: Context = mockk() val packageManager: PackageManager = mockk() diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/ProtectionsViewTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/ProtectionsViewTest.kt index c88152ebcd947d4f89660a137f17f566afbec182..0fbf6e1852a1d53950945d790867ba897789fcd0 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/ProtectionsViewTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/ProtectionsViewTest.kt @@ -53,46 +53,46 @@ class ProtectionsViewTest { binding = view.binding } - @Test - fun `WHEN updating THEN bind checkbox`() { - val websiteUrl = "https://mozilla.org" - val state = ProtectionsState( - tab = createTab(url = websiteUrl), - url = websiteUrl, - isTrackingProtectionEnabled = true, - cookieBannerUIMode = CookieBannerUIMode.ENABLE, - listTrackers = listOf(), - mode = ProtectionsState.Mode.Normal, - lastAccessedCategory = "", - ) - - every { settings.shouldUseTrackingProtection } returns true - - view.update(state) - - assertTrue(binding.root.isVisible) - assertTrue(binding.trackingProtectionSwitch.isChecked) - } - - @Test - fun `GIVEN TP is globally off WHEN updating THEN hide the TP section`() { - val websiteUrl = "https://mozilla.org" - val state = ProtectionsState( - tab = createTab(url = websiteUrl), - url = websiteUrl, - isTrackingProtectionEnabled = true, - cookieBannerUIMode = CookieBannerUIMode.ENABLE, - listTrackers = listOf(), - mode = ProtectionsState.Mode.Normal, - lastAccessedCategory = "", - ) - - every { settings.shouldUseTrackingProtection } returns false - - view.update(state) - - assertFalse(binding.trackingProtectionSwitch.isVisible) - } +// @Test +// fun `WHEN updating THEN bind checkbox`() { +// val websiteUrl = "https://mozilla.org" +// val state = ProtectionsState( +// tab = createTab(url = websiteUrl), +// url = websiteUrl, +// isTrackingProtectionEnabled = true, +// cookieBannerUIMode = CookieBannerUIMode.ENABLE, +// listTrackers = listOf(), +// mode = ProtectionsState.Mode.Normal, +// lastAccessedCategory = "", +// ) +// +// every { settings.shouldUseTrackingProtection } returns true +// +// view.update(state) +// +// assertTrue(binding.root.isVisible) +// assertTrue(binding.trackingProtectionSwitch.isChecked) +// } + +// @Test +// fun `GIVEN TP is globally off WHEN updating THEN hide the TP section`() { +// val websiteUrl = "https://mozilla.org" +// val state = ProtectionsState( +// tab = createTab(url = websiteUrl), +// url = websiteUrl, +// isTrackingProtectionEnabled = true, +// cookieBannerUIMode = CookieBannerUIMode.ENABLE, +// listTrackers = listOf(), +// mode = ProtectionsState.Mode.Normal, +// lastAccessedCategory = "", +// ) +// +// every { settings.shouldUseTrackingProtection } returns false +// +// view.update(state) +// +// assertFalse(binding.trackingProtectionSwitch.isVisible) +// } @Test fun `GIVEN cookie banners handling is globally off WHEN updating THEN hide the cookie banner section`() { @@ -157,18 +157,18 @@ class ProtectionsViewTest { assertFalse(binding.cookieBannerItem.isVisible) } - @Test - fun `WHEN updateDetailsSection is called THEN update the visibility of the section`() { - every { settings.shouldUseTrackingProtection } returns false - - view.updateDetailsSection(false) - - assertFalse(binding.trackingProtectionDetails.isVisible) - - view.updateDetailsSection(true) - - assertTrue(binding.trackingProtectionDetails.isVisible) - } +// @Test +// fun `WHEN updateDetailsSection is called THEN update the visibility of the section`() { +// every { settings.shouldUseTrackingProtection } returns false +// +// view.updateDetailsSection(false) +// +// assertFalse(binding.trackingProtectionDetails.isVisible) +// +// view.updateDetailsSection(true) +// +// assertTrue(binding.trackingProtectionDetails.isVisible) +// } @Test fun `WHEN all the views from protectionView are gone THEN tracking protection divider is gone`() { diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragmentTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragmentTest.kt index 328bee295c96ae1d1d2ad6b1c5c99ce252f80052..ff0e9a0eac2f4f3b72c8d9fc0fee962fb77f1a97 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragmentTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragmentTest.kt @@ -52,111 +52,111 @@ class QuickSettingsSheetDialogFragmentTest { every { fragment.activity } returns mockk(relaxed = true) } - @Test - fun `WHEN a tracker is loaded THEN trackers view is updated`() { - val tab = createTab("mozilla.org") - - every { fragment.provideTabId() } returns tab.id - every { fragment.updateTrackers(any()) } returns Unit - - fragment.observeTrackersChange(store) - - addAndSelectTab(tab) - - verify(exactly = 1) { - fragment.updateTrackers(tab) - } - - store.dispatch(TrackerLoadedAction(tab.id, mockk())).joinBlocking() - - val updatedTab = store.state.findTab(tab.id)!! - - assertNotSame(updatedTab, tab) - - verify(exactly = 1) { - fragment.updateTrackers(updatedTab) - } - } - - @Test - fun `WHEN a tracker is blocked THEN trackers view is updated`() { - val tab = createTab("mozilla.org") - - every { fragment.provideTabId() } returns tab.id - every { fragment.updateTrackers(any()) } returns Unit - - fragment.observeTrackersChange(store) - - addAndSelectTab(tab) - - verify(exactly = 1) { - fragment.updateTrackers(tab) - } - - store.dispatch(TrackerBlockedAction(tab.id, mockk())).joinBlocking() - - val updatedTab = store.state.findTab(tab.id)!! - - assertNotSame(updatedTab, tab) - - verify(exactly = 1) { - fragment.updateTrackers(updatedTab) - } - } - - @Test - fun `GIVEN no trackers WHEN calling updateTrackers THEN hide the details section`() { - val tab = createTab("mozilla.org") - val trackingProtectionUseCases: TrackingProtectionUseCases = mockk(relaxed = true) - val protectionsView: ProtectionsView = mockk(relaxed = true) - - val onComplete = slot<(List<TrackerLog>) -> Unit>() - - every { fragment.protectionsView } returns protectionsView - - every { - trackingProtectionUseCases.fetchTrackingLogs.invoke( - any(), - capture(onComplete), - any(), - ) - }.answers { onComplete.captured.invoke(emptyList()) } - - every { fragment.provideTrackingProtectionUseCases() } returns trackingProtectionUseCases - - fragment.updateTrackers(tab) - - verify { - protectionsView.updateDetailsSection(false) - } - } - - @Test - fun `GIVEN trackers WHEN calling updateTrackers THEN show the details section`() { - val tab = createTab("mozilla.org") - val trackingProtectionUseCases: TrackingProtectionUseCases = mockk(relaxed = true) - val protectionsView: ProtectionsView = mockk(relaxed = true) - - val onComplete = slot<(List<TrackerLog>) -> Unit>() - - every { fragment.protectionsView } returns protectionsView - - every { - trackingProtectionUseCases.fetchTrackingLogs.invoke( - any(), - capture(onComplete), - any(), - ) - }.answers { onComplete.captured.invoke(listOf(TrackerLog(""))) } - - every { fragment.provideTrackingProtectionUseCases() } returns trackingProtectionUseCases - - fragment.updateTrackers(tab) - - verify { - protectionsView.updateDetailsSection(true) - } - } +// @Test +// fun `WHEN a tracker is loaded THEN trackers view is updated`() { +// val tab = createTab("mozilla.org") +// +// every { fragment.provideTabId() } returns tab.id +// every { fragment.updateTrackers(any()) } returns Unit +// +// fragment.observeTrackersChange(store) +// +// addAndSelectTab(tab) +// +// verify(exactly = 1) { +// fragment.updateTrackers(tab) +// } +// +// store.dispatch(TrackerLoadedAction(tab.id, mockk())).joinBlocking() +// +// val updatedTab = store.state.findTab(tab.id)!! +// +// assertNotSame(updatedTab, tab) +// +// verify(exactly = 1) { +// fragment.updateTrackers(updatedTab) +// } +// } + +// @Test +// fun `WHEN a tracker is blocked THEN trackers view is updated`() { +// val tab = createTab("mozilla.org") +// +// every { fragment.provideTabId() } returns tab.id +// every { fragment.updateTrackers(any()) } returns Unit +// +// fragment.observeTrackersChange(store) +// +// addAndSelectTab(tab) +// +// verify(exactly = 1) { +// fragment.updateTrackers(tab) +// } +// +// store.dispatch(TrackerBlockedAction(tab.id, mockk())).joinBlocking() +// +// val updatedTab = store.state.findTab(tab.id)!! +// +// assertNotSame(updatedTab, tab) +// +// verify(exactly = 1) { +// fragment.updateTrackers(updatedTab) +// } +// } + +// @Test +// fun `GIVEN no trackers WHEN calling updateTrackers THEN hide the details section`() { +// val tab = createTab("mozilla.org") +// val trackingProtectionUseCases: TrackingProtectionUseCases = mockk(relaxed = true) +// val protectionsView: ProtectionsView = mockk(relaxed = true) +// +// val onComplete = slot<(List<TrackerLog>) -> Unit>() +// +// every { fragment.protectionsView } returns protectionsView +// +// every { +// trackingProtectionUseCases.fetchTrackingLogs.invoke( +// any(), +// capture(onComplete), +// any(), +// ) +// }.answers { onComplete.captured.invoke(emptyList()) } +// +// every { fragment.provideTrackingProtectionUseCases() } returns trackingProtectionUseCases +// +// fragment.updateTrackers(tab) +// +// verify { +// protectionsView.updateDetailsSection(false) +// } +// } + +// @Test +// fun `GIVEN trackers WHEN calling updateTrackers THEN show the details section`() { +// val tab = createTab("mozilla.org") +// val trackingProtectionUseCases: TrackingProtectionUseCases = mockk(relaxed = true) +// val protectionsView: ProtectionsView = mockk(relaxed = true) +// +// val onComplete = slot<(List<TrackerLog>) -> Unit>() +// +// every { fragment.protectionsView } returns protectionsView +// +// every { +// trackingProtectionUseCases.fetchTrackingLogs.invoke( +// any(), +// capture(onComplete), +// any(), +// ) +// }.answers { onComplete.captured.invoke(listOf(TrackerLog(""))) } +// +// every { fragment.provideTrackingProtectionUseCases() } returns trackingProtectionUseCases +// +// fragment.updateTrackers(tab) +// +// verify { +// protectionsView.updateDetailsSection(true) +// } +// } private fun addAndSelectTab(tab: TabSessionState) { store.dispatch(TabListAction.AddTabAction(tab)).joinBlocking() diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsViewTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsViewTest.kt index 5afd82b0f204e218df75ac4e741292b0073065a7..727b1714297e8029177b33068cd23f30e6b46787 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsViewTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerHandlingDetailsViewTest.kt @@ -227,29 +227,29 @@ class CookieBannerHandlingDetailsViewTest { view.update(state) assertEquals(View.GONE, view.binding.cookieBannerSwitch.visibility) - assertEquals(View.VISIBLE, view.binding.cancelButton.visibility) - assertEquals(View.VISIBLE, view.binding.requestSupport.visibility) +// assertEquals(View.VISIBLE, view.binding.cancelButton.visibility) +// assertEquals(View.VISIBLE, view.binding.requestSupport.visibility) } - @Test - fun `WHEN clicking the request support button THEN view must delegate to the interactor#handleRequestSiteSupportPressed()`() { - val websiteUrl = "https://mozilla.org" - val state = ProtectionsState( - tab = createTab(url = websiteUrl), - url = websiteUrl, - isTrackingProtectionEnabled = true, - cookieBannerUIMode = CookieBannerUIMode.SITE_NOT_SUPPORTED, - listTrackers = listOf(), - mode = ProtectionsState.Mode.Normal, - lastAccessedCategory = "", - ) - - view.update(state) - - view.binding.requestSupport.performClick() - - verify { - interactor.handleRequestSiteSupportPressed() - } - } +// @Test +// fun `WHEN clicking the request support button THEN view must delegate to the interactor#handleRequestSiteSupportPressed()`() { +// val websiteUrl = "https://mozilla.org" +// val state = ProtectionsState( +// tab = createTab(url = websiteUrl), +// url = websiteUrl, +// isTrackingProtectionEnabled = true, +// cookieBannerUIMode = CookieBannerUIMode.SITE_NOT_SUPPORTED, +// listTrackers = listOf(), +// mode = ProtectionsState.Mode.Normal, +// lastAccessedCategory = "", +// ) +// +// view.update(state) +// +// view.binding.requestSupport.performClick() +// +// verify { +// interactor.handleRequestSiteSupportPressed() +// } +// } } diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt index 3c82e6d0e8a8f68dc9413a3dfbb3a66d56d9ae07..25d5fceaf5c7f189bf8ae8abe6f455b3c2c953c8 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt @@ -220,43 +220,43 @@ internal class DefaultCookieBannerDetailsControllerTest { } } - @Test - fun `GIVEN cookie banner mode is site not supported WHEN handleRequestSiteSupportPressed THEN request report site domain`() = - runTestOnMain { - val store = BrowserStore( - BrowserState( - customTabs = listOf( - createCustomTab( - url = "https://www.mozilla.org", - id = "mozilla", - ), - ), - ), - ) - every { testContext.components.core.store } returns store - coEvery { controller.getTabDomain(any()) } returns "mozilla.org" - every { protectionsStore.dispatch(any()) } returns mockk() - - controller.handleRequestSiteSupportPressed() - - assertNotNull(CookieBanners.reportDomainSiteButton.testGetValue()) - Pings.cookieBannerReportSite.testBeforeNextSubmit { - assertNotNull(CookieBanners.reportSiteDomain.testGetValue()) - assertEquals("mozilla.org", CookieBanners.reportSiteDomain.testGetValue()) - } - advanceUntilIdle() - coVerifyOrder { - protectionsStore.dispatch( - ProtectionsAction.RequestReportSiteDomain( - "mozilla.org", - ), - ) - protectionsStore.dispatch( - ProtectionsAction.UpdateCookieBannerMode( - cookieBannerUIMode = CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED, - ), - ) - cookieBannersStorage.saveSiteDomain("mozilla.org") - } - } +// @Test +// fun `GIVEN cookie banner mode is site not supported WHEN handleRequestSiteSupportPressed THEN request report site domain`() = +// runTestOnMain { +// val store = BrowserStore( +// BrowserState( +// customTabs = listOf( +// createCustomTab( +// url = "https://www.mozilla.org", +// id = "mozilla", +// ), +// ), +// ), +// ) +// every { testContext.components.core.store } returns store +// coEvery { controller.getTabDomain(any()) } returns "mozilla.org" +// every { protectionsStore.dispatch(any()) } returns mockk() +// +// controller.handleRequestSiteSupportPressed() +// +// assertNotNull(CookieBanners.reportDomainSiteButton.testGetValue()) +// Pings.cookieBannerReportSite.testBeforeNextSubmit { +// assertNotNull(CookieBanners.reportSiteDomain.testGetValue()) +// assertEquals("mozilla.org", CookieBanners.reportSiteDomain.testGetValue()) +// } +// advanceUntilIdle() +// coVerifyOrder { +// protectionsStore.dispatch( +// ProtectionsAction.RequestReportSiteDomain( +// "mozilla.org", +// ), +// ) +// protectionsStore.dispatch( +// ProtectionsAction.UpdateCookieBannerMode( +// cookieBannerUIMode = CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED, +// ), +// ) +// cookieBannersStorage.saveSiteDomain("mozilla.org") +// } +// } } diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt index 9045409db5609e0592067121c04b99e50fa8bd22..f64ae6dfbdbd7e6341ef51503fb1ce019309bffe 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt @@ -39,7 +39,7 @@ class AppViewHolderTest { fun `bind app share option`() { val app = AppShareOption( name = "Pocket", - icon = getDrawable(testContext, R.drawable.ic_pocket)!!, + icon = getDrawable(testContext, R.drawable.mozac_lib_crash_notification)!!, packageName = "com.mozilla.pocket", activityName = "MainActivity", ) @@ -53,7 +53,7 @@ class AppViewHolderTest { fun `trigger interactor if application is bound`() { val app = AppShareOption( name = "Pocket", - icon = getDrawable(testContext, R.drawable.ic_pocket)!!, + icon = getDrawable(testContext, R.drawable.mozac_lib_crash_notification)!!, packageName = "com.mozilla.pocket", activityName = "MainActivity", ) diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/ProtectionsStoreTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/ProtectionsStoreTest.kt index 6141970557bdd2e361982d1b83031edb55b68ce7..ad0e95557655034adc440f425894aaa1d0d02a1e 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/ProtectionsStoreTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/ProtectionsStoreTest.kt @@ -135,22 +135,22 @@ class ProtectionsStoreTest { ) } - @Test - fun `ProtectionsAction - RequestReportSiteDomain`() = runTest { - val initialState = defaultState() - val store = ProtectionsStore(initialState) - - store.dispatch( - ProtectionsAction.RequestReportSiteDomain( - url = "youtube.com", - ), - ).join() - - assertEquals( - "youtube.com", - store.state.url, - ) - } +// @Test +// fun `ProtectionsAction - RequestReportSiteDomain`() = runTest { +// val initialState = defaultState() +// val store = ProtectionsStore(initialState) +// +// store.dispatch( +// ProtectionsAction.RequestReportSiteDomain( +// url = "youtube.com", +// ), +// ).join() +// +// assertEquals( +// "youtube.com", +// store.state.url, +// ) +// } @Test fun `ProtectionsAction - UpdateCookieBannerMode`() = runTest { diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt index e983189817a278edceb1ebd6a419258e92a29b90..76168151453739fba1da887a8f4ccb6cabc43e16 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -23,6 +23,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitType @@ -54,13 +55,13 @@ class SettingsTest { fun launchLinksInPrivateTab() { // When just created // Then - assertFalse(settings.openLinksInAPrivateTab) + assertTrue(settings.openLinksInAPrivateTab) // When - settings.openLinksInAPrivateTab = true + settings.openLinksInAPrivateTab = false // Then - assertTrue(settings.openLinksInAPrivateTab) + assertFalse(settings.openLinksInAPrivateTab) } @Test @@ -159,7 +160,11 @@ class SettingsTest { fun isTelemetryEnabled() { // When just created // Then - assertTrue(settings.isTelemetryEnabled) + if (BuildConfig.DATA_COLLECTION_DISABLED) { + assertFalse(settings.isTelemetryEnabled) + } else { + assertTrue(settings.isTelemetryEnabled) + } } @Test @@ -451,7 +456,7 @@ class SettingsTest { settings.incrementVisitedInstallableCount() // Then - assertTrue(settings.shouldShowPwaCfr) + assertFalse(settings.shouldShowPwaCfr) } @Test @@ -920,28 +925,28 @@ class SettingsTest { assertFalse(settings.shouldUseHttpsOnlyInPrivateTabsOnly) } - @Test - fun `GIVEN open links in apps setting THEN return the correct display string`() { - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_always" - settings.lastKnownMode = BrowsingMode.Normal - assertEquals(settings.getOpenLinksInAppsString(), "Always") - - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_ask" - assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") - - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_never" - assertEquals(settings.getOpenLinksInAppsString(), "Never") - - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_always" - settings.lastKnownMode = BrowsingMode.Private - assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") - - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_ask" - assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") - - settings.openLinksInExternalApp = "pref_key_open_links_in_apps_never" - assertEquals(settings.getOpenLinksInAppsString(), "Never") - } +// @Test +// fun `GIVEN open links in apps setting THEN return the correct display string`() { +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_always" +// settings.lastKnownMode = BrowsingMode.Normal +// assertEquals(settings.getOpenLinksInAppsString(), "Always") +// +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_ask" +// assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") +// +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_never" +// assertEquals(settings.getOpenLinksInAppsString(), "Never") +// +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_always" +// settings.lastKnownMode = BrowsingMode.Private +// assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") +// +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_ask" +// assertEquals(settings.getOpenLinksInAppsString(), "Ask before opening") +// +// settings.openLinksInExternalApp = "pref_key_open_links_in_apps_never" +// assertEquals(settings.getOpenLinksInAppsString(), "Never") +// } @Test fun `GIVEN a written integer value for pref_key_search_widget_installed WHEN reading searchWidgetInstalled THEN do not throw a ClassCastException`() { diff --git a/mobile/android/fenix/build.gradle b/mobile/android/fenix/build.gradle index b714cf70e7e2de84ba187525a3339e840e6bbfa8..0235ad2705906e73f34369c6e144733d689a39d0 100644 --- a/mobile/android/fenix/build.gradle +++ b/mobile/android/fenix/build.gradle @@ -10,6 +10,7 @@ import java.nio.file.StandardCopyOption buildscript { // This logic is duplicated in the allprojects block: I don't know how to fix that. repositories { + mavenLocal() gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> maven { url repository @@ -51,6 +52,7 @@ plugins { allprojects { // This logic is duplicated in the buildscript block: I don't know how to fix that. repositories { + mavenLocal() gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> maven { url repository diff --git a/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt index b7f722aa1fdebfe4b86ae928137ada8499857dc0..35c2824844993d2979030e9d1e2713feda0daed3 100644 --- a/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt +++ b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt @@ -24,7 +24,8 @@ object FenixVersions { @Suppress("unused") object FenixDependencies { - const val adjust = "com.adjust.sdk:adjust-android:${FenixVersions.adjust}" +// Disable features and functionality +// const val adjust = "com.adjust.sdk:adjust-android:${FenixVersions.adjust}" const val installreferrer = "com.android.installreferrer:installreferrer:${FenixVersions.installreferrer}" const val mockk = "io.mockk:mockk:${FenixVersions.mockk}" diff --git a/mobile/android/fenix/tools/tba-fetch-deps.sh b/mobile/android/fenix/tools/tba-fetch-deps.sh new file mode 100755 index 0000000000000000000000000000000000000000..5ece75afccfd25fbd45057639eec250a7a7f6dfb --- /dev/null +++ b/mobile/android/fenix/tools/tba-fetch-deps.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +cd "$(dirname $(realpath "$0"))/.." + +if [ -z "$TOR_BROWSER_BUILD" ]; then + TOR_BROWSER_BUILD=../../../../tor-browser-build +fi + +tor_expert_bundle_aar="$(ls -1td "$TOR_BROWSER_BUILD/out/tor-expert-bundle-aar/"tor-expert-bundle-aar-* | head -1)" +if [ -z "tor_expert_bundle_aar" ]; then + echo "Cannot find Tor Expert Bundle arr artifacts!" + exit 2 +fi + +cp "$tor_expert_bundle_aar"/* app/ + +noscript="$(find "$TOR_BROWSER_BUILD/out/browser" -name 'noscript*.xpi' -print | sort | tail -1)" +mkdir -p "app/src/main/assets/extensions" +if [ -f "$noscript" ]; then + cp "$noscript" "app/src/main/assets/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi" +fi diff --git a/mobile/android/fenix/tools/tba-sign-devbuilds.sh b/mobile/android/fenix/tools/tba-sign-devbuilds.sh new file mode 100755 index 0000000000000000000000000000000000000000..53fc0f8245ff926828c3972b5e195e89e56a23b4 --- /dev/null +++ b/mobile/android/fenix/tools/tba-sign-devbuilds.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +cd "$(dirname $(realpath "$0"))/.." + +if [ -z "$APKSIGNER_ARGS" ]; then + if [ -z "$QA_KEY" ]; then + if [ -z "$TOR_BROWSER_BUILD" ]; then + TOR_BROWSER_BUILD=../../../../tor-browser-build + fi + QA_KEY="$TOR_BROWSER_BUILD/projects/browser/android-qa.keystore" + fi + if [ ! -f "$QA_KEY" ]; then + echo "The QA key has not been found." + echo "Please define either \$QA_KEY with its path, or \$TOR_BROWSER_BUILD with the path to tor-browser-build" + exit 2 + fi + APKSIGNER_ARGS="--ks "$QA_KEY" --ks-key-alias androidqakey --key-pass pass:android --ks-pass pass:android" +fi + +if [ -z "$ANDROID_HOME" ]; then + ANDROID_HOME=~/Android +fi + +function find_tool() { + tool="$(find $ANDROID_HOME -name "$1" | head -1)" + if [ -z "$tool" ]; then + tool=$(which $1) + fi + echo $tool +} + +apksigner="$(find_tool apksigner)" +zipalign="$(find_tool zipalign)" +if [ -z "$apksigner" -o ! -x "$apksigner" -o -z "$zipalign" -o ! -x "$zipalign" ]; then + echo "apksigner or zipalign not found." + echo "Please make sure they are on your \$PATH, or define \$ANDROID_HOME." + exit 3 +fi + +noscript="$(find "$TOR_BROWSER_BUILD/out/browser" -name 'noscript*.xpi' -print | sort | tail -1)" +tmpdir="$(mktemp -d)" +mkdir -p "$tmpdir/assets/extensions" +if [ -f "$noscript" ]; then + cp "$noscript" "$tmpdir/assets/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi" +fi + +sign () { + apk="$(realpath $1)" + out="$apk" + if [ ! -f "$apk" ]; then + return + fi + out="${out/unsigned/signed}" + aligned="$apk" + aligned="${aligned/unsigned/aligned}" + pushd "$tmpdir" > /dev/null + zip -Xr "$apk" assets > /dev/null + popd > /dev/null + rm -f "$aligned" + "$zipalign" -p 4 "$apk" "$aligned" + echo "Signing $out" + "$apksigner" sign --in "$aligned" --out "$out" $APKSIGNER_ARGS +} + +for channel in app/build/outputs/apk/fenix/*; do + for apk in $channel/*-unsigned.apk; do + sign "$apk" + done +done + +rm -rf "$tmpdir" diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index 3a6f4399adc80f7ab271f84e2dc3cfd5914c954c..8e5eebbf0344b9d05571f80a3fb5ecdb75967d7f 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -896,6 +896,8 @@ package org.mozilla.geckoview { method public boolean getRemoteDebuggingEnabled(); method @Nullable public GeckoRuntime getRuntime(); method @Nullable public Rect getScreenSizeOverride(); + method public boolean getSpoofEnglish(); + method public int getTorSecurityLevel(); method public boolean getTranslationsOfferPopup(); method @NonNull public String getTrustedRecursiveResolverUri(); method public int getTrustedRecusiveResolverMode(); @@ -931,6 +933,8 @@ package org.mozilla.geckoview { method @NonNull public GeckoRuntimeSettings setLoginAutofillEnabled(boolean); method @NonNull public GeckoRuntimeSettings setPreferredColorScheme(int); method @NonNull public GeckoRuntimeSettings setRemoteDebuggingEnabled(boolean); + method @NonNull public GeckoRuntimeSettings setSpoofEnglish(boolean); + method @NonNull public GeckoRuntimeSettings setTorSecurityLevel(int); method @NonNull public GeckoRuntimeSettings setTranslationsOfferPopup(boolean); method @NonNull public GeckoRuntimeSettings setTrustedRecursiveResolverMode(int); method @NonNull public GeckoRuntimeSettings setTrustedRecursiveResolverUri(@NonNull String); @@ -990,6 +994,8 @@ package org.mozilla.geckoview { method @NonNull public GeckoRuntimeSettings.Builder preferredColorScheme(int); method @NonNull public GeckoRuntimeSettings.Builder remoteDebuggingEnabled(boolean); method @NonNull public GeckoRuntimeSettings.Builder screenSizeOverride(int, int); + method @NonNull public GeckoRuntimeSettings.Builder spoofEnglish(boolean); + method @NonNull public GeckoRuntimeSettings.Builder torSecurityLevel(int); method @NonNull public GeckoRuntimeSettings.Builder translationsOfferPopup(boolean); method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverMode(int); method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverUri(@NonNull String); diff --git a/mobile/android/geckoview/build.gradle b/mobile/android/geckoview/build.gradle index 85d1e04fd5d3c936e999829c77169e3ad9e21db4..c2b2ba44d50b4b642f80a8ae992293d1d003ed26 100644 --- a/mobile/android/geckoview/build.gradle +++ b/mobile/android/geckoview/build.gradle @@ -43,6 +43,7 @@ android { buildConfigField 'String', "MOZ_APP_DISPLAYNAME", "\"${mozconfig.substs.MOZ_APP_DISPLAYNAME}\""; buildConfigField 'String', "MOZ_APP_UA_NAME", "\"${mozconfig.substs.MOZ_APP_UA_NAME}\""; buildConfigField 'String', "MOZ_UPDATE_CHANNEL", "\"${mozconfig.substs.MOZ_UPDATE_CHANNEL}\""; + buildConfigField 'boolean', "TOR_BROWSER", mozconfig.substs.TOR_BROWSER ? 'true' : 'false'; // MOZILLA_VERSION is oddly quoted from autoconf, but we don't have to handle it specially in Gradle. buildConfigField 'String', "MOZILLA_VERSION", "\"${mozconfig.substs.MOZILLA_VERSION}\""; diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt deleted file mode 100644 index 7e1f8b127542b620050e1ca4c4b11e838641c94c..0000000000000000000000000000000000000000 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -package org.mozilla.geckoview.test - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.webrtc.CameraEnumerationAndroid.CaptureFormat -import org.webrtc.CameraEnumerator -import org.webrtc.CameraVideoCapturer -import org.webrtc.CameraVideoCapturer.CameraEventsHandler -import org.webrtc.videoengine.VideoCaptureAndroid - -@RunWith(AndroidJUnit4::class) -@SmallTest -class VideoCaptureTest { - // Always throw exception. - class BadCameraEnumerator : CameraEnumerator { - override fun getDeviceNames(): Array<String?>? { - throw java.lang.RuntimeException("") - } - - override fun isFrontFacing(deviceName: String?): Boolean { - throw java.lang.RuntimeException("") - } - - override fun isBackFacing(deviceName: String?): Boolean { - throw java.lang.RuntimeException("") - } - - override fun isInfrared(deviceName: String?): Boolean { - throw java.lang.RuntimeException("") - } - - override fun getSupportedFormats(deviceName: String?): List<CaptureFormat?>? { - throw java.lang.RuntimeException("") - } - - override fun createCapturer( - deviceName: String?, - eventsHandler: CameraEventsHandler?, - ): CameraVideoCapturer? { - throw java.lang.RuntimeException("") - } - } - - @Test - fun constructWithBadEnumerator() { - val ctr = VideoCaptureAndroid::class.java.getDeclaredConstructors()[0].apply { isAccessible = true } - val capture = ctr.newInstance( - InstrumentationRegistry.getInstrumentation().targetContext, - "my camera", - BadCameraEnumerator(), - ) as VideoCaptureAndroid - assertEquals(false, capture.canCapture()) - } -} diff --git a/mobile/android/geckoview/src/main/AndroidManifest.xml b/mobile/android/geckoview/src/main/AndroidManifest.xml index 65458e004d5cea4b9306893344e2b009da0c6172..664dbdee4a7f338efca6514e86da633b47782a0e 100644 --- a/mobile/android/geckoview/src/main/AndroidManifest.xml +++ b/mobile/android/geckoview/src/main/AndroidManifest.xml @@ -5,21 +5,33 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android"> +<!--#ifdef MOZ_ANDROID_NETWORK_STATE--> + <!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + --> +<!--#endif--> <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> +<!--#ifdef MOZ_ANDROID_LOCATION--> + <!-- <uses-feature android:name="android.hardware.location" android:required="false"/> <uses-feature android:name="android.hardware.location.gps" android:required="false"/> + --> +<!--#endif--> <uses-feature android:name="android.hardware.touchscreen" android:required="false"/> +<!--#ifdef MOZ_WEBRTC--> + <!-- TODO preprocess AndroidManifest.xml so that we can + conditionally include WebRTC permissions based on MOZ_WEBRTC. --> + <!-- <uses-feature android:name="android.hardware.camera" android:required="false"/> @@ -36,6 +48,8 @@ <uses-feature android:name="android.hardware.camera.any" android:required="false"/> + --> +<!--#endif--> <!-- GeckoView requires OpenGL ES 2.0 --> <uses-feature diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java index 9d098a303f4ebd334f5a1b652b9f8535b9275007..95b184084f43602e7b923002339f77ea3fe9225b 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java @@ -526,55 +526,7 @@ public class GeckoMediaDrmBridgeV21 implements GeckoMediaDrm { @Override protected Void doInBackground(final Void... params) { - HttpURLConnection urlConnection = null; - BufferedReader in = null; - try { - final URI finalURI = - new URI(mURL + "&signedRequest=" + URLEncoder.encode(new String(mDrmRequest), "UTF-8")); - urlConnection = (HttpURLConnection) ProxySelector.openConnectionWithProxy(finalURI); - urlConnection.setRequestMethod("POST"); - if (DEBUG) Log.d(LOGTAG, "Provisioning, posting url =" + finalURI.toString()); - - // Add data - urlConnection.setRequestProperty("Accept", "*/*"); - urlConnection.setRequestProperty("User-Agent", getCDMUserAgent()); - urlConnection.setRequestProperty("Content-Type", "application/json"); - - // Execute HTTP Post Request - urlConnection.connect(); - - final int responseCode = urlConnection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { - in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), UTF_8)); - String inputLine; - final StringBuffer response = new StringBuffer(); - - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - in.close(); - mResponseBody = String.valueOf(response).getBytes(UTF_8); - if (DEBUG) Log.d(LOGTAG, "Provisioning, response received."); - if (mResponseBody != null) Log.d(LOGTAG, "response length=" + mResponseBody.length); - } else { - Log.d(LOGTAG, "Provisioning, server returned HTTP error code :" + responseCode); - } - } catch (final IOException e) { - Log.e(LOGTAG, "Got exception during posting provisioning request ...", e); - } catch (final URISyntaxException e) { - Log.e(LOGTAG, "Got exception during creating uri ...", e); - } finally { - if (urlConnection != null) { - urlConnection.disconnect(); - } - try { - if (in != null) { - in.close(); - } - } catch (final IOException e) { - Log.e(LOGTAG, "Exception during closing in ...", e); - } - } + Log.i(LOGTAG, "This is Tor Browser. Skipping."); return null; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java index 2fb4015f4126f7c9201a64a9892b7c9383e55be3..503cc421743e81f12b5a7363d9fa79029b30d20d 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java @@ -29,16 +29,19 @@ import java.util.List; public class ProxySelector { public static URLConnection openConnectionWithProxy(final URI uri) throws IOException { - final java.net.ProxySelector ps = java.net.ProxySelector.getDefault(); - Proxy proxy = Proxy.NO_PROXY; - if (ps != null) { - final List<Proxy> proxies = ps.select(uri); - if (proxies != null && !proxies.isEmpty()) { - proxy = proxies.get(0); - } - } - - return uri.toURL().openConnection(proxy); + // tor-browser#42660: This should not be used: it cannot safely get tor configs so would be a + // proxy bypass risk. + throw new IOException("openConnectionWithProxy disabled by tb-42660"); + // final java.net.ProxySelector ps = java.net.ProxySelector.getDefault(); + // Proxy proxy = Proxy.NO_PROXY; + // if (ps != null) { + // final List<Proxy> proxies = ps.select(uri); + // if (proxies != null && !proxies.isEmpty()) { + // proxy = proxies.get(0); + // } + // } + // + // return uri.toURL().openConnection(proxy); } public ProxySelector() {} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java index 84182207dbbb0c38d923c76d6b6c352ba54d7907..3493d8b334489da3a009c3a03c240277d44a74de 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java @@ -169,6 +169,11 @@ public class CrashReporter { @NonNull final File minidumpFile, @NonNull final JSONObject extras) throws IOException, URISyntaxException { + // tor-browser#42660: makeing a NOP + if (true) { + return GeckoResult.fromValue("0"); + } + Log.d(LOGTAG, "Sending crash report: " + minidumpFile.getPath()); HttpURLConnection conn = null; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java index e1e82a492d4409300d1f3e775b091ab7c0cfcd88..c857a095e0b92c0d3f036afed5515bb9139e90fb 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java @@ -178,7 +178,11 @@ public final class GeckoRuntime implements Parcelable { GeckoAppShell.resumeLocation(); // Monitor network status and send change notifications to Gecko // while active. - GeckoNetworkManager.getInstance().start(GeckoAppShell.getApplicationContext()); + if (!BuildConfig.TOR_BROWSER) { + GeckoNetworkManager.getInstance().start(GeckoAppShell.getApplicationContext()); + } else { + Log.d(LOGTAG, "Tor Browser: skip GeckoNetworkManager startup"); + } // Set settings that may have changed between last app opening GeckoAppShell.setIs24HourFormat( @@ -192,7 +196,9 @@ public final class GeckoRuntime implements Parcelable { // Pause listening for locations when in background GeckoAppShell.pauseLocation(); // Stop monitoring network status while inactive. - GeckoNetworkManager.getInstance().stop(); + if (!BuildConfig.TOR_BROWSER) { + GeckoNetworkManager.getInstance().stop(); + } GeckoThread.onPause(); } } @@ -238,6 +244,8 @@ public final class GeckoRuntime implements Parcelable { private final ProfilerController mProfilerController; private final GeckoScreenChangeListener mScreenChangeListener; + private TorIntegrationAndroid mTorIntegration; + private GeckoRuntime() { mWebExtensionController = new WebExtensionController(this); mContentBlockingController = new ContentBlockingController(); @@ -487,6 +495,8 @@ public final class GeckoRuntime implements Parcelable { mScreenChangeListener.enable(); } + mTorIntegration = new TorIntegrationAndroid(context); + mProfilerController.addMarker( "GeckoView Initialization START", mProfilerController.getProfilerTime()); return true; @@ -597,6 +607,10 @@ public final class GeckoRuntime implements Parcelable { mScreenChangeListener.disable(); } + if (mTorIntegration != null) { + mTorIntegration.shutdown(); + } + GeckoThread.forceQuit(); } @@ -997,6 +1011,14 @@ public final class GeckoRuntime implements Parcelable { return mPushController; } + /** + * Get the Tor integration controller for this runtime. + */ + @UiThread + public @NonNull TorIntegrationAndroid getTorIntegrationController() { + return mTorIntegration; + } + /** * Appends notes to crash report. * diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java index df7ef4dbcc6215a2dddf1489e1e8dc49b456921d..8f36ac21b14e2174c142d635070307041bd15adc 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -22,7 +22,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.LinkedHashMap; +import java.util.Collection; +import java.util.HashMap; import java.util.Locale; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.GeckoSystemStateListener; @@ -576,6 +577,38 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { getSettings().setLargeKeepaliveFactor(factor); return this; } + + public @NonNull Builder supportedLocales(final Collection<String> locales) { + getSettings().mSupportedLocales.clear(); + for (String tag : locales) { + Locale locale = Locale.forLanguageTag(tag); + getSettings().mSupportedLocales.put(locale, locale); + getSettings().mSupportedLocales.put(new Locale(locale.getLanguage()), locale); + } + return this; + } + + /** + * Sets whether we should spoof locale to English for webpages. + * + * @param flag True if we should spoof locale to English for webpages, false otherwise. + * @return This Builder instance. + */ + public @NonNull Builder spoofEnglish(final boolean flag) { + getSettings().mSpoofEnglish.set(flag ? 2 : 1); + return this; + } + + /** + * Set security level. + * + * @param level A value determining the security level. Default is 0. + * @return This Builder instance. + */ + public @NonNull Builder torSecurityLevel(final int level) { + getSettings().mSecurityLevel.set(level); + return this; + } } private GeckoRuntime mRuntime; @@ -659,6 +692,9 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { new Pref<>("toolkit.telemetry.user_characteristics_ping.current_version", 0); /* package */ PrefWithoutDefault<Boolean> mDisableShip = new PrefWithoutDefault<Boolean>("fission.disableSessionHistoryInParent"); + /* package */ final Pref<Integer> mSpoofEnglish = new Pref<>("privacy.spoof_english", 0); + /* package */ final Pref<Integer> mSecurityLevel = + new Pref<>("browser.security_level.security_slider", 4); /* package */ int mPreferredColorScheme = COLOR_SCHEME_SYSTEM; @@ -672,6 +708,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { /* package */ Class<? extends Service> mCrashHandler; /* package */ String[] mRequestedLocales; /* package */ ExperimentDelegate mExperimentDelegate; + /* package */ HashMap<Locale, Locale> mSupportedLocales = new HashMap<>(); /** * Attach and commit the settings to the given runtime. @@ -723,6 +760,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { mRequestedLocales = settings.mRequestedLocales; mConfigFilePath = settings.mConfigFilePath; mExperimentDelegate = settings.mExperimentDelegate; + mSupportedLocales = settings.mSupportedLocales; } /* package */ void commit() { @@ -1132,24 +1170,39 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { EventDispatcher.getInstance().dispatch("GeckoView:SetLocale", data); } - private String computeAcceptLanguages() { - final LinkedHashMap<String, String> locales = new LinkedHashMap<>(); + private Locale getLocaleIfSupported(String tag) { + Locale exact = Locale.forLanguageTag(tag); + if (mSupportedLocales.containsKey(exact)) { + return exact; + } + Locale fallback = new Locale(exact.getLanguage()); + return mSupportedLocales.get(fallback); + } - // Explicitly-set app prefs come first: + private String computeAcceptLanguages() { + Locale locale = null; if (mRequestedLocales != null) { - for (final String locale : mRequestedLocales) { - locales.put(locale.toLowerCase(Locale.ROOT), locale); + for (String tag : mRequestedLocales) { + locale = getLocaleIfSupported(tag); + if (locale != null) { + break; + } } } - // OS prefs come second: - for (final String locale : getSystemLocalesForAcceptLanguage()) { - final String localeLowerCase = locale.toLowerCase(Locale.ROOT); - if (!locales.containsKey(localeLowerCase)) { - locales.put(localeLowerCase, locale); + if (locale == null) { + for (final String tag : getSystemLocalesForAcceptLanguage()) { + locale = getLocaleIfSupported(tag); + if (locale != null) { + break; + } } } - - return TextUtils.join(",", locales.values()); + String acceptLanguages = locale != null ? locale.toLanguageTag().replace('_', '-') : "en-US"; + if (acceptLanguages.equals("en-US")) { + // For consistency with spoof English. + acceptLanguages += ", en"; + } + return acceptLanguages; } private static String[] getSystemLocalesForAcceptLanguage() { @@ -1821,6 +1874,46 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return this; } + /** + * Get whether we should spoof locale to English for webpages. + * + * @return Whether we should spoof locale to English for webpages. + */ + public boolean getSpoofEnglish() { + return mSpoofEnglish.get() == 2; + } + + /** + * Set whether we should spoof locale to English for webpages. + * + * @param flag A flag determining whether we should locale to English for webpages. + * @return This GeckoRuntimeSettings instance. + */ + public @NonNull GeckoRuntimeSettings setSpoofEnglish(final boolean flag) { + mSpoofEnglish.commit(flag ? 2 : 1); + return this; + } + + /** + * Gets the current security level. + * + * @return current security protection level + */ + public int getTorSecurityLevel() { + return mSecurityLevel.get(); + } + + /** + * Sets the Security Level. + * + * @param level security protection level + * @return This GeckoRuntimeSettings instance. + */ + public @NonNull GeckoRuntimeSettings setTorSecurityLevel(final int level) { + mSecurityLevel.commit(level); + return this; + } + @Override // Parcelable public void writeToParcel(final Parcel out, final int flags) { super.writeToParcel(out, flags); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index dfb6c145b194cd4b0f3d88819e2dd264ba5624a8..d345ba4f790a520ba9c57c718be4d38da109f066 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -2620,6 +2620,24 @@ public class GeckoSession { return mEventDispatcher.queryBoolean("GeckoView:IsPdfJs"); } + /** + * Try to get last circuit used in this session, if possible. + * + * @return The circuit information as a {@link GeckoResult} object. + */ + @AnyThread + public @NonNull GeckoResult<GeckoBundle> getTorCircuit() { + return mEventDispatcher.queryBundle("GeckoView:GetTorCircuit"); + } + + /** + * Change the circuit for this session. + */ + @UiThread + public void newTorCircuit() { + mEventDispatcher.dispatch("GeckoView:NewTorCircuit", null); + } + /** * Set this GeckoSession as active or inactive, which represents if the session is currently * visible or not. Setting a GeckoSession to inactive will significantly reduce its memory @@ -6320,12 +6338,19 @@ public class GeckoSession { return super.confirm(); } + private static String normalizePath(String input) { + // For an unclear reason, Android media picker delivers file paths + // starting with double slash. Firefox performs path validation on + // all paths, and double slash is deemed invalid. + return input.startsWith("//") ? input.substring(1) : input; + } + private static String getFile(final @NonNull Context context, final @NonNull Uri uri) { if (uri == null) { return null; } if ("file".equals(uri.getScheme())) { - return uri.getPath(); + return normalizePath(uri.getPath()); } final ContentResolver cr = context.getContentResolver(); final Cursor cur = @@ -6347,7 +6372,7 @@ public class GeckoSession { try { final String path = cur.getString(idx); if (path != null && !path.isEmpty()) { - return path; + return normalizePath(path); } } catch (final Exception e) { } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java new file mode 100644 index 0000000000000000000000000000000000000000..d84e9836908223d40f52f1e8eb4beda8d70f9e7c --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java @@ -0,0 +1,722 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * vim: ts=4 sw=4 expandtab: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.geckoview; + +import android.content.Context; +import android.os.AsyncTask; +import android.util.Log; +import androidx.annotation.NonNull; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import org.mozilla.gecko.EventDispatcher; +import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.util.BundleEventListener; +import org.mozilla.gecko.util.EventCallback; +import org.mozilla.gecko.util.GeckoBundle; +import org.mozilla.geckoview.androidlegacysettings.TorLegacyAndroidSettings; + +public class TorIntegrationAndroid implements BundleEventListener { + private static final String TAG = "TorIntegrationAndroid"; + + // Events we listen to + private static final String EVENT_TOR_START = "GeckoView:Tor:StartTor"; + private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor"; + private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek"; + private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek"; + private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; + private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError"; + private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress"; + private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete"; + private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs"; + private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady"; + private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged"; + + // Events we emit + private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet"; + private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet"; + private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin"; + private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto"; + private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel"; + private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState"; + + private static final String CONTROL_PORT_FILE = "/control-ipc"; + private static final String SOCKS_FILE = "/socks-ipc"; + private static final String COOKIE_AUTH_FILE = "/auth-file"; + + private final String mLibraryDir; + private final String mCacheDir; + private final String mIpcDirectory; + private final File mDataDir; + + private TorProcess mTorProcess = null; + + /** + * The first time we run a Tor process in this session, we copy some configuration files to be + * sure we always have the latest version, but if we re-launch a tor process we do not need to + * copy them again. + */ + private boolean mCopiedConfigFiles = false; + + /** + * Allow multiple proxies to be started, even though it might not actually happen. The key should + * be positive (also 0 is not allowed). + */ + private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>(); + + private int mMeekCounter; + + /** + * mSettings is a Java-side copy of the authoritative settings in the JS code. It's useful to + * maintain as the UI may be fetching these options often and we don't watch each fetch to be a + * passthrough to JS with marshalling/unmarshalling each time. + */ + private TorSettings mSettings = null; + + /* package */ TorIntegrationAndroid(Context context) { + mLibraryDir = context.getApplicationInfo().nativeLibraryDir; + mCacheDir = context.getCacheDir().getAbsolutePath(); + mIpcDirectory = mCacheDir + "/tor-private"; + mDataDir = new File(context.getFilesDir(), "tor"); + registerListener(); + } + + /* package */ synchronized void shutdown() { + // FIXME: It seems this never gets called + if (mTorProcess != null) { + mTorProcess.shutdown(); + mTorProcess = null; + } + } + + private void registerListener() { + EventDispatcher.getInstance() + .registerUiThreadListener( + this, + EVENT_TOR_START, + EVENT_MEEK_START, + EVENT_MEEK_STOP, + EVENT_SETTINGS_READY, + EVENT_SETTINGS_CHANGED, + EVENT_CONNECT_STATE_CHANGED, + EVENT_CONNECT_ERROR, + EVENT_BOOTSTRAP_PROGRESS, + EVENT_BOOTSTRAP_COMPLETE, + EVENT_TOR_LOGS); + } + + @Override // BundleEventListener + public synchronized void handleMessage( + final String event, final GeckoBundle message, final EventCallback callback) { + if (EVENT_TOR_START.equals(event)) { + startDaemon(message, callback); + } else if (EVENT_TOR_STOP.equals(event)) { + stopDaemon(message, callback); + } else if (EVENT_MEEK_START.equals(event)) { + startMeek(message, callback); + } else if (EVENT_MEEK_STOP.equals(event)) { + stopMeek(message, callback); + } else if (EVENT_SETTINGS_READY.equals(event)) { + try { + new SettingsLoader().execute(message); + } catch (Exception e) { + Log.e(TAG, "SettingsLoader error: " + e.toString()); + } + } else if (EVENT_SETTINGS_CHANGED.equals(event)) { + GeckoBundle newSettings = message.getBundle("settings"); + if (newSettings != null) { + // TODO: Should we notify listeners? + mSettings = new TorSettings(newSettings); + } else { + Log.w(TAG, "Ignoring a settings changed event that did not have the new settings."); + } + } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) { + String state = message.getString("state"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapStateChange(state); + } + } else if (EVENT_CONNECT_ERROR.equals(event)) { + String code = message.getString("code"); + String msg = message.getString("message"); + String phase = message.getString("phase"); + String reason = message.getString("reason"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapError(code, msg, phase, reason); + } + } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) { + double progress = message.getDouble("progress"); + boolean hasWarnings = message.getBoolean("hasWarnings"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapProgress(progress, hasWarnings); + } + } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) { + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapComplete(); + } + } else if (EVENT_TOR_LOGS.equals(event)) { + String msg = message.getString("message"); + String type = message.getString("logType"); + String timestamp = message.getString("timestamp"); + for (TorLogListener listener : mLogListeners) { + listener.onLog(type, msg, timestamp); + } + } + } + + private class SettingsLoader extends AsyncTask<GeckoBundle, Void, TorSettings> { + protected TorSettings doInBackground(GeckoBundle... messages) { + GeckoBundle message = messages[0]; + TorSettings settings; + if (TorLegacyAndroidSettings.unmigrated()) { + settings = TorLegacyAndroidSettings.loadTorSettings(); + } else { + GeckoBundle bundle = message.getBundle("settings"); + settings = new TorSettings(bundle); + } + return settings; + } + + @Override + protected void onPostExecute(TorSettings torSettings) { + mSettings = torSettings; + if (TorLegacyAndroidSettings.unmigrated()) { + setSettings(mSettings); + TorLegacyAndroidSettings.setMigrated(); + } + } + } + + private synchronized void startDaemon(final GeckoBundle message, final EventCallback callback) { + // Let JS generate this to possibly reduce the chance of race conditions. + String handle = message.getString("handle", ""); + if (handle.isEmpty()) { + Log.e(TAG, "Requested to start a tor process without a handle."); + callback.sendError("Expected a handle for the new process."); + return; + } + Log.d(TAG, "Starting the a tor process with handle " + handle); + + TorProcess previousProcess = mTorProcess; + if (previousProcess != null) { + Log.w(TAG, "We still have a running process: " + previousProcess.getHandle()); + } + + boolean tcpSocks = message.getBoolean("tcpSocks", false); + mTorProcess = new TorProcess(handle, tcpSocks); + + GeckoBundle bundle = new GeckoBundle(3); + bundle.putString("controlPortPath", mIpcDirectory + CONTROL_PORT_FILE); + bundle.putString("cookieFilePath", mIpcDirectory + COOKIE_AUTH_FILE); + if (tcpSocks) { + bundle.putInt("socksPort", 0); + } else { + bundle.putString("socksPath", mIpcDirectory + SOCKS_FILE); + } + callback.sendSuccess(bundle); + } + + private synchronized void stopDaemon(final GeckoBundle message, final EventCallback callback) { + if (mTorProcess == null) { + if (callback != null) { + callback.sendSuccess(null); + } + return; + } + String handle = message.getString("handle", ""); + if (!mTorProcess.getHandle().equals(handle)) { + GeckoBundle bundle = new GeckoBundle(1); + bundle.putString( + "error", "The requested process has not been found. It might have already been stopped."); + callback.sendError(bundle); + return; + } + mTorProcess.shutdown(); + mTorProcess = null; + callback.sendSuccess(null); + } + + class TorProcess extends Thread { + private static final String EVENT_TOR_STARTED = "GeckoView:Tor:TorStarted"; + private static final String EVENT_TOR_START_FAILED = "GeckoView:Tor:TorStartFailed"; + private static final String EVENT_TOR_EXITED = "GeckoView:Tor:TorExited"; + private final String mHandle; + private final boolean mTcpSocks; + private Process mProcess = null; + + TorProcess(String handle, boolean tcpSocks) { + mHandle = handle; + mTcpSocks = tcpSocks; + setName("tor-process-" + handle); + start(); + } + + @Override + public void run() { + cleanIpcDirectory(); + + final String ipcDir = TorIntegrationAndroid.this.mIpcDirectory; + final ArrayList<String> args = new ArrayList<>(); + args.add(mLibraryDir + "/libTor.so"); + args.add("DisableNetwork"); + args.add("1"); + args.add("+__ControlPort"); + args.add("unix:" + ipcDir + CONTROL_PORT_FILE); + final String socksFlags = " IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"; + args.add("+__SocksPort"); + args.add("unix:" + ipcDir + SOCKS_FILE + socksFlags); + if (mTcpSocks) { + args.add("+__SocksPort"); + args.add("auto " + socksFlags); + } + args.add("CookieAuthentication"); + args.add("1"); + args.add("CookieAuthFile"); + args.add(ipcDir + COOKIE_AUTH_FILE); + args.add("DataDirectory"); + args.add(mDataDir.getAbsolutePath()); + boolean copied = true; + try { + copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args); + } catch (IOException e) { + Log.w( + TAG, "torrc-default cannot be created, pluggable transports will not be available", e); + copied = false; + } + // tor-browser#42607: For now we do not ship geoip databases, as we + // do not have the circuit display functionality and they allow us + // to save some space in the final APK. + /*try { + copyAndUseConfigFile("GeoIPFile", "geoip", args); + copyAndUseConfigFile("GeoIPv6File", "geoip6", args); + } catch (IOException e) { + Log.w(TAG, "GeoIP files cannot be created, this feature will not be available.", e); + copied = false; + }*/ + mCopiedConfigFiles = copied; + + Log.d(TAG, "Starting tor with the follwing args: " + args.toString()); + final ProcessBuilder builder = new ProcessBuilder(args); + builder.directory(new File(mLibraryDir)); + try { + mProcess = builder.start(); + } catch (IOException e) { + Log.e(TAG, "Cannot start tor " + mHandle, e); + final GeckoBundle data = new GeckoBundle(2); + data.putString("handle", mHandle); + data.putString("error", e.getMessage()); + EventDispatcher.getInstance().dispatch(EVENT_TOR_START_FAILED, data); + return; + } + Log.i(TAG, "Tor process " + mHandle + " started."); + { + final GeckoBundle data = new GeckoBundle(1); + data.putString("handle", mHandle); + EventDispatcher.getInstance().dispatch(EVENT_TOR_STARTED, data); + } + try { + BufferedReader reader = + new BufferedReader(new InputStreamReader(mProcess.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.i(TAG, "[tor-" + mHandle + "] " + line); + } + } catch (IOException e) { + Log.e(TAG, "Failed to read stdout of the tor process " + mHandle, e); + } + Log.d(TAG, "Exiting the stdout loop for process " + mHandle); + final GeckoBundle data = new GeckoBundle(2); + data.putString("handle", mHandle); + try { + data.putInt("status", mProcess.waitFor()); + } catch (InterruptedException e) { + Log.e(TAG, "Failed to wait for the tor process " + mHandle, e); + data.putInt("status", 0xdeadbeef); + } + // FIXME: We usually don't reach this when the application is killed! + // So, we don't do our cleanup. + Log.i(TAG, "Tor process " + mHandle + " has exited."); + EventDispatcher.getInstance().dispatch(EVENT_TOR_EXITED, data); + } + + private void cleanIpcDirectory() { + File directory = new File(TorIntegrationAndroid.this.mIpcDirectory); + if (!directory.isDirectory()) { + if (!directory.mkdirs()) { + Log.e(TAG, "Failed to create the IPC directory."); + return; + } + try { + // First remove the permissions for everybody... + directory.setReadable(false, false); + directory.setWritable(false, false); + directory.setExecutable(false, false); + // ... then add them back, but only for the owner. + directory.setReadable(true, true); + directory.setWritable(true, true); + directory.setExecutable(true, true); + } catch (SecurityException e) { + Log.e(TAG, "Could not set the permissions to the IPC directory.", e); + } + return; + } + // We assume we do not have child directories, only files + File[] maybeFiles = directory.listFiles(); + if (maybeFiles != null) { + for (File file : maybeFiles) { + if (!file.delete()) { + Log.d(TAG, "Could not delete " + file); + } + } + } + } + + private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) + throws IOException { + File file = copyConfigFile(name); + args.add(option); + args.add(file.getAbsolutePath()); + } + + private File copyConfigFile(String name) throws IOException { + final File file = new File(mCacheDir, name); + if (mCopiedConfigFiles && file.exists()) { + return file; + } + + final Context context = GeckoAppShell.getApplicationContext(); + final InputStream in = context.getAssets().open("common/" + name); + // Files.copy is API 26+, so use java.io and a loop for now. + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + } catch (IOException e) { + in.close(); + throw e; + } + try { + byte buffer[] = new byte[4096]; + int read; + while ((read = in.read(buffer)) >= 0) { + out.write(buffer, 0, read); + } + } finally { + try { + in.close(); + } catch (IOException e) { + Log.w(TAG, "Cannot close the input stream for " + name); + } + try { + out.close(); + } catch (IOException e) { + Log.w(TAG, "Cannot close the output stream for " + name); + } + } + return file; + } + + public void shutdown() { + if (mProcess != null && mProcess.isAlive()) { + mProcess.destroy(); + } + if (isAlive()) { + try { + join(); + } catch (InterruptedException e) { + Log.e( + TAG, + "Cannot join the thread for tor process " + mHandle + ", possibly already terminated", + e); + } + } + } + + public String getHandle() { + return mHandle; + } + } + + private synchronized void startMeek(final GeckoBundle message, final EventCallback callback) { + if (callback == null) { + Log.e(TAG, "Tried to start Meek without a callback."); + return; + } + mMeekCounter++; + mMeeks.put( + new Integer(mMeekCounter), + new MeekTransport(callback, mMeekCounter, message.getStringArray("arguments"))); + } + + private synchronized void stopMeek(final GeckoBundle message, final EventCallback callback) { + final Integer key = message.getInteger("id"); + final MeekTransport meek = mMeeks.remove(key); + if (meek != null) { + meek.shutdown(); + } + if (callback != null) { + callback.sendSuccess(null); + } + } + + private class MeekTransport extends Thread { + private static final String TRANSPORT = "meek_lite"; + private Process mProcess; + private final EventCallback mCallback; + private final int mId; + + MeekTransport(final EventCallback callback, int id, String[] args) { + setName("meek-" + id); + + final String command = mLibraryDir + "/libObfs4proxy.so"; + ArrayList<String> argList = new ArrayList<String>(); + argList.add(command); + if (args != null && args.length > 0) { + // Normally not used, but it helps to debug only by editing JS. + Log.d(TAG, "Requested custom arguments for meek: " + String.join(" ", args)); + argList.addAll(Arrays.asList(args)); + } + final ProcessBuilder builder = new ProcessBuilder(argList); + + File ptStateDir = new File(mDataDir, "pt_state"); + Log.d(TAG, "Using " + ptStateDir.getAbsolutePath() + " as a state directory for meek."); + final Map<String, String> env = builder.environment(); + env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1"); + env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath()); + env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1"); + env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT); + + mCallback = callback; + mId = id; + try { + // We expect this process to be short-lived, therefore we do not bother with + // implementing this as a service. + mProcess = builder.start(); + } catch (IOException e) { + Log.e(TAG, "Cannot start the PT", e); + callback.sendError(e.getMessage()); + return; + } + start(); + } + + /** + * Parse the standard output of the pluggable transport to find the hostname and port it is + * listening on. + * + * <p>See also the specs for the IPC protocol at https://spec.torproject.org/pt-spec/ipc.html. + */ + @Override + public void run() { + final String PROTOCOL_VERSION = "1"; + String hostname = ""; + boolean valid = false; + int port = 0; + String error = "Did not see a CMETHOD"; + try { + InputStreamReader isr = new InputStreamReader(mProcess.getInputStream()); + BufferedReader reader = new BufferedReader(isr); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + Log.d(TAG, "Meek line: " + line); + // Split produces always at least one item + String[] tokens = line.split(" "); + if ("VERSION".equals(tokens[0]) + && (tokens.length != 2 || !PROTOCOL_VERSION.equals(tokens[1]))) { + error = "Bad version: " + line; + break; + } + if ("CMETHOD".equals(tokens[0])) { + if (tokens.length != 4) { + error = "Bad number of tokens in CMETHOD: " + line; + break; + } + if (!tokens[1].equals(TRANSPORT)) { + error = "Unexpected transport: " + tokens[1]; + break; + } + if (!"socks5".equals(tokens[2])) { + error = "Unexpected proxy type: " + tokens[2]; + break; + } + String[] addr = tokens[3].split(":"); + if (addr.length != 2) { + error = "Invalid address"; + break; + } + hostname = addr[0]; + try { + port = Integer.parseInt(addr[1]); + } catch (NumberFormatException e) { + error = "Invalid port: " + e.getMessage(); + break; + } + if (port < 1 || port > 65535) { + error = "Invalid port: out of bounds"; + break; + } + valid = true; + break; + } + if (tokens[0].endsWith("-ERROR")) { + error = "Seen an error: " + line; + break; + } + } + } catch (Exception e) { + error = e.getMessage(); + } + if (valid) { + Log.d(TAG, "Setup a meek transport " + mId + ": " + hostname + ":" + port); + final GeckoBundle bundle = new GeckoBundle(3); + bundle.putInt("id", mId); + bundle.putString("address", hostname); + bundle.putInt("port", port); + mCallback.sendSuccess(bundle); + } else { + Log.e(TAG, "Failed to get a usable config from the PT: " + error); + mCallback.sendError(error); + return; + } + dumpStdout(); + } + + void shutdown() { + if (mProcess != null) { + Log.i(TAG, "Shutting down meek process " + mId); + mProcess.destroy(); + mProcess = null; + } else { + Log.w( + TAG, + "Shutdown request on the meek process " + mId + " that has already been shutdown."); + } + try { + join(); + } catch (InterruptedException e) { + Log.e(TAG, "Could not join the meek thread", e); + } + } + + void dumpStdout() { + try { + BufferedReader reader = + new BufferedReader(new InputStreamReader(mProcess.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.d(TAG, "[meek-" + mId + "] " + line); + } + } catch (InterruptedIOException e) { + // This happens normally, do not log it. + } catch (IOException e) { + Log.e(TAG, "Failed to read stdout of the meek process process " + mId, e); + } + } + } + + public interface BootstrapStateChangeListener { + void onBootstrapStateChange(String state); + + void onBootstrapProgress(double progress, boolean hasWarnings); + + void onBootstrapComplete(); + + void onBootstrapError(String code, String message, String phase, String reason); + } + + public interface TorLogListener { + void onLog(String logType, String message, String timestamp); + } + + private @NonNull void reloadSettings() { + EventDispatcher.getInstance() + .queryBundle(EVENT_SETTINGS_GET) + .then( + new GeckoResult.OnValueListener<GeckoBundle, Void>() { + public GeckoResult<Void> onValue(final GeckoBundle bundle) { + mSettings = new TorSettings(bundle); + return new GeckoResult<Void>(); + } + }); + } + + public TorSettings getSettings() { + return mSettings; + } + + public void setSettings(final TorSettings settings) { + mSettings = settings; + + emitSetSettings(settings) + .then( + new GeckoResult.OnValueListener<Void, Void>() { + public GeckoResult<Void> onValue(Void v) { + return new GeckoResult<Void>(); + } + }, + new GeckoResult.OnExceptionListener<Void>() { + public GeckoResult<Void> onException(final Throwable e) { + Log.e(TAG, "Failed to set settings", e); + reloadSettings(); + return new GeckoResult<Void>(); + } + }); + } + + private @NonNull GeckoResult<Void> emitSetSettings( + final TorSettings settings) { + GeckoBundle bundle = new GeckoBundle(1); + bundle.putBundle("settings", settings.asGeckoBundle()); + return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle); + } + + public @NonNull GeckoResult<Void> beginBootstrap() { + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN); + } + + public @NonNull GeckoResult<Void> beginAutoBootstrap(final String countryCode) { + final GeckoBundle bundle = new GeckoBundle(1); + bundle.putString("countryCode", countryCode); + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN_AUTO, bundle); + } + + public @NonNull GeckoResult<Void> beginAutoBootstrap() { + return beginAutoBootstrap(null); + } + + public @NonNull GeckoResult<Void> cancelBootstrap() { + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL); + } + + public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) { + mBootstrapStateListeners.add(listener); + } + + public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) { + mBootstrapStateListeners.remove(listener); + } + + private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>(); + + public void registerLogListener(TorLogListener listener) { + mLogListeners.add(listener); + } + + public void unregisterLogListener(TorLogListener listener) { + mLogListeners.remove(listener); + } + + private final HashSet<TorLogListener> mLogListeners = new HashSet<>(); +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..e1a2fe93af382e1121a414eeaba546d7f03fdf9f --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java @@ -0,0 +1,192 @@ +package org.mozilla.geckoview; + +import android.util.Log; +import org.mozilla.gecko.util.GeckoBundle; + +public class TorSettings { + + public enum BridgeSource { + Invalid(-1), + BuiltIn(0), + BridgeDB(1), + UserProvided(2); + + private int source; + + BridgeSource(final int source) { + this.source = source; + } + + public static BridgeSource fromInt(int i) { + switch (i) { + case -1: + return Invalid; + case 0: + return BuiltIn; + case 1: + return BridgeDB; + case 2: + return UserProvided; + } + return Invalid; + } + + public int toInt() { + return this.source; + } + } + + public enum ProxyType { + Invalid(-1), + Socks4(0), + Socks5(1), + HTTPS(2); + + private int type; + + ProxyType(final int type) { + this.type = type; + } + + public int toInt() { + return type; + } + + public static ProxyType fromInt(int i) { + switch (i) { + case -1: + return Invalid; + case 0: + return Socks4; + case 1: + return Socks5; + case 2: + return HTTPS; + } + return Invalid; + } + } + + public enum BridgeBuiltinType { + /* TorSettings.sys.mjs ~ln43: string: obfs4|meek-azure|snowflake|etc */ + Invalid("invalid"), + Obfs4("obfs4"), + MeekAzure("meek-azure"), + Snowflake("snowflake"); + + private String type; + + BridgeBuiltinType(String type) { + this.type = type; + } + + public String toString() { + return type; + } + + public static BridgeBuiltinType fromString(String s) { + switch (s) { + case "obfs4": + return Obfs4; + case "meek-azure": + return MeekAzure; + case "snowflake": + return Snowflake; + } + return Invalid; + } + } + + private boolean loaded = false; + + public boolean enabled = true; + + public boolean quickstart = false; + + // bridges section + public boolean bridgesEnabled = false; + public BridgeSource bridgesSource = BridgeSource.Invalid; + public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid; + public String[] bridgeBridgeStrings; + + // proxy section + public boolean proxyEnabled = false; + public ProxyType proxyType = ProxyType.Invalid; + public String proxyAddress = ""; + public int proxyPort = 0; + public String proxyUsername = ""; + public String proxyPassword = ""; + + // firewall section + public boolean firewallEnabled = false; + public int[] firewallAllowedPorts; + + public TorSettings() {} + + public TorSettings(GeckoBundle bundle) { + try { + GeckoBundle qs = bundle.getBundle("quickstart"); + GeckoBundle bridges = bundle.getBundle("bridges"); + GeckoBundle proxy = bundle.getBundle("proxy"); + GeckoBundle firewall = bundle.getBundle("firewall"); + + bridgesEnabled = bridges.getBoolean("enabled"); + bridgesSource = BridgeSource.fromInt(bridges.getInt("source")); + bridgesBuiltinType = BridgeBuiltinType.fromString(bridges.getString("builtin_type")); + bridgeBridgeStrings = bridges.getStringArray("bridge_strings"); + + quickstart = qs.getBoolean("enabled"); + + firewallEnabled = firewall.getBoolean("enabled"); + firewallAllowedPorts = firewall.getIntArray("allowed_ports"); + + proxyEnabled = proxy.getBoolean("enabled"); + proxyAddress = proxy.getString("address"); + proxyUsername = proxy.getString("username"); + proxyPassword = proxy.getString("password"); + proxyPort = proxy.getInt("port"); + proxyType = ProxyType.fromInt(proxy.getInt("type")); + + loaded = true; + } catch (Exception e) { + Log.e("TorSettings", "bundle access error: " + e.toString(), e); + } + } + + public GeckoBundle asGeckoBundle() { + GeckoBundle bundle = new GeckoBundle(); + + GeckoBundle qs = new GeckoBundle(); + GeckoBundle bridges = new GeckoBundle(); + GeckoBundle proxy = new GeckoBundle(); + GeckoBundle firewall = new GeckoBundle(); + + bridges.putBoolean("enabled", bridgesEnabled); + bridges.putInt("source", bridgesSource.toInt()); + bridges.putString("builtin_type", bridgesBuiltinType.toString()); + bridges.putStringArray("bridge_strings", bridgeBridgeStrings); + + qs.putBoolean("enabled", quickstart); + + firewall.putBoolean("enabled", firewallEnabled); + firewall.putIntArray("allowed_ports", firewallAllowedPorts); + + proxy.putBoolean("enabled", proxyEnabled); + proxy.putString("address", proxyAddress); + proxy.putString("username", proxyUsername); + proxy.putString("password", proxyPassword); + proxy.putInt("port", proxyPort); + proxy.putInt("type", proxyType.toInt()); + + bundle.putBundle("quickstart", qs); + bundle.putBundle("bridges", bridges); + bundle.putBundle("proxy", proxy); + bundle.putBundle("firewall", firewall); + + return bundle; + } + + public boolean isLoaded() { + return this.loaded; + } +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java index cdc3633a039606cd0eb6ccb81e10a284241c9df1..77484e29bb3df6562874ec05f4dac0bf491dcd6c 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java @@ -1166,6 +1166,27 @@ public class WebExtensionController { }); } + private boolean isBundledExtension(final String extensionId) { + return "{73a6fe31-595d-460b-a920-fcc0f8843232}".equals(extensionId); + } + + private boolean promptBypass(final WebExtension extension, final EventCallback callback) { + // allow bundled extensions, e.g. NoScript, to be installed with no prompt + if (isBundledExtension(extension.id)) { + callback.resolveTo( + GeckoResult.allow().map( + allowOrDeny -> { + final GeckoBundle response = new GeckoBundle(1); + response.putBoolean("allow", true); + return response; + } + ) + ); + return true; + } + return false; + } + private void installPrompt(final GeckoBundle message, final EventCallback callback) { final GeckoBundle extensionBundle = message.getBundle("extension"); if (extensionBundle == null @@ -1181,6 +1202,10 @@ public class WebExtensionController { final WebExtension extension = new WebExtension(mDelegateControllerProvider, extensionBundle); + if (promptBypass(extension, callback)) { + return; + } + if (mPromptDelegate == null) { Log.e( LOGTAG, "Tried to install extension " + extension.id + " but no delegate is registered"); @@ -1220,6 +1245,10 @@ public class WebExtensionController { final WebExtension currentExtension = new WebExtension(mDelegateControllerProvider, currentBundle); + if (promptBypass(currentExtension, callback)) { + return; + } + final WebExtension updatedExtension = new WebExtension(mDelegateControllerProvider, updatedBundle); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java index 30ee5451aa2eb50b53e16ae9230b79094ecf0547..a90953230c921ba81c6c31dccd30fdae35de7a1e 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java @@ -49,6 +49,9 @@ public class WebRequest extends WebMessage { /** The value of the Referer header for this request. */ public final @Nullable String referrer; + /** The value of the origin of this request. */ + public final @Nullable String origin; + @Retention(RetentionPolicy.SOURCE) @IntDef({ CACHE_MODE_DEFAULT, @@ -110,6 +113,7 @@ public class WebRequest extends WebMessage { cacheMode = builder.mCacheMode; referrer = builder.mReferrer; beConservative = builder.mBeConservative; + origin = builder.mOrigin; if (builder.mBody != null) { body = builder.mBody.asReadOnlyBuffer(); @@ -125,6 +129,7 @@ public class WebRequest extends WebMessage { /* package */ int mCacheMode = CACHE_MODE_DEFAULT; /* package */ String mReferrer; /* package */ boolean mBeConservative; + /* package */ String mOrigin; /** * Construct a Builder instance with the specified URI. @@ -235,6 +240,17 @@ public class WebRequest extends WebMessage { return this; } + /** + * Set the origin URI. + * + * @param origin A URI String + * @return This Builder instance. + */ + public @NonNull Builder origin(final @Nullable String origin) { + mOrigin = origin; + return this; + } + /** * @return A {@link WebRequest} constructed with the values from this Builder instance. */ diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java new file mode 100644 index 0000000000000000000000000000000000000000..df40627463691756f4712c049e988e04f79a0788 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java @@ -0,0 +1,69 @@ +package org.mozilla.geckoview.androidlegacysettings; + +import android.content.Context; +import android.content.SharedPreferences; +import java.util.Locale; +import org.mozilla.gecko.GeckoAppShell; + +// tor-android-service utils/Prefs.java + +/* package */ class Prefs { + private static final String PREF_BRIDGES_ENABLED = "pref_bridges_enabled"; + private static final String PREF_BRIDGES_LIST = "pref_bridges_list"; + + private static SharedPreferences prefs; + + // OrbotConstants + private static final String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences"; + + // tor-android-service utils/TorServiceUtil.java + + private static void setContext() { + if (prefs == null) { + prefs = + GeckoAppShell.getApplicationContext() + .getSharedPreferences(PREF_TOR_SHARED_PREFS, Context.MODE_MULTI_PROCESS); + } + } + + public static boolean getBoolean(String key, boolean def) { + setContext(); + return prefs.getBoolean(key, def); + } + + public static void putBoolean(String key, boolean value) { + setContext(); + prefs.edit().putBoolean(key, value).apply(); + } + + public static void putString(String key, String value) { + setContext(); + prefs.edit().putString(key, value).apply(); + } + + public static String getString(String key, String def) { + setContext(); + return prefs.getString(key, def); + } + + public static boolean bridgesEnabled() { + setContext(); + // for Locale.getDefault().getLanguage().equals("fa"), bridges were enabled by default (and + // it was meek). This was a default set in 2019 code, but it is not a good default anymore, + // so we removed the check. + return prefs.getBoolean(PREF_BRIDGES_ENABLED, false); + } + + public static String getBridgesList() { + setContext(); + String list = prefs.getString(PREF_BRIDGES_LIST, ""); + // list might be empty if the default PT was used, so check also if bridges are enabled. + if (list.isEmpty() && prefs.getBoolean(PREF_BRIDGES_ENABLED, false)) { + // Even though the check on the fa locale is not good to enable bridges by default, we + // still check it here, because if the list was empty, it was likely that it was the + // choice for users with this locale. + return (Locale.getDefault().getLanguage().equals("fa")) ? "meek" : "obfs4"; + } + return list; + } +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..6abf64c759c78213c8760a99c805247af654eb86 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java @@ -0,0 +1,74 @@ +package org.mozilla.geckoview.androidlegacysettings; + +import org.mozilla.geckoview.TorSettings; + +public class TorLegacyAndroidSettings { + + private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs"; + + public static boolean unmigrated() { + return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false); + } + + public static void setUnmigrated() { + Prefs.putBoolean(PREF_USE_MOZ_PREFS, false); + } + + public static void setMigrated() { + Prefs.putBoolean(PREF_USE_MOZ_PREFS, true); + } + + public static TorSettings loadTorSettings() { + TorSettings settings = new TorSettings(); + + // always true, tor is enabled in TB + settings.enabled = true; + + // firefox-android disconnected quick start a while ago so it's untracked + settings.quickstart = false; + + settings.bridgesEnabled = Prefs.bridgesEnabled(); + + // tor-android-service CustomTorInstaller.java + /* + BridgesList is an overloaded field, which can cause some confusion. + The list can be: + 1) a filter like obfs4, meek, or snowflake OR + 2) it can be a custom bridge + For (1), we just pass back all bridges, the filter will occur + elsewhere in the library. + For (2) we return the bridge list as a raw stream. + If length is greater than 9, then we know this is a custom bridge + */ + String userDefinedBridgeList = Prefs.getBridgesList(); + boolean userDefinedBridge = userDefinedBridgeList.length() > 9; + // Terrible hack. Must keep in sync with topl::addBridgesFromResources. + if (!userDefinedBridge) { + settings.bridgesSource = TorSettings.BridgeSource.BuiltIn; + switch (userDefinedBridgeList) { + case "obfs4": + case "snowflake": + settings.bridgesBuiltinType = + TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList); + break; + case "meek": + settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure; + break; + default: + settings.bridgesSource = TorSettings.BridgeSource.Invalid; + break; + } + } else { + settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided + settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n"); + } + + // Tor Browser Android doesn't take proxy and firewall settings + settings.proxyEnabled = false; + + settings.firewallEnabled = false; + settings.firewallAllowedPorts = new int[0]; + + return settings; + } +} diff --git a/mobile/android/gradle/with_gecko_binaries.gradle b/mobile/android/gradle/with_gecko_binaries.gradle index 3628c1be4972a7f781b1e73dc039512db14a73a3..c430396bd8bb5e51cab056bb2ca3a07476e35c8f 100644 --- a/mobile/android/gradle/with_gecko_binaries.gradle +++ b/mobile/android/gradle/with_gecko_binaries.gradle @@ -16,7 +16,7 @@ def hasCompileArtifacts() { } ext.configureVariantWithGeckoBinaries = { variant -> - if (hasCompileArtifacts()) { + if (hasCompileArtifacts() || true) { // Local (read, not 'official') builds want to reflect developer changes to // the omnijar sources, and (when compiling) to reflect developer changes to // the native binaries. To do this, the Gradle build calls out to the diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index d330007d561273a2e379553f5705c64f24a3ffb7..76d04fe110a2c54f9d8114830366e6828c8a69ea 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -124,6 +124,13 @@ @BINPATH@/chrome/devtools@JAREXT@ @BINPATH@/chrome/devtools.manifest +; Base Browser +@BINPATH@/components/SecurityLevel.manifest + +; Torbutton +@BINPATH@/chrome/torbutton@JAREXT@ +@BINPATH@/chrome/torbutton.manifest + ; [Default Preferences] ; All the pref files must be part of base to prevent migration bugs #ifndef MOZ_ANDROID_FAT_AAR_ARCHITECTURES @@ -165,6 +172,7 @@ @BINPATH@/res/locale/layout/HtmlForm.properties @BINPATH@/res/locale/layout/MediaDocument.properties @BINPATH@/res/locale/layout/xmlparser.properties +@BINPATH@/res/locale/xslt/xslt.properties @BINPATH@/res/locale/dom/dom.properties #ifndef MOZ_ANDROID_EXCLUDE_FONTS diff --git a/mobile/android/moz.configure b/mobile/android/moz.configure index f9aa14c3a7914dfa3ad1ba50678665cda6a9e862..0f16fa9e0b43af3ee2f3e0bc1371db73e320c280 100644 --- a/mobile/android/moz.configure +++ b/mobile/android/moz.configure @@ -10,10 +10,11 @@ project_flag( default=True, ) +# tor-browser#29859 project_flag( "MOZ_ANDROID_HLS_SUPPORT", help="Enable HLS (HTTP Live Streaming) support (currently using the ExoPlayer library)", - default=True, + default=False, ) option( @@ -58,7 +59,10 @@ option( set_config("MOZ_ANDROID_GECKOVIEW_LITE", True, when="--enable-geckoview-lite") imply_option("MOZ_NORMANDY", False) -imply_option("MOZ_SERVICES_HEALTHREPORT", True) +# Comment this so we can imply |False| in basebrowser.configure +# The Build system doesn't allow multiple imply_option() +# calls with the same key. +# imply_option("MOZ_SERVICES_HEALTHREPORT", True) imply_option("MOZ_GECKOVIEW_HISTORY", True) imply_option("MOZ_APP_UA_NAME", "Firefox") @@ -81,6 +85,8 @@ def check_target(target): ) +include("basebrowser.configure") + include("../../toolkit/moz.configure") include("../../build/moz.configure/android-sdk.configure") include("../../build/moz.configure/java.configure") @@ -98,3 +104,15 @@ set_config( "MOZ_ANDROID_FAT_AAR_ARCHITECTURES", depends("MOZ_ANDROID_FAT_AAR_ARCHITECTURES")(lambda x: x), ) + +project_flag( + "MOZ_ANDROID_NETWORK_STATE", + help="Include permission for accessing WiFi/network state on Android", + default=False, +) + +project_flag( + "MOZ_ANDROID_LOCATION", + help="Include permission for accessing fine and course-grain Location on Android", + default=False, +) diff --git a/mobile/android/shared-settings.gradle b/mobile/android/shared-settings.gradle index 7673720492ab40290a3b29994d09537e82fcfccb..94700deb52bf68ef8249950cf81bcf533d686d4e 100644 --- a/mobile/android/shared-settings.gradle +++ b/mobile/android/shared-settings.gradle @@ -167,7 +167,16 @@ gradle.projectsLoaded { -> rename { 'manifest.json' } into extDir - def values = ['version': getManifestVersionString(rootProject.ext.config.componentsVersion)] + // android-components#40013: overwrite the timestamp in + // extension version to ensure build reproducibility. + def systemEnvBuildDate = System.getenv('MOZ_BUILD_DATE') + // MOZ_BUILD_DATE is in the YYYYMMDDHHMMSS format. Thus, we only use a + // substring of it if it is available. + def values = ['version': rootProject.ext.config.componentsVersion + "." + + (systemEnvBuildDate != null ? + systemEnvBuildDate.substring(4) : + new Date().format('MMddHHmmss'))] + inputs.properties(values) expand(values) } diff --git a/mobile/shared/chrome/geckoview/geckoview.js b/mobile/shared/chrome/geckoview/geckoview.js index d66a57c78ad727586b1dc975a84c69358cce57f4..83d149f18fa51e1ed8f3feaad2facc3c5e685108 100644 --- a/mobile/shared/chrome/geckoview/geckoview.js +++ b/mobile/shared/chrome/geckoview/geckoview.js @@ -21,6 +21,7 @@ ChromeUtils.defineESModuleGetters(this, { InitializationTracker: "resource://gre/modules/GeckoViewTelemetry.sys.mjs", RemoteSecuritySettings: "resource://gre/modules/psm/RemoteSecuritySettings.sys.mjs", + RemoteSettings: "resource://services-settings/remote-settings.sys.mjs", SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs", }); @@ -922,6 +923,10 @@ function startup() { Blocklist.loadBlocklistAsync(); }); + InitLater(() => { + RemoteSettings.pollChanges({ trigger: "timer" }); + }); + // This should always go last, since the idle tasks (except for the ones with // timeouts) should execute in order. Note that this observer notification is // not guaranteed to fire, since the window could close before we get here. diff --git a/mobile/shared/components/geckoview/GeckoViewStartup.sys.mjs b/mobile/shared/components/geckoview/GeckoViewStartup.sys.mjs index 4483941f8e5e4bda3e02165a0737221e62f60cbc..409aaabd96c48c2dd8096a65959eec2525a457f8 100644 --- a/mobile/shared/components/geckoview/GeckoViewStartup.sys.mjs +++ b/mobile/shared/components/geckoview/GeckoViewStartup.sys.mjs @@ -11,6 +11,9 @@ ChromeUtils.defineESModuleGetters(lazy, { ActorManagerParent: "resource://gre/modules/ActorManagerParent.sys.mjs", EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", PdfJs: "resource://pdf.js/PdfJs.sys.mjs", + RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", + TorAndroidIntegration: "resource://gre/modules/TorAndroidIntegration.sys.mjs", + TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", }); const { debug, warn } = GeckoViewUtils.initLogging("Startup"); @@ -258,6 +261,11 @@ export class GeckoViewStartup { "GeckoView:InitialForeground", ]); + this.#migratePreferences(); + + lazy.TorAndroidIntegration.init(); + lazy.TorDomainIsolator.init(); + Services.obs.addObserver(this, "browser-idle-startup-tasks-finished"); Services.obs.addObserver(this, "handlersvc-store-initialized"); @@ -339,6 +347,10 @@ export class GeckoViewStartup { if (aData.requestedLocales) { Services.locale.requestedLocales = aData.requestedLocales; } + lazy.RFPHelper._handleSpoofEnglishChanged(); + if (Services.prefs.getIntPref("privacy.spoof_english", 0) === 2) { + break; + } const pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance( Ci.nsIPrefLocalizedString ); @@ -360,6 +372,50 @@ export class GeckoViewStartup { break; } } + + /** + * This is the equivalent of BrowserGlue._migrateUITBB. + */ + #migratePreferences() { + const MIGRATION_VERSION = 1; + const MIGRATION_PREF = "torbrowser.migration_android.version"; + + // We do not have a way to check for new profiles on Android. + // However, the first version is harmless for new installs, so run it + // anyway. + const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0); + if (currentVersion < 1) { + // First implementation of the migration on Android (tor-browser#43124, + // 14.0a5, September 2024). + const prefToClear = [ + // Old torbutton preferences not used anymore. + // Some of them should have never been set on Android, as on Android we + // force PBM... But who knows about very old profiles. + "browser.cache.disk.enable", + "places.history.enabled", + "security.nocertdb", + "permissions.memory_only", + "extensions.torbutton.loglevel", + "extensions.torbutton.logmethod", + "extensions.torbutton.pref_fixup_version", + "extensions.torbutton.resize_new_windows", + "extensions.torbutton.startup", + "extensions.torlauncher.prompt_for_locale", + "extensions.torlauncher.loglevel", + "extensions.torlauncher.logmethod", + "extensions.torlauncher.torrc_fixup_version", + // tor-browser#42149: Do not change HTTPS-Only settings in the security + // level. + "dom.security.https_only_mode_send_http_background_request", + ]; + for (const pref of prefToClear) { + if (Services.prefs.prefHasUserValue(pref)) { + Services.prefs.clearUserPref(pref); + } + } + } + Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION); + } } GeckoViewStartup.prototype.classID = Components.ID( diff --git a/mobile/shared/modules/geckoview/GeckoViewContent.sys.mjs b/mobile/shared/modules/geckoview/GeckoViewContent.sys.mjs index 35ffb76d90bec01d9f14b3e69ff0f0ac20290af7..79c37fdebdad8cdad0e83bec6fb3bfbcebe09bba 100644 --- a/mobile/shared/modules/geckoview/GeckoViewContent.sys.mjs +++ b/mobile/shared/modules/geckoview/GeckoViewContent.sys.mjs @@ -8,6 +8,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { isProductURL: "chrome://global/content/shopping/ShoppingProduct.mjs", ShoppingProduct: "chrome://global/content/shopping/ShoppingProduct.mjs", + TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", }); export class GeckoViewContent extends GeckoViewModule { @@ -38,6 +39,8 @@ export class GeckoViewContent extends GeckoViewModule { "GeckoView:UpdateInitData", "GeckoView:ZoomToInput", "GeckoView:IsPdfJs", + "GeckoView:GetTorCircuit", + "GeckoView:NewTorCircuit", ]); } @@ -308,6 +311,12 @@ export class GeckoViewContent extends GeckoViewModule { case "GeckoView:HasCookieBannerRuleForBrowsingContextTree": this._hasCookieBannerRuleForBrowsingContextTree(aCallback); break; + case "GeckoView:GetTorCircuit": + this._getTorCircuit(aCallback); + break; + case "GeckoView:NewTorCircuit": + this._newTorCircuit(aCallback); + break; } } @@ -418,6 +427,25 @@ export class GeckoViewContent extends GeckoViewModule { } } + _getTorCircuit(aCallback) { + if (this.browser && aCallback) { + const domain = lazy.TorDomainIsolator.getDomainForBrowser(this.browser); + const nodes = lazy.TorDomainIsolator.getCircuit( + this.browser, + domain, + this.browser.contentPrincipal.originAttributes.userContextId + ); + aCallback?.onSuccess({ domain, nodes }); + } else { + aCallback?.onSuccess(null); + } + } + + _newTorCircuit(aCallback) { + lazy.TorDomainIsolator.newCircuitForBrowser(this.browser); + aCallback?.onSuccess(); + } + async _containsFormData(aCallback) { aCallback.onSuccess(await this.actor.containsFormData()); } diff --git a/mobile/shared/modules/geckoview/GeckoViewProgress.sys.mjs b/mobile/shared/modules/geckoview/GeckoViewProgress.sys.mjs index c00ffd1abea1be394244cb5e191ba8e78746ee90..ca1ea9c6c05a7dfec3d15fdc0897e3bdfd888092 100644 --- a/mobile/shared/modules/geckoview/GeckoViewProgress.sys.mjs +++ b/mobile/shared/modules/geckoview/GeckoViewProgress.sys.mjs @@ -138,6 +138,10 @@ var IdentityHandler = { result.host = uri.host; } + if (!aBrowser.securityUI.secInfo) { + return result; + } + const cert = aBrowser.securityUI.secInfo.serverCert; result.certificate = diff --git a/mobile/shared/modules/geckoview/GeckoViewWebExtension.sys.mjs b/mobile/shared/modules/geckoview/GeckoViewWebExtension.sys.mjs index cde1cf4ff25b52a61d855f91a07b2b5483cc7287..bfb60b9722249f79c7a1f4386804d4df2889f4a5 100644 --- a/mobile/shared/modules/geckoview/GeckoViewWebExtension.sys.mjs +++ b/mobile/shared/modules/geckoview/GeckoViewWebExtension.sys.mjs @@ -354,7 +354,9 @@ async function exportExtension(aAddon, aSourceURI) { disabledFlags.push("appVersionDisabled"); } const baseURL = policy ? policy.getURL() : ""; - const privateBrowsingAllowed = policy ? policy.privateBrowsingAllowed : false; + const privateBrowsingAllowed = policy + ? policy.privateBrowsingAllowed + : lazy.PrivateBrowsingUtils.permanentPrivateBrowsing; let updateDate; try { @@ -509,6 +511,9 @@ class ExtensionInstallListener { async onInstallEnded(aInstall, aAddon) { debug`onInstallEnded addonId=${aAddon.id}`; + if (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) { + await GeckoViewWebExtension.setPrivateBrowsingAllowed(aAddon.id, true); + } const extension = await exportExtension(aAddon, aInstall.sourceURI); this.resolve({ extension }); } diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 9b76f3b66237a4ff2cfc538ff48d199214475d15..2e642a316c21d85e13cc079426fa81b2854bcd91 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -6171,6 +6171,10 @@ static const PrefListEntry sOverrideRestrictionsList[]{ // has it set as a string... PREF_LIST_ENTRY("services.settings.preview_enabled"), PREF_LIST_ENTRY("services.settings.server"), + + // tor-browser#41165, tor-browser!765: leave this static pref in + // gSharedMap to prevent a crash in gpu process in debug builds. + PREF_LIST_ENTRY("browser.urlbar.onionRewrites.enabled"), }; // These prefs are dynamically-named (i.e. not specified in prefs.js or diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index a46fad5c380aec8bc3e1a73113e0566d3e2bb6b1..d16243b3fdf6d39c97922a4638c1be7f409f310e 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -1450,6 +1450,12 @@ value: false mirror: always +# tor-browser#42220 +- name: browser.download.ignore_content_disposition + type: bool + value: true + mirror: always + # See bug 1811830 - name: browser.download.force_save_internally_handled_attachments type: bool @@ -1879,6 +1885,14 @@ value: false mirror: always +# tor-browser#28005, tor-browser#40458: enable .tor.onion aliases by default. +# When they are enabled, the browser will need to refresh the alias lists by +# connecting to third parties periodically. +- name: browser.urlbar.onionRewrites.enabled + type: RelaxedAtomicBool + value: true + mirror: always + - name: browser.viewport.desktopWidth type: RelaxedAtomicInt32 value: 980 diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index da46468600c9198930c2ccdbf6950a305ce59a19..48a714e683b61e669b683c34bd60a212ff2820f0 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3474,6 +3474,8 @@ pref("browser.safebrowsing.downloads.remote.block_uncommon", true); // Android SafeBrowsing's configuration is in ContentBlocking.java, keep in sync. #ifndef MOZ_WIDGET_ANDROID +// tor-browser#42604: safe-browsing is disabled elsewhere, but no reason to ship scary google prefs +#ifndef BASE_BROWSER_VERSION // Google Safe Browsing provider (legacy) pref("browser.safebrowsing.provider.google.pver", "2.2"); pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,googpub-phish-shavar,goog-malware-shavar,goog-unwanted-shavar"); @@ -3497,6 +3499,7 @@ pref("browser.safebrowsing.provider.google4.advisoryURL", "https://developers.go pref("browser.safebrowsing.provider.google4.advisoryName", "Google Safe Browsing"); pref("browser.safebrowsing.provider.google4.dataSharingURL", "https://safebrowsing.googleapis.com/v4/threatHits?$ct=application/x-protobuf&key=%GOOGLE_SAFEBROWSING_API_KEY%&$httpMethod=POST"); pref("browser.safebrowsing.provider.google4.dataSharing.enabled", false); +#endif // ifndef BASE_BROWSER_VERSION #endif // ifndef MOZ_WIDGET_ANDROID @@ -4000,7 +4003,7 @@ pref("devtools.policy.disabled", false); // Enable deprecation warnings. pref("devtools.errorconsole.deprecation_warnings", true); -#ifdef NIGHTLY_BUILD +#if defined(NIGHTLY_BUILD) || defined(TOR_BROWSER_NIGHTLY_BUILD) // Don't show the Browser Toolbox prompt on local builds / nightly. pref("devtools.debugger.prompt-connection", false, sticky); #else diff --git a/moz.configure b/moz.configure index 4c2ce606385b81a43ec3b1a619a4fb46c6b7235a..b20ea887e2de058ba4d668ffdde2a6b9ae671426 100755 --- a/moz.configure +++ b/moz.configure @@ -905,6 +905,63 @@ with only_when(cross_compiling): ) set_config("JS_BINARY", depends_if("JS_BINARY")(lambda value: value[0])) +option( + "--with-relative-data-dir", + nargs=1, + help="Sets the data directories to be relative to the application directory", +) + + +@depends("--with-relative-data-dir", target) +@imports("json") +def relative_data_dir(value, target): + if value and target.os == "Android": + die("--with-relative-data-dir is not supported on Android") + if value: + return json.dumps(value[0]) + + +set_define("RELATIVE_DATA_DIR", relative_data_dir) + + +option( + "--with-base-browser-version", + nargs=1, + help="Set the Base Browser version, e.g., 7.0a1", +) + + +@depends("--with-base-browser-version") +def base_browser_version(value): + if not value: + die( + "--with-base-browser-version is required for Base Browser and derived browsers." + ) + return value[0] + + +@depends("--with-base-browser-version") +def base_browser_version_quoted(value): + if not value: + die( + "--with-base-browser-version is required for Base Browser and derived browsers." + ) + if '"' in value or "\\" in value: + die('--with-base-browser-version cannot contain " or \\.') + return '"{}"'.format(value[0]) + + +set_define("BASE_BROWSER_VERSION", base_browser_version) +set_define("BASE_BROWSER_VERSION_QUOTED", base_browser_version_quoted) + + +# Tor Browser additions. + +# We always want Tor Browser to be defined. Since we do not need any +# value for it, just always set it to True. +set_define("TOR_BROWSER", True) + + # Please do not add configure checks from here on. # Fallthrough to autoconf-based configure diff --git a/mozconfig-android-aarch64 b/mozconfig-android-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..cd03397c13017c3c036756226218d3948f66fc1d --- /dev/null +++ b/mozconfig-android-aarch64 @@ -0,0 +1,4 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser-android + +mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-aarch64-linux-android +ac_add_options --target=aarch64-linux-android diff --git a/mozconfig-android-all b/mozconfig-android-all new file mode 100644 index 0000000000000000000000000000000000000000..5935c2d090c772488013c913c5d8302fa1156046 --- /dev/null +++ b/mozconfig-android-all @@ -0,0 +1,41 @@ +# Changes on this file might need to be synchronized with +# browser/config/mozconfigs/base-browser-android! +# See also tor-browser#43151. + +export MOZILLA_OFFICIAL=1 + +ac_add_options --enable-application=mobile/android + +ac_add_options --disable-compile-environment + +ac_add_options --with-java-bin-path=$JAVA_HOME/bin +ac_add_options --with-android-sdk=$ANDROID_HOME +ac_add_options --with-gradle=$GRADLE_HOME/bin/gradle + +ac_add_options --disable-tests +ac_add_options --disable-debug + +ac_add_options --disable-updater +ac_add_options --disable-crashreporter +ac_add_options --disable-webrtc +ac_add_options --disable-parental-controls + +ac_add_options --enable-proxy-bypass-protection +ac_add_options --disable-system-policies + +# See tor-browser#41131 +ac_add_options --disable-backgroundtasks + +# Disable telemetry +ac_add_options MOZ_TELEMETRY_REPORTING= + +if test -n "$LOCAL_DEV_BUILD"; then + # You must use the "default" bogus channel for dev builds + ac_add_options --enable-update-channel=default + ac_add_options --with-base-browser-version=dev-build + ac_add_options --disable-minify +fi + +if test -z "$WASI_SYSROOT"; then + ac_add_options --without-wasm-sandboxed-libraries +fi diff --git a/mozconfig-android-armv7 b/mozconfig-android-armv7 new file mode 100644 index 0000000000000000000000000000000000000000..fb005a976d12f78a6b13e7738eb1e8f05938fdfc --- /dev/null +++ b/mozconfig-android-armv7 @@ -0,0 +1,4 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser-android + +mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-arm-linux-androideabi +ac_add_options --target=arm-linux-androideabi diff --git a/mozconfig-android-x86 b/mozconfig-android-x86 new file mode 100644 index 0000000000000000000000000000000000000000..9e42962ca222efeab5f6e7818b50783f0fc58ac9 --- /dev/null +++ b/mozconfig-android-x86 @@ -0,0 +1,4 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser-android + +mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-i386-linux-android +ac_add_options --target=i686-linux-android diff --git a/mozconfig-android-x86_64 b/mozconfig-android-x86_64 new file mode 100644 index 0000000000000000000000000000000000000000..7ceece15fcb2ddd6d1d970dd29bdd99a63acb17c --- /dev/null +++ b/mozconfig-android-x86_64 @@ -0,0 +1,4 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser-android + +mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-x86_64-linux-android +ac_add_options --target=x86_64-linux-android diff --git a/mozconfig-linux-aarch64 b/mozconfig-linux-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..247293ba153f714d880ffeb6fe9db987c3ca624b --- /dev/null +++ b/mozconfig-linux-aarch64 @@ -0,0 +1,12 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --target=aarch64-unknown-linux-gnu + +# Moz switched to lld for all Linux targets in Bug 1839739. +ac_add_options --enable-linker=lld + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --enable-default-toolkit=cairo-gtk3 + diff --git a/mozconfig-linux-aarch64-dev b/mozconfig-linux-aarch64-dev new file mode 100644 index 0000000000000000000000000000000000000000..f975b9af2f9acb520624132402d9dd6d7a76c057 --- /dev/null +++ b/mozconfig-linux-aarch64-dev @@ -0,0 +1,20 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +# This mozconfig file is not used in official builds. +# It is only intended to be used when doing incremental Linux builds +# during development. + +# Moz switched to lld for all Linux targets in Bug 1839739. +ac_add_options --enable-linker=lld + +export MOZILLA_OFFICIAL= +export MOZ_APP_REMOTINGNAME="Tor Browser Dev" +ac_add_options --with-branding=browser/branding/tb-nightly + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --with-base-browser-version=dev-build +ac_add_options --disable-base-browser-update diff --git a/mozconfig-linux-arm b/mozconfig-linux-arm new file mode 100644 index 0000000000000000000000000000000000000000..33546709108a74a9d2e577003831868502f1b3c2 --- /dev/null +++ b/mozconfig-linux-arm @@ -0,0 +1,18 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --target=arm-linux-gnueabihf + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +# Bug 31448: ld.gold fails if we don't disable debug-symbols. +# Also, we keep strip enabled. +ac_add_options --disable-debug-symbols + +# From Arch Linux ARM for Firefox 102.0.1 +# https://github.com/archlinuxarm/PKGBUILDs/blob/6da804f4020487c112f59ea067e6644a309c4338/extra/firefox/PKGBUILD +ac_add_options --disable-elf-hack +ac_add_options --disable-av1 +ac_add_options --enable-optimize="-g0 -O2" +# One of the following two lines (not sure which) prevents "read-only segment has dynamic relocations" linker error. +export MOZ_DEBUG_FLAGS=" " +export RUSTFLAGS="-Cdebuginfo=0" diff --git a/mozconfig-linux-i686 b/mozconfig-linux-i686 new file mode 100644 index 0000000000000000000000000000000000000000..0761ecb60c1fbb09c6e6defd6613bfedef273e63 --- /dev/null +++ b/mozconfig-linux-i686 @@ -0,0 +1,16 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --target=i686-linux-gnu + +# Moz switched to lld for all Linux targets in Bug 1839739. +# Also, gold used not to work with debug symbols (tor-browser#42146). +ac_add_options --enable-linker=lld + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + diff --git a/mozconfig-linux-x86_64 b/mozconfig-linux-x86_64 new file mode 100644 index 0000000000000000000000000000000000000000..7d96d5aaa734dc550dd6e33c10bd2691352e796d --- /dev/null +++ b/mozconfig-linux-x86_64 @@ -0,0 +1,13 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +# Moz switched to lld for all Linux targets in Bug 1839739. +ac_add_options --enable-linker=lld + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + diff --git a/mozconfig-linux-x86_64-asan b/mozconfig-linux-x86_64-asan new file mode 100644 index 0000000000000000000000000000000000000000..20a0bf08da8094f0f6a97131486b2551cfa81460 --- /dev/null +++ b/mozconfig-linux-x86_64-asan @@ -0,0 +1,26 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +export CFLAGS="-fsanitize=address -Dxmalloc=myxmalloc" +export CXXFLAGS="-fsanitize=address -Dxmalloc=myxmalloc" +# We need to add -ldl explicitely due to bug 1213698 +export LDFLAGS="-fsanitize=address -ldl" + +# Define HOST_CFLAGS, etc. to avoid compiling programs such as mbsdiff +# (which is part of mar-tools and is not distributed to end-users) with +# ASan. See bug 17858. +export HOST_CFLAGS="" +export HOST_CXXFLAGS="" +export HOST_LDFLAGS="-ldl" + +ac_add_options --enable-address-sanitizer +ac_add_options --disable-jemalloc +ac_add_options --disable-elf-hack + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + diff --git a/mozconfig-linux-x86_64-dev b/mozconfig-linux-x86_64-dev new file mode 100644 index 0000000000000000000000000000000000000000..e55fbe4b5f4fe3eb94a3dca6a25bf08add00db4c --- /dev/null +++ b/mozconfig-linux-x86_64-dev @@ -0,0 +1,23 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +# This mozconfig file is not used in official builds. +# It is only intended to be used when doing incremental Linux builds +# during development. + +# Moz switched to lld for all Linux targets in Bug 1839739. +ac_add_options --enable-linker=lld + +export MOZILLA_OFFICIAL= +export MOZ_APP_REMOTINGNAME="Tor Browser Dev" +ac_add_options --with-branding=browser/branding/tb-nightly + +ac_add_options --enable-default-toolkit=cairo-gtk3 + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --with-base-browser-version=dev-build +ac_add_options --disable-base-browser-update + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme diff --git a/mozconfig-macos b/mozconfig-macos new file mode 100644 index 0000000000000000000000000000000000000000..0f4ad63ae1ff97a6f3d2b5645dcc6715622064cf --- /dev/null +++ b/mozconfig-macos @@ -0,0 +1,14 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --enable-strip + +# See bug #13379 +ac_add_options --enable-nss-mar + +# See bug #41131 +ac_add_options --disable-update-agent + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + +ac_add_options --with-relative-data-dir=../TorBrowser-Data/Browser diff --git a/mozconfig-macos-dev b/mozconfig-macos-dev new file mode 100644 index 0000000000000000000000000000000000000000..03713226651ed5d31d83ebdbad09bdb138c2d3ed --- /dev/null +++ b/mozconfig-macos-dev @@ -0,0 +1,27 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +# This mozconfig file is not used in official builds. +# It is only intended to be used when doing incremental macOS builds +# during development. + +export MOZILLA_OFFICIAL= + +ac_add_options --disable-strip +ac_add_options --disable-install-strip + +ac_add_options --with-base-browser-version=dev-build + +ac_add_options --disable-base-browser-update +# See bug #13379 +ac_add_options --enable-nss-mar +# See bug #41131 +ac_add_options --disable-update-agent + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + +ac_add_options --with-relative-data-dir=../TorBrowser-Data/Browser + +#copied from the diff between mozconfig-linux-x86_64 and mozconfig-linux-x86_64-dev +export MOZ_APP_REMOTINGNAME="Tor Browser Dev" +ac_add_options --with-branding=browser/branding/tb-nightly diff --git a/mozconfig-windows-i686 b/mozconfig-windows-i686 new file mode 100644 index 0000000000000000000000000000000000000000..20547b22b87b297fee9d1ad505d342cddeb3f79e --- /dev/null +++ b/mozconfig-windows-i686 @@ -0,0 +1,25 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --target=i686-w64-mingw32 +ac_add_options --with-toolchain-prefix=i686-w64-mingw32- + +ac_add_options --enable-strip + +# Bits is Background Intelligent Transfer Service +ac_add_options --disable-bits-download +ac_add_options --disable-maintenance-service +ac_add_options --disable-default-browser-agent + +# See bug #13379 +ac_add_options --enable-nss-mar + +# See bug #41131 +ac_add_options --disable-update-agent + +# Bug 1782837: Not supported because Mozilla (and therefore also us) build +# libc++ with LIBCXX_ENABLE_FILESYSTEM disabled. +ac_add_options --disable-notification-server + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + diff --git a/mozconfig-windows-x86_64 b/mozconfig-windows-x86_64 new file mode 100644 index 0000000000000000000000000000000000000000..e40fee4e8737f6a492c74ba3bef9b0cf3dbf8f89 --- /dev/null +++ b/mozconfig-windows-x86_64 @@ -0,0 +1,25 @@ +. $topsrcdir/browser/config/mozconfigs/tor-browser + +ac_add_options --target=x86_64-w64-mingw32 +ac_add_options --with-toolchain-prefix=x86_64-w64-mingw32- + +ac_add_options --enable-strip + +# Bits is Background Intelligent Transfer Service +ac_add_options --disable-bits-download +ac_add_options --disable-maintenance-service +ac_add_options --disable-default-browser-agent + +# See bug #13379 +ac_add_options --enable-nss-mar + +# See bug #41131 +ac_add_options --disable-update-agent + +# Bug 1782837: Not supported because Mozilla (and therefore also us) build +# libc++ with LIBCXX_ENABLE_FILESYSTEM disabled. +ac_add_options --disable-notification-server + +# Let's make sure no preference is enabling either Adobe's or Google's CDM. +ac_add_options --disable-eme + diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 33ccf6cce1bba6040a78d7943703afba2f028584..ce53b4eaab7072180989228f48166b62dbbba3f6 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -3041,7 +3041,8 @@ nsresult NS_ShouldSecureUpgrade( } // If it is a mixed content trustworthy loopback, then we shouldn't upgrade // it. - if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) { + if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI) || + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(aURI)) { aShouldUpgrade = false; return NS_OK; } diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp index b96b33c74265c252644e7d747db142133c200446..a8f226050f32b7b09f3a296435dbfb2afcc3da92 100644 --- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -219,6 +219,12 @@ nsresult ErrorAccordingToNSPR(PRErrorCode errorCode) { default: if (psm::IsNSSErrorCode(errorCode)) { rv = psm::GetXPCOMFromNSSError(errorCode); + } else { + // If we received a Tor extended error code via SOCKS, pass it through. + nsresult res = nsresult(errorCode); + if (NS_ERROR_GET_MODULE(res) == NS_ERROR_MODULE_TOR) { + rv = res; + } } break; diff --git a/netwerk/build/components.conf b/netwerk/build/components.conf index 2d8150e6f1dd6cb3535ec9d8c7ac5a3a9a2eacb1..c35986cb4e92ef25ad3b663f83d6d5115f7e1fc9 100644 --- a/netwerk/build/components.conf +++ b/netwerk/build/components.conf @@ -818,3 +818,14 @@ if toolkit != 'android': 'headers': ['mozilla/net/CachePurgeLock.h'], }, ] + +Classes += [ + { + 'cid': '{0df7784b-7316-486d-bc99-bf47b7a05974}', + 'contract_ids': ['@torproject.org/onion-alias-service;1'], + 'singleton': True, + 'type': 'IOnionAliasService', + 'constructor': 'torproject::OnionAliasService::GetSingleton', + 'headers': ['torproject/OnionAliasService.h'], + }, +] diff --git a/netwerk/build/nsNetCID.h b/netwerk/build/nsNetCID.h index 641fd9e4b3645639fd038470c14fb1b995e233d4..2686e7970e12c02f2e890ad6e2e85773fdba4d73 100644 --- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -846,4 +846,13 @@ } \ } +// Onion alias service implementing IOnionAliasService +#define ONIONALIAS_CONTRACTID "@torproject.org/onion-alias-service;1" +#define ONIONALIAS_CID \ + { /* 0df7784b-7316-486d-bc99-bf47b7a05974 */ \ + 0x0df7784b, 0x7316, 0x486d, { \ + 0xbc, 0x99, 0xbf, 0x47, 0xb7, 0xa0, 0x59, 0x74 \ + } \ + } + #endif // nsNetCID_h__ diff --git a/netwerk/dns/IOnionAliasService.idl b/netwerk/dns/IOnionAliasService.idl new file mode 100644 index 0000000000000000000000000000000000000000..692c74b9179308c33fd26214ace8be4b106eaaa9 --- /dev/null +++ b/netwerk/dns/IOnionAliasService.idl @@ -0,0 +1,34 @@ +#include "nsISupports.idl" + +/** + * Service used for .tor.onion aliases. + * It stores the real .onion address that correspond to .tor.onion addresses, + * so that both C++ code and JS can access them. + */ +[scriptable, uuid(0df7784b-7316-486d-bc99-bf47b7a05974)] +interface IOnionAliasService : nsISupports +{ + /** + * Add a new Onion alias + * @param aShortHostname + * The short hostname that is being rewritten + * @param aLongHostname + * The complete onion v3 hostname + */ + void addOnionAlias(in ACString aShortHostname, + in ACString aLongHostname); + + /** + * Return an onion alias. + * + * @param aShortHostname + * The .tor.onion hostname to resolve + * @return a v3 address, or the input, if the short hostname is not known + */ + ACString getOnionAlias(in ACString aShortHostname); + + /** + * Clears Onion aliases. + */ + void clearOnionAliases(); +}; diff --git a/netwerk/dns/OnionAliasService.cpp b/netwerk/dns/OnionAliasService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50d9841e87b6c7a50e3790979fea550be1c3a27d --- /dev/null +++ b/netwerk/dns/OnionAliasService.cpp @@ -0,0 +1,99 @@ +#include "torproject/OnionAliasService.h" + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/StaticPrefs_browser.h" +#include "nsUnicharUtils.h" + +/** + * Check if a hostname is a valid Onion v3 hostname. + * + * @param aHostname + * The hostname to verify. It is not a const reference because any + * uppercase character will be transformed to lowercase during the + * verification. + * @return Tells whether the input string is an Onion v3 address + */ +static bool ValidateOnionV3(nsACString& aHostname) { + constexpr nsACString::size_type v3Length = 56 + 6; + if (aHostname.Length() != v3Length) { + return false; + } + ToLowerCase(aHostname); + if (!StringEndsWith(aHostname, ".onion"_ns)) { + return false; + } + + const char* cur = aHostname.BeginWriting(); + // We have already checked that it ends by ".onion" + const char* end = aHostname.EndWriting() - 6; + for (; cur < end; ++cur) { + if (!(islower(*cur) || ('2' <= *cur && *cur <= '7'))) { + return false; + } + } + + return true; +} + +namespace torproject { + +NS_IMPL_ISUPPORTS(OnionAliasService, IOnionAliasService) + +static mozilla::StaticRefPtr<OnionAliasService> gOAService; + +// static +already_AddRefed<IOnionAliasService> OnionAliasService::GetSingleton() { + if (gOAService) { + return do_AddRef(gOAService); + } + + gOAService = new OnionAliasService(); + ClearOnShutdown(&gOAService); + return do_AddRef(gOAService); +} + +NS_IMETHODIMP +OnionAliasService::AddOnionAlias(const nsACString& aShortHostname, + const nsACString& aLongHostname) { + nsAutoCString shortHostname; + ToLowerCase(aShortHostname, shortHostname); + mozilla::UniquePtr<nsAutoCString> longHostname = + mozilla::MakeUnique<nsAutoCString>(aLongHostname); + if (!longHostname) { + return NS_ERROR_OUT_OF_MEMORY; + } + if (!StringEndsWith(shortHostname, ".tor.onion"_ns) || + !ValidateOnionV3(*longHostname)) { + return NS_ERROR_INVALID_ARG; + } + mozilla::AutoWriteLock lock(mLock); + mOnionAliases.InsertOrUpdate(shortHostname, std::move(longHostname)); + return NS_OK; +} + +NS_IMETHODIMP +OnionAliasService::GetOnionAlias(const nsACString& aShortHostname, + nsACString& aLongHostname) { + aLongHostname = aShortHostname; + if (mozilla::StaticPrefs::browser_urlbar_onionRewrites_enabled() && + StringEndsWith(aShortHostname, ".tor.onion"_ns)) { + nsAutoCString* alias = nullptr; + // We want to keep the string stored in the map alive at least until we + // finish to copy it to the output parameter. + mozilla::AutoReadLock lock(mLock); + if (mOnionAliases.Get(aShortHostname, &alias)) { + // We take for granted aliases have already been validated + aLongHostname.Assign(*alias); + } + } + return NS_OK; +} + +NS_IMETHODIMP +OnionAliasService::ClearOnionAliases() { + mozilla::AutoWriteLock lock(mLock); + mOnionAliases.Clear(); + return NS_OK; +} + +} // namespace torproject diff --git a/netwerk/dns/OnionAliasService.h b/netwerk/dns/OnionAliasService.h new file mode 100644 index 0000000000000000000000000000000000000000..836e085b118ba569583e61dbea550b71882f621f --- /dev/null +++ b/netwerk/dns/OnionAliasService.h @@ -0,0 +1,39 @@ +#ifndef OnionAliasService_h_ +#define OnionAliasService_h_ + +#include "IOnionAliasService.h" + +#include "mozilla/RWLock.h" +#include "nsClassHashtable.h" +#include "nsHashKeys.h" +#include "ScopedNSSTypes.h" + +namespace torproject { + +class OnionAliasService final : public IOnionAliasService { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_IONIONALIASSERVICE + + static already_AddRefed<IOnionAliasService> GetSingleton(); + + private: + OnionAliasService() = default; + OnionAliasService(const OnionAliasService&) = delete; + OnionAliasService(OnionAliasService&&) = delete; + OnionAliasService& operator=(const OnionAliasService&) = delete; + OnionAliasService& operator=(OnionAliasService&&) = delete; + virtual ~OnionAliasService() = default; + + // mLock protects access to mOnionAliases + mozilla::RWLock mLock{"OnionAliasService.mLock"}; + + // AutoCStrings have a 64 byte buffer, so it is advised not to use them for + // long storage. However, it is enough to contain onion addresses, so we use + // them instead, and avoid allocating on heap for each alias + nsClassHashtable<nsCStringHashKey, nsAutoCString> mOnionAliases; +}; + +} // namespace torproject + +#endif // OnionAliasService_h_ diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat index 8fb41df56ffd79b96b1b1a6d954ab2a45697b41d..2246c2afca94e91372b7b1a17ebb867700d247cc 100644 --- a/netwerk/dns/effective_tld_names.dat +++ b/netwerk/dns/effective_tld_names.dat @@ -5038,6 +5038,12 @@ pro.om // onion : https://tools.ietf.org/html/rfc7686 onion +tor.onion +securedrop.tor.onion +// An additional TLD for abc.au.securedrop.tor.onion only. +// See tor-browser#41831. +// TODO: Remove once abc.au has migrated. See tor-browser#43443. +au.securedrop.tor.onion // org : https://www.iana.org/domains/root/db/org.html org diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build index 1bb0430f01aa3d8f489cf013233cd23d7ef5e239..93bb1954bc9cb505276ffd963dffdf0cfe47e508 100644 --- a/netwerk/dns/moz.build +++ b/netwerk/dns/moz.build @@ -119,3 +119,7 @@ LOCAL_INCLUDES += [ ] USE_LIBS += ["icu"] + +XPIDL_SOURCES += ["IOnionAliasService.idl"] +UNIFIED_SOURCES += ["OnionAliasService.cpp"] +EXPORTS.torproject += ["OnionAliasService.h"] diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 3580e986e11fafabda210842ade89f0df000cd96..a606e7d01472c77667e961cfc2aa4090968c5b61 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -353,6 +353,7 @@ void HttpBaseChannel::AddClassificationFlags(uint32_t aClassificationFlags, static bool isSecureOrTrustworthyURL(nsIURI* aURI) { return aURI->SchemeIs("https") || + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(aURI) || (StaticPrefs::network_http_encoding_trustworthy_is_https() && nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)); } @@ -379,7 +380,6 @@ nsresult HttpBaseChannel::Init(nsIURI* aURI, uint32_t aCaps, // Construct connection info object nsAutoCString host; int32_t port = -1; - bool isHTTPS = isSecureOrTrustworthyURL(mURI); nsresult rv = mURI->GetAsciiHost(host); if (NS_FAILED(rv)) return rv; @@ -408,7 +408,7 @@ nsresult HttpBaseChannel::Init(nsIURI* aURI, uint32_t aCaps, if (NS_FAILED(rv)) return rv; rv = gHttpHandler->AddStandardRequestHeaders( - &mRequestHead, isHTTPS, aContentPolicyType, + &mRequestHead, isSecureOrTrustworthyURL(mURI), aContentPolicyType, nsContentUtils::ShouldResistFingerprinting(this, RFPTarget::HttpUserAgent)); if (NS_FAILED(rv)) return rv; diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index 9a600a613181a12691af3c1f9cff2461bb0d95cb..41c6dfff53d584c7f3b75a915589c28a9adf8242 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -918,7 +918,7 @@ void nsHttpHandler::BuildUserAgent() { mUserAgent += '/'; mUserAgent += mProductSub; - bool isFirefox = mAppName.EqualsLiteral("Firefox"); + bool isFirefox = true; if (isFirefox || mCompatFirefoxEnabled) { // "Firefox/x.y" (compatibility) app token mUserAgent += ' '; diff --git a/netwerk/protocol/http/nsHttpNTLMAuth.cpp b/netwerk/protocol/http/nsHttpNTLMAuth.cpp index 0d8f5f083ad0d489933f4b87d08cf3bfad37e810..c02bd97d690f04534c82ee1953f3cd6fa399dd3d 100644 --- a/netwerk/protocol/http/nsHttpNTLMAuth.cpp +++ b/netwerk/protocol/http/nsHttpNTLMAuth.cpp @@ -167,6 +167,9 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel* channel, *identityInvalid = false; + /* Always fail Negotiate auth for Tor Browser. We don't need it. */ + return NS_ERROR_ABORT; + // Start a new auth sequence if the challenge is exactly "NTLM". // If native NTLM auth apis are available and enabled through prefs, // try to use them. diff --git a/netwerk/sctp/src/moz.build b/netwerk/sctp/src/moz.build index 94555e6836027c3376ec83e94b563caa5a4eba58..8a475415e864988584280c1d272370ff4ba7c973 100644 --- a/netwerk/sctp/src/moz.build +++ b/netwerk/sctp/src/moz.build @@ -62,3 +62,5 @@ if CONFIG['OS_TARGET'] in ('Linux', 'Android'): DEFINES['_GNU_SOURCE'] = 1 elif CONFIG['OS_TARGET'] == 'Darwin': DEFINES['__APPLE_USE_RFC_2292'] = 1 +elif CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['_CRT_RAND_S'] = True diff --git a/netwerk/sctp/src/netinet/sctp_cc_functions.c b/netwerk/sctp/src/netinet/sctp_cc_functions.c index 176338a05e718f5535a0eb3fa689d8e5d0f849be..77193d8f9de60d9b57c3a9230e3d538a0fb40a37 100644 --- a/netwerk/sctp/src/netinet/sctp_cc_functions.c +++ b/netwerk/sctp/src/netinet/sctp_cc_functions.c @@ -49,6 +49,10 @@ #include <netinet/sctp_kdtrace.h> #endif +#if defined(_WIN32) && defined(__MINGW32__) +#include <minmax.h> +#endif + #define SHIFT_MPTCP_MULTI_N 40 #define SHIFT_MPTCP_MULTI_Z 16 #define SHIFT_MPTCP_MULTI 8 diff --git a/netwerk/sctp/src/netinet/sctp_indata.c b/netwerk/sctp/src/netinet/sctp_indata.c index 115ec1d763e22a6280eb3e4d95477019c6d36079..8ecb971e8a4648d3f5dc746e72b0f94e4f7db05a 100644 --- a/netwerk/sctp/src/netinet/sctp_indata.c +++ b/netwerk/sctp/src/netinet/sctp_indata.c @@ -53,6 +53,11 @@ #if defined(__FreeBSD__) && !defined(__Userspace__) #include <netinet/sctp_lock_bsd.h> #endif + +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + /* * NOTES: On the outbound side of things I need to check the sack timer to * see if I should generate a sack into the chunk queue (if I have data to diff --git a/netwerk/sctp/src/netinet/sctp_input.c b/netwerk/sctp/src/netinet/sctp_input.c index a3c1476f5b399e34dd28af6581ef7ad3ec7bd35d..29ee1a8f3be3999c853807da7f01f0afef71b681 100644 --- a/netwerk/sctp/src/netinet/sctp_input.c +++ b/netwerk/sctp/src/netinet/sctp_input.c @@ -58,6 +58,10 @@ #include <sys/smp.h> #endif +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + static void sctp_stop_all_cookie_timers(struct sctp_tcb *stcb) { diff --git a/netwerk/sctp/src/netinet/sctp_output.c b/netwerk/sctp/src/netinet/sctp_output.c index 33a6e169d84ec153674629fcaaae1d13e186173d..294568080c28ab23942cef057b207423f8fd6a15 100644 --- a/netwerk/sctp/src/netinet/sctp_output.c +++ b/netwerk/sctp/src/netinet/sctp_output.c @@ -74,6 +74,11 @@ #if defined(__Userspace__) && defined(INET6) #include <netinet6/sctp6_var.h> #endif + +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + #if defined(__APPLE__) && !defined(__Userspace__) #if !(defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD)) #define SCTP_MAX_LINKHDR 16 diff --git a/netwerk/sctp/src/netinet/sctp_usrreq.c b/netwerk/sctp/src/netinet/sctp_usrreq.c index 53aeaa1d45108a9818c4c351508d5ad53bdad293..f3d20b0e66f8cd69c584b6e38a72411f8ef99c24 100644 --- a/netwerk/sctp/src/netinet/sctp_usrreq.c +++ b/netwerk/sctp/src/netinet/sctp_usrreq.c @@ -63,6 +63,10 @@ #include <netinet/sctp_peeloff.h> #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */ +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + extern const struct sctp_cc_functions sctp_cc_functions[]; extern const struct sctp_ss_functions sctp_ss_functions[]; diff --git a/netwerk/sctp/src/netinet/sctputil.c b/netwerk/sctp/src/netinet/sctputil.c index bd414141d23ed436ff622cbcfe36367c1b1fc8a9..4a819b9bf73775ea846ddfffb6268899fbdf1016 100644 --- a/netwerk/sctp/src/netinet/sctputil.c +++ b/netwerk/sctp/src/netinet/sctputil.c @@ -77,6 +77,10 @@ #endif #endif +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + extern const struct sctp_cc_functions sctp_cc_functions[]; extern const struct sctp_ss_functions sctp_ss_functions[]; diff --git a/netwerk/sctp/src/user_mbuf.c b/netwerk/sctp/src/user_mbuf.c index 85badc0fa520fc84a8d1aad03736469cd245084b..83b6ee3d8dd75994f5b95965324b82dc380effa2 100644 --- a/netwerk/sctp/src/user_mbuf.c +++ b/netwerk/sctp/src/user_mbuf.c @@ -35,6 +35,10 @@ * */ +#if defined(_WIN32) && !defined(_MSC_VER) +#include <minmax.h> +#endif + #include <stdio.h> #include <string.h> /* #include <sys/param.h> This defines MSIZE 256 */ diff --git a/netwerk/sctp/src/user_socket.c b/netwerk/sctp/src/user_socket.c index cde6ecc417b521194e8048469ab37646b5d90d89..9bdd51e105d05346a6bd8eb6e374cd994c6914f6 100644 --- a/netwerk/sctp/src/user_socket.c +++ b/netwerk/sctp/src/user_socket.c @@ -60,9 +60,12 @@ #endif userland_mutex_t accept_mtx; userland_cond_t accept_cond; -#ifdef _WIN32 +#if defined(_WIN32) #include <time.h> #include <sys/timeb.h> +#if !defined(_MSC_VER) +#include <minmax.h> +#endif #endif MALLOC_DEFINE(M_PCB, "sctp_pcb", "sctp pcb"); diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp index 138c6c8dc15bf4eae23f2bd8714f9e8ae2ff9cc0..1b4fa8aa6a41bfc612b32dbebf41c5fb2542a494 100644 --- a/netwerk/socket/nsSOCKSIOLayer.cpp +++ b/netwerk/socket/nsSOCKSIOLayer.cpp @@ -25,6 +25,8 @@ #include "mozilla/net/DNS.h" #include "mozilla/Unused.h" +#include "IOnionAliasService.h" + using mozilla::LogLevel; using namespace mozilla::net; @@ -841,11 +843,23 @@ PRStatus nsSOCKSSocketInfo::WriteV5ConnectRequest() { // Add the address to the SOCKS 5 request. SOCKS 5 supports several // address types, so we pick the one that works best for us. if (proxy_resolve) { - // Add the host name. Only a single byte is used to store the length, - // so we must prevent long names from being used. - buf2 = buf.WriteUint8(0x03) // addr type -- domainname - .WriteUint8(mDestinationHost.Length()) // name length - .WriteString<MAX_HOSTNAME_LEN>(mDestinationHost); // Hostname + if (StringEndsWith(mDestinationHost, ".tor.onion"_ns)) { + nsAutoCString realHost; + nsCOMPtr<IOnionAliasService> oas = do_GetService(ONIONALIAS_CID); + if (NS_FAILED(oas->GetOnionAlias(mDestinationHost, realHost))) { + HandshakeFinished(PR_BAD_ADDRESS_ERROR); + return PR_FAILURE; + } + buf2 = buf.WriteUint8(0x03) + .WriteUint8(realHost.Length()) + .WriteString<MAX_HOSTNAME_LEN>(realHost); + } else { + // Add the host name. Only a single byte is used to store the length, + // so we must prevent long names from being used. + buf2 = buf.WriteUint8(0x03) // addr type -- domainname + .WriteUint8(mDestinationHost.Length()) // name length + .WriteString<MAX_HOSTNAME_LEN>(mDestinationHost); // Hostname + } if (!buf2) { LOGERROR(("socks5: destination host name is too long!")); HandshakeFinished(PR_BAD_ADDRESS_ERROR); @@ -959,6 +973,55 @@ PRStatus nsSOCKSSocketInfo::ReadV5ConnectResponseTop() { "08, Address type not supported.")); c = PR_BAD_ADDRESS_ERROR; break; + case 0xF0: // Tor SOCKS5_HS_NOT_FOUND + LOGERROR( + ("socks5: connect failed: F0," + " Tor onion service descriptor can not be found.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_NOT_FOUND); + break; + case 0xF1: // Tor SOCKS5_HS_IS_INVALID + LOGERROR( + ("socks5: connect failed: F1," + " Tor onion service descriptor is invalid.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_IS_INVALID); + break; + case 0xF2: // Tor SOCKS5_HS_INTRO_FAILED + LOGERROR( + ("socks5: connect failed: F2," + " Tor onion service introduction failed.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_INTRO_FAILED); + break; + case 0xF3: // Tor SOCKS5_HS_REND_FAILED + LOGERROR( + ("socks5: connect failed: F3," + " Tor onion service rendezvous failed.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_REND_FAILED); + break; + case 0xF4: // Tor SOCKS5_HS_MISSING_CLIENT_AUTH + LOGERROR( + ("socks5: connect failed: F4," + " Tor onion service missing client authorization.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH); + break; + case 0xF5: // Tor SOCKS5_HS_BAD_CLIENT_AUTH + LOGERROR( + ("socks5: connect failed: F5," + " Tor onion service wrong client authorization.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH); + break; + case 0xF6: // Tor SOCKS5_HS_BAD_ADDRESS + LOGERROR( + ("socks5: connect failed: F6," + " Tor onion service bad address.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS); + break; + case 0xF7: // Tor SOCKS5_HS_INTRO_TIMEDOUT + LOGERROR( + ("socks5: connect failed: F7," + " Tor onion service introduction timed out.")); + c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT); + break; + default: LOGERROR(("socks5: connect failed.")); break; diff --git a/netwerk/system/android/nsAndroidNetworkLinkService.cpp b/netwerk/system/android/nsAndroidNetworkLinkService.cpp index a3d0328d8b203d196745db8788d59072afdcade3..f7d4645c1e5e040b0800fea141c728e021063814 100644 --- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp +++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp @@ -126,11 +126,15 @@ nsAndroidNetworkLinkService::GetLinkType(uint32_t* aLinkType) { NS_IMETHODIMP nsAndroidNetworkLinkService::GetNetworkID(nsACString& aNetworkID) { +#ifdef BASE_BROWSER_VERSION + aNetworkID.Truncate(); +#else if (!mNetlinkSvc) { return NS_ERROR_NOT_AVAILABLE; } mNetlinkSvc->GetNetworkID(aNetworkID); +#endif return NS_OK; } diff --git a/netwerk/system/linux/nsNetworkLinkService.cpp b/netwerk/system/linux/nsNetworkLinkService.cpp index 59894ba1fa54ae07f19f82aaf252226935efd4ed..330e6a0d5e591a666140ab7a3566793fe8ef9342 100644 --- a/netwerk/system/linux/nsNetworkLinkService.cpp +++ b/netwerk/system/linux/nsNetworkLinkService.cpp @@ -50,11 +50,15 @@ nsNetworkLinkService::GetLinkType(uint32_t* aLinkType) { NS_IMETHODIMP nsNetworkLinkService::GetNetworkID(nsACString& aNetworkID) { +#ifdef BASE_BROWSER_VERSION + aNetworkID.Truncate(); +#else if (!mNetlinkSvc) { return NS_ERROR_NOT_AVAILABLE; } mNetlinkSvc->GetNetworkID(aNetworkID); +#endif return NS_OK; } diff --git a/netwerk/system/mac/nsNetworkLinkService.mm b/netwerk/system/mac/nsNetworkLinkService.mm index e664d11b18ed8e3d7b6828e46f2c9f8d1843dfeb..ea19014ca99e32d1470b5d2accd6ca56f49c8393 100644 --- a/netwerk/system/mac/nsNetworkLinkService.mm +++ b/netwerk/system/mac/nsNetworkLinkService.mm @@ -127,8 +127,12 @@ nsNetworkLinkService::GetLinkType(uint32_t* aLinkType) { NS_IMETHODIMP nsNetworkLinkService::GetNetworkID(nsACString& aNetworkID) { +#ifdef BASE_BROWSER_VERSION + aNetworkID.Truncate(); +#else MutexAutoLock lock(mMutex); aNetworkID = mNetworkId; +#endif return NS_OK; } diff --git a/netwerk/system/netlink/NetlinkService.cpp b/netwerk/system/netlink/NetlinkService.cpp index f50284af0c1fc939d80543bdefb629c8b7b61612..2d9ce2632ae1272e10dd4b9618d10451b0d87e66 100644 --- a/netwerk/system/netlink/NetlinkService.cpp +++ b/netwerk/system/netlink/NetlinkService.cpp @@ -1871,8 +1871,12 @@ void NetlinkService::CalculateNetworkID() { } void NetlinkService::GetNetworkID(nsACString& aNetworkID) { +#ifdef BASE_BROWSER_VERSION + aNetworkID.Truncate(); +#else MutexAutoLock lock(mMutex); aNetworkID = mNetworkId; +#endif } nsresult NetlinkService::GetDnsSuffixList(nsTArray<nsCString>& aDnsSuffixList) { diff --git a/netwerk/system/win32/nsNotifyAddrListener.cpp b/netwerk/system/win32/nsNotifyAddrListener.cpp index 6174754c8c0616662dec4edec16ee16bb9e46196..dc71996c19b5a27a45a93405e26daffd3640241d 100644 --- a/netwerk/system/win32/nsNotifyAddrListener.cpp +++ b/netwerk/system/win32/nsNotifyAddrListener.cpp @@ -104,8 +104,12 @@ nsNotifyAddrListener::GetLinkType(uint32_t* aLinkType) { NS_IMETHODIMP nsNotifyAddrListener::GetNetworkID(nsACString& aNetworkID) { +#ifdef BASE_BROWSER_VERSION + aNetworkID.Truncate(); +#else MutexAutoLock lock(mMutex); aNetworkID = mNetworkId; +#endif return NS_OK; } diff --git a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp index 6f5924ab50af0753bec63fd7d5d11a5ed48dfc2c..6527dc05c0e4d3c95a9981371d073cb4fb9216ad 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp @@ -78,7 +78,7 @@ void UrlClassifierFeatureBase::InitializePreferences() { nsCOMPtr<nsIUrlClassifierExceptionListService> exceptionListService = do_GetService("@mozilla.org/url-classifier/exception-list-service;1"); - if (NS_WARN_IF(!exceptionListService)) { + if (!exceptionListService) { return; } diff --git a/netwerk/url-classifier/components.conf b/netwerk/url-classifier/components.conf index 3cf63a06f112bf56dca40b9c23560fca121ebce0..b2e6672473177433f5066621064620570219233c 100644 --- a/netwerk/url-classifier/components.conf +++ b/netwerk/url-classifier/components.conf @@ -13,10 +13,4 @@ Classes = [ 'constructor': 'mozilla::net::ChannelClassifierService::GetSingleton', 'headers': ['mozilla/net/ChannelClassifierService.h'], }, - { - 'cid': '{b9f4fd03-9d87-4bfd-9958-85a821750ddc}', - 'contract_ids': ['@mozilla.org/url-classifier/exception-list-service;1'], - 'esModule': 'resource://gre/modules/UrlClassifierExceptionListService.sys.mjs', - 'constructor': 'UrlClassifierExceptionListService', - }, ] diff --git a/python/mach/mach/site.py b/python/mach/mach/site.py index 7041437bf8daac05f46e985c16d7ce4effa19985..c48d282b2fc29de6c9b8d56ead056d88f08cff87 100644 --- a/python/mach/mach/site.py +++ b/python/mach/mach/site.py @@ -17,6 +17,7 @@ import subprocess import sys import sysconfig import tempfile +import warnings from contextlib import contextmanager from pathlib import Path from typing import Callable, Optional @@ -817,33 +818,75 @@ class PythonVirtualenv: """Calculates paths of interest for general python virtual environments""" def __init__(self, prefix): - if _is_windows: - self.bin_path = os.path.join(prefix, "Scripts") - self.python_path = os.path.join(self.bin_path, "python.exe") - else: - self.bin_path = os.path.join(prefix, "bin") - self.python_path = os.path.join(self.bin_path, "python") self.prefix = os.path.realpath(prefix) + self.paths = self._get_sysconfig_paths(self.prefix) - @functools.lru_cache(maxsize=None) - def resolve_sysconfig_packages_path(self, sysconfig_path): - # macOS uses a different default sysconfig scheme based on whether it's using the - # system Python or running in a virtualenv. - # Manually define the scheme (following the implementation in - # "sysconfig._get_default_scheme()") so that we're always following the - # code path for a virtualenv directory structure. - if os.name == "posix": - scheme = "posix_prefix" - else: - scheme = os.name + # Name of the Python executable to use in virtual environments. + # An executable with the same name as sys.executable might not exist in + # virtual environments. An executable with 'python' as the steam — + # without version numbers or ABI flags — will always be present in + # virtual environments, so we use that. + python_exe_name = "python" + sysconfig.get_config_var("EXE") + + self.bin_path = self.paths["scripts"] + self.python_path = os.path.join(self.bin_path, python_exe_name) - sysconfig_paths = sysconfig.get_paths(scheme) - data_path = Path(sysconfig_paths["data"]) - path = Path(sysconfig_paths[sysconfig_path]) - relative_path = path.relative_to(data_path) + @staticmethod + def _get_sysconfig_paths(prefix): + """Calculate the sysconfig paths of a virtual environment in the given prefix. - # Path to virtualenv's "site-packages" directory for provided sysconfig path - return os.path.normpath(os.path.normcase(Path(self.prefix) / relative_path)) + The virtual environment MUST be using the same Python distribution as us. + """ + # Determine the sysconfig scheme used in virtual environments + if "venv" in sysconfig.get_scheme_names(): + # A 'venv' scheme was added in Python 3.11 to allow users to + # calculate the paths for a virtual environment, since the default + # scheme may not always be the same as used on virtual environments. + # Some common examples are the system Python distributed by macOS, + # Debian, and Fedora. + # For more information, see https://github.com/python/cpython/issues/89576 + venv_scheme = "venv" + elif os.name == "nt": + # We know that before the 'venv' scheme was added, on Windows, + # the 'nt' scheme was used in virtual environments. + venv_scheme = "nt" + elif os.name == "posix": + # We know that before the 'venv' scheme was added, on POSIX, + # the 'posix_prefix' scheme was used in virtual environments. + venv_scheme = "posix_prefix" + else: + # This should never happen with upstream Python, as the 'venv' + # scheme should always be available on >=3.11, and no other + # platforms are supported by the upstream on older Python versions. + # + # Since the 'venv' scheme isn't available, and we have no knowledge + # of this platform/distribution, fallback to the default scheme. + # + # Hitting this will likely be the result of running a custom Python + # distribution targetting a platform that is not supported by the + # upstream. + # In this case, unless the Python vendor patched the Python + # distribution in such a way as the default scheme may not always be + # the same scheme, using the default scheme should be correct. + # If the vendor did patch Python as such, to work around this issue, + # I would recommend them to define a 'venv' scheme that matches + # the layout used on virtual environments in their Python distribution. + # (rec. signed Filipe Laíns — upstream sysconfig maintainer) + venv_scheme = sysconfig.get_default_scheme() + warnings.warn( + f"Unknown platform '{os.name}', using the default install scheme '{venv_scheme}'. " + "If this is incorrect, please ask your Python vendor to add a 'venv' sysconfig scheme " + "(see https://github.com/python/cpython/issues/89576, or check the code comment).", + stacklevel=2, + ) + # Build the sysconfig config_vars dictionary for the virtual environment. + venv_vars = sysconfig.get_config_vars().copy() + venv_vars["base"] = venv_vars["platbase"] = prefix + # Get sysconfig paths for the virtual environment. + return sysconfig.get_paths(venv_scheme, vars=venv_vars) + + def resolve_sysconfig_packages_path(self, sysconfig_path): + return self.paths[sysconfig_path] def site_packages_dirs(self): dirs = [] diff --git a/python/mozbuild/mozbuild/action/node.py b/python/mozbuild/mozbuild/action/node.py index fca0745b809af15ca45a569341dcb538f17aa99f..9f90a220bc43eb73714a53b0afb1892c8d9f4129 100644 --- a/python/mozbuild/mozbuild/action/node.py +++ b/python/mozbuild/mozbuild/action/node.py @@ -2,13 +2,14 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -import pipes import subprocess import sys import buildconfig import six +from mozbuild.shellutil import quote as shell_quote + SCRIPT_ALLOWLIST = [buildconfig.topsrcdir + "/devtools/client/shared/build/build.js"] ALLOWLIST_ERROR = """ @@ -47,8 +48,7 @@ def execute_node_cmd(node_cmd_list): """ try: - printable_cmd = " ".join(pipes.quote(arg) for arg in node_cmd_list) - print('Executing "{}"'.format(printable_cmd), file=sys.stderr) + print('Executing "{}"'.format(shell_quote(*node_cmd_list)), file=sys.stderr) sys.stderr.flush() # We need to redirect stderr to a pipe because diff --git a/python/mozbuild/mozbuild/artifacts.py b/python/mozbuild/mozbuild/artifacts.py index 6e46664f20403f46bff8c9dc4b572727e6ec2865..ec34766109b7bef4ea0aaefcc1299a15caef7981 100644 --- a/python/mozbuild/mozbuild/artifacts.py +++ b/python/mozbuild/mozbuild/artifacts.py @@ -561,7 +561,6 @@ class LinuxArtifactJob(ArtifactJob): "{product}/{product}", "{product}/{product}-bin", "{product}/minidump-analyzer", - "{product}/pingsender", "{product}/plugin-container", "{product}/updater", "{product}/glxtest", @@ -661,7 +660,6 @@ class MacArtifactJob(ArtifactJob): "*.dylib", "minidump-analyzer", "nmhproxy", - "pingsender", "plugin-container.app/Contents/MacOS/plugin-container", "updater.app/Contents/MacOS/org.mozilla.updater", # 'xpcshell', diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index 926099c94f3563ec64a1994a3bc77bbd80ed8fcd..1cbbebd089191a51f44aa7d7c66b268a1a2437b6 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -3327,6 +3327,10 @@ def package_l10n(command_context, verbose=False, locales=[]): target = ["package"] if command_context.substs["MOZ_BUILD_APP"] == "mobile/android": target.append("AB_CD=multi") + else: + # tor-browser#41458 and tor-browser-build#40687: do not actually + # create the package (at least on desktop) + return 0 command_context._run_make( directory=command_context.topobjdir, diff --git a/python/mozlint/mozlint/cli.py b/python/mozlint/mozlint/cli.py index 36ff7b4f9a7d8b60bbf0ab76cc811c7c814e477f..7324b9384b6a79b176ba27341fc4f9d2b0458d7e 100644 --- a/python/mozlint/mozlint/cli.py +++ b/python/mozlint/mozlint/cli.py @@ -10,6 +10,30 @@ from pathlib import Path from mozlint.errors import NoValidLinter from mozlint.formatters import all_formatters +# We (the Tor Project) do not use all of Mozilla's linters. +# Below is a list of linters we do not use, +# these will be skipped when running `./mach lint` commands. +INACTIVE_LINTERS = [ + "android-api-lint", + "android-checkstyle", + "android-format", + "android-javadoc", + "android-lint", + "android-test", + "clippy", + "codespell", + "condprof-addons", + "file-perm", + "ignorefile", + "license", + "lintpref", + "perfdocs", + "rejected-words", + "rst", + "updatebot", + "wpt", +] + class MozlintParser(ArgumentParser): arguments = [ @@ -276,6 +300,9 @@ def find_linters(config_paths, linters=None): name = name.rsplit(".", 1)[0] + if not linters and name in INACTIVE_LINTERS: + continue + if linters and name not in linters: continue @@ -341,10 +368,14 @@ def run( if list_linters: lint_paths = find_linters(lintargs["config_paths"], linters) - linters = [ + formatted_linters = [ os.path.splitext(os.path.basename(l))[0] for l in lint_paths["lint_paths"] ] - print("\n".join(sorted(linters))) + print("\n".join(sorted(formatted_linters))) + + if not linters: + print("\nINACTIVE -- ".join(sorted(["", *INACTIVE_LINTERS])).strip()) + print( "\nNote that clang-tidy checks are not run as part of this " "command, but using the static-analysis command." diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp index 0e73a0d4756286afe65b377f237de93523aaea0c..5859e4ec10d733a005b7b13fe35c9c46b1c877dc 100644 --- a/security/certverifier/CertVerifier.cpp +++ b/security/certverifier/CertVerifier.cpp @@ -772,6 +772,9 @@ Result CertVerifier::VerifySSLServerCert( if (rv != Success) { return rv; } + + bool errOnionWithSelfSignedCert = false; + bool isBuiltChainRootBuiltInRootLocal; rv = VerifyCert( peerCertBytes, certificateUsageSSLServer, time, pinarg, @@ -794,9 +797,21 @@ Result CertVerifier::VerifySSLServerCert( // In this case we didn't find any issuer for the certificate, or we did // find other certificates with the same subject but different keys, and // the certificate is self-signed. - return Result::ERROR_SELF_SIGNED_CERT; + if (StringEndsWith(hostname, ".onion"_ns)) { + // Self signed cert over onion is deemed secure in some cases, as the + // onion service provides encryption. + // Firefox treats some errors as self-signed certificates and it allows + // to override them. For Onion services, we prefer being stricter, and + // we return the original errors. + // Moreover, we need also to determine if there are other legitimate + // certificate errors (such as expired, wrong domain) that we would like + // to surface to the user. + errOnionWithSelfSignedCert = rv == Result::ERROR_UNKNOWN_ISSUER; + } else { + return Result::ERROR_SELF_SIGNED_CERT; + } } - if (rv == Result::ERROR_UNKNOWN_ISSUER) { + if (rv == Result::ERROR_UNKNOWN_ISSUER && !errOnionWithSelfSignedCert) { // In this case we didn't get any valid path for the cert. Let's see if // the issuer is the same as the issuer for our canary probe. If yes, this // connection is connecting via a misconfigured proxy. @@ -832,7 +847,9 @@ Result CertVerifier::VerifySSLServerCert( return hostnameResult; } } - return rv; + if (!errOnionWithSelfSignedCert) { + return rv; + } } if (dcInfo) { @@ -871,6 +888,9 @@ Result CertVerifier::VerifySSLServerCert( return rv; } + if (errOnionWithSelfSignedCert) { + return Result::ERROR_ONION_WITH_SELF_SIGNED_CERT; + } return Success; } diff --git a/security/manager/ssl/NSSSocketControl.cpp b/security/manager/ssl/NSSSocketControl.cpp index 1928af4a5ca8e48e56ef2ee0f711808a3fa09ebd..449096cae59af21040b647c8db98f9d73deb389f 100644 --- a/security/manager/ssl/NSSSocketControl.cpp +++ b/security/manager/ssl/NSSSocketControl.cpp @@ -414,7 +414,11 @@ void NSSSocketControl::SetCertVerificationResult(PRErrorCode errorCode) { "Invalid state transition to AfterCertVerification"); if (mFd) { - SECStatus rv = SSL_AuthCertificateComplete(mFd, errorCode); + PRErrorCode passCode = errorCode; + if (errorCode == MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT) { + passCode = 0; + } + SECStatus rv = SSL_AuthCertificateComplete(mFd, passCode); // Only replace errorCode if there was originally no error. // SSL_AuthCertificateComplete will return SECFailure with the error code // set to PR_WOULD_BLOCK_ERROR if there is a pending event to select a @@ -429,7 +433,8 @@ void NSSSocketControl::SetCertVerificationResult(PRErrorCode errorCode) { } } - if (errorCode) { + if (errorCode && + errorCode != MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT) { mFailedVerification = true; SetCanceled(errorCode); } diff --git a/security/manager/ssl/RemoteSecuritySettings.sys.mjs b/security/manager/ssl/RemoteSecuritySettings.sys.mjs index fb98d8387f6d810dd323dc93f866d2ee8179826b..d86fcb9647e484ef044ad621dd2d3c75cb4b6e71 100644 --- a/security/manager/ssl/RemoteSecuritySettings.sys.mjs +++ b/security/manager/ssl/RemoteSecuritySettings.sys.mjs @@ -252,6 +252,16 @@ export var RemoteSecuritySettings = { class IntermediatePreloads { constructor() { + this.maybeInit(); + } + + maybeInit() { + if ( + this.client || + !Services.prefs.getBoolPref(INTERMEDIATES_ENABLED_PREF, true) + ) { + return; + } this.client = RemoteSettings("intermediates", { bucketName: SECURITY_STATE_BUCKET, signerName: SECURITY_STATE_SIGNER, @@ -277,6 +287,7 @@ class IntermediatePreloads { ); return; } + this.maybeInit(); // Download attachments that are awaiting download, up to a max. const maxDownloadsPerRun = Services.prefs.getIntPref( @@ -506,6 +517,16 @@ function compareFilters(filterA, filterB) { class CRLiteFilters { constructor() { + this.maybeInit(); + } + + maybeInit() { + if ( + this.client || + !Services.prefs.getBoolPref(CRLITE_FILTERS_ENABLED_PREF, true) + ) { + return; + } this.client = RemoteSettings("cert-revocations", { bucketName: SECURITY_STATE_BUCKET, signerName: SECURITY_STATE_SIGNER, @@ -556,6 +577,8 @@ class CRLiteFilters { return; } + this.maybeInit(); + let hasPriorFilter = await hasPriorData( Ci.nsICertStorage.DATA_TYPE_CRLITE_FILTER_FULL ); diff --git a/security/manager/ssl/SSLServerCertVerification.cpp b/security/manager/ssl/SSLServerCertVerification.cpp index 0e838ddd02387d9442e219dd6d65d4d84a2cd1d3..95094b0d062ac1c7d678ca2f89d4823b3d1f30d6 100644 --- a/security/manager/ssl/SSLServerCertVerification.cpp +++ b/security/manager/ssl/SSLServerCertVerification.cpp @@ -138,6 +138,8 @@ #include "sslerr.h" #include "sslexp.h" +#include "IOnionAliasService.h" + extern mozilla::LazyLogModule gPIPNSSLog; using namespace mozilla::pkix; @@ -283,6 +285,7 @@ CategorizeCertificateError(PRErrorCode certificateError) { case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: + case mozilla::pkix::MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT: return Some( nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST); @@ -617,6 +620,78 @@ Result AuthCertificate( return rv; } +/** + * Check if the self-signed onion certificate error can be overridden by another + * error. + * + * Basically, this function restore part of the old functionalities of + * DetermineCertOverrideErrors, before it was changed in Bug 1781104. + */ +static PRErrorCode OverrideOnionSelfSignedError( + const nsCOMPtr<nsIX509Cert>& aCert, const nsACString& aHostName, + mozilla::pkix::Time aNow, PRErrorCode aCertVerificationError) { + nsTArray<uint8_t> certDER; + if (NS_FAILED(aCert->GetRawDER(certDER))) { + return SEC_ERROR_LIBRARY_FAILURE; + } + mozilla::pkix::Input certInput; + if (certInput.Init(certDER.Elements(), certDER.Length()) != Success) { + return SEC_ERROR_BAD_DER; + } + + // First, check the hostname. + { + Input hostnameInput; + Result result = hostnameInput.Init( + BitwiseCast<const uint8_t*, const char*>(aHostName.BeginReading()), + aHostName.Length()); + if (result != Success) { + return SEC_ERROR_INVALID_ARGS; + } + result = CheckCertHostname(certInput, hostnameInput); + if (result == Result::ERROR_BAD_DER || + result == Result::ERROR_BAD_CERT_DOMAIN) { + aCertVerificationError = SSL_ERROR_BAD_CERT_DOMAIN; + } else if (IsFatalError(result)) { + // This should be then mapped to a fatal error by + // CategorizeCertificateError. + return MapResultToPRErrorCode(result); + } + } + + // Then, check if the certificate has expired. + { + mozilla::pkix::BackCert backCert( + certInput, mozilla::pkix::EndEntityOrCA::MustBeEndEntity, nullptr); + Result rv = backCert.Init(); + if (rv != Success) { + PR_SetError(MapResultToPRErrorCode(rv), 0); + return SECFailure; + } + mozilla::pkix::Time notBefore(mozilla::pkix::Time::uninitialized); + mozilla::pkix::Time notAfter(mozilla::pkix::Time::uninitialized); + // If the validity can't be parsed, ParseValidity will return + // Result::ERROR_INVALID_DER_TIME. + rv = mozilla::pkix::ParseValidity(backCert.GetValidity(), ¬Before, + ¬After); + if (rv != Success) { + return MapResultToPRErrorCode(rv); + } + // If `now` is outside of the certificate's validity period, + // CheckValidity will return Result::ERROR_NOT_YET_VALID_CERTIFICATE or + // Result::ERROR_EXPIRED_CERTIFICATE, as appropriate, and Success + // otherwise. + rv = mozilla::pkix::CheckValidity(aNow, notBefore, notAfter); + if (rv != Success) { + return MapResultToPRErrorCode(rv); + } + } + + // If we arrive here, the cert is okay, just self-signed, so return the + // original error. + return aCertVerificationError; +} + PRErrorCode AuthCertificateParseResults( uint64_t aPtrForLog, const nsACString& aHostName, int32_t aPort, const OriginAttributes& aOriginAttributes, @@ -628,6 +703,12 @@ PRErrorCode AuthCertificateParseResults( uint32_t probeValue = MapCertErrorToProbeValue(aCertVerificationError); Telemetry::Accumulate(Telemetry::SSL_CERT_VERIFICATION_ERRORS, probeValue); + if (aCertVerificationError == + mozilla::pkix::MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT) { + aCertVerificationError = OverrideOnionSelfSignedError( + aCert, aHostName, aTime, aCertVerificationError); + } + Maybe<nsITransportSecurityInfo::OverridableErrorCategory> maybeOverridableErrorCategory = CategorizeCertificateError(aCertVerificationError); @@ -736,6 +817,13 @@ SECStatus SSLServerCertVerificationJob::Dispatch( return SECWouldBlock; } +void SSLServerCertVerificationJob::FixOnionAlias() { + if (StringEndsWith(mHostName, ".tor.onion"_ns)) { + nsCOMPtr<IOnionAliasService> oas = do_GetService(ONIONALIAS_CID); + oas->GetOnionAlias(mHostName, mHostName); + } +} + NS_IMETHODIMP SSLServerCertVerificationJob::Run() { // Runs on a cert verification thread and only on parent process. diff --git a/security/manager/ssl/SSLServerCertVerification.h b/security/manager/ssl/SSLServerCertVerification.h index d01b367695c74b4152bb0ea205e2e1cf6812cf5b..32b5ab125093966b992a58d56d011a6814a5773b 100644 --- a/security/manager/ssl/SSLServerCertVerification.h +++ b/security/manager/ssl/SSLServerCertVerification.h @@ -139,7 +139,11 @@ class SSLServerCertVerificationJob : public Runnable { mStapledOCSPResponse(std::move(stapledOCSPResponse)), mSCTsFromTLSExtension(std::move(sctsFromTLSExtension)), mDCInfo(std::move(dcInfo)), - mResultTask(aResultTask) {} + mResultTask(aResultTask) { + FixOnionAlias(); + } + + void FixOnionAlias(); uint64_t mAddrForLogging; void* mPinArg; diff --git a/security/manager/ssl/StaticHPKPins.h b/security/manager/ssl/StaticHPKPins.h index 423fecbb5d3214e5f3ce771905c718e0f7cf451c..6c160deb48d70e516782878f1d225adc613afd61 100644 --- a/security/manager/ssl/StaticHPKPins.h +++ b/security/manager/ssl/StaticHPKPins.h @@ -289,6 +289,14 @@ static const StaticFingerprints kPinset_google = { kPinset_google_Data }; +static const char* const kPinset_tor_browser_Data[] = { + kISRG_Root_X1Fingerprint, +}; +static const StaticFingerprints kPinset_tor_browser = { + sizeof(kPinset_tor_browser_Data) / sizeof(const char*), + kPinset_tor_browser_Data +}; + static const char* const kPinset_facebook_Data[] = { kCOMODO_ECC_Certification_AuthorityFingerprint, kISRG_Root_X1Fingerprint, @@ -345,6 +353,7 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = { { "aus5.mozilla.org", true, true, true, 7, &kPinset_mozilla_services }, { "blogger.com", true, false, false, -1, &kPinset_google_root_pems }, { "blogspot.com", true, false, false, -1, &kPinset_google_root_pems }, + { "bridges.torproject.org", false, false, false, -1, &kPinset_tor_browser }, { "bugs.chromium.org", true, false, false, -1, &kPinset_google_root_pems }, { "build.chromium.org", true, false, false, -1, &kPinset_google_root_pems }, { "business.facebook.com", true, false, false, -1, &kPinset_facebook }, diff --git a/security/manager/ssl/nsSecureBrowserUI.cpp b/security/manager/ssl/nsSecureBrowserUI.cpp index 4f56d7319f3028409592795de9ab08e7677962dd..c6699a17c76c91432b6d02e8107688a92f728c08 100644 --- a/security/manager/ssl/nsSecureBrowserUI.cpp +++ b/security/manager/ssl/nsSecureBrowserUI.cpp @@ -9,6 +9,7 @@ #include "mozilla/Logging.h" #include "mozilla/Unused.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/nsMixedContentBlocker.h" #include "nsContentUtils.h" #include "nsIChannel.h" #include "nsDocShell.h" @@ -84,6 +85,17 @@ void nsSecureBrowserUI::RecomputeSecurityFlags() { } } } + + // any protocol routed over tor is secure + if (!(mState & nsIWebProgressListener::STATE_IS_SECURE)) { + nsCOMPtr<nsIURI> innerDocURI = NS_GetInnermostURI(win->GetDocumentURI()); + if (innerDocURI && + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innerDocURI)) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is onion")); + mState = (mState & ~nsIWebProgressListener::STATE_IS_INSECURE) | + nsIWebProgressListener::STATE_IS_SECURE; + } + } } // Add upgraded-state flags when request has been diff --git a/security/moz.build b/security/moz.build index b30e9c2f72a72bfc42bb6d07a6e2dcf0595722b0..7eb1fe6f94e1a78b47c632cd8b88ba80c52981a4 100644 --- a/security/moz.build +++ b/security/moz.build @@ -89,7 +89,8 @@ gyp_vars["nss_dist_obj_dir"] = "$PRODUCT_DIR/dist/bin" gyp_vars["disable_tests"] = 1 gyp_vars["disable_dbm"] = 1 gyp_vars["disable_libpkix"] = 1 -gyp_vars["enable_sslkeylogfile"] = 1 +# tor-browser#18885, tor-browser#21849 +gyp_vars["enable_sslkeylogfile"] = 0 # Whether we're using system NSS or Rust nssckbi, we don't need # to build C nssckbi gyp_vars["disable_ckbi"] = 1 diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index ac47e5098c4732c877665424ba6a0082a62ac2e9..b3103cf6d3894dfe3346747f3e73ae967bc0b0e9 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -2926,6 +2926,9 @@ loser: static PRFileDesc * ocsp_ConnectToHost(const char *host, PRUint16 port) { +#ifdef MOZ_PROXY_BYPASS_PROTECTION + return NULL; +#else PRFileDesc *sock = NULL; PRIntervalTime timeout; PRNetAddr addr; @@ -2984,6 +2987,7 @@ loser: if (netdbbuf != NULL) PORT_Free(netdbbuf); return NULL; +#endif } /* diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c index ac5e9d3796812e4bdfac3c8e8a30000d463902d8..ab49b5403427bf5ba9e4082ca149a01784dab3be 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c @@ -1322,6 +1322,9 @@ pkix_pl_Socket_Create( PKIX_PL_Socket **pSocket, void *plContext) { +#ifdef MOZ_PROXY_BYPASS_PROTECTION + PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); +#else PKIX_PL_Socket *socket = NULL; PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create"); @@ -1369,6 +1372,7 @@ cleanup: } PKIX_RETURN(SOCKET); +#endif } /* @@ -1418,6 +1422,9 @@ pkix_pl_Socket_CreateByName( PKIX_PL_Socket **pSocket, void *plContext) { +#ifdef MOZ_PROXY_BYPASS_PROTECTION + PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); +#else PRNetAddr netAddr; PKIX_PL_Socket *socket = NULL; char *sepPtr = NULL; @@ -1520,6 +1527,7 @@ cleanup: } PKIX_RETURN(SOCKET); +#endif } /* @@ -1571,6 +1579,9 @@ pkix_pl_Socket_CreateByHostAndPort( PKIX_PL_Socket **pSocket, void *plContext) { +#ifdef MOZ_PROXY_BYPASS_PROTECTION + PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); +#else PRNetAddr netAddr; PKIX_PL_Socket *socket = NULL; char *sepPtr = NULL; @@ -1658,6 +1669,7 @@ cleanup: } PKIX_RETURN(SOCKET); +#endif } /* diff --git a/security/nss/lib/mozpkix/include/pkix/Result.h b/security/nss/lib/mozpkix/include/pkix/Result.h index 5b788877ab2bf7ed4821303fe8d1ecd2c119c624..e40f018e37137defed493e9c4cf409f676794618 100644 --- a/security/nss/lib/mozpkix/include/pkix/Result.h +++ b/security/nss/lib/mozpkix/include/pkix/Result.h @@ -188,6 +188,8 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800; SEC_ERROR_LIBRARY_FAILURE) \ MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \ SEC_ERROR_NO_MEMORY) \ + MOZILLA_PKIX_MAP(ERROR_ONION_WITH_SELF_SIGNED_CERT, 155, \ + MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT) \ /* nothing here */ enum class Result { diff --git a/security/nss/lib/mozpkix/include/pkix/pkixnss.h b/security/nss/lib/mozpkix/include/pkix/pkixnss.h index 54249b5171f993536680ae4e37259b5389e580b5..e2ca2eb726d00960e4c79701a13796de8cd20fc2 100644 --- a/security/nss/lib/mozpkix/include/pkix/pkixnss.h +++ b/security/nss/lib/mozpkix/include/pkix/pkixnss.h @@ -94,6 +94,7 @@ enum ErrorCode { MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED = ERROR_BASE + 13, MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT = ERROR_BASE + 14, MOZILLA_PKIX_ERROR_MITM_DETECTED = ERROR_BASE + 15, + MOZILLA_PKIX_ERROR_ONION_WITH_SELF_SIGNED_CERT = ERROR_BASE + 100, END_OF_LIST }; diff --git a/security/nss/lib/ssl/Makefile b/security/nss/lib/ssl/Makefile index 61abff37211729c912b84aa3468a60c723badd7d..24c66b948c60d85c4f1ae4be73e620f5010a259e 100644 --- a/security/nss/lib/ssl/Makefile +++ b/security/nss/lib/ssl/Makefile @@ -37,7 +37,8 @@ endif # Enable key logging by default in debug builds, but not opt builds. # Logging still needs to be enabled at runtime through env vars. -NSS_ALLOW_SSLKEYLOGFILE ?= $(if $(BUILD_OPT),0,1) +# tor-browser#18885, tor-browser#21849 +NSS_ALLOW_SSLKEYLOGFILE ?= 0 ifeq (1,$(NSS_ALLOW_SSLKEYLOGFILE)) DEFINES += -DNSS_ALLOW_SSLKEYLOGFILE=1 endif diff --git a/security/sandbox/common/SandboxUtils.sys.mjs b/security/sandbox/common/SandboxUtils.sys.mjs index bf647aab76272431a7ccfe1f8900db95666f6380..e46e85cc43f5883bc6d9cedbc3c1bc4cab747eff 100644 --- a/security/sandbox/common/SandboxUtils.sys.mjs +++ b/security/sandbox/common/SandboxUtils.sys.mjs @@ -46,7 +46,7 @@ export var SandboxUtils = { let buttons = [ { - supportPage: "install-firefox-linux", + supportPage: "install-firefox-linux#w_security-features-warning", "l10n-id": "sandbox-unprivileged-namespaces-howtofix", }, { diff --git a/services/settings/Attachments.sys.mjs b/services/settings/Attachments.sys.mjs index 9982c27661199de8e16c04ecfa43791e36716808..cb18ef78d6383f38f4f7b6c8f303471fcb531479 100644 --- a/services/settings/Attachments.sys.mjs +++ b/services/settings/Attachments.sys.mjs @@ -355,6 +355,10 @@ export class Downloader { fallbackToDump = false; } + avoidDownload = true; + fallbackToCache = true; + fallbackToDump = true; + const dumpInfo = new LazyRecordAndBuffer(() => this._readAttachmentDump(attachmentId) ); @@ -576,6 +580,8 @@ export class Downloader { attachment: { location, hash, size }, } = record; + return (await this.#fetchAttachment(record)).buffer; + // eslint-disable-next-line no-unreachable let baseURL; try { baseURL = await lazy.Utils.baseAttachmentsURL(); diff --git a/services/settings/IDBHelpers.sys.mjs b/services/settings/IDBHelpers.sys.mjs index d77243b7a1d9142b36ef5cc889c6484203f10be2..30b9da761992039a6557b12eca95bf6160dd2b1f 100644 --- a/services/settings/IDBHelpers.sys.mjs +++ b/services/settings/IDBHelpers.sys.mjs @@ -180,6 +180,10 @@ async function openIDB(allowUpgrades = true) { }); } if (event.oldVersion < 3) { + // Clear existing stores for a fresh start + transaction.objectStore("records").clear(); + transaction.objectStore("timestamps").clear(); + transaction.objectStore("collections").clear(); // Attachment store db.createObjectStore("attachments", { keyPath: ["cid", "attachmentId"], diff --git a/services/settings/RemoteSettingsClient.sys.mjs b/services/settings/RemoteSettingsClient.sys.mjs index 7e98e6d5b3fc69bbaa75dafcc89002ca651ba280..7af897a35158b056332ae15999c716544a2c2684 100644 --- a/services/settings/RemoteSettingsClient.sys.mjs +++ b/services/settings/RemoteSettingsClient.sys.mjs @@ -431,11 +431,19 @@ export class RemoteSettingsClient extends EventEmitter { order = "", // not sorted by default. dumpFallback = true, emptyListFallback = true, - forceSync = false, loadDumpIfNewer = true, - syncIfEmpty = true, } = options; - let { verifySignature = false } = options; + + const hasLocalDump = await lazy.Utils.hasLocalDump( + this.bucketName, + this.collectionName + ); + if (!hasLocalDump) { + return []; + } + const forceSync = false; + const syncIfEmpty = true; + let verifySignature = false; const hasParallelCall = !!this._importingPromise; let data; @@ -605,6 +613,10 @@ export class RemoteSettingsClient extends EventEmitter { * @param {Object} options See #maybeSync() options. */ async sync(options) { + if (AppConstants.BASE_BROWSER_VERSION) { + return; + } + if (lazy.Utils.shouldSkipRemoteActivityDueToTests) { return; } @@ -671,7 +683,7 @@ export class RemoteSettingsClient extends EventEmitter { let thrownError = null; try { // If network is offline, we can't synchronize. - if (lazy.Utils.isOffline) { + if (!AppConstants.BASE_BROWSER_VERSION && lazy.Utils.isOffline) { throw new RemoteSettingsClient.NetworkOfflineError(); } @@ -1053,14 +1065,8 @@ export class RemoteSettingsClient extends EventEmitter { options = {} ) { const { retry = false } = options; - const since = retry || !localTimestamp ? undefined : `"${localTimestamp}"`; - // Fetch collection metadata and list of changes from server. - lazy.console.debug( - `${this.identifier} Fetch changes from server (expected=${expectedTimestamp}, since=${since})` - ); - const { metadata, remoteTimestamp, remoteRecords } = - await this._fetchChangeset(expectedTimestamp, since); + let metadata, remoteTimestamp; // We build a sync result, based on remote changes. const syncResult = { @@ -1069,24 +1075,20 @@ export class RemoteSettingsClient extends EventEmitter { updated: [], deleted: [], }; - // If data wasn't changed, return empty sync result. - // This can happen when we update the signature but not the data. - lazy.console.debug( - `${this.identifier} local timestamp: ${localTimestamp}, remote: ${remoteTimestamp}` - ); - if (localTimestamp && remoteTimestamp < localTimestamp) { + + try { + await this._importJSONDump(); + } catch (e) { return syncResult; } - await this.db.importChanges(metadata, remoteTimestamp, remoteRecords, { - clear: retry, - }); - // Read the new local data, after updating. const newLocal = await this.db.list(); const newRecords = newLocal.map(r => this._cleanLocalFields(r)); // And verify the signature on what is now stored. - if (this.verifySignature) { + if (metadata === undefined) { + // When working only with dumps, we do not have signatures. + } else if (this.verifySignature) { try { await this._validateCollectionSignature( newRecords, diff --git a/services/settings/dumps/gen_last_modified.py b/services/settings/dumps/gen_last_modified.py index d16eaa01e39429af034dadaaace22aab49a9fcd0..1151c1b30d97f2f0297bbabbcea87773d0f41a8c 100644 --- a/services/settings/dumps/gen_last_modified.py +++ b/services/settings/dumps/gen_last_modified.py @@ -63,8 +63,10 @@ def main(output): dumps_locations = [] if buildconfig.substs["MOZ_BUILD_APP"] == "browser": dumps_locations += ["services/settings/dumps/"] + dumps_locations += ["services/settings/static-dumps/"] elif buildconfig.substs["MOZ_BUILD_APP"] == "mobile/android": dumps_locations += ["services/settings/dumps/"] + dumps_locations += ["services/settings/static-dumps/"] elif buildconfig.substs["MOZ_BUILD_APP"] == "mobile/ios": dumps_locations += ["services/settings/dumps/"] elif buildconfig.substs["MOZ_BUILD_APP"] == "comm/mail": diff --git a/services/settings/dumps/main/moz.build b/services/settings/dumps/main/moz.build index f4f4f276875d589aaa93ce087e2898ae08dab580..335333d53fab23e8d46df747602d318873a2fc32 100644 --- a/services/settings/dumps/main/moz.build +++ b/services/settings/dumps/main/moz.build @@ -6,10 +6,6 @@ if CONFIG["MOZ_BUILD_APP"] == "browser": # These collections are only referenced from browser/ FINAL_TARGET_FILES.defaults.settings.main += [ "language-dictionaries.json", - "search-telemetry-v2.json", - "sites-classification.json", - "top-sites.json", - "urlbar-persisted-search-terms.json", ] # These collections are referenced in toolkit/ or other core code, however @@ -23,112 +19,8 @@ if not CONFIG["MOZ_BUILD_APP"].startswith("mobile/"): "example.json", "hijack-blocklists.json", "password-rules.json", - "search-config-icons.json", - "search-config-overrides-v2.json", - "search-config-v2.json", "search-default-override-allowlist.json", "translations-models.json", "translations-wasm.json", - "url-classifier-skip-urls.json", "websites-with-shared-credential-backends.json", ] - -# These collections are referenced in toolkit/ or other core code. -FINAL_TARGET_FILES.defaults.settings.main += [ - "password-recipes.json", -] - -# These search config icons only apply to desktop. -if CONFIG["MOZ_BUILD_APP"] == "browser": - FINAL_TARGET_FILES.defaults.settings.main["search-config-icons"] += [ - "search-config-icons/001500a9-1a6c-3f5a-ba15-a5f5a075d256", - "search-config-icons/001500a9-1a6c-3f5a-ba15-a5f5a075d256.meta.json", - "search-config-icons/06cf7432-efd7-f244-927b-5e423005e1ea", - "search-config-icons/06cf7432-efd7-f244-927b-5e423005e1ea.meta.json", - "search-config-icons/0d7668a8-c3f4-cfee-cbc8-536511528937", - "search-config-icons/0d7668a8-c3f4-cfee-cbc8-536511528937.meta.json", - "search-config-icons/0eec5640-6fde-d6fe-322a-c72c6d5bd5a2", - "search-config-icons/0eec5640-6fde-d6fe-322a-c72c6d5bd5a2.meta.json", - "search-config-icons/101ce01d-2691-b729-7f16-9d389803384b", - "search-config-icons/101ce01d-2691-b729-7f16-9d389803384b.meta.json", - "search-config-icons/177aba42-9bed-4078-e36b-580e8794cd7f", - "search-config-icons/177aba42-9bed-4078-e36b-580e8794cd7f.meta.json", - "search-config-icons/25de0352-aabb-d31f-15f7-bf9299fb004c", - "search-config-icons/25de0352-aabb-d31f-15f7-bf9299fb004c.meta.json", - "search-config-icons/2bbe48f4-d3b8-c9e0-86e3-a54c37ec3335", - "search-config-icons/2bbe48f4-d3b8-c9e0-86e3-a54c37ec3335.meta.json", - "search-config-icons/2e835b0e-9709-d1bb-9725-87f59f3445ca", - "search-config-icons/2e835b0e-9709-d1bb-9725-87f59f3445ca.meta.json", - "search-config-icons/32d26d19-aeb0-5c01-32e8-f8970be9246f", - "search-config-icons/32d26d19-aeb0-5c01-32e8-f8970be9246f.meta.json", - "search-config-icons/39979158-80cf-4f0c-8bd6-9220eb09e751", - "search-config-icons/39979158-80cf-4f0c-8bd6-9220eb09e751.meta.json", - "search-config-icons/47da97b5-600f-c450-fd15-a52bb2169c11", - "search-config-icons/47da97b5-600f-c450-fd15-a52bb2169c11.meta.json", - "search-config-icons/4e271681-3e0f-91ac-9750-03f665efc171", - "search-config-icons/4e271681-3e0f-91ac-9750-03f665efc171.meta.json", - "search-config-icons/50f6171f-8e7a-b41b-862e-f97397038fb2", - "search-config-icons/50f6171f-8e7a-b41b-862e-f97397038fb2.meta.json", - "search-config-icons/5ded611d-44b2-dc46-fd67-fb116888d75d", - "search-config-icons/5ded611d-44b2-dc46-fd67-fb116888d75d.meta.json", - "search-config-icons/5e03d6f4-6ee9-8bc8-cf22-7a5f2cf55c41", - "search-config-icons/5e03d6f4-6ee9-8bc8-cf22-7a5f2cf55c41.meta.json", - "search-config-icons/6a83583a-f0ba-fd39-2fdb-fd2b6990ea3b", - "search-config-icons/6a83583a-f0ba-fd39-2fdb-fd2b6990ea3b.meta.json", - "search-config-icons/6d10d702-7bd6-1452-90a5-3df665a38f66", - "search-config-icons/6d10d702-7bd6-1452-90a5-3df665a38f66.meta.json", - "search-config-icons/6f4da442-d31e-28f8-03af-797d16bbdd27", - "search-config-icons/6f4da442-d31e-28f8-03af-797d16bbdd27.meta.json", - "search-config-icons/70fdd651-6c50-b7bb-09ec-7e85da259173", - "search-config-icons/70fdd651-6c50-b7bb-09ec-7e85da259173.meta.json", - "search-config-icons/74793ce1-a918-a5eb-d3c0-2aadaff3c88c", - "search-config-icons/74793ce1-a918-a5eb-d3c0-2aadaff3c88c.meta.json", - "search-config-icons/7bbe6c5c-fdb8-2845-a4f4-e1382e708a0e", - "search-config-icons/7bbe6c5c-fdb8-2845-a4f4-e1382e708a0e.meta.json", - "search-config-icons/7bf4ca37-e2b8-4d31-a1c3-979bc0e85131", - "search-config-icons/7bf4ca37-e2b8-4d31-a1c3-979bc0e85131.meta.json", - "search-config-icons/7efbed51-813c-581d-d8d3-f8758434e451", - "search-config-icons/7efbed51-813c-581d-d8d3-f8758434e451.meta.json", - "search-config-icons/84bb4962-e571-227a-9ef6-2ac5f2aac361", - "search-config-icons/84bb4962-e571-227a-9ef6-2ac5f2aac361.meta.json", - "search-config-icons/87ac4cde-f581-398b-1e32-eb4079183b36", - "search-config-icons/87ac4cde-f581-398b-1e32-eb4079183b36.meta.json", - "search-config-icons/8831ce10-b1e4-6eb4-4975-83c67457288e", - "search-config-icons/8831ce10-b1e4-6eb4-4975-83c67457288e.meta.json", - "search-config-icons/890de5c4-0941-a116-473a-5d240e79497a", - "search-config-icons/890de5c4-0941-a116-473a-5d240e79497a.meta.json", - "search-config-icons/91a9672d-e945-8e1e-0996-aefdb0190716", - "search-config-icons/91a9672d-e945-8e1e-0996-aefdb0190716.meta.json", - "search-config-icons/96327a73-c433-5eb4-a16d-b090cadfb80b", - "search-config-icons/96327a73-c433-5eb4-a16d-b090cadfb80b.meta.json", - "search-config-icons/a06db97d-1210-ea2e-5474-0e2f7d295bfd", - "search-config-icons/a06db97d-1210-ea2e-5474-0e2f7d295bfd.meta.json", - "search-config-icons/a06dc3fd-4bdb-41f3-2ebc-4cbed06a9bd3", - "search-config-icons/a06dc3fd-4bdb-41f3-2ebc-4cbed06a9bd3.meta.json", - "search-config-icons/a2c7d4e9-f770-51e1-0963-3c2c8401631d", - "search-config-icons/a2c7d4e9-f770-51e1-0963-3c2c8401631d.meta.json", - "search-config-icons/b64f09fd-52d1-c48e-af23-4ce918e7bf3b", - "search-config-icons/b64f09fd-52d1-c48e-af23-4ce918e7bf3b.meta.json", - "search-config-icons/b8ca5a94-8fff-27ad-6e00-96e244a32e21", - "search-config-icons/b8ca5a94-8fff-27ad-6e00-96e244a32e21.meta.json", - "search-config-icons/c411adc1-9661-4fb5-a4c1-8cfe74911943", - "search-config-icons/c411adc1-9661-4fb5-a4c1-8cfe74911943.meta.json", - "search-config-icons/cbf9e891-d079-2b28-5617-283450d463dd", - "search-config-icons/cbf9e891-d079-2b28-5617-283450d463dd.meta.json", - "search-config-icons/d87f251c-3e12-a8bf-e2d0-afd43d36c5f9", - "search-config-icons/d87f251c-3e12-a8bf-e2d0-afd43d36c5f9.meta.json", - "search-config-icons/e02f23df-8d48-2b1b-3b5c-6dd27302c61c", - "search-config-icons/e02f23df-8d48-2b1b-3b5c-6dd27302c61c.meta.json", - "search-config-icons/e718e983-09aa-e8f6-b25f-cd4b395d4785", - "search-config-icons/e718e983-09aa-e8f6-b25f-cd4b395d4785.meta.json", - "search-config-icons/e7547f62-187b-b641-d462-e54a3f813d9a", - "search-config-icons/e7547f62-187b-b641-d462-e54a3f813d9a.meta.json", - "search-config-icons/f312610a-ebfb-a106-ea92-fd643c5d3636", - "search-config-icons/f312610a-ebfb-a106-ea92-fd643c5d3636.meta.json", - "search-config-icons/fa0fc42c-d91d-fca7-34eb-806ff46062dc", - "search-config-icons/fa0fc42c-d91d-fca7-34eb-806ff46062dc.meta.json", - "search-config-icons/fca3e3ee-56cd-f474-dc31-307fd24a891d", - "search-config-icons/fca3e3ee-56cd-f474-dc31-307fd24a891d.meta.json", - "search-config-icons/fed4f021-ff3e-942a-010e-afa43fda2136", - "search-config-icons/fed4f021-ff3e-942a-010e-afa43fda2136.meta.json", - ] diff --git a/services/settings/remote-settings.sys.mjs b/services/settings/remote-settings.sys.mjs index 7a5530abd2527074c7cbb66ad5c6e22383e095dc..8b1d4893d846eb4d825bbce005cd0c0736332ce9 100644 --- a/services/settings/remote-settings.sys.mjs +++ b/services/settings/remote-settings.sys.mjs @@ -91,6 +91,7 @@ export async function jexlFilterFunc(entry, environment) { function remoteSettingsFunction() { const _clients = new Map(); let _invalidatePolling = false; + let _initialized = false; // If not explicitly specified, use the default signer. const defaultOptions = { @@ -194,6 +195,39 @@ function remoteSettingsFunction() { trigger = "manual", full = false, } = {}) => { + if (AppConstants.BASE_BROWSER_VERSION) { + // Called multiple times on GeckoView due to bug 1730026 + if (_initialized) { + return; + } + _initialized = true; + let importedFromDump = false; + for (const client of _clients.values()) { + const hasLocalDump = await lazy.Utils.hasLocalDump( + client.bucketName, + client.collectionName + ); + if (hasLocalDump) { + const lastModified = await client.getLastModified(); + const lastModifiedDump = await lazy.Utils.getLocalDumpLastModified( + client.bucketName, + client.collectionName + ); + if (lastModified < lastModifiedDump) { + await client.maybeSync(lastModifiedDump, { + loadDump: true, + trigger, + }); + importedFromDump = true; + } + } + } + if (importedFromDump) { + Services.obs.notifyObservers(null, "remote-settings:changes-poll-end"); + } + return; + } + if (lazy.Utils.shouldSkipRemoteActivityDueToTests) { return; } diff --git a/services/settings/servicesSettings.manifest b/services/settings/servicesSettings.manifest index 3bfed26ea4d92029ae48ee4371613e84b65ae80b..d452910cfd3e6f7ffc14f319753ca489ad0f372d 100644 --- a/services/settings/servicesSettings.manifest +++ b/services/settings/servicesSettings.manifest @@ -4,4 +4,4 @@ resource services-settings resource://gre/modules/services-settings/ # Schedule polling of remote settings changes # (default 24H, max 72H) # see syntax https://searchfox.org/mozilla-central/rev/cc280c4be94ff8cf64a27cc9b3d6831ffa49fa45/toolkit/components/timermanager/UpdateTimerManager.jsm#155 -category update-timer RemoteSettingsComponents @mozilla.org/services/settings;1,getService,services-settings-poll-changes,services.settings.poll_interval,86400,259200 +# category update-timer RemoteSettingsComponents @mozilla.org/services/settings;1,getService,services-settings-poll-changes,services.settings.poll_interval,86400,259200 diff --git a/services/settings/static-dumps/main/moz.build b/services/settings/static-dumps/main/moz.build index de7b915d833ef94d49226410a14a7e34443cbce9..b62407ef14f383a40d7f8a5bca4e220966599df9 100644 --- a/services/settings/static-dumps/main/moz.build +++ b/services/settings/static-dumps/main/moz.build @@ -2,6 +2,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +FINAL_TARGET_FILES.defaults.settings.main += [ + "query-stripping.json", +] + if CONFIG["MOZ_BUILD_APP"] == "browser": DIST_SUBDIR = "browser" diff --git a/services/settings/static-dumps/main/query-stripping.json b/services/settings/static-dumps/main/query-stripping.json new file mode 100644 index 0000000000000000000000000000000000000000..ffc064bef7fa927a9c22916f90f765c49d64818c --- /dev/null +++ b/services/settings/static-dumps/main/query-stripping.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "schema": 1678379807899, + "allowList": [], + "stripList": [ + "gclid", + "dclid", + "msclkid", + "_openstat", + "yclid", + "wickedid", + "twclid", + "_hsenc", + "__hssc", + "__hstc", + "__hsfp", + "hsctatracking", + "wbraid", + "gbraid", + "ysclid" + ], + "id": "85078bad-f31e-4d93-bb8a-81088b25d6dd", + "last_modified": 1678736907773 + }, + { + "schema": 1649695008608, + "allowList": [], + "stripList": [ + "mc_eid", + "oly_anon_id", + "oly_enc_id", + "__s", + "vero_id", + "_hsenc", + "mkt_tok", + "fbclid" + ], + "id": "76495cfc-fac9-4079-9b5f-9ff0784484de", + "last_modified": 1649762862679 + } + ], + "timestamp": 1678736907773 +} diff --git a/services/sync/components.conf b/services/sync/components.conf index e4f82b35b1d53cc97a7a3aae781ec80f520a4abb..e100af3e971a9f2235240ac5de56b661ed5bd54e 100644 --- a/services/sync/components.conf +++ b/services/sync/components.conf @@ -11,10 +11,4 @@ Classes = [ 'esModule': 'resource://services-sync/Weave.sys.mjs', 'constructor': 'WeaveService', }, - { - 'cid': '{d28f8a0b-95da-48f4-b712-caf37097be41}', - 'contract_ids': ['@mozilla.org/network/protocol/about;1?what=sync-log'], - 'esModule': 'resource://services-sync/Weave.sys.mjs', - 'constructor': 'AboutWeaveLog', - }, ] diff --git a/testing/mozbase/mozinstall/mozinstall/mozinstall.py b/testing/mozbase/mozinstall/mozinstall/mozinstall.py index 7ff5b52d18c26d5bddf6709ef638671bd7a6b0e4..b756b96304878324aaa3a3251fdecf9184894e75 100644 --- a/testing/mozbase/mozinstall/mozinstall/mozinstall.py +++ b/testing/mozbase/mozinstall/mozinstall/mozinstall.py @@ -352,7 +352,8 @@ def _install_exe(src, dest): # possibly gets around UAC in vista (still need to run as administrator) os.environ["__compat_layer"] = "RunAsInvoker" - cmd = '"%s" /extractdir=%s' % (src, os.path.realpath(dest)) + cmd = '"%s" /S /D=%s' % (src, os.path.realpath(dest)) + # cmd = '"%s" /extractdir=%s' % (src, os.path.realpath(dest)) subprocess.check_call(cmd) diff --git a/testing/mozbase/setup_development.py b/testing/mozbase/setup_development.py index 73aba7aaee8dc89fa7b3c3b46df86ac9dd1991d1..07ae39031da7a742198cc2c4f21d0cd8c9088419 100755 --- a/testing/mozbase/setup_development.py +++ b/testing/mozbase/setup_development.py @@ -267,23 +267,28 @@ def main(args=sys.argv[1:]): os.environ.get("PATH", "").strip(os.path.pathsep), ) + current_file_path = os.path.abspath(__file__) + topobjdir = os.path.dirname(os.path.dirname(os.path.dirname(current_file_path))) + mach = str(os.path.join(topobjdir, "mach")) + # install non-mozbase dependencies # these need to be installed separately and the --no-deps flag # subsequently used due to a bug in setuptools; see # https://bugzilla.mozilla.org/show_bug.cgi?id=759836 pypi_deps = dict([(i, j) for i, j in alldeps.items() if i not in unrolled]) for package, version in pypi_deps.items(): - # easy_install should be available since we rely on setuptools - call(["easy_install", version]) + # Originally, Mozilla used easy_install here. + # That tool is deprecated, therefore we swich to pip. + call([sys.executable, mach, "python", "-m", "pip", "install", version]) # install packages required for unit testing for package in test_packages: - call(["easy_install", package]) + call([sys.executable, mach, "python", "-m", "pip", "install", package]) # install extra non-mozbase packages if desired if options.extra: for package in extra_packages: - call(["easy_install", package]) + call([sys.executable, mach, "python", "-m", "pip", "install", package]) if __name__ == "__main__": diff --git a/testing/mozharness/scripts/does_it_crash.py b/testing/mozharness/scripts/does_it_crash.py index 8dc8f15ce722032d21d7d49bf1fd53444c85d1bc..5e2d5ccc8c7dd45177edae8c806ebfffb4e5c70d 100755 --- a/testing/mozharness/scripts/does_it_crash.py +++ b/testing/mozharness/scripts/does_it_crash.py @@ -110,6 +110,13 @@ class DoesItCrash(BaseScript): for retry in range(3): if is_win: proc.send_signal(signal.CTRL_BREAK_EVENT) + + # Manually kill all processes we spawned, + # not sure why this is required, but without it we hang forever. + process_name = self.config["thing_to_run"].split("/")[-1] + subprocess.run( + ["taskkill", "/T", "/F", "/IM", process_name], check=True + ) else: os.killpg(proc.pid, signal.SIGKILL) try: diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h index fe9afa4ba295309c822e6b926375a5147428e502..5510660083a32f25616da46dfd1d669fb61ab8d1 100644 --- a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h +++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h @@ -15,7 +15,7 @@ #include "rtc_base/system/arch.h" -#if defined(WEBRTC_POSIX) +#if (defined(WEBRTC_POSIX) || defined(__MINGW32__)) #define WebRtcIsac_lrint lrint #elif (defined(WEBRTC_ARCH_X86) && defined(WIN32)) static __inline long int WebRtcIsac_lrint(double x_dbl) { diff --git a/third_party/libwebrtc/modules/desktop_capture/desktop_capture_types.h b/third_party/libwebrtc/modules/desktop_capture/desktop_capture_types.h index e777a45f92a0bd99ca2e4ad5106630580bc318db..eaa1385c2bbcea8beb9aba4d597a56a217557c8f 100644 --- a/third_party/libwebrtc/modules/desktop_capture/desktop_capture_types.h +++ b/third_party/libwebrtc/modules/desktop_capture/desktop_capture_types.h @@ -11,12 +11,14 @@ #ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_ #define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_ +// pid_t +#if !defined(XP_WIN) || defined(__MINGW32__) +#include <sys/types.h> +#else +typedef int pid_t; +#endif #include <stdint.h> -#ifdef XP_WIN // Moving this into the global namespace -typedef int pid_t; // matching what used to be in -#endif // video_capture_defines.h - namespace webrtc { enum class CaptureType { kWindow, kScreen, kAnyScreenContent }; diff --git a/third_party/libwebrtc/modules/desktop_capture/win/desktop_capture_utils.cc b/third_party/libwebrtc/modules/desktop_capture/win/desktop_capture_utils.cc index 476ddc4abace90a8d73e5972455f2ac7d2215c5d..bc429774c12318de14489035aef4e9a1eebd3fd7 100644 --- a/third_party/libwebrtc/modules/desktop_capture/win/desktop_capture_utils.cc +++ b/third_party/libwebrtc/modules/desktop_capture/win/desktop_capture_utils.cc @@ -10,7 +10,9 @@ #include "modules/desktop_capture/win/desktop_capture_utils.h" -#include "rtc_base/strings/string_builder.h" +#include <cstdio> +#include <cstdlib> +#include "stringapiset.h" namespace webrtc { namespace desktop_capture { @@ -20,11 +22,16 @@ namespace utils { std::string ComErrorToString(const _com_error& error) { char buffer[1024]; rtc::SimpleStringBuilder string_builder(buffer); - // Use _bstr_t to simplify the wchar to char conversion for ErrorMessage(). - _bstr_t error_message(error.ErrorMessage()); - string_builder.AppendFormat("HRESULT: 0x%08X, Message: %s", error.Error(), - static_cast<const char*>(error_message)); - return string_builder.str(); + string_builder.AppendFormat("HRESULT: 0x%08X, Message: ", error.Error()); +#ifdef _UNICODE + WideCharToMultiByte(CP_UTF8, 0, error.ErrorMessage(), -1, + buffer + string_builder.size(), + sizeof(buffer) - string_builder.size(), nullptr, nullptr); + buffer[sizeof(buffer) - 1] = 0; +#else + string_builder << error.ErrorMessage(); +#endif + return buffer; } } // namespace utils diff --git a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capture_session.cc b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capture_session.cc index f9429134dcb9442d156cc712f175484beca4b2f5..2f780bad781f5ef9b2dd858cb235b7be5b37f9e2 100644 --- a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capture_session.cc +++ b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capture_session.cc @@ -10,9 +10,9 @@ #include "modules/desktop_capture/win/wgc_capture_session.h" -#include <DispatcherQueue.h> +#include <dispatcherqueue.h> #include <windows.graphics.capture.interop.h> -#include <windows.graphics.directX.direct3d11.interop.h> +#include <windows.graphics.directx.direct3d11.interop.h> #include <windows.graphics.h> #include <wrl/client.h> #include <wrl/event.h> @@ -181,9 +181,7 @@ HRESULT WgcCaptureSession::StartCapture(const DesktopCaptureOptions& options) { if (!options.prefer_cursor_embedded()) { ComPtr<ABI::Windows::Graphics::Capture::IGraphicsCaptureSession2> session2; - if (SUCCEEDED(session_->QueryInterface( - ABI::Windows::Graphics::Capture::IID_IGraphicsCaptureSession2, - &session2))) { + if (SUCCEEDED(session_->QueryInterface(IID_PPV_ARGS(&session2)))) { session2->put_IsCursorCaptureEnabled(false); } } @@ -367,7 +365,7 @@ HRESULT WgcCaptureSession::ProcessFrame() { return hr; } - ComPtr<Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess> + ComPtr<ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess> direct3DDxgiInterfaceAccess; hr = d3d_surface->QueryInterface(IID_PPV_ARGS(&direct3DDxgiInterfaceAccess)); if (FAILED(hr)) { diff --git a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.cc b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.cc index 9c545597aa92d02779835aab9340e596cfeb122d..c7866df5714d32373f22f2317227bc0dec435c9f 100644 --- a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.cc +++ b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.cc @@ -10,7 +10,7 @@ #include "modules/desktop_capture/win/wgc_capturer_win.h" -#include <DispatcherQueue.h> +#include <dispatcherqueue.h> #include <windows.foundation.metadata.h> #include <windows.graphics.capture.h> diff --git a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.h b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.h index 30253d9db62b4854a2840dd869f9d00ca297d0bb..64c50e0cf00365fa98eab06cb415eb08d74ec0c2 100644 --- a/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.h +++ b/third_party/libwebrtc/modules/desktop_capture/win/wgc_capturer_win.h @@ -11,7 +11,7 @@ #ifndef MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_ #define MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_ -#include <DispatcherQueue.h> +#include <dispatcherqueue.h> #include <d3d11.h> #include <wrl/client.h> diff --git a/third_party/libwebrtc/modules/video_capture/windows/device_info_ds.h b/third_party/libwebrtc/modules/video_capture/windows/device_info_ds.h index a9a1449b9974c4c99de53a245b464c808d7a1fd6..72e9c764c39a15a8b188bf7de4c736737a87ce81 100644 --- a/third_party/libwebrtc/modules/video_capture/windows/device_info_ds.h +++ b/third_party/libwebrtc/modules/video_capture/windows/device_info_ds.h @@ -12,7 +12,7 @@ #define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_DEVICE_INFO_DS_H_ #include <dshow.h> -#include <Ks.h> +#include <ks.h> #include <dbt.h> #include "modules/video_capture/device_info_impl.h" diff --git a/third_party/libwebrtc/rtc_base/platform_thread_types.cc b/third_party/libwebrtc/rtc_base/platform_thread_types.cc index c3c6955a7b27c89bc9bdc313333e04542943513d..0c8d77134ae89f49f63c80adc5ea64151065ca3d 100644 --- a/third_party/libwebrtc/rtc_base/platform_thread_types.cc +++ b/third_party/libwebrtc/rtc_base/platform_thread_types.cc @@ -95,6 +95,8 @@ void SetCurrentThreadName(const char* name) { set_thread_description_func(::GetCurrentThread(), wide_thread_name); } +#if defined(_MSC_VER) + // SEH is only impelmented for the MSVC compiler // For details see: // https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code #pragma pack(push, 8) @@ -114,6 +116,7 @@ void SetCurrentThreadName(const char* name) { } __except (EXCEPTION_EXECUTE_HANDLER) { // NOLINT } #pragma warning(pop) +#endif // _MSC_VER #elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID) prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name)); // NOLINT #elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS) diff --git a/third_party/libwebrtc/rtc_base/socket.h b/third_party/libwebrtc/rtc_base/socket.h index 275294e6e35442c5c16340819632a08db710ff40..e06d5adca3e65463e192392a316c73701658e339 100644 --- a/third_party/libwebrtc/rtc_base/socket.h +++ b/third_party/libwebrtc/rtc_base/socket.h @@ -68,6 +68,20 @@ #define EHOSTUNREACH WSAEHOSTUNREACH #undef ENETUNREACH #define ENETUNREACH WSAENETUNREACH +#undef ENOTEMPTY +#define ENOTEMPTY WSAENOTEMPTY +#undef EPROCLIM +#define EPROCLIM WSAEPROCLIM +#undef EUSERS +#define EUSERS WSAEUSERS +#undef EDQUOT +#define EDQUOT WSAEDQUOT +#undef ESTALE +#define ESTALE WSAESTALE +#undef EREMOTE +#define EREMOTE WSAEREMOTE +#undef EACCES +#define EACCES WSAEACCES #define SOCKET_EACCES WSAEACCES #endif // WEBRTC_WIN diff --git a/third_party/libwebrtc/rtc_base/system/file_wrapper.cc b/third_party/libwebrtc/rtc_base/system/file_wrapper.cc index b768ad0417217ed0711caf090c3197c43e45bb8e..cee68eb7c6bc81c0aa7232956d0070c5c6d54245 100644 --- a/third_party/libwebrtc/rtc_base/system/file_wrapper.cc +++ b/third_party/libwebrtc/rtc_base/system/file_wrapper.cc @@ -22,7 +22,7 @@ #include "rtc_base/numerics/safe_conversions.h" #ifdef _WIN32 -#include <Windows.h> +#include <windows.h> #else #endif diff --git a/third_party/libwebrtc/rtc_base/win/create_direct3d_device.h b/third_party/libwebrtc/rtc_base/win/create_direct3d_device.h index 7c21f8720a4366771da1e5a8e7a668d7649df72c..e1991b3efb961242dc2f9704bcf60f5bf9be3594 100644 --- a/third_party/libwebrtc/rtc_base/win/create_direct3d_device.h +++ b/third_party/libwebrtc/rtc_base/win/create_direct3d_device.h @@ -11,8 +11,18 @@ #ifndef RTC_BASE_WIN_CREATE_DIRECT3D_DEVICE_H_ #define RTC_BASE_WIN_CREATE_DIRECT3D_DEVICE_H_ -#include <windows.graphics.directX.direct3d11.h> -#include <windows.graphics.directX.direct3d11.interop.h> +#include <windows.graphics.directx.direct3d11.h> +#ifndef __MINGW32__ +# include <windows.graphics.directX.direct3d11.interop.h> +#else +# include <dxgi.h> +# include <inspectable.h> +extern "C" { +// This function is only used in decltype(..) +HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice( + ::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice); +} +#endif #include <winerror.h> #include <wrl/client.h> diff --git a/third_party/sipcc/cpr_win_types.h b/third_party/sipcc/cpr_win_types.h index c4dfa0b72a497346b3cda988b9c1a46bedb60226..106e551728b93d06e2a18fe6f05e4e9c39070f35 100644 --- a/third_party/sipcc/cpr_win_types.h +++ b/third_party/sipcc/cpr_win_types.h @@ -40,15 +40,22 @@ typedef uint8_t boolean; * NOTE: size_t should already be declared by both the MinGW and Microsoft * SDKs. */ -#ifndef _SSIZE_T_ + +#if defined(_MSC_VER) && !defined(_SSIZE_T_) #define _SSIZE_T_ -typedef int ssize_t; +#if !defined(_WIN64) +typedef int32_t ssize_t; +#else +typedef int64_t ssize_t; +#endif #endif /* - * Define pid_t. + * Define pid_t for MSVC builds */ +#if defined(_WIN32) && defined (_MSC_VER) typedef int pid_t; +#endif /* * Define min/max diff --git a/third_party/sipcc/sdp_token.c b/third_party/sipcc/sdp_token.c index b570d8169009f66beb3b9bc07b10b70e1e940b3b..70f2a19138ea43cad6417c1b24a60c806d1ddbaf 100644 --- a/third_party/sipcc/sdp_token.c +++ b/third_party/sipcc/sdp_token.c @@ -4,6 +4,10 @@ #include <errno.h> +#if defined(SIP_OS_WINDOWS) && !defined(_MSC_VER) +#include <minmax.h> +#endif + #include "sdp_os_defs.h" #include "sipcc_sdp.h" #include "sdp_private.h" diff --git a/toolkit/.eslintrc.js b/toolkit/.eslintrc.js index 3528c798313aee749af942aaf643dd1a9595b395..374098e517115c5ff0df2609ba8b6d2e10fc1597 100644 --- a/toolkit/.eslintrc.js +++ b/toolkit/.eslintrc.js @@ -8,6 +8,6 @@ module.exports = { rules: { // XXX Bug 1326071 - This should be reduced down - probably to 20 or to // be removed & synced with the mozilla/recommended value. - complexity: ["error", 45], + complexity: ["error", 47], }, }; diff --git a/toolkit/actors/AboutHttpsOnlyErrorParent.sys.mjs b/toolkit/actors/AboutHttpsOnlyErrorParent.sys.mjs index 3d4ed65daa5fb2a3755abbeb9f6cec01cd477fc5..95420ab4a31dc7104ac7b77ad1bc3918529267ca 100644 --- a/toolkit/actors/AboutHttpsOnlyErrorParent.sys.mjs +++ b/toolkit/actors/AboutHttpsOnlyErrorParent.sys.mjs @@ -5,6 +5,8 @@ import { HomePage } from "resource:///modules/HomePage.sys.mjs"; import { PrivateBrowsingUtils } from "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"; +import { TorConnect } from "resource://gre/modules/TorConnect.sys.mjs"; + export class AboutHttpsOnlyErrorParent extends JSWindowActorParent { get browser() { return this.browsingContext.top.embedderElement; @@ -15,7 +17,10 @@ export class AboutHttpsOnlyErrorParent extends JSWindowActorParent { case "goBack": this.goBackFromErrorPage(this.browser); break; + case "ShouldShowTorConnect": + return TorConnect.shouldShowTorConnect; } + return undefined; } goBackFromErrorPage(aBrowser) { diff --git a/toolkit/actors/FilesFilterChild.sys.mjs b/toolkit/actors/FilesFilterChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..6f223567ef75272195952551e03e7f858f7d5557 --- /dev/null +++ b/toolkit/actors/FilesFilterChild.sys.mjs @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "console", () => { + return console.createInstance({ + prefix: "FilesFilter", + }); +}); + +export class FilesFilterChild extends JSWindowActorChild { + handleEvent(event) { + if (!Services.prefs.getBoolPref("browser.filesfilter.enabled", true)) { + return; + } + // drop or paste + const { composedTarget } = event; + const dt = event.clipboardData || event.dataTransfer; + + if ([...dt.files].some(f => f.mozFullPath)) { + if ( + ["HTMLInputElement", "HTMLTextAreaElement"].includes( + ChromeUtils.getClassName(composedTarget) + ) + ) { + event.preventDefault(); + lazy.console.log( + `Preventing path leak on ${event.type} for ${[...dt.files] + .map(f => `${f.name} (${f.mozFullPath})`) + .join(", ")}.` + ); + } + return; + } + + // "Paste Without Formatting" (ctrl+shift+V) in HTML editors coerces files into paths + if (!(event.clipboardData && /[\/\\]/.test(dt.getData("text")))) { + return; + } + + // check wether the clipboard contains a file + const { clipboard } = Services; + if ( + [clipboard.kSelectionClipboard, clipboard.kGlobalClipboard].some( + clipboardType => + clipboard.isClipboardTypeSupported(clipboardType) && + clipboard.hasDataMatchingFlavors( + ["application/x-moz-file"], + clipboardType + ) + ) + ) { + event.preventDefault(); + event.stopPropagation(); + lazy.console.log( + `Preventing path leak on "Paste Without Formatting" for ${dt.getData( + "text" + )}.` + ); + } + } +} diff --git a/toolkit/actors/FilesFilterParent.sys.mjs b/toolkit/actors/FilesFilterParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..444361d060be82ce2f996272b3c88f3f3f4c32cb --- /dev/null +++ b/toolkit/actors/FilesFilterParent.sys.mjs @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export class FilesFilterParent extends JSWindowActorParent { + // just a stub for now +} diff --git a/toolkit/actors/NetErrorChild.sys.mjs b/toolkit/actors/NetErrorChild.sys.mjs index db203d06308e1dfd5c0cf17dd330c5a929e0e83f..2ffd18005e996522c87c6ca2d1ed5444a64c2347 100644 --- a/toolkit/actors/NetErrorChild.sys.mjs +++ b/toolkit/actors/NetErrorChild.sys.mjs @@ -133,12 +133,15 @@ export class NetErrorChild extends RemotePageChild { shortDesc.appendChild(span); }, }; - - Services.uriFixup.checkHost( - info.fixedURI, - onLookupCompleteListener, - this.document.nodePrincipal.originAttributes - ); + try { + Services.uriFixup.checkHost( + info.fixedURI, + onLookupCompleteListener, + this.document.nodePrincipal.originAttributes + ); + } catch (e) { + // DNS resolution may fail synchronously if forbidden by proxy + } } // Get the header from the http response of the failed channel. This function diff --git a/toolkit/actors/NetErrorParent.sys.mjs b/toolkit/actors/NetErrorParent.sys.mjs index 071529976a5418559a19b29099929e59275f2cad..b172eee8ebfe40ffb9d3278765813b30ab092d25 100644 --- a/toolkit/actors/NetErrorParent.sys.mjs +++ b/toolkit/actors/NetErrorParent.sys.mjs @@ -19,6 +19,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs", HomePage: "resource:///modules/HomePage.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", }); class CaptivePortalObserver { @@ -337,6 +338,9 @@ export class NetErrorParent extends JSWindowActorParent { let win = browser.ownerGlobal; win.openPreferences("privacy-doh"); break; + case "ShouldShowTorConnect": + return lazy.TorConnect.shouldShowTorConnect; } + return undefined; } } diff --git a/toolkit/actors/moz.build b/toolkit/actors/moz.build index 3940049041e20d1c067d57064c67b6df07a90018..bc340543bf769d91886a01759dce07ceafc462f8 100644 --- a/toolkit/actors/moz.build +++ b/toolkit/actors/moz.build @@ -53,6 +53,8 @@ FINAL_TARGET_FILES.actors += [ "DateTimePickerChild.sys.mjs", "DateTimePickerParent.sys.mjs", "ExtFindChild.sys.mjs", + "FilesFilterChild.sys.mjs", + "FilesFilterParent.sys.mjs", "FindBarChild.sys.mjs", "FindBarParent.sys.mjs", "FinderChild.sys.mjs", diff --git a/toolkit/components/antitracking/antitracking.manifest b/toolkit/components/antitracking/antitracking.manifest index 5eb37f9a3f99d31c976c31e1070920c23917f664..872e6af07575a2f98af245b89f90c5779dbc00af 100644 --- a/toolkit/components/antitracking/antitracking.manifest +++ b/toolkit/components/antitracking/antitracking.manifest @@ -1 +1 @@ -category profile-after-change URLDecorationAnnotationsService @mozilla.org/tracking-url-decoration-service;1 process=main +# category profile-after-change URLDecorationAnnotationsService @mozilla.org/tracking-url-decoration-service;1 process=main diff --git a/toolkit/components/antitracking/components.conf b/toolkit/components/antitracking/components.conf index 6a584b493fba4af405d6655e0407fe38b5fd30e7..94c1b9b9e1a6c83647f1560884e0047a229e4b30 100644 --- a/toolkit/components/antitracking/components.conf +++ b/toolkit/components/antitracking/components.conf @@ -11,13 +11,6 @@ Classes = [ 'esModule': 'resource://gre/modules/TrackingDBService.sys.mjs', 'constructor': 'TrackingDBService', }, - { - 'cid': '{5874af6d-5719-4e1b-b155-ef4eae7fcb32}', - 'contract_ids': ['@mozilla.org/tracking-url-decoration-service;1'], - 'esModule': 'resource://gre/modules/URLDecorationAnnotationsService.sys.mjs', - 'constructor': 'URLDecorationAnnotationsService', - 'processes': ProcessSelector.MAIN_PROCESS_ONLY, - }, { 'cid': '{90d1fd17-2018-4e16-b73c-a04a26fa6dd4}', 'contract_ids': ['@mozilla.org/purge-tracker-service;1'], diff --git a/toolkit/components/downloads/DownloadCore.sys.mjs b/toolkit/components/downloads/DownloadCore.sys.mjs index 4c2a7639c95432d3b41f54c84dca9ff938447910..e4a2e19b1b2deae680f005358d9d3e735e122228 100644 --- a/toolkit/components/downloads/DownloadCore.sys.mjs +++ b/toolkit/components/downloads/DownloadCore.sys.mjs @@ -715,6 +715,10 @@ Download.prototype = { } this._promiseUnblock = (async () => { + if (this.allow) { + this.allow(); + return; + } try { await IOUtils.move(this.target.partFilePath, this.target.path); await this.target.refresh(); @@ -723,7 +727,6 @@ Download.prototype = { this._promiseUnblock = null; throw ex; } - this.succeeded = true; this.hasBlockedData = false; this._notifyChange(); @@ -953,7 +956,9 @@ Download.prototype = { await this._promiseCanceled; } // Ask the saver object to remove any partial data. - await this.saver.removeData(); + if (this.saver) { + await this.saver.removeData(); + } // For completeness, clear the number of bytes transferred. if (this.currentBytes != 0 || this.hasPartialData) { this.currentBytes = 0; diff --git a/toolkit/components/downloads/DownloadIntegration.sys.mjs b/toolkit/components/downloads/DownloadIntegration.sys.mjs index 11a866139a884a51eb090c8f829e936feefe7e22..c00a52692b533ece01342a0155946132c9670afd 100644 --- a/toolkit/components/downloads/DownloadIntegration.sys.mjs +++ b/toolkit/components/downloads/DownloadIntegration.sys.mjs @@ -1172,10 +1172,7 @@ var DownloadObserver = { case "blocked-automatic-download": if (AppConstants.MOZ_BUILD_APP == "browser") { DownloadIntegration._initializeDownloadSpamProtection(); - DownloadIntegration.downloadSpamProtection.update( - aData, - aSubject.topChromeWindow - ); + DownloadIntegration.downloadSpamProtection.update(aData, aSubject); } break; } diff --git a/toolkit/components/extensions/Extension.sys.mjs b/toolkit/components/extensions/Extension.sys.mjs index ead52808306afd809eb81c7240f98c093c7f51e7..84fe4f0a98ccd33a4fe49420ff56a7f12920fe71 100644 --- a/toolkit/components/extensions/Extension.sys.mjs +++ b/toolkit/components/extensions/Extension.sys.mjs @@ -935,6 +935,15 @@ export class ExtensionData { this.eventPagesEnabled = lazy.eventPagesEnabled; } + /** + * Whether this is the NoScript extension. + * + * @type {boolean} + */ + get isNoScript() { + return this.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}"; + } + /** * A factory function that allows the construction of ExtensionData, with * the isPrivileged flag computed asynchronously. @@ -3750,6 +3759,15 @@ export class Extension extends ExtensionData { this.permissions.add(PRIVATE_ALLOWED_PERMISSION); } + // Bug 40253: Explicitly allow NoScript in Private Browsing mode. + if (this.isNoScript) { + lazy.ExtensionPermissions.add(this.id, { + permissions: [PRIVATE_ALLOWED_PERMISSION], + origins: [], + }); + this.permissions.add(PRIVATE_ALLOWED_PERMISSION); + } + // We only want to update the SVG_CONTEXT_PROPERTIES_PERMISSION during // install and upgrade/downgrade startups. if (INSTALL_AND_UPDATE_STARTUP_REASONS.has(this.startupReason)) { diff --git a/toolkit/components/extensions/ExtensionParent.sys.mjs b/toolkit/components/extensions/ExtensionParent.sys.mjs index 7c77aec3ba689aba525b5d7c6243e87586b7fd6d..c430c8d5b6bd320889a369ae01bace6dfc3b994e 100644 --- a/toolkit/components/extensions/ExtensionParent.sys.mjs +++ b/toolkit/components/extensions/ExtensionParent.sys.mjs @@ -252,6 +252,8 @@ const ProxyMessenger = { /** @type {Map<number, Promise>} */ portPromises: new Map(), + _torRuntimeMessageListeners: [], + init() { this.conduit = new lazy.BroadcastConduit(ProxyMessenger, { id: "ProxyMessenger", @@ -352,6 +354,10 @@ const ProxyMessenger = { }, async recvRuntimeMessage(arg, { sender }) { + // We need to listen to some extension messages in Tor Browser + for (const listener of this._torRuntimeMessageListeners) { + listener(arg); + } arg.firstResponse = true; let kind = await this.normalizeArgs(arg, sender); arg.query = true; @@ -2333,6 +2339,44 @@ var StartupCache = { Services.obs.addObserver(StartupCache, "startupcache-invalidate"); +async function torSendExtensionMessage(extensionId, message) { + // This should broadcast the message to all children "conduits" + // listening for a "RuntimeMessage". Those children conduits + // will either be extension background pages or other extension + // pages listening to browser.runtime.onMessage. + const result = await ProxyMessenger.conduit.castRuntimeMessage("messenger", { + extensionId, + holder: new StructuredCloneHolder("torSendExtensionMessage", null, message), + firstResponse: true, + sender: { + id: extensionId, + envType: "addon_child", + }, + }); + return result + ? result.value + : Promise.reject({ message: ERROR_NO_RECEIVERS }); +} + +async function torWaitForExtensionMessage(extensionId, checker) { + return new Promise(resolve => { + const msgListener = msg => { + try { + if (msg && msg.extensionId === extensionId) { + const deserialized = msg.holder.deserialize({}); + if (checker(deserialized)) { + const idx = + ProxyMessenger._torRuntimeMessageListeners.indexOf(msgListener); + ProxyMessenger._torRuntimeMessageListeners.splice(idx, 1); + resolve(deserialized); + } + } + } catch (e) {} + }; + ProxyMessenger._torRuntimeMessageListeners.push(msgListener); + }); +} + export var ExtensionParent = { GlobalManager, HiddenExtensionPage, @@ -2345,6 +2389,8 @@ export var ExtensionParent = { watchExtensionProxyContextLoad, watchExtensionWorkerContextLoaded, DebugUtils, + torSendExtensionMessage, + torWaitForExtensionMessage, }; // browserPaintedPromise and browserStartupPromise are promises that diff --git a/toolkit/components/httpsonlyerror/content/errorpage.js b/toolkit/components/httpsonlyerror/content/errorpage.js index f2933252ba68fcf8651d903e8a928f6cf0962638..c21474757866c65c36a6a162903b57c0d334ebde 100644 --- a/toolkit/components/httpsonlyerror/content/errorpage.js +++ b/toolkit/components/httpsonlyerror/content/errorpage.js @@ -127,8 +127,17 @@ function addAutofocus(selector, position = "afterbegin") { /* Initialize Page */ -initPage(); -// Dispatch this event so tests can detect that we finished loading the error page. -// We're using the same event name as neterror because BrowserTestUtils.sys.mjs relies on that. -let event = new CustomEvent("AboutNetErrorLoad", { bubbles: true }); -document.dispatchEvent(event); +RPMSendQuery("ShouldShowTorConnect").then(shouldShow => { + if (shouldShow) { + // pass orginal destination as redirect param + const encodedRedirect = encodeURIComponent(document.location.href); + document.location.replace(`about:torconnect?redirect=${encodedRedirect}`); + return; + } + + initPage(); + // Dispatch this event so tests can detect that we finished loading the error page. + // We're using the same event name as neterror because BrowserTestUtils.sys.mjs relies on that. + let event = new CustomEvent("AboutNetErrorLoad", { bubbles: true }); + document.dispatchEvent(event); +}); diff --git a/toolkit/components/lox/Lox.sys.mjs b/toolkit/components/lox/Lox.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..b9c56a8f3a02bfbd9f010c1f81cbaec7bf8be401 --- /dev/null +++ b/toolkit/components/lox/Lox.sys.mjs @@ -0,0 +1,1150 @@ +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; +import { + clearInterval, + setInterval, +} from "resource://gre/modules/Timer.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "logger", () => { + return console.createInstance({ + maxLogLevel: "Warn", + maxLogLevelPref: "lox.log_level", + prefix: "Lox", + }); +}); + +ChromeUtils.defineESModuleGetters(lazy, { + DomainFrontRequestBuilder: + "resource://gre/modules/DomainFrontedRequests.sys.mjs", + DomainFrontRequestNetworkError: + "resource://gre/modules/DomainFrontedRequests.sys.mjs", + DomainFrontRequestResponseError: + "resource://gre/modules/DomainFrontedRequests.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", + TorConnectStage: "resource://gre/modules/TorConnect.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", + TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs", + TorBridgeSource: "resource://gre/modules/TorSettings.sys.mjs", +}); + +// eslint-disable-next-line mozilla/reject-chromeutils-import +XPCOMUtils.defineLazyModuleGetters(lazy, { + init: "resource://gre/modules/lox_wasm.jsm", + open_invite: "resource://gre/modules/lox_wasm.jsm", + handle_new_lox_credential: "resource://gre/modules/lox_wasm.jsm", + set_panic_hook: "resource://gre/modules/lox_wasm.jsm", + invitation_is_trusted: "resource://gre/modules/lox_wasm.jsm", + issue_invite: "resource://gre/modules/lox_wasm.jsm", + handle_issue_invite: "resource://gre/modules/lox_wasm.jsm", + prepare_invite: "resource://gre/modules/lox_wasm.jsm", + get_invites_remaining: "resource://gre/modules/lox_wasm.jsm", + get_trust_level: "resource://gre/modules/lox_wasm.jsm", + level_up: "resource://gre/modules/lox_wasm.jsm", + handle_level_up: "resource://gre/modules/lox_wasm.jsm", + trust_promotion: "resource://gre/modules/lox_wasm.jsm", + handle_trust_promotion: "resource://gre/modules/lox_wasm.jsm", + trust_migration: "resource://gre/modules/lox_wasm.jsm", + handle_trust_migration: "resource://gre/modules/lox_wasm.jsm", + get_next_unlock: "resource://gre/modules/lox_wasm.jsm", + check_blockage: "resource://gre/modules/lox_wasm.jsm", + handle_check_blockage: "resource://gre/modules/lox_wasm.jsm", + blockage_migration: "resource://gre/modules/lox_wasm.jsm", + handle_blockage_migration: "resource://gre/modules/lox_wasm.jsm", + check_lox_pubkeys_update: "resource://gre/modules/lox_wasm.jsm", + handle_update_cred: "resource://gre/modules/lox_wasm.jsm", +}); + +export const LoxTopics = Object.freeze({ + // Whenever the activeLoxId value changes. + UpdateActiveLoxId: "lox:update-active-lox-id", + // Whenever the bridges *might* have changed. + // getBridges only uses #credentials, so this will only fire when it changes. + UpdateBridges: "lox:update-bridges", + // Whenever we gain a new upgrade or blockage event, or clear events. + UpdateEvents: "lox:update-events", + // Whenever the next unlock *might* have changed. + // getNextUnlock uses #credentials and #constants, so will fire when either + // value changes. + UpdateNextUnlock: "lox:update-next-unlock", + // Whenever the remaining invites *might* have changed. + // getRemainingInviteCount only uses #credentials, so will only fire when it + // changes. + UpdateRemainingInvites: "lox:update-remaining-invites", + // Whenever we generate a new invite. + NewInvite: "lox:new-invite", +}); + +const LoxSettingsPrefs = Object.freeze({ + /* string: the lox credential */ + credentials: "lox.settings.credentials", + invites: "lox.settings.invites", + events: "lox.settings.events", + pubkeys: "lox.settings.pubkeys", + enctable: "lox.settings.enctable", + constants: "lox.settings.constants", +}); + +/** + * Error class for Lox. + */ +export class LoxError extends Error { + static BadInvite = "BadInvite"; + static LoxServerUnreachable = "LoxServerUnreachable"; + static ErrorResponse = "ErrorResponse"; + + /** + * @param {string} message - The error message. + * @param {string?} [code] - The specific error type, if any. + */ + constructor(message, code = null) { + super(message); + this.name = "LoxError"; + this.code = code; + } +} + +/** + * This class contains the implementation of the Lox client. + * It provides data for the frontend and it runs background operations. + */ +class LoxImpl { + /** + * Whether the Lox module has completed initialization. + * + * @type {boolean} + */ + #initialized = false; + + /** + * Whether the Lox module is enabled for this Tor Browser instance. + * + * @type {boolean} + */ + #enabled = AppConstants.MOZ_UPDATE_CHANNEL !== "release"; + + get enabled() { + return this.#enabled; + } + + #pubKeyPromise = null; + #encTablePromise = null; + #constantsPromise = null; + #domainFrontedRequests = null; + /** + * The list of invites generated. + * + * @type {string[]} + */ + #invites = []; + #pubKeys = null; + #encTable = null; + #constants = null; + /** + * The latest credentials for a given lox id. + * + * @type {Map<string, string>} + */ + #credentials = new Map(); + /** + * The list of accumulated blockage or upgrade events. + * + * This can be cleared when the user acknowledges the events. + * + * @type {EventData[]} + */ + #events = []; + #backgroundInterval = null; + + /** + * The lox ID that is currently active. + * + * Stays in sync with TorSettings.bridges.lox_id. null when uninitialized. + * + * @type {string?} + */ + #activeLoxId = null; + + get activeLoxId() { + return this.#activeLoxId; + } + + /** + * Update the active lox id. + */ + #updateActiveLoxId() { + const loxId = lazy.TorSettings.bridges.lox_id; + if (loxId === this.#activeLoxId) { + return; + } + lazy.logger.debug( + `#activeLoxId switching from "${this.#activeLoxId}" to "${loxId}"` + ); + if (this.#activeLoxId !== null) { + lazy.logger.debug( + `Clearing event data and invites for "${this.#activeLoxId}"` + ); + // If not initializing clear the metadata for the old lox ID when it + // changes. + this.clearEventData(this.#activeLoxId); + // TODO: Do we want to keep invites? See tor-browser#42453 + this.#invites = []; + this.#store(); + } + this.#activeLoxId = loxId; + + Services.obs.notifyObservers(null, LoxTopics.UpdateActiveLoxId); + } + + observe(subject, topic) { + switch (topic) { + case lazy.TorSettingsTopics.SettingsChanged: { + const { changes } = subject.wrappedJSObject; + if ( + changes.includes("bridges.enabled") || + changes.includes("bridges.source") || + changes.includes("bridges.lox_id") + ) { + // The lox_id may have changed. + this.#updateActiveLoxId(); + + // Only run background tasks if Lox is enabled + if (this.#inuse) { + if (!this.#backgroundInterval) { + this.#backgroundInterval = setInterval( + this.#backgroundTasks.bind(this), + 1000 * 60 * 60 * 12 + ); + } + } else if (this.#backgroundInterval) { + clearInterval(this.#backgroundInterval); + this.#backgroundInterval = null; + } + } + break; + } + case lazy.TorSettingsTopics.Ready: + // Set the initial #activeLoxId. + this.#updateActiveLoxId(); + // Run background tasks every 12 hours if Lox is enabled + if (this.#inuse) { + this.#backgroundInterval = setInterval( + this.#backgroundTasks.bind(this), + 1000 * 60 * 60 * 12 + ); + } + break; + } + } + + /** + * Assert that the module is initialized. + */ + #assertInitialized() { + if (!this.enabled || !this.#initialized) { + throw new LoxError("Not initialized"); + } + } + + get #inuse() { + return ( + this.enabled && + Boolean(this.#activeLoxId) && + lazy.TorSettings.bridges.enabled === true && + lazy.TorSettings.bridges.source === lazy.TorBridgeSource.Lox + ); + } + + /** + * Stores a promise for the last task that was performed to change + * credentials for a given lox ID. This promise completes when the task + * completes and it is safe to perform a new action on the credentials. + * + * This essentially acts as a lock on the credential, so that only one task + * acts on the credentials at any given time. See tor-browser#42492. + * + * @type {Map<string, Promise>} + */ + #credentialsTasks = new Map(); + + /** + * Attempt to change some existing credentials for an ID to a new value. + * + * Each call for the same lox ID must await the previous call. As such, this + * should *never* be called recursively. + * + * @param {string} loxId - The ID to change the credentials for. + * @param {Function} task - The task that performs the change in credentials. + * The method is given the current credentials. It should either return the + * new credentials as a string, or null if the credentials should not + * change, or throw an error which will fall through to the caller. + * + * @returns {?string} - The credentials returned by the task, if any. + */ + async #changeCredentials(loxId, task) { + // Read and replace #credentialsTasks before we do any async operations. + // I.e. this is effectively atomic read and replace. + const prevTask = this.#credentialsTasks.get(loxId); + let taskComplete; + this.#credentialsTasks.set( + loxId, + new Promise(res => { + taskComplete = res; + }) + ); + + // Wait for any previous task to complete first, to avoid making conflicting + // changes to the credentials. See tor-browser#42492. + // prevTask is either undefined or a promise that should not throw. + await prevTask; + + // Future calls now await us. + + const cred = this.#getCredentials(loxId); + let newCred = null; + try { + // This task may throw, in which case we do not set new credentials. + newCred = await task(cred); + if (newCred) { + this.#credentials.set(loxId, newCred); + // Store the new credentials. + this.#store(); + lazy.logger.debug("Changed credentials"); + } + } finally { + // Stop awaiting us. + taskComplete(); + } + + if (!newCred) { + return null; + } + + // Let listeners know we have new credentials. We do this *after* calling + // taskComplete to avoid a recursive call to await this.#changeCredentials, + // which would cause us to hang. + + // NOTE: In principle we could determine within this module whether the + // bridges, remaining invites, or next unlock changes in value when + // switching credentials. + // However, this logic can be done by the topic observers, as needed. In + // particular, TorSettings.bridges.bridge_strings has its own logic + // determining whether its value has changed. + + // Let TorSettings know about possibly new bridges. + Services.obs.notifyObservers(null, LoxTopics.UpdateBridges); + // Let UI know about changes. + Services.obs.notifyObservers(null, LoxTopics.UpdateRemainingInvites); + Services.obs.notifyObservers(null, LoxTopics.UpdateNextUnlock); + + return newCred; + } + + /** + * Fetch the latest credentials. + * + * @param {string} loxId - The ID to get the credentials for. + * + * @returns {string} - The credentials. + */ + #getCredentials(loxId) { + const cred = loxId ? this.#credentials.get(loxId) : undefined; + if (!cred) { + throw new LoxError(`No credentials for ${loxId}`); + } + return cred; + } + + /** + * Formats and returns bridges from the stored Lox credential. + * + * @param {string} loxId The id string associated with a lox credential. + * + * @returns {string[]} An array of formatted bridge lines. The array is empty + * if there are no bridges. + */ + getBridges(loxId) { + this.#assertInitialized(); + // Note: this is messy now but can be mostly removed after we have + // https://gitlab.torproject.org/tpo/anti-censorship/lox/-/issues/46 + let bridgelines = JSON.parse(this.#getCredentials(loxId)).bridgelines; + let bridges = []; + for (const bridge of bridgelines) { + let addr = bridge.addr; + while (addr[addr.length - 1] === 0) { + addr.pop(); + } + addr = new Uint8Array(addr); + let decoder = new TextDecoder("utf-8"); + addr = decoder.decode(addr); + + let info = bridge.info; + while (info[info.length - 1] === 0) { + info.pop(); + } + info = new Uint8Array(info); + info = decoder.decode(info); + + let regexpTransport = /type=([a-zA-Z0-9]*)/; + let transport = info.match(regexpTransport); + if (transport !== null) { + transport = transport[1]; + } else { + transport = ""; + } + + let regexpFingerprint = /fingerprint=\"([a-zA-Z0-9]*)\"/; + let fingerprint = info.match(regexpFingerprint); + if (fingerprint !== null) { + fingerprint = fingerprint[1]; + } else { + fingerprint = ""; + } + + let regexpParams = /params=Some\(\{(.*)\}\)/; + let params = info.match(regexpParams); + if (params !== null) { + params = params[1] + .replaceAll('"', "") + .replaceAll(": ", "=") + .replaceAll(",", " "); + } else { + params = ""; + } + + bridges.push( + `${transport} ${addr}:${bridge.port} ${fingerprint} ${params}` + ); + } + return bridges; + } + + #store() { + Services.prefs.setStringPref(LoxSettingsPrefs.pubkeys, this.#pubKeys); + Services.prefs.setStringPref(LoxSettingsPrefs.enctable, this.#encTable); + Services.prefs.setStringPref(LoxSettingsPrefs.constants, this.#constants); + Services.prefs.setStringPref( + LoxSettingsPrefs.credentials, + JSON.stringify(Object.fromEntries(this.#credentials)) + ); + Services.prefs.setStringPref( + LoxSettingsPrefs.invites, + JSON.stringify(this.#invites) + ); + Services.prefs.setStringPref( + LoxSettingsPrefs.events, + JSON.stringify(this.#events) + ); + } + + #load() { + const cred = Services.prefs.getStringPref(LoxSettingsPrefs.credentials, ""); + this.#credentials = new Map(cred ? Object.entries(JSON.parse(cred)) : []); + const invites = Services.prefs.getStringPref(LoxSettingsPrefs.invites, ""); + this.#invites = invites ? JSON.parse(invites) : []; + const events = Services.prefs.getStringPref(LoxSettingsPrefs.events, ""); + this.#events = events ? JSON.parse(events) : []; + this.#pubKeys = Services.prefs.getStringPref( + LoxSettingsPrefs.pubkeys, + null + ); + this.#encTable = Services.prefs.getStringPref( + LoxSettingsPrefs.enctable, + null + ); + this.#constants = Services.prefs.getStringPref( + LoxSettingsPrefs.constants, + null + ); + } + + /** + * Update Lox credential after Lox key rotation. + * + * Do not call directly, use #getPubKeys() instead to start the update only + * once. + */ + async #updatePubkeys() { + let pubKeys = await this.#makeRequest("pubkeys", null); + const prevKeys = this.#pubKeys; + if (prevKeys !== null) { + // check if the lox pubkeys have changed and update the lox + // credentials if so. + await this.#changeCredentials(this.#activeLoxId, async cred => { + // The UpdateCredOption rust struct serializes to "req" rather than + // "request". + const { updated, req: request } = JSON.parse( + lazy.check_lox_pubkeys_update(pubKeys, prevKeys, cred) + ); + if (!updated) { + return null; + } + // Try update credentials. + // NOTE: This should be re-callable if any step fails. + // TODO: Verify this. + lazy.logger.debug( + `Lox pubkey updated, update Lox credential "${this.#activeLoxId}"` + ); + // TODO: If this call doesn't succeed due to a networking error, the Lox + // credential may be in an unusable state (spent but not updated) + // until this request can be completed successfully (and until Lox + // is refactored to send repeat responses: + // https://gitlab.torproject.org/tpo/anti-censorship/lox/-/issues/74) + let response = await this.#makeRequest("updatecred", request); + return lazy.handle_update_cred(request, response, pubKeys); + }); + } + // If we arrive here we haven't had other errors before, we can actually + // store the new public key. + this.#pubKeys = pubKeys; + this.#store(); + } + + async #getPubKeys() { + // FIXME: We are always refetching #pubKeys, #encTable and #constants once + // per session, but they may change more frequently. tor-browser#42502 + if (this.#pubKeyPromise === null) { + this.#pubKeyPromise = this.#updatePubkeys().catch(error => { + lazy.logger.debug("Failed to update pubKeys", error); + // Try again with the next call. + this.#pubKeyPromise = null; + if (!this.#pubKeys) { + // Re-throw if we have no pubKeys value for the caller. + throw error; + } + }); + } + await this.#pubKeyPromise; + } + + async #getEncTable() { + if (this.#encTablePromise === null) { + this.#encTablePromise = this.#makeRequest("reachability", null) + .then(encTable => { + this.#encTable = encTable; + this.#store(); + }) + .catch(error => { + lazy.logger.debug("Failed to get encTable", error); + // Make the next call try again. + this.#encTablePromise = null; + // Try to update first, but if that doesn't work fall back to stored data + if (!this.#encTable) { + throw error; + } + }); + } + await this.#encTablePromise; + } + + async #getConstants() { + if (this.#constantsPromise === null) { + // Try to update first, but if that doesn't work fall back to stored data + this.#constantsPromise = this.#makeRequest("constants", null) + .then(constants => { + const prevValue = this.#constants; + this.#constants = constants; + this.#store(); + if (prevValue !== this.#constants) { + Services.obs.notifyObservers(null, LoxTopics.UpdateNextUnlock); + } + }) + .catch(error => { + lazy.logger.debug("Failed to get constants", error); + // Make the next call try again. + this.#constantsPromise = null; + if (!this.#constants) { + throw error; + } + }); + } + await this.#constantsPromise; + } + + /** + * Parse a decimal string to a non-negative integer. + * + * @param {string} str - The string to parse. + * @returns {integer} - The integer. + */ + static #parseNonNegativeInteger(str) { + if (typeof str !== "string" || !/^[0-9]+$/.test(str)) { + throw new LoxError(`Expected a non-negative decimal integer: "${str}"`); + } + return parseInt(str, 10); + } + + /** + * Get the current lox trust level. + * + * @param {string} loxId - The ID to fetch the level for. + * @returns {integer} - The trust level. + */ + #getLevel(loxId) { + return LoxImpl.#parseNonNegativeInteger( + lazy.get_trust_level(this.#getCredentials(loxId)) + ); + } + + /** + * Check for blockages and attempt to perform a levelup + * + * If either blockages or a levelup happened, add an event to the event queue + */ + async #backgroundTasks() { + this.#assertInitialized(); + // Only run background tasks for the active lox ID. + const loxId = this.#activeLoxId; + if (!loxId) { + lazy.logger.warn("No loxId for the background task"); + return; + } + + // Attempt to update pubkeys each time background tasks are run + // this should catch key rotations (ideally some days) prior to the next + // credential update + await this.#getPubKeys(); + let levelup = false; + try { + levelup = await this.#attemptUpgrade(loxId); + } catch (error) { + lazy.logger.error(error); + } + if (levelup) { + const level = this.#getLevel(loxId); + const newEvent = { + type: "levelup", + newlevel: level, + }; + this.#events.push(newEvent); + this.#store(); + } + + let leveldown = false; + try { + leveldown = await this.#blockageMigration(loxId); + } catch (error) { + lazy.logger.error(error); + } + if (leveldown) { + let level = this.#getLevel(loxId); + const newEvent = { + type: "blockage", + newlevel: level, + }; + this.#events.push(newEvent); + this.#store(); + } + + if (levelup || leveldown) { + Services.obs.notifyObservers(null, LoxTopics.UpdateEvents); + } + } + + /** + * Generates a new random lox id to be associated with an invitation/credential + * + * @returns {string} + */ + #genLoxId() { + return crypto.randomUUID(); + } + + async init() { + if (!this.enabled) { + lazy.logger.info( + "Skipping initialization since Lox module is not enabled" + ); + return; + } + // If lox_id is set, load it + Services.obs.addObserver(this, lazy.TorSettingsTopics.SettingsChanged); + Services.obs.addObserver(this, lazy.TorSettingsTopics.Ready); + + // Hack to make the generated wasm happy + const win = { crypto }; + win.window = win; + await lazy.init(win); + lazy.set_panic_hook(); + if (typeof lazy.open_invite !== "function") { + throw new LoxError("Initialization failed"); + } + this.#load(); + this.#initialized = true; + } + + async uninit() { + if (!this.enabled) { + return; + } + Services.obs.removeObserver(this, lazy.TorSettingsTopics.SettingsChanged); + Services.obs.removeObserver(this, lazy.TorSettingsTopics.Ready); + if (this.#domainFrontedRequests !== null) { + try { + const domainFronting = await this.#domainFrontedRequests; + domainFronting.uninit(); + } catch {} + this.#domainFrontedRequests = null; + } + this.#initialized = false; + this.#invites = []; + this.#pubKeys = null; + this.#encTable = null; + this.#constants = null; + this.#pubKeyPromise = null; + this.#encTablePromise = null; + this.#constantsPromise = null; + this.#credentials = new Map(); + this.#events = []; + if (this.#backgroundInterval) { + clearInterval(this.#backgroundInterval); + } + this.#backgroundInterval = null; + } + + /** + * Parses an input string to check if it is a valid Lox invitation. + * + * @param {string} invite A Lox invitation. + * @returns {bool} Whether the value passed in was a Lox invitation. + */ + validateInvitation(invite) { + this.#assertInitialized(); + try { + lazy.invitation_is_trusted(invite); + } catch (err) { + lazy.logger.info(`Does not parse as an invite: "${invite}".`, err); + return false; + } + return true; + } + + // Note: This is only here for testing purposes. We're going to be using telegram + // to issue open invitations for Lox bridges. + async requestOpenInvite() { + this.#assertInitialized(); + let invite = JSON.parse(await this.#makeRequest("invite", null)); + lazy.logger.debug(invite); + return invite; + } + + /** + * Redeems a Lox open invitation to obtain an untrusted Lox credential + * and 1 bridge. + * + * @param {string} invite A Lox open invitation. + * @returns {string} The loxId of the associated credential on success. + */ + async redeemInvite(invite) { + this.#assertInitialized(); + // It's fine to get pubkey here without a delay since the user will not have a Lox + // credential yet + await this.#getPubKeys(); + // NOTE: We currently only handle "open invites". + // "trusted invites" are not yet supported. tor-browser#42974. + let request = await lazy.open_invite(JSON.parse(invite).invite); + let response; + try { + response = await this.#makeRequest("openreq", request); + } catch (error) { + if (error instanceof LoxError && error.code === LoxError.ErrorResponse) { + throw new LoxError("Error response to openreq", LoxError.BadInvite); + } else { + throw error; + } + } + let cred = lazy.handle_new_lox_credential(request, response, this.#pubKeys); + // Generate an id that is not already in the #credentials map. + let loxId; + do { + loxId = this.#genLoxId(); + } while (this.#credentials.has(loxId)); + // Set new credentials. + this.#credentials.set(loxId, cred); + this.#store(); + return loxId; + } + + /** + * Get metadata on all invites historically generated by this credential. + * + * @returns {string[]} A list of all historical invites. + */ + getInvites() { + this.#assertInitialized(); + // Return a copy. + return structuredClone(this.#invites); + } + + /** + * Generates a new trusted Lox invitation that a user can pass to their + * contacts. + * + * Throws if: + * - there is no saved Lox credential, or + * - the saved credential does not have any invitations available. + * + * @param {string} loxId - The ID to generate an invite for. + * @returns {string} A valid Lox invitation. + */ + async generateInvite(loxId) { + this.#assertInitialized(); + // Check for pubkey update prior to invitation generation + // to avoid invite being generated with outdated keys + // TODO: it's still possible the keys could be rotated before the invitation is redeemed + // so updating the invite after issuing should also be possible somehow + if (this.#pubKeys == null) { + // TODO: Set pref to call this function after some time #43086 + // See also: https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests/1090#note_3066911 + await this.#getPubKeys(); + throw new LoxError( + `Pubkeys just updated, retry later to avoid deanonymization` + ); + } + await this.#getEncTable(); + let level = this.#getLevel(loxId); + if (level < 1) { + throw new LoxError(`Cannot generate invites at level ${level}`); + } + + const cred = await this.#changeCredentials(loxId, async cred => { + let request = lazy.issue_invite(cred, this.#encTable, this.#pubKeys); + let response = await this.#makeRequest("issueinvite", request); + // TODO: Do we ever expect handle_issue_invite to fail (beyond + // implementation bugs)? + // TODO: What happens if #pubkeys for `issue_invite` differs from the value + // when calling `handle_issue_invite`? Should we cache the value at the + // start of this method? + return lazy.handle_issue_invite(request, response, this.#pubKeys); + }); + + const invite = lazy.prepare_invite(cred); + this.#invites.push(invite); + // cap length of stored invites + if (this.#invites.len > 50) { + this.#invites.shift(); + } + this.#store(); + Services.obs.notifyObservers(null, LoxTopics.NewInvite); + // Return a copy. + // Right now invite is just a string, but that might change in the future. + return structuredClone(invite); + } + + /** + * Get the number of invites that a user has remaining. + * + * @param {string} loxId - The ID to check. + * @returns {int} The number of invites that can still be generated by a + * user's credential. + */ + getRemainingInviteCount(loxId) { + this.#assertInitialized(); + return LoxImpl.#parseNonNegativeInteger( + lazy.get_invites_remaining(this.#getCredentials(loxId)) + ); + } + + async #blockageMigration(loxId) { + return Boolean( + await this.#changeCredentials(loxId, async cred => { + let request; + try { + request = lazy.check_blockage(cred, this.#pubKeys); + } catch { + lazy.logger.log("Not ready for blockage migration"); + return null; + } + let response = await this.#makeRequest("checkblockage", request); + // NOTE: If a later method fails, we should be ok to re-call "checkblockage" + // from the Lox authority. So there shouldn't be any adverse side effects to + // loosing migrationCred. + // TODO: Confirm this is safe to lose. + const migrationCred = lazy.handle_check_blockage(cred, response); + request = lazy.blockage_migration(cred, migrationCred, this.#pubKeys); + response = await this.#makeRequest("blockagemigration", request); + return lazy.handle_blockage_migration(cred, response, this.#pubKeys); + }) + ); + } + + /** + * Attempts to upgrade the currently saved Lox credential. + * If an upgrade is available, save an event in the event list. + * + * @param {string} loxId Lox ID + * @returns {boolean} Whether the credential was successfully migrated. + */ + async #attemptUpgrade(loxId) { + await this.#getEncTable(); + await this.#getConstants(); + let level = this.#getLevel(loxId); + if (level < 1) { + // attempt trust promotion instead + return this.#trustMigration(loxId); + } + return Boolean( + await this.#changeCredentials(loxId, async cred => { + let request = lazy.level_up(cred, this.#encTable, this.#pubKeys); + let response; + try { + response = await this.#makeRequest("levelup", request); + } catch (error) { + if ( + error instanceof LoxError && + error.code === LoxError.ErrorResponse + ) { + // Not an error. + lazy.logger.debug("Not ready for level up", error); + return null; + } + throw error; + } + return lazy.handle_level_up(request, response, this.#pubKeys); + }) + ); + } + + /** + * Attempt to migrate from an untrusted to a trusted Lox credential + * + * @param {string} loxId - The ID to use. + * @returns {boolean} Whether the credential was successfully migrated. + */ + async #trustMigration(loxId) { + if (this.#pubKeys == null) { + // TODO: Set pref to call this function after some time #43086 + // See also: https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests/1090#note_3066911 + this.#getPubKeys(); + return false; + } + return Boolean( + await this.#changeCredentials(loxId, async cred => { + let request; + try { + request = lazy.trust_promotion(cred, this.#pubKeys); + } catch (err) { + // This function is called routinely during the background tasks without + // previous checks on whether an upgrade is possible, so it is expected to + // fail with a certain frequency. Therefore, do not relay the error to the + // caller and just log the message for debugging. + lazy.logger.debug("Not ready to upgrade", err); + return null; + } + + let response = await this.#makeRequest("trustpromo", request); + // FIXME: Store response to "trustpromo" in case handle_trust_promotion + // or "trustmig" fails. The Lox authority will not accept a re-request + // to "trustpromo" with the same credentials. + let promoCred = lazy.handle_trust_promotion(request, response); + lazy.logger.debug("Formatted promotion cred: ", promoCred); + + request = lazy.trust_migration(cred, promoCred, this.#pubKeys); + response = await this.#makeRequest("trustmig", request); + lazy.logger.debug("Got new credential: ", response); + + // FIXME: Store response to "trustmig" in case handle_trust_migration + // fails. The Lox authority will not accept a re-request to "trustmig" with + // the same credentials. + return lazy.handle_trust_migration(request, response); + }) + ); + } + + /** + * @typedef {object} EventData + * + * @property {string} [type] - the type of event. This should be one of: + * ("levelup", "blockage") + * @property {integer} [newlevel] - the new level, after the event. Levels count + * from 0, but "blockage" events can never take the user to 0, so this will always + * be 1 or greater. + */ + + /** + * Get a list of accumulated events. + * + * @param {string} loxId - The ID to get events for. + * @returns {EventData[]} A list of the accumulated, unacknowledged events + * associated with a user's credential. + */ + getEventData(loxId) { + this.#assertInitialized(); + if (loxId !== this.#activeLoxId) { + lazy.logger.warn( + `No event data for loxId ${loxId} since it was replaced by ${ + this.#activeLoxId + }` + ); + return []; + } + // Return a copy. + return structuredClone(this.#events); + } + + /** + * Clears accumulated event data. + * + * Should be called whenever the user acknowledges the existing events. + * + * @param {string} loxId - The ID to clear events for. + */ + clearEventData(loxId) { + this.#assertInitialized(); + if (loxId !== this.#activeLoxId) { + lazy.logger.warn( + `Not clearing event data for loxId ${loxId} since it was replaced by ${ + this.#activeLoxId + }` + ); + return; + } + this.#events = []; + this.#store(); + Services.obs.notifyObservers(null, LoxTopics.UpdateEvents); + } + + /** + * @typedef {object} UnlockData + * + * @property {string} date - The date-time for the next level up, formatted as + * YYYY-MM-DDTHH:mm:ssZ. + * @property {integer} nextLevel - The next level. Levels count from 0, so + * this will be 1 or greater. + */ + + /** + * Get details about the next feature unlock. + * + * NOTE: A call to this method may trigger LoxTopics.UpdateNextUnlock. + * + * @param {string} loxId - The ID to get the unlock for. + * @returns {UnlockData} - Details about the next unlock. + */ + async getNextUnlock(loxId) { + this.#assertInitialized(); + await this.#getConstants(); + let nextUnlock = JSON.parse( + lazy.get_next_unlock(this.#constants, this.#getCredentials(loxId)) + ); + const level = this.#getLevel(loxId); + return { + date: nextUnlock.trust_level_unlock_date, + nextLevel: level + 1, + }; + } + + /** + * Fetch from the Lox authority. + * + * @param {string} procedure - The request endpoint. + * @param {string} body - The arguments to send in the body, if any. + * + * @returns {string} - The response body. + */ + async #fetch(procedure, body) { + // TODO: Customize to for Lox + const url = `https://lox.torproject.org/${procedure}`; + const method = "POST"; + const contentType = "application/vnd.api+json"; + + if (lazy.TorConnect.stageName === lazy.TorConnectStage.Bootstrapped) { + let request; + try { + request = await fetch(url, { + method, + headers: { "Content-Type": contentType }, + body, + }); + } catch (error) { + lazy.logger.debug("fetch fail", url, body, error); + throw new LoxError( + `fetch "${procedure}" from Lox authority failed: ${error?.message}`, + LoxError.LoxServerUnreachable + ); + } + if (!request.ok) { + lazy.logger.debug("fetch response", url, body, request); + // Do not treat as a LoxServerUnreachable type. + throw new LoxError( + `Lox authority responded to "${procedure}" with ${request.status}: ${request.statusText}` + ); + } + return request.text(); + } + + // TODO: Only make domain fronted requests with user permission. + // tor-browser#42606. + if (this.#domainFrontedRequests === null) { + this.#domainFrontedRequests = new Promise((resolve, reject) => { + // TODO: Customize to the values for Lox + const reflector = Services.prefs.getStringPref( + "extensions.torlauncher.bridgedb_reflector" + ); + const front = Services.prefs.getStringPref( + "extensions.torlauncher.bridgedb_front" + ); + const builder = new lazy.DomainFrontRequestBuilder(); + builder + .init(reflector, front) + .then(() => resolve(builder)) + .catch(reject); + }); + } + const builder = await this.#domainFrontedRequests; + try { + return await builder.buildRequest(url, { method, contentType, body }); + } catch (error) { + lazy.logger.debug("Domain front request fail", url, body, error); + if (error instanceof lazy.DomainFrontRequestNetworkError) { + throw new LoxError( + `Domain front fetch "${procedure}" from Lox authority failed: ${error?.message}`, + LoxError.LoxServerUnreachable + ); + } + if (error instanceof lazy.DomainFrontRequestResponseError) { + // Do not treat as a LoxServerUnreachable type. + throw new LoxError( + `Lox authority responded to domain front "${procedure}" with ${error.status}: ${error.statusText}` + ); + } + throw new LoxError( + `Domain front request for "${procedure}" from Lox authority failed: ${error?.message}` + ); + } + } + + /** + * Make a request to the lox authority, check for an error response, and + * convert it to a string. + * + * @param {string} procedure - The request endpoint. + * @param {?string} request - The request data, as a JSON string containing a + * "request" field. Or `null` to send no data. + * + * @returns {string} - The stringified JSON response. + */ + async #makeRequest(procedure, request) { + // Verify that the response is valid json, by parsing. + const jsonResponse = JSON.parse( + await this.#fetch( + procedure, + request ? JSON.stringify(JSON.parse(request).request) : "" + ) + ); + lazy.logger.debug(`${procedure} response:`, jsonResponse); + if (Object.hasOwn(jsonResponse, "error")) { + // TODO: Figure out if any of the "error" responses should be treated as + // an error. I.e. which of the procedures have soft failures and hard + // failures. + throw LoxError( + `Error response to ${procedure}: ${jsonResponse.error}`, + LoxError.ErrorResponse + ); + } + return JSON.stringify(jsonResponse); + } +} + +export const Lox = new LoxImpl(); diff --git a/toolkit/components/lox/content/lox_wasm_bg.wasm b/toolkit/components/lox/content/lox_wasm_bg.wasm new file mode 100644 index 0000000000000000000000000000000000000000..11f581870b918b7475f3e70c709fa730756d4689 Binary files /dev/null and b/toolkit/components/lox/content/lox_wasm_bg.wasm differ diff --git a/toolkit/components/lox/jar.mn b/toolkit/components/lox/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..8cb768c7f72f7595154400496146a5c87fe8c635 --- /dev/null +++ b/toolkit/components/lox/jar.mn @@ -0,0 +1,4 @@ +toolkit.jar: +#ifndef ANDROID + content/global/lox/lox_wasm_bg.wasm (content/lox_wasm_bg.wasm) +#endif diff --git a/toolkit/components/lox/lox_wasm.jsm b/toolkit/components/lox/lox_wasm.jsm new file mode 100644 index 0000000000000000000000000000000000000000..c6f581cdb27b355f7bd8b7eaa2c819a1da44414f --- /dev/null +++ b/toolkit/components/lox/lox_wasm.jsm @@ -0,0 +1,1428 @@ +var EXPORTED_SYMBOLS = ["set_panic_hook", "open_invite", "handle_new_lox_credential", "trust_promotion", "handle_trust_promotion", "trust_migration", "handle_trust_migration", "level_up", "handle_level_up", "issue_invite", "handle_issue_invite", "prepare_invite", "redeem_invite", "handle_redeem_invite", "check_blockage", "handle_check_blockage", "blockage_migration", "handle_blockage_migration", "update_cred", "handle_update_cred", "update_invite", "handle_update_invite", "get_last_upgrade_time", "get_trust_level", "get_invites_remaining", "get_issued_invite_expiry", "get_received_invite_expiry", "get_bridgelines_from_bucket", "invitation_is_trusted", "get_next_unlock", "check_lox_pubkeys_update", "check_invitation_pubkeys_update", "init", "initSync"]; + +let wasm; +let module; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} +/** +*/ +function set_panic_hook() { + wasm.set_panic_hook(); +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} +/** +* @param {string} base64_invite +* @returns {string} +*/ +function open_invite(base64_invite) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(base64_invite, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.open_invite(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} open_lox_result +* @param {string} open_lox_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_new_lox_credential(open_lox_result, open_lox_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(open_lox_result, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(open_lox_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_new_lox_credential(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} open_lox_cred +* @param {string} lox_pub +* @returns {string} +*/ +function trust_promotion(open_lox_cred, lox_pub) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(open_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.trust_promotion(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} trust_promo_request +* @param {string} trust_promo_response +* @returns {string} +*/ +function handle_trust_promotion(trust_promo_request, trust_promo_response) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(trust_promo_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(trust_promo_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.handle_trust_promotion(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} open_lox_cred +* @param {string} trust_promo_cred +* @param {string} lox_pub +* @returns {string} +*/ +function trust_migration(open_lox_cred, trust_promo_cred, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(open_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(trust_promo_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.trust_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} trust_migration_request +* @param {string} trust_migration_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_trust_migration(trust_migration_request, trust_migration_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(trust_migration_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(trust_migration_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_trust_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} level_one_cred +* @param {string} encrypted_table +* @param {string} lox_pub +* @returns {string} +*/ +function level_up(level_one_cred, encrypted_table, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(level_one_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.level_up(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} levelup_request +* @param {string} levelup_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_level_up(levelup_request, levelup_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(levelup_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(levelup_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_level_up(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} trusted_cred +* @param {string} encrypted_table +* @param {string} lox_pub +* @returns {string} +*/ +function issue_invite(trusted_cred, encrypted_table, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(trusted_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.issue_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} issue_invite_request +* @param {string} issue_invite_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_issue_invite(issue_invite_request, issue_invite_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(issue_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(issue_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_issue_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} invitation_cred +* @returns {string} +*/ +function prepare_invite(invitation_cred) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(invitation_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.prepare_invite(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} invitation +* @param {string} lox_pub +* @returns {string} +*/ +function redeem_invite(invitation, lox_pub) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(invitation, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.redeem_invite(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} redeem_invite_request +* @param {string} redeem_invite_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_redeem_invite(redeem_invite_request, redeem_invite_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(redeem_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(redeem_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_redeem_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} lox_cred +* @param {string} lox_pub +* @returns {string} +*/ +function check_blockage(lox_cred, lox_pub) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.check_blockage(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} check_blockage_request +* @param {string} check_blockage_response +* @returns {string} +*/ +function handle_check_blockage(check_blockage_request, check_blockage_response) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(check_blockage_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(check_blockage_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.handle_check_blockage(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} lox_cred +* @param {string} check_migration_cred +* @param {string} lox_pub +* @returns {string} +*/ +function blockage_migration(lox_cred, check_migration_cred, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(check_migration_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.blockage_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} blockage_migration_request +* @param {string} blockage_migration_response +* @param {string} lox_pub +* @returns {string} +*/ +function handle_blockage_migration(blockage_migration_request, blockage_migration_response, lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(blockage_migration_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(blockage_migration_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_blockage_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} lox_cred +* @param {string} lox_pub +* @returns {string} +*/ +function update_cred(lox_cred, lox_pub) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.update_cred(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} update_cred_request +* @param {string} update_cred_response +* @param {string} updated_lox_pub +* @returns {string} +*/ +function handle_update_cred(update_cred_request, update_cred_response, updated_lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(update_cred_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(update_cred_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(updated_lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_update_cred(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} invite_cred +* @param {string} lox_pub +* @returns {string} +*/ +function update_invite(invite_cred, lox_pub) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(invite_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.update_invite(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} update_invite_request +* @param {string} update_invite_response +* @param {string} updated_lox_pub +* @returns {string} +*/ +function handle_update_invite(update_invite_request, update_invite_response, updated_lox_pub) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(update_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(update_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(updated_lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.handle_update_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} lox_cred_str +* @returns {string} +*/ +function get_last_upgrade_time(lox_cred_str) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.get_last_upgrade_time(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} lox_cred_str +* @returns {string} +*/ +function get_trust_level(lox_cred_str) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.get_trust_level(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} lox_cred_str +* @returns {string} +*/ +function get_invites_remaining(lox_cred_str) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.get_invites_remaining(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} lox_cred_str +* @returns {string} +*/ +function get_issued_invite_expiry(lox_cred_str) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.get_issued_invite_expiry(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} invite_cred_str +* @returns {string} +*/ +function get_received_invite_expiry(invite_cred_str) { + let deferred3_0; + let deferred3_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(invite_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.get_received_invite_expiry(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr2 = r0; + var len2 = r1; + if (r3) { + ptr2 = 0; len2 = 0; + throw takeObject(r2); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** +* @param {string} lox_cred_str +* @param {string} encrypted_table +* @returns {string} +*/ +function get_bridgelines_from_bucket(lox_cred_str, encrypted_table) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.get_bridgelines_from_bucket(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} unspecified_invitation_str +* @returns {boolean} +*/ +function invitation_is_trusted(unspecified_invitation_str) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(unspecified_invitation_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.invitation_is_trusted(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + if (r2) { + throw takeObject(r1); + } + return r0 !== 0; + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +/** +* @param {string} constants_str +* @param {string} lox_cred_str +* @returns {string} +*/ +function get_next_unlock(constants_str, lox_cred_str) { + let deferred4_0; + let deferred4_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(constants_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + wasm.get_next_unlock(retptr, ptr0, len0, ptr1, len1); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr3 = r0; + var len3 = r1; + if (r3) { + ptr3 = 0; len3 = 0; + throw takeObject(r2); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** +* @param {string} new_pubkeys_str +* @param {string} old_pubkeys_str +* @param {string} old_lox_cred +* @returns {string} +*/ +function check_lox_pubkeys_update(new_pubkeys_str, old_pubkeys_str, old_lox_cred) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(new_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(old_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(old_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.check_lox_pubkeys_update(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +/** +* @param {string} new_pubkeys_str +* @param {string} old_pubkeys_str +* @param {string} old_invite_cred +* @returns {string} +*/ +function check_invitation_pubkeys_update(new_pubkeys_str, old_pubkeys_str, old_invite_cred) { + let deferred5_0; + let deferred5_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(new_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(old_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(old_invite_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + wasm.check_invitation_pubkeys_update(retptr, ptr0, len0, ptr1, len1, ptr2, len2); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr4 = r0; + var len4 = r1; + if (r3) { + ptr4 = 0; len4 = 0; + throw takeObject(r2); + } + deferred5_0 = ptr4; + deferred5_1 = len4; + return getStringFromWasm0(ptr4, len4); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred5_0, deferred5_1, 1); + } +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports(window) { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_new0_7d84e5b2cd9fdc73 = function() { + const ret = new Date(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getTime_2bc4375165f02d15 = function(arg0) { + const ret = getObject(arg0).getTime(); + return ret; + }; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbg_log_9b9925d843c39805 = function(arg0, arg1) { + console.log(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_crypto_1d1f22824a6a080c = function(arg0) { + const ret = getObject(arg0).crypto; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbg_process_4a72847cc503995b = function(arg0) { + const ret = getObject(arg0).process; + return addHeapObject(ret); + }; + imports.wbg.__wbg_versions_f686565e586dd935 = function(arg0) { + const ret = getObject(arg0).versions; + return addHeapObject(ret); + }; + imports.wbg.__wbg_node_104a2ff8d6ea03a2 = function(arg0) { + const ret = getObject(arg0).node; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbg_require_cca90b1a94a0255b = function() { return handleError(function () { + const ret = module.require; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_call_b3ca7c6051f9bec1 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_msCrypto_eb05e62b530a1508 = function(arg0) { + const ret = getObject(arg0).msCrypto; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithlength_e9b4878cebadb3d3 = function(arg0) { + const ret = new Uint8Array(arg0 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_ce0dbfc45cf2f5be = function() { return handleError(function () { + const ret = window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_c6fb939a7f436783 = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_d1e6af4856ba331b = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_207b558942527489 = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbg_newnoargs_e258087cd0daa0ea = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_call_27c0f87801dedf93 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_12d079cc21e14bdb = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_randomFillSync_5c9c955aa56b6049 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).randomFillSync(takeObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_subarray_a1f73cd4b5b42fe1 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getRandomValues_3aa56aa6edec874c = function() { return handleError(function (arg0, arg1) { + getObject(arg0).getRandomValues(getObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_new_63b92bc8671ed464 = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_a47bac70306a19a7 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + init.__wbindgen_wasm_module = module; + cachedInt32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module, window) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(window); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function init(window, input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') {{ + input = "chrome://global/content/lox/lox_wasm_bg.wasm"; + }} + const imports = __wbg_get_imports(window); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + diff --git a/toolkit/components/lox/moz.build b/toolkit/components/lox/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..1f978327c8bb466b487d466d3af9a6744cca651f --- /dev/null +++ b/toolkit/components/lox/moz.build @@ -0,0 +1,7 @@ +EXTRA_JS_MODULES += [ + "Lox.sys.mjs", + # Let's keep the old jsm format until wasm-bindgen is updated + "lox_wasm.jsm", +] + +JAR_MANIFESTS += ["jar.mn"] diff --git a/toolkit/components/moz.build b/toolkit/components/moz.build index 532b0e96513835b7b5aa85882250afb5a9127e6a..21f2986724c538a005837aa3ba2eb8aa6d1896ec 100644 --- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -46,6 +46,7 @@ DIRS += [ "httpsonlyerror", "jsoncpp/src/lib_json", "kvstore", + "lox", "mediasniffer", "ml", "mozintl", @@ -65,6 +66,7 @@ DIRS += [ "reportbrokensite", "resistfingerprinting", "search", + "securitylevel", "sessionstore", "shell", "shopping", @@ -76,6 +78,8 @@ DIRS += [ "thumbnails", "timermanager", "tooltiptext", + "torconnect", + "tor-launcher", "typeaheadfind", "utils", "url-classifier", @@ -130,7 +134,9 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] not in ("android", "windows"): DIRS += ["aboutwebauthn"] if CONFIG["MOZ_BUILD_APP"] == "browser": - DIRS += ["featuregates", "messaging-system", "normandy"] + if CONFIG["MOZ_NORMANDY"]: + DIRS += ["normandy"] + DIRS += ["featuregates", "messaging-system"] DIRS += ["nimbus"] diff --git a/toolkit/components/places/PlacesUtils.sys.mjs b/toolkit/components/places/PlacesUtils.sys.mjs index 129be7e2719bcaec16ee88b744b72e506e017af7..a0d33c1a65e6681f2c4728d21ec6b9c58af584fd 100644 --- a/toolkit/components/places/PlacesUtils.sys.mjs +++ b/toolkit/components/places/PlacesUtils.sys.mjs @@ -12,6 +12,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { Bookmarks: "resource://gre/modules/Bookmarks.sys.mjs", History: "resource://gre/modules/History.sys.mjs", + OpaqueDrag: "resource://gre/modules/DragDropFilter.sys.mjs", PlacesSyncUtils: "resource://gre/modules/PlacesSyncUtils.sys.mjs", Sqlite: "resource://gre/modules/Sqlite.sys.mjs", }); @@ -1122,6 +1123,9 @@ export var PlacesUtils = { unwrapNodes: function PU_unwrapNodes(blob, type) { // We split on "\n" because the transferable system converts "\r\n" to "\n" var nodes = []; + if (type === "application/x-torbrowser-opaque") { + ({ value: blob, type } = lazy.OpaqueDrag.retrieve(blob)); + } switch (type) { case this.TYPE_X_MOZ_PLACE: case this.TYPE_X_MOZ_PLACE_SEPARATOR: diff --git a/toolkit/components/remotebrowserutils/RemoteWebNavigation.sys.mjs b/toolkit/components/remotebrowserutils/RemoteWebNavigation.sys.mjs index 2d337064270c32ea478f1b5d2c006933b871c523..6bfd189403b868d15bdee0121b26688b0abf3365 100644 --- a/toolkit/components/remotebrowserutils/RemoteWebNavigation.sys.mjs +++ b/toolkit/components/remotebrowserutils/RemoteWebNavigation.sys.mjs @@ -76,6 +76,9 @@ export class RemoteWebNavigation { } _speculativeConnect(uri, loadURIOptions) { + return; + + /* eslint-disable-next-line no-unreachable */ try { // Let's start a network connection before the content process asks. // Note that we might have already set up the speculative connection in diff --git a/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs b/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs index ff72ce39ae165d36586eb8856d604e12f753137c..7966321adab1bc1b201f96a5fc9290f6beed8edb 100644 --- a/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs +++ b/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs @@ -15,18 +15,120 @@ const kPrefLetterboxingDimensions = "privacy.resistFingerprinting.letterboxing.dimensions"; const kPrefLetterboxingTesting = "privacy.resistFingerprinting.letterboxing.testing"; +const kPrefLetterboxingVcenter = + "privacy.resistFingerprinting.letterboxing.vcenter"; +const kPrefLetterboxingGradient = + "privacy.resistFingerprinting.letterboxing.gradient"; +const kPrefLetterboxingDidForceSize = + "privacy.resistFingerprinting.letterboxing.didForceSize"; + const kTopicDOMWindowOpened = "domwindowopened"; -var logConsole; -function log(msg) { - if (!logConsole) { - logConsole = console.createInstance({ - prefix: "RFPHelper", - maxLogLevelPref: "privacy.resistFingerprinting.jsmloglevel", - }); +const kPrefResizeWarnings = "privacy.resistFingerprinting.resizeWarnings"; + +const lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "logConsole", () => + console.createInstance({ + prefix: "RFPHelper", + maxLogLevelPref: "privacy.resistFingerprinting.jsmloglevel", + }) +); + +function log(...args) { + lazy.logConsole.log(...args); +} + +function forEachWindow(callback) { + const windowList = Services.wm.getEnumerator("navigator:browser"); + while (windowList.hasMoreElements()) { + const win = windowList.getNext(); + if (win.gBrowser && !win.closed) { + try { + callback(win); + } catch (e) { + lazy.logConsole.error(e); + } + } + } +} + +async function windowResizeHandler(aEvent) { + if (RFPHelper.letterboxingEnabled || !RFPHelper.rfpEnabled) { + return; + } + if (Services.prefs.getIntPref(kPrefResizeWarnings) <= 0) { + return; + } + + const window = aEvent.currentTarget; + + // Wait for end of execution queue to ensure we have correct windowState. + await new Promise(resolve => window.setTimeout(resolve, 0)); + switch (window.windowState) { + case window.STATE_MAXIMIZED: + case window.STATE_FULLSCREEN: + break; + default: + return; } - logConsole.log(msg); + // Do not add another notification if one is already showing. + const kNotificationName = "rfp-window-resize-notification"; + let box = window.gNotificationBox; + if (box.getNotificationWithValue(kNotificationName)) { + return; + } + + // Rate-limit showing our notification if needed. + if (Date.now() - (windowResizeHandler.timestamp || 0) < 1000) { + return; + } + windowResizeHandler.timestamp = Date.now(); + + const decreaseWarningsCount = () => { + const currentCount = Services.prefs.getIntPref(kPrefResizeWarnings); + if (currentCount > 0) { + Services.prefs.setIntPref(kPrefResizeWarnings, currentCount - 1); + } + }; + + const [label, accessKey] = await window.document.l10n.formatValues([ + { id: "basebrowser-rfp-restore-window-size-button-label" }, + { id: "basebrowser-rfp-restore-window-size-button-ak" }, + ]); + + const buttons = [ + { + label, + accessKey, + popup: null, + callback() { + // reset notification timer to work-around resize race conditions + windowResizeHandler.timestamp = Date.now(); + // restore the original (rounded) size we had stored on window startup + let { _rfpOriginalSize } = window; + window.setTimeout(() => { + window.resizeTo(_rfpOriginalSize.width, _rfpOriginalSize.height); + }, 0); + }, + }, + ]; + + box.appendNotification( + kNotificationName, + { + label: { "l10n-id": "basebrowser-rfp-maximize-warning-message" }, + priority: box.PRIORITY_WARNING_LOW, + eventCallback(event) { + if (event === "dismissed") { + // user manually dismissed the notification + decreaseWarningsCount(); + } + }, + }, + buttons + ); } class _RFPHelper { @@ -46,6 +148,9 @@ class _RFPHelper { // Add unconditional observers Services.prefs.addObserver(kPrefResistFingerprinting, this); Services.prefs.addObserver(kPrefLetterboxing, this); + Services.prefs.addObserver(kPrefLetterboxingVcenter, this); + Services.prefs.addObserver(kPrefLetterboxingGradient, this); + XPCOMUtils.defineLazyPreferenceGetter( this, "_letterboxingDimensions", @@ -64,6 +169,9 @@ class _RFPHelper { // Add RFP and Letterboxing observers if prefs are enabled this._handleResistFingerprintingChanged(); this._handleLetterboxingPrefChanged(); + + // Synchronize language preferences if accidentally messed up (tor-browser#42084) + this._handleSpoofEnglishChanged(); } uninit() { @@ -74,6 +182,8 @@ class _RFPHelper { // Remove unconditional observers Services.prefs.removeObserver(kPrefResistFingerprinting, this); + Services.prefs.removeObserver(kPrefLetterboxingGradient, this); + Services.prefs.removeObserver(kPrefLetterboxingVcenter, this); Services.prefs.removeObserver(kPrefLetterboxing, this); // Remove the RFP observers, swallowing exceptions if they weren't present this._removeRFPObservers(); @@ -90,7 +200,7 @@ class _RFPHelper { case kTopicDOMWindowOpened: // We attach to the newly created window by adding tabsProgressListener // and event listener on it. We listen for new tabs being added or - // the change of the content principal and apply margins accordingly. + // the change of the content principal and round browser sizes accordingly. this._handleDOMWindowOpened(subject); break; default: @@ -101,8 +211,9 @@ class _RFPHelper { handleEvent(aMessage) { switch (aMessage.type) { case "TabOpen": { - let tab = aMessage.target; - this._addOrClearContentMargin(tab.linkedBrowser); + let browser = aMessage.target.linkedBrowser; + this._roundOrResetContentSize(browser, /* isNewTab = */ true); + browser.ownerGlobal._rfpResizeObserver.observe(browser.parentElement); break; } default: @@ -113,12 +224,18 @@ class _RFPHelper { _handlePrefChanged(data) { switch (data) { case kPrefResistFingerprinting: + Services.prefs.clearUserPref(kPrefLetterboxingDidForceSize); this._handleResistFingerprintingChanged(); break; case kPrefSpoofEnglish: + case "intl.accept_languages": this._handleSpoofEnglishChanged(); break; case kPrefLetterboxing: + Services.prefs.clearUserPref(kPrefLetterboxingDidForceSize); + // fall-through + case kPrefLetterboxingVcenter: + case kPrefLetterboxingGradient: this._handleLetterboxingPrefChanged(); break; default: @@ -126,10 +243,6 @@ class _RFPHelper { } } - contentSizeUpdated(win) { - this._updateMarginsForTabsInWindow(win); - } - // ============================================================================ // Language Prompt // ============================================================================ @@ -154,26 +267,39 @@ class _RFPHelper { } _handleResistFingerprintingChanged() { - if (Services.prefs.getBoolPref(kPrefResistFingerprinting)) { + if ( + (this.rfpEnabled = Services.prefs.getBoolPref(kPrefResistFingerprinting)) + ) { this._addRFPObservers(); + Services.ww.registerNotification(this); + forEachWindow(win => this._attachWindow(win)); } else { + forEachWindow(win => this._detachWindow(win)); + Services.ww.unregisterNotification(this); this._removeRFPObservers(); } } _handleSpoofEnglishChanged() { + Services.prefs.removeObserver("intl.accept_languages", this); switch (Services.prefs.getIntPref(kPrefSpoofEnglish)) { case 0: // will prompt // This should only happen when turning privacy.resistFingerprinting off. // Works like disabling accept-language spoofing. // fall through case 1: // don't spoof - // We don't reset intl.accept_languages. Instead, setting - // privacy.spoof_english to 1 allows user to change preferred language - // settings through Preferences UI. + if (this.rfpEnabled) { + // When RFP is enabled, we force intl.accept_languages to be the + // default, or en-US, en when spoof English is enabled. + // See tor-browser#41930. + Services.prefs.clearUserPref("intl.accept_languages"); + Services.prefs.addObserver("intl.accept_languages", this); + } break; case 2: // spoof Services.prefs.setCharPref("intl.accept_languages", "en-US, en"); + // Ensure spoofing works if preferences are set out of order + Services.prefs.addObserver("intl.accept_languages", this); break; default: break; @@ -274,49 +400,22 @@ class _RFPHelper { // ============================================================================ /** * We use the TabsProgressListener to catch the change of the content - * principal. We would clear the margins around the content viewport if - * it is the system principal. + * principal. We would reset browser size if it is the system principal. */ onLocationChange(aBrowser) { - this._addOrClearContentMargin(aBrowser); + this._roundOrResetContentSize(aBrowser); } _handleLetterboxingPrefChanged() { - if (Services.prefs.getBoolPref(kPrefLetterboxing, false)) { - Services.ww.registerNotification(this); - this._registerLetterboxingActor(); - this._attachAllWindows(); - } else { - this._unregisterLetterboxingActor(); - this._detachAllWindows(); - Services.ww.unregisterNotification(this); + this.letterboxingEnabled = Services.prefs.getBoolPref( + kPrefLetterboxing, + false + ); + if (this.rfpEnabled) { + forEachWindow(win => this._updateSizeForTabsInWindow(win)); } } - _registerLetterboxingActor() { - /* - * It turns out that this triggers a warning that we're registering a Desktop-only actor - * in toolkit (which will also run on mobile.) It just happens this actor only handles - * letterboxing, which isn't used on mobile, but we should resolve this. - */ - ChromeUtils.registerWindowActor("RFPHelper", { - parent: { - esModuleURI: "resource:///actors/RFPHelperParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/RFPHelperChild.sys.mjs", - events: { - resize: {}, - }, - }, - allFrames: true, - }); - } - - _unregisterLetterboxingActor() { - ChromeUtils.unregisterWindowActor("RFPHelper"); - } - // The function to parse the dimension set from the pref value. The pref value // should be formated as 'width1xheight1, width2xheight2, ...'. For // example, '100x100, 200x200, 400x200 ...'. @@ -340,130 +439,151 @@ class _RFPHelper { }); } - _addOrClearContentMargin(aBrowser) { - let tab = aBrowser.getTabBrowser().getTabForBrowser(aBrowser); + getLetterboxingDefaultRule(document) { + return (document._letterBoxingSizingRule ||= (() => { + // If not already cached on the document object, traverse the CSSOM and + // find the rule applying the default letterboxing styles to browsers + // preemptively in order to beat race conditions on tab/window creation + const LETTERBOX_CSS_URL = + "chrome://global/content/resistfingerprinting/letterboxing.css"; + const LETTERBOX_CSS_SELECTOR = ".letterboxing .browserContainer"; + for (let ss of document.styleSheets) { + if (ss.href !== LETTERBOX_CSS_URL) { + continue; + } + for (let rule of ss.rules) { + if (rule.selectorText === LETTERBOX_CSS_SELECTOR) { + return rule; + } + } + } + return null; // shouldn't happen + })()); + } + _noLetterBoxingFor({ contentPrincipal, currentURI }) { + // we don't want letterboxing on... + return ( + // ... privileged pages + contentPrincipal.isSystemPrincipal || + // pdf.js + contentPrincipal.origin.startsWith("resource://pdf.js") || + // ... about: URIs EXCEPT about:blank + (currentURI.schemeIs("about") && currentURI.filePath !== "blank") || + // ... source code + currentURI.schemeIs("view-source") || + // ... browser extensions + contentPrincipal.addonPolicy + ); + } + + _roundOrResetContentSize(aBrowser, isNewTab = false) { // We won't do anything for lazy browsers. - if (!aBrowser.isConnected) { + if (!aBrowser?.isConnected) { return; } - - // We should apply no margin around an empty tab or a tab with system - // principal. - if (tab.isEmpty || aBrowser.contentPrincipal.isSystemPrincipal) { - this._clearContentViewMargin(aBrowser); + if (this._noLetterBoxingFor(aBrowser)) { + // this tab doesn't need letterboxing + this._resetContentSize(aBrowser); } else { - this._roundContentView(aBrowser); + this._roundContentSize(aBrowser, isNewTab); } } /** - * Given a width or height, returns the appropriate margin to apply. + * Given a width or height, rounds it with the proper stepping. */ - steppedRange(aDimension) { + steppedSize(aDimension, aIsWidth = false) { let stepping; if (aDimension <= 50) { return 0; } else if (aDimension <= 500) { stepping = 50; } else if (aDimension <= 1600) { - stepping = 100; + stepping = aIsWidth ? 200 : 100; } else { stepping = 200; } - return (aDimension % stepping) / 2; + return aDimension - (aDimension % stepping); } /** - * The function will round the given browser by adding margins around the - * content viewport. + * The function will round the given browser size */ - async _roundContentView(aBrowser) { - let logId = Math.random(); - log("_roundContentView[" + logId + "]"); + async _roundContentSize(aBrowser, isNewTab = false) { + let logPrefix = `_roundContentSize[${Math.random()}]`; + log(logPrefix); let win = aBrowser.ownerGlobal; let browserContainer = aBrowser .getTabBrowser() .getBrowserContainer(aBrowser); + let browserParent = aBrowser.parentElement; + browserParent.classList.remove("exclude-letterboxing"); + let [ + [contentWidth, contentHeight], + [parentWidth, parentHeight], + [containerWidth, containerHeight], + ] = await win.promiseDocumentFlushed(() => + // Read layout info only inside this callback and do not write, to avoid additional reflows + [aBrowser, browserParent, browserContainer].map(element => [ + element.clientWidth, + element.clientHeight, + ]) + ); - let { contentWidth, contentHeight, containerWidth, containerHeight } = - await win.promiseDocumentFlushed(() => { - let contentWidth = aBrowser.clientWidth; - let contentHeight = aBrowser.clientHeight; - let containerWidth = browserContainer.clientWidth; - let containerHeight = browserContainer.clientHeight; - - // If the findbar or devtools are out, we need to subtract their height (plus 1 - // for the separator) from the container height, because we need to adjust our - // letterboxing to account for it; however it is not included in that dimension - // (but rather is subtracted from the content height.) - let findBar = win.gFindBarInitialized ? win.gFindBar : undefined; - let findBarOffset = - findBar && !findBar.hidden ? findBar.clientHeight + 1 : 0; - let devtools = browserContainer.getElementsByClassName( - "devtools-toolbox-bottom-iframe" - ); - let devtoolsOffset = devtools.length ? devtools[0].clientHeight : 0; + const isInitialSize = + win._rfpOriginalSize && + win.outerWidth === win._rfpOriginalSize.width && + win.outerHeight === win._rfpOriginalSize.height; - return { - contentWidth, - contentHeight, - containerWidth, - containerHeight: containerHeight - findBarOffset - devtoolsOffset, - }; - }); + // We may need to shrink this window to rounded size if the browser container + // area is taller than the original, meaning extra chrome (like the optional + // "Only Show on New Tab" bookmarks toobar) was present and now gone. + const needToShrink = + isInitialSize && containerHeight > win._rfpOriginalSize.containerHeight; log( - "_roundContentView[" + - logId + - "] contentWidth=" + - contentWidth + - " contentHeight=" + - contentHeight + - " containerWidth=" + - containerWidth + - " containerHeight=" + - containerHeight + - " " + `${logPrefix} contentWidth=${contentWidth} contentHeight=${contentHeight} parentWidth=${parentWidth} parentHeight=${parentHeight} containerWidth=${containerWidth} containerHeight=${containerHeight}${ + isNewTab ? " (new tab)." : "." + }` ); - let calcMargins = (aWidth, aHeight) => { - let result; - log( - "_roundContentView[" + - logId + - "] calcMargins(" + - aWidth + - ", " + - aHeight + - ")" - ); + if (containerWidth === 0) { + // race condition: tab already be closed, bail out + return; + } + + let lastRoundedSize; + + const roundDimensions = (aWidth, aHeight) => { + const r = (width, height) => { + lastRoundedSize = { width, height }; + log( + `${logPrefix} roundDimensions(${aWidth}, ${aHeight}) = ${width} x ${height}` + ); + return { + "--letterboxing-width": `var(--rdm-width, ${width}px)`, + "--letterboxing-height": `var(--rdm-height, ${height}px)`, + }; + }; + + log(`${logPrefix} roundDimensions(${aWidth}, ${aHeight})`); + + if (!(isInitialSize || this.letterboxingEnabled)) { + // just round size to int + return r(aWidth, aHeight); + } + // If the set is empty, we will round the content with the default // stepping size. if (!this._letterboxingDimensions.length) { - result = { - width: this.steppedRange(aWidth), - height: this.steppedRange(aHeight), - }; - log( - "_roundContentView[" + - logId + - "] calcMargins(" + - aWidth + - ", " + - aHeight + - ") = " + - result.width + - " x " + - result.height - ); - return result; + return r(this.steppedSize(aWidth, true), this.steppedSize(aHeight)); } let matchingArea = aWidth * aHeight; let minWaste = Number.MAX_SAFE_INTEGER; - let targetDimensions = undefined; + let targetDimensions; // Find the desired dimensions which waste the least content area. for (let dim of this._letterboxingDimensions) { @@ -483,133 +603,217 @@ class _RFPHelper { // If we cannot find any dimensions match to the real content window, this // means the content area is smaller the smallest size in the set. In this - // case, we won't apply any margins. - if (!targetDimensions) { - result = { - width: 0, - height: 0, - }; - } else { - result = { - width: (aWidth - targetDimensions.width) / 2, - height: (aHeight - targetDimensions.height) / 2, - }; - } - - log( - "_roundContentView[" + - logId + - "] calcMargins(" + - aWidth + - ", " + - aHeight + - ") = " + - result.width + - " x " + - result.height - ); - return result; + // case, we won't round the size and default to the max. + return targetDimensions + ? r(targetDimensions.width, targetDimensions.height) + : r(aWidth, aHeight); }; - // Calculating the margins around the browser element in order to round the - // content viewport. We will use a 200x100 stepping if the dimension set - // is not given. - let margins = calcMargins(containerWidth, containerHeight); + const styleChanges = Object.assign([], { + queueIfNeeded({ style }, props) { + for (let [name, value] of Object.entries(props)) { + if (style[name] !== value) { + this.push(() => { + style.setProperty(name, value); + }); + } + } + }, + perform() { + win.requestAnimationFrame(() => { + for (let change of this) { + try { + change(); + } catch (e) { + lazy.logConsole.error(e); + } + } + if (needToShrink && win.shrinkToLetterbox()) { + win.addEventListener( + "resize", + () => { + // We need to record the "new" initial size in this listener + // because resized dimensions are not immediately available. + RFPHelper._recordWindowSize(win); + }, + { once: true } + ); + } + }); + }, + }); + + const roundedDefault = roundDimensions(containerWidth, containerHeight); + + styleChanges.queueIfNeeded( + this.getLetterboxingDefaultRule(aBrowser.ownerDocument), + roundedDefault + ); + + const roundedInline = + !isNewTab && // new tabs cannot have extra UI components + (containerHeight > parentHeight || containerWidth > parentWidth) + ? // optional UI components such as the notification box, the find bar + // or devtools are constraining this browser's size: recompute custom + roundDimensions(parentWidth, parentHeight) + : { + "--letterboxing-width": "", + "--letterboxing-height": "", + }; // otherwise we can keep the default (rounded) size + styleChanges.queueIfNeeded(browserParent, roundedInline); + + if (lastRoundedSize) { + // check wether the letterboxing margin is less than the border radius, and if so flatten the borders + let borderRadius = parseInt( + win + .getComputedStyle(browserContainer) + .getPropertyValue("--letterboxing-border-radius") + ); + if ( + borderRadius && + parentWidth - lastRoundedSize.width < borderRadius && + parentHeight - lastRoundedSize.height < borderRadius + ) { + borderRadius = 0; + } else { + borderRadius = ""; + } + styleChanges.queueIfNeeded(browserParent, { + "--letterboxing-decorator-visibility": + borderRadius === 0 ? "hidden" : "", + "--letterboxing-border-radius": borderRadius, + }); + } // If the size of the content is already quantized, we do nothing. - if (aBrowser.style.margin == `${margins.height}px ${margins.width}px`) { - log("_roundContentView[" + logId + "] is_rounded == true"); + if (!styleChanges.length) { + log(`${logPrefix} is_rounded == true`); if (this._isLetterboxingTesting) { log( - "_roundContentView[" + - logId + - "] is_rounded == true test:letterboxing:update-margin-finish" + `${logPrefix} is_rounded == true test:letterboxing:update-size-finish` ); Services.obs.notifyObservers( null, - "test:letterboxing:update-margin-finish" + "test:letterboxing:update-size-finish" ); } return; } - win.requestAnimationFrame(() => { - log( - "_roundContentView[" + - logId + - "] setting margins to " + - margins.width + - " x " + - margins.height - ); - // One cannot (easily) control the color of a margin unfortunately. - // An initial attempt to use a border instead of a margin resulted - // in offset event dispatching; so for now we use a colorless margin. - aBrowser.style.margin = `${margins.height}px ${margins.width}px`; - }); + log( + `${logPrefix} setting size to ${JSON.stringify({ + roundedDefault, + roundedInline, + })}` + ); + // Here we round the browser's size through CSS. + // A "border" visual is created by using a CSS outline, which does't + // affect layout, while the background appearance is borrowed from the + // toolbar and set in the .letterboxing ancestor (see browser.css). + styleChanges.perform(); } - _clearContentViewMargin(aBrowser) { - aBrowser.ownerGlobal.requestAnimationFrame(() => { - aBrowser.style.margin = ""; - }); + _resetContentSize(aBrowser) { + aBrowser.parentElement.classList.add("exclude-letterboxing"); } - _updateMarginsForTabsInWindow(aWindow) { + _updateSizeForTabsInWindow(aWindow) { let tabBrowser = aWindow.gBrowser; + tabBrowser.tabpanels?.classList.add("letterboxing"); + tabBrowser.tabpanels?.classList.toggle( + "letterboxing-vcenter", + Services.prefs.getBoolPref(kPrefLetterboxingVcenter, false) + ); + tabBrowser.tabpanels?.classList.toggle( + "letterboxing-gradient", + Services.prefs.getBoolPref(kPrefLetterboxingGradient, false) + ); + for (let tab of tabBrowser.tabs) { let browser = tab.linkedBrowser; - this._addOrClearContentMargin(browser); + this._roundOrResetContentSize(browser); } + // we need to add this class late because otherwise new windows get maximized + aWindow.setTimeout(() => { + tabBrowser.tabpanels?.classList.add("letterboxing-ready"); + if (!aWindow._rfpOriginalSize) { + this._recordWindowSize(aWindow); + } + }); } - _attachWindow(aWindow) { - aWindow.gBrowser.addTabsProgressListener(this); - aWindow.addEventListener("TabOpen", this); - - // Rounding the content viewport. - this._updateMarginsForTabsInWindow(aWindow); + _recordWindowSize(aWindow) { + aWindow.promiseDocumentFlushed(() => { + aWindow._rfpOriginalSize = { + width: aWindow.outerWidth, + height: aWindow.outerHeight, + containerHeight: aWindow.gBrowser.getBrowserContainer()?.clientHeight, + }; + log("Recording original window size", aWindow._rfpOriginalSize); + }); } - _attachAllWindows() { - let windowList = Services.wm.getEnumerator("navigator:browser"); - - while (windowList.hasMoreElements()) { - let win = windowList.getNext(); + // We will attach this method to each browser window. When called + // it will instantly resize the window to exactly fit the selected + // (possibly letterboxed) browser. + // Returns true if a window resize will occur, false otherwise. + shrinkToLetterbox() { + let { selectedBrowser } = this.gBrowser; + let stack = selectedBrowser.closest(".browserStack"); + const outer = stack.getBoundingClientRect(); + const inner = selectedBrowser.getBoundingClientRect(); + if (inner.width !== outer.witdh || inner.height !== outer.height) { + this.resizeBy(inner.width - outer.width, inner.height - outer.height); + return true; + } + return false; + } - if (win.closed || !win.gBrowser) { - continue; - } + _onWindowDoubleClick(e) { + if (e.target.classList.contains("browserStack")) { + e.currentTarget.shrinkToLetterbox(); + } + } - this._attachWindow(win); + _attachWindow(aWindow) { + aWindow.addEventListener("sizemodechange", windowResizeHandler); + aWindow.shrinkToLetterbox = this.shrinkToLetterbox; + aWindow.addEventListener("dblclick", this._onWindowDoubleClick); + aWindow.gBrowser.addTabsProgressListener(this); + aWindow.addEventListener("TabOpen", this); + const resizeObserver = (aWindow._rfpResizeObserver = + new aWindow.ResizeObserver(entries => { + for (let { target } of entries) { + this._roundOrResetContentSize(target.querySelector("browser")); + } + })); + // observe resizing of each browser's parent (gets rid of RPC from content windows) + for (let bs of aWindow.document.querySelectorAll(".browserStack")) { + resizeObserver.observe(bs); } + // Rounding the content viewport. + this._updateSizeForTabsInWindow(aWindow); } _detachWindow(aWindow) { let tabBrowser = aWindow.gBrowser; tabBrowser.removeTabsProgressListener(this); + aWindow._rfpResizeObserver?.disconnect(); + delete aWindow._rfpResizeObserver; aWindow.removeEventListener("TabOpen", this); - // Clear all margins and tooltip for all browsers. + // revert tabpanel's style to default + tabBrowser.tabpanels?.classList.remove("letterboxing"); + + // and restore default size on each browser element for (let tab of tabBrowser.tabs) { let browser = tab.linkedBrowser; - this._clearContentViewMargin(browser); - } - } - - _detachAllWindows() { - let windowList = Services.wm.getEnumerator("navigator:browser"); - - while (windowList.hasMoreElements()) { - let win = windowList.getNext(); - - if (win.closed || !win.gBrowser) { - continue; - } - - this._detachWindow(win); + this._resetContentSize(browser); } + aWindow.removeEventListener("dblclick", this._onWindowDoubleClick); + delete aWindow.shrinkToLetterbox; + aWindow.removeEventListener("sizemodechange", windowResizeHandler); } _handleDOMWindowOpened(win) { diff --git a/toolkit/components/resistfingerprinting/content/letterboxing.css b/toolkit/components/resistfingerprinting/content/letterboxing.css new file mode 100644 index 0000000000000000000000000000000000000000..b571cda5d23f8be9e4150274b90d0839362667de --- /dev/null +++ b/toolkit/components/resistfingerprinting/content/letterboxing.css @@ -0,0 +1,122 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + Never modify the following selector without synchronizing + LETTERBOX_CSS_SELECTOR in RFPHelper.sys.mjs, where + --letterboxing-width & --letterboxing-height are actually set. + And you will need to update the JS also if you move the rules to another file. +**/ +.letterboxing .browserContainer { + /* + From Firefox 115 on, .browserContainer layout is flex / column, + and without this trick the .browserStack's resize observer + doesn't get notified on horizontal shrinking. + See also tor-browser#42405. + */ + overflow: hidden; + background: var(--letterboxing-bgcolor); +} + +.browserDecorator { + display: none; + pointer-events: none; + background: transparent; + position: relative; + z-index: 1; +} + +.letterboxing { + --letterboxing-border-radius: 8px; + --letterboxing-border-top-radius: 0; + --letterboxing-vertical-alignment: start; + --letterboxing-shadow-color: rgba(12, 12, 13, 0.10); + --letterboxing-bgcolor: var(--tabpanel-background-color); + --letterboxing-gradient-color1: var(--letterboxing-bgcolor); + --letterboxing-gradient-color2: color-mix(in srgb, var(--chrome-content-separator-color) 50%, var(--letterboxing-bgcolor)); + --letterboxing-border-color: var(--letterboxing-bgcolor); + --letterboxing-decorator-visibility: visible; +} + +.letterboxing.letterboxing-vcenter .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) { + --letterboxing-border-top-radius: var(--letterboxing-border-radius); + --letterboxing-vertical-alignment: center; +} + +.letterboxing.letterboxing-gradient .browserContainer { + background: linear-gradient(283deg, var(--letterboxing-gradient-color1) 0%, var(--letterboxing-gradient-color2) 100%), var(--letterboxing-bgcolor); +} + +:root:not([inDOMFullscreen]) .letterboxing .browserContainer:not(.responsive-mode) + > .browserStack:not(.exclude-letterboxing) + > .browserDecorator { + display: initial; + visibility: var(--letterboxing-decorator-visibility); + border-radius: var(--letterboxing-border-radius); + border-top-left-radius: var(--letterboxing-border-top-radius); + border-top-right-radius: var(--letterboxing-border-top-radius); + box-shadow: var(--letterboxing-border-color) 0px 0px .1px inset, var(--letterboxing-border-color) 0 0 .1px; + border: .1px solid var(--letterboxing-border-color); + outline: .1px solid var(--letterboxing-bgcolor); + height: calc(var(--letterboxing-height) + 1px); + top: -1px; +} + +.letterboxing-vcenter .browserDecorator { + height: auto !important; + top: 0 !important; +} + +/* + Align status bar with content. + TODO: switch to nested CSS selectors for conciseness when available (Firefox >= 117) +*/ +.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) + > #statuspanel:not([hidden]) { + position: relative; + place-self: end left; + left: 0; + right: 0; + z-index: 2; + --letterboxing-status-left-radius: var(--letterboxing-border-radius); + --letterboxing-status-right-radius: 0; +} +.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) + > #statuspanel:not([mirror]):-moz-locale-dir(rtl), +.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) + > #statuspanel[mirror]:-moz-locale-dir(ltr) { + left: 0; + right: 0; + --letterboxing-status-right-radius: var(--letterboxing-border-radius); + --letterboxing-status-left-radius: 0; + justify-self: right; +} + +.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) +#statuspanel-label { + border-radius: 0 0 var(--letterboxing-status-right-radius) var(--letterboxing-status-left-radius); + margin: 0; + border: 1px solid var(--letterboxing-border-color); + max-width: calc(var(--letterboxing-width) * .5); +} + +.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) > browser { + box-shadow: 0px 4px 8px 0px var(--letterboxing-shadow-color); + border-radius: var(--letterboxing-border-radius); + border-top-left-radius: var(--letterboxing-border-top-radius); + border-top-right-radius: var(--letterboxing-border-top-radius); + width: var(--letterboxing-width) !important; + height: var(--letterboxing-height) !important; + background: var(--letterboxing-gradient-color2); +} + +browser:fullscreen { + --letterboxing-border-top-radius: 0; + --letterboxing-border-radius: 0; +} + +:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode) + > .browserStack:not(.exclude-letterboxing) { + place-content: var(--letterboxing-vertical-alignment) center; +} diff --git a/toolkit/components/resistfingerprinting/jar.mn b/toolkit/components/resistfingerprinting/jar.mn index 9053057d14b496a4afbff03554d32cb56ba67900..ec1b6b10394be1f754443e6eacda28a31ac0506e 100644 --- a/toolkit/components/resistfingerprinting/jar.mn +++ b/toolkit/components/resistfingerprinting/jar.mn @@ -3,6 +3,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. toolkit.jar: + content/global/resistfingerprinting/letterboxing.css (content/letterboxing.css) content/global/usercharacteristics/gl-matrix.js (content/gl-matrix.js) content/global/usercharacteristics/ssdeep.js (content/ssdeep.js) content/global/usercharacteristics/usercharacteristics.css (content/usercharacteristics.css) diff --git a/toolkit/components/search/AppProvidedSearchEngine.sys.mjs b/toolkit/components/search/AppProvidedSearchEngine.sys.mjs index 6b99857906866855b9ab2ee5b93e1d9632049d60..0e6a21cb0ed66ef618d93348320b519b10b628bd 100644 --- a/toolkit/components/search/AppProvidedSearchEngine.sys.mjs +++ b/toolkit/components/search/AppProvidedSearchEngine.sys.mjs @@ -84,6 +84,8 @@ class IconHandler { await this.#getIconList(); } + return this.#iconList.get(engineIdentifier); + // eslint-disable-next-line no-unreachable let iconRecords = this.#iconList.filter(r => this._identifierMatches(engineIdentifier, r.engineIdentifiers) ); @@ -210,12 +212,18 @@ class IconHandler { */ async #getIconList() { try { - this.#iconList = await this.#iconCollection.get(); + this.#iconList = new Map( + await ( + await fetch( + "chrome://global/content/search/torBrowserSearchEngineIcons.json" + ) + ).json() + ); } catch (ex) { console.error(ex); - this.#iconList = []; + this.#iconList = null; } - if (!this.#iconList.length) { + if (!this.#iconList) { console.error("Failed to obtain search engine icon list records"); } } diff --git a/toolkit/components/search/SearchEngine.sys.mjs b/toolkit/components/search/SearchEngine.sys.mjs index 733fec524fb64d224dbc2f07733fa76010fad803..74a67bab07d819406892688e2bbbb38b8e0783ee 100644 --- a/toolkit/components/search/SearchEngine.sys.mjs +++ b/toolkit/components/search/SearchEngine.sys.mjs @@ -12,6 +12,7 @@ ChromeUtils.defineESModuleGetters(lazy, { NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", SearchSettings: "resource://gre/modules/SearchSettings.sys.mjs", SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs", + SecurityLevelPrefs: "resource://gre/modules/SecurityLevel.sys.mjs", OpenSearchEngine: "resource://gre/modules/OpenSearchEngine.sys.mjs", }); @@ -439,6 +440,26 @@ export class EngineURL { */ getSubmission(searchTerms, queryCharset, purpose) { var url = ParamSubstitution(this.template, searchTerms, queryCharset); + + if ( + lazy.SecurityLevelPrefs?.securityLevel === "safest" && + this.type === lazy.SearchUtils.URL_TYPE.SEARCH + ) { + let host = this.templateHost; + try { + host = Services.eTLD.getBaseDomainFromHost(host); + } catch (ex) { + lazy.logConsole.warn("Failed to get a FPD", ex, host); + } + if ( + host === "duckduckgo.com" || + host === + "duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion" + ) { + url += "html"; + } + } + // Default to searchbar if the purpose is not provided var requestPurpose = purpose || "searchbar"; diff --git a/toolkit/components/search/SearchService.sys.mjs b/toolkit/components/search/SearchService.sys.mjs index 69b739ff0b961396e15995f7c92cfcf3e6edf6fb..5103a6e2dfd14e0e48e07d93639325391f4772d4 100644 --- a/toolkit/components/search/SearchService.sys.mjs +++ b/toolkit/components/search/SearchService.sys.mjs @@ -1275,10 +1275,6 @@ export class SearchService { // start listening straight away. Services.obs.addObserver(this, lazy.Region.REGION_TOPIC); - this.#getIgnoreListAndSubscribe().catch(ex => - console.error(ex, "Search Service could not get the ignore list.") - ); - this.#engineSelector = new lazy.SearchEngineSelector( this.#handleConfigurationUpdated.bind(this) ); @@ -1410,6 +1406,7 @@ export class SearchService { * handled via a sync listener. * */ + // eslint-disable-next-line no-unused-private-class-members async #getIgnoreListAndSubscribe() { let listener = this.#handleIgnoreListUpdated.bind(this); const current = await lazy.IgnoreLists.getAndSubscribe(listener); @@ -2436,22 +2433,11 @@ export class SearchService { // This is prefixed with _ rather than # because it is // called in test_remove_engine_notification_box.js async _fetchEngineSelectorEngines() { - let searchEngineSelectorProperties = { - locale: Services.locale.appLocaleAsBCP47, - region: lazy.Region.home || "unknown", - channel: lazy.SearchUtils.MODIFIED_APP_CHANNEL, - experiment: - lazy.NimbusFeatures.searchConfiguration.getVariable("experiment") ?? "", - distroID: lazy.SearchUtils.distroID ?? "", - }; - - for (let [key, value] of Object.entries(searchEngineSelectorProperties)) { - this._settings.setMetaDataAttribute(key, value); - } - - return this.#engineSelector.fetchEngineConfiguration( - searchEngineSelectorProperties - ); + // tor-browser#43525: Check this still works. + const engines = await ( + await fetch("chrome://global/content/search/torBrowserSearchEngines.json") + ).json(); + return { engines, privateDefault: undefined }; } #setDefaultFromSelector(refinedConfig) { diff --git a/toolkit/components/search/content/duckduckgo.ico b/toolkit/components/search/content/duckduckgo.ico new file mode 100644 index 0000000000000000000000000000000000000000..3ad20825c107dd0f0b544f840f3755d44cba8719 Binary files /dev/null and b/toolkit/components/search/content/duckduckgo.ico differ diff --git a/toolkit/components/search/content/startpage.png b/toolkit/components/search/content/startpage.png new file mode 100644 index 0000000000000000000000000000000000000000..30ed2cd3a65a0ff09fec246e5dab662a297bacb9 Binary files /dev/null and b/toolkit/components/search/content/startpage.png differ diff --git a/toolkit/components/search/content/torBrowserSearchEngineIcons.json b/toolkit/components/search/content/torBrowserSearchEngineIcons.json new file mode 100644 index 0000000000000000000000000000000000000000..cb29be917f200f16b18128cde46ddd8d7321a353 --- /dev/null +++ b/toolkit/components/search/content/torBrowserSearchEngineIcons.json @@ -0,0 +1,7 @@ +[ + ["ddg", "chrome://global/content/search/duckduckgo.ico"], + ["ddg-onion", "chrome://global/content/search/duckduckgo.ico"], + ["startpage", "chrome://global/content/search/startpage.png"], + ["startpage-onion", "chrome://global/content/search/startpage.png"], + ["wikipedia", "chrome://global/content/search/wikipedia.ico"] +] diff --git a/toolkit/components/search/content/torBrowserSearchEngines.json b/toolkit/components/search/content/torBrowserSearchEngines.json new file mode 100644 index 0000000000000000000000000000000000000000..31fea068e1c5e5beed43d6efb4a69e9e327d4e7e --- /dev/null +++ b/toolkit/components/search/content/torBrowserSearchEngines.json @@ -0,0 +1,78 @@ +[ + { + "aliases": ["duckduckgo", "ddg"], + "name": "DuckDuckGo", + "urls": { + "search": { + "base": "https://duckduckgo.com/", + "params": [], + "searchTermParamName": "q" + } + }, + "id": "04e99a38-13ee-47d8-8aa4-64482b3dea99", + "identifier": "ddg", + "recordType": "engine", + "variants": [] + }, + { + "aliases": ["ddgonion"], + "name": "DuckDuckGo (.onion)", + "urls": { + "search": { + "base": "https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/", + "params": [], + "searchTermParamName": "q" + } + }, + "id": "1e431da4-a60c-4411-9251-a95a841d451f", + "identifier": "ddg-onion", + "recordType": "engine", + "variants": [] + }, + { + "aliases": ["startpage"], + "name": "Startpage", + "urls": { + "search": { + "base": "https://www.startpage.com/sp/search", + "params": [], + "searchTermParamName": "q" + } + }, + "id": "927bbd9f-b2f3-48b4-8974-1c1148028f4d", + "identifier": "startpage", + "recordType": "engine", + "variants": [] + }, + { + "aliases": ["startpage-onion"], + "name": "Startpage (.onion)", + "urls": { + "search": { + "base": "http://startpagel6srwcjlue4zgq3zevrujfaow726kjytqbbjyrswwmjzcqd.onion/sp/search", + "params": [], + "searchTermParamName": "q" + } + }, + "id": "e7eaba8d-6b9e-43fb-a799-b01b096c03ff", + "identifier": "startpage-onion", + "recordType": "engine", + "variants": [] + }, + { + "aliases": ["wikipedia"], + "classification": "unknown", + "name": "Wikipedia (en)", + "urls": { + "search": { + "base": "https://en.wikipedia.org/wiki/Special:Search", + "params": [], + "searchTermParamName": "search" + } + }, + "id": "7f6d23c2-191e-483e-af3a-ce6451e3a8dd", + "identifier": "wikipedia", + "recordType": "engine", + "variants": [] + } +] diff --git a/toolkit/components/search/content/wikipedia.ico b/toolkit/components/search/content/wikipedia.ico new file mode 100644 index 0000000000000000000000000000000000000000..4314071e24c026048339d5b466f4929db1f9ffc0 Binary files /dev/null and b/toolkit/components/search/content/wikipedia.ico differ diff --git a/toolkit/components/search/jar.mn b/toolkit/components/search/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..1c657dc684687d17c0dda62b14fe862351a2d688 --- /dev/null +++ b/toolkit/components/search/jar.mn @@ -0,0 +1,6 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +toolkit.jar: + content/global/search/ (content/*) diff --git a/toolkit/components/search/moz.build b/toolkit/components/search/moz.build index 4c811352a48e54a38e55032241de72dedee35be8..1c14dc108319b09104090badabbc4f1f888d5a43 100644 --- a/toolkit/components/search/moz.build +++ b/toolkit/components/search/moz.build @@ -42,5 +42,7 @@ TESTING_JS_MODULES += [ "tests/SearchTestUtils.sys.mjs", ] +JAR_MANIFESTS += ["jar.mn"] + with Files("**"): BUG_COMPONENT = ("Firefox", "Search") diff --git a/toolkit/components/securitylevel/SecurityLevel.manifest b/toolkit/components/securitylevel/SecurityLevel.manifest new file mode 100644 index 0000000000000000000000000000000000000000..0bfbd2ba1ac7b9d980d511ed79ea70ad6d01b79a --- /dev/null +++ b/toolkit/components/securitylevel/SecurityLevel.manifest @@ -0,0 +1 @@ +category profile-after-change SecurityLevel @torproject.org/security-level;1 diff --git a/toolkit/components/securitylevel/SecurityLevel.sys.mjs b/toolkit/components/securitylevel/SecurityLevel.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..28636a6fb9f65b8a2d51f8ae0a167373f1139afb --- /dev/null +++ b/toolkit/components/securitylevel/SecurityLevel.sys.mjs @@ -0,0 +1,476 @@ +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs", +}); + +const logger = console.createInstance({ + maxLogLevel: "Info", + prefix: "SecurityLevel", +}); + +const BrowserTopics = Object.freeze({ + ProfileAfterChange: "profile-after-change", +}); + +// The Security Settings prefs in question. +const kSliderPref = "browser.security_level.security_slider"; +const kCustomPref = "browser.security_level.security_custom"; + +// __getPrefValue(prefName)__ +// Returns the current value of a preference, regardless of its type. +var getPrefValue = function (prefName) { + switch (Services.prefs.getPrefType(prefName)) { + case Services.prefs.PREF_BOOL: + return Services.prefs.getBoolPref(prefName); + case Services.prefs.PREF_INT: + return Services.prefs.getIntPref(prefName); + case Services.prefs.PREF_STRING: + return Services.prefs.getCharPref(prefName); + default: + return null; + } +}; + +// __bindPref(prefName, prefHandler, init)__ +// Applies prefHandler whenever the value of the pref changes. +// If init is true, applies prefHandler to the current value. +// Returns a zero-arg function that unbinds the pref. +var bindPref = function (prefName, prefHandler, init = false) { + let update = () => { + prefHandler(getPrefValue(prefName)); + }, + observer = { + observe(subject, topic, data) { + if (data === prefName) { + update(); + } + }, + }; + Services.prefs.addObserver(prefName, observer); + if (init) { + update(); + } + return () => { + Services.prefs.removeObserver(prefName, observer); + }; +}; + +// __bindPrefAndInit(prefName, prefHandler)__ +// Applies prefHandler to the current value of pref specified by prefName. +// Re-applies prefHandler whenever the value of the pref changes. +// Returns a zero-arg function that unbinds the pref. +var bindPrefAndInit = (prefName, prefHandler) => + bindPref(prefName, prefHandler, true); + +async function waitForExtensionMessage(extensionId, checker = () => {}) { + const { torWaitForExtensionMessage } = lazy.ExtensionParent; + if (torWaitForExtensionMessage) { + return torWaitForExtensionMessage(extensionId, checker); + } + return undefined; +} + +async function sendExtensionMessage(extensionId, message) { + const { torSendExtensionMessage } = lazy.ExtensionParent; + if (torSendExtensionMessage) { + return torSendExtensionMessage(extensionId, message); + } + return undefined; +} + +// ## NoScript settings + +// Minimum and maximum capability states as controlled by NoScript. +const max_caps = [ + "fetch", + "font", + "frame", + "media", + "object", + "other", + "script", + "webgl", + "noscript", +]; +const min_caps = ["frame", "other", "noscript"]; + +// Untrusted capabilities for [Standard, Safer, Safest] safety levels. +const untrusted_caps = [ + max_caps, // standard safety: neither http nor https + ["frame", "font", "object", "other", "noscript"], // safer: http + min_caps, // safest: neither http nor https +]; + +// Default capabilities for [Standard, Safer, Safest] safety levels. +const default_caps = [ + max_caps, // standard: both http and https + ["fetch", "font", "frame", "object", "other", "script", "noscript"], // safer: https only + min_caps, // safest: both http and https +]; + +// __noscriptSettings(safetyLevel)__. +// Produces NoScript settings with policy according to +// the safetyLevel which can be: +// 0 = Standard, 1 = Safer, 2 = Safest +// +// At the "Standard" safety level, we leave all sites at +// default with maximal capabilities. Essentially no content +// is blocked. +// +// At "Safer", we set all http sites to untrusted, +// and all https sites to default. Scripts are only permitted +// on https sites. Neither type of site is supposed to allow +// media, but both allow fonts (as we used in legacy NoScript). +// +// At "Safest", all sites are at default with minimal +// capabilities. Most things are blocked. +let noscriptSettings = safetyLevel => ({ + __meta: { + name: "updateSettings", + recipientInfo: null, + }, + policy: { + DEFAULT: { + capabilities: default_caps[safetyLevel], + temp: false, + }, + TRUSTED: { + capabilities: max_caps, + temp: false, + }, + UNTRUSTED: { + capabilities: untrusted_caps[safetyLevel], + temp: false, + }, + sites: { + trusted: [], + untrusted: [[], ["http:"], []][safetyLevel], + custom: {}, + temp: [], + }, + enforced: true, + autoAllowTop: false, + }, + isTorBrowser: true, + tabId: -1, +}); + +// ## Communications + +// The extension ID for NoScript (WebExtension) +const noscriptID = "{73a6fe31-595d-460b-a920-fcc0f8843232}"; + +// Ensure binding only occurs once. +let initialized = false; + +// __initialize()__. +// The main function that binds the NoScript settings to the security +// slider pref state. +var initializeNoScriptControl = () => { + if (initialized) { + return; + } + initialized = true; + + try { + // LegacyExtensionContext is not there anymore. Using raw + // Services.cpmm.sendAsyncMessage mechanism to communicate with + // NoScript. + + // The component that handles WebExtensions' sendMessage. + + // __setNoScriptSettings(settings)__. + // NoScript listens for internal settings with onMessage. We can send + // a new settings JSON object according to NoScript's + // protocol and these are accepted! See the use of + // `browser.runtime.onMessage.addListener(...)` in NoScript's bg/main.js. + + // TODO: Is there a better way? + let sendNoScriptSettings = settings => + sendExtensionMessage(noscriptID, settings); + + // __setNoScriptSafetyLevel(safetyLevel)__. + // Set NoScript settings according to a particular safety level + // (security slider level): 0 = Standard, 1 = Safer, 2 = Safest + let setNoScriptSafetyLevel = safetyLevel => + sendNoScriptSettings(noscriptSettings(safetyLevel)); + + // __securitySliderToSafetyLevel(sliderState)__. + // Converts the "browser.security_level.security_slider" pref value + // to a "safety level" value: 0 = Standard, 1 = Safer, 2 = Safest + let securitySliderToSafetyLevel = sliderState => + [undefined, 2, 1, 1, 0][sliderState]; + + // Wait for the first message from NoScript to arrive, and then + // bind the security_slider pref to the NoScript settings. + let messageListener = a => { + try { + logger.debug("Message received from NoScript:", a); + let noscriptPersist = Services.prefs.getBoolPref( + "browser.security_level.noscript_persist", + false + ); + let noscriptInited = Services.prefs.getBoolPref( + "browser.security_level.noscript_inited", + false + ); + // Set the noscript safety level once if we have never run noscript + // before, or if we are not allowing noscript per-site settings to be + // persisted between browser sessions. Otherwise make sure that the + // security slider position, if changed, will rewrite the noscript + // settings. + bindPref( + kSliderPref, + sliderState => + setNoScriptSafetyLevel(securitySliderToSafetyLevel(sliderState)), + !noscriptPersist || !noscriptInited + ); + if (!noscriptInited) { + Services.prefs.setBoolPref( + "browser.security_level.noscript_inited", + true + ); + } + } catch (e) { + logger.exception(e); + } + }; + waitForExtensionMessage(noscriptID, a => a.__meta.name === "started").then( + messageListener + ); + logger.info("Listening for messages from NoScript."); + } catch (e) { + logger.exception(e); + } +}; + +// ### Constants + +// __kSecuritySettings__. +// A table of all prefs bound to the security slider, and the value +// for each security setting. Note that 2-m and 3-m are identical, +// corresponding to the old 2-medium-high setting. We also separately +// bind NoScript settings to the browser.security_level.security_slider +// (see noscript-control.js). +/* eslint-disable */ +// prettier-ignore +const kSecuritySettings = { + // Preference name: [0, 1-high 2-m 3-m 4-low] + "javascript.options.ion": [, false, false, false, true ], + "javascript.options.baselinejit": [, false, false, false, true ], + "javascript.options.native_regexp": [, false, false, false, true ], + "mathml.disabled": [, true, true, true, false], + "gfx.font_rendering.graphite.enabled": [, false, false, false, true ], + "gfx.font_rendering.opentype_svg.enabled": [, false, false, false, true ], + "svg.disabled": [, true, false, false, false], + "javascript.options.asmjs": [, false, false, false, true ], + "javascript.options.wasm": [, false, false, false, true ], +}; +/* eslint-enable */ + +// ### Prefs + +// __write_setting_to_prefs(settingIndex)__. +// Take a given setting index and write the appropriate pref values +// to the pref database. +var write_setting_to_prefs = function (settingIndex) { + Object.keys(kSecuritySettings).forEach(prefName => + Services.prefs.setBoolPref( + prefName, + kSecuritySettings[prefName][settingIndex] + ) + ); +}; + +// __read_setting_from_prefs()__. +// Read the current pref values, and decide if any of our +// security settings matches. Otherwise return null. +var read_setting_from_prefs = function (prefNames) { + prefNames = prefNames || Object.keys(kSecuritySettings); + for (let settingIndex of [1, 2, 3, 4]) { + let possibleSetting = true; + // For the given settingIndex, check if all current pref values + // match the setting. + for (let prefName of prefNames) { + if ( + kSecuritySettings[prefName][settingIndex] !== + Services.prefs.getBoolPref(prefName) + ) { + possibleSetting = false; + } + } + if (possibleSetting) { + // We have a match! + return settingIndex; + } + } + // No matching setting; return null. + return null; +}; + +// __watch_security_prefs(onSettingChanged)__. +// Whenever a pref bound to the security slider changes, onSettingChanged +// is called with the new security setting value (1,2,3,4 or null). +// Returns a zero-arg function that ends this binding. +var watch_security_prefs = function (onSettingChanged) { + let prefNames = Object.keys(kSecuritySettings); + let unbindFuncs = []; + for (let prefName of prefNames) { + unbindFuncs.push( + bindPrefAndInit(prefName, () => + onSettingChanged(read_setting_from_prefs()) + ) + ); + } + // Call all the unbind functions. + return () => unbindFuncs.forEach(unbind => unbind()); +}; + +// __initialized__. +// Have we called initialize() yet? +var initializedSecPrefs = false; + +// __initialize()__. +// Defines the behavior of "browser.security_level.security_custom", +// "browser.security_level.security_slider", and the security-sensitive +// prefs declared in kSecuritySettings. +var initializeSecurityPrefs = function () { + // Only run once. + if (initializedSecPrefs) { + return; + } + logger.info("Initializing security-prefs.js"); + initializedSecPrefs = true; + // When security_custom is set to false, apply security_slider setting + // to the security-sensitive prefs. + bindPrefAndInit(kCustomPref, function (custom) { + if (custom === false) { + write_setting_to_prefs(Services.prefs.getIntPref(kSliderPref)); + } + }); + // If security_slider is given a new value, then security_custom should + // be set to false. + bindPref(kSliderPref, function (prefIndex) { + Services.prefs.setBoolPref(kCustomPref, false); + write_setting_to_prefs(prefIndex); + }); + // If a security-sensitive pref changes, then decide if the set of pref values + // constitutes a security_slider setting or a custom value. + watch_security_prefs(settingIndex => { + if (settingIndex === null) { + Services.prefs.setBoolPref(kCustomPref, true); + } else { + Services.prefs.setIntPref(kSliderPref, settingIndex); + Services.prefs.setBoolPref(kCustomPref, false); + } + }); + // Migrate from old medium-low (3) to new medium (2). + if ( + Services.prefs.getBoolPref(kCustomPref) === false && + Services.prefs.getIntPref(kSliderPref) === 3 + ) { + Services.prefs.setIntPref(kSliderPref, 2); + write_setting_to_prefs(2); + } + + logger.info("security-prefs.js initialization complete"); +}; + +// tor-browser#41460: we changed preference names in 12.0. +// 11.5.8 is an obligated step for desktop users, so this code is helpful only +// to alpha users, and we could remove it quite soon. +function migratePreferences() { + const kPrefCheck = "extensions.torbutton.noscript_inited"; + // For 12.0, check for extensions.torbutton.noscript_inited, which was set + // as a user preference for sure, if someone used security level in previous + // versions. + if (!Services.prefs.prefHasUserValue(kPrefCheck)) { + return; + } + const migrate = (oldName, newName, getter, setter) => { + oldName = `extensions.torbutton.${oldName}`; + newName = `browser.${newName}`; + if (Services.prefs.prefHasUserValue(oldName)) { + setter(newName, getter(oldName)); + Services.prefs.clearUserPref(oldName); + } + }; + const prefs = { + security_custom: "security_level.security_custom", + noscript_persist: "security_level.noscript_persist", + noscript_inited: "security_level.noscript_inited", + }; + for (const [oldName, newName] of Object.entries(prefs)) { + migrate( + oldName, + newName, + Services.prefs.getBoolPref.bind(Services.prefs), + Services.prefs.setBoolPref.bind(Services.prefs) + ); + } + migrate( + "security_slider", + "security_level.security_slider", + Services.prefs.getIntPref.bind(Services.prefs), + Services.prefs.setIntPref.bind(Services.prefs) + ); +} + +/** + * This class is used to initialize the security level stuff at the startup + */ +export class SecurityLevel { + QueryInterface = ChromeUtils.generateQI(["nsIObserver"]); + + init() { + migratePreferences(); + initializeNoScriptControl(); + initializeSecurityPrefs(); + } + + observe(aSubject, aTopic) { + if (aTopic === BrowserTopics.ProfileAfterChange) { + this.init(); + } + } +} + +/* + Security Level Prefs + + Getters and Setters for relevant torbutton prefs +*/ +export const SecurityLevelPrefs = { + SecurityLevels: Object.freeze({ + safest: 1, + safer: 2, + standard: 4, + }), + security_slider_pref: "browser.security_level.security_slider", + security_custom_pref: "browser.security_level.security_custom", + + get securityLevel() { + // Set the default return value to 0, which won't match anything in + // SecurityLevels. + const val = Services.prefs.getIntPref(this.security_slider_pref, 0); + return Object.entries(this.SecurityLevels).find( + entry => entry[1] === val + )?.[0]; + }, + + set securityLevel(level) { + const val = this.SecurityLevels[level]; + if (val !== undefined) { + Services.prefs.setIntPref(this.security_slider_pref, val); + } + }, + + get securityCustom() { + return Services.prefs.getBoolPref(this.security_custom_pref); + }, + + set securityCustom(val) { + Services.prefs.setBoolPref(this.security_custom_pref, val); + }, +}; /* Security Level Prefs */ diff --git a/toolkit/components/securitylevel/components.conf b/toolkit/components/securitylevel/components.conf new file mode 100644 index 0000000000000000000000000000000000000000..d58ef8e5d198ec5253c66e30d9410aa2dafd4b8f --- /dev/null +++ b/toolkit/components/securitylevel/components.conf @@ -0,0 +1,10 @@ +Classes = [ + { + "cid": "{c602ffe5-abf4-40d0-a944-26738b81efdb}", + "contract_ids": [ + "@torproject.org/security-level;1", + ], + "esModule": "resource://gre/modules/SecurityLevel.sys.mjs", + "constructor": "SecurityLevel", + } +] diff --git a/toolkit/components/securitylevel/moz.build b/toolkit/components/securitylevel/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..fb51d1810650edb74653ad59744f66af9de2588e --- /dev/null +++ b/toolkit/components/securitylevel/moz.build @@ -0,0 +1,11 @@ +EXTRA_JS_MODULES += [ + "SecurityLevel.sys.mjs", +] + +XPCOM_MANIFESTS += [ + "components.conf", +] + +EXTRA_COMPONENTS += [ + "SecurityLevel.manifest", +] diff --git a/toolkit/components/shopping/jar.mn b/toolkit/components/shopping/jar.mn index d6a9720b10587038fdaa166c35ed7529e10956fe..f0a462c9b5eb2fa278d3b8c12c48c65438dcd91d 100644 --- a/toolkit/components/shopping/jar.mn +++ b/toolkit/components/shopping/jar.mn @@ -2,19 +2,4 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -toolkit.jar: - content/global/shopping/ProductConfig.mjs (content/ProductConfig.mjs) - content/global/shopping/ProductValidator.sys.mjs (content/ProductValidator.sys.mjs) - content/global/shopping/ShoppingProduct.mjs (content/ShoppingProduct.mjs) - content/global/shopping/analysis_response.schema.json (schemas/analysis_response.schema.json) - content/global/shopping/recommendations_response.schema.json (schemas/recommendations_response.schema.json) - content/global/shopping/analysis_request.schema.json (schemas/analysis_request.schema.json) - content/global/shopping/recommendations_request.schema.json (schemas/recommendations_request.schema.json) - content/global/shopping/attribution_response.schema.json (schemas/attribution_response.schema.json) - content/global/shopping/attribution_request.schema.json (schemas/attribution_request.schema.json) - content/global/shopping/reporting_response.schema.json (schemas/reporting_response.schema.json) - content/global/shopping/reporting_request.schema.json (schemas/reporting_request.schema.json) - content/global/shopping/analysis_status_request.schema.json (schemas/analysis_status_request.schema.json) - content/global/shopping/analysis_status_response.schema.json (schemas/analysis_status_response.schema.json) - content/global/shopping/analyze_request.schema.json (schemas/analyze_request.schema.json) - content/global/shopping/analyze_response.schema.json (schemas/analyze_response.schema.json) +# Removed ShoppingProduct modules and schema JSONs. tor-browser#42831. diff --git a/toolkit/components/telemetry/app/TelemetrySend.sys.mjs b/toolkit/components/telemetry/app/TelemetrySend.sys.mjs index 56e7f2e5ad380e79c46daed49833a55af5c657eb..aa1b078160a21c1d17ad138cb2a3a65350f1c907 100644 --- a/toolkit/components/telemetry/app/TelemetrySend.sys.mjs +++ b/toolkit/components/telemetry/app/TelemetrySend.sys.mjs @@ -1694,6 +1694,9 @@ export var TelemetrySendImpl = { }, runPingSender(pings, observer) { + throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); + + /* eslint-disable-next-line no-unreachable */ if (AppConstants.platform === "android") { throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); } diff --git a/toolkit/components/telemetry/moz.build b/toolkit/components/telemetry/moz.build index baaddec36152f073ff76b3c5f8e0b6459a9f66b8..d1e3e0986f631e612cba0c0c6e3baa6992f0da2a 100644 --- a/toolkit/components/telemetry/moz.build +++ b/toolkit/components/telemetry/moz.build @@ -8,10 +8,6 @@ include("/ipc/chromium/chromium-config.mozbuild") FINAL_LIBRARY = "xul" -DIRS = [ - "pingsender", -] - if CONFIG["COMPILE_ENVIRONMENT"]: EXPORTS.mozilla += ["!dap_ffi_generated.h"] diff --git a/toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs b/toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..1d1bdaf0c4994b8a29686ce59a6c72ea267ea1e1 --- /dev/null +++ b/toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs @@ -0,0 +1,147 @@ +import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", +}); + +const log = console.createInstance({ + maxLogLevel: "Info", + prefix: "TorBootstrapRequest", +}); + +/** + * This class encapsulates the observer register/unregister logic to provide an + * XMLHttpRequest-like API to bootstrap tor. + * TODO: Remove this class, and move its logic inside the TorProvider. + */ +export class TorBootstrapRequest { + // number of ms to wait before we abandon the bootstrap attempt + // a value of 0 implies we never wait + timeout = 0; + + // callbacks for bootstrap process status updates + onbootstrapstatus = (_progress, _status) => {}; + onbootstrapcomplete = () => {}; + onbootstraperror = _error => {}; + + // internal resolve() method for bootstrap + #bootstrapPromiseResolve = null; + #bootstrapPromise = null; + #timeoutID = null; + + observe(subject, topic) { + const obj = subject?.wrappedJSObject; + switch (topic) { + case lazy.TorProviderTopics.BootstrapStatus: { + const progress = obj.PROGRESS; + if (this.onbootstrapstatus) { + const status = obj.TAG; + this.onbootstrapstatus(progress, status); + } + if (progress === 100) { + if (this.onbootstrapcomplete) { + this.onbootstrapcomplete(); + } + this.#bootstrapPromiseResolve(true); + clearTimeout(this.#timeoutID); + this.#timeoutID = null; + } + + break; + } + case lazy.TorProviderTopics.BootstrapError: { + log.info("TorBootstrapRequest: observerd TorBootstrapError", obj); + const error = new Error(obj.summary); + Object.assign(error, obj); + this.#stop(error); + break; + } + } + } + + // resolves 'true' if bootstrap succeeds, false otherwise + bootstrap() { + if (this.#bootstrapPromise) { + return this.#bootstrapPromise; + } + + this.#bootstrapPromise = new Promise(resolve => { + this.#bootstrapPromiseResolve = resolve; + + // register ourselves to listen for bootstrap events + Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapStatus); + Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapError); + + // optionally cancel bootstrap after a given timeout + if (this.timeout > 0) { + this.#timeoutID = setTimeout(() => { + this.#timeoutID = null; + this.#stop( + new Error( + `Bootstrap attempt abandoned after waiting ${this.timeout} ms` + ) + ); + }, this.timeout); + } + + // Wait for bootstrapping to begin and maybe handle error. + // Notice that we do not resolve the promise here in case of success, but + // we do it from the BootstrapStatus observer. + // NOTE: After TorProviderBuilder.build resolves, TorProvider.init will + // have completed. In particular, assuming no errors, the TorSettings will + // have been initialised and passed on to the provider via + // TorProvider.writeSettings. Therefore we should be safe to immediately + // call `connect` using the latest user settings. + lazy.TorProviderBuilder.build() + .then(provider => provider.connect()) + .catch(err => { + this.#stop(err); + }); + }).finally(() => { + // and remove ourselves once bootstrap is resolved + Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapStatus); + Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapError); + this.#bootstrapPromise = null; + }); + + return this.#bootstrapPromise; + } + + async cancel() { + await this.#stop(); + } + + // Internal implementation. Do not use directly, but call cancel, instead. + async #stop(error) { + // first stop our bootstrap timeout before handling the error + if (this.#timeoutID !== null) { + clearTimeout(this.#timeoutID); + this.#timeoutID = null; + } + + let provider; + try { + provider = await lazy.TorProviderBuilder.build(); + } catch { + // This was probably the error that lead to stop in the first place. + // No need to continue propagating it. + } + try { + await provider?.stopBootstrap(); + } catch (e) { + console.error("Failed to stop the bootstrap.", e); + if (!error) { + error = e; + } + } + + if (this.onbootstraperror && error) { + this.onbootstraperror(error); + } + + this.#bootstrapPromiseResolve(false); + } +} diff --git a/toolkit/components/tor-launcher/TorControlPort.sys.mjs b/toolkit/components/tor-launcher/TorControlPort.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..2453f908df34052b98d1437459603204aa945917 --- /dev/null +++ b/toolkit/components/tor-launcher/TorControlPort.sys.mjs @@ -0,0 +1,1345 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { TorParsers } from "resource://gre/modules/TorParsers.sys.mjs"; + +const logger = console.createInstance({ + maxLogLevelPref: "browser.tor_provider.cp_log_level", + prefix: "TorControlPort", +}); + +/** + * A wrapper around XPCOM sockets and buffers to handle streams in a standard + * async JS fashion. + * This class can handle both Unix sockets and TCP sockets. + */ +class AsyncSocket { + /** + * The output stream used for write operations. + * + * @type {nsIAsyncOutputStream} + */ + #outputStream; + /** + * The output stream can only have one registered callback at a time, so + * multiple writes need to be queued up (see nsIAsyncOutputStream.idl). + * Every item is associated with a promise we returned in write, and it will + * resolve it or reject it when called by the output stream. + * + * @type {nsIOutputStreamCallback[]} + */ + #outputQueue = []; + /** + * The input stream. + * + * @type {nsIAsyncInputStream} + */ + #inputStream; + /** + * An input stream adapter that makes reading from scripts easier. + * + * @type {nsIScriptableInputStream} + */ + #scriptableInputStream; + /** + * The queue of callbacks to be used when we receive data. + * Every item is associated with a promise we returned in read, and it will + * resolve it or reject it when called by the input stream. + * + * @type {nsIInputStreamCallback[]} + */ + #inputQueue = []; + + /** + * Connect to a Unix socket. Not available on Windows. + * + * @param {nsIFile} ipcFile The path to the Unix socket to connect to. + * @returns {AsyncSocket} + */ + static fromIpcFile(ipcFile) { + const sts = Cc[ + "@mozilla.org/network/socket-transport-service;1" + ].getService(Ci.nsISocketTransportService); + const socket = new AsyncSocket(); + const transport = sts.createUnixDomainTransport(ipcFile); + socket.#createStreams(transport); + return socket; + } + + /** + * Connect to a TCP socket. + * + * @param {string} host The hostname to connect the TCP socket to. + * @param {number} port The port to connect the TCP socket to. + * @returns {AsyncSocket} + */ + static fromSocketAddress(host, port) { + const sts = Cc[ + "@mozilla.org/network/socket-transport-service;1" + ].getService(Ci.nsISocketTransportService); + const socket = new AsyncSocket(); + const transport = sts.createTransport([], host, port, null, null); + socket.#createStreams(transport); + return socket; + } + + #createStreams(socketTransport) { + const OPEN_UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED; + this.#outputStream = socketTransport + .openOutputStream(OPEN_UNBUFFERED, 1, 1) + .QueryInterface(Ci.nsIAsyncOutputStream); + + this.#inputStream = socketTransport + .openInputStream(OPEN_UNBUFFERED, 1, 1) + .QueryInterface(Ci.nsIAsyncInputStream); + this.#scriptableInputStream = Cc[ + "@mozilla.org/scriptableinputstream;1" + ].createInstance(Ci.nsIScriptableInputStream); + this.#scriptableInputStream.init(this.#inputStream); + } + + /** + * Asynchronously write string to underlying socket. + * + * When write is called, we create a new promise and queue it on the output + * queue. If it is the only element in the queue, we ask the output stream to + * run it immediately. + * Otherwise, the previous item of the queue will run it after it finishes. + * + * @param {string} str The string to write to the socket. The underlying + * implementation should convert JS strings (UTF-16) into UTF-8 strings. + * See also write nsIOutputStream (the first argument is a string, not a + * wstring). + * @returns {Promise<number>} The number of written bytes + */ + async write(str) { + return new Promise((resolve, reject) => { + // Asynchronously wait for the stream to be writable (or closed) if we + // have any pending requests. + const tryAsyncWait = () => { + if (this.#outputQueue.length) { + this.#outputStream.asyncWait( + this.#outputQueue.at(0), // next request + 0, + 0, + Services.tm.currentThread + ); + } + }; + + // Implement an nsIOutputStreamCallback: write the string once possible, + // and then start running the following queue item, if any. + this.#outputQueue.push({ + onOutputStreamReady: () => { + try { + const bytesWritten = this.#outputStream.write(str, str.length); + + // Remove this callback object from queue, as it is now completed. + this.#outputQueue.shift(); + + // Queue the next request if there is one. + tryAsyncWait(); + + // Finally, resolve the promise. + resolve(bytesWritten); + } catch (err) { + // Reject the promise on error. + reject(err); + } + }, + }); + + // Length 1 imples that there is no in-flight asyncWait, so we may + // immediately follow through on this write. + if (this.#outputQueue.length === 1) { + tryAsyncWait(); + } + }); + } + + /** + * Asynchronously read string from underlying socket and return it. + * + * When read is called, we create a new promise and queue it on the input + * queue. If it is the only element in the queue, we ask the input stream to + * run it immediately. + * Otherwise, the previous item of the queue will run it after it finishes. + * + * This function is expected to throw when the underlying socket has been + * closed. + * + * @returns {Promise<string>} The read string + */ + async read() { + return new Promise((resolve, reject) => { + const tryAsyncWait = () => { + if (this.#inputQueue.length) { + this.#inputStream.asyncWait( + this.#inputQueue.at(0), // next input request + 0, + 0, + Services.tm.currentThread + ); + } + }; + + this.#inputQueue.push({ + onInputStreamReady: () => { + try { + if (!this.#scriptableInputStream.available()) { + // This means EOF, but not closed yet. However, arriving at EOF + // should be an error condition for us, since we are in a socket, + // and EOF should mean peer disconnected. + // If the stream has been closed, this function itself should + // throw. + reject( + new Error("onInputStreamReady called without available bytes.") + ); + return; + } + + // Read our string from input stream. + const str = this.#scriptableInputStream.read( + this.#scriptableInputStream.available() + ); + + // Remove this callback object from queue now that we have read. + this.#inputQueue.shift(); + + // Start waiting for incoming data again if the reading queue is not + // empty. + tryAsyncWait(); + + // Finally resolve the promise. + resolve(str); + } catch (err) { + // E.g., we received a NS_BASE_STREAM_CLOSED because the socket was + // closed. + reject(err); + } + }, + }); + + // Length 1 imples that there is no in-flight asyncWait, so we may + // immediately follow through on this read. + if (this.#inputQueue.length === 1) { + tryAsyncWait(); + } + }); + } + + /** + * Close the streams. + */ + close() { + this.#outputStream.close(); + this.#inputStream.close(); + } +} + +/** + * @typedef Command + * @property {string} commandString The string to send over the control port + * @property {Function} resolve The function to resolve the promise with the + * response we got on the control port + * @property {Function} reject The function to reject the promise associated to + * the command + */ +/** + * The ID of a circuit. + * From control-spec.txt: + * CircuitID = 1*16 IDChar + * IDChar = ALPHA / DIGIT + * Currently, Tor only uses digits, but this may change. + * + * @typedef {string} CircuitID + */ +/** + * The ID of a stream. + * From control-spec.txt: + * CircuitID = 1*16 IDChar + * IDChar = ALPHA / DIGIT + * Currently, Tor only uses digits, but this may change. + * + * @typedef {string} StreamID + */ +/** + * The fingerprint of a node. + * From control-spec.txt: + * Fingerprint = "$" 40*HEXDIG + * However, we do not keep the $ in our structures. + * + * @typedef {string} NodeFingerprint + */ +/** + * @typedef {object} CircuitInfo + * @property {CircuitID} id The ID of a circuit + * @property {NodeFingerprint[]} nodes List of node fingerprints + */ +/** + * @typedef {object} Bridge + * @property {string} transport The transport of the bridge, or vanilla if not + * specified + * @property {string} addr The IP address and port of the bridge + * @property {NodeFingerprint} id The fingerprint of the bridge + * @property {string} args Optional arguments passed to the bridge + */ +/** + * @typedef {object} PTInfo The information about a pluggable transport + * @property {string[]} transports An array with all the transports supported by + * this configuration + * @property {string} type Either socks4, socks5 or exec + * @property {string} [ip] The IP address of the proxy (only for socks4 and + * socks5) + * @property {integer} [port] The port of the proxy (only for socks4 and socks5) + * @property {string} [pathToBinary] Path to the binary that is run (only for + * exec) + * @property {string} [options] Optional options passed to the binary (only for + * exec) + */ +/** + * @typedef {object} SocksListener + * @property {string} [ipcPath] path to a Unix socket to use for an IPC proxy + * @property {string} [host] The host to connect for a TCP proxy + * @property {number} [port] The port number to use for a TCP proxy + */ +/** + * @typedef {object} OnionAuthKeyInfo + * @property {string} address The address of the onion service + * @property {string} typeAndKey Onion service key and type of key, as + * `type:base64-private-key` + * @property {string} Flags Additional flags, such as Permanent + */ +/** + * @callback EventCallback A callback to receive messages from the control + * port. + * @param {string} message The message to handle + */ + +/** + * This is a custom error thrown when we receive an error response over the + * control port. + * + * It includes the command that caused it, the error code and the raw message + * sent by the tor daemon. + */ +class TorProtocolError extends Error { + constructor(command, reply) { + super(`${command} -> ${reply}`); + this.name = "TorProtocolError"; + const info = reply.match(/(?<code>\d{3})(?:\s(?<message>.+))?/); + this.torStatusCode = info.groups.code; + if (info.groups.message) { + this.torMessage = info.groups.message; + } + } +} + +/** + * This class implements a JavaScript API around some of the commands and + * notifications that can be sent and received with tor's control port protocol. + */ +export class TorController { + /** + * The socket to write to the control port. + * + * @type {AsyncSocket} + */ + #socket; + + /** + * Data we received on a read but that was not a complete line (missing a + * final CRLF). We will prepend it to the next read. + * + * @type {string} + */ + #pendingData = ""; + /** + * The lines we received and are still queued for being evaluated. + * + * @type {string[]} + */ + #pendingLines = []; + /** + * The commands that need to be run or receive a response. + * + * NOTE: This must be in the order with the last requested command at the end + * of the queue. + * + * @type {Command[]} + */ + #commandQueue = []; + + /** + * The event handler. + * + * @type {TorEventHandler} + */ + #eventHandler; + + /** + * Connect to a control port over a Unix socket. + * Not available on Windows. + * + * @param {nsIFile} ipcFile The path to the Unix socket to connect to + * @param {TorEventHandler} eventHandler The event handler to use for + * asynchronous notifications + * @returns {TorController} + */ + static fromIpcFile(ipcFile, eventHandler) { + return new TorController(AsyncSocket.fromIpcFile(ipcFile), eventHandler); + } + + /** + * Connect to a control port over a TCP socket. + * + * @param {string} host The hostname to connect to + * @param {number} port The port to connect the to + * @param {TorEventHandler} eventHandler The event handler to use for + * asynchronous notifications + * @returns {TorController} + */ + static fromSocketAddress(host, port, eventHandler) { + return new TorController( + AsyncSocket.fromSocketAddress(host, port), + eventHandler + ); + } + + /** + * Construct the controller and start the message pump. + * The class should not be constructed directly, but through static methods. + * However, this is public because JavaScript does not support private + * constructors. + * + * @private + * @param {AsyncSocket} socket The socket to use + * @param {TorEventHandler} eventHandler The event handler to use for + * asynchronous notifications + */ + constructor(socket, eventHandler) { + this.#socket = socket; + this.#eventHandler = eventHandler; + this.#startMessagePump(); + } + + // Socket and communication handling + + /** + * Return the next line in the queue. If there is not any, block until one is + * read (or until a communication error happens, including the underlying + * socket being closed while it was still waiting for data). + * Any letfovers will be prepended to the next read. + * + * @returns {Promise<string>} A line read over the socket + */ + async #readLine() { + // Keep reading from socket until we have at least a full line to return. + while (!this.#pendingLines.length) { + if (!this.#socket) { + throw new Error( + "Read interrupted because the control socket is not available anymore" + ); + } + // Read data from our socket and split on newline tokens. + // This might still throw when the socket has been closed. + this.#pendingData += await this.#socket.read(); + const lines = this.#pendingData.split("\r\n"); + // The last line will either be empty string, or a partial read of a + // response/event so save it off for the next socket read. + this.#pendingData = lines.pop(); + // Copy remaining full lines to our pendingLines list. + this.#pendingLines = this.#pendingLines.concat(lines); + } + return this.#pendingLines.shift(); + } + + /** + * Blocks until an entire message is ready and returns it. + * This function does a rudimentary parsing of the data only to handle + * multi-line responses. + * + * @returns {Promise<string>} The read message (without the final CRLF) + */ + async #readMessage() { + // Whether we are searching for the end of a multi-line values. + // See control-spec section 3.9. + let handlingMultlineValue = false; + let endOfMessageFound = false; + const message = []; + + do { + const line = await this.#readLine(); + message.push(line); + + if (handlingMultlineValue) { + // look for end of multiline + if (line === ".") { + handlingMultlineValue = false; + } + } else { + // 'Multiline values' are possible. We avoid interrupting one by + // detecting it and waiting for a terminating "." on its own line. + // (See control-spec section 3.9 and + // https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/16990#note_2625464). + // Ensure this is the first line of a new message + // eslint-disable-next-line no-lonely-if + if (message.length === 1 && line.match(/^\d\d\d\+.+?=$/)) { + handlingMultlineValue = true; + } + // Look for end of message (notice the space character at end of the + // regex!). + else if (line.match(/^\d\d\d /)) { + if (message.length === 1) { + endOfMessageFound = true; + } else { + const firstReplyCode = message[0].substring(0, 3); + const lastReplyCode = line.substring(0, 3); + endOfMessageFound = firstReplyCode === lastReplyCode; + } + } + } + } while (!endOfMessageFound); + + // join our lines back together to form one message + return message.join("\r\n"); + } + + /** + * Handles a message that was received as a reply to a command (i.e., all the + * messages that are not async notification messages starting with 650). + * + * @param {string} message The message to handle + */ + #handleCommandReply(message) { + const cmd = this.#commandQueue.shift(); + // We resolve also for messages that are failures for sure. The commands + // should always check the output. + cmd.resolve(message); + + // send next command if one is available + if (this.#commandQueue.length) { + this.#writeNextCommand(); + } + } + + /** + * Read messages on the socket and routed them to a dispatcher until the + * socket is open or some error happens (including the underlying socket being + * closed). + */ + async #startMessagePump() { + try { + // This while is inside the try block because it is very likely that it + // will be broken by a NS_BASE_STREAM_CLOSED exception, rather than by its + // condition becoming false. + while (this.#socket) { + const message = await this.#readMessage(); + try { + if (message.startsWith("650")) { + this.#handleNotification(message); + } else { + this.#handleCommandReply(message); + } + } catch (err) { + // E.g., if a notification handler fails. Without this internal + // try/catch we risk of closing the connection while not actually + // needed. + logger.error("Caught an exception while handling a message", err); + } + } + } catch (err) { + logger.debug("Caught an exception, closing the control port", err); + try { + this.#close(err); + } catch (ec) { + logger.error( + "Caught another error while closing the control socket.", + ec + ); + } + } + } + + /** + * Start running the first available command in the queue. + * To be called when the previous one has finished running. + * This makes sure to avoid conflicts when using the control port. + */ + #writeNextCommand() { + const cmd = this.#commandQueue[0]; + this.#socket.write(`${cmd.commandString}\r\n`).catch(cmd.reject); + } + + /** + * Send a command over the control port. + * This function returns only when it receives a complete message over the + * control port. This class does some rudimentary parsing to check wheter it + * needs to handle multi-line messages. + * + * @param {string} commandString The command to send + * @returns {Promise<string>} The message sent by the control port. The return + * value should never be an empty string (even though it will not include the + * final CRLF). + */ + async #sendCommand(commandString) { + if (!this.#socket) { + throw new Error("ControlSocket not open"); + } + + // this promise is resolved either in #handleCommandReply, or in + // #startMessagePump (on stream error) + return new Promise((resolve, reject) => { + const command = { + commandString, + resolve, + reject, + }; + this.#commandQueue.push(command); + if (this.#commandQueue.length === 1) { + this.#writeNextCommand(); + } + }); + } + + /** + * Send a simple command whose response is expected to be simply a "250 OK". + * The function will not return a reply, but will throw if an unexpected one + * is received. + * + * @param {string} command The command to send + */ + async #sendCommandSimple(command) { + const reply = await this.#sendCommand(command); + if (!/^250 OK\s*$/i.test(reply)) { + throw new TorProtocolError(command, reply); + } + } + + /** + * Reject all the commands that are still in queue and close the control + * socket. + * + * @param {object?} reason An error object used to pass a more specific + * rejection reason to the commands that are still queued. + */ + #close(reason) { + logger.info("Closing the control port", reason); + const error = new Error( + "The control socket has been closed" + + (reason ? `: ${reason.message}` : "") + ); + const commands = this.#commandQueue; + this.#commandQueue = []; + for (const cmd of commands) { + cmd.reject(error); + } + try { + this.#socket?.close(); + } finally { + this.#socket = null; + } + } + + /** + * Closes the socket connected to the control port. + */ + close() { + this.#close(null); + } + + /** + * Tells whether the underlying socket is still open. + * + * @returns {boolean} + */ + get isOpen() { + return !!this.#socket; + } + + /** + * Authenticate to the tor daemon. + * Notice that a failure in the authentication makes the connection close. + * + * @param {Uint8Array} password The password for the control port, as an array + * of bytes + */ + async authenticate(password) { + const passwordString = Array.from(password ?? [], b => + b.toString(16).padStart(2, "0") + ).join(""); + await this.#sendCommandSimple(`authenticate ${passwordString}`); + } + + // Information + + /** + * Sends a GETINFO for a single key. + * control-spec.txt says "one ReplyLine is sent for each requested value", so, + * we expect to receive only one line starting with `250-keyword=`, or one + * line starting with `250+keyword=` (in which case we will match until a + * period). + * This function could be possibly extended to handle several keys at once, + * but we currently do not need this functionality, so we preferred keeping + * the function simpler. + * + * @param {string} key The key to get value for + * @returns {Promise<string>} The string we received (only the value, without + * the key). We do not do any additional parsing on it + */ + async #getInfo(key) { + this.#expectString(key); + const cmd = `GETINFO ${key}`; + const reply = await this.#sendCommand(cmd); + const match = + reply.match(/^250-([^=]+)=(.*)$/m) || + reply.match(/^250\+([^=]+)=\r?\n(.*?)\r?\n^\.\r?\n^250 OK\s*$/ms); + if (!match || match[1] !== key) { + throw new TorProtocolError(cmd, reply); + } + return match[2]; + } + + /** + * Ask Tor its bootstrap phase. + * + * @returns {object} An object with the bootstrap information received from + * Tor. Its keys might vary, depending on the input + */ + async getBootstrapPhase() { + return this.#parseBootstrapStatus( + await this.#getInfo("status/bootstrap-phase") + ); + } + + /** + * Get the IPv4 and optionally IPv6 addresses of an onion router. + * + * @param {NodeFingerprint} id The fingerprint of the node the caller is + * interested in + * @returns {string[]} The IP addresses (one IPv4 and optionally an IPv6) + */ + async getNodeAddresses(id) { + this.#expectString(id, "id"); + const reply = await this.#getInfo(`ns/id/${id}`); + // See dir-spec.txt. + // r nickname identity digest publication IP OrPort DirPort + const rLine = reply.match(/^r\s+(.*)$/m); + const v4 = rLine ? rLine[1].split(/\s+/) : []; + // Tor should already reply with a 552 when a relay cannot be found. + // Also, publication is a date with a space inside, so it is counted twice. + if (!rLine || v4.length !== 8) { + throw new Error(`Received an invalid node information: ${reply}`); + } + const addresses = [v4[5]]; + // a address:port + // dir-spec.txt also states only the first one should be taken + const v6 = reply.match(/^a\s+\[([0-9a-fA-F:]+)\]:\d{1,5}$/m); + if (v6) { + addresses.push(v6[1]); + } + return addresses; + } + + /** + * Maps IP addresses to 2-letter country codes, or ?? if unknown. + * + * @param {string} ip The IP address to look for + * @returns {Promise<string>} A promise with the country code. If unknown, the + * promise is resolved with "??". It is rejected only when the underlying + * GETINFO command fails or if an exception is thrown + */ + async getIPCountry(ip) { + this.#expectString(ip, "ip"); + return this.#getInfo(`ip-to-country/${ip}`); + } + + /** + * Ask tor which ports it is listening to for SOCKS connections. + * + * @returns {Promise<SocksListener[]>} An array of addresses. It might be + * empty (e.g., when DisableNetwork is set) + */ + async getSocksListeners() { + const listeners = await this.#getInfo("net/listeners/socks"); + return Array.from( + listeners.matchAll(/\s*("(?:[^"\\]|\\.)*"|\S+)\s*/g), + m => { + const listener = TorParsers.unescapeString(m[1]); + if (listener.startsWith("unix:/")) { + return { ipcPath: listener.substring(5) }; + } + const idx = listener.lastIndexOf(":"); + const host = listener.substring(0, idx); + const port = parseInt(listener.substring(idx + 1)); + if (isNaN(port) || port <= 0 || port > 65535 || !host || !port) { + throw new Error(`Could not parse the SOCKS listener ${listener}.`); + } + return { host, port }; + } + ); + } + + /** + * Ask Tor a list of circuits. + * + * @returns {CircuitInfo[]} An array with a string for each line + */ + async getCircuits() { + const circuits = await this.#getInfo("circuit-status"); + return circuits + .split(/\r?\n/) + .map(this.#parseCircBuilt.bind(this)) + .filter(circ => circ); + } + + // Configuration + + /** + * Sends a GETCONF for a single key. + * The function could be easily generalized to get multiple keys at once, but + * we do not need this functionality, at the moment. + * + * @param {string} key The keys to get info for + * @returns {Promise<string[]>} The values obtained from the control port. + * The key is removed, and the values unescaped, but they are not parsed. + * The array might contain an empty string, which means that the default value + * is used + */ + async #getConf(key) { + this.#expectString(key, "key"); + // GETCONF expects a `keyword`, which should be only alpha characters, + // according to the definition in control-port.txt. But as a matter of fact, + // several configuration keys include numbers (e.g., Socks4Proxy). So, we + // accept also numbers in this regular expression. One of the reason to + // sanitize the input is that we then use it to create a regular expression. + // Sadly, JavaScript does not provide a function to escape/quote a string + // for inclusion in a regex. Should we remove this limitation, we should + // also implement a regex sanitizer, or switch to another pattern, like + // `([^=])` and then filter on the keyword. + if (!/^[A-Za-z0-9]+$/.test(key)) { + throw new Error("The key can be composed only of letters and numbers."); + } + const cmd = `GETCONF ${key}`; + const reply = await this.#sendCommand(cmd); + // From control-spec.txt: a 'default' value semantically different from an + // empty string will not have an equal sign, just `250 $key`. + const defaultRe = new RegExp(`^250[-\\s]${key}$`, "gim"); + if (reply.match(defaultRe)) { + return []; + } + const re = new RegExp(`^250[-\\s]${key}=(.*)$`, "gim"); + const values = Array.from(reply.matchAll(re), m => + TorParsers.unescapeString(m[1]) + ); + if (!values.length) { + throw new TorProtocolError(cmd, reply); + } + return values; + } + + /** + * Get the bridges Tor has been configured with. + * + * @returns {Bridge[]} The configured bridges + */ + async getBridges() { + let missingId = false; + const bridges = (await this.#getConf("BRIDGE")).map(line => { + const info = TorParsers.parseBridgeLine(line); + if (!info.id) { + missingId = true; + } + return info; + }); + + // tor-browser#42541: bridge lines are allowed not to have a fingerprint. + // If such a bridge is in use, we will fail to associate it to the circuits, + // and the circuit display will not be shown. + // Tor provides a couple of GETINFO commands we can try to use to get more + // data about bridges, in particular GETINFO ns/purpose/bridge. + // While it tells us the bridge's IP (as configured by the user, which might + // be different from the real one with some PTs such as Snowflake), it does + // not tell the pluggable transport. + // Therefore, we need to start from the configured bridge lines, and if we + // detect that a bridge does not have a fingerprint, we try to associate one + // through its IP address and port. + // However, users can set them directly, therefore we might end up setting + // a fingerprint to the wrong line (e.g., if the IP address is reused). + // Also, we are not sure about when the data of ns/purpose/bridge is + // populated. + // Usually, we are interested only in the data of currently active bridges + // for the circuit display. So, as a matter of fact, we expect to have + // entries and to expose only the correct and working data in the frontend. + if (missingId) { + // See https://spec.torproject.org/dir-spec/consensus-formats.html. + // r <name> <identity> <digest> <date> <time> <address> <orport> <dirport> + const info = (await this.#getInfo("ns/purpose/bridge")).matchAll( + /^r\s+\S+\s+(?<identity>\S+)\s+\S+\s+\S+\s+\S+\s+(?<address>\S+)\s+(?<orport>\d+)/gm + ); + const b64ToHex = b64 => { + let hex = ""; + const raw = atob(b64); + for (let i = 0; i < raw.length; i++) { + hex += raw.charCodeAt(i).toString(16).toUpperCase().padStart(2, "0"); + } + return hex; + }; + const knownBridges = new Map( + Array.from(info, m => [ + `${m.groups.address}:${m.groups.orport}`, + b64ToHex(m.groups.identity), + ]) + ); + for (const b of bridges) { + if (!b.id) { + // We expect the addresses of these lines to be only IPv4, therefore + // we do not check for brackets, even though they might be matched by + // our regex. + b.id = knownBridges.get(b.addr) ?? ""; + } + } + } + + return bridges; + } + + /** + * Get the configured pluggable transports. + * + * @returns {PTInfo[]} An array with the info of all the configured pluggable + * transports. + */ + async getPluggableTransports() { + return (await this.#getConf("ClientTransportPlugin")).map(ptLine => { + // man 1 tor: ClientTransportPlugin transport socks4|socks5 IP:PORT + const socksLine = ptLine.match( + /(\S+)\s+(socks[45])\s+([\d.]{7,15}|\[[\da-fA-F:]+\]):(\d{1,5})/i + ); + // man 1 tor: transport exec path-to-binary [options] + const execLine = ptLine.match( + /(\S+)\s+(exec)\s+("(?:[^"\\]|\\.)*"|\S+)\s*(.*)/i + ); + if (socksLine) { + return { + transports: socksLine[1].split(","), + type: socksLine[2].toLowerCase(), + ip: socksLine[3], + port: parseInt(socksLine[4], 10), + }; + } else if (execLine) { + return { + transports: execLine[1].split(","), + type: execLine[2].toLowerCase(), + pathToBinary: TorParsers.unescapeString(execLine[3]), + options: execLine[4], + }; + } + throw new Error( + `Received an invalid ClientTransportPlugin line: ${ptLine}` + ); + }); + } + + /** + * Send multiple configuration values to tor. + * + * @param {Array} values The values to set. It should be an array of + * [key, value] pairs to pass to SETCONF. Keys can be repeated, and array + * values will be automatically unrolled. + */ + async setConf(values) { + // NOTE: This is an async method. It must ensure that sequential calls to + // this method do not race against each other. I.e. the last call to this + // method must always be the last in #commandQueue. Otherwise a delayed + // earlier call could overwrite the configuration of a later call. + const args = values + .flatMap(([key, value]) => { + if (value === undefined || value === null) { + return [key]; + } + if (Array.isArray(value)) { + return value.length + ? value.map(v => `${key}=${TorParsers.escapeString(v)}`) + : key; + } else if (typeof value === "string" || value instanceof String) { + return `${key}=${TorParsers.escapeString(value)}`; + } else if (typeof value === "boolean") { + return `${key}=${value ? "1" : "0"}`; + } else if (typeof value === "number") { + return `${key}=${value}`; + } + throw new Error(`Unsupported type ${typeof value} (key ${key})`); + }) + .join(" "); + await this.#sendCommandSimple(`SETCONF ${args}`); + } + + /** + * Enable or disable the network. + * Notice: switching from network disabled to network enabled will trigger a + * bootstrap on C tor! (Or stop the current one). + * + * @param {boolean} enabled Tell whether the network should be enabled + */ + async setNetworkEnabled(enabled) { + await this.setConf([["DisableNetwork", !enabled]]); + } + + /** + * Ask Tor to write out its config options into its torrc. + */ + async flushSettings() { + await this.#sendCommandSimple("SAVECONF"); + } + + // Onion service authentication + + /** + * Sends a ONION_CLIENT_AUTH_VIEW command to retrieve the list of private + * keys. + * + * @returns {OnionAuthKeyInfo[]} + */ + async onionAuthViewKeys() { + const cmd = "onion_client_auth_view"; + const message = await this.#sendCommand(cmd); + // Either `250-CLIENT`, or `250 OK` if no keys are available. + if (!message.startsWith("250")) { + throw new TorProtocolError(cmd, message); + } + const re = + /^250-CLIENT\s+(?<HSAddress>[A-Za-z2-7]+)\s+(?<KeyType>[^:]+):(?<PrivateKeyBlob>\S+)(?:\s(?<other>.+))?$/gim; + return Array.from(message.matchAll(re), match => { + // TODO: Change the consumer and make the fields more consistent with what + // we get (e.g., separate key and type, and use a boolen for permanent). + const info = { + address: match.groups.HSAddress, + keyType: match.groups.KeyType, + keyBlob: match.groups.PrivateKeyBlob, + flags: [], + }; + const maybeFlags = match.groups.other?.match(/Flags=(\S+)/); + if (maybeFlags) { + info.flags = maybeFlags[1].split(","); + } + return info; + }); + } + + /** + * Sends an ONION_CLIENT_AUTH_ADD command to add a private key to the Tor + * configuration. + * + * @param {string} address The address of the onion service + * @param {string} b64PrivateKey The private key of the service, in base64 + * @param {boolean} isPermanent Tell whether the key should be saved forever + */ + async onionAuthAdd(address, b64PrivateKey, isPermanent) { + this.#expectString(address, "address"); + this.#expectString(b64PrivateKey, "b64PrivateKey"); + const keyType = "x25519"; + let cmd = `onion_client_auth_add ${address} ${keyType}:${b64PrivateKey}`; + if (isPermanent) { + cmd += " Flags=Permanent"; + } + const reply = await this.#sendCommand(cmd); + const status = reply.substring(0, 3); + if (status !== "250" && status !== "251" && status !== "252") { + throw new TorProtocolError(cmd, reply); + } + } + + /** + * Sends an ONION_CLIENT_AUTH_REMOVE command to remove a private key from the + * Tor configuration. + * + * @param {string} address The address of the onion service + */ + async onionAuthRemove(address) { + this.#expectString(address, "address"); + const cmd = `onion_client_auth_remove ${address}`; + const reply = await this.#sendCommand(cmd); + const status = reply.substring(0, 3); + if (status !== "250" && status !== "251") { + throw new TorProtocolError(cmd, reply); + } + } + + // Daemon ownership + + /** + * Instructs Tor to shut down when this control connection is closed. + * If multiple connection sends this request, Tor will shut dwon when any of + * them is closed. + */ + async takeOwnership() { + await this.#sendCommandSimple("TAKEOWNERSHIP"); + } + + /** + * The __OwningControllerProcess argument can be used to make Tor periodically + * check if a certain PID is still present, or terminate itself otherwise. + * When switching to the ownership tied to the control port, this mechanism + * should be stopped by calling this function. + */ + async resetOwningControllerProcess() { + await this.#sendCommandSimple("RESETCONF __OwningControllerProcess"); + } + + // Signals + + /** + * Ask Tor to swtich to new circuits and clear the DNS cache. + */ + async newnym() { + await this.#sendCommandSimple("SIGNAL NEWNYM"); + } + + // Events monitoring + + /** + * Enable receiving certain events. + * As per control-spec.txt, any events turned on in previous calls but not + * included in this one will be turned off. + * + * @param {string[]} types The events to enable. If empty, no events will be + * watched. + * @returns {Promise<void>} + */ + setEvents(types) { + if (!types.every(t => typeof t === "string" || t instanceof String)) { + throw new Error("Event types must be strings"); + } + return this.#sendCommandSimple("SETEVENTS " + types.join(" ")); + } + + /** + * Parse an asynchronous event and pass the data to the relative handler. + * Only single-line messages are currently supported. + * + * @param {string} message The message received on the control port. It should + * starts with `"650" SP`. + */ + #handleNotification(message) { + if (!this.#eventHandler) { + return; + } + const data = message.match(/^650\s+(?<type>\S+)\s*(?<data>.*)?/); + if (!data) { + return; + } + switch (data.groups.type) { + case "STATUS_CLIENT": + let status; + try { + status = this.#parseBootstrapStatus(data.groups.data); + } catch (e) { + // Probably, a non bootstrap client status + logger.debug(`Failed to parse STATUS_CLIENT: ${data.groups.data}`, e); + break; + } + this.#eventHandler.onBootstrapStatus(status); + break; + case "CIRC": + const maybeCircuit = this.#parseCircBuilt(data.groups.data); + const closedEvent = /^(?<ID>[a-zA-Z0-9]{1,16})\sCLOSED/.exec( + data.groups.data + ); + if (maybeCircuit) { + this.#eventHandler.onCircuitBuilt( + maybeCircuit.id, + maybeCircuit.nodes + ); + } else if (closedEvent) { + this.#eventHandler.onCircuitClosed(closedEvent.groups.ID); + } + break; + case "STREAM": + const sentConnectEvent = + /^(?<StreamID>[a-zA-Z0-9]{1,16})\sSENTCONNECT\s(?<CircuitID>[a-zA-Z0-9]{1,16})/.exec( + data.groups.data + ); + if (sentConnectEvent) { + const credentials = this.#parseCredentials(data.groups.data); + this.#eventHandler.onStreamSentConnect( + sentConnectEvent.groups.StreamID, + sentConnectEvent.groups.CircuitID, + credentials?.username ?? null, + credentials?.password ?? null + ); + } + break; + case "NOTICE": + case "WARN": + case "ERR": + this.#eventHandler.onLogMessage(data.groups.type, data.groups.data); + break; + } + } + + // Parsers + + /** + * Parse a bootstrap status line. + * + * @param {string} line The line to parse, without the command/notification + * prefix + * @returns {object} An object with the bootstrap information received from + * Tor. Its keys might vary, depending on the input + */ + #parseBootstrapStatus(line) { + const match = line.match(/^(NOTICE|WARN) BOOTSTRAP\s*(.*)/); + if (!match) { + throw Error( + `Received an invalid response for the bootstrap phase: ${line}` + ); + } + const status = { + // Type is actually StatusSeverity in the specifications. + TYPE: match[1], + ...this.#getKeyValues(match[2]), + }; + if (status.PROGRESS !== undefined) { + status.PROGRESS = parseInt(status.PROGRESS, 10); + } + if (status.COUNT !== undefined) { + status.COUNT = parseInt(status.COUNT, 10); + } + return status; + } + + /** + * Parse a CIRC BUILT event or a GETINFO circuit-status. + * + * @param {string} line The line to parse + * @returns {CircuitInfo?} The ID and nodes of the circuit, or null if the + * parsing failed. + */ + #parseCircBuilt(line) { + const builtEvent = + /^(?<ID>[a-zA-Z0-9]{1,16})\sBUILT\s(?<Path>(,?\$([0-9a-fA-F]{40})(?:~[a-zA-Z0-9]{1,19})?)+)/.exec( + line + ); + if (!builtEvent) { + return null; + } + const fp = /\$([0-9a-fA-F]{40})/g; + const nodes = Array.from(builtEvent.groups.Path.matchAll(fp), g => + g[1].toUpperCase() + ); + // In some cases, we might already receive SOCKS credentials in the + // line. However, this might be a problem with Onion services: we get + // also a 4-hop circuit that we likely do not want to show to the + // user, especially because it is used only temporarily, and it would + // need a technical explaination. + // So we do not try to extract them for now. Otherwise, we could do + // const credentials = this.#parseCredentials(line); + return { id: builtEvent.groups.ID, nodes }; + } + + /** + * Check if a STREAM or CIRC response line contains SOCKS_USERNAME and + * SOCKS_PASSWORD. + * + * @param {string} line The circ or stream line to check + * @returns {object?} The credentials, or null if not found + */ + #parseCredentials(line) { + const username = /SOCKS_USERNAME=("(?:[^"\\]|\\.)*")/.exec(line); + const password = /SOCKS_PASSWORD=("(?:[^"\\]|\\.)*")/.exec(line); + return username && password + ? { + username: TorParsers.unescapeString(username[1]), + password: TorParsers.unescapeString(password[1]), + } + : null; + } + + /** + * Return an object with all the matches that are in the form `key="value"` or + * `key=value`. The values will be unescaped, but no additional parsing will + * be done (e.g., numbers will be returned as strings). + * If keys are repeated, only the last one will be taken. + * + * @param {string} str The string to match tokens in + * @returns {object} An object with all the various tokens. If none is found, + * an empty object is returned. + */ + #getKeyValues(str) { + return Object.fromEntries( + Array.from( + str.matchAll(/\s*([^=]+)=("(?:[^"\\]|\\.)*"|\S+)\s*/g) || [], + pair => [pair[1], TorParsers.unescapeString(pair[2])] + ) + ); + } + + // Other helpers + + /** + * Throw an exception when value is not a string. + * + * @param {any} value The value to check + * @param {string} name The name of the `value` argument + */ + #expectString(value, name) { + if (typeof value !== "string" && !(value instanceof String)) { + throw new Error(`The ${name} argument is expected to be a string.`); + } + } +} + +/** + * @typedef {object} TorEventHandler + * The event handler interface. + * The controller owner can implement this methods to receive asynchronous + * notifications from the controller. + * + * @property {OnBootstrapStatus} onBootstrapStatus Called when a bootstrap + * status is received (i.e., a STATUS_CLIENT event with a BOOTSTRAP action) + * @property {OnLogMessage} onLogMessage Called when a log message is received + * (i.e., a NOTICE, WARN or ERR notification) + * @property {OnCircuitBuilt} onCircuitBuilt Called when a circuit is built + * (i.e., a CIRC event with a BUILT status) + * @property {OnCircuitClosed} onCircuitClosed Called when a circuit is closed + * (i.e., a CIRC event with a CLOSED status) + * @property {OnStreamSentConnect} onStreamSentConnect Called when a stream sent + * a connect cell along a circuit (i.e., a STREAM event with a SENTCONNECT + * status) + */ +/** + * @callback OnBootstrapStatus + * + * @param {object} status An object with the bootstrap information. Its keys + * depend on what the arguments sent by the tor daemon + */ +/** + * @callback OnLogMessage + * + * @param {string} type The type of message (NOTICE, WARNING, ERR, etc...) + * @param {string} message The actual log message + */ +/** + * @callback OnCircuitBuilt + * + * @param {CircuitID} id The id of the circuit that has been built + * @param {NodeFingerprint[]} nodes The onion routers composing the circuit + */ +/** + * @callback OnCircuitClosed + * + * @param {CircuitID} id The id of the circuit that has been closed + */ +/** + * @callback OnStreamSentConnect + * + * @param {StreamID} streamId The id of the stream that switched to the succeeded + * state + * @param {CircuitID} circuitId The id of the circuit the stream is using + * @param {string?} username The SOCKS username associated to the stream, or + * null if not available + * @param {string?} username The SOCKS password associated to the stream, or + * null if not available + */ diff --git a/toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs b/toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..323f0a33e23b89cffab0a7603a2c274d0a66e6fe --- /dev/null +++ b/toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs @@ -0,0 +1,728 @@ +/** + * A component for Tor Browser that puts requests from different first party + * domains on separate Tor circuits. + */ + +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; +import { + clearInterval, + setInterval, +} from "resource://gre/modules/Timer.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", +}); + +XPCOMUtils.defineLazyServiceGetters(lazy, { + ProtocolProxyService: [ + "@mozilla.org/network/protocol-proxy-service;1", + "nsIProtocolProxyService", + ], +}); + +const logger = console.createInstance({ + prefix: "TorDomainIsolator", + maxLogLevelPref: "browser.tordomainisolator.loglevel", +}); + +// The string to use instead of the domain when it is not known. +const CATCHALL_DOMAIN = "--unknown--"; + +// The maximum lifetime for the catch-all circuit in milliseconds. +// When the catch-all circuit is needed, we check if more than this amount of +// time has passed since we last changed it nonce, and in case we change it +// again. +const CATCHALL_MAX_LIFETIME = 600_000; + +// The preference to observe, to know whether isolation should be enabled or +// disabled. +const NON_TOR_PROXY_PREF = "extensions.torbutton.use_nontor_proxy"; + +// The topic of new identity, to observe to cleanup all the nonces. +const NEW_IDENTITY_TOPIC = "new-identity-requested"; + +// The topic on which we broacast circuit change notifications. +const TOR_CIRCUIT_TOPIC = "TorCircuitChange"; + +// We have an interval to delete circuits that are not reclaimed by any browser. +const CLEAR_TIMEOUT = 600_000; + +/** + * @typedef {string} CircuitId A string that we use to identify a circuit. + * Currently, it is a string that combines SOCKS credentials, to make it easier + * to use as a map key. + * It is not related to Tor's CircuitIDs. + */ +/** + * @typedef {number} BrowserId + */ +/** + * @typedef {NodeData[]} CircuitData The data about the nodes, ordered from + * guard (or bridge) to exit. + */ +/** + * @typedef BrowserCircuits Circuits related to a certain combination of + * isolators (first-party domain and user context ID, currently). + * @property {CircuitId} current The id of the last known circuit that has been + * used to fetch data for the isolated context. + * @property {CircuitId?} pending The id of the last used circuit for this + * isolation context. We might or might not know data about it, yet. But if we + * know it, we should move this id into current. + */ + +/** + * This class implements circuit-isolation based on first-party domains and user + * context IDs. + * It takes for granted the tor daemon is configured with IsolateSOCKSAuth (or + * an equivalent option for other backends), so that it can hijack the proxy + * configuration to update its username and password. + * + * This class also collects the data that will be used by the circuit display. + */ +class TorDomainIsolatorImpl { + /** + * A mutable map that records what nonce we are using for each domain. + * + * @type {Map<string, string>} + */ + #noncesForDomains = new Map(); + + /** + * A mutable map that records what nonce we are using for each tab container. + * + * @type {Map<string, string>} + */ + #noncesForUserContextId = new Map(); + + /** + * Tell whether we use SOCKS auth for isolation or not. + * + * @type {boolean} + */ + #isolationEnabled = true; + + /** + * Specifies when the current catch-all circuit was first used. + * + * @type {integer} + */ + #catchallDirtySince = Date.now(); + + /** + * A map that associates circuit ids to the circuit information. + * + * @type {Map<CircuitId, CircuitData>} + */ + #knownCircuits = new Map(); + + /** + * A map that associates a certain browser to all the circuits it used or it + * is going to use. + * The circuits are keyed on the SOCKS username, which we take for granted + * being a combination of the first-party domain and the user context id. + * + * @type {Map<BrowserId, Map<string, BrowserCircuits>>} + */ + #browsers = new Map(); + + /** + * The handle of the interval we use to cleanup old circuit data. + * + * @type {number?} + */ + #cleanupIntervalId = null; + + /** + * Initialize the domain isolator. + * This function will setup the proxy filter that injects the credentials, + * register some observers, and setup the cleaning interval. + */ + init() { + logger.info("Setup circuit isolation by domain and user context"); + + if (Services.prefs.getBoolPref(NON_TOR_PROXY_PREF, false)) { + this.#isolationEnabled = false; + logger.info( + `The domain isolation will not be enabled because of ${NON_TOR_PROXY_PREF}.` + ); + } + this.#setupProxyFilter(); + + Services.prefs.addObserver(NON_TOR_PROXY_PREF, this); + Services.obs.addObserver(this, NEW_IDENTITY_TOPIC); + Services.obs.addObserver( + this, + lazy.TorProviderTopics.CircuitCredentialsMatched + ); + + this.#cleanupIntervalId = setInterval( + this.#clearKnownCircuits.bind(this), + CLEAR_TIMEOUT + ); + } + + /** + * Removes the observers added in the initialization and stops the cleaning + * interval. + */ + uninit() { + Services.prefs.removeObserver(NON_TOR_PROXY_PREF, this); + Services.obs.removeObserver(this, NEW_IDENTITY_TOPIC); + Services.obs.removeObserver( + this, + lazy.TorProviderTopics.CircuitCredentialsMatched + ); + clearInterval(this.#cleanupIntervalId); + this.#cleanupIntervalId = null; + this.clearIsolation(); + } + + enable() { + logger.trace("Domain isolation enabled"); + this.#isolationEnabled = true; + } + + disable() { + logger.trace("Domain isolation disabled"); + this.#isolationEnabled = false; + } + + /** + * Get the last circuit used in a certain browser. + * The returned data is created when the circuit is first seen, therefore it + * could be stale (i.e., the circuit might not be available anymore). + * + * @param {MozBrowser} browser The browser to get data for + * @param {string} domain The first party domain we want to get the circuit + * for + * @param {number} userContextId The user context domain we want to get the + * circuit for + * @returns {NodeData[]} The node data, or an empty array if we do not have + * data for the requested key. + */ + getCircuit(browser, domain, userContextId) { + const username = this.#makeUsername(domain, userContextId); + const circuits = this.#browsers.get(browser.browserId)?.get(username); + // This is the only place where circuit data can go out, so the only place + // where it makes a difference to check whether the pending circuit is still + // pending, or it has actually got data. + const pending = this.#knownCircuits.get(circuits?.pending); + if (pending?.length) { + circuits.current = circuits.pending; + circuits.pending = null; + return pending; + } + // TODO: At this point we already know if we expect a circuit change for + // this key: (circuit?.pending && !pending). However, we do not consume this + // data yet in the frontend, so do not send it for now. + return this.#knownCircuits.get(circuits?.current) ?? []; + } + + /** + * Create a new nonce for the FP domain of the selected browser and reload the + * tab with a new circuit. + * + * @param {object} browser The browser we want to change the circuit for. + */ + newCircuitForBrowser(browser) { + const firstPartyDomain = getDomainForBrowser(browser); + this.newCircuitForDomain(firstPartyDomain); + const { username, password } = this.#getSocksProxyCredentials( + firstPartyDomain, + browser.contentPrincipal.originAttributes.userContextId + ); + this.#trackBrowser(browser, username, password); + browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); + } + + /** + * Clear the isolation state cache, forcing new circuits to be used for all + * subsequent requests. + */ + clearIsolation() { + logger.trace("Clearing isolation nonces."); + + // Per-domain and per contextId nonces are stored in maps, so simply clear + // them. + // Notice that the catch-all circuit is included in #noncesForDomains, so we + // are implicilty cleaning it. Should this change, we should change its + // nonce explicitly here. + this.#noncesForDomains.clear(); + this.#noncesForUserContextId.clear(); + this.#catchallDirtySince = Date.now(); + + this.#knownCircuits.clear(); + this.#browsers.clear(); + } + + async observe(subject, topic, data) { + if (topic === "nsPref:changed" && data === NON_TOR_PROXY_PREF) { + if (Services.prefs.getBoolPref(NON_TOR_PROXY_PREF)) { + this.disable(); + } else { + this.enable(); + } + } else if (topic === NEW_IDENTITY_TOPIC) { + logger.info( + "New identity has been requested, clearing isolation tokens." + ); + this.clearIsolation(); + try { + const provider = await lazy.TorProviderBuilder.build(); + await provider.newnym(); + } catch (e) { + logger.error("Could not send the newnym command", e); + // TODO: What UX to use here? See tor-browser#41708 + } + } else if (topic === lazy.TorProviderTopics.CircuitCredentialsMatched) { + const { username, password, circuit } = subject.wrappedJSObject; + this.#updateCircuit(username, password, circuit); + } + } + + /** + * Setup a filter that for every HTTPChannel. + */ + #setupProxyFilter() { + lazy.ProtocolProxyService.registerChannelFilter( + { + applyFilter: (aChannel, aProxy, aCallback) => { + aCallback.onProxyFilterResult(this.#proxyFilter(aChannel, aProxy)); + }, + }, + 0 + ); + } + + /** + * Replaces the default SOCKS proxy with one that authenticates to the SOCKS + * server (the tor client process) with a username (the first party domain and + * userContextId) and a nonce password. + * Tor provides a separate circuit for each username+password combination. + * + * @param {nsIChannel} aChannel The channel we are setting the proxy for + * @param {nsIProxyInfo} aProxy The original proxy + * @returns {nsIProxyInfo} The new proxy to use + */ + #proxyFilter(aChannel, aProxy) { + if (!this.#isolationEnabled) { + return aProxy; + } + try { + const channel = aChannel.QueryInterface(Ci.nsIChannel); + let firstPartyDomain = channel.loadInfo.originAttributes.firstPartyDomain; + const userContextId = channel.loadInfo.originAttributes.userContextId; + const scheme = channel.loadInfo.loadingPrincipal?.URI?.scheme; + const filePath = channel.loadInfo.loadingPrincipal?.URI?.filePath; + if ( + (scheme === "about" && filePath === "reader") || + (scheme === "moz-extension" && filePath === "/readerview.html") + ) { + try { + const searchParams = new URLSearchParams( + channel.loadInfo.loadingPrincipal.URI.query + ); + if (searchParams.has("url")) { + firstPartyDomain = Services.eTLD.getSchemelessSite( + Services.io.newURI(searchParams.get("url")) + ); + } + } catch (e) { + logger.error("Failed to get first party domain for reader view", e); + } + } + if (!firstPartyDomain) { + firstPartyDomain = CATCHALL_DOMAIN; + if (Date.now() - this.#catchallDirtySince > CATCHALL_MAX_LIFETIME) { + logger.info( + "tor catchall circuit has reached its maximum lifetime. Rotating." + ); + this.newCircuitForDomain(CATCHALL_DOMAIN); + } + } + const { username, password } = this.#getSocksProxyCredentials( + firstPartyDomain, + userContextId + ); + const browser = this.#getBrowserForChannel(channel); + if (browser) { + this.#trackBrowser(browser, username, password); + } + logger.debug(`Requested ${channel.URI.spec} via ${username}:${password}`); + const proxy = aProxy.QueryInterface(Ci.nsIProxyInfo); + return lazy.ProtocolProxyService.newProxyInfoWithAuth( + "socks", + proxy.host, + proxy.port, + username, + password, + "", // aProxyAuthorizationHeader + "", // aConnectionIsolationKey + proxy.flags, + proxy.failoverTimeout, + proxy.failoverProxy + ); + } catch (e) { + logger.error("Error while setting a new proxy", e); + return null; + } + } + + /** + * Return the credentials to use as username and password for the SOCKS proxy, + * given a certain domain and userContextId. + * A new random password will be created if not available yet. + * + * @param {string} firstPartyDomain The first party domain associated to the + * requests + * @param {number} userContextId The context ID associated to the request + * @returns {object} The credentials + */ + #getSocksProxyCredentials(firstPartyDomain, userContextId) { + if (!this.#noncesForDomains.has(firstPartyDomain)) { + const nonce = this.#nonce(); + logger.info(`New nonce for first party ${firstPartyDomain}: ${nonce}`); + this.#noncesForDomains.set(firstPartyDomain, nonce); + } + if (!this.#noncesForUserContextId.has(userContextId)) { + const nonce = this.#nonce(); + logger.info(`New nonce for userContextId ${userContextId}: ${nonce}`); + this.#noncesForUserContextId.set(userContextId, nonce); + } + // TODO: How to properly handle the user-context? Should we use + // (domain, userContextId) pairs, instead of concatenating nonces? + return { + username: this.#makeUsername(firstPartyDomain, userContextId), + password: + this.#noncesForDomains.get(firstPartyDomain) + + this.#noncesForUserContextId.get(userContextId), + }; + } + + /** + * Combine the needed data into a username for the proxy. + * + * @param {string} domain The first-party domain associated to the request + * @param {integer} userContextId The userContextId associated to the request + * @returns {string} The username to be passed to the SOCKS proxy + */ + #makeUsername(domain, userContextId) { + if (!domain) { + domain = CATCHALL_DOMAIN; + } + return `${domain}:${userContextId}`; + } + + /** + * Combine SOCKS username and password into a string to use as ID. + * + * @param {string} username The SOCKS username + * @param {string} password The SOCKS password + * @returns {CircuitId} A string that combines username and password and can + * be used for map lookups. + */ + #credentialsToId(username, password) { + return `${username}|${password}`; + } + + /** + * Generate a new 128 bit random tag. + * + * Strictly speaking both using a cryptographic entropy source and using 128 + * bits of entropy for the tag are likely overkill, as correct behavior only + * depends on how unlikely it is for there to be a collision. + * + * @returns {string} The random nonce + */ + #nonce() { + return Array.from(crypto.getRandomValues(new Uint8Array(16)), byte => + byte.toString(16).padStart(2, "0") + ).join(""); + } + + /** + * Re-generate the nonce for a certain domain. + * + * @param {string?} domain The first-party domain to re-create the nonce for. + * If empty or null, the catchall domain will be used. + */ + newCircuitForDomain(domain) { + if (!domain) { + domain = CATCHALL_DOMAIN; + } + this.#noncesForDomains.set(domain, this.#nonce()); + if (domain === CATCHALL_DOMAIN) { + this.#catchallDirtySince = Date.now(); + } + logger.info( + `New domain isolation for ${domain}: ${this.#noncesForDomains.get( + domain + )}` + ); + } + + /** + * Re-generate the nonce for a userContextId. + * + * Currently, this function is not hooked to anything. + * + * @param {integer} userContextId The userContextId to re-create the nonce for + */ + // eslint-disable-next-line no-unused-private-class-members + #newCircuitForUserContextId(userContextId) { + this.#noncesForUserContextId.set(userContextId, this.#nonce()); + logger.info( + `New container isolation for ${userContextId}: ${this.#noncesForUserContextId.get( + userContextId + )}` + ); + } + + /** + * Try to extract a browser from a channel. + * + * @param {nsIChannel} channel The channel to extract the browser from + * @returns {MozBrowser?} The browser the channel is associated to + */ + #getBrowserForChannel(channel) { + const currentBrowser = + channel.loadInfo.browsingContext?.topChromeWindow?.browser; + if ( + channel.loadInfo.browsingContext && + currentBrowser?.browsingContext === channel.loadInfo.browsingContext + ) { + // Android has only one browser, and does not have the browsers property. + return currentBrowser; + } + const browsers = + channel.loadInfo.browsingContext?.topChromeWindow?.gBrowser?.browsers; + if (!browsers || !channel.loadInfo.browsingContext?.browserId) { + logger.debug("Missing data to associate to a browser", channel.loadInfo); + return null; + } + for (const browser of browsers) { + if (browser.browserId === channel.loadInfo.browsingContext.browserId) { + logger.debug( + "Matched browser with browserId", + channel.loadInfo.browsingContext.browserId + ); + return browser; + } + } + // Expected to arrive here for example for the update checker. + // If we find a way to check that, we could raise the level to a warn. + logger.debug("Browser not matched", channel); + return null; + } + + /** + * Associate the SOCKS credentials to a browser. + * If needed (the browser is associated for the first time, or it was already + * known but its credential changed), notify the related circuit display. + * + * @param {MozBrowser} browser The browser to track + * @param {string} username The SOCKS username + * @param {string} password The SOCKS password + */ + #trackBrowser(browser, username, password) { + let browserCircuits = this.#browsers.get(browser.browserId); + if (!browserCircuits) { + browserCircuits = new Map(); + this.#browsers.set(browser.browserId, browserCircuits); + } + const circuitIds = browserCircuits.get(username) ?? {}; + const id = this.#credentialsToId(username, password); + if (circuitIds.current === id) { + // The circuit with these credentials was already built (we already knew + // its nodes, or we would not have promoted it to the current circuit). + // We do not need to do anything else, because we cannot detect a change + // of nodes here. + return; + } + + logger.debug( + `Found new credentials ${username} ${password} for browser`, + browser + ); + const circuit = this.#knownCircuits.get(id); + if (circuit?.length) { + circuitIds.current = id; + if (circuitIds.pending === id) { + circuitIds.pending = null; + } + browserCircuits.set(username, circuitIds); + // FIXME: We only notify the circuit display when we have a change that + // involves circuits whose nodes are known, for now. We need to resolve a + // few other techical problems (e.g., associate the circuit to the + // document?) and develop a UX with some animation to notify the circuit + // display more often. + // See tor-browser#41700 and tor-browser!699. + // In any case, notify the circuit display only after the internal map has + // been updated. + this.#notifyCircuitDisplay(); + } else if (circuitIds.pending !== id) { + // We do not have node data, so we store that we might need to track this. + // Otherwise, when a circuit is ready, we do not know which browser was it + // used for. + circuitIds.pending = id; + browserCircuits.set(username, circuitIds); + } + } + + /** + * Update a circuit, and notify the related circuit displays if it changed. + * + * This function is called when a certain stream has succeeded and so we can + * associate its SOCKS credential to the circuit it is using. + * We receive only the fingerprints of the circuit nodes, but they are enough + * to check if the circuit has changed. If it has, we also get the nodes' + * information through the control port. + * + * @param {string} username The SOCKS username + * @param {string} password The SOCKS password + * @param {NodeFingerprint[]} circuit The fingerprints of the nodes that + * compose the circuit + */ + async #updateCircuit(username, password, circuit) { + const id = this.#credentialsToId(username, password); + let data = this.#knownCircuits.get(id) ?? []; + // Should we modify the lower layer to send a circuit identifier, instead? + if ( + circuit.length === data.length && + circuit.every((id, index) => id === data[index].fingerprint) + ) { + return; + } + + const provider = await lazy.TorProviderBuilder.build(); + data = await Promise.all( + circuit.map(fingerprint => provider.getNodeInfo(fingerprint)) + ); + logger.debug(`Updating circuit ${id}`, data); + this.#knownCircuits.set(id, data); + // We know that something changed, but we cannot know if anyone is + // interested in this change. So, we have to notify all the possible + // consumers of the data in any case. + // Not being specific and let them check if they need to do something allows + // us to keep a simpler structure. + this.#notifyCircuitDisplay(); + } + + /** + * Broadcast a notification when a circuit changed, or a browser is changing + * circuit (which might happen also in case of navigation). + */ + #notifyCircuitDisplay() { + Services.obs.notifyObservers(null, TOR_CIRCUIT_TOPIC); + } + + /** + * Clear the known circuit information, when they are not needed anymore. + * + * We keep circuit data around for a while. We decouple it from the underlying + * tor circuit management in case the user clicks on the circuit display when + * circuit has long gone. + * However, data accumulate during a session. So, since we store all the + * browsers that used a circuit anyway, every now and then we check if we + * still know browsers using a certain circuits. If there are not, we forget + * about it. + * + * This function is run by an interval. + */ + #clearKnownCircuits() { + logger.info("Running the circuit cleanup"); + const windows = []; + const enumerator = Services.wm.getEnumerator("navigator:browser"); + while (enumerator.hasMoreElements()) { + windows.push(enumerator.getNext()); + } + const browsers = windows + .flatMap(win => win.gBrowser.browsers.map(b => b.browserId)) + .filter(id => this.#browsers.has(id)); + this.#browsers = new Map(browsers.map(id => [id, this.#browsers.get(id)])); + this.#knownCircuits = new Map( + Array.from(this.#browsers.values(), circuits => + Array.from(circuits.values(), ids => { + const r = []; + const current = this.#knownCircuits.get(ids.current); + if (current) { + r.push([ids.current, current]); + } + const pending = this.#knownCircuits.get(ids.pending); + if (pending) { + r.push([ids.pending, pending]); + } + return r; + }) + ).flat(2) + ); + } +} + +/** + * Get the first party domain for a certain browser. + * + * @param {MozBrowser} browser The browser to get the FP-domain for. + * Please notice that it should be gBrowser.selectedBrowser, because + * browser.documentURI is the actual shown page, and might be an error page. + * In this case, we rely on currentURI, which for gBrowser is an alias of + * gBrowser.selectedBrowser.currentURI. + * See browser/base/content/tabbrowser.js and tor-browser#31562. + * + * @returns {string} The FPD associated to the principal of the passed browser. + */ +function getDomainForBrowser(browser) { + let fpd = browser.contentPrincipal.originAttributes.firstPartyDomain; + + const { documentURI } = browser; + if (documentURI && documentURI.schemeIs("about")) { + // Bug 31562: For neterror or certerror, get the original URL from + // browser.currentURI and use it to calculate the firstPartyDomain. + const knownErrors = [ + "about:neterror", + "about:certerror", + "about:httpsonlyerror", + ]; + if (knownErrors.some(x => documentURI.spec.startsWith(x))) { + const knownSchemes = ["http", "https"]; + const currentURI = browser.currentURI; + if (currentURI && knownSchemes.some(x => currentURI.schemeIs(x))) { + try { + fpd = Services.eTLD.getBaseDomainFromHost(currentURI.host); + } catch (e) { + if ( + e.result === Cr.NS_ERROR_HOST_IS_IP_ADDRESS || + e.result === Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS + ) { + fpd = currentURI.host; + } else { + logger.error( + `Failed to get first party domain for host ${currentURI.host}`, + e + ); + } + } + } + } else if (documentURI.spec.startsWith("about:reader")) { + try { + const searchParams = new URLSearchParams(documentURI.query); + if (searchParams.has("url")) { + fpd = Services.eTLD.getSchemelessSite( + Services.io.newURI(searchParams.get("url")) + ); + } + } catch (e) { + logger.error("Failed to get first party domain for about:reader", e); + } + } + } + + return fpd; +} + +export const TorDomainIsolator = new TorDomainIsolatorImpl(); +// Reduce global vars pollution +TorDomainIsolator.getDomainForBrowser = getDomainForBrowser; diff --git a/toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs b/toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..998f4f22bfede28cc215adf3450447d14cdbbdec --- /dev/null +++ b/toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs @@ -0,0 +1,702 @@ +// Copyright (c) 2022, The Tor Project, Inc. +// See LICENSE for licensing information. + +/************************************************************************* + * Tor Launcher Util JS Module + *************************************************************************/ + +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", +}); + +const kPropBundleURI = "chrome://torbutton/locale/torlauncher.properties"; +const kPropNamePrefix = "torlauncher."; +const kIPCDirPrefName = "extensions.torlauncher.tmp_ipc_dir"; + +/** + * This class allows to lookup for the paths of the various files that are + * needed or can be used with the tor daemon, such as its configuration, the + * GeoIP databases, and the Unix sockets that can be optionally used for the + * control and the SOCKS ports. + */ +class TorFile { + // The nsIFile to be returned + file = null; + + isIPC = false; + ipcFileName = ""; + checkIPCPathLen = true; + + static _isFirstIPCPathRequest = true; + static _dataDir = null; + static _appDir = null; + static _torDir = null; + + constructor(aTorFileType, aCreate) { + this.fileType = aTorFileType; + + this.getFromPref(); + this.getIPC(); + // No preference and no pre-determined IPC path: use a default path. + if (!this.file) { + this.getDefault(); + } + // At this point, this.file must not be null, or previous functions must + // have thrown and interrupted this constructor. + if (!this.file.exists() && !this.isIPC && aCreate) { + this.createFile(); + } + this.normalize(); + } + + getFile() { + return this.file; + } + + getFromPref() { + const prefName = `extensions.torlauncher.${this.fileType}_path`; + const path = Services.prefs.getCharPref(prefName, ""); + if (path) { + const isUserData = + this.fileType !== "tor" && + this.fileType !== "pt-startup-dir" && + this.fileType !== "torrc-defaults"; + // always try to use path if provided in pref + this.checkIPCPathLen = false; + this.setFileFromPath(path, isUserData); + } + } + + getIPC() { + const isControlIPC = this.fileType === "control_ipc"; + const isSOCKSIPC = this.fileType === "socks_ipc"; + this.isIPC = isControlIPC || isSOCKSIPC; + if (!this.isIPC) { + return; + } + + const kControlIPCFileName = "control.socket"; + const kSOCKSIPCFileName = "socks.socket"; + this.ipcFileName = isControlIPC ? kControlIPCFileName : kSOCKSIPCFileName; + this.extraIPCPathLen = this.isSOCKSIPC ? 2 : 0; + + // Do not do anything else if this.file has already been populated with the + // _path preference for this file type (or if we are not looking for an IPC + // file). + if (this.file) { + return; + } + + // If this is the first request for an IPC path during this browser + // session, remove the old temporary directory. This helps to keep /tmp + // clean if the browser crashes or is killed. + if (TorFile._isFirstIPCPathRequest) { + TorLauncherUtil.cleanupTempDirectories(); + TorFile._isFirstIPCPathRequest = false; + } else { + // FIXME: Do we really need a preference? Or can we save it in a static + // member? + // Retrieve path for IPC objects (it may have already been determined). + const ipcDirPath = Services.prefs.getCharPref(kIPCDirPrefName, ""); + if (ipcDirPath) { + // We have already determined where IPC objects will be placed. + this.file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + this.file.initWithPath(ipcDirPath); + this.file.append(this.ipcFileName); + this.checkIPCPathLen = false; // already checked. + return; + } + } + + // If XDG_RUNTIME_DIR is set, use it as the base directory for IPC + // objects (e.g., Unix domain sockets) -- assuming it is not too long. + if (!Services.env.exists("XDG_RUNTIME_DIR")) { + return; + } + const ipcDir = this.createUniqueIPCDir(Services.env.get("XDG_RUNTIME_DIR")); + if (ipcDir) { + const f = ipcDir.clone(); + f.append(this.ipcFileName); + if (this.isIPCPathLengthOK(f.path, this.extraIPCPathLen)) { + this.file = f; + this.checkIPCPathLen = false; // no need to check again. + + // Store directory path so it can be reused for other IPC objects + // and so it can be removed during exit. + Services.prefs.setCharPref(kIPCDirPrefName, ipcDir.path); + } else { + // too long; remove the directory that we just created. + ipcDir.remove(false); + } + } + } + + getDefault() { + switch (this.fileType) { + case "tor": + this.file = TorFile.torDir; + this.file.append(TorLauncherUtil.isWindows ? "tor.exe" : "tor"); + break; + case "torrc-defaults": + if (TorLauncherUtil.isMac) { + this.file = TorFile.appDir; + this.file.appendRelativePath( + "Contents/Resources/TorBrowser/Tor/torrc-defaults" + ); + } else { + // FIXME: Should we move this file to the tor directory, in the other + // platforms, since it is not user data? + this.file = TorFile.torDataDir; + this.file.append("torrc-defaults"); + } + break; + case "torrc": + this.file = TorFile.torDataDir; + this.file.append("torrc"); + break; + case "tordatadir": + this.file = TorFile.torDataDir; + break; + case "toronionauthdir": + this.file = TorFile.torDataDir; + this.file.append("onion-auth"); + break; + case "pt-startup-dir": + // On macOS we specify different relative paths than on Linux and + // Windows + this.file = TorLauncherUtil.isMac ? TorFile.torDir : TorFile.appDir; + break; + default: + if (!TorLauncherUtil.isWindows && this.isIPC) { + this.setFileFromPath(`Tor/${this.ipcFileName}`, true); + break; + } + throw new Error("Unknown file type"); + } + } + + // This function is used to set this.file from a string that contains a path. + // As a matter of fact, it is used only when setting a path from preferences, + // or to set the default IPC paths. + setFileFromPath(path, isUserData) { + if (TorLauncherUtil.isWindows) { + path = path.replaceAll("/", "\\"); + } + // Turn 'path' into an absolute path when needed. + if (TorLauncherUtil.isPathRelative(path)) { + if (TorLauncherUtil.isMac) { + // On macOS, files are correctly separated because it was needed for the + // gatekeeper signing. + this.file = isUserData ? TorFile.dataDir : TorFile.appDir; + } else { + // Windows and Linux still use the legacy behavior. + // To avoid breaking old installations, let's just keep it. + this.file = TorFile.appDir; + this.file.append("TorBrowser"); + } + this.file.appendRelativePath(path); + } else { + this.file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + this.file.initWithPath(path); + } + } + + createFile() { + if ( + "tordatadir" == this.fileType || + "toronionauthdir" == this.fileType || + "pt-profiles-dir" == this.fileType + ) { + this.file.create(this.file.DIRECTORY_TYPE, 0o700); + } else { + this.file.create(this.file.NORMAL_FILE_TYPE, 0o600); + } + } + + // If the file exists or an IPC object was requested, normalize the path + // and return a file object. The control and SOCKS IPC objects will be + // created by tor. + normalize() { + if (this.file.exists()) { + try { + this.file.normalize(); + } catch (e) { + console.warn("Normalization of the path failed", e); + } + } else if (!this.isIPC) { + throw new Error(`${this.fileType} file not found: ${this.file.path}`); + } + + // Ensure that the IPC path length is short enough for use by the + // operating system. If not, create and use a unique directory under + // /tmp for all IPC objects. The created directory path is stored in + // a preference so it can be reused for other IPC objects and so it + // can be removed during exit. + if ( + this.isIPC && + this.checkIPCPathLen && + !this.isIPCPathLengthOK(this.file.path, this.extraIPCPathLen) + ) { + this.file = this.createUniqueIPCDir("/tmp"); + if (!this.file) { + throw new Error("failed to create unique directory under /tmp"); + } + + Services.prefs.setCharPref(kIPCDirPrefName, this.file.path); + this.file.append(this.ipcFileName); + } + } + + // Return true if aPath is short enough to be used as an IPC object path, + // e.g., for a Unix domain socket path. aExtraLen is the "delta" necessary + // to accommodate other IPC objects that have longer names; it is used to + // account for "control.socket" vs. "socks.socket" (we want to ensure that + // all IPC objects are placed in the same parent directory unless the user + // has set prefs or env vars to explicitly specify the path for an object). + // We enforce a maximum length of 100 because all operating systems allow + // at least 100 characters for Unix domain socket paths. + isIPCPathLengthOK(aPath, aExtraLen) { + const kMaxIPCPathLen = 100; + return aPath && aPath.length + aExtraLen <= kMaxIPCPathLen; + } + + // Returns an nsIFile or null if a unique directory could not be created. + createUniqueIPCDir(aBasePath) { + try { + const d = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + d.initWithPath(aBasePath); + d.append("Tor"); + d.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700); + return d; + } catch (e) { + console.error(`createUniqueIPCDir failed for ${aBasePath}: `, e); + return null; + } + } + + // Returns an nsIFile that points to the binary directory (on Linux and + // Windows), and to the root of the application bundle on macOS. + static get appDir() { + if (!this._appDir) { + // .../Browser on Windows and Linux, .../TorBrowser.app/Contents/MacOS/ on + // macOS. + this._appDir = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; + if (TorLauncherUtil.isMac) { + this._appDir = this._appDir.parent.parent; + } + } + return this._appDir.clone(); + } + + // Returns an nsIFile that points to the data directory. This is usually + // TorBrowser/Data/ on Linux and Windows, and TorBrowser-Data/ on macOS. + // The parent directory of the default profile directory is taken. + static get dataDir() { + if (!this._dataDir) { + // Notice that we use `DefProfRt`, because users could create their + // profile in a completely unexpected directory: the profiles.ini contains + // a IsRelative entry, which I expect could influence ProfD, but not this. + this._dataDir = Services.dirsvc.get("DefProfRt", Ci.nsIFile).parent; + } + return this._dataDir.clone(); + } + + // Returns an nsIFile that points to the directory that contains the tor + // executable. + static get torDir() { + if (!this._torDir) { + // The directory that contains firefox + const torDir = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; + if (!TorLauncherUtil.isMac) { + torDir.append("TorBrowser"); + } + torDir.append("Tor"); + // Save the value only if the XPCOM methods do not throw. + this._torDir = torDir; + } + return this._torDir.clone(); + } + + // Returns an nsIFile that points to the directory that contains the tor + // data. Currently it is ${dataDir}/Tor. + static get torDataDir() { + const dir = this.dataDir; + dir.append("Tor"); + return dir; + } +} + +export const TorLauncherUtil = { + get isAndroid() { + return Services.appinfo.OS === "Android"; + }, + + get isLinux() { + // Use AppConstants for Linux rather then appinfo because we are sure it + // will catch also various Unix flavors for which unofficial ports might + // exist (which should work as Linux, as far as we know). + return AppConstants.platform === "linux"; + }, + + get isMac() { + return Services.appinfo.OS === "Darwin"; + }, + + get isWindows() { + return Services.appinfo.OS === "WINNT"; + }, + + isPathRelative(path) { + const re = this.isWindows ? /^([A-Za-z]:|\\)\\/ : /^\//; + return !re.test(path); + }, + + // Returns true if user confirms; false if not. + showConfirm(aParentWindow, aMsg, aDefaultButtonLabel, aCancelButtonLabel) { + if (!aParentWindow) { + aParentWindow = Services.wm.getMostRecentWindow("navigator:browser"); + } + + const ps = Services.prompt; + const title = this.getLocalizedString("error_title"); + const btnFlags = + ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING + + ps.BUTTON_POS_0_DEFAULT + + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING; + + const notUsed = { value: false }; + const btnIndex = ps.confirmEx( + aParentWindow, + title, + aMsg, + btnFlags, + aDefaultButtonLabel, + aCancelButtonLabel, + null, + null, + notUsed + ); + return btnIndex === 0; + }, + + /** + * Ask the user whether they desire to restart tor. + * + * @param {boolean} initError If we could connect to the control port at + * least once and we are showing this prompt because the tor process exited + * suddenly, we will display a different message + * @returns {boolean} true if the user asked to restart tor + */ + showRestartPrompt(initError) { + let s; + if (initError) { + const key = "tor_exited_during_startup"; + s = this.getLocalizedString(key); + } else { + // tor exited suddenly, so configuration should be okay + s = + this.getLocalizedString("tor_exited") + + "\n\n" + + this.getLocalizedString("tor_exited2"); + } + const defaultBtnLabel = this.getLocalizedString("restart_tor"); + let cancelBtnLabel = "OK"; + try { + const kSysBundleURI = "chrome://global/locale/commonDialogs.properties"; + const sysBundle = Services.strings.createBundle(kSysBundleURI); + cancelBtnLabel = sysBundle.GetStringFromName(cancelBtnLabel); + } catch (e) { + console.warn("Could not localize the cancel button", e); + } + return this.showConfirm(null, s, defaultBtnLabel, cancelBtnLabel); + }, + + _stringBundle: null, + + // Localized Strings + // TODO: Switch to fluent also these ones. + + // "torlauncher." is prepended to aStringName. + getLocalizedString(aStringName) { + if (!aStringName) { + return aStringName; + } + if (!this._stringBundle) { + this._stringBundle = Services.strings.createBundle(kPropBundleURI); + } + try { + const key = kPropNamePrefix + aStringName; + return this._stringBundle.GetStringFromName(key); + } catch (e) {} + return aStringName; + }, + + /** + * Determine what kind of SOCKS port has been requested for this session or + * the browser has been configured for. + * On Windows (where Unix domain sockets are not supported), TCP is always + * used. + * + * The following environment variables are supported and take precedence over + * preferences: + * TOR_TRANSPROXY (do not use a proxy) + * TOR_SOCKS_IPC_PATH (file system path; ignored on Windows) + * TOR_SOCKS_HOST + * TOR_SOCKS_PORT + * + * The following preferences are consulted: + * network.proxy.socks + * network.proxy.socks_port + * extensions.torlauncher.socks_port_use_ipc (Boolean) + * extensions.torlauncher.socks_ipc_path (file system path) + * If extensions.torlauncher.socks_ipc_path is empty, a default path is used. + * + * When using TCP, if a value is not defined via an env variable it is + * taken from the corresponding browser preference if possible. The + * exceptions are: + * If network.proxy.socks contains a file: URL, a default value of + * "127.0.0.1" is used instead. + * If the network.proxy.socks_port value is not valid (outside the + * (0; 65535] range), we will let the tor daemon choose a port. + * + * The SOCKS configuration will not influence the launch of a tor daemon and + * the configuration of the control port in any way. + * When a SOCKS configuration is required without TOR_SKIP_LAUNCH, the browser + * will try to configure the tor instance to use the required configuration. + * This also applies to TOR_TRANSPROXY (at least for now): tor will be + * launched with its defaults. + * + * @returns {SocksSettings} + */ + getPreferredSocksConfiguration() { + if (Services.env.exists("TOR_TRANSPROXY")) { + return { transproxy: true }; + } + + let useIPC; + const socksPortInfo = { + transproxy: false, + }; + + if (!this.isWindows && Services.env.exists("TOR_SOCKS_IPC_PATH")) { + useIPC = true; + const ipcPath = Services.env.get("TOR_SOCKS_IPC_PATH"); + if (ipcPath) { + socksPortInfo.ipcFile = new lazy.FileUtils.File(ipcPath); + } + } else { + // Check for TCP host and port environment variables. + if (Services.env.exists("TOR_SOCKS_HOST")) { + socksPortInfo.host = Services.env.get("TOR_SOCKS_HOST"); + useIPC = false; + } + if (Services.env.exists("TOR_SOCKS_PORT")) { + const port = parseInt(Services.env.get("TOR_SOCKS_PORT"), 10); + if (Number.isInteger(port) && port >= 0 && port <= 65535) { + socksPortInfo.port = port; + useIPC = false; + } + } + } + + if (useIPC === undefined) { + useIPC = + !this.isWindows && + Services.prefs.getBoolPref( + "extensions.torlauncher.socks_port_use_ipc", + false + ); + } + + // Fill in missing SOCKS info from prefs. + if (useIPC) { + if (!socksPortInfo.ipcFile) { + socksPortInfo.ipcFile = TorLauncherUtil.getTorFile("socks_ipc", false); + } + } else { + if (!socksPortInfo.host) { + let socksAddr = Services.prefs.getCharPref( + "network.proxy.socks", + "127.0.0.1" + ); + let socksAddrHasHost = socksAddr && !socksAddr.startsWith("file:"); + socksPortInfo.host = socksAddrHasHost ? socksAddr : "127.0.0.1"; + } + + if (socksPortInfo.port === undefined) { + let socksPort = Services.prefs.getIntPref( + "network.proxy.socks_port", + 9150 + ); + if (socksPort > 0 && socksPort <= 65535) { + socksPortInfo.port = socksPort; + } else { + // Automatic port number, we have to query tor over the control port + // every time we change DisableNetwork. + socksPortInfo.port = 0; + } + } + } + + return socksPortInfo; + }, + + /** + * Apply our proxy configuration to the browser. + * + * Currently, we try to configure the Tor daemon to match the browser's + * configuration, but this might change in the future (tor-browser#42062). + * + * @param {SocksSettings} socksPortInfo The configuration to apply + */ + setProxyConfiguration(socksPortInfo) { + if (socksPortInfo.transproxy) { + Services.prefs.setBoolPref("network.proxy.socks_remote_dns", false); + Services.prefs.setIntPref("network.proxy.type", 0); + Services.prefs.setIntPref("network.proxy.socks_port", 0); + Services.prefs.setCharPref("network.proxy.socks", ""); + return; + } + + if (socksPortInfo.ipcFile) { + const fph = Services.io + .getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + const fileURI = fph.newFileURI(socksPortInfo.ipcFile); + Services.prefs.setCharPref("network.proxy.socks", fileURI.spec); + Services.prefs.setIntPref("network.proxy.socks_port", 0); + } else { + if (socksPortInfo.host) { + Services.prefs.setCharPref("network.proxy.socks", socksPortInfo.host); + } + if (socksPortInfo.port > 0 && socksPortInfo.port <= 65535) { + Services.prefs.setIntPref( + "network.proxy.socks_port", + socksPortInfo.port + ); + } + } + + if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) { + Services.prefs.setBoolPref("network.proxy.socks_remote_dns", true); + Services.prefs.setIntPref("network.proxy.type", 1); + } + + // Force prefs to be synced to disk + Services.prefs.savePrefFile(null); + }, + + /** + * Determine the current value for whether we should start and own Tor. + * + * @returns {boolean} Whether we should start and own Tor. + */ + _getShouldStartAndOwnTor() { + const kPrefStartTor = "extensions.torlauncher.start_tor"; + try { + const kBrowserToolboxPort = "MOZ_BROWSER_TOOLBOX_PORT"; + const kEnvSkipLaunch = "TOR_SKIP_LAUNCH"; + const kEnvProvider = "TOR_PROVIDER"; + if (Services.env.exists(kBrowserToolboxPort)) { + return false; + } + if (Services.env.exists(kEnvSkipLaunch)) { + const value = parseInt(Services.env.get(kEnvSkipLaunch)); + return isNaN(value) || !value; + } + if ( + Services.env.exists(kEnvProvider) && + Services.env.get(kEnvProvider) === "none" + ) { + return false; + } + } catch (e) {} + return Services.prefs.getBoolPref(kPrefStartTor, true); + }, + + /** + * Cached value for shouldStartAndOwnTor, or `null` if not yet initialised. + * + * @type {boolean} + */ + _shouldStartAndOwnTor: null, + + /** + * Whether we should start and own Tor. + * + * The value should be constant per-session. + * + * @type {boolean} + */ + get shouldStartAndOwnTor() { + // Do not want this value to change within the same session, so always used + // the cached valued if it is available. + if (this._shouldStartAndOwnTor === null) { + this._shouldStartAndOwnTor = this._getShouldStartAndOwnTor(); + } + return this._shouldStartAndOwnTor; + }, + + get shouldShowNetworkSettings() { + try { + const kEnvForceShowNetConfig = "TOR_FORCE_NET_CONFIG"; + if (Services.env.exists(kEnvForceShowNetConfig)) { + const value = parseInt(Services.env.get(kEnvForceShowNetConfig)); + return !isNaN(value) && value; + } + } catch (e) {} + return true; + }, + + get shouldOnlyConfigureTor() { + const kPrefOnlyConfigureTor = "extensions.torlauncher.only_configure_tor"; + try { + const kEnvOnlyConfigureTor = "TOR_CONFIGURE_ONLY"; + if (Services.env.exists(kEnvOnlyConfigureTor)) { + const value = parseInt(Services.env.get(kEnvOnlyConfigureTor)); + return !isNaN(value) && value; + } + } catch (e) {} + return Services.prefs.getBoolPref(kPrefOnlyConfigureTor, false); + }, + + // Returns an nsIFile. + // If aTorFileType is "control_ipc" or "socks_ipc", aCreate is ignored + // and there is no requirement that the IPC object exists. + // For all other file types, null is returned if the file does not exist + // and it cannot be created (it will be created if aCreate is true). + getTorFile(aTorFileType, aCreate) { + if (!aTorFileType) { + return null; + } + try { + const torFile = new TorFile(aTorFileType, aCreate); + return torFile.getFile(); + } catch (e) { + console.error(`getTorFile: cannot get ${aTorFileType}`, e); + } + return null; // File not found or error (logged above). + }, + + cleanupTempDirectories() { + const dirPath = Services.prefs.getCharPref(kIPCDirPrefName, ""); + try { + Services.prefs.clearUserPref(kIPCDirPrefName); + } catch (e) {} + try { + if (dirPath) { + const f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + f.initWithPath(dirPath); + if (f.exists()) { + f.remove(false); + } + } + } catch (e) { + console.warn("Could not remove the IPC directory", e); + } + }, +}; diff --git a/toolkit/components/tor-launcher/TorParsers.sys.mjs b/toolkit/components/tor-launcher/TorParsers.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..3d0f3936385d97cf8967e36ff91eb8fd3aab4fd4 --- /dev/null +++ b/toolkit/components/tor-launcher/TorParsers.sys.mjs @@ -0,0 +1,122 @@ +// Copyright (c) 2022, The Tor Project, Inc. + +export const TorStatuses = Object.freeze({ + OK: 250, + EventNotification: 650, +}); + +export const TorParsers = Object.freeze({ + // Escape non-ASCII characters for use within the Tor Control protocol. + // Based on Vidalia's src/common/stringutil.cpp:string_escape(). + // Returns the new string. + escapeString(aStr) { + // Just return if all characters are printable ASCII excluding SP, ", and # + const kSafeCharRE = /^[\x21\x24-\x7E]*$/; + if (!aStr || kSafeCharRE.test(aStr)) { + return aStr; + } + const escaped = aStr + .replaceAll("\\", "\\\\") + .replaceAll('"', '\\"') + .replaceAll("\n", "\\n") + .replaceAll("\r", "\\r") + .replaceAll("\t", "\\t") + .replaceAll(/[^\x20-\x7e]+/g, text => { + const encoder = new TextEncoder(); + return Array.from( + encoder.encode(text), + ch => "\\x" + ch.toString(16) + ).join(""); + }); + return `"${escaped}"`; + }, + + // Unescape Tor Control string aStr (removing surrounding "" and \ escapes). + // Based on Vidalia's src/common/stringutil.cpp:string_unescape(). + // Returns the unescaped string. Throws upon failure. + // Within Torbutton, the file modules/utils.js also contains a copy of + // _strUnescape(). + unescapeString(aStr) { + if ( + !aStr || + aStr.length < 2 || + aStr[0] !== '"' || + aStr[aStr.length - 1] !== '"' + ) { + return aStr; + } + + // Regular expression by Tim Pietzcker + // https://stackoverflow.com/a/15569588 + if (!/^(?:[^"\\]|\\.|"(?:\\.|[^"\\])*")*$/.test(aStr)) { + throw new Error('Unescaped " within string'); + } + + const matchUnicode = /^(\\x[0-9A-Fa-f]{2}|\\[0-7]{3})+/; + let rv = ""; + let lastAdded = 1; + let bs; + while ((bs = aStr.indexOf("\\", lastAdded)) !== -1) { + rv += aStr.substring(lastAdded, bs); + // We always increment lastAdded, because we will either add something, or + // ignore the backslash. + lastAdded = bs + 2; + if (lastAdded === aStr.length) { + // The string ends with \", which is illegal + throw new Error("Missing character after \\"); + } + switch (aStr[bs + 1]) { + case "n": + rv += "\n"; + break; + case "r": + rv += "\r"; + break; + case "t": + rv += "\t"; + break; + case '"': + case "\\": + rv += aStr[bs + 1]; + break; + default: + aStr.substring(bs).replace(matchUnicode, sequence => { + const bytes = []; + for (let i = 0; i < sequence.length; i += 4) { + if (sequence[i + 1] === "x") { + bytes.push(parseInt(sequence.substring(i + 2, i + 4), 16)); + } else { + bytes.push(parseInt(sequence.substring(i + 1, i + 4), 8)); + } + } + lastAdded = bs + sequence.length; + const decoder = new TextDecoder(); + rv += decoder.decode(new Uint8Array(bytes)); + return ""; + }); + // We have already incremented lastAdded, which means we ignore the + // backslash, and we will do something at the next one. + break; + } + } + rv += aStr.substring(lastAdded, aStr.length - 1); + return rv; + }, + + parseBridgeLine(line) { + if (!line) { + return null; + } + const re = + /\s*(?:(?<transport>\S+)\s+)?(?<addr>[0-9a-fA-F\.\[\]\:]+:\d{1,5})(?:\s+(?<id>[0-9a-fA-F]{40}))?(?:\s+(?<args>.+))?/; + const match = re.exec(line); + if (!match) { + throw new Error(`Invalid bridge line: ${line}.`); + } + const bridge = match.groups; + if (!bridge.transport) { + bridge.transport = "vanilla"; + } + return bridge; + }, +}); diff --git a/toolkit/components/tor-launcher/TorProcess.sys.mjs b/toolkit/components/tor-launcher/TorProcess.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..6320adebdfa9ef8634a0c44f73d641a73ce49587 --- /dev/null +++ b/toolkit/components/tor-launcher/TorProcess.sys.mjs @@ -0,0 +1,393 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { setTimeout } from "resource://gre/modules/Timer.sys.mjs"; +import { Subprocess } from "resource://gre/modules/Subprocess.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + TorParsers: "resource://gre/modules/TorParsers.sys.mjs", +}); + +const TorProcessStatus = Object.freeze({ + Unknown: 0, + Starting: 1, + Running: 2, + Exited: 3, +}); + +const logger = console.createInstance({ + maxLogLevel: "Info", + prefix: "TorProcess", +}); + +/** + * This class can be used to start a tor daemon instance and receive + * notifications when it exits. + * It will automatically convert the settings objects into the appropriate + * command line arguments. + * + * It does not offer a way to stop a process because it is supposed to exit + * automatically when the owning control port connection is closed. + */ +export class TorProcess { + #controlSettings; + #socksSettings; + #exeFile = null; + #dataDir = null; + #args = []; + #subprocess = null; + #status = TorProcessStatus.Unknown; + + onExit = _exitCode => {}; + + constructor(controlSettings, socksSettings) { + if ( + controlSettings && + !controlSettings.password?.length && + !controlSettings.cookieFilePath + ) { + throw new Error("Unauthenticated control port is not supported"); + } + + const checkPort = (port, allowZero) => + port === undefined || + (Number.isInteger(port) && + port < 65535 && + (port > 0 || (allowZero && port === 0))); + if (!checkPort(controlSettings?.port, false)) { + throw new Error("Invalid control port"); + } + // Port 0 for SOCKS means automatic port. + if (!checkPort(socksSettings.port, true)) { + throw new Error("Invalid port specified for the SOCKS port"); + } + + this.#controlSettings = { ...controlSettings }; + const ipcFileToString = file => + "unix:" + lazy.TorParsers.escapeString(file.path); + if (controlSettings.ipcFile) { + this.#controlSettings.ipcFile = ipcFileToString(controlSettings.ipcFile); + } + this.#socksSettings = { ...socksSettings }; + if (socksSettings.ipcFile) { + this.#socksSettings.ipcFile = ipcFileToString(socksSettings.ipcFile); + } + } + + get isRunning() { + return ( + this.#status === TorProcessStatus.Starting || + this.#status === TorProcessStatus.Running + ); + } + + async start() { + if (this.#subprocess) { + return; + } + + this.#status = TorProcessStatus.Unknown; + + try { + this.#makeArgs(); + this.#addControlPortArgs(); + this.#addSocksPortArg(); + + const pid = Services.appinfo.processID; + if (pid !== 0) { + this.#args.push("__OwningControllerProcess", pid.toString()); + } + + if (lazy.TorLauncherUtil.shouldShowNetworkSettings) { + this.#args.push("DisableNetwork", "1"); + } + + this.#status = TorProcessStatus.Starting; + + // useful for simulating slow tor daemon launch + const kPrefTorDaemonLaunchDelay = "extensions.torlauncher.launch_delay"; + const launchDelay = Services.prefs.getIntPref( + kPrefTorDaemonLaunchDelay, + 0 + ); + if (launchDelay > 0) { + await new Promise(resolve => setTimeout(() => resolve(), launchDelay)); + } + + logger.debug(`Starting ${this.#exeFile.path}`, this.#args); + const options = { + command: this.#exeFile.path, + arguments: this.#args, + stderr: "stdout", + workdir: lazy.TorLauncherUtil.getTorFile("pt-startup-dir", false).path, + }; + if (lazy.TorLauncherUtil.isLinux) { + let ldLibPath = Services.env.get("LD_LIBRARY_PATH") ?? ""; + if (ldLibPath) { + ldLibPath = ":" + ldLibPath; + } + options.environment = { + LD_LIBRARY_PATH: this.#exeFile.parent.path + ldLibPath, + }; + options.environmentAppend = true; + } + this.#subprocess = await Subprocess.call(options); + this.#status = TorProcessStatus.Running; + } catch (e) { + this.#status = TorProcessStatus.Exited; + this.#subprocess = null; + logger.error("startTor error:", e); + throw e; + } + + // Do not await the following functions, as they will return only when the + // process exits. + this.#dumpStdout(); + this.#watchProcess(); + } + + // Forget about a process. + // + // Instead of killing the tor process, we rely on the TAKEOWNERSHIP feature + // to shut down tor when we close the control port connection. + // + // Previously, we sent a SIGNAL HALT command to the tor control port, + // but that caused hangs upon exit in the Firefox 24.x based browser. + // Apparently, Firefox does not like to process socket I/O while + // quitting if the browser did not finish starting up (e.g., when + // someone presses the Quit button on our Network Settings window + // during startup). + // + // Still, before closing the owning connection, this class should forget about + // the process, so that future notifications will be ignored. + forget() { + this.#subprocess = null; + this.#status = TorProcessStatus.Exited; + } + + async #dumpStdout() { + let string; + while ( + this.#subprocess && + (string = await this.#subprocess.stdout.readString()) + ) { + dump(string); + } + } + + async #watchProcess() { + const watched = this.#subprocess; + if (!watched) { + return; + } + let processExitCode; + try { + const { exitCode } = await watched.wait(); + processExitCode = exitCode; + + if (watched !== this.#subprocess) { + logger.debug(`A Tor process exited with code ${exitCode}.`); + } else if (exitCode) { + logger.warn(`The watched Tor process exited with code ${exitCode}.`); + } else { + logger.info("The Tor process exited."); + } + } catch (e) { + logger.error("Failed to watch the tor process", e); + } + + if (watched === this.#subprocess) { + this.#processExitedUnexpectedly(processExitCode); + } + } + + #processExitedUnexpectedly(exitCode) { + this.#subprocess = null; + this.#status = TorProcessStatus.Exited; + logger.warn("Tor exited suddenly."); + this.onExit(exitCode); + } + + #makeArgs() { + this.#exeFile = lazy.TorLauncherUtil.getTorFile("tor", false); + if (!this.#exeFile) { + throw new Error("Could not find the tor binary."); + } + const torrcFile = lazy.TorLauncherUtil.getTorFile("torrc", true); + if (!torrcFile) { + // FIXME: Is this still a fatal error? + throw new Error("Could not find the torrc."); + } + // Get the Tor data directory first so it is created before we try to + // construct paths to files that will be inside it. + this.#dataDir = lazy.TorLauncherUtil.getTorFile("tordatadir", true); + if (!this.#dataDir) { + throw new Error("Could not find the tor data directory."); + } + const onionAuthDir = lazy.TorLauncherUtil.getTorFile( + "toronionauthdir", + true + ); + if (!onionAuthDir) { + throw new Error("Could not find the tor onion authentication directory."); + } + + this.#args = []; + this.#args.push("-f", torrcFile.path); + this.#args.push("DataDirectory", this.#dataDir.path); + this.#args.push("ClientOnionAuthDir", onionAuthDir.path); + + // TODO: Create this starting from pt_config.json (tor-browser#42357). + const torrcDefaultsFile = lazy.TorLauncherUtil.getTorFile( + "torrc-defaults", + false + ); + if (torrcDefaultsFile) { + this.#args.push("--defaults-torrc", torrcDefaultsFile.path); + // The geoip and geoip6 files are in the same directory as torrc-defaults. + // TODO: Change TorFile to return the generic path to these files to make + // them independent from the torrc-defaults. + const geoipFile = torrcDefaultsFile.clone(); + geoipFile.leafName = "geoip"; + this.#args.push("GeoIPFile", geoipFile.path); + const geoip6File = torrcDefaultsFile.clone(); + geoip6File.leafName = "geoip6"; + this.#args.push("GeoIPv6File", geoip6File.path); + } else { + logger.warn( + "torrc-defaults was not found, some functionalities will be disabled." + ); + } + } + + /** + * Add all the arguments related to the control port. + * We use the + prefix so that the the port is added to any other port already + * defined in the torrc, and the __ prefix so that it is never written to + * torrc. + */ + #addControlPortArgs() { + if (!this.#controlSettings) { + return; + } + + let controlPortArg; + if (this.#controlSettings.ipcFile) { + controlPortArg = this.#controlSettings.ipcFile; + } else if (this.#controlSettings.port) { + controlPortArg = this.#controlSettings.host + ? `${this.#controlSettings.host}:${this.#controlSettings.port}` + : this.#controlSettings.port.toString(); + } + if (controlPortArg) { + this.#args.push("+__ControlPort", controlPortArg); + } + + if (this.#controlSettings.password?.length) { + this.#args.push( + "HashedControlPassword", + this.#hashPassword(this.#controlSettings.password) + ); + } + if (this.#controlSettings.cookieFilePath) { + this.#args.push("CookieAuthentication", "1"); + this.#args.push("CookieAuthFile", this.#controlSettings.cookieFilePath); + } + } + + /** + * Add the argument related to the control port. + * We use the + prefix so that the the port is added to any other port already + * defined in the torrc, and the __ prefix so that it is never written to + * torrc. + */ + #addSocksPortArg() { + let socksPortArg; + if (this.#socksSettings.ipcFile) { + socksPortArg = this.#socksSettings.ipcFile; + } else if (this.#socksSettings.port > 0) { + socksPortArg = this.#socksSettings.host + ? `${this.#socksSettings.host}:${this.#socksSettings.port}` + : this.#socksSettings.port.toString(); + } else { + socksPortArg = "auto"; + } + if (socksPortArg) { + const socksPortFlags = Services.prefs.getCharPref( + "extensions.torlauncher.socks_port_flags", + "IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth" + ); + if (socksPortFlags) { + socksPortArg += " " + socksPortFlags; + } + this.#args.push("+__SocksPort", socksPortArg); + } + } + + /** + * Hash a password to then pass it to Tor as a command line argument. + * Based on Vidalia's TorSettings::hashPassword(). + * + * @param {Uint8Array} password The password, as an array of bytes + * @returns {string} The hashed password + */ + #hashPassword(password) { + // The password has already been checked by the caller. + + // Generate a random, 8 byte salt value. + const salt = Array.from(crypto.getRandomValues(new Uint8Array(8))); + + // Run through the S2K algorithm and convert to a string. + const toHex = v => v.toString(16).padStart(2, "0"); + const arrayToHex = aArray => aArray.map(toHex).join(""); + const kCodedCount = 96; + const hashVal = this.#cryptoSecretToKey( + Array.from(password), + salt, + kCodedCount + ); + return "16:" + arrayToHex(salt) + toHex(kCodedCount) + arrayToHex(hashVal); + } + + /** + * Generates and return a hash of a password by following the iterated and + * salted S2K algorithm (see RFC 2440 section 3.6.1.3). + * See also https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/control-spec.txt#L3824. + * #cryptoSecretToKey() is similar to Vidalia's crypto_secret_to_key(). + * + * @param {Array} password The password to hash, as an array of bytes + * @param {Array} salt The salt to use for the hash, as an array of bytes + * @param {number} codedCount The counter, coded as specified in RFC 2440 + * @returns {Array} The hash of the password, as an array of bytes + */ + #cryptoSecretToKey(password, salt, codedCount) { + const inputArray = salt.concat(password); + + // Subtle crypto only has the final digest, and does not allow incremental + // updates. + const hasher = Cc["@mozilla.org/security/hash;1"].createInstance( + Ci.nsICryptoHash + ); + hasher.init(hasher.SHA1); + const kEXPBIAS = 6; + let count = (16 + (codedCount & 15)) << ((codedCount >> 4) + kEXPBIAS); + while (count > 0) { + if (count > inputArray.length) { + hasher.update(inputArray, inputArray.length); + count -= inputArray.length; + } else { + const finalArray = inputArray.slice(0, count); + hasher.update(finalArray, finalArray.length); + count = 0; + } + } + return hasher + .finish(false) + .split("") + .map(b => b.charCodeAt(0)); + } +} diff --git a/toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs b/toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..8f6edd626fef4d7e6e5a0c675d6544ef9e1f6b12 --- /dev/null +++ b/toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", +}); + +const logger = console.createInstance({ + maxLogLevel: "Info", + prefix: "TorProcessAndroid", +}); + +const TorOutgoingEvents = Object.freeze({ + start: "GeckoView:Tor:StartTor", + stop: "GeckoView:Tor:StopTor", +}); + +// The events we will listen to +const TorIncomingEvents = Object.freeze({ + started: "GeckoView:Tor:TorStarted", + startFailed: "GeckoView:Tor:TorStartFailed", + exited: "GeckoView:Tor:TorExited", +}); + +/** + * This class allows to start a tor process on Android devices. + * + * GeckoView does not include the facilities to start processes from JavaScript, + * therefore the actual implementation is written in Java, and this is just + * plumbing code over the global EventDispatcher. + */ +export class TorProcessAndroid { + /** + * The handle the Java counterpart uses to refer to the process we started. + * We use it to filter the exit events and make sure they refer to the daemon + * we are interested in. + */ + #processHandle = null; + /** + * The promise resolver we call when the Java counterpart sends the event that + * tor has started. + */ + #startResolve = null; + /** + * The promise resolver we call when the Java counterpart sends the event that + * it failed to start tor. + */ + #startReject = null; + + onExit = () => {}; + + get isRunning() { + return !!this.#processHandle; + } + + async start() { + // Generate the handle on the JS side so that it's ready in case it takes + // less to start the process than to propagate the success. + this.#processHandle = crypto.randomUUID(); + logger.info(`Starting new process with handle ${this.#processHandle}`); + // Let's declare it immediately, so that the Java side can do its stuff in + // an async manner and we avoid possible race conditions (at most we await + // an already resolved/rejected promise. + const startEventPromise = new Promise((resolve, reject) => { + this.#startResolve = resolve; + this.#startReject = reject; + }); + lazy.EventDispatcher.instance.registerListener( + this, + Object.values(TorIncomingEvents) + ); + let config; + try { + config = await lazy.EventDispatcher.instance.sendRequestForResult({ + type: TorOutgoingEvents.start, + handle: this.#processHandle, + tcpSocks: Services.prefs.getBoolPref( + "extensions.torlauncher.socks_port_use_tcp", + false + ), + }); + logger.debug("Sent the start event."); + } catch (e) { + this.forget(); + throw e; + } + await startEventPromise; + return config; + } + + forget() { + // Processes usually exit when we close the control port connection to them. + logger.trace(`Forgetting process ${this.#processHandle}`); + lazy.EventDispatcher.instance.sendRequestForResult({ + type: TorOutgoingEvents.stop, + handle: this.#processHandle, + }); + logger.debug("Sent the start event."); + this.#processHandle = null; + lazy.EventDispatcher.instance.unregisterListener( + this, + Object.values(TorIncomingEvents) + ); + } + + onEvent(event, data, _callback) { + if (data?.handle !== this.#processHandle) { + logger.debug(`Ignoring event ${event} with another handle`, data); + return; + } + logger.info(`Received an event ${event}`, data); + switch (event) { + case TorIncomingEvents.started: + this.#startResolve(); + break; + case TorIncomingEvents.startFailed: + this.#startReject(new Error(data.error)); + break; + case TorIncomingEvents.exited: + this.forget(); + if (this.#startReject !== null) { + this.#startReject(); + } + this.onExit(data.status); + break; + } + } +} diff --git a/toolkit/components/tor-launcher/TorProvider.sys.mjs b/toolkit/components/tor-launcher/TorProvider.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..d9f239790c4ead811756248e63f77d95036aa0db --- /dev/null +++ b/toolkit/components/tor-launcher/TorProvider.sys.mjs @@ -0,0 +1,1156 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs"; +import { TorParsers } from "resource://gre/modules/TorParsers.sys.mjs"; +import { TorProviderTopics } from "resource://gre/modules/TorProviderBuilder.sys.mjs"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", + TorController: "resource://gre/modules/TorControlPort.sys.mjs", + TorProcess: "resource://gre/modules/TorProcess.sys.mjs", + TorProcessAndroid: "resource://gre/modules/TorProcessAndroid.sys.mjs", + TorProxyType: "resource://gre/modules/TorSettings.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", +}); + +const logger = console.createInstance({ + maxLogLevelPref: "browser.tor_provider.log_level", + prefix: "TorProvider", +}); + +/** + * @typedef {object} ControlPortSettings An object with the settings to use for + * the control port. All the entries are optional, but an authentication + * mechanism and a communication method must be specified. + * @property {Uint8Array} [password] The clear text password as an array of + * bytes. It must always be defined, unless cookieFilePath is + * @property {string} [cookieFilePath] The path to the cookie file to use for + * authentication + * @property {nsIFile} [ipcFile] The nsIFile object with the path to a Unix + * socket to use for control socket + * @property {string} [host] The host to connect for a TCP control port + * @property {number} [port] The port number to use for a TCP control port + */ +/** + * @typedef {object} SocksSettings An object that includes the proxy settings to + * be configured in the browser. + * @property {boolean} [transproxy] If true, no proxy is configured + * @property {nsIFile} [ipcFile] The nsIFile object with the path to a Unix + * socket to use for an IPC proxy + * @property {string} [host] The host to connect for a TCP proxy + * @property {number} [port] The port number to use for a TCP proxy + */ +/** + * @typedef {object} LogEntry An object with a log message + * @property {string} timestamp The local date-time stamp at which we received the message + * @property {string} type The message level + * @property {string} msg The message + */ +/** + * Stores the data associated with a circuit node. + * + * @typedef NodeData + * @property {NodeFingerprint} fingerprint The node fingerprint + * @property {string[]} ipAddrs The ip addresses associated with this node + * @property {string?} bridgeType The bridge type for this node, or "" if the + * node is a bridge but the type is unknown, or null if this is not a bridge + * node + * @property {string?} regionCode An upper case 2-letter ISO3166-1 code for the + * first ip address, or null if there is no region. This should also be a + * valid BCP47 Region subtag + */ + +const Preferences = Object.freeze({ + ControlUseIpc: "extensions.torlauncher.control_port_use_ipc", + ControlHost: "extensions.torlauncher.control_host", + ControlPort: "extensions.torlauncher.control_port", + MaxLogEntries: "extensions.torlauncher.max_tor_log_entries", +}); + +/* Config Keys used to configure tor daemon */ +const TorConfigKeys = Object.freeze({ + useBridges: "UseBridges", + bridgeList: "Bridge", + socks4Proxy: "Socks4Proxy", + socks5Proxy: "Socks5Proxy", + socks5ProxyUsername: "Socks5ProxyUsername", + socks5ProxyPassword: "Socks5ProxyPassword", + httpsProxy: "HTTPSProxy", + httpsProxyAuthenticator: "HTTPSProxyAuthenticator", + reachableAddresses: "ReachableAddresses", + clientTransportPlugin: "ClientTransportPlugin", +}); + +/** + * This is a Tor provider for the C Tor daemon. + * + * It can start a new tor instance, or connect to an existing one. + * In the former case, it also takes its ownership by default. + */ +export class TorProvider { + /** + * The control port settings. + * + * @type {ControlPortSettings?} + */ + #controlPortSettings = null; + /** + * An instance of the tor controller. + * We take for granted that if it is not null, we connected to it and managed + * to authenticate. + * Public methods can use the #controller getter, which will throw an + * exception whenever the control port is not open. + * + * @type {TorController?} + */ + #controlConnection = null; + /** + * A helper that can be used to get the control port connection and assert it + * is open and it can be used. + * If this is not the case, this getter will throw. + * + * @returns {TorController} + */ + get #controller() { + if (!this.#controlConnection?.isOpen) { + throw new Error("Control port connection not available."); + } + return this.#controlConnection; + } + /** + * A function that can be called to cancel the current connection attempt. + */ + #cancelConnection = () => {}; + + /** + * The tor process we launched. + * + * @type {TorProcess} + */ + #torProcess = null; + + /** + * The settings for the SOCKS proxy. + * + * @type {SocksSettings?} + */ + #socksSettings = null; + + /** + * The logs we received over the control port. + * We store a finite number of log entries which can be configured with + * extensions.torlauncher.max_tor_log_entries. + * + * @type {LogEntry[]} + */ + #logs = []; + + #isBootstrapDone = false; + /** + * Keep the last warning to avoid broadcasting an async warning if it is the + * same one as the last broadcast. + */ + #lastWarning = {}; + + /** + * Stores the nodes of a circuit. Keys are cicuit IDs, and values are the node + * fingerprints. + * + * Theoretically, we could hook this map up to the new identity notification, + * but in practice it does not work. Tor pre-builds circuits, and the NEWNYM + * signal does not affect them. So, we might end up using a circuit that was + * built before the new identity but not yet used. If we cleaned the map, we + * risked of not having the data about it. + * + * @type {Map<CircuitID, Promise<NodeFingerprint[]>>} + */ + #circuits = new Map(); + /** + * The last used bridge, or null if bridges are not in use or if it was not + * possible to detect the bridge. This needs the user to have specified bridge + * lines with fingerprints to work. + * + * @type {NodeFingerprint?} + */ + #currentBridge = null; + + /** + * Starts a new tor process and connect to its control port, or connect to the + * control port of an existing tor daemon. + */ + async init() { + logger.debug("Initializing the Tor provider."); + + // These settings might be customized in the following steps. + if (TorLauncherUtil.isAndroid) { + this.#socksSettings = { transproxy: false }; + } else { + this.#socksSettings = TorLauncherUtil.getPreferredSocksConfiguration(); + logger.debug("Requested SOCKS configuration", this.#socksSettings); + } + + try { + await this.#setControlPortConfiguration(); + } catch (e) { + logger.error("We do not have a control port configuration", e); + throw e; + } + + if (this.#socksSettings.transproxy) { + logger.info("Transparent proxy required, not starting a Tor daemon."); + } else if (this.ownsTorDaemon) { + try { + await this.#startDaemon(); + } catch (e) { + logger.error("Failed to start the tor daemon", e); + throw e; + } + } else { + logger.debug( + "Not starting a tor daemon because we were requested not to." + ); + } + + try { + await this.#firstConnection(); + } catch (e) { + logger.error("Cannot connect to the control port", e); + throw e; + } + + if (this.ownsTorDaemon) { + try { + await lazy.TorSettings.initializedPromise; + await this.writeSettings(); + } catch (e) { + logger.warn( + "Failed to initialize TorSettings or to write our initial settings. Continuing the initialization anyway.", + e + ); + } + } + + TorLauncherUtil.setProxyConfiguration(this.#socksSettings); + + logger.info("The Tor provider is ready."); + + // If we are using an external Tor daemon, we might need to fetch circuits + // already, in case streams use them. Do not await because we do not want to + // block the intialization on this (it should not fail anyway...). + this.#fetchCircuits(); + } + + /** + * Close the connection to the tor daemon. + * When Tor is started by Tor Browser, it is configured to exit when the + * control connection is closed. Therefore, as a matter of facts, calling this + * function also makes the child Tor instance stop. + */ + uninit() { + logger.debug("Uninitializing the Tor provider."); + + if (this.#torProcess) { + this.#torProcess.forget(); + this.#torProcess.onExit = () => {}; + this.#torProcess = null; + } + + this.#closeConnection("Uninitializing the provider."); + } + + // Provider API + + /** + * Send settings to the tor daemon. + * + * This should only be called internally or by the TorSettings module. + */ + async writeSettings() { + // Fetch the current settings. + // We set the useTemporary parameter since we want to apply temporary + // bridges if they are available. + const settings = lazy.TorSettings.getSettings(true); + logger.debug("TorProvider.writeSettings", settings); + const torSettings = new Map(); + + // Bridges + const haveBridges = + settings.bridges?.enabled && !!settings.bridges.bridge_strings.length; + torSettings.set(TorConfigKeys.useBridges, haveBridges); + if (haveBridges) { + torSettings.set( + TorConfigKeys.bridgeList, + settings.bridges.bridge_strings + ); + } else { + torSettings.set(TorConfigKeys.bridgeList, null); + } + + // Proxy + torSettings.set(TorConfigKeys.socks4Proxy, null); + torSettings.set(TorConfigKeys.socks5Proxy, null); + torSettings.set(TorConfigKeys.socks5ProxyUsername, null); + torSettings.set(TorConfigKeys.socks5ProxyPassword, null); + torSettings.set(TorConfigKeys.httpsProxy, null); + torSettings.set(TorConfigKeys.httpsProxyAuthenticator, null); + if (settings.proxy && !settings.proxy.enabled) { + settings.proxy.type = null; + } + const address = settings.proxy?.address; + const port = settings.proxy?.port; + const username = settings.proxy?.username; + const password = settings.proxy?.password; + switch (settings.proxy?.type) { + case lazy.TorProxyType.Socks4: + torSettings.set(TorConfigKeys.socks4Proxy, `${address}:${port}`); + break; + case lazy.TorProxyType.Socks5: + torSettings.set(TorConfigKeys.socks5Proxy, `${address}:${port}`); + torSettings.set(TorConfigKeys.socks5ProxyUsername, username); + torSettings.set(TorConfigKeys.socks5ProxyPassword, password); + break; + case lazy.TorProxyType.HTTPS: + torSettings.set(TorConfigKeys.httpsProxy, `${address}:${port}`); + torSettings.set( + TorConfigKeys.httpsProxyAuthenticator, + `${username}:${password}` + ); + break; + } + + // Firewall + if (settings.firewall?.enabled) { + const reachableAddresses = settings.firewall.allowed_ports + .map(port => `*:${port}`) + .join(","); + torSettings.set(TorConfigKeys.reachableAddresses, reachableAddresses); + } else { + torSettings.set(TorConfigKeys.reachableAddresses, null); + } + + logger.debug("Mapped settings object", settings, torSettings); + + // Send settings to the tor process. + // NOTE: Since everything up to this point has been non-async, the order in + // which TorProvider.writeSettings is called should match the order in which + // the configuration is passed onto setConf. In turn, TorControlPort.setConf + // should similarly ensure that the configuration reaches the tor process in + // the same order. + // In particular, we do not want a race where an earlier call to + // TorProvider.writeSettings can be delayed and override a later call. + await this.#controller.setConf(Array.from(torSettings)); + } + + async flushSettings() { + await this.#controller.flushSettings(); + } + + /** + * Start the bootstrap process. + */ + async connect() { + await this.#controller.setNetworkEnabled(true); + if (this.#socksSettings.port === 0) { + // Enablign/disabling network resets also the SOCKS listener. + // So, every time we do it, we need to update the browser's configuration + // to use the updated port. + const settings = structuredClone(this.#socksSettings); + for (const listener of await this.#controller.getSocksListeners()) { + // When set to automatic port, ignore any IPC listener, as the intention + // was to use TCP. + if (listener.ipcPath) { + continue; + } + // The tor daemon can have any number of SOCKS listeners (see SocksPort + // in man 1 tor). We take for granted that any TCP one will work for us. + settings.host = listener.host; + settings.port = listener.port; + break; + } + TorLauncherUtil.setProxyConfiguration(settings); + } + this.#lastWarning = {}; + this.retrieveBootstrapStatus(); + } + + /** + * Stop the bootstrap process. + */ + async stopBootstrap() { + // Tell tor to disable use of the network; this should stop the bootstrap. + await this.#controller.setNetworkEnabled(false); + // We are not interested in waiting for this, nor in **catching its error**, + // so we do not await this. We just want to be notified when the bootstrap + // status is actually updated through observers. + this.retrieveBootstrapStatus(); + } + + /** + * Ask Tor to swtich to new circuits and clear the DNS cache. + */ + async newnym() { + await this.#controller.newnym(); + } + + /** + * Get the bridges Tor has been configured with. + * + * @returns {Bridge[]} The configured bridges + */ + async getBridges() { + // Ideally, we would not need this function, because we should be the one + // setting them with TorSettings. However, TorSettings is not notified of + // change of settings. So, asking tor directly with the control connection + // is the most reliable way of getting the configured bridges, at the + // moment. Also, we are using this for the circuit display, which should + // work also when we are not configuring the tor daemon, but just using it. + return this.#controller.getBridges(); + } + + /** + * Get the configured pluggable transports. + * + * @returns {PTInfo[]} An array with the info of all the configured pluggable + * transports. + */ + async getPluggableTransports() { + return this.#controller.getPluggableTransports(); + } + + /** + * Ask Tor its bootstrap phase. + * This function will also update the internal state when using an external + * tor daemon. + * + * @returns {object} An object with the bootstrap information received from + * Tor. Its keys might vary, depending on the input + */ + async retrieveBootstrapStatus() { + this.#processBootstrapStatus( + await this.#controller.getBootstrapPhase(), + false + ); + } + + /** + * Returns tha data about a relay or a bridge. + * + * @param {string} id The fingerprint of the node to get data about + * @returns {Promise<NodeData>} + */ + async getNodeInfo(id) { + const node = { + fingerprint: id, + ipAddrs: [], + bridgeType: null, + regionCode: null, + }; + const bridge = (await this.#controller.getBridges())?.find( + foundBridge => foundBridge.id?.toUpperCase() === id.toUpperCase() + ); + if (bridge) { + node.bridgeType = bridge.transport ?? ""; + // Attempt to get an IP address from bridge address string. + const ip = bridge.addr.match(/^\[?([^\]]+)\]?:\d+$/)?.[1]; + if (ip && !ip.startsWith("0.")) { + node.ipAddrs.push(ip); + } + } else { + node.ipAddrs = await this.#controller.getNodeAddresses(id); + } + // tor-browser#43116, tor-browser-build#41224: on Android, we do not ship + // the GeoIP databases to save some space. So skip it for now. + if (node.ipAddrs.length && !TorLauncherUtil.isAndroid) { + // Get the country code for the node's IP address. + try { + // Expect a 2-letter ISO3166-1 code, which should also be a valid + // BCP47 Region subtag. + const regionCode = await this.#controller.getIPCountry(node.ipAddrs[0]); + if (regionCode && regionCode !== "??") { + node.regionCode = regionCode.toUpperCase(); + } + } catch (e) { + logger.warn(`Cannot get a country for IP ${node.ipAddrs[0]}`, e); + } + } + return node; + } + + /** + * Add a private key to the Tor configuration. + * + * @param {string} address The address of the onion service + * @param {string} b64PrivateKey The private key of the service, in base64 + * @param {boolean} isPermanent Tell whether the key should be saved forever + */ + async onionAuthAdd(address, b64PrivateKey, isPermanent) { + await this.#controller.onionAuthAdd(address, b64PrivateKey, isPermanent); + } + + /** + * Remove a private key from the Tor configuration. + * + * @param {string} address The address of the onion service + */ + async onionAuthRemove(address) { + await this.#controller.onionAuthRemove(address); + } + + /** + * Retrieve the list of private keys. + * + * @returns {OnionAuthKeyInfo[]} The onion authentication keys known by the + * tor daemon + */ + async onionAuthViewKeys() { + return this.#controller.onionAuthViewKeys(); + } + + /** + * Returns captured log message as a text string (one message per line). + * + * @returns {string} The logs we collected from the tor daemon so far + */ + getLog() { + return this.#logs + .map(logObj => `${logObj.timestamp} [${logObj.type}] ${logObj.msg}`) + .join(TorLauncherUtil.isWindows ? "\r\n" : "\n"); + } + + /** + * @returns {boolean} true if we launched and control tor, false if we are + * using system tor. + */ + get ownsTorDaemon() { + return TorLauncherUtil.shouldStartAndOwnTor; + } + + get isBootstrapDone() { + return this.#isBootstrapDone; + } + + /** + * TODO: Rename to isReady once we remove finish the migration. + * + * @returns {boolean} true if we currently have a connection to the control + * port. We take for granted that if we have one, we authenticated to it, and + * so we have already verified we can send and receive data. + */ + get isRunning() { + return this.#controlConnection?.isOpen ?? false; + } + + /** + * Return the data about the current bridge, if any, or null. + * We can detect bridge only when the configured bridge lines include the + * fingerprints. + * + * @returns {NodeData?} The node information, or null if the first node + * is not a bridge, or no circuit has been opened, yet. + */ + get currentBridge() { + return this.#currentBridge; + } + + // Process management + + async #startDaemon() { + // TorProcess should be instanced once, then always reused and restarted + // only through the prompt it exposes when the controlled process dies. + if (this.#torProcess) { + logger.warn( + "Ignoring a request to start a tor daemon because one is already running." + ); + return; + } + + if (TorLauncherUtil.isAndroid) { + this.#torProcess = new lazy.TorProcessAndroid(); + } else { + this.#torProcess = new lazy.TorProcess( + this.#controlPortSettings, + this.#socksSettings + ); + } + // Use a closure instead of bind because we reassign #cancelConnection. + // Also, we now assign an exit handler that cancels the first connection, + // so that a sudden exit before the first connection is completed might + // still be handled as an initialization failure. + // But after the first connection is created successfully, we will change + // the exit handler to broadcast a notification instead. + this.#torProcess.onExit = () => { + this.#cancelConnection( + "The tor process exited before the first connection" + ); + }; + + logger.debug("Trying to start the tor process."); + const res = await this.#torProcess.start(); + if (TorLauncherUtil.isAndroid) { + logger.debug("Configuration from TorProcessAndriod", res); + this.#controlPortSettings = { + ipcFile: new lazy.FileUtils.File(res.controlPortPath), + cookieFilePath: res.cookieFilePath, + }; + this.#socksSettings = { + transproxy: false, + }; + if (res.socksPath) { + this.#socksSettings.ipcFile = new lazy.FileUtils.File(res.socksPath); + } else if (res.socksPort !== undefined) { + this.#socksSettings.host = res.socksHost ?? "127.0.0.1"; + this.#socksSettings.port = res.socksPort; + } else { + throw new Error( + "TorProcessAndroid did not return a valid SOCKS configuration." + ); + } + } + logger.info("Started a tor process"); + } + + // Control port setup and connection + + /** + * Read the control port settings from environment variables and from + * preferences. + */ + async #setControlPortConfiguration() { + logger.debug("Reading the control port configuration"); + const settings = {}; + + if (TorLauncherUtil.isAndroid) { + // We will populate the settings after having started the daemon. + return; + } + + const isWindows = Services.appinfo.OS === "WINNT"; + // Determine how Tor Launcher will connect to the Tor control port. + // Environment variables get top priority followed by preferences. + if (!isWindows && Services.env.exists("TOR_CONTROL_IPC_PATH")) { + const ipcPath = Services.env.get("TOR_CONTROL_IPC_PATH"); + settings.ipcFile = new lazy.FileUtils.File(ipcPath); + } else { + // Check for TCP host and port environment variables. + if (Services.env.exists("TOR_CONTROL_HOST")) { + settings.host = Services.env.get("TOR_CONTROL_HOST"); + } + if (Services.env.exists("TOR_CONTROL_PORT")) { + const port = parseInt(Services.env.get("TOR_CONTROL_PORT"), 10); + if (Number.isInteger(port) && port > 0 && port <= 65535) { + settings.port = port; + } + } + } + + const useIPC = + !isWindows && + Services.prefs.getBoolPref(Preferences.ControlUseIpc, false); + if (!settings.host && !settings.port && useIPC) { + settings.ipcFile = TorLauncherUtil.getTorFile("control_ipc", false); + } else { + if (!settings.host) { + settings.host = Services.prefs.getCharPref( + Preferences.ControlHost, + "127.0.0.1" + ); + } + if (!settings.port) { + settings.port = Services.prefs.getIntPref( + Preferences.ControlPort, + 9151 + ); + } + } + + if (Services.env.exists("TOR_CONTROL_PASSWD")) { + const password = Services.env.get("TOR_CONTROL_PASSWD"); + // As per 3.5 of control-spec.txt, AUTHENTICATE can use either a quoted + // string, or a sequence of hex characters. + // However, the password is hashed byte by byte, so we need to convert the + // string to its character codes, or the hex digits to actual bytes. + // Notice that Tor requires at least one hex character, without an upper + // limit, but it does not explicitly tell how to pad an odd number of hex + // characters, so we require the user to hand an even number of hex + // digits. + // We also want to enforce the authentication if we start the daemon. + // So, if a password is not valid (not a hex sequence and not a quoted + // string), or if it is empty (including the quoted empty string), we + // force a random password. + if ( + password.length >= 2 && + password[0] === '"' && + password[password.length - 1] === '"' + ) { + const encoder = new TextEncoder(); + settings.password = encoder.encode(TorParsers.unescapeString(password)); + } else if (/^([0-9a-fA-F]{2})+$/.test(password)) { + settings.password = new Uint8Array(password.length / 2); + for (let i = 0, j = 0; i < settings.password.length; i++, j += 2) { + settings.password[i] = parseInt(password.substring(j, j + 2), 16); + } + } + if (password && !settings.password?.length) { + logger.warn( + "Invalid password specified at TOR_CONTROL_PASSWD. " + + "You should put it in double quotes, or it should be a hex-encoded sequence. " + + "The password cannot be empty. " + + "A random password will be used, instead." + ); + } + } else if (Services.env.exists("TOR_CONTROL_COOKIE_AUTH_FILE")) { + const cookiePath = Services.env.get("TOR_CONTROL_COOKIE_AUTH_FILE"); + if (cookiePath) { + settings.cookieFilePath = cookiePath; + } + } + if ( + this.ownsTorDaemon && + !settings.password?.length && + !settings.cookieFilePath + ) { + settings.password = this.#generateRandomPassword(); + } + this.#controlPortSettings = settings; + logger.debug("Control port configuration read"); + } + + /** + * Start the first connection to the Tor daemon. + * This function should be called only once during the initialization. + */ + async #firstConnection() { + let canceled = false; + let timeout = 0; + const maxDelay = 10_000; + let delay = 5; + logger.debug("Connecting to the control port for the first time."); + this.#controlConnection = await new Promise((resolve, reject) => { + this.#cancelConnection = reason => { + canceled = true; + clearTimeout(timeout); + reject(new Error(reason)); + }; + const tryConnect = () => { + if (this.ownsTorDaemon && !this.#torProcess?.isRunning) { + reject(new Error("The controlled tor daemon is not running.")); + return; + } + this.#openControlPort() + .then(controller => { + this.#cancelConnection = () => {}; + // The cancel function should have already called reject. + if (!canceled) { + logger.info("Connected to the control port."); + resolve(controller); + } + }) + .catch(e => { + if (delay < maxDelay && !canceled) { + logger.info( + `Failed to connect to the control port. Trying again in ${delay}ms.`, + e + ); + timeout = setTimeout(tryConnect, delay); + delay *= 2; + } else { + reject(e); + } + }); + }; + tryConnect(); + }); + + // The following code will never throw, but we still want to wait for it + // before marking the provider as initialized. + + if (this.ownsTorDaemon) { + // The first connection cannot be canceled anymore, and the rest of the + // code is supposed not to fail. If the tor process exits, from now on we + // can only close the connection and broadcast a notification. + this.#torProcess.onExit = exitCode => { + logger.info(`The tor process exited with code ${exitCode}`); + this.#closeConnection("The tor process exited suddenly"); + Services.obs.notifyObservers(null, TorProviderTopics.ProcessExited); + }; + if (!TorLauncherUtil.shouldOnlyConfigureTor) { + await this.#takeOwnership(); + } + } + await this.#setupEvents(); + } + + /** + * Try to become the primary controller. This will make tor exit when our + * connection is closed. + * This function cannot fail or throw (any exception will be treated as a + * warning and just logged). + */ + async #takeOwnership() { + logger.debug("Taking the ownership of the tor process."); + try { + await this.#controlConnection.takeOwnership(); + } catch (e) { + logger.warn("Take ownership failed", e); + return; + } + try { + await this.#controlConnection.resetOwningControllerProcess(); + } catch (e) { + logger.warn("Clear owning controller process failed", e); + } + } + + /** + * Tells the Tor daemon which events we want to receive. + * This function will never throw. Any failure will be treated as a warning of + * a possibly degraded experience, not as an error. + */ + async #setupEvents() { + // We always listen to these events, because they are needed for the circuit + // display. + const events = ["CIRC", "STREAM"]; + if (this.ownsTorDaemon) { + events.push("STATUS_CLIENT", "NOTICE", "WARN", "ERR"); + // Do not await on the first bootstrap status retrieval, and do not + // propagate its errors. + this.#controlConnection + .getBootstrapPhase() + .then(status => this.#processBootstrapStatus(status, false)) + .catch(e => + logger.error("Failed to get the first bootstrap status", e) + ); + } + try { + logger.debug(`Setting events: ${events.join(" ")}`); + await this.#controlConnection.setEvents(events); + } catch (e) { + logger.error( + "We could not enable all the events we need. Tor Browser's functionalities might be reduced.", + e + ); + } + } + + /** + * Open a connection to the control port and authenticate to it. + * #setControlPortConfiguration must have been called before, as this function + * will follow the configuration set by it. + * + * @returns {Promise<TorController>} An authenticated TorController + */ + async #openControlPort() { + let controlPort; + if (this.#controlPortSettings.ipcFile) { + controlPort = lazy.TorController.fromIpcFile( + this.#controlPortSettings.ipcFile, + this + ); + } else { + controlPort = lazy.TorController.fromSocketAddress( + this.#controlPortSettings.host, + this.#controlPortSettings.port, + this + ); + } + try { + let password = this.#controlPortSettings.password; + if (password === undefined && this.#controlPortSettings.cookieFilePath) { + password = await this.#readAuthenticationCookie( + this.#controlPortSettings.cookieFilePath + ); + } + await controlPort.authenticate(password); + } catch (e) { + try { + controlPort.close(); + } catch (ec) { + // Tor already closes the control port when the authentication fails. + logger.debug( + "Expected exception when closing the control port for a failed authentication", + ec + ); + } + throw e; + } + return controlPort; + } + + /** + * Close the connection to the control port. + * + * @param {string} reason The reason for which we are closing the connection + * (used for logging and in case this ends up canceling the current connection + * attempt) + */ + #closeConnection(reason) { + this.#cancelConnection(reason); + if (this.#controlConnection) { + logger.info("Closing the control connection", reason); + try { + this.#controlConnection.close(); + } catch (e) { + logger.error("Failed to close the control port connection", e); + } + this.#controlConnection = null; + } else { + logger.trace( + "Requested to close an already closed control port connection" + ); + } + this.#isBootstrapDone = false; + this.#lastWarning = {}; + } + + // Authentication + + /** + * Read a cookie file to perform cookie-based authentication. + * + * @param {string} path The path to the cookie file + * @returns {Uint8Array} The content of the file in bytes + */ + async #readAuthenticationCookie(path) { + return IOUtils.read(path); + } + + /** + * @returns {Uint8Array} A random 16-byte password. + */ + #generateRandomPassword() { + const kPasswordLen = 16; + return crypto.getRandomValues(new Uint8Array(kPasswordLen)); + } + + /** + * Ask Tor the circuits it already knows to populate our circuit map with the + * circuits that were already open before we started listening for events. + */ + async #fetchCircuits() { + for (const { id, nodes } of await this.#controller.getCircuits()) { + this.onCircuitBuilt(id, nodes); + } + } + + // Notification handlers + + /** + * Receive and process a notification with the bootstrap status. + * + * @param {object} status The status object + */ + onBootstrapStatus(status) { + logger.debug("Received bootstrap status update", status); + this.#processBootstrapStatus(status, true); + } + + /** + * Process a bootstrap status to update the current state, and broadcast it + * to TorBootstrapStatus observers. + * + * @param {object} statusObj The status object that the controller returned. + * Its entries depend on what Tor sent to us. + * @param {boolean} isNotification We broadcast warnings only when we receive + * them through an asynchronous notification. + */ + #processBootstrapStatus(statusObj, isNotification) { + // Notify observers + Services.obs.notifyObservers(statusObj, TorProviderTopics.BootstrapStatus); + + if (statusObj.PROGRESS === 100) { + this.#isBootstrapDone = true; + return; + } + + this.#isBootstrapDone = false; + + // Can TYPE ever be ERR for STATUS_CLIENT? + if ( + isNotification && + statusObj.TYPE === "WARN" && + statusObj.RECOMMENDATION !== "ignore" + ) { + this.#notifyBootstrapError(statusObj); + } + } + + /** + * Broadcast a bootstrap warning or error. + * + * @param {object} statusObj The bootstrap status object with the error + */ + #notifyBootstrapError(statusObj) { + logger.error("Tor bootstrap error", statusObj); + + if ( + statusObj.TAG !== this.#lastWarning.phase || + statusObj.REASON !== this.#lastWarning.reason + ) { + this.#lastWarning.phase = statusObj.TAG; + this.#lastWarning.reason = statusObj.REASON; + + // FIXME: currently, this is observed only by TorBoostrapRequest. + // We should remove that class, and use an async method to do the + // bootstrap here. + // At that point, the lastWarning mechanism will probably not be necessary + // anymore, since the first error eligible for notification will as a + // matter of fact cancel the bootstrap. + Services.obs.notifyObservers( + { + phase: statusObj.TAG, + reason: statusObj.REASON, + summary: statusObj.SUMMARY, + warning: statusObj.WARNING, + }, + TorProviderTopics.BootstrapError + ); + } + } + + /** + * Handle a log message from the tor daemon. It will be added to the internal + * logs. If it is a warning or an error, a notification will be broadcast. + * + * @param {string} type The message type + * @param {string} msg The message + */ + onLogMessage(type, msg) { + if (type === "WARN" || type === "ERR") { + // Notify so that Copy Log can be enabled. + Services.obs.notifyObservers(null, TorProviderTopics.HasWarnOrErr); + } + + const timestamp = new Date() + .toISOString() + .replace("T", " ") + .replace("Z", ""); + + Services.obs.notifyObservers( + { type, msg, timestamp }, + TorProviderTopics.TorLog + ); + + const maxEntries = Services.prefs.getIntPref( + Preferences.MaxLogEntries, + 1000 + ); + if (maxEntries > 0 && this.#logs.length >= maxEntries) { + this.#logs.splice(0, 1); + } + + this.#logs.push({ type, msg, timestamp }); + switch (type) { + case "ERR": + logger.error(`[Tor error] ${msg}`); + break; + case "WARN": + logger.warn(`[Tor warning] ${msg}`); + break; + default: + logger.info(`[Tor ${type.toLowerCase()}] ${msg}`); + } + } + + /** + * Handle a notification that a new circuit has been built. + * If a change of bridge is detected (including a change from bridge to a + * normal guard), a notification is broadcast. + * + * @param {CircuitID} id The circuit ID + * @param {NodeFingerprint[]} nodes The nodes that compose the circuit + */ + async onCircuitBuilt(id, nodes) { + this.#circuits.set(id, nodes); + logger.debug(`Built tor circuit ${id}`, nodes); + // Ignore circuits of length 1, that are used, for example, to probe + // bridges. So, only store them, since we might see streams that use them, + // but then early-return. + if (nodes.length === 1) { + return; + } + + if (this.#currentBridge?.fingerprint !== nodes[0]) { + const nodeInfo = await this.getNodeInfo(nodes[0]); + let notify = false; + if (nodeInfo?.bridgeType) { + logger.info(`Bridge changed to ${nodes[0]}`); + this.#currentBridge = nodeInfo; + notify = true; + } else if (this.#currentBridge) { + logger.info("Bridges disabled"); + this.#currentBridge = null; + notify = true; + } + if (notify) { + Services.obs.notifyObservers(null, TorProviderTopics.BridgeChanged); + } + } + } + + /** + * Handle a notification of a circuit being closed. We use it to clean the + * internal data. + * + * @param {CircuitID} id The circuit id + */ + onCircuitClosed(id) { + logger.debug("Circuit closed event", id); + this.#circuits.delete(id); + } + + /** + * Handle a notification about a stream switching to the sentconnect status. + * + * @param {StreamID} streamId The ID of the stream that switched to the + * sentconnect status. + * @param {CircuitID} circuitId The ID of the circuit used by the stream + * @param {string} username The SOCKS username + * @param {string} password The SOCKS password + */ + async onStreamSentConnect(streamId, circuitId, username, password) { + if (!username || !password) { + return; + } + logger.debug("Stream sentconnect event", username, password, circuitId); + let circuit = this.#circuits.get(circuitId); + if (!circuit) { + circuit = new Promise((resolve, reject) => { + this.#controlConnection.getCircuits().then(circuits => { + for (const { id, nodes } of circuits) { + if (id === circuitId) { + resolve(nodes); + return; + } + // Opportunistically collect circuits, since we are iterating them. + this.#circuits.set(id, nodes); + } + logger.error( + `Seen a STREAM SENTCONNECT with circuit ${circuitId}, but Tor did not send information about it.` + ); + reject(); + }); + }); + this.#circuits.set(circuitId, circuit); + } + try { + circuit = await circuit; + } catch { + return; + } + Services.obs.notifyObservers( + { + wrappedJSObject: { + username, + password, + circuit, + }, + }, + TorProviderTopics.CircuitCredentialsMatched + ); + } +} diff --git a/toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs b/toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..f9dd275957a01628c26ef31c88b45e54be1dc980 --- /dev/null +++ b/toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs @@ -0,0 +1,238 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + TorProvider: "resource://gre/modules/TorProvider.sys.mjs", +}); + +export const TorProviderTopics = Object.freeze({ + ProcessExited: "TorProcessExited", + BootstrapStatus: "TorBootstrapStatus", + BootstrapError: "TorBootstrapError", + TorLog: "TorLog", + HasWarnOrErr: "TorLogHasWarnOrErr", + BridgeChanged: "TorBridgeChanged", + CircuitCredentialsMatched: "TorCircuitCredentialsMatched", +}); + +export const TorProviders = Object.freeze({ + none: 0, + tor: 1, +}); + +/** + * The factory to get a Tor provider. + * Currently we support only TorProvider, i.e., the one that interacts with + * C-tor through the control port protocol. + */ +export class TorProviderBuilder { + /** + * A promise with the instance of the provider that we are using. + * + * @type {Promise<TorProvider>?} + */ + static #provider = null; + + /** + * The observer that checks when the tor process exits, and reinitializes the + * provider. + * + * @type {Function} + */ + static #exitObserver = null; + + /** + * Tell whether the browser UI is ready. + * We ignore any errors until it is because we cannot show them. + * + * @type {boolean} + */ + static #uiReady = false; + + /** + * Initialize the provider of choice. + */ + static init() { + switch (this.providerType) { + case TorProviders.tor: + // Even though initialization of the initial TorProvider is + // asynchronous, we do not expect the caller to await it. The reason is + // that any call to build() will wait the initialization anyway (and + // re-throw any initialization error). + this.#initTorProvider(); + break; + case TorProviders.none: + lazy.TorLauncherUtil.setProxyConfiguration( + lazy.TorLauncherUtil.getPreferredSocksConfiguration() + ); + break; + default: + console.error(`Unknown tor provider ${this.providerType}.`); + break; + } + } + + /** + * Replace #provider with a new instance. + * + * @returns {Promise<TorProvider>} The new instance. + */ + static #initTorProvider() { + if (!this.#exitObserver) { + this.#exitObserver = this.#torExited.bind(this); + Services.obs.addObserver( + this.#exitObserver, + TorProviderTopics.ProcessExited + ); + } + + // NOTE: We need to ensure that the #provider is set as soon + // TorProviderBuilder.init is called. + // I.e. it should be safe to call + // TorProviderBuilder.init(); + // TorProviderBuilder.build(); + // without any await. + // + // Therefore, we await the oldProvider within the Promise rather than make + // #initTorProvider async. + // + // In particular, this is needed by TorConnect when the user has selected + // quickstart, in which case `TorConnect.init` will immediately request the + // provider. See tor-browser#41921. + this.#provider = this.#replaceTorProvider(this.#provider); + return this.#provider; + } + + /** + * Replace a TorProvider instance. Resolves once the TorProvider is + * initialised. + * + * @param {Promise<TorProvider>?} oldProvider - The previous's provider's + * promise, if any. + * @returns {TorProvider} The new TorProvider instance. + */ + static async #replaceTorProvider(oldProvider) { + try { + // Uninitialise the old TorProvider, if there is any. + (await oldProvider)?.uninit(); + } catch {} + const provider = new lazy.TorProvider(); + await provider.init(); + return provider; + } + + static uninit() { + this.#provider?.then(provider => { + provider.uninit(); + this.#provider = null; + }); + if (this.#exitObserver) { + Services.obs.removeObserver( + this.#exitObserver, + TorProviderTopics.ProcessExited + ); + this.#exitObserver = null; + } + } + + /** + * Build a provider. + * This method will wait for the system to be initialized, and allows you to + * catch also any initialization errors. + * + * @returns {TorProvider} A TorProvider instance + */ + static async build() { + if (!this.#provider && this.providerType === TorProviders.none) { + throw new Error( + "Tor Browser has been configured to use only the proxy functionalities." + ); + } else if (!this.#provider) { + throw new Error( + "The provider has not been initialized or already uninitialized." + ); + } + return this.#provider; + } + + /** + * Check if the provider has been succesfully initialized when the first + * browser window is shown. + * This is a workaround we need because ideally we would like the tor process + * to start as soon as possible, to avoid delays in the about:torconnect page, + * but we should modify TorConnect and about:torconnect to handle this case + * there with a better UX. + */ + static async firstWindowLoaded() { + // FIXME: Just integrate this with the about:torconnect or about:tor UI. + if ( + !lazy.TorLauncherUtil.shouldStartAndOwnTor || + this.providerType !== TorProviders.tor + ) { + // If we are not managing the Tor daemon we cannot restart it, so just + // early return. + return; + } + let running = false; + try { + const provider = await this.#provider; + // The initialization might have succeeded, but so far we have ignored any + // error notification. So, check that the process has not exited after the + // provider has been initialized successfully, but the UI was not ready + // yet. + running = provider.isRunning; + } catch { + // Not even initialized, running is already false. + } + while (!running && lazy.TorLauncherUtil.showRestartPrompt(true)) { + try { + await this.#initTorProvider(); + running = true; + } catch {} + } + // The user might have canceled the restart, but at this point the UI is + // ready in any case. + this.#uiReady = true; + } + + static async #torExited() { + if (!this.#uiReady) { + console.warn( + `Seen ${TorProviderTopics.ProcessExited}, but not doing anything because the UI is not ready yet.` + ); + return; + } + while (lazy.TorLauncherUtil.showRestartPrompt(false)) { + try { + await this.#initTorProvider(); + break; + } catch {} + } + } + + /** + * Return the provider chosen by the user. + * This function checks the TOR_PROVIDER environment variable and if it is a + * known provider, it returns its associated value. + * Otherwise, if it is not valid, the C tor implementation is chosen as the + * default one. + * + * @returns {number} An entry from TorProviders + */ + static get providerType() { + // TODO: Add a preference to permanently save this without and avoid always + // using an environment variable. + let provider = TorProviders.tor; + const kEnvName = "TOR_PROVIDER"; + if ( + Services.env.exists(kEnvName) && + Services.env.get(kEnvName) in TorProviders + ) { + provider = TorProviders[Services.env.get(kEnvName)]; + } + return provider; + } +} diff --git a/toolkit/components/tor-launcher/TorStartupService.sys.mjs b/toolkit/components/tor-launcher/TorStartupService.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..faab8a1040ef283eae49f22d69f00a3987f1eeda --- /dev/null +++ b/toolkit/components/tor-launcher/TorStartupService.sys.mjs @@ -0,0 +1,62 @@ +const lazy = {}; + +// We will use the modules only when the profile is loaded, so prefer lazy +// loading +ChromeUtils.defineESModuleGetters(lazy, { + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", + TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", +}); + +/* Browser observer topis */ +const BrowserTopics = Object.freeze({ + ProfileAfterChange: "profile-after-change", + QuitApplicationGranted: "quit-application-granted", +}); + +let gInited = false; + +/** + * This class is registered as an observer, and will be instanced automatically + * by Firefox. + * When it observes profile-after-change, it initializes whatever is needed to + * launch Tor. + */ +export class TorStartupService { + observe(aSubject, aTopic) { + if (aTopic === BrowserTopics.ProfileAfterChange && !gInited) { + this.#init(); + } else if (aTopic === BrowserTopics.QuitApplicationGranted) { + this.#uninit(); + } + } + + #init() { + Services.obs.addObserver(this, BrowserTopics.QuitApplicationGranted); + + lazy.TorSettings.init(); + + // Theoretically, build() is expected to await the initialization of the + // provider, and anything needing the Tor Provider should be able to just + // await on TorProviderBuilder.build(). + lazy.TorProviderBuilder.init(); + + lazy.TorConnect.init(); + + lazy.TorDomainIsolator.init(); + + gInited = true; + } + + #uninit() { + Services.obs.removeObserver(this, BrowserTopics.QuitApplicationGranted); + + lazy.TorDomainIsolator.uninit(); + + lazy.TorProviderBuilder.uninit(); + lazy.TorLauncherUtil.cleanupTempDirectories(); + lazy.TorSettings.uninit(); + } +} diff --git a/toolkit/components/tor-launcher/components.conf b/toolkit/components/tor-launcher/components.conf new file mode 100644 index 0000000000000000000000000000000000000000..7ddb93d2ae6c9516c6e70647d99a18dd9710b42c --- /dev/null +++ b/toolkit/components/tor-launcher/components.conf @@ -0,0 +1,10 @@ +Classes = [ + { + "cid": "{df46c65d-be2b-4d16-b280-69733329eecf}", + "contract_ids": [ + "@torproject.org/tor-startup-service;1" + ], + "esModule": "resource://gre/modules/TorStartupService.sys.mjs", + "constructor": "TorStartupService", + }, +] diff --git a/toolkit/components/tor-launcher/moz.build b/toolkit/components/tor-launcher/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..7629b13427af66219e711a8d7f975c5250f87204 --- /dev/null +++ b/toolkit/components/tor-launcher/moz.build @@ -0,0 +1,20 @@ +EXTRA_JS_MODULES += [ + "TorBootstrapRequest.sys.mjs", + "TorControlPort.sys.mjs", + "TorDomainIsolator.sys.mjs", + "TorLauncherUtil.sys.mjs", + "TorParsers.sys.mjs", + "TorProcess.sys.mjs", + "TorProcessAndroid.sys.mjs", + "TorProvider.sys.mjs", + "TorProviderBuilder.sys.mjs", + "TorStartupService.sys.mjs", +] + +XPCOM_MANIFESTS += [ + "components.conf", +] + +EXTRA_COMPONENTS += [ + "tor-launcher.manifest", +] diff --git a/toolkit/components/tor-launcher/tor-launcher.manifest b/toolkit/components/tor-launcher/tor-launcher.manifest new file mode 100644 index 0000000000000000000000000000000000000000..649f3419e8257a789ccbd3399a39bde984845cad --- /dev/null +++ b/toolkit/components/tor-launcher/tor-launcher.manifest @@ -0,0 +1 @@ +category profile-after-change TorStartupService @torproject.org/tor-startup-service;1 diff --git a/toolkit/components/torconnect/TorConnectChild.sys.mjs b/toolkit/components/torconnect/TorConnectChild.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..4b0d758128d9fbcbe3aa96a4b8c3a3545c8fda2a --- /dev/null +++ b/toolkit/components/torconnect/TorConnectChild.sys.mjs @@ -0,0 +1,84 @@ +// Copyright (c) 2021, The Tor Project, Inc. + +import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs"; + +/** + * Actor child class for the about:torconnect page. + * Most of the communication happens through RPM* calls, which do not go through + * this class. + */ +export class TorConnectChild extends RemotePageChild { + /** + * Whether we have redirected the page (after bootstrapping) or not. + * + * @type {boolean} + */ + #redirected = false; + + /** + * If bootstrapping is complete, or TorConnect is disabled, we redirect the + * page. + */ + async #maybeRedirect() { + if (await this.sendQuery("torconnect:should-show")) { + // Enabled and not yet bootstrapped. + return; + } + if (this.#redirected) { + return; + } + this.#redirected = true; + + const redirect = new URLSearchParams( + new URL(this.contentWindow.document.location.href).search + ).get("redirect"); + + // Fallback in error cases: + let replaceURI = "about:tor"; + try { + const url = new URL( + redirect + ? decodeURIComponent(redirect) + : // NOTE: We expect no redirect when address is entered manually, or + // about:torconnect is opened from preferences or urlbar. + // Go to the home page. + await this.sendQuery("torconnect:home-page") + ); + // Do not allow javascript URI. See tor-browser#41766 + if ( + ["about:", "file:", "https:", "http:"].includes(url.protocol) || + // Allow blank page. See tor-browser#42184. + // Blank page's are given as a chrome URL rather than "about:blank". + url.href === "chrome://browser/content/blanktab.html" + ) { + replaceURI = url.href; + } else { + console.error(`Scheme is not allowed "${redirect}"`); + } + } catch { + console.error(`Invalid redirect URL "${redirect}"`); + } + + // Replace the destination to prevent "about:torconnect" entering the + // history. + // NOTE: This is done here, in the window actor, rather than in content + // because we have the privilege to redirect to a "chrome:" uri here (for + // when the HomePage is set to be blank). + this.contentWindow.location.replace(replaceURI); + } + + actorCreated() { + super.actorCreated(); + // about:torconnect could need to be immediately redirected. E.g. if it is + // reached after bootstrapping. + this.#maybeRedirect(); + } + + receiveMessage(message) { + super.receiveMessage(message); + + if (message.name === "torconnect:stage-change") { + this.#maybeRedirect(); + } + } +} diff --git a/toolkit/components/torconnect/TorConnectParent.sys.mjs b/toolkit/components/torconnect/TorConnectParent.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..6ceed78e36c4f224dce4953d05a852446cedfe34 --- /dev/null +++ b/toolkit/components/torconnect/TorConnectParent.sys.mjs @@ -0,0 +1,137 @@ +// Copyright (c) 2021, The Tor Project, Inc. + +import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs"; +import { + TorConnect, + TorConnectTopics, +} from "resource://gre/modules/TorConnect.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + HomePage: "resource:///modules/HomePage.sys.jsm", +}); + +/* +This object is basically a marshalling interface between the TorConnect module +and a particular about:torconnect page +*/ + +/** + * Actor parent class for the about:torconnect page. + * It adapts and relays the messages from and to the TorConnect module. + */ +export class TorConnectParent extends JSWindowActorParent { + constructor(...args) { + super(...args); + + const self = this; + + // JSWindowActiveParent derived objects cannot observe directly, so create a + // member object to do our observing for us. + // + // This object converts the various lifecycle events from the TorConnect + // module, and maintains a state object which we pass down to our + // about:torconnect page, which uses the state object to update its UI. + this.torConnectObserver = { + observe(subject, topic) { + const obj = subject?.wrappedJSObject; + switch (topic) { + case TorConnectTopics.StageChange: + self.sendAsyncMessage("torconnect:stage-change", obj); + break; + case TorConnectTopics.BootstrapProgress: + self.sendAsyncMessage("torconnect:bootstrap-progress", obj); + break; + case TorConnectTopics.QuickstartChange: + self.sendAsyncMessage( + "torconnect:quickstart-change", + TorConnect.quickstart + ); + break; + } + }, + }; + + Services.obs.addObserver( + this.torConnectObserver, + TorConnectTopics.StageChange + ); + Services.obs.addObserver( + this.torConnectObserver, + TorConnectTopics.BootstrapProgress + ); + Services.obs.addObserver( + this.torConnectObserver, + TorConnectTopics.QuickstartChange + ); + } + + didDestroy() { + Services.obs.removeObserver( + this.torConnectObserver, + TorConnectTopics.StageChange + ); + Services.obs.removeObserver( + this.torConnectObserver, + TorConnectTopics.BootstrapProgress + ); + Services.obs.removeObserver( + this.torConnectObserver, + TorConnectTopics.QuickstartChange + ); + } + + async receiveMessage(message) { + switch (message.name) { + case "torconnect:should-show": + return Promise.resolve(TorConnect.shouldShowTorConnect); + case "torconnect:home-page": + // If there are multiple home pages, just load the first one. + return Promise.resolve(TorConnect.fixupURIs(lazy.HomePage.get())[0]); + case "torconnect:set-quickstart": + TorConnect.quickstart = message.data; + break; + case "torconnect:open-tor-preferences": + this.browsingContext.top.embedderElement.ownerGlobal.openPreferences( + "connection" + ); + break; + case "torconnect:view-tor-logs": + this.browsingContext.top.embedderElement.ownerGlobal.openPreferences( + "connection-viewlogs" + ); + break; + case "torconnect:restart": + Services.startup.quit( + Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit + ); + break; + case "torconnect:start-again": + TorConnect.startAgain(); + break; + case "torconnect:choose-region": + TorConnect.chooseRegion(); + break; + case "torconnect:begin-bootstrapping": + TorConnect.beginBootstrapping(message.data.regionCode); + break; + case "torconnect:cancel-bootstrapping": + TorConnect.cancelBootstrapping(); + break; + case "torconnect:get-init-args": + // Called on AboutTorConnect.init(), pass down all state data it needs + // to init. + return { + TorStrings, + Direction: Services.locale.isAppLocaleRTL ? "rtl" : "ltr", + CountryNames: TorConnect.countryNames, + stage: TorConnect.stage, + quickstartEnabled: TorConnect.quickstart, + }; + case "torconnect:get-country-codes": + return TorConnect.getCountryCodes(); + } + return undefined; + } +} diff --git a/toolkit/components/torconnect/content/aboutTorConnect.css b/toolkit/components/torconnect/content/aboutTorConnect.css new file mode 100644 index 0000000000000000000000000000000000000000..8ffd7898d7aefab9e904ab95410565a60d62e2d7 --- /dev/null +++ b/toolkit/components/torconnect/content/aboutTorConnect.css @@ -0,0 +1,419 @@ + +/* Copyright (c) 2021, The Tor Project, Inc. */ + +@import url("chrome://global/skin/error-pages.css"); +@import url("chrome://global/skin/tor-colors.css"); +@import url("chrome://global/skin/onion-pattern.css"); + +:root { + --onion-opacity: 1; + --onion-color: var(--card-outline-color); +} + +html { + width: 100%; + height: 100%; +} + +#breadcrumbs { + display: flex; + align-items: center; + margin: 0 0 24px 0; +} + +#breadcrumbs.hidden { + visibility: hidden; +} + +.breadcrumb-item, .breadcrumb-separator { + display: flex; + margin: 0; + margin-inline-start: 20px; + padding: 8px; +} + +.breadcrumb-item { + align-items: center; + cursor: pointer; + color: var(--in-content-text-color); + border-radius: 4px; +} + +.breadcrumb-item:hover { + color: var(--in-content-accent-color); + background-color: var(--in-content-button-background-hover); +} + +.breadcrumb-item:active { + color: var(--in-content-accent-color-active); + background-color: var(--in-content-button-background-active); +} + +.breadcrumb-separator { + width: 15px; + list-style-image: url("chrome://global/content/torconnect/arrow-right.svg"); +} + +.breadcrumb-separator:dir(rtl) { + scale: -1 1; +} + +.breadcrumb-icon { + display: inline list-item; + height: 16px; + list-style-position: inside; + -moz-context-properties: fill, stroke; + fill: currentColor; + stroke: currentColor; +} + +.breadcrumb-item.active { + color: var(--in-content-accent-color); +} + +.breadcrumb-item.disabled, .breadcrumb-item.disabled:hover, .breadcrumb-item.disabled:active { + color: var(--in-content-text-color); + opacity: 0.4; + cursor: default; +} + +.breadcrumb-item.error { + color: var(--in-content-danger-button-background); +} + +.breadcrumb-item.error:hover { + color: var(--in-content-danger-button-background-hover); +} + +.breadcrumb-item.error:active { + color: var(--in-content-danger-button-background-active); +} + +.breadcrumb-item.hidden, .breadcrumb-separator.hidden { + display: none; +} + +#connect-to-tor { + margin-inline-start: 0; +} + +#connect-to-tor-icon { + list-style-image: url("chrome://global/content/torconnect/tor-connect.svg"); +} + +#connection-assist-icon { + list-style-image: url("chrome://global/content/torconnect/tor-connect-broken.svg"); +} + +#location-settings-icon { + list-style-image: url("chrome://global/content/torconnect/globe.svg"); +} + +#try-bridge { + cursor: default; +} + +#try-bridge-icon { + list-style-image: url("chrome://global/content/torconnect/bridge.svg"); +} + +#locationDropdownLabel { + margin-block: auto; + margin-inline: 4px; +} + +#locationDropdownLabel.error { + color: var(--text-color-error) +} + +/* this follows similar css in error-pages.css for buttons */ +@media only screen and (min-width: 480px) { + form#locationDropdown { + margin-inline: 4px; + /* subtracting out the margin is needeed because by + default forms have different margins than buttons */ + max-width: calc(100% - 8px); + } +} + +@media only screen and (max-width: 480px) { + #tryAgainButton { + margin-top: 4px; + } +} + +form#locationDropdown { + width: 240px; +} + +form#locationDropdown select { + max-width: 100%; + margin-inline: 0; + font-weight: 700; +} + +:root { + --progressbar-shadow-start: rgba(255, 255, 255, 0.7); + --progressbar-gradient: linear-gradient(90deg, #FC00FF 0%, #00DBDE 50%, #FC00FF 100%); +} + +@media (prefers-color-scheme: dark) { + :root { + --progressbar-shadow-start: rgba(28, 27, 34, 0.7); + } +} + +#progressBar:not([hidden]) { + position: fixed; + inset-block-start: 0; + inset-inline: 0; + display: grid; + --progress-percent: 0%; + --progress-animation: progressAnimation 5s ease infinite; + --progress-bar-height: 7px; +} + +#progressBar > * { + grid-area: 1 / 1; +} + +#progressBarBackground { + width: 100%; + height: var(--progress-bar-height); + background: var(--in-content-box-info-background); +} + +#progressBackground { + z-index: 1; + width: var(--progress-percent); + height: 66px; + margin-block-start: -26px; + background-image: + linear-gradient(var(--progressbar-shadow-start), var(--in-content-page-background) 100%), + var(--progressbar-gradient); + animation: var(--progress-animation); + filter: blur(5px); + border-end-end-radius: 33px; +} + +#progressSolid { + z-index: 2; + width: var(--progress-percent); + height: var(--progress-bar-height); + border-start-end-radius: calc(var(--progress-bar-height) / 2); + border-end-end-radius: calc(var(--progress-bar-height) / 2); + background-image: var(--progressbar-gradient); + animation: var(--progress-animation); +} + +#progressBackground, #progressSolid { + background-size: 200% 100%; +} + +@keyframes progressAnimation { + 0% { + background-position: 200%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +@keyframes progressAnimation { + 0% { + background-position: 200%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +#connectPageContainer { + margin-top: 10vh; + width: 100%; + max-width: 45em; +} + +#quickstartToggle { + width: max-content; +} + +/* mirrors p element spacing */ +#viewLogButton { + margin: 1em 0; +} + +body.aboutTorConnect { + justify-content: space-between; + /* Always reserve 150px for the background, plus 15px padding with content. */ + padding-block-end: calc(var(--onion-pattern-height) + 15px); +} + +body.aboutTorConnect .title { + background-image: url("chrome://global/content/torconnect/tor-connect.svg"); + -moz-context-properties: stroke, fill, fill-opacity; + fill-opacity: var(--onion-opacity); + fill: var(--onion-color); + stroke: var(--onion-color); + /* Make sure there is no padding between the title and #breadcrumbs. */ + padding-block-start: 0; +} + +body.aboutTorConnect .title.offline { + background-image: url("chrome://global/content/torconnect/connection-failure.svg"); +} + +body.aboutTorConnect .title:is(.assist, .final) { + background-image: url("chrome://global/content/torconnect/tor-connect-broken.svg"); +} + +body.aboutTorConnect .title.location { + background-image: url("chrome://global/content/torconnect/connection-location.svg"); + stroke: var(--in-content-warning-icon-color); +} + +/* Android-specific CSS, to be removed when we use only the native UI. */ +:root { + --android-dark-accents-buttons: #9059FF; + --android-dark-background-secondary: #E1E0E7; + --android-dark-text-primary: #FBFBFE; + --android-light-text-primary: #15141A; +} + +[hidden=true] { + display: none !important; +} + +body.android { + --onion-color: var(--android-dark-text-primary); + width: 100%; + height: 100%; + box-sizing: border-box; + margin: 0; + padding: 0 24px !important; + color: var(--onion-color); + background: linear-gradient(194deg, #692E9D -0.93%, #393270 48.91%); + font: menu; + font-size: 14px; + display: flex; +} + +.android #connectPageContainer { + max-width: none; + display: flex; + flex-direction: column; + flex: 1; +} + +.android #breadcrumbs { + display: none; +} + +.android #text-container { + display: flex; + flex-direction: column; + flex: 1; +} + +.android .title { + background-position: left 0; + background-repeat: no-repeat; + background-size: 40px; + padding-top: 64px; + font-size: 22px; + line-height: 28px; +} + +.android h1 { + font-weight: normal; + font-size: 100%; + margin: 0 0 16px 0; +} + +.android p { + margin: 0; + padding-bottom: 8px; + line-height: 20px; +} + +.android #quickstartContainer { + margin-top: 24px; +} + +.android .button-container { + display: flex; + flex: 1; + flex-direction: column; +} + +.android #locationDropdown { + width: 100%; + max-width: none; + margin: 0; +} + +.android select { + background: transparent; + border: none; + border-bottom: 1px solid var(--android-dark-text-primary); + color: var(--android-dark-text-primary); + display: block; + width: 100%; + margin-top: 10px; + padding: 8px; +} + +.android #buttonPadding { + flex: 1; +} + +body:not(.android) #connectButtonContainer { + /* Use the .button-container context */ + display: contents; +} + +.android #connectButtonContainer { + width: 100%; + padding-bottom: 18px; + display: grid; +} + +/* Be sure not to match the togglee */ +.android #connectButtonContainer button { + display: block; + width: 100%; + margin: 4px 0; + padding: 11px 30px; + font-size: 14px; + font-weight: 500; + border: none; + border-radius: 4px; +} + +.android #connectButton, .android #tryBridgeButton, .android #configureButton.primary { + color: var(--android-dark-text-primary); + background-color: var(--android-dark-accents-buttons); +} + +.android #configureButton { + order: 1; +} + +.android #restartButton { + order: 2; +} + +.android #restartButton, .android #cancelButton, .android #configureButton { + color: var(--android-light-text-primary); + background-color: var(--android-dark-background-secondary); +} + +.android .onion-pattern-container { + display: none; +} diff --git a/toolkit/components/torconnect/content/aboutTorConnect.html b/toolkit/components/torconnect/content/aboutTorConnect.html new file mode 100644 index 0000000000000000000000000000000000000000..5eab0bfea4c581c5424ef40718cdd7584ebd2043 --- /dev/null +++ b/toolkit/components/torconnect/content/aboutTorConnect.html @@ -0,0 +1,94 @@ +<!-- Copyright (c) 2021, The Tor Project, Inc. --> +<!DOCTYPE html> +<html> + <head> + <meta + http-equiv="Content-Security-Policy" + content="default-src chrome:; object-src 'none'" + /> + <meta name="viewport" content="width=device-width" /> + <link + rel="stylesheet" + href="chrome://global/content/torconnect/aboutTorConnect.css" + type="text/css" + media="all" + /> + + <script + type="module" + src="chrome://global/content/elements/moz-toggle.mjs" + ></script> + </head> + <body class="aboutTorConnect onion-pattern-background"> + <div id="progressBar" hidden="hidden"> + <div id="progressSolid"></div> + <div id="progressBackground"></div> + <div id="progressBarBackground"></div> + </div> + <div id="connectPageContainer" class="container"> + <div id="breadcrumbs" class="hidden"> + <span id="connect-to-tor" class="breadcrumb-item"> + <span id="connect-to-tor-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> + </span> + <span + id="connection-assist-separator" + class="breadcrumb-separator breadcrumb-icon" + ></span> + <span id="connection-assist" class="breadcrumb-item"> + <span id="connection-assist-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> + </span> + <span + id="try-bridge-separator" + class="breadcrumb-separator breadcrumb-icon" + ></span> + <span id="try-bridge" class="breadcrumb-item"> + <span id="try-bridge-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> + </span> + </div> + <div id="text-container"> + <div class="title"> + <h1 class="title-text"></h1> + </div> + <div id="connectLongContent"> + <p id="connectLongContentText"></p> + </div> + <div id="connectShortDesc"> + <p id="connectShortDescText"></p> + </div> + + <button id="viewLogButton"></button> + + <div id="quickstartContainer"> + <moz-toggle id="quickstartToggle" label-align-after=""></moz-toggle> + </div> + + <div class="button-container"> + <label id="locationDropdownLabel" for="countries"></label> + <form id="locationDropdown" hidden="true"> + <select id="countries"></select> + </form> + <span id="buttonPadding"></span> + <span id="connectButtonContainer"> + <button id="restartButton" hidden="true"></button> + <button id="configureButton" hidden="true"></button> + <button id="cancelButton" hidden="true"></button> + <button + id="connectButton" + hidden="true" + class="tor-button" + ></button> + <button + id="tryBridgeButton" + hidden="true" + class="tor-button" + ></button> + </span> + </div> + </div> + </div> + <script src="chrome://global/content/torconnect/aboutTorConnect.js"></script> + </body> +</html> diff --git a/toolkit/components/torconnect/content/aboutTorConnect.js b/toolkit/components/torconnect/content/aboutTorConnect.js new file mode 100644 index 0000000000000000000000000000000000000000..da27e1d8c002320d15d1c7a15a4bb28ed46956c5 --- /dev/null +++ b/toolkit/components/torconnect/content/aboutTorConnect.js @@ -0,0 +1,811 @@ +// Copyright (c) 2021, The Tor Project, Inc. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* eslint-env mozilla/remote-page */ + +// populated in AboutTorConnect.init() +let TorStrings = {}; + +const UIStates = Object.freeze({ + ConnectToTor: "ConnectToTor", + Offline: "Offline", + ConnectionAssist: "ConnectionAssist", + CouldNotLocate: "CouldNotLocate", + LocationConfirm: "LocationConfirm", + FinalError: "FinalError", +}); + +const BreadcrumbStatus = Object.freeze({ + Hidden: "hidden", + Disabled: "disabled", + Default: "default", + Active: "active", + Error: "error", +}); + +/** + * The controller for the about:torconnect page. + */ +class AboutTorConnect { + selectors = Object.freeze({ + textContainer: { + title: "div.title", + titleText: "h1.title-text", + longContentText: "#connectLongContentText", + }, + progress: { + description: "p#connectShortDescText", + meter: "div#progressBar", + }, + breadcrumbs: { + container: "#breadcrumbs", + connectToTor: { + link: "#connect-to-tor", + label: "#connect-to-tor .breadcrumb-label", + }, + connectionAssist: { + separator: "#connection-assist-separator", + link: "#connection-assist", + label: "#connection-assist .breadcrumb-label", + }, + tryBridge: { + separator: "#try-bridge-separator", + link: "#try-bridge", + label: "#try-bridge .breadcrumb-label", + }, + }, + viewLog: { + button: "#viewLogButton", + }, + quickstart: { + container: "div#quickstartContainer", + toggle: "#quickstartToggle", + }, + buttons: { + restart: "button#restartButton", + configure: "button#configureButton", + cancel: "button#cancelButton", + connect: "button#connectButton", + tryBridge: "button#tryBridgeButton", + locationDropdownLabel: "#locationDropdownLabel", + locationDropdown: "#locationDropdown", + locationDropdownSelect: "#locationDropdown select", + }, + }); + + elements = Object.freeze({ + title: document.querySelector(this.selectors.textContainer.title), + titleText: document.querySelector(this.selectors.textContainer.titleText), + longContentText: document.querySelector( + this.selectors.textContainer.longContentText + ), + progressDescription: document.querySelector( + this.selectors.progress.description + ), + progressMeter: document.querySelector(this.selectors.progress.meter), + breadcrumbContainer: document.querySelector( + this.selectors.breadcrumbs.container + ), + connectToTorLink: document.querySelector( + this.selectors.breadcrumbs.connectToTor.link + ), + connectToTorLabel: document.querySelector( + this.selectors.breadcrumbs.connectToTor.label + ), + connectionAssistSeparator: document.querySelector( + this.selectors.breadcrumbs.connectionAssist.separator + ), + connectionAssistLink: document.querySelector( + this.selectors.breadcrumbs.connectionAssist.link + ), + connectionAssistLabel: document.querySelector( + this.selectors.breadcrumbs.connectionAssist.label + ), + tryBridgeSeparator: document.querySelector( + this.selectors.breadcrumbs.tryBridge.separator + ), + tryBridgeLink: document.querySelector( + this.selectors.breadcrumbs.tryBridge.link + ), + tryBridgeLabel: document.querySelector( + this.selectors.breadcrumbs.tryBridge.label + ), + viewLogButton: document.querySelector(this.selectors.viewLog.button), + quickstartContainer: document.querySelector( + this.selectors.quickstart.container + ), + quickstartToggle: document.querySelector(this.selectors.quickstart.toggle), + restartButton: document.querySelector(this.selectors.buttons.restart), + configureButton: document.querySelector(this.selectors.buttons.configure), + cancelButton: document.querySelector(this.selectors.buttons.cancel), + connectButton: document.querySelector(this.selectors.buttons.connect), + locationDropdownLabel: document.querySelector( + this.selectors.buttons.locationDropdownLabel + ), + locationDropdown: document.querySelector( + this.selectors.buttons.locationDropdown + ), + locationDropdownSelect: document.querySelector( + this.selectors.buttons.locationDropdownSelect + ), + tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge), + }); + + selectedLocation; + shownStage = null; + + locations = {}; + + beginBootstrapping() { + RPMSendAsyncMessage("torconnect:begin-bootstrapping", {}); + } + + beginAutoBootstrapping(regionCode) { + RPMSendAsyncMessage("torconnect:begin-bootstrapping", { + regionCode, + }); + } + + cancelBootstrapping() { + RPMSendAsyncMessage("torconnect:cancel-bootstrapping"); + } + + /* + Element helper methods + */ + + show(element, primary = false) { + element.classList.toggle("primary", primary); + element.removeAttribute("hidden"); + } + + hide(element) { + element.setAttribute("hidden", "true"); + } + + hideButtons() { + this.hide(this.elements.quickstartContainer); + this.hide(this.elements.restartButton); + this.hide(this.elements.configureButton); + this.hide(this.elements.cancelButton); + this.hide(this.elements.connectButton); + this.hide(this.elements.locationDropdownLabel); + this.hide(this.elements.locationDropdown); + this.hide(this.elements.tryBridgeButton); + } + + populateLocations() { + const selectCountryRegion = document.createElement("option"); + selectCountryRegion.textContent = TorStrings.torConnect.selectCountryRegion; + selectCountryRegion.value = ""; + + // get all codes and names from TorStrings + const locationNodes = []; + for (const [code, name] of Object.entries(this.locations)) { + let option = document.createElement("option"); + option.value = code; + option.textContent = name; + locationNodes.push(option); + } + // locale sort by name + locationNodes.sort((left, right) => + left.textContent.localeCompare(right.textContent) + ); + this.elements.locationDropdownSelect.append( + selectCountryRegion, + ...locationNodes + ); + } + + populateFrequentLocations(locations) { + this.removeFrequentLocations(); + if (!locations || !locations.length) { + return; + } + + const locationNodes = []; + for (const code of locations) { + const option = document.createElement("option"); + option.value = code; + option.className = "frequent-location"; + // codes (partially) come from rdsys service, so make sure we have a + // string defined for it + let name = this.locations[code]; + if (!name) { + name = code; + } + option.textContent = name; + locationNodes.push(option); + } + // locale sort by name + locationNodes.sort((left, right) => + left.textContent.localeCompare(right.textContent) + ); + + const frequentGroup = document.createElement("optgroup"); + frequentGroup.setAttribute( + "label", + TorStrings.torConnect.frequentLocations + ); + frequentGroup.className = "frequent-location"; + const locationGroup = document.createElement("optgroup"); + locationGroup.setAttribute("label", TorStrings.torConnect.otherLocations); + locationGroup.className = "frequent-location"; + // options[0] is either "Select Country or Region" or "Automatic" + this.elements.locationDropdownSelect.options[0].after( + frequentGroup, + ...locationNodes, + locationGroup + ); + } + + removeFrequentLocations() { + const select = this.elements.locationDropdownSelect; + for (const option of select.querySelectorAll(".frequent-location")) { + option.remove(); + } + } + + validateLocation() { + const selectedIndex = this.elements.locationDropdownSelect.selectedIndex; + const selectedOption = + this.elements.locationDropdownSelect.options[selectedIndex]; + if (!selectedOption.value) { + this.elements.tryBridgeButton.setAttribute("disabled", "disabled"); + } else { + this.elements.tryBridgeButton.removeAttribute("disabled"); + } + } + + setTitle(title, className) { + this.elements.titleText.textContent = title; + this.elements.title.className = "title"; + if (className) { + this.elements.title.classList.add(className); + } + document.title = title; + } + + setLongText(...args) { + this.elements.longContentText.textContent = ""; + this.elements.longContentText.append(...args); + } + + setBreadcrumbsStatus(connectToTor, connectionAssist, tryBridge) { + this.elements.breadcrumbContainer.classList.remove("hidden"); + const elems = [ + [this.elements.connectToTorLink, connectToTor, null], + [ + this.elements.connectionAssistLink, + connectionAssist, + this.elements.connectionAssistSeparator, + ], + [ + this.elements.tryBridgeLink, + tryBridge, + this.elements.tryBridgeSeparator, + ], + ]; + elems.forEach(([elem, status, separator]) => { + elem.classList.remove(BreadcrumbStatus.Hidden); + elem.classList.remove(BreadcrumbStatus.Disabled); + elem.classList.remove(BreadcrumbStatus.Active); + elem.classList.remove(BreadcrumbStatus.Error); + if (status !== "") { + elem.classList.add(status); + } + separator?.classList.toggle("hidden", status === BreadcrumbStatus.Hidden); + }); + } + + hideBreadcrumbs() { + this.elements.breadcrumbContainer.classList.add("hidden"); + } + + getLocalizedStatus(status) { + const aliases = { + conn_dir: "conn", + handshake_dir: "onehop_create", + conn_or: "enough_dirinfo", + handshake_or: "ap_conn", + }; + if (status in aliases) { + status = aliases[status]; + } + return TorStrings.torConnect.bootstrapStatus[status] ?? status; + } + + getMaybeLocalizedError(error) { + switch (error.code) { + case "Offline": + return TorStrings.torConnect.offline; + case "BootstrapError": { + if (!error.phase || !error.reason) { + return TorStrings.torConnect.torBootstrapFailed; + } + let status = this.getLocalizedStatus(error.phase); + const reason = + TorStrings.torConnect.bootstrapWarning[error.reason] ?? error.reason; + return TorStrings.torConnect.bootstrapFailedDetails + .replace("%1$S", status) + .replace("%2$S", reason); + } + case "CannotDetermineCountry": + return TorStrings.torConnect.cannotDetermineCountry; + case "NoSettingsForCountry": + return TorStrings.torConnect.noSettingsForCountry; + case "AllSettingsFailed": + return TorStrings.torConnect.autoBootstrappingAllFailed; + case "ExternaError": + // A standard JS error, or something for which we do probably do not + // have a translation. Returning the original message is the best we can + // do. + return error.message; + default: + console.warn(`Unknown error code: ${error.code}`, error); + return error.message || error.code; + } + } + + /* + These methods update the UI based on the current TorConnect state + */ + + updateStage(stage) { + if (stage.name === this.shownStage) { + return; + } + + this.shownStage = stage.name; + this.selectedLocation = stage.defaultRegion; + + let showProgress = false; + let showLog = false; + switch (stage.name) { + case "Disabled": + console.error("Should not be open when TorConnect is disabled"); + break; + case "Loading": + case "Start": + // Loading is not currnetly handled, treat the same as "Start", but UI + // will be unresponsive. + this.showStart(stage.tryAgain, stage.potentiallyBlocked); + break; + case "Bootstrapping": + showProgress = true; + this.showBootstrapping(stage.bootstrapTrigger, stage.tryAgain); + break; + case "Offline": + showLog = true; + this.showOffline(); + break; + case "ChooseRegion": + showLog = true; + this.showChooseRegion(stage.error); + break; + case "RegionNotFound": + showLog = true; + this.showRegionNotFound(); + break; + case "ConfirmRegion": + showLog = true; + this.showConfirmRegion(stage.error); + break; + case "FinalError": + showLog = true; + this.showFinalError(stage.error); + break; + case "Bootstrapped": + showProgress = true; + this.showBootstrapped(); + break; + default: + console.error(`Unknown stage ${stage.name}`); + break; + } + + if (showProgress) { + this.show(this.elements.progressMeter); + } else { + this.hide(this.elements.progressMeter); + } + + this.updateBootstrappingStatus(stage.bootstrappingStatus); + + if (showLog) { + this.show(this.elements.viewLogButton); + } else { + this.hide(this.elements.viewLogButton); + } + } + + updateBootstrappingStatus(data) { + this.elements.progressMeter.style.setProperty( + "--progress-percent", + `${data.progress}%` + ); + if (this.shownStage === "Bootstrapping" && data.hasWarning) { + // When bootstrapping starts, we hide the log button, but we re-show it if + // we get a warning. + this.show(this.elements.viewLogButton); + } + } + + updateQuickstart(enabled) { + this.elements.quickstartToggle.pressed = enabled; + } + + showBootstrapped() { + this.setTitle(TorStrings.torConnect.torConnected, ""); + this.setLongText(TorStrings.settings.torPreferencesDescription); + this.elements.progressDescription.textContent = ""; + this.hideButtons(); + } + + showStart(tryAgain, potentiallyBlocked) { + this.setTitle(TorStrings.torConnect.torConnect, ""); + this.setLongText(TorStrings.settings.torPreferencesDescription); + this.elements.progressDescription.textContent = ""; + this.hideButtons(); + this.show(this.elements.quickstartContainer); + this.show(this.elements.configureButton); + this.show(this.elements.connectButton, true); + this.elements.connectButton.focus(); + if (tryAgain) { + this.elements.connectButton.textContent = TorStrings.torConnect.tryAgain; + } + if (potentiallyBlocked) { + this.setBreadcrumbsStatus( + BreadcrumbStatus.Active, + BreadcrumbStatus.Default, + BreadcrumbStatus.Disabled + ); + } + } + + showBootstrapping(trigger, tryAgain) { + let title = ""; + let description = ""; + const breadcrumbs = [ + BreadcrumbStatus.Disabled, + BreadcrumbStatus.Disabled, + BreadcrumbStatus.Disabled, + ]; + switch (trigger) { + case "Start": + case "Offline": + breadcrumbs[0] = BreadcrumbStatus.Active; + title = tryAgain + ? TorStrings.torConnect.tryAgain + : TorStrings.torConnect.torConnecting; + description = TorStrings.settings.torPreferencesDescription; + break; + case "ChooseRegion": + breadcrumbs[2] = BreadcrumbStatus.Active; + title = TorStrings.torConnect.tryingBridge; + description = TorStrings.torConnect.assistDescription; + break; + case "RegionNotFound": + breadcrumbs[2] = BreadcrumbStatus.Active; + title = TorStrings.torConnect.tryingBridgeAgain; + description = TorStrings.torConnect.errorLocationDescription; + break; + case "ConfirmRegion": + breadcrumbs[2] = BreadcrumbStatus.Active; + title = TorStrings.torConnect.tryingBridgeAgain; + description = TorStrings.torConnect.isLocationCorrectDescription; + break; + default: + console.warn("Unrecognized bootstrap trigger", trigger); + break; + } + this.setTitle(title, ""); + this.showConfigureConnectionLink(description); + this.elements.progressDescription.textContent = ""; + if (tryAgain) { + this.setBreadcrumbsStatus(...breadcrumbs); + } else { + this.hideBreadcrumbs(); + } + this.hideButtons(); + this.show(this.elements.cancelButton); + this.elements.cancelButton.focus(); + } + + showOffline() { + this.setTitle(TorStrings.torConnect.noInternet, "offline"); + this.setLongText(TorStrings.torConnect.noInternetDescription); + this.elements.progressDescription.textContent = + TorStrings.torConnect.offline; + this.setBreadcrumbsStatus( + BreadcrumbStatus.Default, + BreadcrumbStatus.Active, + BreadcrumbStatus.Hidden + ); + this.hideButtons(); + this.show(this.elements.configureButton); + this.show(this.elements.connectButton, true); + this.elements.connectButton.textContent = TorStrings.torConnect.tryAgain; + } + + showChooseRegion(error) { + this.setTitle(TorStrings.torConnect.couldNotConnect, "assist"); + this.showConfigureConnectionLink(TorStrings.torConnect.assistDescription); + this.elements.progressDescription.textContent = + this.getMaybeLocalizedError(error); + this.setBreadcrumbsStatus( + BreadcrumbStatus.Default, + BreadcrumbStatus.Active, + BreadcrumbStatus.Disabled + ); + this.showLocationForm(true, TorStrings.torConnect.tryBridge); + this.elements.tryBridgeButton.focus(); + } + + showRegionNotFound() { + this.setTitle(TorStrings.torConnect.errorLocation, "location"); + this.showConfigureConnectionLink( + TorStrings.torConnect.errorLocationDescription + ); + this.elements.progressDescription.textContent = + TorStrings.torConnect.cannotDetermineCountry; + this.setBreadcrumbsStatus( + BreadcrumbStatus.Default, + BreadcrumbStatus.Active, + BreadcrumbStatus.Disabled + ); + this.showLocationForm(false, TorStrings.torConnect.tryBridge); + this.elements.tryBridgeButton.focus(); + } + + showConfirmRegion(error) { + this.setTitle(TorStrings.torConnect.isLocationCorrect, "location"); + this.showConfigureConnectionLink( + TorStrings.torConnect.isLocationCorrectDescription + ); + this.elements.progressDescription.textContent = + this.getMaybeLocalizedError(error); + this.setBreadcrumbsStatus( + BreadcrumbStatus.Default, + BreadcrumbStatus.Default, + BreadcrumbStatus.Active + ); + this.showLocationForm(false, TorStrings.torConnect.tryAgain); + this.elements.tryBridgeButton.focus(); + } + + showFinalError(error) { + this.setTitle(TorStrings.torConnect.finalError, "final"); + this.setLongText(TorStrings.torConnect.finalErrorDescription); + this.elements.progressDescription.textContent = + this.getMaybeLocalizedError(error); + this.setBreadcrumbsStatus( + BreadcrumbStatus.Default, + BreadcrumbStatus.Default, + BreadcrumbStatus.Active + ); + this.hideButtons(); + this.show(this.elements.restartButton); + this.show(this.elements.configureButton, true); + } + + showConfigureConnectionLink(text) { + const pieces = text.split("%S"); + const link = document.createElement("a"); + link.textContent = TorStrings.torConnect.configureConnection; + link.setAttribute("href", "#"); + link.addEventListener("click", e => { + e.preventDefault(); + RPMSendAsyncMessage("torconnect:open-tor-preferences"); + }); + if (pieces.length > 1) { + const first = pieces.shift(); + this.setLongText(first, link, ...pieces); + } else { + this.setLongText(text); + } + } + + showLocationForm(isChoose, buttonLabel) { + this.hideButtons(); + RPMSendQuery("torconnect:get-country-codes").then(codes => { + if (codes && codes.length) { + this.populateFrequentLocations(codes); + this.setLocation(); + } + }); + let firstOpt = this.elements.locationDropdownSelect.options[0]; + if (isChoose) { + firstOpt.value = "automatic"; + firstOpt.textContent = TorStrings.torConnect.automatic; + } else { + firstOpt.value = ""; + firstOpt.textContent = TorStrings.torConnect.selectCountryRegion; + } + this.setLocation(); + this.validateLocation(); + this.show(this.elements.locationDropdownLabel); + this.show(this.elements.locationDropdown); + this.elements.locationDropdownLabel.classList.toggle("error", !isChoose); + this.show(this.elements.tryBridgeButton, true); + if (buttonLabel !== undefined) { + this.elements.tryBridgeButton.textContent = buttonLabel; + } + } + + getLocation() { + const selectedIndex = this.elements.locationDropdownSelect.selectedIndex; + return this.elements.locationDropdownSelect.options[selectedIndex].value; + } + + setLocation() { + const code = this.selectedLocation; + if (this.getLocation() === code) { + return; + } + const options = this.elements.locationDropdownSelect.options; + // We need to do this way, because we have repeated values that break + // the .value way to select (which would however require the label, + // rather than the code)... + for (let i = 0; i < options.length; i++) { + if (options[i].value === code) { + this.elements.locationDropdownSelect.selectedIndex = i; + break; + } + } + this.validateLocation(); + } + + initElements(direction) { + const isAndroid = navigator.userAgent.includes("Android"); + document.body.classList.toggle("android", isAndroid); + + document.documentElement.setAttribute("dir", direction); + + this.elements.connectToTorLink.addEventListener("click", () => { + RPMSendAsyncMessage("torconnect:start-again"); + }); + this.elements.connectToTorLabel.textContent = + TorStrings.torConnect.torConnect; + this.elements.connectionAssistLink.addEventListener("click", () => { + if ( + this.elements.connectionAssistLink.classList.contains( + BreadcrumbStatus.Active + ) || + this.elements.connectionAssistLink.classList.contains( + BreadcrumbStatus.Disabled + ) + ) { + return; + } + RPMSendAsyncMessage("torconnect:choose-region"); + }); + this.elements.connectionAssistLabel.textContent = + TorStrings.torConnect.breadcrumbAssist; + this.elements.tryBridgeLabel.textContent = + TorStrings.torConnect.breadcrumbTryBridge; + + this.hide(this.elements.viewLogButton); + this.elements.viewLogButton.textContent = TorStrings.torConnect.viewLog; + this.elements.viewLogButton.addEventListener("click", () => { + RPMSendAsyncMessage("torconnect:view-tor-logs"); + }); + + this.elements.quickstartToggle.addEventListener("toggle", () => { + const quickstart = this.elements.quickstartToggle.pressed; + RPMSendAsyncMessage("torconnect:set-quickstart", quickstart); + }); + this.elements.quickstartToggle.setAttribute( + "label", + TorStrings.settings.quickstartCheckbox + ); + + this.elements.restartButton.textContent = + TorStrings.torConnect.restartTorBrowser; + this.elements.restartButton.addEventListener("click", () => { + RPMSendAsyncMessage("torconnect:restart"); + }); + + this.elements.configureButton.textContent = + TorStrings.torConnect.torConfigure; + this.elements.configureButton.addEventListener("click", () => { + RPMSendAsyncMessage("torconnect:open-tor-preferences"); + }); + + this.elements.cancelButton.textContent = TorStrings.torConnect.cancel; + this.elements.cancelButton.addEventListener("click", () => { + this.cancelBootstrapping(); + }); + + this.elements.connectButton.textContent = + TorStrings.torConnect.torConnectButton; + this.elements.connectButton.addEventListener("click", () => { + this.beginBootstrapping(); + }); + + this.populateLocations(); + this.elements.locationDropdownSelect.addEventListener("change", () => { + this.validateLocation(); + }); + + this.elements.locationDropdownLabel.textContent = + TorStrings.torConnect.unblockInternetIn; + + this.elements.tryBridgeButton.textContent = TorStrings.torConnect.tryBridge; + this.elements.tryBridgeButton.addEventListener("click", () => { + const value = this.getLocation(); + if (value) { + this.beginAutoBootstrapping(value); + } + }); + + // Prevent repeat triggering on keydown when the Enter key is held down. + // + // Without this, holding down Enter will continue to trigger the button's + // click event until the user stops holding. This means that a user can + // accidentally re-trigger a button several times. And if focus moves to a + // new button it can also get triggered, despite not receiving the initial + // keydown event. + // + // E.g. If the user presses down Enter on the "Connect" button it will + // trigger and focus will move to the "Cancel" button. This should prevent + // the user accidentally triggering the "Cancel" button if they hold down + // Enter for a little bit too long. + for (const button of document.body.querySelectorAll("button")) { + button.addEventListener("keydown", event => { + // If the keydown is a repeating Enter event, ignore it. + // NOTE: If firefox uses wayland display (rather than xwayland), the + // "repeat" event is always "false" so this will not work. + // See bugzilla bug 1784438. Also see bugzilla bug 1594003. + // Currently tor browser uses xwayland by default on linux. + if (event.key === "Enter" && event.repeat) { + event.preventDefault(); + } + }); + } + } + + initObservers() { + // TorConnectParent feeds us state blobs to we use to update our UI + RPMAddMessageListener("torconnect:stage-change", ({ data }) => { + this.updateStage(data); + }); + RPMAddMessageListener("torconnect:bootstrap-progress", ({ data }) => { + this.updateBootstrappingStatus(data); + }); + RPMAddMessageListener("torconnect:quickstart-change", ({ data }) => { + this.updateQuickstart(data); + }); + } + + initKeyboardShortcuts() { + document.onkeydown = evt => { + // unfortunately it looks like we still haven't standardized keycodes to + // integers, so we must resort to a string compare here :( + // see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code for relevant documentation + if (evt.code === "Escape") { + this.cancelBootstrapping(); + } + }; + } + + async init() { + let args = await RPMSendQuery("torconnect:get-init-args"); + + // various constants + TorStrings = Object.freeze(args.TorStrings); + this.locations = args.CountryNames; + + this.initElements(args.Direction); + this.initObservers(); + this.initKeyboardShortcuts(); + + this.updateStage(args.stage); + this.updateQuickstart(args.quickstartEnabled); + } +} + +const aboutTorConnect = new AboutTorConnect(); +aboutTorConnect.init(); diff --git a/toolkit/components/torconnect/content/arrow-right.svg b/toolkit/components/torconnect/content/arrow-right.svg new file mode 100644 index 0000000000000000000000000000000000000000..3f6d8ded52bedba8885d205a0b81cb6dbfa61aa8 --- /dev/null +++ b/toolkit/components/torconnect/content/arrow-right.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M10.9991 8.352L5.53406 13.818C5.41557 13.9303 5.25792 13.9918 5.09472 13.9895C4.93152 13.9872 4.77567 13.9212 4.66039 13.8057C4.54511 13.6902 4.47951 13.5342 4.47758 13.3709C4.47565 13.2077 4.53754 13.0502 4.65006 12.932L9.58506 7.998L4.65106 3.067C4.53868 2.94864 4.47697 2.79106 4.47909 2.62786C4.48121 2.46466 4.54698 2.30874 4.66239 2.19333C4.7778 2.07792 4.93372 2.01215 5.09692 2.01003C5.26012 2.00792 5.41769 2.06962 5.53606 2.182L11.0001 7.647L10.9991 8.352Z" fill="context-fill"/> +</svg> diff --git a/toolkit/components/torconnect/content/bridge.svg b/toolkit/components/torconnect/content/bridge.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ae3f05dfd08296a60764791724c2753786d4e80 --- /dev/null +++ b/toolkit/components/torconnect/content/bridge.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M1 9.48528C1 9.48528 3.82843 9.48528 6.65685 6.65685C9.48528 3.82843 9.48528 1 9.48528 1" stroke="context-fill" stroke-width="1.25" stroke-linecap="round"/> + <path d="M6.65686 15.1421C6.65686 15.1421 6.65686 12.3137 9.48529 9.48529C12.3137 6.65686 15.1421 6.65686 15.1421 6.65686" stroke="context-fill" stroke-width="1.25" stroke-linecap="round"/> +</svg> diff --git a/toolkit/components/torconnect/content/connection-failure.svg b/toolkit/components/torconnect/content/connection-failure.svg new file mode 100644 index 0000000000000000000000000000000000000000..7931260fb3de6c92a055629631716f62d422712a --- /dev/null +++ b/toolkit/components/torconnect/content/connection-failure.svg @@ -0,0 +1,7 @@ +<svg fill="none" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"> + <rect height="1.22295" rx=".611475" transform="matrix(-.707107 -.707107 -.707107 .707107 14.9464 14.1921)" width="18.6565" fill="context-fill" /> + <g fill="context-fill" fill-rule="evenodd"> + <path d="m3.9498 1.68761c1.19924-.769433 2.60316-1.18761 4.0502-1.18761 1.98912 0 3.8968.79018 5.3033 2.1967s2.1967 3.31418 2.1967 5.3033c0 1.44704-.4182 2.851-1.1876 4.0502l-.9179-.9179c.4428-.7667.7192-1.62112.8075-2.5073h-2.229c-.0215.32648-.0599.65056-.1148.971l-2.22101-2.221h1.08181c-.146-1.92835-.96795-3.74329-2.321-5.125h-.796c-.52113.53217-.96348 1.12861-1.31877 1.77104l-.9115-.9115c.17951-.29615.37579-.58315.58827-.85954h-.408c-.23805.10224-.46875.21884-.69093.34888zm9.0744 2.61245c-.6605-.90129-1.5504-1.60918-2.5772-2.05006h-.407c1.1378 1.47922 1.8109 3.26288 1.934 5.125h2.229c-.1112-1.11187-.5182-2.17365-1.1788-3.07494z" /> + <path d="m3.08673 2.33343c-.13383.11605-.26395.23718-.39003.36327-1.40652 1.40652-2.1967 3.31418-2.1967 5.3033s.79018 3.8968 2.1967 5.3033 3.31418 2.1967 5.3033 2.1967 3.8968-.7902 5.3033-2.1967c.1261-.1261.2472-.2562.3633-.39l-.8933-.8933c-.6277.7494-1.4237 1.3427-2.3253 1.73h-.409c.6819-.8861 1.1969-1.8815 1.5266-2.9377l-1.0208-1.02083c-.3313 1.48633-1.07154 2.85943-2.1478 3.95853h-.795c-1.35305-1.3817-2.175-3.1966-2.321-5.125h4.09731l-1.25-1.25h-2.84731c.06073-.80217.23844-1.58472.52269-2.32462l-.95329-.95329c-.46748 1.02882-.74878 2.13867-.8244 3.27791h-2.229c.11102-1.1118.51787-2.17355 1.17823-3.07484.29198-.39851.62881-.75922 1.00248-1.07575zm-.11176 9.36657c.66039.9014 1.55027 1.6092 2.57703 2.05h.408c-1.13778-1.4792-1.81088-3.2629-1.934-5.125h-2.229c.11081 1.11186.51758 2.1737 1.17797 3.075z" /> + </g> +</svg> diff --git a/toolkit/components/torconnect/content/connection-location.svg b/toolkit/components/torconnect/content/connection-location.svg new file mode 100644 index 0000000000000000000000000000000000000000..3e49cbbf11f8f70560bd05b2e10b6cdea9b921d1 --- /dev/null +++ b/toolkit/components/torconnect/content/connection-location.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" d="M7.73334 11.442C7.73334 9.541 9.34511 8.00001 11.3333 8.00001C13.3216 8.00001 14.9333 9.541 14.9333 11.442C14.9333 12.801 13.0948 14.729 12.0456 15.7185C11.855 15.899 11.5994 16 11.3333 16C11.0672 16 10.8117 15.899 10.6211 15.7185C9.57191 14.729 7.73334 12.8005 7.73334 11.442ZM10.7466 9.98339C10.9326 9.90634 11.132 9.86667 11.3333 9.86667C11.74 9.86667 12.13 10.0282 12.4176 10.3158C12.7051 10.6033 12.8667 10.9933 12.8667 11.4C12.8667 11.8067 12.7051 12.1967 12.4176 12.4842C12.13 12.7718 11.74 12.9333 11.3333 12.9333C11.132 12.9333 10.9326 12.8937 10.7466 12.8166C10.5605 12.7396 10.3915 12.6266 10.2491 12.4842C10.1067 12.3419 9.99378 12.1728 9.91672 11.9868C9.83966 11.8008 9.8 11.6014 9.8 11.4C9.8 11.1986 9.83966 10.9993 9.91672 10.8132C9.99378 10.6272 10.1067 10.4582 10.2491 10.3158C10.3915 10.1734 10.5605 10.0604 10.7466 9.98339Z" fill="context-stroke"/> + <path d="M15.4042 9.15991C15.489 8.70846 15.5333 8.24275 15.5333 7.76667C15.5333 3.62454 12.1755 0.26667 8.03332 0.26667C3.89119 0.26667 0.533325 3.62454 0.533325 7.76667C0.533325 11.9088 3.89119 15.2667 8.03332 15.2667C8.33067 15.2667 8.62398 15.2494 8.91229 15.2157C7.77562 13.9767 6.66666 12.467 6.66666 11.2932C6.66666 10.0893 7.18892 8.99941 8.03333 8.21045V5.93855C8.83962 5.93855 9.52399 6.46053 9.76697 7.185C10.1327 7.06327 10.5195 6.98297 10.9209 6.95013C10.5653 5.69011 9.40713 4.76667 8.03333 4.76667L8.03332 3.68854C10.0174 3.68854 11.6705 5.10537 12.0361 6.98245C12.4679 7.04338 12.8804 7.1596 13.2649 7.32314C13.0397 4.63121 10.7834 2.51667 8.03332 2.51666V1.43855C11.5283 1.43855 14.3615 4.27174 14.3615 7.76667C14.3615 7.83574 14.3604 7.90454 14.3582 7.97308C14.7773 8.30672 15.1325 8.70843 15.4042 9.15991Z" fill="context-fill"/> +</svg> diff --git a/toolkit/components/torconnect/content/tor-connect-broken.svg b/toolkit/components/torconnect/content/tor-connect-broken.svg new file mode 100644 index 0000000000000000000000000000000000000000..470de6d77db4e7871a6db26a8b90030e7dbd7832 --- /dev/null +++ b/toolkit/components/torconnect/content/tor-connect-broken.svg @@ -0,0 +1,11 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M3.32745 2.13476C4.60904 1.11242 6.23317 0.501331 8 0.501331C12.1414 0.501331 15.4987 3.85866 15.4987 8C15.4987 9.76709 14.8876 11.3911 13.8652 12.6725L13.0315 11.8388C13.8448 10.7747 14.328 9.44438 14.328 8C14.328 4.50401 11.496 1.672 8 1.672C6.5562 1.672 5.22564 2.15503 4.16105 2.96836L3.32745 2.13476Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M2.35636 3.06235C1.20135 4.38144 0.501343 6.10899 0.501343 8C0.501343 11.5867 3.01868 14.584 6.38401 15.3227C6.73601 15.4 7.09333 15.4533 7.46134 15.4773V9.74933C6.71467 9.52 6.17068 8.82401 6.17068 8C6.17068 7.67615 6.25474 7.37202 6.40223 7.10822L5.55539 6.26138C5.20574 6.75196 5.00001 7.3521 5.00001 8C5.00001 9.06133 5.55201 9.99466 6.38401 10.528V14.1173C3.67201 13.4053 1.67201 10.9387 1.67201 8C1.67201 6.43179 2.24187 4.99718 3.18588 3.89187L2.35636 3.06235Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M6.56041 5.36771L7.44804 6.25534C7.62219 6.20033 7.80762 6.17067 8.00001 6.17067C9.01067 6.17067 9.82934 6.98934 9.82934 8C9.82934 8.19242 9.79968 8.37785 9.7447 8.552L10.6324 9.43967C10.8667 9.01221 11 8.52156 11 8C11 6.34399 9.65601 5 8.00001 5C7.47845 5 6.98783 5.13332 6.56041 5.36771Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M9.73889 10.4449L8.89214 9.59813C8.78095 9.66036 8.6626 9.71127 8.53868 9.74933V15.4773C8.90668 15.4533 9.26401 15.4 9.61601 15.3227C10.8695 15.0475 12.0054 14.459 12.9374 13.6434L12.1076 12.8136C11.396 13.4207 10.5481 13.8726 9.61601 14.1173V10.528C9.65768 10.5013 9.69865 10.4736 9.73889 10.4449Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M12.2609 11.0682C12.8837 10.2055 13.2507 9.14573 13.2507 8C13.2507 5.10133 10.8987 2.74933 7.99999 2.74933C6.85488 2.74933 5.79508 3.11639 4.9319 3.73921L5.77475 4.58207C6.41445 4.16498 7.1787 3.92267 7.99999 3.92267C10.2533 3.92267 12.0773 5.74666 12.0773 8C12.0773 8.82056 11.8348 9.58497 11.4175 10.2248L12.2609 11.0682Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M10.5086 11.2146L11.3423 12.0483C10.8375 12.4651 10.2534 12.7892 9.616 12.9947V11.744C9.93702 11.6057 10.2367 11.4271 10.5086 11.2146Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M4.78492 5.49092L3.95137 4.65737C3.20058 5.56555 2.74933 6.73033 2.74933 8C2.74933 10.336 4.27467 12.3147 6.384 12.9947V11.744C4.936 11.12 3.92267 9.67733 3.92267 8C3.92267 7.05341 4.24455 6.18259 4.78492 5.49092Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M7.16918 7.8752L8.12478 8.83079C8.08406 8.83686 8.04238 8.84 7.99997 8.84C7.53605 8.84 7.15997 8.46392 7.15997 8C7.15997 7.95759 7.16312 7.91592 7.16918 7.8752Z" fill="context-fill" fill-opacity="context-fill-opacity" /> + <path d="M1.15533 1.85684L14.0906 14.7921C14.3511 15.0527 14.3511 15.4751 14.0906 15.7357L14.0906 15.7357C13.83 15.9963 13.4075 15.9963 13.1469 15.7357L0.211679 2.8005C-0.048903 2.53992 -0.0489032 2.11743 0.211682 1.85684C0.472265 1.59626 0.894753 1.59626 1.15533 1.85684Z" fill="context-stroke" fill-opacity="context-fill-opacity" /> +</svg> diff --git a/toolkit/components/torconnect/content/tor-connect.svg b/toolkit/components/torconnect/content/tor-connect.svg new file mode 100644 index 0000000000000000000000000000000000000000..c62c85d7e7de01d0b48d0caa92c0139ccbc8e81c --- /dev/null +++ b/toolkit/components/torconnect/content/tor-connect.svg @@ -0,0 +1,7 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 0.501331C3.85867 0.501331 0.501343 3.85866 0.501343 8C0.501343 11.5867 3.01868 14.584 6.38401 15.3227C6.73601 15.4 7.09333 15.4533 7.46134 15.4773V9.74933C6.71467 9.52 6.17068 8.82401 6.17068 8C6.17068 6.98934 6.98935 6.17067 8.00001 6.17067C9.01067 6.17067 9.82934 6.98934 9.82934 8C9.82934 8.82401 9.28534 9.52 8.53868 9.74933V15.4773C8.90668 15.4533 9.26401 15.4 9.61601 15.3227C12.9813 14.584 15.4987 11.5867 15.4987 8C15.4987 3.85866 12.1414 0.501331 8.00001 0.501331ZM9.61601 14.1173V10.528C10.448 9.99466 11 9.06133 11 8C11 6.344 9.65601 5 8.00001 5C6.344 5 5.00001 6.344 5.00001 8C5.00001 9.06133 5.55201 9.99466 6.38401 10.528V14.1173C3.67201 13.4053 1.67201 10.9387 1.67201 8C1.67201 4.504 4.50401 1.67201 8.00001 1.67201C11.496 1.67201 14.328 4.50401 14.328 8C14.328 10.9387 12.328 13.4053 9.61601 14.1173Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99999 2.74933C5.10133 2.74933 2.74933 5.10134 2.74933 8C2.74933 10.336 4.27467 12.3147 6.384 12.9947V11.744C4.936 11.12 3.92267 9.67733 3.92267 8C3.92267 5.74666 5.74666 3.92267 7.99999 3.92267C10.2533 3.92267 12.0773 5.74666 12.0773 8C12.0773 9.67733 11.064 11.12 9.61599 11.744V12.9947C11.7253 12.3147 13.2507 10.336 13.2507 8C13.2507 5.10133 10.8987 2.74933 7.99999 2.74933Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +<path d="M7.99997 8.84C8.46389 8.84 8.83997 8.46392 8.83997 8C8.83997 7.53608 8.46389 7.16 7.99997 7.16C7.53605 7.16 7.15997 7.53608 7.15997 8C7.15997 8.46392 7.53605 8.84 7.99997 8.84Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +</g> +</svg> diff --git a/toolkit/components/torconnect/content/tor-not-connected-to-connected-animated.svg b/toolkit/components/torconnect/content/tor-not-connected-to-connected-animated.svg new file mode 100644 index 0000000000000000000000000000000000000000..7d653d68a31faaa85d43c3a3d78def3b6d89e8ec --- /dev/null +++ b/toolkit/components/torconnect/content/tor-not-connected-to-connected-animated.svg @@ -0,0 +1,34 @@ +<svg width="176" height="16" viewBox="0 0 176 16" xmlns="http://www.w3.org/2000/svg"> + <!-- First frame, same as tor-connect-broken.svg --> + <path d="M3.32745 2.13476C4.60904 1.11242 6.23317 0.501331 8 0.501331C12.1414 0.501331 15.4987 3.85866 15.4987 8C15.4987 9.76709 14.8876 11.3911 13.8652 12.6725L13.0315 11.8388C13.8448 10.7747 14.328 9.44438 14.328 8C14.328 4.50401 11.496 1.672 8 1.672C6.5562 1.672 5.22564 2.15503 4.16105 2.96836L3.32745 2.13476Z" fill="context-fill" /> + <path d="M2.35636 3.06235C1.20135 4.38144 0.501343 6.10899 0.501343 8C0.501343 11.5867 3.01868 14.584 6.38401 15.3227C6.73601 15.4 7.09333 15.4533 7.46134 15.4773V9.74933C6.71467 9.52 6.17068 8.82401 6.17068 8C6.17068 7.67615 6.25474 7.37202 6.40223 7.10822L5.55539 6.26138C5.20574 6.75196 5.00001 7.3521 5.00001 8C5.00001 9.06133 5.55201 9.99466 6.38401 10.528V14.1173C3.67201 13.4053 1.67201 10.9387 1.67201 8C1.67201 6.43179 2.24187 4.99718 3.18588 3.89187L2.35636 3.06235Z" fill="context-fill" /> + <path d="M6.56041 5.36771L7.44804 6.25534C7.62219 6.20033 7.80762 6.17067 8.00001 6.17067C9.01067 6.17067 9.82934 6.98934 9.82934 8C9.82934 8.19242 9.79968 8.37785 9.7447 8.552L10.6324 9.43967C10.8667 9.01221 11 8.52156 11 8C11 6.34399 9.65601 5 8.00001 5C7.47845 5 6.98783 5.13332 6.56041 5.36771Z" fill="context-fill" /> + <path d="M9.73889 10.4449L8.89214 9.59813C8.78095 9.66036 8.6626 9.71127 8.53868 9.74933V15.4773C8.90668 15.4533 9.26401 15.4 9.61601 15.3227C10.8695 15.0475 12.0054 14.459 12.9374 13.6434L12.1076 12.8136C11.396 13.4207 10.5481 13.8726 9.61601 14.1173V10.528C9.65768 10.5013 9.69865 10.4736 9.73889 10.4449Z" fill="context-fill" /> + <path d="M12.2609 11.0682C12.8837 10.2055 13.2507 9.14573 13.2507 8C13.2507 5.10133 10.8987 2.74933 7.99999 2.74933C6.85488 2.74933 5.79508 3.11639 4.9319 3.73921L5.77475 4.58207C6.41445 4.16498 7.1787 3.92267 7.99999 3.92267C10.2533 3.92267 12.0773 5.74666 12.0773 8C12.0773 8.82056 11.8348 9.58497 11.4175 10.2248L12.2609 11.0682Z" fill="context-fill" /> + <path d="M10.5086 11.2146L11.3423 12.0483C10.8375 12.4651 10.2534 12.7892 9.616 12.9947V11.744C9.93702 11.6057 10.2367 11.4271 10.5086 11.2146Z" fill="context-fill" /> + <path d="M4.78492 5.49092L3.95137 4.65737C3.20058 5.56555 2.74933 6.73033 2.74933 8C2.74933 10.336 4.27467 12.3147 6.384 12.9947V11.744C4.936 11.12 3.92267 9.67733 3.92267 8C3.92267 7.05341 4.24455 6.18259 4.78492 5.49092Z" fill="context-fill" /> + <path d="M7.16918 7.8752L8.12478 8.83079C8.08406 8.83686 8.04238 8.84 7.99997 8.84C7.53605 8.84 7.15997 8.46392 7.15997 8C7.15997 7.95759 7.16312 7.91592 7.16918 7.8752Z" fill="context-fill" /> + <path d="M1.15533 1.85684L14.0906 14.7921C14.3511 15.0527 14.3511 15.4751 14.0906 15.7357L14.0906 15.7357C13.83 15.9963 13.4075 15.9963 13.1469 15.7357L0.211679 2.8005C-0.048903 2.53992 -0.0489032 2.11743 0.211682 1.85684C0.472265 1.59626 0.894753 1.59626 1.15533 1.85684Z" fill="context-stroke" /> + <!-- End of first frame. --> + <path d="m 26.5604,5.36771 0.8877,0.88763 C 27.6222,6.20033 27.8076,6.17067 28,6.17067 c 1.0107,0 1.8294,0.81867 1.8294,1.82933 0,0.1924 -0.0297,0.3779 -0.0847,0.552 l 0.8877,0.8877 C 30.8667,9.0122 31,8.5216 31,8 31,6.34399 29.656,5 28,5 27.4785,5 26.9878,5.13332 26.5604,5.36771 Z" fill="context-fill" /> + <path d="M 32.2609,11.0682 C 32.8837,10.2055 33.2507,9.1457 33.2507,8 33.2507,5.10133 30.8987,2.74933 28,2.74933 c -1.1451,0 -2.2049,0.36706 -3.0681,0.98988 l 0.8428,0.84286 c 0.6397,-0.41709 1.404,-0.6594 2.2253,-0.6594 2.2533,0 4.0773,1.82399 4.0773,4.07733 0,0.8206 -0.2425,1.585 -0.6598,2.2248 z" fill="context-fill" /> + <path fill-rule="evenodd" d="M 25.1667,1.05506 C 26.0409,0.69808 26.9975,0.50133 28,0.50133 c 4.1414,0 7.4987,3.35732 7.4987,7.49867 0,1.7671 -0.6111,3.3911 -1.6335,4.6725 L 33.0315,11.8388 C 33.8448,10.7747 34.328,9.4444 34.328,8 34.328,4.504 31.496,1.67199 28,1.67199 c -1.4438,0 -2.7744,0.48303 -3.8389,1.29636 L 24.1597,2.96703 c -0.3568,0.27263 -0.6838,0.58239 -0.9752,0.9235 l 0.0014,0.00134 C 22.2419,4.99718 21.672,6.43179 21.672,8 c 0,1.7592 0.7167,3.3492 1.8739,4.4949 0.473,0.4681 1.0196,0.862 1.6208,1.1628 0.385,0.1928 0.7924,0.3481 1.2173,0.4596 V 10.528 C 25.552,9.9947 25,9.0613 25,8 25,7.8685 25.0085,7.7389 25.0249,7.6118 L 24.1287,6.71563 C 23.995,7.11937 23.9227,7.5512 23.9227,8 c 0,1.6773 1.0133,3.12 2.4613,3.744 v 1.2507 C 24.2747,12.3147 22.7493,10.336 22.7493,8 c 0,-0.78053 0.1706,-1.52142 0.4764,-2.18742 L 22.8632,5.45009 c -0.2597,-0.2597 -0.2597,-0.68075 0,-0.94045 0.2597,-0.2597 0.6808,-0.2597 0.9405,0 L 34.0943,14.8002 c 0.2597,0.2597 0.2597,0.6808 0,0.9405 -0.2597,0.2597 -0.6808,0.2597 -0.9405,0 L 31.849,14.4359 c -0.6815,0.4082 -1.4333,0.7112 -2.233,0.8868 -0.352,0.0773 -0.7093,0.1306 -1.0773,0.1546 v -4.3518 l -1.0774,-1.0773 v 5.4291 C 27.0933,15.4533 26.736,15.4 26.384,15.3227 24.9758,15.0136 23.7161,14.309 22.7272,13.3313 21.3519,11.9723 20.5,10.0852 20.5,7.9987 20.5,4.85935 22.4292,2.17055 25.1667,1.05319 Z M 29.616,14.1173 v -1.9144 0.7918 c 0.1953,-0.063 0.3857,-0.1371 0.5702,-0.2216 l 0.804,0.804 c -0.4306,0.2309 -0.8911,0.4134 -1.3742,0.5402 z" fill="context-fill" /> + <path d="m 46.5604,5.36771 0.8877,0.88763 C 47.6222,6.20033 47.8076,6.17067 48,6.17067 c 1.0107,0 1.8294,0.81867 1.8294,1.82933 0,0.1924 -0.0297,0.3779 -0.0847,0.552 l 0.8877,0.8877 C 50.8667,9.0122 51,8.5216 51,8 51,6.34399 49.656,5 48,5 47.4785,5 46.9878,5.13332 46.5604,5.36771 Z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 48,0.50133 c -1.0025,0 -1.9591,0.19675 -2.8333,0.55373 V 1.05319 C 42.4292,2.17055 40.5,4.85935 40.5,7.9987 c 0,2.0865 0.8519,3.9736 2.2272,5.3326 0.9889,0.9777 2.2486,1.6823 3.6568,1.9914 0.352,0.0773 0.7093,0.1306 1.0773,0.1546 v -5.4291 l 1.0774,1.0773 v 4.3518 c 0.368,-0.024 0.7253,-0.0773 1.0773,-0.1546 0.7997,-0.1756 1.5515,-0.4786 2.233,-0.8868 l 1.3048,1.3048 c 0.2597,0.2597 0.6808,0.2597 0.9405,0 0.2597,-0.2597 0.2597,-0.6808 0,-0.9405 L 45.5277,6.23361 c -0.2597,-0.2597 -0.6808,-0.2597 -0.9405,0 -0.2597,0.2597 -0.2597,0.68075 0,0.94045 L 45.0249,7.6118 C 45.0085,7.7389 45,7.8684 45,8 c 0,1.0613 0.552,1.9947 1.384,2.528 v 1.2164 c -1.4476,-0.6242 -2.4607,-2.0667 -2.4607,-3.7437 0,-2.25337 1.824,-4.07736 4.0774,-4.07736 0.0919,0 0.1832,0.00304 0.2736,0.00902 2.1252,0.1409 3.803,1.90649 3.803,4.06764 0,0.8206 -0.2425,1.585 -0.6598,2.2248 l 0.8434,0.8434 C 52.8837,10.2055 53.2507,9.1457 53.2507,8 53.2507,5.10133 50.8987,2.74933 48,2.74933 c -1.1451,0 -2.2049,0.36706 -3.0681,0.98988 C 43.6101,4.69295 42.75,6.24712 42.75,8.0007 c 0,2.3357 1.525,4.3143 3.634,4.9945 v 1.1221 C 45.9591,14.0058 45.5517,13.8511 45.1667,13.6584 44.5655,13.3575 44.0189,12.963 43.5459,12.4949 42.3887,11.3492 41.672,9.7592 41.672,8 c 0,-1.56821 0.5699,-3.00282 1.5139,-4.10813 L 43.1845,3.89053 c 0.2914,-0.34111 0.6184,-0.65087 0.9752,-0.9235 l 0.0014,0.00132 C 45.2256,2.15502 46.5562,1.67199 48,1.67199 c 3.496,0 6.328,2.83201 6.328,6.32801 0,1.4444 -0.4832,2.7747 -1.2965,3.8388 l 0.8337,0.8337 C 54.8876,11.3911 55.4987,9.7671 55.4987,8 55.4987,3.85865 52.1414,0.50133 48,0.50133 Z m 1.616,11.70147 v 1.9145 c 0.4831,-0.1268 0.9436,-0.3093 1.3742,-0.5402 l -0.8039,-0.804 c -0.1846,0.0845 -0.375,0.1586 -0.5703,0.2216 z" fill="context-fill" /> + <path d="m 48,8.21 c 0.116,0 0.21,-0.094 0.21,-0.21 0,-0.116 -0.094,-0.21 -0.21,-0.21 -0.116,0 -0.21,0.094 -0.21,0.21 0,0.116 0.094,0.21 0.21,0.21 z" fill="context-fill" /> + <path fill-rule="evenodd" d="M 67.9987,0.5 H 68 v 0.00133 c 4.1414,0 7.4987,3.35732 7.4987,7.49867 0,1.7671 -0.6111,3.3911 -1.6335,4.6725 L 73.0315,11.8388 C 73.8448,10.7747 74.328,9.4444 74.328,8 74.328,4.504 71.496,1.67199 68,1.67199 c -1.4438,0 -2.7744,0.48303 -3.8389,1.29636 L 64.1597,2.96703 c -1.5132,1.15605 -2.489,2.97944 -2.489,5.03167 0,2.204 1.125,4.1425 2.8316,5.2743 0.5689,0.3773 1.2024,0.665 1.8804,0.843 V 12.9947 C 64.2744,12.3141 62.75,10.3359 62.75,8.0007 62.75,6.24712 63.6107,4.69363 64.9326,3.73989 65.7957,3.11707 66.8549,2.74933 68,2.74933 c 2.8987,0 5.2507,2.352 5.2507,5.25067 0,1.1457 -0.367,2.2055 -0.9898,3.0682 L 71.4175,10.2248 C 71.8348,9.585 72.0773,8.8206 72.0773,8 c 0,-2.16115 -1.6778,-3.92736 -3.803,-4.06827 -0.0904,-0.00598 -0.1817,-0.00839 -0.2736,-0.00839 -2.2534,0 -4.0774,1.82399 -4.0774,4.07736 0,1.6765 1.0124,3.1186 2.4594,3.7431 v -1.2171 c -0.832,-0.5334 -1.384,-1.4667 -1.384,-2.528 0,-1.65603 1.344,-3.00003 3,-3.00003 H 68 V 5 c 1.656,0 3,1.34399 3,3 0,0.5216 -0.1333,1.0122 -0.3676,1.4397 L 69.7447,8.552 C 69.7997,8.3778 69.8294,8.1924 69.8294,8 69.8294,6.98934 69.0107,6.17067 68,6.17067 c -0.1924,0 -0.3778,0.02966 -0.5519,0.08467 L 67.4467,6.254 c -0.7407,0.23396 -1.2774,0.92639 -1.2774,1.7447 0,0.3258 0.0851,0.6317 0.2342,0.8966 -0.0799,-0.2328 -0.027,-0.501 0.1587,-0.6867 0.2597,-0.2597 0.6807,-0.2597 0.9404,0 l 6.5917,6.5916 c 0.2597,0.2597 0.2597,0.6808 0,0.9405 -0.2597,0.2597 -0.6808,0.2597 -0.9405,0 L 71.849,14.4359 c -0.6815,0.4082 -1.4333,0.7112 -2.233,0.8868 -0.352,0.0773 -0.7093,0.1306 -1.0773,0.1546 V 11.1255 L 67.46,10.0469 V 15.476 C 67.092,15.452 66.7347,15.3987 66.3827,15.3214 65.9631,15.2293 65.5567,15.1021 65.1667,14.943 62.4288,13.8261 60.5,11.1382 60.5,7.9987 60.5,4.89266 62.3885,2.22766 65.0799,1.08929 65.977,0.70983 66.9633,0.5 67.9987,0.5 Z m 1.6173,11.7028 v 1.9145 c 0.4831,-0.1268 0.9436,-0.3093 1.3742,-0.5402 l -0.804,-0.804 c -0.1845,0.0845 -0.3749,0.1586 -0.5702,0.2216 z" fill="context-fill" /> + <path d="m 68,8.42 c 0.2319,0 0.42,-0.188 0.42,-0.42 0,-0.232 -0.1881,-0.42 -0.42,-0.42 -0.232,0 -0.42,0.188 -0.42,0.42 0,0.232 0.188,0.42 0.42,0.42 z" fill="context-fill" /> + <path d="M 87.9987,0.5 H 88 v 0.00133 c 4.1414,0 7.4987,3.35732 7.4987,7.49867 0,1.7671 -0.6111,3.3911 -1.6335,4.6725 L 93.0315,11.8388 C 93.8448,10.7747 94.328,9.4444 94.328,8 94.328,4.504 91.496,1.67199 88,1.67199 c -1.4438,0 -2.7744,0.48303 -3.8389,1.29636 L 84.1597,2.96703 c -1.5132,1.15605 -2.489,2.97944 -2.489,5.03167 0,2.204 1.125,4.1425 2.8316,5.2743 0.5689,0.3773 1.2024,0.665 1.8804,0.843 V 12.9947 C 84.2744,12.3141 82.75,10.3359 82.75,8.0007 82.75,6.24712 83.6107,4.69363 84.9326,3.73989 85.7957,3.11707 86.8549,2.74933 88,2.74933 c 2.8987,0 5.2507,2.352 5.2507,5.25067 0,1.1457 -0.367,2.2055 -0.9898,3.0682 L 91.4175,10.2248 C 91.8348,9.585 92.0773,8.8206 92.0773,8 c 0,-2.16115 -1.6778,-3.92736 -3.803,-4.06827 -0.0904,-0.00598 -0.1817,-0.00839 -0.2736,-0.00839 -2.2534,0 -4.0774,1.82399 -4.0774,4.07736 0,1.6765 1.0124,3.1186 2.4594,3.7431 v -1.2171 c -0.832,-0.5334 -1.384,-1.4667 -1.384,-2.528 0,-1.65603 1.344,-3.00003 3,-3.00003 H 88 V 5 c 1.656,0 3,1.34399 3,3 0,0.5216 -0.1333,1.0122 -0.3676,1.4397 L 89.7447,8.552 C 89.7997,8.3778 89.8294,8.1924 89.8294,8 89.8294,6.98934 89.0107,6.17067 88,6.17067 c -0.1924,0 -0.3778,0.02966 -0.5519,0.08467 L 87.4467,6.254 c -0.7407,0.23396 -1.2774,0.92639 -1.2774,1.7447 0,0.824 0.544,1.52 1.2907,1.7493 v 5.728 C 87.092,15.452 86.7347,15.3987 86.3827,15.3214 85.9631,15.2293 85.5567,15.1021 85.1667,14.943 82.4288,13.8261 80.5,11.1382 80.5,7.9987 80.5,4.89266 82.3885,2.22766 85.0799,1.08929 85.977,0.70983 86.9633,0.5 87.9987,0.5 Z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 88.5387,11.1255 -0.7798,-0.7798 c -0.2597,-0.2597 -0.2597,-0.6807 0,-0.9404 0.2597,-0.2597 0.6807,-0.2597 0.9404,0 l 5.395,5.3949 c 0.2597,0.2597 0.2597,0.6808 0,0.9405 -0.2597,0.2597 -0.6808,0.2597 -0.9405,0 L 91.849,14.4359 c -0.6815,0.4082 -1.4333,0.7112 -2.233,0.8868 -0.352,0.0773 -0.7093,0.1306 -1.0773,0.1546 z m 1.0773,1.0774 v 1.9144 c 0.4831,-0.1268 0.9436,-0.3093 1.3742,-0.5402 l -0.804,-0.804 c -0.1845,0.0845 -0.3749,0.1586 -0.5702,0.2216 z" fill="context-fill" /> + <path d="m 88,8.63 c 0.3479,0 0.63,-0.2821 0.63,-0.63 0,-0.3479 -0.2821,-0.63 -0.63,-0.63 -0.3479,0 -0.63,0.2821 -0.63,0.63 0,0.3479 0.2821,0.63 0.63,0.63 z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 100.5,7.9987 c 0,-4.14137 3.357,-7.4987 7.499,-7.4987 2.061,0 3.927,0.83143 5.283,2.17715 1.369,1.35859 2.217,3.24172 2.217,5.32285 0,1.7671 -0.611,3.3911 -1.634,4.6725 l -0.834,-0.8337 c 0.413,-0.5403 0.741,-1.1493 0.964,-1.807 h -0.002 c 0.216,-0.6379 0.334,-1.3217 0.334,-2.0331 0,-1.75964 -0.718,-3.35103 -1.876,-4.49778 -1.143,-1.13084 -2.715,-1.82893 -4.451,-1.82893 -1.444,0 -2.774,0.48303 -3.839,1.29636 L 104.16,2.96702 c -1.513,1.15606 -2.489,2.97945 -2.489,5.03168 0,2.9387 2,5.4053 4.712,6.1173 v -1.1213 c -2.109,-0.6806 -3.633,-2.6588 -3.633,-4.994 0,-1.75358 0.861,-3.30707 2.183,-4.26081 0.863,-0.62282 1.922,-0.99056 3.067,-0.99056 2.899,0 5.251,2.352 5.251,5.25067 0,1.1457 -0.367,2.2055 -0.99,3.0682 l -0.844,-0.8434 c 0.418,-0.6398 0.66,-1.4042 0.66,-2.2248 0,-2.16115 -1.678,-3.92736 -3.803,-4.06827 -0.09,-0.00598 -0.181,-0.00839 -0.273,-0.00839 -2.254,0 -4.078,1.82399 -4.078,4.07736 0,1.6765 1.013,3.1186 2.46,3.7431 v -1.2171 c -0.832,-0.5334 -1.384,-1.4667 -1.384,-2.528 0,-1.65603 1.344,-3.00003 3,-3.00003 1.656,0 3,1.344 3,3.00003 0,1.0081 -0.498,1.9008 -1.261,2.4449 l 0.001,0.0013 c -0.04,0.0287 -0.081,0.0564 -0.123,0.0831 v 0.1942 c 0.206,-0.036 0.426,0.0257 0.585,0.1848 l 3.893,3.8932 c 0.26,0.2597 0.26,0.6808 0,0.9405 -0.259,0.2597 -0.68,0.2597 -0.94,0 l -1.305,-1.3048 c -0.682,0.4082 -1.433,0.7112 -2.233,0.8868 -0.352,0.0773 -0.709,0.1306 -1.077,0.1546 v -0.0014 l -0.002,1e-4 V 9.748 c 0.747,-0.2293 1.291,-0.9253 1.291,-1.7493 0,-1.01069 -0.819,-1.82936 -1.829,-1.82936 -1.011,0 -1.83,0.81867 -1.83,1.82936 0,0.824 0.544,1.52 1.291,1.7493 v 5.728 c -0.368,-0.024 -0.725,-0.0773 -1.077,-0.1546 -3.366,-0.7387 -5.883,-3.736 -5.883,-7.3227 z m 9.116,6.1169 v -1.9127 0.7918 c 0.195,-0.063 0.386,-0.1371 0.57,-0.2216 l 0.804,0.804 c -0.179,0.0963 -0.364,0.1842 -0.554,0.2631 v -0.0019 c -0.265,0.1104 -0.538,0.2033 -0.82,0.2773 z" fill="context-fill" /> + <path d="m 108,8.84 c 0.464,0 0.84,-0.3761 0.84,-0.84 0,-0.4639 -0.376,-0.84 -0.84,-0.84 -0.464,0 -0.84,0.3761 -0.84,0.84 0,0.4639 0.376,0.84 0.84,0.84 z" fill="context-fill" /> + <path d="m 127.999,0.5 c -4.142,0 -7.499,3.35733 -7.499,7.4987 0,3.5867 2.517,6.584 5.883,7.3227 0.352,0.0773 0.709,0.1306 1.077,0.1546 V 9.748 c -0.747,-0.2293 -1.291,-0.9253 -1.291,-1.7493 0,-1.01069 0.819,-1.82936 1.83,-1.82936 1.01,0 1.829,0.81867 1.829,1.82936 0,0.824 -0.544,1.52 -1.291,1.7493 v 5.728 l 0.002,-1e-4 v 0.0014 c 0.368,-0.024 0.725,-0.0773 1.077,-0.1546 0.8,-0.1756 1.551,-0.4786 2.233,-0.8868 l 1.305,1.3048 c 0.26,0.2597 0.681,0.2597 0.94,0 0.26,-0.2597 0.26,-0.6808 0,-0.9405 l -2.132,-2.1327 c -0.26,-0.2597 -0.681,-0.2597 -0.941,0 -0.249,0.2494 -0.259,0.6477 -0.03,0.9089 -0.18,0.0966 -0.365,0.1847 -0.555,0.2638 v -0.0019 c -0.265,0.1104 -0.538,0.2033 -0.82,0.2773 V 10.528 c 0.042,-0.0267 0.083,-0.0544 0.123,-0.0831 l -0.001,-0.0013 c 0.763,-0.5441 1.261,-1.4368 1.261,-2.4449 0,-1.65603 -1.344,-3.00003 -3,-3.00003 -1.656,0 -3,1.344 -3,3.00003 0,1.0613 0.552,1.9946 1.384,2.528 v 1.2171 c -1.447,-0.6245 -2.46,-2.0666 -2.46,-3.7431 0,-2.25337 1.824,-4.07736 4.078,-4.07736 2.253,0 4.077,1.82399 4.077,4.07736 0,1.3054 -0.614,2.4688 -1.569,3.2146 -0.272,0.2125 -0.572,0.3904 -0.893,0.5287 v 1.2507 c 0,-10e-5 0,10e-5 0,0 2.109,-0.68 3.635,-2.658 3.635,-4.994 0,-2.8987 -2.352,-5.2507 -5.25,-5.2507 -2.899,0 -5.251,2.35201 -5.251,5.2507 0,2.3352 1.524,4.3134 3.633,4.994 v 1.1213 c -2.712,-0.712 -4.712,-3.1786 -4.712,-6.1173 0,-2.05223 0.976,-3.87562 2.489,-5.03168 l 0.001,0.00133 c 1.065,-0.81333 2.395,-1.29636 3.839,-1.29636 1.736,0 3.308,0.69809 4.451,1.82893 1.158,1.14675 1.876,2.73814 1.876,4.49778 0,0.7114 -0.118,1.3952 -0.334,2.0331 h 0.002 c -0.223,0.6577 -0.551,1.2667 -0.964,1.807 l 0.834,0.8337 c 1.023,-1.2814 1.634,-2.9054 1.634,-4.6725 0,-2.08113 -0.848,-3.96426 -2.217,-5.32285 C 131.926,1.33143 130.06,0.5 127.999,0.5 Z" fill="context-fill" /> + <path d="m 128,8.84 c 0.464,0 0.84,-0.3761 0.84,-0.84 0,-0.4639 -0.376,-0.84 -0.84,-0.84 -0.464,0 -0.84,0.3761 -0.84,0.84 0,0.4639 0.376,0.84 0.84,0.84 z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 152.493,14.139 c 0.259,-0.2597 0.68,-0.2597 0.94,0 l 0.661,0.6612 c 0.26,0.2597 0.26,0.6808 0,0.9405 -0.259,0.2597 -0.68,0.2597 -0.94,0 l -0.661,-0.6612 c -0.26,-0.2597 -0.26,-0.6808 0,-0.9405 z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 140.5,7.9987 c 0,-4.14137 3.357,-7.4987 7.499,-7.4987 4.141,0 7.498,3.35733 7.498,7.4987 0,3.5867 -2.517,6.584 -5.882,7.3227 -0.352,0.0773 -0.71,0.1306 -1.078,0.1546 V 9.748 c 0.747,-0.2293 1.291,-0.9253 1.291,-1.7493 0,-1.01069 -0.819,-1.82936 -1.829,-1.82936 -1.011,0 -1.83,0.81867 -1.83,1.82936 0,0.824 0.544,1.52 1.291,1.7493 v 5.728 c -0.368,-0.024 -0.725,-0.0773 -1.077,-0.1546 -3.366,-0.7387 -5.883,-3.736 -5.883,-7.3227 z m 9.115,2.528 v 3.5893 c 2.712,-0.712 4.712,-3.1786 4.712,-6.1173 0,-3.49602 -2.832,-6.32802 -6.328,-6.32802 -3.496,0 -6.328,2.83199 -6.328,6.32802 0,2.9387 2,5.4053 4.712,6.1173 v -1.1213 c -2.109,-0.6806 -3.633,-2.6588 -3.633,-4.994 0,-2.89869 2.352,-5.2507 5.251,-5.2507 2.898,0 5.25,2.352 5.25,5.2507 0,2.336 -1.525,4.3147 -3.634,4.9947 v -1.2507 c 1.448,-0.624 2.461,-2.0667 2.461,-3.744 0,-2.25337 -1.824,-4.07736 -4.077,-4.07736 -2.254,0 -4.078,1.82399 -4.078,4.07736 0,1.6765 1.013,3.1186 2.46,3.7431 v -1.2171 c -0.832,-0.5334 -1.384,-1.4667 -1.384,-2.528 0,-1.65603 1.344,-3.00003 3,-3.00003 1.656,0 3,1.344 3,3.00003 0,1.0613 -0.552,1.9946 -1.384,2.528 z" fill="context-fill" /> + <path d="m 148,8.84 c 0.464,0 0.84,-0.3761 0.84,-0.84 0,-0.4639 -0.376,-0.84 -0.84,-0.84 -0.464,0 -0.84,0.3761 -0.84,0.84 0,0.4639 0.376,0.84 0.84,0.84 z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 168.001,2.75 c -2.899,0 -5.251,2.35201 -5.251,5.2507 0,2.336 1.525,4.3147 3.635,4.9947 v -1.2507 c -1.448,-0.624 -2.462,-2.0667 -2.462,-3.744 0,-2.25337 1.824,-4.07736 4.078,-4.07736 2.253,0 4.077,1.82399 4.077,4.07736 0,1.6773 -1.013,3.12 -2.461,3.744 v 1.2507 c 2.109,-0.68 3.634,-2.6587 3.634,-4.9947 0,-2.8987 -2.352,-5.2507 -5.25,-5.2507 z" fill="context-fill" /> + <path fill-rule="evenodd" d="m 167.999,0.5 c -4.142,0 -7.499,3.35733 -7.499,7.4987 0,3.5867 2.517,6.584 5.883,7.3227 0.352,0.0773 0.709,0.1306 1.077,0.1546 V 9.748 c -0.747,-0.2293 -1.291,-0.9253 -1.291,-1.7493 0,-1.01069 0.819,-1.82936 1.83,-1.82936 1.01,0 1.829,0.81867 1.829,1.82936 0,0.824 -0.544,1.52 -1.291,1.7493 v 5.728 c 0.368,-0.024 0.726,-0.0773 1.078,-0.1546 3.365,-0.7387 5.882,-3.736 5.882,-7.3227 0,-4.14137 -3.357,-7.4987 -7.498,-7.4987 z m 1.616,13.616 v -3.5893 c 0.832,-0.5334 1.384,-1.4667 1.384,-2.528 0,-1.65603 -1.344,-3.00003 -3,-3.00003 -1.656,0 -3,1.344 -3,3.00003 0,1.0613 0.552,1.9946 1.384,2.528 v 3.5893 c -2.712,-0.712 -4.712,-3.1786 -4.712,-6.1173 0,-3.49603 2.832,-6.32802 6.328,-6.32802 3.496,0 6.328,2.832 6.328,6.32802 0,2.9387 -2,5.4053 -4.712,6.1173 z" fill="context-fill" /> + <path d="m 168,8.84 c 0.464,0 0.84,-0.3761 0.84,-0.84 0,-0.4639 -0.376,-0.84 -0.84,-0.84 -0.464,0 -0.84,0.3761 -0.84,0.84 0,0.4639 0.376,0.84 0.84,0.84 z" fill="context-fill" /> +</svg> diff --git a/toolkit/components/torconnect/content/torConnectTitlebarStatus.css b/toolkit/components/torconnect/content/torConnectTitlebarStatus.css new file mode 100644 index 0000000000000000000000000000000000000000..e1631bb57b3c0e8d7686386b1e4eb0772459b591 --- /dev/null +++ b/toolkit/components/torconnect/content/torConnectTitlebarStatus.css @@ -0,0 +1,73 @@ +#tor-connect-titlebar-status:not([hidden]) { + display: flex; + align-items: center; + /* Want same as #private-browsing-indicator-with-label */ + margin-inline: 7px; +} + +#tor-connect-titlebar-status-label { + margin-inline: 6px; + white-space: nowrap; +} + +#tor-connect-titlebar-status img { + -moz-context-properties: fill, stroke; + fill: currentColor; + stroke: currentColor; + width: 16px; + height: 16px; + object-fit: none; + --num-animation-steps: 8; + /* First frame has no offset. */ + --tor-not-connected-offset: 0; + /* Each frame/step is offset by 20px from the previous. */ + --tor-connected-offset: calc(-20px * var(--num-animation-steps)); + object-position: var(--tor-not-connected-offset); +} + +#tor-connect-titlebar-status.tor-connect-status-potentially-blocked img { + /* NOTE: context-stroke is only used for the first "frame" for the slash. When + * we assign the potentially-blocked class, we do *not* expect to be connected + * at the same time, so we only expect this first frame to be visible in this + * state. */ + stroke: #c50042; +} + +@media (prefers-color-scheme: dark) { + #tor-connect-titlebar-status.tor-connect-status-potentially-blocked img { + stroke: #ff9aa2; + } +} + +#tor-connect-titlebar-status.tor-connect-status-connected img { + object-position: var(--tor-connected-offset); +} + +#tor-connect-titlebar-status.tor-connect-status-connected { + color: var(--tor-accent-color); +} + +@keyframes onion-not-connected-to-connected { + from { + object-position: var(--tor-not-connected-offset); + } + + to { + object-position: var(--tor-connected-offset); + } +} + +@media (prefers-reduced-motion: no-preference) { + #tor-connect-titlebar-status.tor-connect-status-connected.tor-connect-status-animate-transition { + transition: color 1000ms; + } + + #tor-connect-titlebar-status.tor-connect-status-connected.tor-connect-status-animate-transition img { + animation-name: onion-not-connected-to-connected; + animation-delay: 200ms; + animation-fill-mode: both; + /* Run animation at 60 frames-per-second. */ + animation-duration: calc(var(--num-animation-steps) * 1000ms / 60); + animation-timing-function: steps(var(--num-animation-steps)); + } +} diff --git a/toolkit/components/torconnect/content/torConnectTitlebarStatus.js b/toolkit/components/torconnect/content/torConnectTitlebarStatus.js new file mode 100644 index 0000000000000000000000000000000000000000..37fffc604424ff90a209b6ae52bd3bda2e236467 --- /dev/null +++ b/toolkit/components/torconnect/content/torConnectTitlebarStatus.js @@ -0,0 +1,153 @@ +/* eslint-env mozilla/browser-window */ + +/** + * A TorConnect status shown in the application title bar. + */ +var gTorConnectTitlebarStatus = { + /** + * The status element in the title bar. + * + * @type {Element} + */ + node: null, + /** + * The status label. + * + * @type {Element} + */ + label: null, + /** + * Whether we are connected, or null if the connection state is not yet known. + * + * @type {bool?} + */ + connected: null, + + /** + * Initialize the component. + */ + init() { + const { TorStrings } = ChromeUtils.importESModule( + "resource://gre/modules/TorStrings.sys.mjs" + ); + + this._strings = TorStrings.torConnect; + + this.node = document.getElementById("tor-connect-titlebar-status"); + this.label = document.getElementById("tor-connect-titlebar-status-label"); + // The title also acts as an accessible name for the role="status". + this.node.setAttribute("title", this._strings.titlebarStatusName); + + this._observeTopic = TorConnectTopics.StageChange; + this._stateListener = { + observe: (subject, topic) => { + if (topic !== this._observeTopic) { + return; + } + this._torConnectStateChanged(); + }, + }; + Services.obs.addObserver(this._stateListener, this._observeTopic); + + this._torConnectStateChanged(); + }, + + /** + * De-initialize the component. + */ + uninit() { + Services.obs.removeObserver(this._stateListener, this._observeTopic); + }, + + /** + * Callback for when the TorConnect state changes. + */ + _torConnectStateChanged() { + let textId; + let connected = false; + let potentiallyBlocked = false; + switch (TorConnect.stageName) { + case TorConnectStage.Disabled: + // Hide immediately. + this.node.hidden = true; + return; + case TorConnectStage.Bootstrapped: + textId = "titlebarStatusConnected"; + connected = true; + break; + case TorConnectStage.Bootstrapping: + textId = "titlebarStatusConnecting"; + break; + default: + if (TorConnect.potentiallyBlocked) { + textId = "titlebarStatusPotentiallyBlocked"; + potentiallyBlocked = true; + } else { + textId = "titlebarStatusNotConnected"; + } + break; + } + this.label.textContent = this._strings[textId]; + if (this.connected !== connected) { + // When we are transitioning from + // this.connected = false + // to + // this.connected = true + // we want to animate the transition from the not connected state to the + // connected state (provided prefers-reduced-motion is not set). + // + // If instead we are transitioning directly from the initial state + // this.connected = null + // to + // this.connected = true + // we want to immediately show the connected state without any transition. + // + // In both cases, the status will eventually be hidden. + // + // We only expect this latter case when opening a new window after + // bootstrapping has already completed. See tor-browser#41850. + this.node.classList.toggle( + "tor-connect-status-animate-transition", + connected && this.connected !== null + ); + this.node.classList.toggle("tor-connect-status-connected", connected); + this.connected = connected; + if (connected) { + this._startHiding(); + } else { + // We can leave the connected state when we are no longer Bootstrapped + // because the underlying tor process exited early and needs a + // restart. In this case we want to re-show the status. + this._stopHiding(); + } + } + this.node.classList.toggle( + "tor-connect-status-potentially-blocked", + potentiallyBlocked + ); + }, + + /** + * Mark the component to be hidden after some delay. + */ + _startHiding() { + if (this._hidingTimeout) { + // Already hiding. + return; + } + this._hidingTimeout = setTimeout(() => { + this.node.hidden = true; + }, 5000); + }, + + /** + * Re-show the component immediately. + */ + _stopHiding() { + if (this._hidingTimeout) { + clearTimeout(this._hidingTimeout); + this._hidingTimeout = 0; + } + this.node.hidden = false; + }, +}; diff --git a/toolkit/components/torconnect/content/torConnectUrlbarButton.js b/toolkit/components/torconnect/content/torConnectUrlbarButton.js new file mode 100644 index 0000000000000000000000000000000000000000..299fcd69c1ba3b2d576593bd0bcf586b5e8a6194 --- /dev/null +++ b/toolkit/components/torconnect/content/torConnectUrlbarButton.js @@ -0,0 +1,156 @@ +/* eslint-env mozilla/browser-window */ + +/** + * A "Connect" button shown in the urlbar when not connected to tor and in tabs + * other than about:torconnect. + */ +var gTorConnectUrlbarButton = { + /** + * The urlbar button node. + * + * @type {Element} + */ + button: null, + /** + * Whether we are active. + * + * @type {boolean} + */ + _isActive: false, + /** + * Whether we are in the "about:torconnect" tab. + * + * @type {boolean} + */ + // We init to "true" so that the button can only appear after the first page + // load. + _inAboutTorConnectTab: true, + + /** + * Initialize the button. + */ + init() { + if (this._isActive) { + return; + } + this._isActive = true; + + const { TorStrings } = ChromeUtils.importESModule( + "resource://gre/modules/TorStrings.sys.mjs" + ); + + this.button = document.getElementById("tor-connect-urlbar-button"); + document.getElementById("tor-connect-urlbar-button-label").value = + TorStrings.torConnect.torConnectButton; + this.button.addEventListener("click", event => { + if (event.button !== 0) { + return; + } + this.connect(); + }); + this.button.addEventListener("keydown", event => { + if (event.key !== "Enter" && event.key !== " ") { + return; + } + this.connect(); + }); + + this._observeTopic = TorConnectTopics.StageChange; + this._stateListener = { + observe: (subject, topic) => { + if (topic !== this._observeTopic) { + return; + } + this._torConnectStageChanged(); + }, + }; + Services.obs.addObserver(this._stateListener, this._observeTopic); + + this._locationListener = { + onLocationChange: (webProgress, request, locationURI, flags) => { + if ( + webProgress.isTopLevel && + !(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) + ) { + this._inAboutTorConnectTab = + gBrowser.selectedBrowser.currentURI?.spec.startsWith( + "about:torconnect" + ); + this._updateButtonVisibility(); + } + }, + }; + // Notified of new locations for the currently selected browser (tab) *and* + // switching selected browser. + gBrowser.addProgressListener(this._locationListener); + + this._torConnectStageChanged(); + }, + + /** + * Deactivate and de-initialize the button. + */ + uninit() { + if (!this._isActive) { + return; + } + this._isActive = false; + + Services.obs.removeObserver(this._stateListener, this._observeTopic); + gBrowser.removeProgressListener(this._locationListener); + this._updateButtonVisibility(); + }, + + /** + * Begin the tor connection bootstrapping process. + */ + connect() { + TorConnect.openTorConnect({ beginBootstrapping: "soft" }); + }, + + /** + * Callback for when the TorConnect stage changes. + */ + _torConnectStageChanged() { + if (TorConnect.stageName === TorConnectStage.Disabled) { + // NOTE: We do not uninit early when we reach the + // TorConnectStage.Bootstrapped stage because we can still leave the + // Bootstrapped stage if the tor process exists early and needs a restart. + this.uninit(); + return; + } + this._updateButtonVisibility(); + }, + + /** + * Callback when the TorConnect state, current browser location, or activation + * state changes. + */ + _updateButtonVisibility() { + if (!this.button) { + return; + } + // NOTE: We do not manage focus when hiding the button. We only expect to + // move from "not hidden" to "hidden" when: + // + switching tabs to "about:torconnect", or + // + starting bootstrapping. + // + // When switching tabs, the normal tab switching logic will eventually move + // focus to the new tab or url bar, so whilst the focus may be lost + // temporarily when we hide the button, it will be re-established quickly on + // tab switch. + // + // And we don't expect bootstrapping to start whilst outside of the + // "about:torconnect", and the automatic bootstrapping should only trigger + // at the initial start. + this.button.hidden = + !this._isActive || + this._inAboutTorConnectTab || + !TorConnect.enabled || + !TorConnect.canBeginBootstrap; + this.button.classList.toggle( + "tor-urlbar-button-plain", + TorConnect.potentiallyBlocked + ); + }, +}; diff --git a/toolkit/components/torconnect/jar.mn b/toolkit/components/torconnect/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..45dc5823f920ebf70dc1031fde7c2c0f5a958432 --- /dev/null +++ b/toolkit/components/torconnect/jar.mn @@ -0,0 +1,14 @@ +toolkit.jar: + content/global/torconnect/torConnectUrlbarButton.js (content/torConnectUrlbarButton.js) + content/global/torconnect/torConnectTitlebarStatus.js (content/torConnectTitlebarStatus.js) + content/global/torconnect/torConnectTitlebarStatus.css (content/torConnectTitlebarStatus.css) + content/global/torconnect/aboutTorConnect.css (content/aboutTorConnect.css) + content/global/torconnect/aboutTorConnect.html (content/aboutTorConnect.html) + content/global/torconnect/aboutTorConnect.js (content/aboutTorConnect.js) + content/global/torconnect/arrow-right.svg (content/arrow-right.svg) + content/global/torconnect/bridge.svg (content/bridge.svg) + content/global/torconnect/connection-failure.svg (content/connection-failure.svg) + content/global/torconnect/connection-location.svg (content/connection-location.svg) + content/global/torconnect/tor-connect.svg (content/tor-connect.svg) + content/global/torconnect/tor-not-connected-to-connected-animated.svg (content/tor-not-connected-to-connected-animated.svg) + content/global/torconnect/tor-connect-broken.svg (content/tor-connect-broken.svg) diff --git a/toolkit/components/torconnect/moz.build b/toolkit/components/torconnect/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..02b0d55e23063e9064e63fc60aaccfe817630696 --- /dev/null +++ b/toolkit/components/torconnect/moz.build @@ -0,0 +1,6 @@ +JAR_MANIFESTS += ["jar.mn"] + +FINAL_TARGET_FILES.actors += [ + "TorConnectChild.sys.mjs", + "TorConnectParent.sys.mjs", +] diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp index 585a957fd8a1467dc262bd1ca2058584fd8762c9..a0bba75f07602225632847c71003f5f16fc2224b 100644 --- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp +++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp @@ -2371,7 +2371,8 @@ static void SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner, "complicated, and this is a conservative behavior to avoid " "exempting something that shouldn't be. It also presents a " "uniform behavior for something that's very browser-related.", - RFPTarget::RoundWindowSize)) { + RFPTarget::RoundWindowSize) && + nsContentUtils::ShouldRoundWindowSizeForResistingFingerprinting()) { /* Unlike position, force size out-of-bounds check only if size actually was specified. Otherwise, intrinsically sized windows are broken. */ diff --git a/toolkit/content/.eslintrc.js b/toolkit/content/.eslintrc.js index b56cafb08b90c98eaec2f119d35ff78807b3dfcb..558512e82ad420365801cc4d8f1f032931508b52 100644 --- a/toolkit/content/.eslintrc.js +++ b/toolkit/content/.eslintrc.js @@ -19,6 +19,6 @@ module.exports = { rules: { // XXX Bug 1358949 - This should be reduced down - probably to 20 or to // be removed & synced with the mozilla/recommended value. - complexity: ["error", 48], + complexity: ["error", 51], }, }; diff --git a/toolkit/content/aboutNetError.html b/toolkit/content/aboutNetError.html index 965038ad45f1f07a3368cf87f6441a462327bc3a..56a42a7c7d0587ed098eb89beede68dfad50a002 100644 --- a/toolkit/content/aboutNetError.html +++ b/toolkit/content/aboutNetError.html @@ -20,6 +20,7 @@ <link rel="localization" href="branding/brand.ftl" /> <link rel="localization" href="toolkit/neterror/certError.ftl" /> <link rel="localization" href="toolkit/neterror/netError.ftl" /> + <link rel="localization" href="toolkit/global/tor-browser.ftl" /> </head> <body> <div class="container"> diff --git a/toolkit/content/aboutNetError.mjs b/toolkit/content/aboutNetError.mjs index f5a2b068746286739669528621a65328d3933b27..27dc23ff75d7eeaa3896c8031565446351f58cde 100644 --- a/toolkit/content/aboutNetError.mjs +++ b/toolkit/content/aboutNetError.mjs @@ -284,7 +284,93 @@ function recordTRREventTelemetry( } } -function initPage() { +/** + * Initialize the onion error page. + * + * @return {boolean} Whether the page was initialized as an onion error page. + */ +function initOnionError() { + const docTitle = document.querySelector("title"); + + if (getCSSClass() === "onionAuthPrompt") { + // Only showing the authorization prompt. The page will be blank. + document.l10n.setAttributes(docTitle, "onion-neterror-authorization-title"); + return true; + } + + const onionErrors = { + // Tor SOCKS error 0xF0: + "onionServices.descNotFound": { + headerId: "onion-neterror-not-found-header", + descriptionId: "onion-neterror-not-found-description", + }, + // Tor SOCKS error 0xF1: + "onionServices.descInvalid": { + headerId: "onion-neterror-unreachable-header", + descriptionId: "onion-neterror-unreachable-description", + }, + // Tor SOCKS error 0xF2: + "onionServices.introFailed": { + headerId: "onion-neterror-disconnected-header", + descriptionId: "onion-neterror-disconnected-description", + }, + // Tor SOCKS error 0xF3: + "onionServices.rendezvousFailed": { + headerId: "onion-neterror-connection-failed-header", + descriptionId: "onion-neterror-connection-failed-description", + }, + // Tor SOCKS error 0xF4: + "onionServices.clientAuthMissing": { + headerId: "onion-neterror-missing-authentication-header", + descriptionId: "onion-neterror-missing-authentication-description", + }, + // Tor SOCKS error 0xF5: + "onionServices.clientAuthIncorrect": { + headerId: "onion-neterror-incorrect-authentication-header", + descriptionId: "onion-neterror-incorrect-authetication-description", + }, + // Tor SOCKS error 0xF6: + "onionServices.badAddress": { + headerId: "onion-neterror-invalid-address-header", + descriptionId: "onion-neterror-invalid-address-description", + }, + // Tor SOCKS error 0xF7: + "onionServices.introTimedOut": { + headerId: "onion-neterror-timed-out-header", + descriptionId: "onion-neterror-timed-out-description", + }, + }; + + if (!Object.hasOwn(onionErrors, gErrorCode)) { + return false; + } + + document.body.classList.add("onion-error"); + + document.l10n.setAttributes(docTitle, "onion-neterror-page-title"); + document.l10n.setAttributes( + document.querySelector(".title-text"), + onionErrors[gErrorCode].headerId + ); + document.l10n.setAttributes( + document.getElementById("errorShortDesc"), + onionErrors[gErrorCode].descriptionId + ); + + const tryAgain = document.getElementById("netErrorButtonContainer"); + tryAgain.hidden = false; + + const learnMore = document.getElementById("learnMoreContainer"); + learnMore.hidden = false; + const learnMoreLink = document.getElementById("learnMoreLink"); + learnMoreLink.href = "about:manual#onion-services"; + + setFocus("#netErrorButtonContainer > .try-again"); + + return true; +} + +async function initPage() { // We show an offline support page in case of a system-wide error, // when a user cannot connect to the internet and access the SUMO website. // For example, clock error, which causes certerrors across the web or @@ -353,6 +439,10 @@ function initPage() { document.body.classList.add("neterror"); + if (initOnionError()) { + return; + } + let longDesc = document.getElementById("errorLongDesc"); const tryAgain = document.getElementById("netErrorButtonContainer"); tryAgain.hidden = false; @@ -465,6 +555,16 @@ function initPage() { learnMore.hidden = false; document.body.className = "certerror"; break; + + case "proxyConnectFailure": + if (await RPMSendQuery("ShouldShowTorConnect")) { + // pass orginal destination as redirect param + const encodedRedirect = encodeURIComponent(document.location.href); + document.location.replace( + `about:torconnect?redirect=${encodedRedirect}` + ); + } + break; } if (!KNOWN_ERROR_TITLE_IDS.has(bodyTitleId)) { diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 2dedc0ffdef14d9b5509c5d3120a606808eae1a3..eeae407b0d128bd14e5dd85cde91d2609744ff8b 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -23,6 +23,7 @@ toolkit.jar: #endif content/global/aboutServiceWorkers.js content/global/aboutServiceWorkers.xhtml +#ifdef MOZ_WEBRTC content/global/aboutwebrtc/aboutWebrtc.css (aboutwebrtc/aboutWebrtc.css) content/global/aboutwebrtc/aboutWebrtc.mjs (aboutwebrtc/aboutWebrtc.mjs) content/global/aboutwebrtc/graph.mjs (aboutwebrtc/graph.mjs) @@ -31,16 +32,19 @@ toolkit.jar: content/global/aboutwebrtc/disclosure.mjs (aboutwebrtc/disclosure.mjs) content/global/aboutwebrtc/copyButton.mjs (aboutwebrtc/copyButton.mjs) content/global/aboutwebrtc/aboutWebrtc.html (aboutwebrtc/aboutWebrtc.html) +#endif content/global/aboutSupport.js * content/global/aboutSupport.xhtml -#ifndef MOZ_GLEAN_ANDROID +#ifdef MOZ_TELEMETRY_REPORTING +# ifndef MOZ_GLEAN_ANDROID content/global/aboutGlean.js content/global/aboutGlean.html content/global/aboutGlean.css -#endif +# endif content/global/aboutTelemetry.js content/global/aboutTelemetry.xhtml content/global/aboutTelemetry.css +#endif content/global/aboutUrlClassifier.js content/global/aboutUrlClassifier.xhtml content/global/aboutUrlClassifier.css @@ -152,3 +156,5 @@ toolkit.jar: # Third party files content/global/third_party/d3/d3.js (/third_party/js/d3/d3.js) content/global/third_party/cfworker/json-schema.js (/third_party/js/cfworker/json-schema.js) + + content/global/pt_config.json (pt_config.json) diff --git a/toolkit/content/license.html b/toolkit/content/license.html index c7d530621c5d2d5291b8b486e73c24a1a8b2ec62..f02898e10e656b244e2d22e7b8a13bdb2c5e686e 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -4148,6 +4148,8 @@ product. <li><code>js/src/vm/Float16.h</code>(the code contained in the half namespace)</li> <li><code>toolkit/components/resistfingerprinting/content/gl-matrix.js</code></li> <li><code>toolkit/components/resistfingerprinting/content/ssdeep.js</code></li> + <li><code>toolkit/modules/Bech32Decode.sys.mjs</code></li> + <li><code>toolkit/modules/QRCode.sys.mjs</code></li> </ul> See the individual LICENSE files or headers for copyright owners.</p> </td> diff --git a/toolkit/content/pt_config.json b/toolkit/content/pt_config.json new file mode 100644 index 0000000000000000000000000000000000000000..0ae75a77ec9b627c61bddfe5b85b1175462eec65 --- /dev/null +++ b/toolkit/content/pt_config.json @@ -0,0 +1,32 @@ +{ + "_comment": "Used for dev build, replaced for release builds in tor-browser-build. This file is copied from tor-browser-build 4ffa9e31:projects/tor-expert-bundle/pt_config.json", + "recommendedDefault" : "obfs4", + "pluggableTransports" : { + "lyrebird" : "ClientTransportPlugin meek_lite,obfs2,obfs3,obfs4,scramblesuit,webtunnel exec ${pt_path}lyrebird${pt_extension}", + "snowflake" : "ClientTransportPlugin snowflake exec ${pt_path}snowflake-client${pt_extension}", + "conjure" : "ClientTransportPlugin conjure exec ${pt_path}conjure-client${pt_extension} -registerURL https://registration.refraction.network/api" + }, + "bridges" : { + "meek-azure" : [ + "meek_lite 192.0.2.18:80 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com", + "meek_lite 192.0.2.20:80 url=https://1314488750.rsc.cdn77.org front=www.phpmyadmin.net utls=HelloRandomizedALPN" + ], + "obfs4" : [ + "obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1", + "obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0", + "obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0", + "obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0", + "obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0", + "obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0", + "obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0", + "obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0", + "obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0", + "obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0", + "obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0" + ], + "snowflake" : [ + "snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.antisip.com:3478,stun:stun.epygi.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.mixvoip.com:3478,stun:stun.nextcloud.com:3478,stun:stun.bethesda.net:3478,stun:stun.nextcloud.com:443 utls-imitate=hellorandomizedalpn", + "snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.antisip.com:3478,stun:stun.epygi.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.mixvoip.com:3478,stun:stun.nextcloud.com:3478,stun:stun.bethesda.net:3478,stun:stun.nextcloud.com:443 utls-imitate=hellorandomizedalpn" + ] + } +} diff --git a/toolkit/content/widgets/infobar.css b/toolkit/content/widgets/infobar.css index 7818f1ef1dcc62e184bd5e3e8d6d936acf77d2ea..af7897f5ca3d88860b0e6e1292f3cb2991242184 100644 --- a/toolkit/content/widgets/infobar.css +++ b/toolkit/content/widgets/infobar.css @@ -51,7 +51,7 @@ color: var(--info-bar-text-color); &::before { - background-image: linear-gradient(0deg, #9059ff 0%, #ff4aa2 52.08%, #ffbd4f 100%); + background-image: linear-gradient(0deg, #00dbde 0%, #9a89ff 50%, #fc00ff 100%); } } } diff --git a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs index 5b1e9ef6d4d7342ea1dfa3f604155e0f6a7a3ad5..0fc78c0c1d83915843199b7ae908b12419237488 100644 --- a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs +++ b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs @@ -64,12 +64,14 @@ export default class MozMessageBar extends MozLitElement { dismissable: { type: Boolean }, messageL10nId: { type: String }, messageL10nArgs: { type: String }, + useAlertRole: { type: Boolean }, }; constructor() { super(); this.type = "info"; this.dismissable = false; + this.useAlertRole = true; } onSlotchange() { @@ -77,11 +79,6 @@ export default class MozMessageBar extends MozLitElement { this.actionsEl.classList.toggle("active", actions.length); } - connectedCallback() { - super.connectedCallback(); - this.setAttribute("role", "alert"); - } - disconnectedCallback() { super.disconnectedCallback(); this.dispatchEvent(new CustomEvent("message-bar:close")); @@ -91,6 +88,17 @@ export default class MozMessageBar extends MozLitElement { return this.supportLinkSlot.assignedElements(); } + setAlertRole() { + // Wait a little for this to render before setting the role for more + // consistent alerts to screen readers. + this.useAlertRole = false; + window.requestAnimationFrame(() => { + window.requestAnimationFrame(() => { + this.useAlertRole = true; + }); + }); + } + iconTemplate() { let iconData = messageTypeToIconData[this.type]; if (iconData) { @@ -111,7 +119,9 @@ export default class MozMessageBar extends MozLitElement { headingTemplate() { if (this.heading) { - return html`<strong class="heading">${this.heading}</strong>`; + return html` + <strong id="heading" class="heading">${this.heading}</strong> + `; } return ""; } @@ -137,13 +147,18 @@ export default class MozMessageBar extends MozLitElement { rel="stylesheet" href="chrome://global/content/elements/moz-message-bar.css" /> - <div class="container"> + <div + class="container" + role=${ifDefined(this.useAlertRole ? "alert" : undefined)} + aria-labelledby=${this.heading ? "heading" : "content"} + aria-describedby=${ifDefined(this.heading ? "content" : undefined)} + > <div class="content"> <div class="text-container"> ${this.iconTemplate()} <div class="text-content"> ${this.headingTemplate()} - <div> + <div id="content"> <span class="message" data-l10n-id=${ifDefined(this.messageL10nId)} diff --git a/toolkit/content/widgets/moz-support-link/moz-support-link.mjs b/toolkit/content/widgets/moz-support-link/moz-support-link.mjs index df6ebac2a5671f5c03bad37d6f9d5e1e11368ce5..22d80c47b2045a872145da424a8ddd5aa9384d87 100644 --- a/toolkit/content/widgets/moz-support-link/moz-support-link.mjs +++ b/toolkit/content/widgets/moz-support-link/moz-support-link.mjs @@ -17,7 +17,9 @@ window.MozXULElement?.insertFTLIfNeeded("toolkit/global/mozSupportLink.ftl"); export default class MozSupportLink extends HTMLAnchorElement { static SUPPORT_URL = "https://www.mozilla.org/"; static get observedAttributes() { - return ["support-page", "utm-content"]; + // We add tor-manual-page for pages hosted at tor project. Also shared with + // base-browser/mullvad-browser. See tor-browser#42583. + return ["support-page", "utm-content", "tor-manual-page"]; } /** @@ -64,6 +66,23 @@ export default class MozSupportLink extends HTMLAnchorElement { !this.getAttribute("data-l10n-name") && !this.childElementCount ) { + const fixupL10nId = this.getAttribute("data-basebrowser-l10n-fixup"); + if (fixupL10nId) { + document.l10n.formatValue(fixupL10nId).then(title => { + this.setAttribute("title", title); + // NOTE: Mozilla adds identical aria-label and title attributes. This is + // generally bad practice because this link has no text content, so the + // title alone will already act as the accessible name. + // Normally setting both aria-label and title will lead to the title being + // used as the accessible description, but since they are identical + // the LocalAccessible::Description method will make an exception and keep + // the description empty. + // Since this component is outside of our fork's control, we follow the + // same practice just in case Mozilla ever adds some text content. + this.setAttribute("aria-label", title); + }); + return; + } document.l10n.setAttributes(this, "moz-support-link-text"); } document.l10n.translateFragment(this); @@ -87,13 +106,35 @@ export default class MozSupportLink extends HTMLAnchorElement { } attributeChangedCallback(attrName) { - if (attrName === "support-page" || attrName === "utm-content") { + if ( + attrName === "support-page" || + attrName === "utm-content" || + attrName === "tor-manual-page" + ) { this.#setHref(); } } #setHref() { + let torManualPage = this.getAttribute("tor-manual-page"); + if (torManualPage) { + this.href = `about:manual#${torManualPage}`; + return; + } let supportPage = this.getAttribute("support-page") ?? ""; + // For tor-browser we sometimes want to override firefox support links with + // our own. + // See tor-browser#40899. + switch (supportPage) { + case "preferences": + // Shown twice in preferences, both as `{ -brand-short-name } Support`. + // Instead of directing to support for preferences, we link to general + // tor browser support. + // See tor-browser#32092. + this.href = "https://support.torproject.org/tbb"; + return; + // Fall through to support.mozilla.org + } let base = MozSupportLink.SUPPORT_URL + supportPage; this.href = this.hasAttribute("utm-content") ? formatUTMParams(this.getAttribute("utm-content"), base) @@ -113,21 +154,7 @@ customElements.define("moz-support-link", MozSupportLink, { extends: "a" }); * Otherwise the url in unmodified form. */ export function formatUTMParams(contentAttribute, url) { - if (!contentAttribute) { - return url; - } - let parsedUrl = new URL(url); - let domain = `.${parsedUrl.hostname}`; - if ( - !domain.endsWith(".mozilla.org") && - // For testing: addons-dev.allizom.org and addons.allizom.org - !domain.endsWith(".allizom.org") - ) { - return url; - } - - parsedUrl.searchParams.set("utm_source", "firefox-browser"); - parsedUrl.searchParams.set("utm_medium", "firefox-browser"); - parsedUrl.searchParams.set("utm_content", contentAttribute); - return parsedUrl.href; + // Do not add utm parameters. See tor-browser#42583. + // NOTE: This method is also present in about:addons. + return url; } diff --git a/toolkit/content/widgets/moz-toggle/moz-toggle.mjs b/toolkit/content/widgets/moz-toggle/moz-toggle.mjs index 1c6fb5a5fc3aa71fbaae0c51cb55c5bfbfa4336f..96b864c3df50a03ae9f0b413492bae696618b926 100644 --- a/toolkit/content/widgets/moz-toggle/moz-toggle.mjs +++ b/toolkit/content/widgets/moz-toggle/moz-toggle.mjs @@ -30,6 +30,10 @@ export default class MozToggle extends MozLitElement { ariaLabel: { type: String, attribute: "aria-label" }, accessKeyAttribute: { type: String, attribute: "accesskey", reflect: true }, accessKey: { type: String, state: true }, + // Extension for tor-browser. Used for tor-browser#41333. + title: { type: String, attribute: "title" }, + // Extension for tor-browser. Used for tor-browser#40837. + labelAlignAfter: { type: Boolean, attribute: "label-align-after" }, }; static get queries() { @@ -94,6 +98,12 @@ export default class MozToggle extends MozLitElement { buttonTemplate() { const { pressed, disabled, description, ariaLabel, handleClick } = this; + // For tor-browser, if we have a title we use it as the aria-description. + // Used for tor-browser#41333. + // Only set the description using the title if it differs from the + // accessible name derived from the label. + const label = ariaLabel || this.label; + const ariaDescription = label === this.title ? undefined : this.title; return html` <button id="moz-toggle-button" @@ -103,6 +113,7 @@ export default class MozToggle extends MozLitElement { ?disabled=${disabled} aria-pressed=${pressed} aria-label=${ifDefined(ariaLabel ?? undefined)} + aria-description=${ifDefined(ariaDescription ?? undefined)} aria-describedby=${ifDefined( description ? "moz-toggle-description" : undefined )} @@ -113,6 +124,11 @@ export default class MozToggle extends MozLitElement { } render() { + // For tor-browser, we want to be able to place the label after the toggle + // as well. + // Used for the enable-bridges switch tor-browser#40837. + const labelAlignAfter = this.labelAlignAfter; + return html` <link rel="stylesheet" @@ -127,11 +143,12 @@ export default class MozToggle extends MozLitElement { for="moz-toggle-button" shownaccesskey=${ifDefined(this.accessKey)} > + ${labelAlignAfter ? this.buttonTemplate() : ""} <span> ${this.label} ${!this.description ? this.supportLinkTemplate() : ""} </span> - ${this.buttonTemplate()} + ${labelAlignAfter ? "" : this.buttonTemplate()} </label> ` : this.buttonTemplate()} diff --git a/toolkit/content/widgets/notificationbox.js b/toolkit/content/widgets/notificationbox.js index fc3e553ca4245cb42cf79a066c2906e900343cd6..8d37165da91db1ae9701c6a4a23c23262c76dfb8 100644 --- a/toolkit/content/widgets/notificationbox.js +++ b/toolkit/content/widgets/notificationbox.js @@ -703,17 +703,6 @@ } } - setAlertRole() { - // Wait a little for this to render before setting the role for more - // consistent alerts to screen readers. - this.removeAttribute("role"); - window.requestAnimationFrame(() => { - window.requestAnimationFrame(() => { - this.setAttribute("role", "alert"); - }); - }); - } - handleEvent(e) { if (e.type == "click" && e.target.localName != "label") { return; diff --git a/toolkit/locales-preview/base-browser-no-translate.ftl b/toolkit/locales-preview/base-browser-no-translate.ftl new file mode 100644 index 0000000000000000000000000000000000000000..5e26c1cae7e3319a20711e63cf066ed9b0c2c396 --- /dev/null +++ b/toolkit/locales-preview/base-browser-no-translate.ftl @@ -0,0 +1 @@ +# base-browser strings that should *not* be sent to translators on Weblate. diff --git a/toolkit/locales-preview/tor-browser-no-translate.ftl b/toolkit/locales-preview/tor-browser-no-translate.ftl new file mode 100644 index 0000000000000000000000000000000000000000..6e5e3de4c8726f4c3553888c8e4eeb654b5aa1cb --- /dev/null +++ b/toolkit/locales-preview/tor-browser-no-translate.ftl @@ -0,0 +1,16 @@ +# tor-browser strings that should *not* be sent to translators on Weblate. + +## Bridge pass invite dialog. +## Temporary until tor-browser#42385 + +lox-invite-dialog-title = + .title = Bridge pass invites +lox-invite-dialog-description = You can ask the bridge bot to create a new invite, which you can share with a trusted contact to give them their own bridge pass. Each invite can only be redeemed once, but you will unlock access to more invites over time. +lox-invite-dialog-request-button = Request new invite +lox-invite-dialog-connecting = Connecting to bridge pass server… +lox-invite-dialog-no-server-error = Unable to connect to bridge pass server. +lox-invite-dialog-generic-invite-error = Failed to create a new invite. +lox-invite-dialog-invites-label = Created invites: +lox-invite-dialog-menu-item-copy-invite = + .label = Copy invite + .accesskey = C diff --git a/toolkit/locales/en-US/toolkit/global/base-browser.ftl b/toolkit/locales/en-US/toolkit/global/base-browser.ftl new file mode 100644 index 0000000000000000000000000000000000000000..aaefc7665940069b6afa86512889549aa8ebf06c --- /dev/null +++ b/toolkit/locales/en-US/toolkit/global/base-browser.ftl @@ -0,0 +1,168 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Language notification + +# $language (String) - The language Tor Browser is displayed in (already translated). +language-notification-label-system = { -brand-short-name } has set your display language to { $language } based on your system’s language. +# This is shown when the system language is not supported, so we fall back to another language instead. +# $language (String) - The language Tor Browser is displayed in (already translated). +language-notification-label = { -brand-short-name } has set your display language to { $language }. +language-notification-button = Change Language… + +## Fullscreen/maximization notification shown when letterboxing is disabled + +basebrowser-rfp-maximize-warning-message = Maximizing the browser window can allow websites to determine your monitor size, which can be used to track you. We recommend that you leave browser windows in their original default size. +basebrowser-rfp-restore-window-size-button-label = Restore +basebrowser-rfp-restore-window-size-button-ak = R + +## Tooltip for the about:addons recommended badge + +basebrowser-addon-badge-recommended = Mozilla only recommends extensions that meet their standards for security and performance +basebrowser-addon-badge-verified = Mozilla has reviewed this extension to meet their standards for security and performance + +## Option to show or hide the NoScript extension button/item. + +basebrowser-addon-noscript-visibility-label = Toolbar button +basebrowser-addon-noscript-visibility-show = Show +basebrowser-addon-noscript-visibility-hide = Hide + +## About dialog + +# "Mozilla Firefox" should be treated like a brand and it should be neither translated nor transliterated. +# $version (String) - The current browser version. E.g. "12.5.3". +# $firefoxVersion (String) - The version number of Firefox the current browser is based on. E.g. "102.15.0esr". +basebrowser-about-dialog-version = { $version } (based on Mozilla Firefox { $firefoxVersion }) + +## New identity. + +# File menu items use title case for English (US). +menu-new-identity = + .label = New Identity + .accesskey = I + +# App menu (hamburger menu) items use sentence case for English (US). +appmenuitem-new-identity = + .label = New identity + +# Uses sentence case for English (US). +# ".label" is the accessible name, and is visible in the overflow menu and when +# customizing the toolbar. +# ".tooltiptext" will be identical to the label. +toolbar-new-identity = + .label = New identity + .tooltiptext = { toolbar-new-identity.label } + +## New identity dialog. + +new-identity-dialog-title = Reset your identity? +new-identity-dialog-description = { -brand-short-name } will close all windows and tabs. All website sessions will be lost. +new-identity-dialog-never-ask-checkbox = + .label = Never ask me again +new-identity-dialog-confirm = + .label = Restart { -brand-short-name } + +## New identity: blocked home page notification. + +# '-brand-short-name' is the localized browser name, like "Tor Browser". +# $url (String) - The URL of the home page, possibly shortened. +new-identity-blocked-home-notification = { -brand-short-name } blocked your homepage ({ $url }) from loading because it might recognize your previous session. +# Button to continue loading the home page, despite the warning message. +new-identity-blocked-home-ignore-button = Load it anyway + +## Preferences - Letterboxing. + +# The word "Letterboxing" is the proper noun for the Tor Browser feature, and is therefore capitalised. +# "Letterboxing" should be treated as a feature/product name, and likely not changed in other languages. +letterboxing-header = Letterboxing +# The word "Letterboxing" is the proper noun for the Tor Browser feature, and is therefore capitalised. +# "Letterboxing" should be treated as a feature/product name, and likely not changed in other languages. +letterboxing-overview = { -brand-short-name }'s Letterboxing feature restricts websites to display at specific sizes, making it harder to single out users on the basis of their window or screen size. +letterboxing-learn-more = Learn more +letterboxing-window-size-header = Window size +letterboxing-remember-size = + .label = Reuse last window size when opening a new window + .accesskey = R +letterboxing-alignment-header = Content alignment +letterboxing-alignment-description = Choose where you want to align the website’s content. +letterboxing-alignment-top = Top +letterboxing-alignment-middle = Middle +# The word "Letterboxing" is the proper noun for the Tor Browser feature, and is therefore capitalised. +# "Letterboxing" should be treated as a feature/product name, and likely not changed in other languages. +letterboxing-disabled-description = Letterboxing is currently disabled. +# The word "Letterboxing" is the proper noun for the Tor Browser feature, and is therefore capitalised. +# "Letterboxing" should be treated as a feature/product name, and likely not changed in other languages. +letterboxing-enable-button = + .label = Enable Letterboxing + +## Security level toolbar button. +## Uses sentence case in English (US). +## ".label" is the accessible name, and shown in the overflow menu and when customizing the toolbar. + +security-level-toolbar-button-standard = + .label = Security level + .tooltiptext = Security level: Standard +security-level-toolbar-button-safer = + .label = Security level + .tooltiptext = Security level: Safer +security-level-toolbar-button-safest = + .label = Security level + .tooltiptext = Security level: Safest +# Used when the user is in some custom configuration that does not match a security level. +security-level-toolbar-button-custom = + .label = Security level + .tooltiptext = Security level: Custom + +## Security level popup panel. + +# Uses sentence case in English (US). +security-level-panel-heading = Security level + +security-level-panel-level-standard = Standard +security-level-panel-level-safer = Safer +security-level-panel-level-safest = Safest +security-level-panel-learn-more-link = Learn more +# Button to open security level settings. +security-level-panel-open-settings-button = Settings… + +## Security level settings. + +security-level-preferences-heading = Security Level +security-level-preferences-overview = Disable certain web features that can be used to attack your security and anonymity. +security-level-preferences-learn-more-link = Learn more +security-level-preferences-level-standard = + .label = Standard +security-level-preferences-level-safer = + .label = Safer +security-level-preferences-level-safest = + .label = Safest + +## Security level summaries shown in security panel and settings. + +security-level-summary-standard = All browser and website features are enabled. +security-level-summary-safer = Disables website features that are often dangerous, causing some sites to lose functionality. +security-level-summary-safest = Only allows website features required for static sites and basic services. These changes affect images, media, and scripts. + +## Security level feature bullet points. +## Shown in the settings under the security level when it is selected. + +security-level-preferences-bullet-https-only-javascript = JavaScript is disabled on non-HTTPS sites. +security-level-preferences-bullet-limit-font-and-symbols = Some fonts and math symbols are disabled. +security-level-preferences-bullet-limit-media = Audio and video (HTML5 media), and WebGL are click-to-play. +security-level-preferences-bullet-disabled-javascript = JavaScript is disabled by default on all sites. +security-level-preferences-bullet-limit-font-and-symbols-and-images = Some fonts, icons, math symbols, and images are disabled. + +## Custom security level. +## Some custom preferences configuration has placed the user outside one of the standard three levels. + +# Shown in the security level panel as an orange badge next to the expected level. +security-level-panel-custom-badge = Custom +# Shown in the security level settings in a warning box. +security-level-preferences-custom-heading = Custom security level configured +# Description of custom state and recommended action. +# Shown in the security level panel and settings. +security-level-summary-custom = Your custom browser preferences have resulted in unusual security settings. For security and privacy reasons, we recommend you choose one of the default security levels. +# Button to undo custom changes to the security level and place the user in one of the standard security levels. +# Shown in the security level panel and settings. +security-level-restore-defaults-button = Restore defaults diff --git a/toolkit/locales/en-US/toolkit/global/tor-browser.ftl b/toolkit/locales/en-US/toolkit/global/tor-browser.ftl new file mode 100644 index 0000000000000000000000000000000000000000..57252f6cddb34d24f8d864fd5c9e771163447a20 --- /dev/null +++ b/toolkit/locales/en-US/toolkit/global/tor-browser.ftl @@ -0,0 +1,702 @@ +# Tor browser manual link shown in the menu bar. +# Uses Title case. +menu-open-tor-manual = + .label = Tor Browser Manual + .accesskey = M +# Tor browser manual link shown in the application menu (aka: hamburger menu). +# Uses Sentence case. +appmenu-open-tor-manual = + .label = Tor Browser manual + .accesskey = m + +## Tor Browser home page. + +tor-browser-home-heading-stable = Explore. Privately. +tor-browser-home-heading-testing = Test. Thoroughly. + +# Only shown when underlying Tor process was not started by Tor Browser. +# "Tails" refers to the operating system, and should be translated as a brand name. +# <a data-l10n-name="tor-check-link"> should contain the link text and close with </a>. +tor-browser-home-tor-check-warning = Your connection to Tor is not being managed by Tor Browser. Some operating systems (like Tails) will manage this for you, or you could have set up a custom configuration. <a data-l10n-name="tor-check-link">Test your connection</a> + +tor-browser-home-duck-duck-go-input = + .placeholder = Search with DuckDuckGo +# Toggle to switch from DuckDuckGo's plain ".com" domain to its ".onion" domain. +tor-browser-home-onionize-toggle = + .label = Onionize + .title = Search using the onion site + +# Update message. +# <a data-l10n-name="update-link"> should contain the link text and close with </a>. +# $version (String) - The new tor browser version. +tor-browser-home-message-updated = Tor Browser has been updated to { $version }. <a data-l10n-name="update-link">See what’s new</a> + +tor-browser-home-message-introduction = You’re ready for the world’s most private browsing experience. + +tor-browser-home-message-donate = Tor is free to use because of donations from people like you. <a data-l10n-name="donate-link">Donate now</a> + +tor-browser-home-message-news = Get the latest news from Tor straight to your inbox. <a data-l10n-name="news-link">Sign up for Tor news</a> + +tor-browser-home-message-testing = This is an unstable version of Tor Browser for testing new features. <a data-l10n-name="learn-more-link">Learn more</a> + +## + +# Shown in Home settings, corresponds to the default about:tor home page. +home-mode-choice-tor = + .label = Tor Browser Home + +## Tor connection settings. + +# "Connection" refers to the Tor Browser's connection to the Tor network. +tor-connection-settings-heading = Connection +# The tooltip text for the "Connection" settings, shown in the preferences side bar. +# Likely should just be "{ tor-connection-settings-heading }", which will match the displayed text exactly. +tor-connection-settings-category = + .tooltiptext = { tor-connection-settings-heading } +# -brand-short-name refers to 'Tor Browser', localized. +tor-connection-overview = { -brand-short-name } routes your traffic over the Tor Network, run by thousands of volunteers around the world. +tor-connection-browser-learn-more-link = Learn more +tor-connection-quickstart-heading = Quickstart +# -brand-short-name refers to 'Tor Browser', localized. +tor-connection-quickstart-description = Quickstart connects { -brand-short-name } to the Tor Network automatically when launched, based on your last used connection settings. +tor-connection-quickstart-checkbox = + .label = Always connect automatically + +# Prefix before the internet connection status. +# "Internet" is not a proper noun, but is capitalized because it is the start of a sentence. +tor-connection-internet-status-label = Internet: +# Button to test the internet connection. +# Here "Test" is a verb, as in "test the internet connection". +# Uses sentence case in English (US). +tor-connection-internet-status-test-button = Test +# Shown when testing the internet status. +# Uses sentence case in English (US). +tor-connection-internet-status-testing = Testing… +# Shown when the user is connected to the internet. +# Uses sentence case in English (US). +tor-connection-internet-status-online = Online +# Shown when the user is not connected to the internet. +# Uses sentence case in English (US). +tor-connection-internet-status-offline = Offline + +# Prefix before the Tor network connection status. +# Uses sentence case in English (US). +tor-connection-network-status-label = Tor network: +# Shown when the user is connected to the Tor network. +# Uses sentence case in English (US). +tor-connection-network-status-connected = Connected +# Shown when the user is not connected to the Tor network. +# Uses sentence case in English (US). +tor-connection-network-status-not-connected = Not connected +# Shown when the user's Tor connection may be blocked. +# Uses sentence case in English (US). +tor-connection-network-status-blocked = Potentially blocked +# Button shown when we are not yet connected to the Tor network. +# It will open a page to start connecting to the Tor network. +# Uses sentence case in English (US). +tor-connection-network-status-connect-button = Connect + +## Tor Bridges Settings. + +tor-bridges-heading = Bridges +tor-bridges-overview = Bridges help you securely access the Tor Network in places where Tor is blocked. Depending on where you are, one bridge may work better than another. +tor-bridges-learn-more-link = Learn more + +# Toggle button for enabling and disabling the use of bridges. +tor-bridges-use-bridges = + .label = Use bridges + +tor-bridges-none-added = No bridges added +tor-bridges-your-bridges = Your bridges +tor-bridges-source-user = Added by you +tor-bridges-source-built-in = Built-in +tor-bridges-source-requested = Requested from Tor +# Here "Bridge pass" is a noun: a bridge pass gives users access to some tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +# This is shown when the user is getting their bridges from Lox. +tor-bridges-source-lox = Bridge pass +# The "..." menu button for all current bridges. +tor-bridges-options-button = + .title = All bridges +# Shown in the "..." menu for all bridges when the user can generate a QR code for all of their bridges. +tor-bridges-menu-item-qr-all-bridge-addresses = Show QR code + .accesskey = Q +# Shown in the "..." menu for all bridges when the user can copy all of their bridges. +tor-bridges-menu-item-copy-all-bridge-addresses = Copy bridge addresses + .accesskey = C +# Only shown in the "..." menu for bridges added by the user. +tor-bridges-menu-item-edit-all-bridges = Edit bridges + .accesskey = E +# Shown in the "..." menu for all current bridges. +tor-bridges-menu-item-remove-all-bridges = Remove all bridges + .accesskey = R + +# Shown when one of the built-in bridges is in use. +tor-bridges-built-in-status-connected = Connected +# "obfs4" is a technical name, and likely should not be translated. +tor-bridges-built-in-obfs4-name = obfs4 +tor-bridges-built-in-obfs4-description = Makes your Tor traffic look like random data. May not work in heavily censored regions. +# "Snowflake" is a proper noun for a type of Tor bridge, and likely should not be translated. +tor-bridges-built-in-snowflake-name = Snowflake +# "Snowflake" is a proper noun for a type of Tor bridge, and likely should not be translated. +tor-bridges-built-in-snowflake-description = Routes your connection through Snowflake proxies to make it look like you’re placing a video call, for example. +# "meek-azure" is a technical name, and likely should not be translated. +tor-bridges-built-in-meek-azure-name = meek-azure +tor-bridges-built-in-meek-azure-description = Makes it look like you’re connected to a Microsoft website, instead of using Tor. May work in heavily censored regions, but is usually very slow. + +# Shown at the start of a Tor bridge line. +# $type (String) - The Tor bridge type ("snowflake", "obfs4", "meek-azure"). +tor-bridges-type-prefix = { $type } bridge: +# Shown at the start of a Tor bridge line, when the transport type is unknown (or "vanilla"). +tor-bridges-type-prefix-generic = Tor bridge: +# Used for an image of a bridge emoji. Each bridge address can be hashed into four emojis shown to the user (bridgemoji feature). This string corresponds to a *single* such emoji. The "title" should just be emojiName. The "alt" should let screen readers know that the image is of a *single* emoji, as well as its name. +# $emojiName (String) - The name of the emoji, already localized. +tor-bridges-emoji-image = + .alt = Emoji: { $emojiName } + .title = { $emojiName } +# The emoji name to show on hover when a bridge emoji's name is unknown. +tor-bridges-emoji-unknown = Unknown +# Shown when the bridge has been used for the most recent Tor circuit, i.e. the most recent bridge we have connected to. +tor-bridges-status-connected = Connected +# Used when the bridge has no status, i.e. the *absence* of a status to report to the user. This is only visibly shown when the status cell has keyboard focus. +tor-bridges-status-none = No status +# The "..." menu button for an individual bridge row. +tor-bridges-individual-bridge-options-button = + .title = Bridge options +# Shown in the "..." menu for an individual bridge. Shows the QR code for this one bridge. +tor-bridges-menu-item-qr-address = Show QR code + .accesskey = Q +# Shown in the "..." menu for an individual bridge. Copies the single bridge address to clipboard. +tor-bridges-menu-item-copy-address = Copy bridge address + .accesskey = C +# Shown in the "..." menu for an individual bridge. Removes this one bridge. +tor-bridges-menu-item-remove-bridge = Remove bridge + .accesskey = R + +# Text shown just before a description of the most recent change to the list of user's bridges. Some white space will separate this text from the change description. +# This text is not visible, but is instead used for screen reader users. +# E.g. in English this could be "Recent update: One of your Tor bridges has been removed." +tor-bridges-update-area-intro = Recent update: +# Update text for screen reader users when only one of their bridges has been removed. +tor-bridges-update-removed-one-bridge = One of your Tor bridges has been removed. +# Update text for screen reader users when all of their bridges have been removed. +tor-bridges-update-removed-all-bridges = All of your Tor bridges have been removed. +# Update text for screen reader users when their bridges have changed in some arbitrary way. +tor-bridges-update-changed-bridges = Your Tor bridges have changed. + +# Shown for requested bridges and bridges added by the user. +tor-bridges-share-heading = Help others connect +tor-bridges-share-description = Share your bridges with trusted contacts. +tor-bridges-copy-addresses-button = Copy addresses +tor-bridges-qr-addresses-button = + .title = Show QR code + +# Shown when using a "bridge pass", i.e. using Lox. +# Here "bridge pass" is a noun: a bridge pass gives users access to some tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +# Here "bridge bot" refers to a service that automatically gives out bridges for the user to use, i.e. the Lox authority. +tor-bridges-lox-description = With a bridge pass, the bridge bot will send you new bridges when your bridges get blocked. If your bridges don’t get blocked, you’ll unlock invites that let you share bridges with trusted contacts. +# The number of days until the user's "bridge pass" is upgraded. +# $numDays (Number) - The number of days until the next upgrade, an integer (1 or higher). +# The "[one]" and "[other]" are special Fluent syntax to mark plural categories that depend on the value of "$numDays". You can use any number of plural categories that work for your locale: "[zero]", "[one]", "[two]", "[few]", "[many]" and/or "[other]". The "*" marks a category as default, and is required. +# See https://projectfluent.org/fluent/guide/selectors.html . +# So in English, the first form will be used if $numDays is "1" (singular) and the second form will be used if $numDays is anything else (plural). +tor-bridges-lox-days-until-unlock = + { $numDays -> + [one] { $numDays } day until you unlock: + *[other] { $numDays } days until you unlock: + } +# This is shown as a list item after "N days until you unlock:" when the user will gain two more bridges in the future. +# Here "bridge bot" refers to a service that automatically gives out bridges for the user to use, i.e. the Lox authority. +tor-bridges-lox-unlock-two-bridges = +2 bridges from the bridge bot +# This is shown as a list item after "N days until you unlock:" when the user will gain access to invites for the first time. +# Here "invites" is a noun, short for "invitations". +tor-bridges-lox-unlock-first-invites = Invites for your trusted contacts +# This is shown as a list item after "N days until you unlock:" when the user already has invites. +# Here "invites" is a noun, short for "invitations". +tor-bridges-lox-unlock-more-invites = More invites for your trusted contacts +# Here "invite" is a noun, short for "invitation". +# $numInvites (Number) - The number of invites remaining, an integer (0 or higher). +# The "[one]" and "[other]" are special Fluent syntax to mark plural categories that depend on the value of "$numInvites". You can use any number of plural categories that work for your locale: "[zero]", "[one]", "[two]", "[few]", "[many]" and/or "[other]". The "*" marks a category as default, and is required. +# See https://projectfluent.org/fluent/guide/selectors.html . +# So in English, the first form will be used if $numInvites is "1" (singular) and the second form will be used if $numInvites is anything else (plural). +tor-bridges-lox-remaining-invites = + { $numInvites -> + [one] { $numInvites } invite remaining + *[other] { $numInvites } invites remaining + } +# Here "invites" is a noun, short for "invitations". +tor-bridges-lox-show-invites-button = Show invites + +# Shown when the user's "bridge pass" has been upgraded. +# Here "bridge pass" is a noun: a bridge pass gives users access to some tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +tor-bridges-lox-upgrade = Your bridge pass has been upgraded! +# Shown when the user's bridges accessed through "bridge pass" have been blocked. +tor-bridges-lox-blocked = Your blocked bridges have been replaced +# Shown *after* the user has had their blocked bridges replaced. +# Here "bridge bot" refers to a service that automatically gives out bridges for the user to use, i.e. the Lox authority. +tor-bridges-lox-new-bridges = New bridges from the bridge bot +# Shown *after* the user has gained two more bridges. +# Here "bridge bot" refers to a service that automatically gives out bridges for the user to use, i.e. the Lox authority. +tor-bridges-lox-gained-two-bridges = +2 bridges from the bridge bot +# Shown *after* a user's "bridge pass" has changed. +# Here "invite" is a noun, short for "invitation". +# $numInvites (Number) - The number of invites remaining, an integer (0 or higher). +# The "[one]" and "[other]" are special Fluent syntax to mark plural categories that depend on the value of "$numInvites". You can use any number of plural categories that work for your locale: "[zero]", "[one]", "[two]", "[few]", "[many]" and/or "[other]". The "*" marks a category as default, and is required. +# See https://projectfluent.org/fluent/guide/selectors.html . +# So in English, the first form will be used if $numInvites is "1" (singular) and the second form will be used if $numInvites is anything else (plural). +tor-bridges-lox-new-invites = + { $numInvites -> + [one] You now have { $numInvites } remaining invite for your trusted contacts + *[other] You now have { $numInvites } remaining invites for your trusted contacts + } +# Button for the user to acknowledge a change in their "bridge pass". +tor-bridges-lox-got-it-button = Got it + + +# Shown as a heading when the user has no current bridges. +tor-bridges-add-bridges-heading = Add bridges +# Shown as a heading when the user has existing bridges that can be replaced. +tor-bridges-replace-bridges-heading = Replace your bridges + +# -brand-short-name refers to 'Tor Browser', localized. +tor-bridges-select-built-in-description = Choose from one of { -brand-short-name }’s built-in bridges +tor-bridges-select-built-in-button = Select a built-in bridge… + +tor-bridges-add-addresses-description = Enter bridge addresses you already know +# Shown when the user has no current bridges. +# Opens a dialog where the user can provide a new bridge address or share code. +tor-bridges-add-new-button = Add new bridges… +# Shown when the user has existing bridges. +# Opens a dialog where the user can provide a new bridge address or share code to replace their current bridges. +tor-bridges-replace-button = Replace bridges… + +tor-bridges-find-more-heading = Find more bridges +# "Tor Project" is the organisation name. +tor-bridges-find-more-description = Since many bridge addresses aren’t public, you may need to request some from the Tor Project. + +# "Telegram" is the common brand name of the Telegram Messenger application +tor-bridges-provider-telegram-name = Telegram +# Here "Message" is a verb, short for "Send a message to". This is an instruction to send a message to the given Telegram Messenger user to receive a new bridge. +# $telegramUserName (String) - The Telegram Messenger user name that should receive messages. Should be wrapped in '<a data-l10n-name="user">' and '</a>'. +# E.g. in English, "Message GetBridgesBot". +tor-bridges-provider-telegram-instruction = Message <a data-l10n-name="user">{ $telegramUserName }</a> + +# "Web" is the proper noun for the "World Wide Web". +tor-bridges-provider-web-name = Web +# Instructions to visit the given website. +# $url (String) - The URL for Tor Project bridges. Should be wrapped in '<a data-l10n-name"url">' and '</a>'. +tor-bridges-provider-web-instruction = Visit <a data-l10n-name="url">{ $url }</a> + +# "Gmail" is the Google brand name. "Riseup" refers to the Riseup organisation at riseup.net. +tor-bridges-provider-email-name = Gmail or Riseup +# Here "Email" is a verb, short for "Send an email to". This is an instruction to send an email to the given address to receive a new bridge. +# $address (String) - The email address that should receive the email. +# E.g. in English, "Email bridges@torproject.org". +tor-bridges-provider-email-instruction = Email { $address } + +tor-bridges-request-from-browser = You can also get bridges from the bridge bot without leaving { -brand-short-name }. +tor-bridges-request-button = Request bridges… + +## Warning dialog when removing all bridges. + +remove-all-bridges-warning-title = Remove all bridges? +remove-all-bridges-warning-description = If these bridges were received from torproject.org or added manually, this action cannot be undone +remove-all-bridges-warning-remove-button = Remove + +## Bridge QR code dialog. + +bridge-qr-dialog-title = + .title = Scan the QR code + +## Common button used in bridge dialogs. + +bridge-dialog-button-connect = Connect +bridge-dialog-button-accept = OK +bridge-dialog-button-submit = Submit + +## User provided bridge dialog. + +# Used when the user is editing their existing bridge addresses. +user-provide-bridge-dialog-edit-title = + .title = Edit your bridges +# Used when the user has no existing bridges. +user-provide-bridge-dialog-add-title = + .title = Add new bridges +# Used when the user is replacing their existing bridges with new ones. +user-provide-bridge-dialog-replace-title = + .title = Replace your bridges +# Description shown when adding new bridges, replacing existing bridges, or editing existing bridges. +user-provide-bridge-dialog-description = Use bridges provided by a trusted organisation or someone you know. +# "Learn more" link shown in the "Add new bridges"/"Replace your bridges" dialog. +user-provide-bridge-dialog-learn-more = Learn more +# Short accessible name for the bridge addresses text area. +user-provide-bridge-dialog-textarea-addresses-label = Bridge addresses +# Here "invite" is a noun, short for "invitation". +# Short accessible name for text area when it can accept either bridge address or a single "bridge pass" invite. +user-provide-bridge-dialog-textarea-addresses-or-invite-label = Bridge addresses or invite +# Placeholder shown when adding new bridge addresses. +user-provide-bridge-dialog-textarea-addresses = + .placeholder = Paste your bridge addresses here +# Placeholder shown when the user can add new bridge addresses or a single "bridge pass" invite. +# Here "bridge pass invite" is a noun: a bridge pass invite can be shared with other users to give them their own bridge pass, so they can get access to tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +# And "invite" is simply short for "invitation". +# NOTE: "invite" is singular, whilst "addresses" is plural. +user-provide-bridge-dialog-textarea-addresses-or-invite = + .placeholder = Paste your bridge addresses or a bridge pass invite here +# Error shown when one of the address lines is invalid. +# $line (Number) - The line number for the invalid address. +user-provide-bridge-dialog-address-error = Incorrectly formatted bridge address on line { $line }. +# Error shown when the user has entered more than one "bridge pass" invite. +# Here "invite" is a noun, short for "invitation". +user-provide-bridge-dialog-multiple-invites-error = Cannot include more than one invite. +# Error shown when the user has mixed their invite with addresses. +# Here "invite" is a noun, short for "invitation". +user-provide-bridge-dialog-mixed-error = Cannot mix bridge addresses with an invite. +# Error shown when the user has entered an invite when it is not supported. +# Here "bridge pass invite" is a noun: a bridge pass invite can be shared with other users to give them their own bridge pass, so they can get access to tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +# And "invite" is simply short for "invitation". +user-provide-bridge-dialog-invite-not-allowed-error = Cannot include a bridge pass invite. +# Error shown when the invite was not accepted by the server. +user-provide-bridge-dialog-bad-invite-error = Invite was not accepted. Try a different one. +# Error shown when the "bridge pass" server does not respond. +# Here "bridge pass" is a noun: a bridge pass gives users access to some tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +user-provide-bridge-dialog-no-server-error = Unable to connect to bridge pass server. +# Generic error when an invite failed. +# Here "invite" is a noun, short for "invitation". +user-provide-bridge-dialog-generic-invite-error = Failed to redeem invite. + +# Here "bridge pass" is a noun: a bridge pass gives users access to some tor bridges. +# So "pass" is referring to something that gives permission or access. Similar to "token", "permit" or "voucher", but for permanent use rather than one-time. +user-provide-bridge-dialog-connecting = Connecting to bridge pass server… + +# Shown after the user has entered a "bridge pass" invite. +user-provide-bridge-dialog-result-invite = The following bridges were shared with you. +# Shown after the user has entered bridge addresses. +user-provide-bridge-dialog-result-addresses = The following bridges were entered by you. +user-provide-bridge-dialog-next-button = + .label = Next + +## Built-in bridges dialog. + +built-in-dialog-title = + .title = Select a Built-In Bridge +# -brand-short-name refers to 'Tor Browser', localized. +built-in-dialog-introduction = { -brand-short-name } includes some specific types of bridges known as “pluggable transports”, which can help conceal the fact you’re using Tor. +# "obfs4" is a technical name, and likely should not be translated. +built-in-dialog-obfs4-radio-option = + .label = obfs4 +# "Snowflake" is a proper noun for a type of Tor bridge, and likely should not be translated. +built-in-dialog-snowflake-radio-option = + .label = Snowflake +# "meek-azure" is a technical name, and likely should not be translated. +built-in-dialog-meek-azure-radio-option = + .label = meek-azure +# Label attached to the built-in bridge option that is already in use. +# The "aria-label" should use the same text, but include some ending punctuation to separate it from the sentence that follows. This is used for screen reader users. +built-in-dialog-current-bridge-label = Current bridge + .aria-label = Current bridge. + +request-bridge-dialog-title = + .title = Request Bridge +request-bridge-dialog-top-wait = Contacting BridgeDB. Please Wait. +request-bridge-dialog-top-solve = Solve the CAPTCHA to request a bridge. +request-bridge-dialog-captcha-input = + .placeholder = Enter the characters from the image +request-bridge-dialog-captcha-failed = The solution is not correct. Please try again. + +## Tor advanced settings. + +tor-advanced-settings-heading = Advanced +tor-advanced-settings-description = Configure how { -brand-short-name } connects to the internet. +# Button that opens the advanced connection settings dialog. +# Uses sentence case in English (US). +tor-advanced-settings-button = Settings… +# "log" is a noun, referring to the recorded text output of the Tor process. +tor-view-log-description = View the Tor log. +# "log" is a noun, referring to the recorded text output of the Tor process. +# Uses sentence case in English (US). +tor-view-log-button = View log… + +## Tor log dialog. + +# "log" is a noun, referring to the recorded text output of the Tor process. +tor-log-dialog-title = + .title = Tor log +# "log" is a noun, referring to the recorded text output of the Tor process. +tor-log-dialog-copy-button = + .label = Copy Tor log to clipboard +# Button text changes for a short time after activating the button. +tor-log-dialog-copy-button-copied = + .label = Copied! + +## Tor advanced connection settings dialog. + +tor-advanced-dialog-title = + .title = Connection settings +tor-advanced-dialog-introduction = Configure how { -brand-short-name } connects to the internet. +tor-advanced-dialog-proxy-checkbox = + .label = I use a proxy to connect to the internet +tor-advanced-dialog-proxy-type-selector-label = Proxy type +# SOCKS4 is a technical name, and should likely not be translated. +tor-advanced-dialog-proxy-socks4-menuitem = + .label = SOCKS4 +# SOCKS5 is a technical name, and should likely not be translated. +tor-advanced-dialog-proxy-socks5-menuitem = + .label = SOCKS5 +# HTTP and HTTPS are technical names, and should likely not be translated. +# The "/" refers to "HTTP or HTTPS" and can be translated. +tor-advanced-dialog-proxy-http-menuitem = + .label = HTTP/HTTPS +# "address" is a noun, referring to an network IP address. +tor-advanced-dialog-proxy-address-input-label = Address +tor-advanced-dialog-proxy-address-input = + .placeholder = IP address or hostname +tor-advanced-dialog-proxy-port-input-label = Port +tor-advanced-dialog-proxy-username-input-label = Username +tor-advanced-dialog-proxy-username-input = + .placeholder = Optional +tor-advanced-dialog-proxy-password-input-label = Password +tor-advanced-dialog-proxy-password-input = + .placeholder = Optional +tor-advanced-dialog-firewall-checkbox = + .label = This computer goes through a firewall that only allows connections to certain ports +tor-advanced-dialog-firewall-ports-input-label = Allowed ports +tor-advanced-dialog-firewall-ports-input = + .placeholder = Comma-separated values + +## About Tor Browser dialog. + +# '<label data-l10n-name="project-link">' and '</label>' should wrap the link text for the Tor Project, and will link to the Tor Project web page. +# -brand-short-name refers to 'Tor Browser', localized. +# -vendor-short-name refers to 'Tor Project', localized. +about-dialog-tor-project = { -brand-short-name } is developed by <label data-l10n-name="project-link">the { -vendor-short-name }</label>, a nonprofit working to defend your privacy and freedom online. + +# '<label data-l10n-name="donate-link">' and '</label>' should wrap the link text for donating to Tor Project, and will link to the Tor Project donation page. +# '<label data-l10n-name="community-link">' and '</label>' should wrap the link text for getting involved with Tor Project, and will link to the Tor Project community page. +about-dialog-help-out = Want to help? <label data-l10n-name="donate-link">Donate</label> or <label data-l10n-name="community-link">get involved</label>! + +# Link text for the Tor Project support page. +about-dialog-questions-link = Questions? +# Link text for the Tor Project page for Tor Network relay operators. +about-dialog-grow-tor-network-link = Help the Tor Network Grow! +# Link text for the Tor Browser license page (about:license). +about-dialog-browser-license-link = Licensing Information + +## New tor circuit. + +# Shown in the File menu. +# Uses title case for English (US). +menu-new-tor-circuit = + .label = New Tor Circuit for this Site + .accesskey = C + +# Shown in the application menu (hamburger menu). +# Uses sentence case for English (US). +appmenuitem-new-tor-circuit = + .label = New Tor circuit for this site + +# Toolbar button to trigger a new circuit, available through toolbar customization. +# Uses sentence case for English (US). +# ".label" is the accessible name, and is visible in the overflow menu and when +# customizing the toolbar. +# ".tooltiptext" will be identical to the label. +toolbar-new-tor-circuit = + .label = New Tor circuit for this site + .tooltiptext = { toolbar-new-tor-circuit.label } + +## Tor circuit URL bar button. + +# The tooltip also acts as the accessible name. +tor-circuit-urlbar-button = + .tooltiptext = Tor Circuit + +## Tor circuit panel. + +# $host (String) - The host name shown in the URL bar, potentially shortened. +tor-circuit-panel-heading = Circuit for { $host } +# Shown when the current address is a ".tor.onion" alias. +# $alias (String) - The alias onion address. This should be wrapped in '<a data-l10n-name="alias-link">' and '</a>', which will link to the corresponding address. +tor-circuit-panel-alias = Connected to <a data-l10n-name="alias-link">{ $alias }</a> + +# Text just before the list of circuit nodes. +tor-circuit-panel-node-list-introduction = Tor Circuit +# First node in the list of circuit nodes. Refers to Tor Browser. +tor-circuit-panel-node-browser = This browser +# Represents a number of unknown relays that complete a connection to an ".onion" site. +tor-circuit-panel-node-onion-relays = Onion site relays +# Represents the bridge node used to connect to the Tor network. +# $bridge-type (String) - The name for the type of bridge used: meek, obfs4, snowflake, etc. +tor-circuit-panel-node-typed-bridge = Bridge: { $bridge-type } +# Represents the bridge node used to connect to the Tor network when the bridge type is unknown. +tor-circuit-panel-node-bridge = Bridge +# Represents the initial guard node used for a tor circuit. +# $region (String) - The region name for the guard node, already localized. +tor-circuit-panel-node-region-guard = { $region } (guard) +# Represents a circuit node with an unknown regional location. +tor-circuit-panel-node-unknown-region = Unknown region + +# Uses sentence case for English (US). +tor-circuit-panel-new-button = New Tor circuit for this site +# Shown when the first node in the circuit is a guard node, rather than a bridge. +tor-circuit-panel-new-button-description-guard = Your guard node may not change +# Shown when the first node in the circuit is a bridge node. +tor-circuit-panel-new-button-description-bridge = Your bridge may not change + +## This dialog is shown when copying a suspected cryptocurrency address from a plain HTTP website. + +crypto-safety-prompt-title = Cryptocurrency address copied from an insecure website +# $address (String) - The cryptocurrency address, possibly truncated. +# $host (String) - The website host the address was copied from. +crypto-safety-prompt-body = The copied text ({ $address }) appears to be a cryptocurrency address. Since the connection to { $host } is not secure, the address may have been modified and should not be trusted. You can try establishing a secure connection by reconnecting with a new circuit. +crypto-safety-prompt-reload-button = Reload Tab with a New Circuit +crypto-safety-prompt-dismiss-button = Dismiss Warning + +## Downloads warning. +## Shown in downloads panel, about:downloads and Library window. + +# "Tails" is the brand name for the Tails operating system and should be localized appropriately. +downloads-tor-warning-message-bar = + .heading = Be careful opening downloads + .message = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like Tails. +# This will be a link to the Tails operating system website. +# "Tails" is the brand name for the Tails operating system and should be localized appropriately. +downloads-tor-warning-tails-link= Learn more about Tails +# Button to dismiss the warning forever. +downloads-tor-warning-dismiss-button = Got it + +## Initial warning page in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-warning-heading = Proceed with Caution +rulesets-warning-description = Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing. +rulesets-warning-checkbox = Warn me when I attempt to access these preferences +rulesets-warning-continue-button = Accept the Risk and Continue + +## Side panel in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-side-panel-heading = Rulesets +rulesets-side-panel-no-rules = No rulesets found +# -brand-short-name refers to 'Tor Browser', localized. +rulesets-side-panel-no-rules-description = When you save a ruleset in { -brand-short-name }, it will show up here. + +## Ruleset update date in about:rulesets. + +# $date (Date) - The update date. The DATETIME function will format the $date according to the locale, using a "long" style. E.g. "January 1, 2000" for English (US), "١ يناير ٢٠٠٠" for Arabic, "2000년 1월 1일" in Korean, and "1 января 2000 г." in Russian. +rulesets-update-last = Last updated { DATETIME($date, dateStyle: "long") } +rulesets-update-never = Never updated, or last update failed +# Shown when the ruleset is disabled. +rulesets-update-rule-disabled = Disabled + +## Ruleset details in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-details-edit-button = Edit +rulesets-details-enable-checkbox = Enable this ruleset +rulesets-details-update-button = Check for Updates +rulesets-details-save-button = Save +rulesets-details-cancel-button = Cancel +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk = JWK +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk-input = + .placeholder = The key used to sign this ruleset in the JWK (JSON Web Key) format +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk-input-invalid = The JWK could not be parsed, or it is not a valid key +# "Path" refers to the URL domain this rule applies to. +rulesets-details-path = Path Prefix +rulesets-details-path-input = + .placeholder = URL prefix that contains the files needed by the ruleset +# "HTTP(S)" refers to "HTTP or HTTPS". +rulesets-details-path-input-invalid = The path prefix is not a valid HTTP(S) URL +# "Scope" refers to the breadth of URLs this rule applies to (as a regular expression). +rulesets-details-scope = Scope +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression. +rulesets-details-scope-input = + .placeholder = Regular expression for the scope of the rules +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression. +rulesets-details-scope-input-invalid = The scope could not be parsed as a regular expression + +## Onion site error page. +## "Onion site" is an abbreviation of "onion website": a website whose domain URL ends in ".onion", which is reachable through the Tor network. + +onion-neterror-page-title = Problem loading onion site +onion-neterror-authorization-title = Authentication required +onion-neterror-not-found-header = Onion site not found +onion-neterror-not-found-description = The most likely cause is that the onion site is offline. Contact the onion site administrator. +onion-neterror-unreachable-header = Onion site cannot be reached +onion-neterror-unreachable-description = The onion site is unreachable due an internal error. +onion-neterror-disconnected-header = Onion site has disconnected +onion-neterror-disconnected-description = The most likely cause is that the onion site is offline. Contact the onion site administrator. +onion-neterror-connection-failed-header = Unable to connect to onion site +onion-neterror-connection-failed-description = The onion site is busy or the Tor network is overloaded. Try again later. +onion-neterror-missing-authentication-header = Onion site requires authentication +onion-neterror-missing-authentication-description = Access to the onion site requires a key but none was provided. +onion-neterror-incorrect-authentication-header = Onion site authentication failed +onion-neterror-incorrect-authetication-description = The provided key is incorrect or has been revoked. Contact the onion site administrator. +onion-neterror-invalid-address-header = Invalid onion site address +onion-neterror-invalid-address-description = The provided onion site address is invalid. Please check that you entered it correctly. +# "Circuit" refers to a Tor network circuit. +onion-neterror-timed-out-header = Onion site circuit creation timed out +onion-neterror-timed-out-description = Failed to connect to the onion site, possibly due to a poor network connection. + +## Onion site authentication prompt. +## "Onion site" is an abbreviation of "onion website": a website whose domain URL ends in ".onion", which is reachable through the Tor network. + +# Here "open" is a verb. +onion-site-authentication-urlbar-button = + .tooltiptext = Open the onion site authentication panel + +# $onionsite (String) - The shortened onion address for the current web site, for example "a3jx8k…pbsh7y.onion". +onion-site-authentication-prompt-description = The onion site { $onionsite } is requesting that you authenticate. +onion-site-authentication-prompt-learn-more = Learn more +onion-site-authentication-prompt-key-input = + .placeholder = Enter your private key for this onion site +onion-site-authentication-prompt-remember-checkbox = + .label = Remember this key +onion-site-authentication-prompt-ok-button = + .label = OK + .accesskey = O +onion-site-authentication-prompt-cancel-button = + .label = Cancel + .accesskey = C +# Error message shown when the entered key is the wrong length or the wrong format. +# "base32" and "base64" are technical names for binary-to-text encodings: https://en.wikipedia.org/wiki/Base64 +onion-site-authentication-prompt-invalid-key = Please enter a valid key (52 base32 characters or 44 base64 characters) +onion-site-authentication-prompt-setting-key-failed = Unable to configure Tor with your key + +## Page Info window for onion sites. +## "Onion site" is an abbreviation of "onion website": a website whose domain URL ends in ".onion", which is reachable through the Tor network. + +# $encryption-type (String) - The name of the encryption algorithm used for the page, for example "TLS_AES_128_GCM_SHA256". +# $encryption-stength (Number) - The number of bits for the encryption key, for example "128" or "256". The "NUMBER" function will format this number to the same locale, and the "useGrouping" option will remove grouping symbols, like thousand separators. Note that the "bit" in "bit keys" refers to a computer "binary digit". +# $encryption-version (String) - The name and version of the encryption, for example "TLS 1.3". +page-info-onion-site-encryption-with-bits = Connection encrypted (Onion site, { $encryption-type }, { NUMBER($encryption-strength, useGrouping: "false") } bit keys, { $encryption-version }) +page-info-onion-site-encryption-plain = Connection encrypted (Onion site) + +## Onion site authentication preferences. +## "Onion site" is an abbreviation of "onion website": a website whose domain URL ends in ".onion", which is reachable through the Tor network. + +onion-site-authentication-preferences-heading = Onion site authentication +onion-site-authentication-preferences-overview = Some onion sites require that you identify yourself with a key (a kind of password) before you can access them. +onion-site-authentication-preferences-learn-more = Learn more +onion-site-authentication-preferences-saved-keys-button = Saved keys… + +## Onion site saved keys dialog. +## "Onion site" is an abbreviation of "onion website": a website whose domain URL ends in ".onion", which is reachable through the Tor network. + +onion-site-saved-keys-dialog-title = + .title = Onion site keys + +onion-site-saved-keys-dialog-intro = The following onion site keys are stored on your computer. +onion-site-saved-keys-dialog-table-header-site = + .label = Onion site +# "Key" is a noun, for an access key. +onion-site-saved-keys-dialog-table-header-key = + .label = Key +onion-site-saved-keys-dialog-remove-button = Remove +onion-site-saved-keys-dialog-remove-all-button = Remove all +onion-site-saved-keys-dialog-fetch-keys-error-message = Unable to retrieve keys from Tor +onion-site-saved-keys-dialog-remove-keys-error-message = Unable to remove key diff --git a/toolkit/locales/jar.mn b/toolkit/locales/jar.mn index 22ea5cbcac9d5bbebbc0e1cc5790d4c73ca0dc0b..9966093dd12d0c865db3057ed863e82875dea893 100644 --- a/toolkit/locales/jar.mn +++ b/toolkit/locales/jar.mn @@ -8,6 +8,8 @@ services (%services/**/*.ftl) toolkit (%toolkit/**/*.ftl) locales-preview/aboutTranslations.ftl (../locales-preview/aboutTranslations.ftl) + locales-preview/base-browser-no-translate.ftl (../locales-preview/base-browser-no-translate.ftl) + locales-preview/tor-browser-no-translate.ftl (../locales-preview/tor-browser-no-translate.ftl) #ifdef MOZ_LAYOUT_DEBUGGER layoutdebug/layoutdebug.ftl (../../layout/tools/layout-debug/ui/content/layoutdebug.ftl) #endif diff --git a/toolkit/modules/ActorManagerParent.sys.mjs b/toolkit/modules/ActorManagerParent.sys.mjs index 5f2e482789f4eaa8a2c276ca698854ba04e862f8..3c0c26dd0ceec4be6719aa9e5896318f5c615908 100644 --- a/toolkit/modules/ActorManagerParent.sys.mjs +++ b/toolkit/modules/ActorManagerParent.sys.mjs @@ -292,6 +292,22 @@ let JSWINDOWACTORS = { allFrames: true, }, + FilesFilter: { + parent: { + esModuleURI: "resource://gre/actors/FilesFilterParent.sys.mjs", + }, + + child: { + esModuleURI: "resource://gre/actors/FilesFilterChild.sys.mjs", + events: { + drop: {}, + paste: { capture: true }, + }, + }, + + allFrames: true, + }, + FindBar: { parent: { esModuleURI: "resource://gre/actors/FindBarParent.sys.mjs", @@ -526,6 +542,20 @@ let JSWINDOWACTORS = { allFrames: true, }, + TorConnect: { + parent: { + esModuleURI: "resource://gre/actors/TorConnectParent.sys.mjs", + }, + child: { + esModuleURI: "resource://gre/actors/TorConnectChild.sys.mjs", + events: { + DOMWindowCreated: {}, + }, + }, + + matches: ["about:torconnect", "about:torconnect?*"], + }, + // This actor is available for all pages that one can // view the source of, however it won't be created until a // request to view the source is made via the message diff --git a/toolkit/modules/AppConstants.sys.mjs b/toolkit/modules/AppConstants.sys.mjs index a20e45c6135d24e42594700fe57184a560facd0f..18592ed295de53b67e1c892bad55749a0e6d74f9 100644 --- a/toolkit/modules/AppConstants.sys.mjs +++ b/toolkit/modules/AppConstants.sys.mjs @@ -338,6 +338,8 @@ export var AppConstants = Object.freeze({ MOZ_UPDATE_CHANNEL: "@MOZ_UPDATE_CHANNEL@", MOZ_WIDGET_TOOLKIT: "@MOZ_WIDGET_TOOLKIT@", + BASE_BROWSER_VERSION: "@BASE_BROWSER_VERSION@", + DEBUG_JS_MODULES: "@DEBUG_JS_MODULES@", MOZ_BING_API_CLIENTID: "@MOZ_BING_API_CLIENTID@", @@ -392,11 +394,11 @@ export var AppConstants = Object.freeze({ #ifdef MOZ_THUNDERBIRD "https://thunderbird-settings.thunderbird.net/v1", #else - "https://firefox.settings.services.mozilla.com/v1", + "", #endif REMOTE_SETTINGS_VERIFY_SIGNATURE: -#ifdef MOZ_THUNDERBIRD +#if defined(MOZ_THUNDERBIRD) || defined(BASE_BROWSER_VERSION) false, #else true, @@ -461,6 +463,13 @@ export var AppConstants = Object.freeze({ "@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@", #endif + BASE_BROWSER_UPDATE: +#ifdef BASE_BROWSER_UPDATE + true, +#else + false, +#endif + // Returns true for CN region build when distibution id set as 'MozillaOnline' isChinaRepack() { return ( diff --git a/toolkit/modules/Bech32Decode.sys.mjs b/toolkit/modules/Bech32Decode.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..67906d915f30e85af6a81b110c99bbcd8e28446d --- /dev/null +++ b/toolkit/modules/Bech32Decode.sys.mjs @@ -0,0 +1,99 @@ +// Adapted from the reference implementation of Bech32 +// https://github.com/sipa/bech32 + +// Copyright (c) 2017 Pieter Wuille +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +/** + * JS module implementation of Bech32 decoding adapted from the reference + * implementation https://github.com/sipa/bech32. + */ + +var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; +var GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]; + +function polymod(values) { + var chk = 1; + for (var p = 0; p < values.length; ++p) { + var top = chk >> 25; + chk = ((chk & 0x1ffffff) << 5) ^ values[p]; + for (var i = 0; i < 5; ++i) { + if ((top >> i) & 1) { + chk ^= GENERATOR[i]; + } + } + } + return chk; +} + +function hrpExpand(hrp) { + var ret = []; + var p; + for (p = 0; p < hrp.length; ++p) { + ret.push(hrp.charCodeAt(p) >> 5); + } + ret.push(0); + for (p = 0; p < hrp.length; ++p) { + ret.push(hrp.charCodeAt(p) & 31); + } + return ret; +} + +function verifyChecksum(hrp, data) { + return polymod(hrpExpand(hrp).concat(data)) === 1; +} + +export function Bech32Decode(bechString) { + var p; + var has_lower = false; + var has_upper = false; + for (p = 0; p < bechString.length; ++p) { + if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) { + return null; + } + if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) { + has_lower = true; + } + if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) { + has_upper = true; + } + } + if (has_lower && has_upper) { + return null; + } + bechString = bechString.toLowerCase(); + var pos = bechString.lastIndexOf("1"); + if (pos < 1 || pos + 7 > bechString.length || bechString.length > 90) { + return null; + } + var hrp = bechString.substring(0, pos); + var data = []; + for (p = pos + 1; p < bechString.length; ++p) { + var d = CHARSET.indexOf(bechString.charAt(p)); + if (d === -1) { + return null; + } + data.push(d); + } + if (!verifyChecksum(hrp, data)) { + return null; + } + return { hrp, data: data.slice(0, data.length - 6) }; +} diff --git a/toolkit/modules/BridgeDB.sys.mjs b/toolkit/modules/BridgeDB.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..a2e374669362a888df5681fa3e935b470895575d --- /dev/null +++ b/toolkit/modules/BridgeDB.sys.mjs @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + MoatRPC: "resource://gre/modules/Moat.sys.mjs", +}); + +export var BridgeDB = { + _moatRPC: null, + _challenge: null, + _image: null, + _bridges: null, + /** + * A collection of controllers to abort any ongoing Moat requests if the + * dialog is closed. + * + * NOTE: We do not expect this set to ever contain more than one instance. + * However the public API has no assurances to prevent multiple calls. + * + * @type {Set<AbortController>} + */ + _moatAbortControllers: new Set(), + + get currentCaptchaImage() { + return this._image; + }, + + get currentBridges() { + return this._bridges; + }, + + async submitCaptchaGuess(solution) { + if (!this._moatRPC) { + this._moatRPC = new lazy.MoatRPC(); + await this._moatRPC.init(); + } + + const abortController = new AbortController(); + this._moatAbortControllers.add(abortController); + try { + this._bridges = await this._moatRPC.check( + "obfs4", + this._challenge, + solution, + abortController.signal + ); + } finally { + this._moatAbortControllers.delete(abortController); + } + return this._bridges; + }, + + async requestNewCaptchaImage() { + try { + if (!this._moatRPC) { + this._moatRPC = new lazy.MoatRPC(); + await this._moatRPC.init(); + } + + const abortController = new AbortController(); + this._moatAbortControllers.add(abortController); + let response; + try { + response = await this._moatRPC.fetch(["obfs4"], abortController.signal); + } finally { + this._moatAbortControllers.delete(abortController); + } + if (response) { + // Not cancelled. + this._challenge = response.challenge; + this._image = + "data:image/jpeg;base64," + encodeURIComponent(response.image); + } + } catch (err) { + console.error("Could not request a captcha image", err); + } + return this._image; + }, + + close() { + // Abort any ongoing requests. + for (const controller of this._moatAbortControllers) { + controller.abort(); + } + this._moatAbortControllers.clear(); + this._moatRPC?.uninit(); + this._moatRPC = null; + this._challenge = null; + this._image = null; + this._bridges = null; + }, +}; diff --git a/toolkit/modules/DomainFrontedRequests.sys.mjs b/toolkit/modules/DomainFrontedRequests.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..c273b95d471f786edc1091dbb76768912351434e --- /dev/null +++ b/toolkit/modules/DomainFrontedRequests.sys.mjs @@ -0,0 +1,616 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +const log = console.createInstance({ + maxLogLevel: "Warn", + prefix: "DomainFrontendRequests", +}); + +ChromeUtils.defineESModuleGetters(lazy, { + EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", + Subprocess: "resource://gre/modules/Subprocess.sys.mjs", + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", +}); + +/** + * The meek pluggable transport takes the reflector URL and front domain as + * proxy credentials, which can be prepared with this function. + * + * @param {string} proxyType The proxy type (socks for socks5 or socks4) + * @param {string} reflector The URL of the service hosted by the CDN + * @param {string} front The domain to use as a front + * @returns {string[]} An array containing [username, password] + */ +function makeMeekCredentials(proxyType, reflector, front) { + // Construct the per-connection arguments. + let meekClientEscapedArgs = ""; + + // Escape aValue per section 3.5 of the PT specification: + // First the "<Key>=<Value>" formatted arguments MUST be escaped, + // such that all backslash, equal sign, and semicolon characters + // are escaped with a backslash. + const escapeArgValue = aValue => + aValue + ? aValue + .replaceAll("\\", "\\\\") + .replaceAll("=", "\\=") + .replaceAll(";", "\\;") + : ""; + + if (reflector) { + meekClientEscapedArgs += "url="; + meekClientEscapedArgs += escapeArgValue(reflector); + } + + if (front) { + if (meekClientEscapedArgs.length) { + meekClientEscapedArgs += ";"; + } + meekClientEscapedArgs += "front="; + meekClientEscapedArgs += escapeArgValue(front); + } + + // socks5 + if (proxyType === "socks") { + if (meekClientEscapedArgs.length <= 255) { + return [meekClientEscapedArgs, "\x00"]; + } + return [ + meekClientEscapedArgs.substring(0, 255), + meekClientEscapedArgs.substring(255), + ]; + } else if (proxyType === "socks4") { + return [meekClientEscapedArgs, undefined]; + } + throw new Error(`Unsupported proxy type ${proxyType}.`); +} + +/** + * Subprocess-based implementation to launch and control a PT process. + */ +class MeekTransport { + // These members are used by consumers to setup the proxy to do requests over + // meek. They are passed to newProxyInfoWithAuth. + proxyType = null; + proxyAddress = null; + proxyPort = 0; + proxyUsername = null; + proxyPassword = null; + + #inited = false; + #meekClientProcess = null; + + // launches the meekprocess + async init(reflector, front) { + // ensure we haven't already init'd + if (this.#inited) { + throw new Error("MeekTransport: Already initialized"); + } + + try { + // figure out which pluggable transport to use + const supportedTransports = ["meek", "meek_lite"]; + const provider = await lazy.TorProviderBuilder.build(); + const proxy = (await provider.getPluggableTransports()).find( + pt => + pt.type === "exec" && + supportedTransports.some(t => pt.transports.includes(t)) + ); + if (!proxy) { + throw new Error("No supported transport found."); + } + + const meekTransport = proxy.transports.find(t => + supportedTransports.includes(t) + ); + // Convert meek client path to absolute path if necessary + const meekWorkDir = lazy.TorLauncherUtil.getTorFile( + "pt-startup-dir", + false + ); + if (lazy.TorLauncherUtil.isPathRelative(proxy.pathToBinary)) { + const meekPath = meekWorkDir.clone(); + meekPath.appendRelativePath(proxy.pathToBinary); + proxy.pathToBinary = meekPath.path; + } + + // Setup env and start meek process + const ptStateDir = lazy.TorLauncherUtil.getTorFile("tordatadir", false); + ptStateDir.append("pt_state"); // Match what tor uses. + + const envAdditions = { + TOR_PT_MANAGED_TRANSPORT_VER: "1", + TOR_PT_STATE_LOCATION: ptStateDir.path, + TOR_PT_EXIT_ON_STDIN_CLOSE: "1", + TOR_PT_CLIENT_TRANSPORTS: meekTransport, + }; + if (lazy.TorSettings.proxy.enabled) { + envAdditions.TOR_PT_PROXY = lazy.TorSettings.proxyUri; + } + + const opts = { + command: proxy.pathToBinary, + arguments: proxy.options.split(/s+/), + workdir: meekWorkDir.path, + environmentAppend: true, + environment: envAdditions, + stderr: "pipe", + }; + + // Launch meek client + this.#meekClientProcess = await lazy.Subprocess.call(opts); + + // Callback chain for reading stderr + const stderrLogger = async () => { + while (this.#meekClientProcess) { + const errString = await this.#meekClientProcess.stderr.readString(); + if (errString) { + log.error(`MeekTransport: stderr => ${errString}`); + } + } + }; + stderrLogger(); + + // Read pt's stdout until terminal (CMETHODS DONE) is reached + // returns array of lines for parsing + const getInitLines = async (stdout = "") => { + stdout += await this.#meekClientProcess.stdout.readString(); + + // look for the final message + const CMETHODS_DONE = "CMETHODS DONE"; + let endIndex = stdout.lastIndexOf(CMETHODS_DONE); + if (endIndex !== -1) { + endIndex += CMETHODS_DONE.length; + return stdout.substring(0, endIndex).split("\n"); + } + return getInitLines(stdout); + }; + + // read our lines from pt's stdout + const meekInitLines = await getInitLines(); + // tokenize our pt lines + const meekInitTokens = meekInitLines.map(line => { + const tokens = line.split(" "); + return { + keyword: tokens[0], + args: tokens.slice(1), + }; + }); + + // parse our pt tokens + for (const { keyword, args } of meekInitTokens) { + const argsJoined = args.join(" "); + let keywordError = false; + switch (keyword) { + case "VERSION": { + if (args.length !== 1 || args[0] !== "1") { + keywordError = true; + } + break; + } + case "PROXY": { + if (args.length !== 1 || args[0] !== "DONE") { + keywordError = true; + } + break; + } + case "CMETHOD": { + if (args.length !== 3) { + keywordError = true; + break; + } + const transport = args[0]; + const proxyType = args[1]; + const addrPortString = args[2]; + const addrPort = addrPortString.split(":"); + + if (transport !== meekTransport) { + throw new Error( + `MeekTransport: Expected ${meekTransport} but found ${transport}` + ); + } + if (!["socks4", "socks4a", "socks5"].includes(proxyType)) { + throw new Error( + `MeekTransport: Invalid proxy type => ${proxyType}` + ); + } + if (addrPort.length !== 2) { + throw new Error( + `MeekTransport: Invalid proxy address => ${addrPortString}` + ); + } + const addr = addrPort[0]; + const port = parseInt(addrPort[1]); + if (port < 1 || port > 65535) { + throw new Error(`MeekTransport: Invalid proxy port => ${port}`); + } + + // convert proxy type to strings used by protocol-proxy-servce + this.proxyType = proxyType === "socks5" ? "socks" : "socks4"; + this.proxyAddress = addr; + this.proxyPort = port; + + break; + } + // terminal + case "CMETHODS": { + if (args.length !== 1 || args[0] !== "DONE") { + keywordError = true; + } + break; + } + // errors (all fall through): + case "VERSION-ERROR": + case "ENV-ERROR": + case "PROXY-ERROR": + case "CMETHOD-ERROR": + throw new Error(`MeekTransport: ${keyword} => '${argsJoined}'`); + } + if (keywordError) { + throw new Error( + `MeekTransport: Invalid ${keyword} keyword args => '${argsJoined}'` + ); + } + } + + // register callback to cleanup on process exit + this.#meekClientProcess.wait().then(() => { + this.#meekClientProcess = null; + this.uninit(); + }); + [this.proxyUsername, this.proxyPassword] = makeMeekCredentials( + this.proxyType, + reflector, + front + ); + this.#inited = true; + } catch (ex) { + if (this.#meekClientProcess) { + this.#meekClientProcess.kill(); + this.#meekClientProcess = null; + } + throw ex; + } + } + + async uninit() { + this.#inited = false; + + await this.#meekClientProcess?.kill(); + this.#meekClientProcess = null; + this.proxyType = null; + this.proxyAddress = null; + this.proxyPort = 0; + this.proxyUsername = null; + this.proxyPassword = null; + } +} + +/** + * Android implementation of the Meek process. + * + * GeckoView does not provide the subprocess module, so we have to use the + * EventDispatcher, and have a Java handler start and stop the proxy process. + */ +class MeekTransportAndroid { + // These members are used by consumers to setup the proxy to do requests over + // meek. They are passed to newProxyInfoWithAuth. + proxyType = null; + proxyAddress = null; + proxyPort = 0; + proxyUsername = null; + proxyPassword = null; + + /** + * An id for process this instance is linked to. + * + * Since we do not restrict the transport to be a singleton, we need a handle to + * identify the process we want to stop when the transport owner is done. + * We use a counter incremented on the Java side for now. + * + * This number must be a positive integer (i.e., 0 is an invalid handler). + * + * @type {number} + */ + #id = 0; + + async init(reflector, front) { + // ensure we haven't already init'd + if (this.#id) { + throw new Error("MeekTransport: Already initialized"); + } + const details = await lazy.EventDispatcher.instance.sendRequestForResult({ + type: "GeckoView:Tor:StartMeek", + }); + this.#id = details.id; + this.proxyType = "socks"; + this.proxyAddress = details.address; + this.proxyPort = details.port; + [this.proxyUsername, this.proxyPassword] = makeMeekCredentials( + this.proxyType, + reflector, + front + ); + } + + async uninit() { + lazy.EventDispatcher.instance.sendRequest({ + type: "GeckoView:Tor:StopMeek", + id: this.#id, + }); + this.#id = 0; + this.proxyType = null; + this.proxyAddress = null; + this.proxyPort = 0; + this.proxyUsername = null; + this.proxyPassword = null; + } +} + +/** + * Corresponds to a Network error with the request. + */ +export class DomainFrontRequestNetworkError extends Error { + constructor(request, statusCode) { + super(`Error fetching ${request.name}: ${statusCode}`); + this.name = "DomainFrontRequestNetworkError"; + this.statusCode = statusCode; + } +} + +/** + * Corresponds to a non-ok response from the server. + */ +export class DomainFrontRequestResponseError extends Error { + constructor(request) { + super( + `Error response from ${request.name} server: ${request.responseStatus}` + ); + this.name = "DomainFrontRequestResponseError"; + this.status = request.responseStatus; + this.statusText = request.responseStatusText; + } +} + +/** + * Thrown when the caller cancels the request. + */ +export class DomainFrontRequestCancelledError extends Error { + constructor(url) { + super(`Cancelled request to ${url}`); + } +} + +/** + * Callback object to promisify the XPCOM request. + */ +class ResponseListener { + #response = ""; + #responsePromise; + #resolve; + #reject; + constructor() { + this.#response = ""; + // we need this promise here because await nsIHttpChannel::asyncOpen does + // not return only once the request is complete, it seems to return + // after it begins, so we have to get the result from this listener object. + // This promise is only resolved once onStopRequest is called + this.#responsePromise = new Promise((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; + }); + } + + /** + * A promise that resolves to the response body from the request. + * + * @type {Promise<string>} + */ + get response() { + return this.#responsePromise; + } + + // noop + onStartRequest() {} + + // resolve or reject our Promise + onStopRequest(request, status) { + try { + if (!Components.isSuccessCode(status)) { + // Assume this is a network error. + this.#reject(new DomainFrontRequestNetworkError(request, status)); + } + if (request.responseStatus !== 200) { + this.#reject(new DomainFrontRequestResponseError(request)); + } + } catch (err) { + this.#reject(err); + } + this.#resolve(this.#response); + } + + // read response data + onDataAvailable(request, stream, offset, length) { + const scriptableStream = Cc[ + "@mozilla.org/scriptableinputstream;1" + ].createInstance(Ci.nsIScriptableInputStream); + scriptableStream.init(stream); + this.#response += scriptableStream.read(length); + } +} + +/** + * Factory to create HTTP(S) requests over a domain fronted transport. + */ +export class DomainFrontRequestBuilder { + #inited = false; + #meekTransport = null; + + get inited() { + return this.#inited; + } + + async init(reflector, front) { + if (this.#inited) { + throw new Error("DomainFrontRequestBuilder: Already initialized"); + } + + const meekTransport = + Services.appinfo.OS === "Android" + ? new MeekTransportAndroid() + : new MeekTransport(); + await meekTransport.init(reflector, front); + this.#meekTransport = meekTransport; + this.#inited = true; + } + + async uninit() { + await this.#meekTransport?.uninit(); + this.#meekTransport = null; + this.#inited = false; + } + + buildHttpHandler(uriString) { + if (!this.#inited) { + throw new Error("DomainFrontRequestBuilder: Not initialized"); + } + + const { proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword } = + this.#meekTransport; + + const proxyPS = Cc[ + "@mozilla.org/network/protocol-proxy-service;1" + ].getService(Ci.nsIProtocolProxyService); + const flags = Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST; + const noTimeout = 0xffffffff; // UINT32_MAX + const proxyInfo = proxyPS.newProxyInfoWithAuth( + proxyType, + proxyAddress, + proxyPort, + proxyUsername, + proxyPassword, + undefined, + undefined, + flags, + noTimeout, + undefined + ); + + const uri = Services.io.newURI(uriString); + // There does not seem to be a way to directly create an nsILoadInfo from + // JavaScript, so we create a throw away non-proxied channel to get one. + const secFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; + const loadInfo = Services.io.newChannelFromURI( + uri, + undefined, + Services.scriptSecurityManager.getSystemPrincipal(), + undefined, + secFlags, + Ci.nsIContentPolicy.TYPE_OTHER + ).loadInfo; + + const httpHandler = Services.io + .getProtocolHandler("http") + .QueryInterface(Ci.nsIHttpProtocolHandler); + const ch = httpHandler + .newProxiedChannel(uri, proxyInfo, 0, undefined, loadInfo) + .QueryInterface(Ci.nsIHttpChannel); + + // remove all headers except for 'Host" + const headers = []; + ch.visitRequestHeaders({ + visitHeader: key => { + if (key !== "Host") { + headers.push(key); + } + }, + }); + headers.forEach(key => ch.setRequestHeader(key, "", false)); + + return ch; + } + + /** + * Make a request. + * + * @param {string} url The URL to request. + * @param {object} args The arguments to send to the procedure. + * @param {string} args.method The request method. + * @param {string} args.body The request body. + * @param {string} args.contentType The "Content-Type" header to set. + * @param {AbortSignal} [signal] args.signal An optional means of cancelling + * the request early. Will throw DomainFrontRequestCancelledError if + * aborted. + * @returns {Promise<string>} A promise that resolves to the response body. + */ + buildRequest(url, args) { + // Pre-fetch the argument values from `args` so the caller cannot change the + // parameters mid-call. + const { body, method, contentType, signal } = args; + let cancel = null; + const promise = new Promise((resolve, reject) => { + if (signal?.aborted) { + // Unexpected, cancel immediately. + reject(new DomainFrontRequestCancelledError(url)); + return; + } + + let ch = null; + + if (signal) { + cancel = () => { + // Reject prior to calling cancel, since we want to ignore any error + // responses from ResponseListener. + // NOTE: In principle we could let ResponseListener throw this error + // when it receives NS_ERROR_ABORT, but that would rely on mozilla + // never calling this error either. + reject(new DomainFrontRequestCancelledError(url)); + ch?.cancel(Cr.NS_ERROR_ABORT); + }; + signal.addEventListener("abort", cancel); + } + + ch = this.buildHttpHandler(url); + + const inStream = Cc[ + "@mozilla.org/io/string-input-stream;1" + ].createInstance(Ci.nsIStringInputStream); + inStream.setData(body, body.length); + const upChannel = ch.QueryInterface(Ci.nsIUploadChannel); + upChannel.setUploadStream(inStream, contentType, body.length); + ch.requestMethod = method; + + // Make request + const listener = new ResponseListener(); + ch.asyncOpen(listener); + listener.response.then( + body => { + resolve(body); + }, + error => { + reject(error); + } + ); + }); + // Clean up. Do not return this `Promise.finally` since the caller should + // not depend on it. + // We pre-catch and suppress all errors for this `.finally` to stop the + // errors from being duplicated in the console log. + promise + .catch(() => {}) + .finally(() => { + // Remove the callback for the AbortSignal so that it doesn't hold onto + // our channel reference if the caller continues to hold a reference to + // AbortSignal. + if (cancel) { + signal.removeEventListener("abort", cancel); + } + }); + return promise; + } +} diff --git a/toolkit/modules/DragDropFilter.sys.mjs b/toolkit/modules/DragDropFilter.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..58df1eb2b8acd7d249fc4e01db652b5700f6ccf8 --- /dev/null +++ b/toolkit/modules/DragDropFilter.sys.mjs @@ -0,0 +1,143 @@ +/************************************************************************* + * Drag and Drop Handler. + * + * Implements an observer that filters drag events to prevent OS + * access to URLs (a potential proxy bypass vector). + *************************************************************************/ + +const lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "logger", () => { + // Keep the logger lazy, because it is used only in the parent process. + // For some reason, Mozilla considers reading the preference linked to the + // level in the children illegal (and triggers a crash when + // fission.enforceBlocklistedPrefsInSubprocesses is true). + // (Or maybe this crash used to happen when the logger was not lazy, and maybe + // the preferences were not ready, yet?) + return console.createInstance({ + maxLogLevelPref: "browser.dragdropfilter.log_level", + prefix: "DragDropFilter", + }); +}); + +const URLISH_TYPES = Object.freeze([ + "text/x-moz-url", + "text/x-moz-url-data", + "text/uri-list", + "application/x-moz-file-promise-url", +]); + +const MAIN_PROCESS = + Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT; + +const EMPTY_PAYLOAD = {}; +export const OpaqueDrag = { + listening: false, + payload: EMPTY_PAYLOAD, + store(value, type) { + let opaqueKey = crypto.randomUUID(); + this.payload = { opaqueKey, value, type }; + if (!this.listening && MAIN_PROCESS) { + Services.ppmm.addMessageListener( + "DragDropFilter:GetOpaqueDrag", + () => this.payload + ); + this.listening = true; + } + return opaqueKey; + }, + retrieve(key) { + let { opaqueKey, value, type } = this.payload; + if (opaqueKey === key) { + return { value, type }; + } + if (!MAIN_PROCESS) { + this.payload = Services.cpmm.sendSyncMessage( + "DragDropFilter:GetOpaqueDrag" + )[0]; + if (key === this.payload.opaqueKey) { + return this.retrieve(key); + } + } + return EMPTY_PAYLOAD; + }, +}; + +export const DragDropFilter = { + init() { + if (MAIN_PROCESS) { + lazy.logger.info( + "Observed profile-after-change: registering the observer." + ); + // We want to update our status in the main process only, in order to + // serve the same opaque drag payload in every process. + try { + Services.obs.addObserver(this, "on-datatransfer-available"); + } catch (e) { + lazy.logger.error("Failed to register drag observer", e); + } + } + }, + + observe(subject, topic) { + if (topic === "on-datatransfer-available") { + lazy.logger.debug("The DataTransfer is available"); + this.filterDataTransferURLs(subject); + } + }, + + filterDataTransferURLs(aDataTransfer) { + for (let i = 0, count = aDataTransfer.mozItemCount; i < count; ++i) { + lazy.logger.debug(`Inspecting the data transfer: ${i}.`); + const types = aDataTransfer.mozTypesAt(i); + const urlType = "text/x-moz-url"; + // Fallback url type, to be parsed by this browser but not externally + const INTERNAL_FALLBACK = "application/x-torbrowser-opaque"; + if (types.contains(urlType)) { + const links = aDataTransfer.mozGetDataAt(urlType, i); + // Skip DNS-safe URLs (no hostname, e.g. RFC 3966 tel:) + const mayLeakDNS = links.split("\n").some(link => { + try { + return new URL(link).hostname; + } catch (e) { + return false; + } + }); + if (!mayLeakDNS) { + continue; + } + const opaqueKey = OpaqueDrag.store(links, urlType); + aDataTransfer.mozSetDataAt(INTERNAL_FALLBACK, opaqueKey, i); + } + for (const maybeUrlType of types) { + lazy.logger.debug(`Type is: ${maybeUrlType}.`); + if (URLISH_TYPES.includes(maybeUrlType)) { + lazy.logger.info( + `Removing transfer data ${aDataTransfer.mozGetDataAt( + maybeUrlType, + i + )}` + ); + // Once we find a URL, we remove also all the other types that can be + // read outside the browser, to be sure the URL is not leaked. + for (const type of types) { + if ( + type !== INTERNAL_FALLBACK && + type !== "text/x-moz-place" && // don't touch bookmarks + type !== "application/x-moz-file" // don't touch downloads + ) { + aDataTransfer.mozClearDataAt(type, i); + } + } + break; + } + } + } + }, + + opaqueDrag: { + get(opaqueKey) { + return OpaqueDrag.retrieve(opaqueKey); + }, + }, +}; diff --git a/toolkit/modules/FinderParent.sys.mjs b/toolkit/modules/FinderParent.sys.mjs index 1f66ec95b0dace9523ba2ae5d1d79b45513dd7b3..ae2cf4123303cd521cdd8a316ee64151a4e12684 100644 --- a/toolkit/modules/FinderParent.sys.mjs +++ b/toolkit/modules/FinderParent.sys.mjs @@ -14,19 +14,9 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { GetClipboardSearchString: "resource://gre/modules/Finder.sys.mjs", - RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", Rect: "resource://gre/modules/Geometry.sys.mjs", }); -const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing"; - -XPCOMUtils.defineLazyPreferenceGetter( - lazy, - "isLetterboxingEnabled", - kPrefLetterboxing, - false -); - XPCOMUtils.defineLazyPreferenceGetter( lazy, "isSoundEnabled", @@ -584,20 +574,10 @@ FinderParent.prototype = { onFindbarClose() { this._lastFoundBrowsingContext = null; this.sendMessageToAllContexts("Finder:FindbarClose"); - - if (lazy.isLetterboxingEnabled) { - let window = this._browser.ownerGlobal; - lazy.RFPHelper.contentSizeUpdated(window); - } }, onFindbarOpen() { this.sendMessageToAllContexts("Finder:FindbarOpen"); - - if (lazy.isLetterboxingEnabled) { - let window = this._browser.ownerGlobal; - lazy.RFPHelper.contentSizeUpdated(window); - } }, onModalHighlightChange(aUseModalHighlight) { diff --git a/toolkit/modules/Moat.sys.mjs b/toolkit/modules/Moat.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..e0185a918e75cbd56596966ec27062172ced3d3f --- /dev/null +++ b/toolkit/modules/Moat.sys.mjs @@ -0,0 +1,469 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +const log = console.createInstance({ + prefix: "Moat", + maxLogLevelPref: "browser.torMoat.loglevel", +}); + +ChromeUtils.defineESModuleGetters(lazy, { + DomainFrontRequestBuilder: + "resource://gre/modules/DomainFrontedRequests.sys.mjs", + DomainFrontRequestCancelledError: + "resource://gre/modules/DomainFrontedRequests.sys.mjs", + TorBridgeSource: "resource://gre/modules/TorSettings.sys.mjs", +}); + +const TorLauncherPrefs = Object.freeze({ + bridgedb_front: "extensions.torlauncher.bridgedb_front", + bridgedb_reflector: "extensions.torlauncher.bridgedb_reflector", + moat_service: "extensions.torlauncher.moat_service", +}); + +/** + * A special response listener that collects the received headers. + */ +class InternetTestResponseListener { + #promise; + #resolve; + #reject; + constructor() { + this.#promise = new Promise((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; + }); + } + + // callers wait on this for final response + get status() { + return this.#promise; + } + + onStartRequest() {} + + // resolve or reject our Promise + onStopRequest(request, status) { + try { + const statuses = { + components: status, + successful: Components.isSuccessCode(status), + }; + try { + if (statuses.successful) { + statuses.http = request.responseStatus; + statuses.date = request.getResponseHeader("Date"); + } + } catch (err) { + console.warn( + "Successful request, but could not get the HTTP status or date", + err + ); + } + this.#resolve(statuses); + } catch (err) { + this.#reject(err); + } + } + + onDataAvailable() { + // We do not care of the actual data, as long as we have a successful + // connection + } +} + +/** + * @typedef {Object} MoatBridges + * + * Bridge settings that can be passed to TorSettings.bridges. + * + * @property {number} source - The `TorBridgeSource` type. + * @property {string} [builtin_type] - The built-in bridge type. + * @property {string[]} [bridge_strings] - The bridge lines. + */ + +/** + * @typedef {Object} MoatSettings + * + * The settings returned by Moat. + * + * @property {MoatBridges[]} bridgesList - The list of bridges found. + * @property {string} [country] - The detected country (region). + */ + +/** + * @typedef {Object} CaptchaChallenge + * + * The details for a captcha challenge. + * + * @property {string} transport - The transport type selected by the Moat + * server. + * @property {string} image - A base64 encoded jpeg with the captcha to + * complete. + * @property {string} challenge - A nonce/cookie string associated with this + * request. + */ + +/** + * Constructs JSON objects and sends requests over Moat. + * The documentation about the JSON schemas to use are available at + * https://gitlab.torproject.org/tpo/anti-censorship/rdsys/-/blob/main/doc/moat.md. + */ +export class MoatRPC { + #requestBuilder = null; + + async init() { + if (this.#requestBuilder !== null) { + return; + } + + const reflector = Services.prefs.getStringPref( + TorLauncherPrefs.bridgedb_reflector + ); + const front = Services.prefs.getStringPref(TorLauncherPrefs.bridgedb_front); + this.#requestBuilder = new lazy.DomainFrontRequestBuilder(); + try { + await this.#requestBuilder.init(reflector, front); + } catch (e) { + this.#requestBuilder = null; + throw e; + } + } + + async uninit() { + await this.#requestBuilder?.uninit(); + this.#requestBuilder = null; + } + + /** + * @typedef {Object} MoatResult + * + * The result of a Moat request. + * + * @property {any} response - The parsed JSON response from the Moat server, + * or `undefined` if the request was cancelled. + * @property {boolean} cancelled - Whether the request was cancelled. + */ + + /** + * Make a request to Moat. + * + * @param {string} procedure - The name of the procedure. + * @param {object} args - The arguments to pass in as a JSON string. + * @param {AbortSignal} [abortSignal] - An optional signal to be able to abort + * the request early. + * @returns {MoatResult} - The result of the request. + */ + async #makeRequest(procedure, args, abortSignal) { + const procedureURIString = `${Services.prefs.getStringPref( + TorLauncherPrefs.moat_service + )}/${procedure}`; + log.info(`Making request to ${procedureURIString}:`, args); + let response = undefined; + let cancelled = false; + try { + response = JSON.parse( + await this.#requestBuilder.buildRequest(procedureURIString, { + method: "POST", + contentType: "application/vnd.api+json", + body: JSON.stringify(args), + signal: abortSignal, + }) + ); + log.info(`Response to ${procedureURIString}:`, response); + } catch (e) { + if (abortSignal && e instanceof lazy.DomainFrontRequestCancelledError) { + log.info(`Request to ${procedureURIString} cancelled`); + cancelled = true; + } else { + throw e; + } + } + return { response, cancelled }; + } + + async testInternetConnection() { + const uri = `${Services.prefs.getStringPref( + TorLauncherPrefs.moat_service + )}/circumvention/countries`; + const ch = this.#requestBuilder.buildHttpHandler(uri); + ch.requestMethod = "HEAD"; + + const listener = new InternetTestResponseListener(); + ch.asyncOpen(listener, ch); + return listener.status; + } + + /** + * Request a CAPTCHA challenge. + * + * @param {string[]} transports - List of transport strings available to us + * eg: ["obfs4", "meek"]. + * @param {AbortSignal} abortSignal - A signal to abort the request early. + * @returns {?CaptchaChallenge} - The captcha challenge, or `null` if the + * request was aborted by the caller. + */ + async fetch(transports, abortSignal) { + if ( + // ensure this is an array + Array.isArray(transports) && + // ensure array has values + !!transports.length && + // ensure each value in the array is a string + transports.reduce((acc, cur) => acc && typeof cur === "string", true) + ) { + const args = { + data: [ + { + version: "0.1.0", + type: "client-transports", + supported: transports, + }, + ], + }; + const { response, cancelled } = await this.#makeRequest( + "fetch", + args, + abortSignal + ); + if (cancelled) { + return null; + } + + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; + throw new Error(`MoatRPC: ${detail} (${code})`); + } + + const transport = response.data[0].transport; + const image = response.data[0].image; + const challenge = response.data[0].challenge; + + return { transport, image, challenge }; + } + throw new Error("MoatRPC: fetch() expects a non-empty array of strings"); + } + + /** + * Submit an answer for a previous CAPTCHA fetch to get bridges. + * + * @param {string} transport - The transport associated with the fetch. + * @param {string} challenge - The nonce string associated with the fetch. + * @param {string} solution - The solution to the CAPTCHA. + * @param {AbortSignal} abortSignal - A signal to abort the request early. + * @returns {?string[]} - The bridge lines for a correct solution, or `null` + * if the solution was incorrect or the request was aborted by the caller. + */ + async check(transport, challenge, solution, abortSignal) { + const args = { + data: [ + { + id: "2", + version: "0.1.0", + type: "moat-solution", + transport, + challenge, + solution, + qrcode: "false", + }, + ], + }; + const { response, cancelled } = await this.#makeRequest( + "check", + args, + abortSignal + ); + if (cancelled) { + return null; + } + + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; + if (code == 419 && detail === "The CAPTCHA solution was incorrect.") { + return null; + } + + throw new Error(`MoatRPC: ${detail} (${code})`); + } + + return response.data[0].bridges; + } + + /** + * Extract bridges from the received Moat settings object. + * + * @param {Object} settings - The received settings. + * @return {MoatBridge} The extracted bridges. + */ + #extractBridges(settings) { + if (!("bridges" in settings)) { + throw new Error("Expected to find `bridges` in the settings object."); + } + const bridges = {}; + switch (settings.bridges.source) { + case "builtin": + bridges.source = lazy.TorBridgeSource.BuiltIn; + bridges.builtin_type = String(settings.bridges.type); + // Ignore the bridge_strings argument since we will use our built-in + // bridge strings instead. + break; + case "bridgedb": + bridges.source = lazy.TorBridgeSource.BridgeDB; + if (settings.bridges.bridge_strings?.length) { + bridges.bridge_strings = Array.from( + settings.bridges.bridge_strings, + item => String(item) + ); + } else { + throw new Error( + "Received no bridge-strings for BridgeDB bridge source" + ); + } + break; + default: + throw new Error( + `Unexpected bridge source '${settings.bridges.source}'` + ); + } + return bridges; + } + + /** + * Extract a list of bridges from the received Moat settings object. + * + * @param {Object} settings - The received settings. + * @return {MoatBridge[]} The list of extracted bridges. + */ + #extractBridgesList(settingsList) { + const bridgesList = []; + for (const settings of settingsList) { + try { + bridgesList.push(this.#extractBridges(settings)); + } catch (ex) { + log.error(ex); + } + } + return bridgesList; + } + + /** + * Request tor settings for the user optionally based on their location + * (derived from their IP). Takes the following parameters: + * + * @param {string[]} transports - A list of transports we support. + * @param {?string} country - The region to request bridges for, as an + * ISO 3166-1 alpha-2 region code, or `null` to have the server + * automatically determine the region. + * @param {AbortSignal} abortSignal - A signal to abort the request early. + * @returns {?MoatSettings} - The returned settings from the server, or `null` + * if the region could not be determined by the server or the caller + * cancelled the request. + */ + async circumvention_settings(transports, country, abortSignal) { + const args = { + transports: transports ? transports : [], + country, + }; + const { response, cancelled } = await this.#makeRequest( + "circumvention/settings", + args, + abortSignal + ); + if (cancelled) { + return null; + } + let settings = {}; + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; + if (code == 406) { + log.error( + "MoatRPC::circumvention_settings(): Cannot automatically determine user's country-code" + ); + // cannot determine user's country + return null; + } + + throw new Error(`MoatRPC: ${detail} (${code})`); + } else if ("settings" in response) { + settings.bridgesList = this.#extractBridgesList(response.settings); + } + if ("country" in response) { + settings.country = response.country; + } + return settings; + } + + // Request a list of country codes with available censorship circumvention + // settings. + // + // returns an array of ISO 3166-1 alpha-2 country codes which we can query + // settings for. + async circumvention_countries() { + const args = {}; + const { response } = await this.#makeRequest( + "circumvention/countries", + args + ); + return response; + } + + // Request a copy of the builtin bridges, takes the following parameters: + // - transports: optional, an array of transports we would like the latest + // bridge strings for; if empty (or not given) returns all of them + // + // returns a map whose keys are pluggable transport types and whose values are + // arrays of bridge strings for that type + async circumvention_builtin(transports) { + const args = { + transports: transports ? transports : [], + }; + const { response } = await this.#makeRequest("circumvention/builtin", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; + throw new Error(`MoatRPC: ${detail} (${code})`); + } + + let map = new Map(); + for (const [transport, bridge_strings] of Object.entries(response)) { + map.set(transport, bridge_strings); + } + + return map; + } + + /** + * Request a copy of the default/fallback bridge settings. + * + * @param {string[]} transports - A list of transports we support. + * @param {AbortSignal} abortSignal - A signal to abort the request early. + * @returns {?MoatBridges[]} - The list of bridges found, or `null` if the + * caller cancelled the request. + */ + async circumvention_defaults(transports, abortSignal) { + const args = { + transports: transports ? transports : [], + }; + const { response, cancelled } = await this.#makeRequest( + "circumvention/defaults", + args, + abortSignal + ); + if (cancelled) { + return null; + } + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; + throw new Error(`MoatRPC: ${detail} (${code})`); + } else if ("settings" in response) { + return this.#extractBridgesList(response.settings); + } + return []; + } +} diff --git a/toolkit/modules/PopupNotifications.sys.mjs b/toolkit/modules/PopupNotifications.sys.mjs index 22e8e356df11bb3c06d1e837fe661ccc3d7f5cf6..b2fe79eafd92cae3a6d6521569f34d03ea3c1a79 100644 --- a/toolkit/modules/PopupNotifications.sys.mjs +++ b/toolkit/modules/PopupNotifications.sys.mjs @@ -439,6 +439,8 @@ PopupNotifications.prototype = { * will be dismissed instead of removed after running the callback. * - [optional] disabled (boolean): If this is true, the button * will be disabled. + * - [optional] leaveOpen (boolean): If this is true, the notification + * will not be removed after running the callback. * If null, the notification will have a default "OK" action button * that can be used to dismiss the popup and secondaryActions will be ignored. * @param secondaryActions @@ -1987,6 +1989,10 @@ PopupNotifications.prototype = { this._dismiss(); return; } + + if (action.leaveOpen) { + return; + } } this._remove(notification); diff --git a/toolkit/modules/QRCode.sys.mjs b/toolkit/modules/QRCode.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..6400b316e1dcffcf6318fc97df84116669d8bbad --- /dev/null +++ b/toolkit/modules/QRCode.sys.mjs @@ -0,0 +1,1238 @@ +/* eslint-disable */ +/** + * @fileoverview + * - Using the 'QRCode for Javascript library' + * - Fixed dataset of 'QRCode for Javascript library' for support full-spec. + * - this library has no dependencies. + * + * Modified to be used as a module by the Tor Project + * + * @author Kazuhiko Arase, davidshimjs, ivan386 + * @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a> + * @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a> + */ + +export var QRCode; + +(function () { + //--------------------------------------------------------------------- + // QRCode for JavaScript + // + // Copyright (c) 2009 Kazuhiko Arase + // + // URL: http://www.d-project.com/ + // + // Licensed under the MIT license: + // http://www.opensource.org/licenses/mit-license.php + // + // The word "QR Code" is registered trademark of + // DENSO WAVE INCORPORATED + // http://www.denso-wave.com/qrcode/faqpatent-e.html + // + //--------------------------------------------------------------------- + function QR8bitByte(data) { + this.mode = QRMode.MODE_8BIT_BYTE; + this.data = data; + this.parsedData = []; + + // Added to support UTF-8 Characters + for (var i = 0, l = this.data.length; i < l; i++) { + var byteArray = []; + var code = this.data.charCodeAt(i); + + if (code > 0x10000) { + byteArray[0] = 0xf0 | ((code & 0x1c0000) >>> 18); + byteArray[1] = 0x80 | ((code & 0x3f000) >>> 12); + byteArray[2] = 0x80 | ((code & 0xfc0) >>> 6); + byteArray[3] = 0x80 | (code & 0x3f); + } else if (code > 0x800) { + byteArray[0] = 0xe0 | ((code & 0xf000) >>> 12); + byteArray[1] = 0x80 | ((code & 0xfc0) >>> 6); + byteArray[2] = 0x80 | (code & 0x3f); + } else if (code > 0x80) { + byteArray[0] = 0xc0 | ((code & 0x7c0) >>> 6); + byteArray[1] = 0x80 | (code & 0x3f); + } else { + byteArray[0] = code; + } + + this.parsedData.push(byteArray); + } + + this.parsedData = Array.prototype.concat.apply([], this.parsedData); + + if (this.parsedData.length != this.data.length) { + this.parsedData.unshift(191); + this.parsedData.unshift(187); + this.parsedData.unshift(239); + } + } + + QR8bitByte.prototype = { + getLength(buffer) { + return this.parsedData.length; + }, + write(buffer) { + for (var i = 0, l = this.parsedData.length; i < l; i++) { + buffer.put(this.parsedData[i], 8); + } + }, + }; + + function QRCodeModel(typeNumber, errorCorrectLevel) { + this.typeNumber = typeNumber; + this.errorCorrectLevel = errorCorrectLevel; + this.modules = null; + this.moduleCount = 0; + this.dataCache = null; + this.dataList = []; + } + + QRCodeModel.prototype = { + addData(data) { + var newData = new QR8bitByte(data); + this.dataList.push(newData); + this.dataCache = null; + }, + isDark(row, col) { + if ( + row < 0 || + this.moduleCount <= row || + col < 0 || + this.moduleCount <= col + ) { + throw new Error(row + "," + col); + } + return this.modules[row][col]; + }, + getModuleCount() { + return this.moduleCount; + }, + make() { + this.makeImpl(false, this.getBestMaskPattern()); + }, + makeImpl(test, maskPattern) { + this.moduleCount = this.typeNumber * 4 + 17; + this.modules = new Array(this.moduleCount); + for (var row = 0; row < this.moduleCount; row++) { + this.modules[row] = new Array(this.moduleCount); + for (var col = 0; col < this.moduleCount; col++) { + this.modules[row][col] = null; + } + } + this.setupPositionProbePattern(0, 0); + this.setupPositionProbePattern(this.moduleCount - 7, 0); + this.setupPositionProbePattern(0, this.moduleCount - 7); + this.setupPositionAdjustPattern(); + this.setupTimingPattern(); + this.setupTypeInfo(test, maskPattern); + if (this.typeNumber >= 7) { + this.setupTypeNumber(test); + } + if (this.dataCache == null) { + this.dataCache = QRCodeModel.createData( + this.typeNumber, + this.errorCorrectLevel, + this.dataList + ); + } + this.mapData(this.dataCache, maskPattern); + }, + setupPositionProbePattern(row, col) { + for (var r = -1; r <= 7; r++) { + if (row + r <= -1 || this.moduleCount <= row + r) { + continue; + } + for (var c = -1; c <= 7; c++) { + if (col + c <= -1 || this.moduleCount <= col + c) { + continue; + } + if ( + (0 <= r && r <= 6 && (c == 0 || c == 6)) || + (0 <= c && c <= 6 && (r == 0 || r == 6)) || + (2 <= r && r <= 4 && 2 <= c && c <= 4) + ) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + }, + getBestMaskPattern() { + var minLostPoint = 0; + var pattern = 0; + for (var i = 0; i < 8; i++) { + this.makeImpl(true, i); + var lostPoint = QRUtil.getLostPoint(this); + if (i == 0 || minLostPoint > lostPoint) { + minLostPoint = lostPoint; + pattern = i; + } + } + return pattern; + }, + createMovieClip(target_mc, instance_name, depth) { + var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); + var cs = 1; + this.make(); + for (var row = 0; row < this.modules.length; row++) { + var y = row * cs; + for (var col = 0; col < this.modules[row].length; col++) { + var x = col * cs; + var dark = this.modules[row][col]; + if (dark) { + qr_mc.beginFill(0, 100); + qr_mc.moveTo(x, y); + qr_mc.lineTo(x + cs, y); + qr_mc.lineTo(x + cs, y + cs); + qr_mc.lineTo(x, y + cs); + qr_mc.endFill(); + } + } + } + return qr_mc; + }, + setupTimingPattern() { + for (var r = 8; r < this.moduleCount - 8; r++) { + if (this.modules[r][6] != null) { + continue; + } + this.modules[r][6] = r % 2 == 0; + } + for (var c = 8; c < this.moduleCount - 8; c++) { + if (this.modules[6][c] != null) { + continue; + } + this.modules[6][c] = c % 2 == 0; + } + }, + setupPositionAdjustPattern() { + var pos = QRUtil.getPatternPosition(this.typeNumber); + for (var i = 0; i < pos.length; i++) { + for (var j = 0; j < pos.length; j++) { + var row = pos[i]; + var col = pos[j]; + if (this.modules[row][col] != null) { + continue; + } + for (var r = -2; r <= 2; r++) { + for (var c = -2; c <= 2; c++) { + if ( + r == -2 || + r == 2 || + c == -2 || + c == 2 || + (r == 0 && c == 0) + ) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + } + } + }, + setupTypeNumber(test) { + var bits = QRUtil.getBCHTypeNumber(this.typeNumber); + for (var i = 0; i < 18; i++) { + var mod = !test && ((bits >> i) & 1) == 1; + this.modules[Math.floor(i / 3)][(i % 3) + this.moduleCount - 8 - 3] = + mod; + } + for (var i = 0; i < 18; i++) { + var mod = !test && ((bits >> i) & 1) == 1; + this.modules[(i % 3) + this.moduleCount - 8 - 3][Math.floor(i / 3)] = + mod; + } + }, + setupTypeInfo(test, maskPattern) { + var data = (this.errorCorrectLevel << 3) | maskPattern; + var bits = QRUtil.getBCHTypeInfo(data); + for (var i = 0; i < 15; i++) { + var mod = !test && ((bits >> i) & 1) == 1; + if (i < 6) { + this.modules[i][8] = mod; + } else if (i < 8) { + this.modules[i + 1][8] = mod; + } else { + this.modules[this.moduleCount - 15 + i][8] = mod; + } + } + for (var i = 0; i < 15; i++) { + var mod = !test && ((bits >> i) & 1) == 1; + if (i < 8) { + this.modules[8][this.moduleCount - i - 1] = mod; + } else if (i < 9) { + this.modules[8][15 - i - 1 + 1] = mod; + } else { + this.modules[8][15 - i - 1] = mod; + } + } + this.modules[this.moduleCount - 8][8] = !test; + }, + mapData(data, maskPattern) { + var inc = -1; + var row = this.moduleCount - 1; + var bitIndex = 7; + var byteIndex = 0; + for (var col = this.moduleCount - 1; col > 0; col -= 2) { + if (col == 6) { + col--; + } + while (true) { + for (var c = 0; c < 2; c++) { + if (this.modules[row][col - c] == null) { + var dark = false; + if (byteIndex < data.length) { + dark = ((data[byteIndex] >>> bitIndex) & 1) == 1; + } + var mask = QRUtil.getMask(maskPattern, row, col - c); + if (mask) { + dark = !dark; + } + this.modules[row][col - c] = dark; + bitIndex--; + if (bitIndex == -1) { + byteIndex++; + bitIndex = 7; + } + } + } + row += inc; + if (row < 0 || this.moduleCount <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + }, + }; + QRCodeModel.PAD0 = 0xec; + QRCodeModel.PAD1 = 0x11; + QRCodeModel.createData = function (typeNumber, errorCorrectLevel, dataList) { + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); + var buffer = new QRBitBuffer(); + for (var i = 0; i < dataList.length; i++) { + var data = dataList[i]; + buffer.put(data.mode, 4); + buffer.put( + data.getLength(), + QRUtil.getLengthInBits(data.mode, typeNumber) + ); + data.write(buffer); + } + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + if (buffer.getLengthInBits() > totalDataCount * 8) { + throw new Error( + "code length overflow. (" + + buffer.getLengthInBits() + + ">" + + totalDataCount * 8 + + ")" + ); + } + if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { + buffer.put(0, 4); + } + while (buffer.getLengthInBits() % 8 != 0) { + buffer.putBit(false); + } + while (true) { + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCodeModel.PAD0, 8); + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCodeModel.PAD1, 8); + } + return QRCodeModel.createBytes(buffer, rsBlocks); + }; + QRCodeModel.createBytes = function (buffer, rsBlocks) { + var offset = 0; + var maxDcCount = 0; + var maxEcCount = 0; + var dcdata = new Array(rsBlocks.length); + var ecdata = new Array(rsBlocks.length); + for (var r = 0; r < rsBlocks.length; r++) { + var dcCount = rsBlocks[r].dataCount; + var ecCount = rsBlocks[r].totalCount - dcCount; + maxDcCount = Math.max(maxDcCount, dcCount); + maxEcCount = Math.max(maxEcCount, ecCount); + dcdata[r] = new Array(dcCount); + for (var i = 0; i < dcdata[r].length; i++) { + dcdata[r][i] = 0xff & buffer.buffer[i + offset]; + } + offset += dcCount; + var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); + var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); + var modPoly = rawPoly.mod(rsPoly); + ecdata[r] = new Array(rsPoly.getLength() - 1); + for (var i = 0; i < ecdata[r].length; i++) { + var modIndex = i + modPoly.getLength() - ecdata[r].length; + ecdata[r][i] = modIndex >= 0 ? modPoly.get(modIndex) : 0; + } + } + var totalCodeCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalCodeCount += rsBlocks[i].totalCount; + } + var data = new Array(totalCodeCount); + var index = 0; + for (var i = 0; i < maxDcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < dcdata[r].length) { + data[index++] = dcdata[r][i]; + } + } + } + for (var i = 0; i < maxEcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < ecdata[r].length) { + data[index++] = ecdata[r][i]; + } + } + } + return data; + }; + var QRMode = { + MODE_NUMBER: 1 << 0, + MODE_ALPHA_NUM: 1 << 1, + MODE_8BIT_BYTE: 1 << 2, + MODE_KANJI: 1 << 3, + }; + var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 }; + var QRMaskPattern = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7, + }; + var QRUtil = { + PATTERN_POSITION_TABLE: [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170], + ], + G15: + (1 << 10) | + (1 << 8) | + (1 << 5) | + (1 << 4) | + (1 << 2) | + (1 << 1) | + (1 << 0), + G18: + (1 << 12) | + (1 << 11) | + (1 << 10) | + (1 << 9) | + (1 << 8) | + (1 << 5) | + (1 << 2) | + (1 << 0), + G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), + getBCHTypeInfo(data) { + var d = data << 10; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { + d ^= + QRUtil.G15 << + (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)); + } + return ((data << 10) | d) ^ QRUtil.G15_MASK; + }, + getBCHTypeNumber(data) { + var d = data << 12; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { + d ^= + QRUtil.G18 << + (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)); + } + return (data << 12) | d; + }, + getBCHDigit(data) { + var digit = 0; + while (data != 0) { + digit++; + data >>>= 1; + } + return digit; + }, + getPatternPosition(typeNumber) { + return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; + }, + getMask(maskPattern, i, j) { + switch (maskPattern) { + case QRMaskPattern.PATTERN000: + return (i + j) % 2 == 0; + case QRMaskPattern.PATTERN001: + return i % 2 == 0; + case QRMaskPattern.PATTERN010: + return j % 3 == 0; + case QRMaskPattern.PATTERN011: + return (i + j) % 3 == 0; + case QRMaskPattern.PATTERN100: + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; + case QRMaskPattern.PATTERN101: + return ((i * j) % 2) + ((i * j) % 3) == 0; + case QRMaskPattern.PATTERN110: + return (((i * j) % 2) + ((i * j) % 3)) % 2 == 0; + case QRMaskPattern.PATTERN111: + return (((i * j) % 3) + ((i + j) % 2)) % 2 == 0; + default: + throw new Error("bad maskPattern:" + maskPattern); + } + }, + getErrorCorrectPolynomial(errorCorrectLength) { + var a = new QRPolynomial([1], 0); + for (var i = 0; i < errorCorrectLength; i++) { + a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); + } + return a; + }, + getLengthInBits(mode, type) { + if (1 <= type && type < 10) { + switch (mode) { + case QRMode.MODE_NUMBER: + return 10; + case QRMode.MODE_ALPHA_NUM: + return 9; + case QRMode.MODE_8BIT_BYTE: + return 8; + case QRMode.MODE_KANJI: + return 8; + default: + throw new Error("mode:" + mode); + } + } else if (type < 27) { + switch (mode) { + case QRMode.MODE_NUMBER: + return 12; + case QRMode.MODE_ALPHA_NUM: + return 11; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 10; + default: + throw new Error("mode:" + mode); + } + } else if (type < 41) { + switch (mode) { + case QRMode.MODE_NUMBER: + return 14; + case QRMode.MODE_ALPHA_NUM: + return 13; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 12; + default: + throw new Error("mode:" + mode); + } + } else { + throw new Error("type:" + type); + } + }, + getLostPoint(qrCode) { + var moduleCount = qrCode.getModuleCount(); + var lostPoint = 0; + for (var row = 0; row < moduleCount; row++) { + for (var col = 0; col < moduleCount; col++) { + var sameCount = 0; + var dark = qrCode.isDark(row, col); + for (var r = -1; r <= 1; r++) { + if (row + r < 0 || moduleCount <= row + r) { + continue; + } + for (var c = -1; c <= 1; c++) { + if (col + c < 0 || moduleCount <= col + c) { + continue; + } + if (r == 0 && c == 0) { + continue; + } + if (dark == qrCode.isDark(row + r, col + c)) { + sameCount++; + } + } + } + if (sameCount > 5) { + lostPoint += 3 + sameCount - 5; + } + } + } + for (var row = 0; row < moduleCount - 1; row++) { + for (var col = 0; col < moduleCount - 1; col++) { + var count = 0; + if (qrCode.isDark(row, col)) { + count++; + } + if (qrCode.isDark(row + 1, col)) { + count++; + } + if (qrCode.isDark(row, col + 1)) { + count++; + } + if (qrCode.isDark(row + 1, col + 1)) { + count++; + } + if (count == 0 || count == 4) { + lostPoint += 3; + } + } + } + for (var row = 0; row < moduleCount; row++) { + for (var col = 0; col < moduleCount - 6; col++) { + if ( + qrCode.isDark(row, col) && + !qrCode.isDark(row, col + 1) && + qrCode.isDark(row, col + 2) && + qrCode.isDark(row, col + 3) && + qrCode.isDark(row, col + 4) && + !qrCode.isDark(row, col + 5) && + qrCode.isDark(row, col + 6) + ) { + lostPoint += 40; + } + } + } + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount - 6; row++) { + if ( + qrCode.isDark(row, col) && + !qrCode.isDark(row + 1, col) && + qrCode.isDark(row + 2, col) && + qrCode.isDark(row + 3, col) && + qrCode.isDark(row + 4, col) && + !qrCode.isDark(row + 5, col) && + qrCode.isDark(row + 6, col) + ) { + lostPoint += 40; + } + } + } + var darkCount = 0; + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount; row++) { + if (qrCode.isDark(row, col)) { + darkCount++; + } + } + } + var ratio = + Math.abs((100 * darkCount) / moduleCount / moduleCount - 50) / 5; + lostPoint += ratio * 10; + return lostPoint; + }, + }; + var QRMath = { + glog(n) { + if (n < 1) { + throw new Error("glog(" + n + ")"); + } + return QRMath.LOG_TABLE[n]; + }, + gexp(n) { + while (n < 0) { + n += 255; + } + while (n >= 256) { + n -= 255; + } + return QRMath.EXP_TABLE[n]; + }, + EXP_TABLE: new Array(256), + LOG_TABLE: new Array(256), + }; + for (var i = 0; i < 8; i++) { + QRMath.EXP_TABLE[i] = 1 << i; + } + for (var i = 8; i < 256; i++) { + QRMath.EXP_TABLE[i] = + QRMath.EXP_TABLE[i - 4] ^ + QRMath.EXP_TABLE[i - 5] ^ + QRMath.EXP_TABLE[i - 6] ^ + QRMath.EXP_TABLE[i - 8]; + } + for (var i = 0; i < 255; i++) { + QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; + } + function QRPolynomial(num, shift) { + if (num.length == undefined) { + throw new Error(num.length + "/" + shift); + } + var offset = 0; + while (offset < num.length && num[offset] == 0) { + offset++; + } + this.num = new Array(num.length - offset + shift); + for (var i = 0; i < num.length - offset; i++) { + this.num[i] = num[i + offset]; + } + } + QRPolynomial.prototype = { + get(index) { + return this.num[index]; + }, + getLength() { + return this.num.length; + }, + multiply(e) { + var num = new Array(this.getLength() + e.getLength() - 1); + for (var i = 0; i < this.getLength(); i++) { + for (var j = 0; j < e.getLength(); j++) { + num[i + j] ^= QRMath.gexp( + QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)) + ); + } + } + return new QRPolynomial(num, 0); + }, + mod(e) { + if (this.getLength() - e.getLength() < 0) { + return this; + } + var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); + var num = new Array(this.getLength()); + for (var i = 0; i < this.getLength(); i++) { + num[i] = this.get(i); + } + for (var i = 0; i < e.getLength(); i++) { + num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); + } + return new QRPolynomial(num, 0).mod(e); + }, + }; + function QRRSBlock(totalCount, dataCount) { + this.totalCount = totalCount; + this.dataCount = dataCount; + } + QRRSBlock.RS_BLOCK_TABLE = [ + [1, 26, 19], + [1, 26, 16], + [1, 26, 13], + [1, 26, 9], + [1, 44, 34], + [1, 44, 28], + [1, 44, 22], + [1, 44, 16], + [1, 70, 55], + [1, 70, 44], + [2, 35, 17], + [2, 35, 13], + [1, 100, 80], + [2, 50, 32], + [2, 50, 24], + [4, 25, 9], + [1, 134, 108], + [2, 67, 43], + [2, 33, 15, 2, 34, 16], + [2, 33, 11, 2, 34, 12], + [2, 86, 68], + [4, 43, 27], + [4, 43, 19], + [4, 43, 15], + [2, 98, 78], + [4, 49, 31], + [2, 32, 14, 4, 33, 15], + [4, 39, 13, 1, 40, 14], + [2, 121, 97], + [2, 60, 38, 2, 61, 39], + [4, 40, 18, 2, 41, 19], + [4, 40, 14, 2, 41, 15], + [2, 146, 116], + [3, 58, 36, 2, 59, 37], + [4, 36, 16, 4, 37, 17], + [4, 36, 12, 4, 37, 13], + [2, 86, 68, 2, 87, 69], + [4, 69, 43, 1, 70, 44], + [6, 43, 19, 2, 44, 20], + [6, 43, 15, 2, 44, 16], + [4, 101, 81], + [1, 80, 50, 4, 81, 51], + [4, 50, 22, 4, 51, 23], + [3, 36, 12, 8, 37, 13], + [2, 116, 92, 2, 117, 93], + [6, 58, 36, 2, 59, 37], + [4, 46, 20, 6, 47, 21], + [7, 42, 14, 4, 43, 15], + [4, 133, 107], + [8, 59, 37, 1, 60, 38], + [8, 44, 20, 4, 45, 21], + [12, 33, 11, 4, 34, 12], + [3, 145, 115, 1, 146, 116], + [4, 64, 40, 5, 65, 41], + [11, 36, 16, 5, 37, 17], + [11, 36, 12, 5, 37, 13], + [5, 109, 87, 1, 110, 88], + [5, 65, 41, 5, 66, 42], + [5, 54, 24, 7, 55, 25], + [11, 36, 12], + [5, 122, 98, 1, 123, 99], + [7, 73, 45, 3, 74, 46], + [15, 43, 19, 2, 44, 20], + [3, 45, 15, 13, 46, 16], + [1, 135, 107, 5, 136, 108], + [10, 74, 46, 1, 75, 47], + [1, 50, 22, 15, 51, 23], + [2, 42, 14, 17, 43, 15], + [5, 150, 120, 1, 151, 121], + [9, 69, 43, 4, 70, 44], + [17, 50, 22, 1, 51, 23], + [2, 42, 14, 19, 43, 15], + [3, 141, 113, 4, 142, 114], + [3, 70, 44, 11, 71, 45], + [17, 47, 21, 4, 48, 22], + [9, 39, 13, 16, 40, 14], + [3, 135, 107, 5, 136, 108], + [3, 67, 41, 13, 68, 42], + [15, 54, 24, 5, 55, 25], + [15, 43, 15, 10, 44, 16], + [4, 144, 116, 4, 145, 117], + [17, 68, 42], + [17, 50, 22, 6, 51, 23], + [19, 46, 16, 6, 47, 17], + [2, 139, 111, 7, 140, 112], + [17, 74, 46], + [7, 54, 24, 16, 55, 25], + [34, 37, 13], + [4, 151, 121, 5, 152, 122], + [4, 75, 47, 14, 76, 48], + [11, 54, 24, 14, 55, 25], + [16, 45, 15, 14, 46, 16], + [6, 147, 117, 4, 148, 118], + [6, 73, 45, 14, 74, 46], + [11, 54, 24, 16, 55, 25], + [30, 46, 16, 2, 47, 17], + [8, 132, 106, 4, 133, 107], + [8, 75, 47, 13, 76, 48], + [7, 54, 24, 22, 55, 25], + [22, 45, 15, 13, 46, 16], + [10, 142, 114, 2, 143, 115], + [19, 74, 46, 4, 75, 47], + [28, 50, 22, 6, 51, 23], + [33, 46, 16, 4, 47, 17], + [8, 152, 122, 4, 153, 123], + [22, 73, 45, 3, 74, 46], + [8, 53, 23, 26, 54, 24], + [12, 45, 15, 28, 46, 16], + [3, 147, 117, 10, 148, 118], + [3, 73, 45, 23, 74, 46], + [4, 54, 24, 31, 55, 25], + [11, 45, 15, 31, 46, 16], + [7, 146, 116, 7, 147, 117], + [21, 73, 45, 7, 74, 46], + [1, 53, 23, 37, 54, 24], + [19, 45, 15, 26, 46, 16], + [5, 145, 115, 10, 146, 116], + [19, 75, 47, 10, 76, 48], + [15, 54, 24, 25, 55, 25], + [23, 45, 15, 25, 46, 16], + [13, 145, 115, 3, 146, 116], + [2, 74, 46, 29, 75, 47], + [42, 54, 24, 1, 55, 25], + [23, 45, 15, 28, 46, 16], + [17, 145, 115], + [10, 74, 46, 23, 75, 47], + [10, 54, 24, 35, 55, 25], + [19, 45, 15, 35, 46, 16], + [17, 145, 115, 1, 146, 116], + [14, 74, 46, 21, 75, 47], + [29, 54, 24, 19, 55, 25], + [11, 45, 15, 46, 46, 16], + [13, 145, 115, 6, 146, 116], + [14, 74, 46, 23, 75, 47], + [44, 54, 24, 7, 55, 25], + [59, 46, 16, 1, 47, 17], + [12, 151, 121, 7, 152, 122], + [12, 75, 47, 26, 76, 48], + [39, 54, 24, 14, 55, 25], + [22, 45, 15, 41, 46, 16], + [6, 151, 121, 14, 152, 122], + [6, 75, 47, 34, 76, 48], + [46, 54, 24, 10, 55, 25], + [2, 45, 15, 64, 46, 16], + [17, 152, 122, 4, 153, 123], + [29, 74, 46, 14, 75, 47], + [49, 54, 24, 10, 55, 25], + [24, 45, 15, 46, 46, 16], + [4, 152, 122, 18, 153, 123], + [13, 74, 46, 32, 75, 47], + [48, 54, 24, 14, 55, 25], + [42, 45, 15, 32, 46, 16], + [20, 147, 117, 4, 148, 118], + [40, 75, 47, 7, 76, 48], + [43, 54, 24, 22, 55, 25], + [10, 45, 15, 67, 46, 16], + [19, 148, 118, 6, 149, 119], + [18, 75, 47, 31, 76, 48], + [34, 54, 24, 34, 55, 25], + [20, 45, 15, 61, 46, 16], + ]; + QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) { + var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); + if (rsBlock == undefined) { + throw new Error( + "bad rs block @ typeNumber:" + + typeNumber + + "/errorCorrectLevel:" + + errorCorrectLevel + ); + } + var length = rsBlock.length / 3; + var list = []; + for (var i = 0; i < length; i++) { + var count = rsBlock[i * 3 + 0]; + var totalCount = rsBlock[i * 3 + 1]; + var dataCount = rsBlock[i * 3 + 2]; + for (var j = 0; j < count; j++) { + list.push(new QRRSBlock(totalCount, dataCount)); + } + } + return list; + }; + QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) { + switch (errorCorrectLevel) { + case QRErrorCorrectLevel.L: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; + case QRErrorCorrectLevel.M: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; + case QRErrorCorrectLevel.Q: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; + case QRErrorCorrectLevel.H: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; + default: + return undefined; + } + }; + function QRBitBuffer() { + this.buffer = []; + this.length = 0; + } + QRBitBuffer.prototype = { + get(index) { + var bufIndex = Math.floor(index / 8); + return ((this.buffer[bufIndex] >>> (7 - (index % 8))) & 1) == 1; + }, + put(num, length) { + for (var i = 0; i < length; i++) { + this.putBit(((num >>> (length - i - 1)) & 1) == 1); + } + }, + getLengthInBits() { + return this.length; + }, + putBit(bit) { + var bufIndex = Math.floor(this.length / 8); + if (this.buffer.length <= bufIndex) { + this.buffer.push(0); + } + if (bit) { + this.buffer[bufIndex] |= 0x80 >>> this.length % 8; + } + this.length++; + }, + }; + var QRCodeLimitLength = [ + [17, 14, 11, 7], + [32, 26, 20, 14], + [53, 42, 32, 24], + [78, 62, 46, 34], + [106, 84, 60, 44], + [134, 106, 74, 58], + [154, 122, 86, 64], + [192, 152, 108, 84], + [230, 180, 130, 98], + [271, 213, 151, 119], + [321, 251, 177, 137], + [367, 287, 203, 155], + [425, 331, 241, 177], + [458, 362, 258, 194], + [520, 412, 292, 220], + [586, 450, 322, 250], + [644, 504, 364, 280], + [718, 560, 394, 310], + [792, 624, 442, 338], + [858, 666, 482, 382], + [929, 711, 509, 403], + [1003, 779, 565, 439], + [1091, 857, 611, 461], + [1171, 911, 661, 511], + [1273, 997, 715, 535], + [1367, 1059, 751, 593], + [1465, 1125, 805, 625], + [1528, 1190, 868, 658], + [1628, 1264, 908, 698], + [1732, 1370, 982, 742], + [1840, 1452, 1030, 790], + [1952, 1538, 1112, 842], + [2068, 1628, 1168, 898], + [2188, 1722, 1228, 958], + [2303, 1809, 1283, 983], + [2431, 1911, 1351, 1051], + [2563, 1989, 1423, 1093], + [2699, 2099, 1499, 1139], + [2809, 2213, 1579, 1219], + [2953, 2331, 1663, 1273], + ]; + + var svgDrawer = (function () { + var Drawing = function (el, htOption) { + this._el = el; + this._htOption = htOption; + }; + + Drawing.prototype.draw = function (oQRCode) { + var _htOption = this._htOption; + var _el = this._el; + var nCount = oQRCode.getModuleCount(); + + this.clear(); + + function makeSVG(tag, attrs) { + var el = _el.ownerDocument.createElementNS( + "http://www.w3.org/2000/svg", + tag + ); + for (var k in attrs) { + if (attrs.hasOwnProperty(k)) { + el.setAttribute(k, attrs[k]); + } + } + return el; + } + + var svg = makeSVG("svg", { + viewBox: "0 0 " + String(nCount) + " " + String(nCount), + width: "100%", + height: "100%", + fill: _htOption.colorLight, + "shape-rendering": "crispEdges", + }); + svg.setAttributeNS( + "http://www.w3.org/2000/xmlns/", + "xmlns", + "http://www.w3.org/2000/svg" + ); + _el.appendChild(svg); + + svg.appendChild( + makeSVG("rect", { + fill: _htOption.colorLight, + width: "100%", + height: "100%", + }) + ); + + var path = []; + for (var row = 0; row < nCount; row++) { + for (var col = 0; col < nCount; col++) { + var width = 0; + while (col + width < nCount && oQRCode.isDark(row, col + width)) { + width++; + } + + if (width > 0) { + path.push("M" + col + " " + row + "v1h" + width + "v-1z"); + col += width; + } + } + } + var child = makeSVG("path", { + d: path.join(""), + fill: _htOption.colorDark, + }); + svg.appendChild(child); + }; + Drawing.prototype.clear = function () { + while (this._el.hasChildNodes()) { + this._el.removeChild(this._el.lastChild); + } + }; + return Drawing; + })(); + + /** + * Get the type by string length + * + * @private + * @param {String} sText + * @param {Number} nCorrectLevel + * @return {Number} type + */ + function _getTypeNumber(sText, nCorrectLevel) { + var nType = 1; + var length = _getUTF8Length(sText); + + for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) { + var nLimit = 0; + + switch (nCorrectLevel) { + case QRErrorCorrectLevel.L: + nLimit = QRCodeLimitLength[i][0]; + break; + case QRErrorCorrectLevel.M: + nLimit = QRCodeLimitLength[i][1]; + break; + case QRErrorCorrectLevel.Q: + nLimit = QRCodeLimitLength[i][2]; + break; + case QRErrorCorrectLevel.H: + nLimit = QRCodeLimitLength[i][3]; + break; + } + + if (length <= nLimit) { + break; + } else { + nType++; + } + } + + if (nType > QRCodeLimitLength.length) { + throw new Error("Too long data"); + } + + return nType; + } + + function _getUTF8Length(sText) { + var replacedText = encodeURI(sText) + .toString() + .replace(/\%[0-9a-fA-F]{2}/g, "a"); + return replacedText.length + (replacedText.length != sText ? 3 : 0); + } + + /** + * @class QRCode + * @constructor + * @example + * new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie"); + * + * @example + * var oQRCode = new QRCode("test", { + * text : "http://naver.com", + * width : 128, + * height : 128 + * }); + * + * oQRCode.clear(); // Clear the QRCode. + * oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode. + * + * @param {HTMLElement} el target element + * @param {Object|String} vOption + * @param {String} vOption.text QRCode link data + * @param {Number} [vOption.width=256] + * @param {Number} [vOption.height=256] + * @param {String} [vOption.colorDark="#000000"] + * @param {String} [vOption.colorLight="#ffffff"] + * @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] + */ + QRCode = function (el, vOption) { + this._htOption = { + width: 256, + height: 256, + typeNumber: 4, + colorDark: "#000000", + colorLight: "#ffffff", + correctLevel: QRErrorCorrectLevel.H, + }; + + if (typeof vOption === "string") { + vOption = { + text: vOption, + }; + } + + // Overwrites options + if (vOption) { + for (var i in vOption) { + this._htOption[i] = vOption[i]; + } + } + + this._el = el; + this._oQRCode = null; + this._oDrawing = new svgDrawer(this._el, this._htOption); + + if (this._htOption.text) { + this.makeCode(this._htOption.text); + } + }; + + /** + * Make the QRCode + * + * @param {String} sText link data + */ + QRCode.prototype.makeCode = function (sText) { + this._oQRCode = new QRCodeModel( + _getTypeNumber(sText, this._htOption.correctLevel), + this._htOption.correctLevel + ); + this._oQRCode.addData(sText); + this._oQRCode.make(); + this._oDrawing.draw(this._oQRCode); + }; + + /** + * Clear the QRCode + */ + QRCode.prototype.clear = function () { + this._oDrawing.clear(); + }; + + /** + * @name QRCode.CorrectLevel + */ + QRCode.CorrectLevel = QRErrorCorrectLevel; +})(); diff --git a/toolkit/modules/RemotePageAccessManager.sys.mjs b/toolkit/modules/RemotePageAccessManager.sys.mjs index a9490967b363dd2eb6f5a777e69a11dcb8ff78a0..ee2b85c0bce05de0002f60b0ff47dbd525ecaee6 100644 --- a/toolkit/modules/RemotePageAccessManager.sys.mjs +++ b/toolkit/modules/RemotePageAccessManager.sys.mjs @@ -71,6 +71,7 @@ export let RemotePageAccessManager = { RPMAddMessageListener: ["WWWReachable"], RPMTryPingSecureWWWLink: ["*"], RPMOpenSecureWWWLink: ["*"], + RPMSendQuery: ["ShouldShowTorConnect"], }, "about:certificate": { RPMSendQuery: ["getCertificates"], @@ -117,36 +118,13 @@ export let RemotePageAccessManager = { RPMGetTRRDomain: ["*"], RPMIsSiteSpecificTRRError: ["*"], RPMSetTRRDisabledLoadFlags: ["*"], - RPMSendQuery: ["Browser:AddTRRExcludedDomain"], + RPMSendQuery: ["Browser:AddTRRExcludedDomain", "ShouldShowTorConnect"], RPMGetIntPref: ["network.trr.mode"], }, "about:newtab": { RPMSendAsyncMessage: ["ActivityStream:ContentToMain"], RPMAddMessageListener: ["ActivityStream:MainToContent"], }, - "about:pocket-saved": { - RPMSendAsyncMessage: ["*"], - RPMAddMessageListener: ["*"], - RPMRemoveMessageListener: ["*"], - RPMGetStringPref: ["extensions.pocket.site"], - }, - "about:pocket-signup": { - RPMSendAsyncMessage: ["*"], - RPMAddMessageListener: ["*"], - RPMRemoveMessageListener: ["*"], - RPMGetStringPref: ["extensions.pocket.site"], - }, - "about:pocket-home": { - RPMSendAsyncMessage: ["*"], - RPMAddMessageListener: ["*"], - RPMRemoveMessageListener: ["*"], - RPMGetStringPref: ["extensions.pocket.site"], - }, - "about:pocket-style-guide": { - RPMSendAsyncMessage: ["*"], - RPMAddMessageListener: ["*"], - RPMRemoveMessageListener: ["*"], - }, "about:privatebrowsing": { RPMSendAsyncMessage: [ "OpenPrivateWindow", @@ -247,26 +225,47 @@ export let RemotePageAccessManager = { ], RPMRecordGleanEvent: ["securityUiProtections"], }, - "about:shoppingsidebar": { - RPMSetPref: [ - "browser.shopping.experience2023.optedIn", - "browser.shopping.experience2023.active", - "browser.shopping.experience2023.ads.userEnabled", - "browser.shopping.experience2023.sidebarClosedCount", - "browser.shopping.experience2023.showKeepSidebarClosedMessage", - "browser.shopping.experience2023.autoOpen.userEnabled", + "about:rulesets": { + RPMAddMessageListener: ["rulesets:channels-change"], + RPMSendAsyncMessage: [ + "rulesets:delete-channel", + "rulesets:enable-channel", + "rulesets:set-show-warning", ], - RPMGetFormatURLPref: ["app.support.baseURL"], - RPMGetIntPref: ["browser.shopping.experience2023.sidebarClosedCount"], - RPMGetBoolPref: [ - "browser.shopping.experience2023.showKeepSidebarClosedMessage", + RPMSendQuery: [ + "rulesets:get-channels", + "rulesets:get-init-args", + "rulesets:set-channel", + "rulesets:update-channel", ], }, + // Removed about:shoppingsidebar. tor-browser#42831. "about:tabcrashed": { RPMSendAsyncMessage: ["Load", "closeTab", "restoreTab", "restoreAll"], RPMAddMessageListener: ["*"], RPMRemoveMessageListener: ["*"], }, + "about:torconnect": { + RPMAddMessageListener: [ + "torconnect:stage-change", + "torconnect:bootstrap-progress", + "torconnect:quickstart-change", + ], + RPMSendAsyncMessage: [ + "torconnect:open-tor-preferences", + "torconnect:begin-bootstrapping", + "torconnect:cancel-bootstrapping", + "torconnect:set-quickstart", + "torconnect:view-tor-logs", + "torconnect:restart", + "torconnect:start-again", + "torconnect:choose-region", + ], + RPMSendQuery: [ + "torconnect:get-init-args", + "torconnect:get-country-codes", + ], + }, "about:welcome": { RPMSendAsyncMessage: ["ActivityStream:ContentToMain"], RPMAddMessageListener: ["ActivityStream:MainToContent"], diff --git a/toolkit/modules/TorAndroidIntegration.sys.mjs b/toolkit/modules/TorAndroidIntegration.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..e3dcfc86dbf6deb49e9239de425bb69718b9408b --- /dev/null +++ b/toolkit/modules/TorAndroidIntegration.sys.mjs @@ -0,0 +1,223 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", + TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs", + TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", +}); + +const Prefs = Object.freeze({ + logLevel: "browser.tor_android.log_level", +}); + +const logger = console.createInstance({ + maxLogLevelPref: Prefs.logLevel, + prefix: "TorAndroidIntegration", +}); + +const EmittedEvents = Object.freeze({ + settingsReady: "GeckoView:Tor:SettingsReady", + settingsChanged: "GeckoView:Tor:SettingsChanged", + connectStateChanged: "GeckoView:Tor:ConnectStateChanged", + connectError: "GeckoView:Tor:ConnectError", + bootstrapProgress: "GeckoView:Tor:BootstrapProgress", + bootstrapComplete: "GeckoView:Tor:BootstrapComplete", + torLogs: "GeckoView:Tor:Logs", +}); + +const ListenedEvents = Object.freeze({ + settingsGet: "GeckoView:Tor:SettingsGet", + // The data is passed directly to TorSettings. + settingsSet: "GeckoView:Tor:SettingsSet", + bootstrapBegin: "GeckoView:Tor:BootstrapBegin", + // Optionally takes a countryCode, as data.countryCode. + bootstrapBeginAuto: "GeckoView:Tor:BootstrapBeginAuto", + bootstrapCancel: "GeckoView:Tor:BootstrapCancel", + bootstrapGetState: "GeckoView:Tor:BootstrapGetState", +}); + +class TorAndroidIntegrationImpl { + #initialized = false; + + async init() { + if (this.#initialized) { + logger.warn("Something tried to initilize us again."); + return; + } + this.#initialized = true; + + lazy.EventDispatcher.instance.registerListener( + this, + Object.values(ListenedEvents) + ); + + Services.obs.addObserver(this, lazy.TorProviderTopics.TorLog); + + for (const topic in lazy.TorConnectTopics) { + Services.obs.addObserver(this, lazy.TorConnectTopics[topic]); + } + + for (const topic in lazy.TorSettingsTopics) { + Services.obs.addObserver(this, lazy.TorSettingsTopics[topic]); + } + + lazy.TorProviderBuilder.init(); + // On Android immediately call firstWindowLoaded. This should be safe to + // call since it will await the initialisation of the TorProvider set up + // by TorProviderBuilder.init. + lazy.TorProviderBuilder.firstWindowLoaded(); + + try { + await lazy.TorSettings.init(); + await lazy.TorConnect.init(); + } catch (e) { + logger.error("Cannot initialize TorSettings or TorConnect", e); + } + } + + /** + * Combine the current TorSettings settings with the TorConnect settings. + * + * @returns {object} The TorSettings in an object, which also has a + * `quickstart.enabled` property. + */ + // This is added for backward compatibility with TorSettings.getSettings prior + // to tor-browser#41921, when it used to control the quickstart setting. + // TODO: Have android separate out the request for TorConnect.quickstart. In + // principle, this would allow android tor connect UI to be loaded before + // TorSettings has initialized (the SettingsReady signal), similar to desktop. + // See tor-browser#43408. + #getAllSettings() { + const settings = lazy.TorSettings.getSettings(); + settings.quickstart = { enabled: lazy.TorConnect.quickstart }; + return settings; + } + + observe(subj, topic) { + switch (topic) { + // TODO: Replace with StageChange. + case lazy.TorConnectTopics.StateChange: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.connectStateChanged, + state: subj.wrappedJSObject.state ?? "", + }); + break; + case lazy.TorConnectTopics.BootstrapProgress: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.bootstrapProgress, + progress: subj.wrappedJSObject.progress ?? 0, + hasWarnings: subj.wrappedJSObject.hasWarnings ?? false, + }); + break; + case lazy.TorConnectTopics.BootstrapComplete: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.bootstrapComplete, + }); + break; + // TODO: Replace with StageChange stage.error. + case lazy.TorConnectTopics.Error: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.connectError, + code: subj.wrappedJSObject.code ?? "", + message: subj.wrappedJSObject.message ?? "", + phase: subj.wrappedJSObject.cause?.phase ?? "", + reason: subj.wrappedJSObject.cause?.reason ?? "", + }); + break; + case lazy.TorProviderTopics.TorLog: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.torLogs, + logType: subj.wrappedJSObject.type ?? "", + message: subj.wrappedJSObject.msg ?? "", + timestamp: subj.wrappedJSObject.timestamp ?? "", + }); + break; + case lazy.TorSettingsTopics.Ready: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.settingsReady, + settings: this.#getAllSettings(), + }); + break; + case lazy.TorSettingsTopics.SettingsChanged: + // For Android we push also the settings object to avoid a round trip on + // the event dispatcher. + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.settingsChanged, + changes: subj.wrappedJSObject.changes ?? [], + settings: this.#getAllSettings(), + }); + break; + case lazy.TorConnectTopics.QuickstartChange: + // We also include the TorSettings, and a `changes` Array similar to + // SettingsChanged signal. This is for backward compatibility with + // TorSettings.getSettings prior to tor-browser#41921, when it used to + // control the quickstart setting. + // TODO: Have android separate out the request for TorConnect.quickstart. + // See tor-browser#43408. + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.settingsChanged, + changes: ["quickstart.enabled"], + settings: this.#getAllSettings(), + }); + break; + } + } + + async onEvent(event, data, callback) { + logger.debug(`Received event ${event}`, data); + try { + switch (event) { + case ListenedEvents.settingsGet: + callback?.onSuccess(this.#getAllSettings()); + return; + case ListenedEvents.settingsSet: + // TODO: Set quickstart via a separate event. See tor-browser#43408. + // NOTE: Currently this may trigger GeckoView:Tor:SettingsChanged + // twice: once for quickstart.enabled, and again for the other + // settings. + if ( + "quickstart" in data.settings && + "enabled" in data.settings.quickstart + ) { + lazy.TorConnect.quickstart = data.settings.quickstart.enabled; + } + // TODO: Handle setting throw? This can throw if data.settings is + // incorrectly formatted, but more like it can throw when the settings + // fail to be passed onto the TorProvider. tor-browser#43405. + await lazy.TorSettings.changeSettings(data.settings); + break; + case ListenedEvents.bootstrapBegin: + lazy.TorConnect.beginBootstrapping(); + break; + case ListenedEvents.bootstrapBeginAuto: + // TODO: The countryCode should be set to "automatic" by the caller + // rather than `null`, so we can just pass in `data.countryCode` + // directly. + lazy.TorConnect.beginBootstrapping(data.countryCode || "automatic"); + break; + case ListenedEvents.bootstrapCancel: + lazy.TorConnect.cancelBootstrapping(); + break; + // TODO: Replace with TorConnect.stage. + case ListenedEvents.bootstrapGetState: + callback?.onSuccess(lazy.TorConnect.state); + return; + // TODO: Expose TorConnect.startAgain() to allow users to begin + // from the start again. + } + callback?.onSuccess(); + } catch (e) { + logger.error(`Error while handling event ${event}`, e); + callback?.onError(e); + } + } +} + +export const TorAndroidIntegration = new TorAndroidIntegrationImpl(); diff --git a/toolkit/modules/TorConnect.sys.mjs b/toolkit/modules/TorConnect.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..a3a8bec5e4bb058774f6a53c5aaed48e365eecc0 --- /dev/null +++ b/toolkit/modules/TorConnect.sys.mjs @@ -0,0 +1,1804 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", + MoatRPC: "resource://gre/modules/Moat.sys.mjs", + TorBootstrapRequest: "resource://gre/modules/TorBootstrapRequest.sys.mjs", + TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + TorSettings: "resource://gre/modules/TorSettings.sys.mjs", + TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs", +}); + +const TorConnectPrefs = Object.freeze({ + censorship_level: "torbrowser.debug.censorship_level", + allow_internet_test: "torbrowser.bootstrap.allow_internet_test", + log_level: "torbrowser.bootstrap.log_level", + /* prompt_at_startup now controls whether the quickstart can trigger. */ + prompt_at_startup: "extensions.torlauncher.prompt_at_startup", + quickstart: "torbrowser.settings.quickstart.enabled", +}); + +export const TorConnectState = Object.freeze({ + /* Our initial state */ + Initial: "Initial", + /* In-between initial boot and bootstrapping, users can change tor network settings during this state */ + Configuring: "Configuring", + /* Tor is attempting to bootstrap with settings from censorship-circumvention db */ + AutoBootstrapping: "AutoBootstrapping", + /* Tor is bootstrapping */ + Bootstrapping: "Bootstrapping", + /* Passthrough state back to Configuring */ + Error: "Error", + /* Final state, after successful bootstrap */ + Bootstrapped: "Bootstrapped", + /* If we are using System tor or the legacy Tor-Launcher */ + Disabled: "Disabled", +}); + +export class TorConnectError extends Error { + static get Offline() { + return "Offline"; + } + static get BootstrapError() { + return "BootstrapError"; + } + static get CannotDetermineCountry() { + return "CannotDetermineCountry"; + } + static get NoSettingsForCountry() { + return "NoSettingsForCountry"; + } + static get AllSettingsFailed() { + return "AllSettingsFailed"; + } + static get ExternalError() { + return "ExternalError"; + } + + constructor(code, cause) { + super(cause?.message ?? `TorConnectError: ${code}`, cause ? { cause } : {}); + this.name = "TorConnectError"; + this.code = code; + } +} + +ChromeUtils.defineLazyGetter(lazy, "logger", () => + console.createInstance({ + maxLogLevelPref: TorConnectPrefs.log_level, + prefix: "TorConnect", + }) +); + +/* Topics Notified by the TorConnect module */ +export const TorConnectTopics = Object.freeze({ + StageChange: "torconnect:stage-change", + // TODO: Remove torconnect:state-change when pages have switched to stage. + StateChange: "torconnect:state-change", + QuickstartChange: "torconnect:quickstart-change", + BootstrapProgress: "torconnect:bootstrap-progress", + BootstrapComplete: "torconnect:bootstrap-complete", + // TODO: Remove torconnect:error when pages have switched to stage. + Error: "torconnect:error", +}); + +/** + * @callback ProgressCallback + * + * @param {integer} progress - The progress percent. + */ +/** + * @typedef {object} BootstrapOptions + * + * Options for a bootstrap attempt. + * + * @property {boolean} [options.simulateCensorship] - Whether to simulate a + * failing bootstrap. + * @property {integer} [options.simulateDelay] - The delay in microseconds to + * apply to simulated bootstraps. + * @property {MoatSettings} [options.simulateMoatResponse] - Simulate a Moat + * response for circumvention settings. Should include a "bridgesList" + * property, and optionally a "country" property. The "bridgesList" property + * should be an Array of MoatBridges objects that match the bridge settings + * accepted by TorSettings.bridges, plus you may add a "simulateCensorship" + * property to make only their bootstrap attempts fail. + * @property {boolean} [options.testInternet] - Whether to also test the + * internet connection. + * @property {boolean} [options.simulateOffline] - Whether to simulate an + * offline test result. This will not cause the bootstrap to fail. + * @property {string} [options.regionCode] - The region code to use to fetch + * auto-bootstrap settings, or "automatic" to automatically choose the region. + */ +/** + * @typedef {object} BootstrapResult + * + * The result of a bootstrap attempt. + * + * @property {string} [result] - The bootstrap result. + * @property {Error} [error] - An error from the attempt. + */ +/** + * @callback ResolveBootstrap + * + * Resolve a bootstrap attempt. + * + * @param {BootstrapResult} - The result, or error. + */ + +/** + * Each instance can be used to attempt one bootstrapping. + */ +class BootstrapAttempt { + /** + * The ongoing bootstrap request. + * + * @type {?TorBootstrapRequest} + */ + #bootstrap = null; + /** + * The error returned by the bootstrap request, if any. + * + * @type {?Error} + */ + #bootstrapError = null; + /** + * The ongoing internet test, if any. + * + * @type {?InternetTest} + */ + #internetTest = null; + /** + * The method to call to complete the `run` promise. + * + * @type {?ResolveBootstrap} + */ + #resolveRun = null; + /** + * Whether the `run` promise has been, or is about to be, resolved. + * + * @type {boolean} + */ + #resolved = false; + /** + * Whether a cancel request has been started. + * + * @type {boolean} + */ + #cancelled = false; + + /** + * Run a bootstrap attempt. + * + * @param {ProgressCallback} progressCallback - The callback to invoke with + * the bootstrap progress. + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + * + * @return {Promise<string, Error>} - The result of the bootstrap. + */ + run(progressCallback, options) { + const { promise, resolve, reject } = Promise.withResolvers(); + this.#resolveRun = arg => { + if (this.#resolved) { + // Already been called once. + if (arg.error) { + lazy.logger.error("Delayed bootstrap error", arg.error); + } + return; + } + this.#resolved = true; + try { + // Should be ok to call this twice in the case where we "cancel" the + // bootstrap. + this.#internetTest?.cancel(); + } catch (error) { + lazy.logger.error("Unexpected error in bootstrap cleanup", error); + } + if (arg.error) { + reject(arg.error); + } else { + resolve(arg.result); + } + }; + try { + this.#runInternal(progressCallback, options); + } catch (error) { + this.#resolveRun({ error }); + } + + return promise; + } + + /** + * Method to call just after the Bootstrapped stage is set in response to this + * bootstrap attempt. + */ + postBootstrapped() { + // Nothing to do. + } + + /** + * Run the attempt. + * + * @param {ProgressCallback} progressCallback - The callback to invoke with + * the bootstrap progress. + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + */ + #runInternal(progressCallback, options) { + if (options.simulateCensorship) { + // Create a fake request. + this.#bootstrap = { + _timeout: 0, + bootstrap() { + this._timeout = setTimeout(() => { + const err = new Error("Censorship simulation"); + err.phase = "conn"; + err.reason = "noroute"; + this.onbootstraperror(err); + }, options.simulateDelay || 0); + }, + cancel() { + clearTimeout(this._timeout); + }, + }; + } else { + this.#bootstrap = new lazy.TorBootstrapRequest(); + } + + this.#bootstrap.onbootstrapstatus = (progress, _status) => { + if (!this.#resolved) { + progressCallback(progress); + } + }; + this.#bootstrap.onbootstrapcomplete = () => { + this.#resolveRun({ result: "complete" }); + }; + this.#bootstrap.onbootstraperror = error => { + if (this.#bootstrapError) { + lazy.logger.warn("Another bootstrap error", error); + return; + } + // We have to wait for the Internet test to finish before sending the + // bootstrap error + this.#bootstrapError = error; + this.#maybeTransitionToError(); + }; + if (options.testInternet) { + this.#internetTest = new InternetTest(options.simulateOffline); + this.#internetTest.onResult = () => { + this.#maybeTransitionToError(); + }; + this.#internetTest.onError = () => { + this.#maybeTransitionToError(); + }; + } + + this.#bootstrap.bootstrap(); + } + + /** + * Callback for when we get a new bootstrap error or a change in the internet + * status. + */ + #maybeTransitionToError() { + if (this.#resolved || this.#cancelled) { + if (this.#bootstrapError) { + // We ignore this error since it occurred after cancelling (by the + // user), or we have already resolved. We assume the error is just a + // side effect of the cancelling. + // E.g. If the cancelling is triggered late in the process, we get + // "Building circuits: Establishing a Tor circuit failed". + // TODO: Maybe move this logic deeper in the process to know when to + // filter out such errors triggered by cancelling. + lazy.logger.warn("Post-complete error.", this.#bootstrapError); + } + return; + } + + if ( + this.#internetTest && + this.#internetTest.status === InternetStatus.Unknown && + this.#internetTest.error === null && + this.#internetTest.enabled + ) { + // We have been called by a failed bootstrap, but the internet test has + // not run yet - force it to run immediately! + this.#internetTest.test(); + // Return from this call, because the Internet test's callback will call + // us again. + return; + } + // Do not transition to "offline" until we are sure that also the bootstrap + // failed, in case Moat is down but the bootstrap can proceed anyway. + if (!this.#bootstrapError) { + return; + } + if (this.#internetTest?.status === InternetStatus.Offline) { + if (this.#bootstrapError) { + lazy.logger.info( + "Ignoring bootstrap error since offline.", + this.#bootstrapError + ); + } + this.#resolveRun({ result: "offline" }); + return; + } + this.#resolveRun({ + error: new TorConnectError( + TorConnectError.BootstrapError, + this.#bootstrapError + ), + }); + } + + /** + * Cancel the bootstrap attempt. + */ + async cancel() { + if (this.#cancelled) { + lazy.logger.warn( + "Cancelled bootstrap after it has already been cancelled" + ); + return; + } + this.#cancelled = true; + if (this.#resolved) { + lazy.logger.warn("Cancelled bootstrap after it has already resolved"); + return; + } + // Wait until after bootstrap.cancel returns before we resolve with + // cancelled. In particular, there is a small chance that the bootstrap + // completes, in which case we want to be able to resolve with a success + // instead. + this.#internetTest?.cancel(); + await this.#bootstrap?.cancel(); + this.#resolveRun({ result: "cancelled" }); + } +} + +/** + * Each instance can be used to attempt one auto-bootstrapping sequence. + */ +class AutoBootstrapAttempt { + /** + * The current bootstrap attempt, if any. + * + * @type {?BootstrapAttempt} + */ + #bootstrapAttempt = null; + /** + * The method to call to complete the `run` promise. + * + * @type {?ResolveBootstrap} + */ + #resolveRun = null; + /** + * Whether the `run` promise has been, or is about to be, resolved. + * + * @type {boolean} + */ + #resolved = false; + /** + * Whether a cancel request has been started. + * + * @type {boolean} + */ + #cancelled = false; + /** + * The method to call when the cancelled value is set to true. + * + * @type {?Function} + */ + #resolveCancelled = null; + /** + * A promise that resolves when the cancelled value is set to true. We can use + * this with Promise.race to end early when the user cancels. + * + * @type {?Promise} + */ + #cancelledPromise = null; + /** + * The list of bridge configurations from Moat. + * + * @type {?MoatBridges[]} + */ + #bridgesList = null; + /** + * The detected region code returned by Moat, if any. + * + * @type {?string} + */ + detectedRegion = null; + + /** + * Run an auto-bootstrap attempt. + * + * @param {ProgressCallback} progressCallback - The callback to invoke with + * the bootstrap progress. + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + * + * @return {Promise<string, Error>} - The result of the bootstrap. + */ + run(progressCallback, options) { + const { promise, resolve, reject } = Promise.withResolvers(); + + this.#resolveRun = async arg => { + if (this.#resolved) { + // Already been called once. + if (arg.error) { + lazy.logger.error("Delayed auto-bootstrap error", arg.error); + } + return; + } + this.#resolved = true; + + if (lazy.TorSettings.initialized) { + // If not initialized, then we won't have applied any settings. + try { + // Run cleanup before we resolve the promise to ensure two instances + // of AutoBootstrapAttempt are not trying to change the settings at + // the same time. + if (arg.result !== "complete") { + // Should do nothing if we never called applyTemporaryBridges. + await lazy.TorSettings.clearTemporaryBridges(); + } + } catch (error) { + lazy.logger.error( + "Unexpected error in auto-bootstrap cleanup", + error + ); + } + } + if (arg.error) { + reject(arg.error); + } else { + resolve(arg.result); + } + }; + + ({ promise: this.#cancelledPromise, resolve: this.#resolveCancelled } = + Promise.withResolvers()); + + this.#runInternal(progressCallback, options).catch(error => { + this.#resolveRun({ error }); + }); + + return promise; + } + + /** + * Method to call just after the Bootstrapped stage is set in response to this + * bootstrap attempt. + */ + postBootstrapped() { + // Persist the current settings to preferences. + lazy.TorSettings.saveTemporaryBridges(); + } + + /** + * Run the attempt. + * + * Note, this is an async method, but should *not* be awaited by the `run` + * method. + * + * @param {ProgressCallback} progressCallback - The callback to invoke with + * the bootstrap progress. + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + */ + async #runInternal(progressCallback, options) { + // Wait for TorSettings to be initialised, which is used for the + // AutoBootstrapping set up. + await Promise.race([ + lazy.TorSettings.initializedPromise, + this.#cancelledPromise, + ]); + if (this.#cancelled || this.#resolved) { + return; + } + + await this.#fetchBridges(options); + if (this.#cancelled || this.#resolved) { + return; + } + + if (!this.#bridgesList?.length) { + this.#resolveRun({ + error: new TorConnectError( + options.regionCode === "automatic" && !this.detectedRegion + ? TorConnectError.CannotDetermineCountry + : TorConnectError.NoSettingsForCountry + ), + }); + } + + // Apply each of our settings and try to bootstrap with each. + for (const [index, bridges] of this.#bridgesList.entries()) { + lazy.logger.info( + `Attempting Bootstrap with configuration ${index + 1}/${ + this.#bridgesList.length + }` + ); + + await this.#tryBridges(bridges, progressCallback, options); + + if (this.#cancelled || this.#resolved) { + return; + } + } + + this.#resolveRun({ + error: new TorConnectError(TorConnectError.AllSettingsFailed), + }); + } + + /** + * Lookup user's potential censorship circumvention settings from Moat + * service. + * + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + */ + async #fetchBridges(options) { + if (options.simulateMoatResponse) { + await Promise.race([ + new Promise(res => setTimeout(res, options.simulateDelay || 0)), + this.#cancelledPromise, + ]); + + if (this.#cancelled || this.#resolved) { + return; + } + + this.detectedRegion = options.simulateMoatResponse.country || null; + this.#bridgesList = options.simulateMoatResponse.bridgesList ?? null; + + return; + } + + const moat = new lazy.MoatRPC(); + try { + // We need to wait Moat's initialization even when we are requested to + // transition to another state to be sure its uninit will have its + // intended effect. So, do not use Promise.race here. + await moat.init(); + + if (this.#cancelled || this.#resolved) { + return; + } + + let moatAbortController = new AbortController(); + // For now, throw any errors we receive from the backend, except when it + // was unable to detect user's country/region. + // If we use specialized error objects, we could pass the original errors + // to them. + const maybeSettings = await Promise.race([ + moat.circumvention_settings( + [...lazy.TorSettings.builtinBridgeTypes, "vanilla"], + options.regionCode === "automatic" ? null : options.regionCode, + moatAbortController.signal + ), + // This might set maybeSettings to undefined. + this.#cancelledPromise, + ]); + if (this.#cancelled) { + // Ended early due to being cancelled. Abort the ongoing Moat request so + // that it does not continue unnecessarily in the background. + // NOTE: We do not care about circumvention_settings return value or + // errors at this point. Nor do we need to await its return. We just + // want it to resolve quickly. + moatAbortController.abort(); + } + if (this.#cancelled || this.#resolved) { + return; + } + + this.detectedRegion = maybeSettings?.country || null; + + if (maybeSettings?.bridgesList?.length) { + this.#bridgesList = maybeSettings.bridgesList; + } else { + // In principle we could reuse the existing moatAbortController + // instance, since its abort method has not been called. But it is + // cleaner to use a new instance to avoid triggering any potential + // lingering callbacks attached to the AbortSignal. + moatAbortController = new AbortController(); + // Keep consistency with the other call. + this.#bridgesList = await Promise.race([ + moat.circumvention_defaults( + [...lazy.TorSettings.builtinBridgeTypes, "vanilla"], + moatAbortController.signal + ), + // This might set this.#bridgesList to undefined. + this.#cancelledPromise, + ]); + if (this.#cancelled) { + // Ended early due to being cancelled. Abort the ongoing Moat request + // so that it does not continue in the background. + moatAbortController.abort(); + } + } + } finally { + // Do not await the uninit. + moat.uninit(); + } + } + + /** + * Try to apply the settings we fetched. + * + * @param {MoatBridges} bridges - The bridges to try. + * @param {ProgressCallback} progressCallback - The callback to invoke with + * the bootstrap progress. + * @param {BootstrapOptions} options - Options to apply to the bootstrap. + */ + async #tryBridges(bridges, progressCallback, options) { + if (this.#cancelled || this.#resolved) { + return; + } + + if (options.simulateMoatResponse && bridges.simulateCensorship) { + // Move the simulateCensorship option to the options for the next + // BootstrapAttempt. + bridges = structuredClone(bridges); + delete bridges.simulateCensorship; + options = { ...options, simulateCensorship: true }; + } + + // Send the new settings directly to the provider. We will save them only + // if the bootstrap succeeds. + await lazy.TorSettings.applyTemporaryBridges(bridges); + + if (this.#cancelled || this.#resolved) { + return; + } + + let result; + try { + this.#bootstrapAttempt = new BootstrapAttempt(); + // At this stage, cancelling AutoBootstrap will also cancel this + // bootstrapAttempt. + result = await this.#bootstrapAttempt.run(progressCallback, options); + } catch (error) { + // Only re-try with the next settings *if* we have a BootstrapError. + // Other errors will end this auto-bootstrap attempt entirely. + if ( + error instanceof TorConnectError && + error.code === TorConnectError.BootstrapError + ) { + lazy.logger.info("TorConnect setting failed", bridges, error); + // Try with the next settings. + // NOTE: We do not restore the user settings in between these runs. + // Instead we wait for #resolveRun callback to do so. + // This means there is a window of time where the setting is applied, but + // no bootstrap is running. + return; + } + // Pass error up. + throw error; + } finally { + this.#bootstrapAttempt = null; + } + + if (this.#cancelled || this.#resolved) { + return; + } + + // Pass the BootstrapAttempt result up. + this.#resolveRun({ result }); + } + + /** + * Cancel the bootstrap attempt. + */ + async cancel() { + if (this.#cancelled) { + lazy.logger.warn( + "Cancelled auto-bootstrap after it has already been cancelled" + ); + return; + } + this.#cancelled = true; + this.#resolveCancelled(); + if (this.#resolved) { + lazy.logger.warn( + "Cancelled auto-bootstrap after it has already resolved" + ); + return; + } + + // Wait until after bootstrap.cancel returns before we resolve with + // cancelled. In particular, there is a small chance that the bootstrap + // completes, in which case we want to be able to resolve with a success + // instead. + if (this.#bootstrapAttempt) { + this.#bootstrapAttempt.cancel(); + await this.#bootstrapAttempt; + } + // In case no bootstrap is running, we resolve with "cancelled". + this.#resolveRun({ result: "cancelled" }); + } +} + +export const InternetStatus = Object.freeze({ + Unknown: -1, + Offline: 0, + Online: 1, +}); + +class InternetTest { + #enabled; + #status = InternetStatus.Unknown; + #error = null; + #pending = false; + #canceled = false; + #timeout = 0; + #simulateOffline = false; + + constructor(simulateOffline) { + this.#simulateOffline = simulateOffline; + + this.#enabled = Services.prefs.getBoolPref( + TorConnectPrefs.allow_internet_test, + true + ); + if (this.#enabled) { + this.#timeout = setTimeout(() => { + this.#timeout = 0; + this.test(); + }, this.#timeoutRand()); + } + this.onResult = _online => {}; + this.onError = _error => {}; + } + + /** + * Perform the internet test. + * + * While this is an async method, the callers are not expected to await it, + * as we are also using callbacks. + */ + async test() { + if (this.#pending || !this.#enabled) { + return; + } + this.cancel(); + this.#pending = true; + this.#canceled = false; + + lazy.logger.info("Starting the Internet test"); + + if (this.#simulateOffline) { + await new Promise(res => setTimeout(res, 500)); + + this.#status = InternetStatus.Offline; + + if (this.#canceled) { + return; + } + this.onResult(this.#status); + return; + } + + const mrpc = new lazy.MoatRPC(); + try { + await mrpc.init(); + const status = await mrpc.testInternetConnection(); + this.#status = status.successful + ? InternetStatus.Online + : InternetStatus.Offline; + // TODO: We could consume the date we got from the HTTP request to detect + // big clock skews that might prevent a successfull bootstrap. + lazy.logger.info(`Performed Internet test, outcome ${this.#status}`); + } catch (err) { + lazy.logger.error("Error while checking the Internet connection", err); + this.#error = err; + this.#pending = false; + } finally { + mrpc.uninit(); + } + + if (this.#canceled) { + return; + } + if (this.#error) { + this.onError(this.#error); + } else { + this.onResult(this.#status); + } + } + + cancel() { + this.#canceled = true; + if (this.#timeout) { + clearTimeout(this.#timeout); + this.#timeout = 0; + } + } + + get status() { + return this.#status; + } + + get error() { + return this.#error; + } + + get enabled() { + return this.#enabled; + } + + // We randomize the Internet test timeout to make fingerprinting it harder, at + // least a little bit... + #timeoutRand() { + const offset = 30000; + const randRange = 5000; + return offset + randRange * (Math.random() * 2 - 1); + } +} + +export const TorConnectStage = Object.freeze({ + Disabled: "Disabled", + Loading: "Loading", + Start: "Start", + Bootstrapping: "Bootstrapping", + Offline: "Offline", + ChooseRegion: "ChooseRegion", + RegionNotFound: "RegionNotFound", + ConfirmRegion: "ConfirmRegion", + FinalError: "FinalError", + Bootstrapped: "Bootstrapped", +}); + +/** + * @typedef {object} ConnectStage + * + * A summary of the user stage. + * + * @property {string} name - The name of the stage. + * @property {string} defaultRegion - The default region to show in the UI. + * @property {?string} bootstrapTrigger - The TorConnectStage prior to this + * bootstrap attempt. Only set during the "Bootstrapping" stage. + * @property {?BootstrapError} error - The last bootstrapping error. + * @property {boolean} tryAgain - Whether a bootstrap attempt has failed, so + * that a normal bootstrap should be shown as "Try Again" instead of + * "Connect". NOTE: to be removed when about:torconnect no longer uses + * breadcrumbs. + * @property {boolean} potentiallyBlocked - Whether bootstrapping has ever + * failed, not including being cancelled or being offline. I.e. whether we + * have reached an error stage at some point before being bootstrapped. + * @property {BootstrappingStatus} bootstrappingStatus - The current + * bootstrapping status. + */ + +/** + * @typedef {object} BootstrappingStatus + * + * The status of a bootstrap. + * + * @property {number} progress - The percent progress. + * @property {boolean} hasWarning - Whether this bootstrap has a warning in the + * Tor log. + */ + +/** + * @typedef {object} BootstrapError + * + * Details about the error that caused bootstrapping to fail. + * + * @property {string} code - The error code type. + * @property {string} message - The error message. + * @property {?string} phase - The bootstrapping phase that failed. + * @property {?string} reason - The bootstrapping failure reason. + */ + +export const TorConnect = { + /** + * Default bootstrap options for simulation. + * + * @type {BootstrapOptions} + */ + simulateBootstrapOptions: {}, + + /** + * The name of the current stage the user is in. + * + * @type {string} + */ + _stageName: TorConnectStage.Loading, + + get stageName() { + return this._stageName; + }, + + /** + * The stage that triggered bootstrapping. + * + * @type {?string} + */ + _bootstrapTrigger: null, + + /** + * The alternative stage that we should move to after bootstrapping completes. + * + * @type {?string} + */ + _requestedStage: null, + + /** + * The default region to show in the UI for auto-bootstrapping. + * + * @type {string} + */ + _defaultRegion: "automatic", + + /** + * The current bootstrap attempt, if any. + * + * @type {?(BootstrapAttempt|AutoBootstrapAttempt)} + */ + _bootstrapAttempt: null, + + /** + * The bootstrap error that was last generated. + * + * @type {?TorConnectError} + */ + _errorDetails: null, + + /** + * Whether a bootstrap attempt has failed, so that a normal bootstrap should + * be shown as "Try Again" instead of "Connect". + * + * @type {boolean} + */ + // TODO: Drop tryAgain when we remove breadcrumbs and use "Start again" + // instead. + _tryAgain: false, + + /** + * Whether bootstrapping has ever returned an error. + * + * @type {boolean} + */ + _potentiallyBlocked: false, + + /** + * Get a summary of the current user stage. + * + * @type {ConnectStage} + */ + get stage() { + return { + name: this._stageName, + defaultRegion: this._defaultRegion, + bootstrapTrigger: this._bootstrapTrigger, + error: this._errorDetails + ? { + code: this._errorDetails.code, + message: String(this._errorDetails.message ?? ""), + phase: this._errorDetails.cause?.phase ?? null, + reason: this._errorDetails.cause?.reason ?? null, + } + : null, + tryAgain: this._tryAgain, + potentiallyBlocked: this._potentiallyBlocked, + bootstrappingStatus: structuredClone(this._bootstrappingStatus), + }; + }, + + // list of country codes Moat has settings for + _countryCodes: [], + _countryNames: Object.freeze( + (() => { + const codes = Services.intl.getAvailableLocaleDisplayNames("region"); + const names = Services.intl.getRegionDisplayNames(undefined, codes); + let codesNames = {}; + for (let i = 0; i < codes.length; i++) { + codesNames[codes[i]] = names[i]; + } + return codesNames; + })() + ), + + // This is used as a helper to make the state of about:torconnect persistent + // during a session, but TorConnect does not use this data at all. + _uiState: {}, + + /** + * The status of the most recent bootstrap attempt. + * + * @type {BootstrappingStatus} + */ + _bootstrappingStatus: { + progress: 0, + hasWarning: false, + }, + + /** + * Notify the bootstrap progress. + */ + _notifyBootstrapProgress() { + lazy.logger.debug("BootstrappingStatus", this._bootstrappingStatus); + Services.obs.notifyObservers( + this._bootstrappingStatus, + TorConnectTopics.BootstrapProgress + ); + }, + + // init should be called by TorStartupService + init() { + lazy.logger.debug("TorConnect.init()"); + + if (!this.enabled) { + // Disabled + this._setStage(TorConnectStage.Disabled); + return; + } + + let observeTopic = addTopic => { + Services.obs.addObserver(this, addTopic); + lazy.logger.debug(`Observing topic '${addTopic}'`); + }; + + // register the Tor topics we always care about + observeTopic(lazy.TorProviderTopics.ProcessExited); + observeTopic(lazy.TorProviderTopics.HasWarnOrErr); + observeTopic(lazy.TorSettingsTopics.SettingsChanged); + + // NOTE: At this point, _requestedStage should still be `null`. + this._setStage(TorConnectStage.Start); + if ( + // Quickstart setting is enabled. + this.quickstart && + // And the previous bootstrap attempt must have succeeded. + !Services.prefs.getBoolPref(TorConnectPrefs.prompt_at_startup, true) + ) { + this.beginBootstrapping(); + } + }, + + async observe(subject, topic) { + lazy.logger.debug(`Observed ${topic}`); + + switch (topic) { + case lazy.TorProviderTopics.HasWarnOrErr: + if (this._bootstrappingStatus.hasWarning) { + // No change. + return; + } + if (this._stageName === "Bootstrapping") { + this._bootstrappingStatus.hasWarning = true; + this._notifyBootstrapProgress(); + } + break; + case lazy.TorProviderTopics.ProcessExited: + lazy.logger.info("Starting again since the tor process exited"); + // Treat a failure as a possibly broken configuration. + // So, prevent quickstart at the next start. + Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true); + this._makeStageRequest(TorConnectStage.Start, true); + break; + case lazy.TorSettingsTopics.SettingsChanged: + if ( + this._stageName !== TorConnectStage.Bootstrapped && + this._stageName !== TorConnectStage.Loading && + this._stageName !== TorConnectStage.Start && + subject.wrappedJSObject.changes.some(propertyName => + propertyName.startsWith("bridges.") + ) + ) { + // A change in bridge settings before we are bootstrapped, we reset + // the stage to Start to: + // + Cancel any ongoing bootstrap attempt. In particular, we + // definitely do not want to continue with an auto-bootstrap's + // temporary bridges if the settings have changed. + // + Reset the UI to be ready for normal bootstrapping in case the + // user returns to about:torconnect. + // See tor-browser#41921. + // NOTE: We do not reset in response to a change in the quickstart, + // firewall or proxy settings. + lazy.logger.warn( + "Resetting to Start stage since bridge settings changed" + ); + // Rather than cancel and return to the pre-bootstrap stage, we + // explicitly cancel and return to the start stage. + this._makeStageRequest(TorConnectStage.Start); + } + break; + } + }, + + /** + * Set the user stage. + * + * @param {string} name - The name of the stage to move to. + */ + _setStage(name) { + if (this._bootstrapAttempt) { + throw new Error(`Trying to set the stage to ${name} during a bootstrap`); + } + + lazy.logger.info(`Entering stage ${name}`); + const prevState = this.state; + this._stageName = name; + this._bootstrappingStatus.hasWarning = false; + this._bootstrappingStatus.progress = + name === TorConnectStage.Bootstrapped ? 100 : 0; + + Services.obs.notifyObservers(this.stage, TorConnectTopics.StageChange); + + // TODO: Remove when all pages have switched to stage. + const newState = this.state; + if (prevState !== newState) { + Services.obs.notifyObservers( + { state: newState }, + TorConnectTopics.StateChange + ); + } + + // Update the progress after the stage has changed. + this._notifyBootstrapProgress(); + }, + + /* + Various getters + */ + + /** + * Whether TorConnect is enabled. + * + * @type {boolean} + */ + get enabled() { + // FIXME: This is called before the TorProvider is ready. + // As a matter of fact, at the moment it is equivalent to the following + // line, but this might become a problem in the future. + return lazy.TorLauncherUtil.shouldStartAndOwnTor; + }, + + /** + * Whether bootstrapping can begin immediately once Tor Browser has been + * opened. + * + * @type {boolean} + */ + get quickstart() { + return Services.prefs.getBoolPref(TorConnectPrefs.quickstart, false); + }, + + set quickstart(enabled) { + enabled = Boolean(enabled); + if (enabled === this.quickstart) { + return; + } + Services.prefs.setBoolPref(TorConnectPrefs.quickstart, enabled); + Services.obs.notifyObservers(null, TorConnectTopics.QuickstartChange); + }, + + get shouldShowTorConnect() { + // TorBrowser must control the daemon + return ( + this.enabled && + // if we have succesfully bootstraped, then no need to show TorConnect + this._stageName !== TorConnectStage.Bootstrapped + ); + }, + + /** + * Whether we are in a stage that can lead into the Bootstrapping stage. I.e. + * whether we can make a "normal" or "auto" bootstrapping request. + * + * The value may change with TorConnectTopics.StageChanged. + * + * @param {boolean} + */ + get canBeginBootstrap() { + return ( + this._stageName === TorConnectStage.Start || + this._stageName === TorConnectStage.Offline || + this._stageName === TorConnectStage.ChooseRegion || + this._stageName === TorConnectStage.RegionNotFound || + this._stageName === TorConnectStage.ConfirmRegion + ); + }, + + /** + * Whether we are in an error stage that can lead into the Bootstrapping + * stage. I.e. whether we can make an "auto" bootstrapping request. + * + * The value may change with TorConnectTopics.StageChanged. + * + * @param {boolean} + */ + get canBeginAutoBootstrap() { + return ( + this._stageName === TorConnectStage.ChooseRegion || + this._stageName === TorConnectStage.RegionNotFound || + this._stageName === TorConnectStage.ConfirmRegion + ); + }, + + // TODO: Remove when all pages have switched to "stage". + get state() { + // There is no "Error" stage, but about:torconnect relies on receiving the + // Error state to update its display. So we temporarily set the stage for a + // StateChange signal. + if (this._isErrorState) { + return TorConnectState.Error; + } + switch (this._stageName) { + case TorConnectStage.Disabled: + return TorConnectState.Disabled; + case TorConnectStage.Loading: + return TorConnectState.Initial; + case TorConnectStage.Start: + case TorConnectStage.Offline: + case TorConnectStage.ChooseRegion: + case TorConnectStage.RegionNotFound: + case TorConnectStage.ConfirmRegion: + case TorConnectStage.FinalError: + return TorConnectState.Configuring; + case TorConnectStage.Bootstrapping: + if ( + this._bootstrapTrigger === TorConnectStage.Start || + this._bootstrapTrigger === TorConnectStage.Offline + ) { + return TorConnectState.Bootstrapping; + } + return TorConnectState.AutoBootstrapping; + case TorConnectStage.Bootstrapped: + return TorConnectState.Bootstrapped; + } + lazy.logger.error(`Unknown state at stage ${this._stageName}`); + return null; + }, + + get countryCodes() { + return this._countryCodes; + }, + + get countryNames() { + return this._countryNames; + }, + + /** + * Whether the Bootstrapping process has ever failed, not including being + * cancelled or being offline. + * + * The value may change with TorConnectTopics.StageChanged. + * + * @type {boolean} + */ + get potentiallyBlocked() { + return this._potentiallyBlocked; + }, + + /** + * Ensure that we are not disabled. + */ + _ensureEnabled() { + if (!this.enabled || this._stageName === TorConnectStage.Disabled) { + throw new Error("Unexpected Disabled stage for user method"); + } + }, + + /** + * Signal an error to listeners. + * + * @param {Error} error - The error. + */ + _signalError(error) { + // TODO: Replace this method with _setError without any signalling when + // pages have switched to stage. + // Currently it simulates the old behaviour for about:torconnect. + lazy.logger.debug("Signalling error", error); + + if (!(error instanceof TorConnectError)) { + error = new TorConnectError(TorConnectError.ExternalError, error); + } + this._errorDetails = error; + + // Temporarily set an error state for listeners. + // We send the Error signal before the "StateChange" signal. + // Expected on android `onBootstrapError` to set lastKnownError. + // Expected in about:torconnect to set the error codes and internet status + // *before* the StateChange signal. + this._isErrorState = true; + Services.obs.notifyObservers(error, TorConnectTopics.Error); + Services.obs.notifyObservers( + { state: this.state }, + TorConnectTopics.StateChange + ); + this._isErrorState = false; + }, + + /** + * Add simulation options to the bootstrap request. + * + * @param {BootstrapOptions} bootstrapOptions - The options to add to. + * @param {string} [regionCode] - The region code being used. + */ + _addSimulateOptions(bootstrapOptions, regionCode) { + if (this.simulateBootstrapOptions.simulateCensorship) { + bootstrapOptions.simulateCensorship = true; + } + if (this.simulateBootstrapOptions.simulateDelay) { + bootstrapOptions.simulateDelay = + this.simulateBootstrapOptions.simulateDelay; + } + if (this.simulateBootstrapOptions.simulateOffline) { + bootstrapOptions.simulateOffline = true; + } + if (this.simulateBootstrapOptions.simulateMoatResponse) { + bootstrapOptions.simulateMoatResponse = + this.simulateBootstrapOptions.simulateMoatResponse; + } + + const censorshipLevel = Services.prefs.getIntPref( + TorConnectPrefs.censorship_level, + 0 + ); + if (censorshipLevel > 0 && !bootstrapOptions.simulateDelay) { + bootstrapOptions.simulateDelay = 1500; + } + if (censorshipLevel === 1) { + // Bootstrap fails, but auto-bootstrap does not. + if (!regionCode) { + bootstrapOptions.simulateCensorship = true; + } + } else if (censorshipLevel === 2) { + // Bootstrap fails. Auto-bootstrap fails with ConfirmRegion when using + // auto-detect region, but succeeds otherwise. + if (!regionCode) { + bootstrapOptions.simulateCensorship = true; + } + if (regionCode === "automatic") { + bootstrapOptions.simulateCensorship = true; + bootstrapOptions.simulateMoatResponse = { + country: "fi", + settings: [{}, {}], + }; + } + } else if (censorshipLevel === 3) { + // Bootstrap and auto-bootstrap fail. + bootstrapOptions.simulateCensorship = true; + bootstrapOptions.simulateMoatResponse = { + country: null, + settings: [], + }; + } + }, + + /** + * Confirm that a bootstrapping can take place, and whether the given values + * are valid. + * + * @param {string} [regionCode] - The region code passed in. + * + * @return {boolean} whether bootstrapping can proceed. + */ + _confirmBootstrapping(regionCode) { + this._ensureEnabled(); + + if (this._bootstrapAttempt) { + lazy.logger.warn( + "Already have an ongoing bootstrap attempt." + + ` Ignoring request with ${regionCode}.` + ); + return false; + } + + const currentStage = this._stageName; + + if (regionCode) { + if (!this.canBeginAutoBootstrap) { + lazy.logger.warn( + `Cannot begin auto bootstrap in stage ${currentStage}` + ); + return false; + } + if ( + regionCode === "automatic" && + currentStage !== TorConnectStage.ChooseRegion + ) { + lazy.logger.warn("Auto bootstrap is missing an explicit regionCode"); + return false; + } + return true; + } + + if (!this.canBeginBootstrap) { + lazy.logger.warn(`Cannot begin bootstrap in stage ${currentStage}`); + return false; + } + if (this.canBeginAutoBootstrap) { + // Only expect "auto" bootstraps to be triggered when in an error stage. + lazy.logger.warn( + `Expected a regionCode to bootstrap in stage ${currentStage}` + ); + return false; + } + + return true; + }, + + /** + * Begin a bootstrap attempt. + * + * @param {string} [regionCode] - An optional region code string to use, or + * "automatic" to automatically determine the region. If given, will start + * an auto-bootstrap attempt. + */ + async beginBootstrapping(regionCode) { + lazy.logger.debug("TorConnect.beginBootstrapping()"); + + if (!this._confirmBootstrapping(regionCode)) { + return; + } + + const beginStage = this._stageName; + const bootstrapOptions = { regionCode }; + const bootstrapAttempt = regionCode + ? new AutoBootstrapAttempt() + : new BootstrapAttempt(); + + if (!regionCode) { + // Only test internet for the first bootstrap attempt. + // TODO: Remove this since we do not have user consent. tor-browser#42605. + bootstrapOptions.testInternet = true; + } + + this._addSimulateOptions(bootstrapOptions, regionCode); + + // NOTE: The only `await` in this method is for `bootstrapAttempt.run`. + // Moreover, we returned early if `_bootstrapAttempt` was non-`null`. + // Therefore, the method is effectively "locked" by `_bootstrapAttempt`, so + // there should only ever be one caller at a time. + + if (regionCode) { + // Set the default to what the user chose. + this._defaultRegion = regionCode; + } else { + // Reset the default region to show in the UI. + this._defaultRegion = "automatic"; + } + this._requestedStage = null; + this._bootstrapTrigger = beginStage; + this._setStage(TorConnectStage.Bootstrapping); + this._bootstrapAttempt = bootstrapAttempt; + + let error = null; + let result = null; + try { + result = await bootstrapAttempt.run(progress => { + this._bootstrappingStatus.progress = progress; + lazy.logger.info(`Bootstrapping ${progress}% complete`); + this._notifyBootstrapProgress(); + }, bootstrapOptions); + } catch (err) { + error = err; + } + + const requestedStage = this._requestedStage; + this._requestedStage = null; + this._bootstrapTrigger = null; + this._bootstrapAttempt = null; + + if (bootstrapAttempt.detectedRegion) { + this._defaultRegion = bootstrapAttempt.detectedRegion; + } + + if (result === "complete") { + // Reset tryAgain, potentiallyBlocked and errorDetails in case the tor + // process exists later on. + this._tryAgain = false; + this._potentiallyBlocked = false; + this._errorDetails = null; + // Re-enable quickstart for future sessions. + Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, false); + + if (requestedStage) { + lazy.logger.warn( + `Ignoring ${requestedStage} request since we are bootstrapped` + ); + } + this._setStage(TorConnectStage.Bootstrapped); + Services.obs.notifyObservers(null, TorConnectTopics.BootstrapComplete); + + // Now call the postBootstrapped method. We do this after changing the + // stage to ensure that AutoBootstrapAttempt.postBootstrapped call to + // saveTemporaryBridges does not trigger SettingsChanged too early and + // cancel itself. + bootstrapAttempt.postBootstrapped(); + return; + } + + if (requestedStage) { + lazy.logger.debug("Ignoring bootstrap result", result, error); + this._setStage(requestedStage); + return; + } + + if ( + result === "offline" && + (beginStage === TorConnectStage.Start || + beginStage === TorConnectStage.Offline) + ) { + this._tryAgain = true; + this._signalError(new TorConnectError(TorConnectError.Offline)); + + this._setStage(TorConnectStage.Offline); + return; + } + + if (error) { + lazy.logger.info("Bootstrap attempt error", error); + + this._tryAgain = true; + this._potentiallyBlocked = true; + // Disable quickstart until we have a successful bootstrap. + Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true); + + this._signalError(error); + + switch (beginStage) { + case TorConnectStage.Start: + case TorConnectStage.Offline: + this._setStage(TorConnectStage.ChooseRegion); + return; + case TorConnectStage.ChooseRegion: + // TODO: Uncomment for behaviour in tor-browser#42550. + /* + if (regionCode !== "automatic") { + // Not automatic. Go straight to the final error. + this._setStage(TorConnectStage.FinalError); + return; + } + */ + if (regionCode !== "automatic" || bootstrapAttempt.detectedRegion) { + this._setStage(TorConnectStage.ConfirmRegion); + return; + } + this._setStage(TorConnectStage.RegionNotFound); + return; + } + this._setStage(TorConnectStage.FinalError); + return; + } + + // Bootstrap was cancelled. + if (result !== "cancelled") { + lazy.logger.error(`Unexpected bootstrap result`, result); + } + + // TODO: Remove this Offline hack when pages use "stage". + if (beginStage === TorConnectStage.Offline) { + // Re-send the "Offline" error to push the pages back to "Offline". + this._signalError(new TorConnectError(TorConnectError.Offline)); + } + + // Return to the previous stage. + this._setStage(beginStage); + }, + + /** + * Cancel an ongoing bootstrap attempt. + */ + cancelBootstrapping() { + lazy.logger.debug("TorConnect.cancelBootstrapping()"); + + this._ensureEnabled(); + + if (!this._bootstrapAttempt) { + lazy.logger.warn("No bootstrap attempt to cancel"); + return; + } + + this._bootstrapAttempt.cancel(); + }, + + /** + * Request the transition to the given stage. + * + * If we are bootstrapping, it will be cancelled and the stage will be + * transitioned to when it resolves. Otherwise, we will switch to the stage + * immediately. + * + * @param {string} stage - The stage to request. + * @param {boolean} [overideBootstrapped=false] - Whether the request can + * override the "Bootstrapped" stage. + */ + _makeStageRequest(stage, overrideBootstrapped = false) { + lazy.logger.debug(`Request for stage ${stage}`); + + this._ensureEnabled(); + + if (stage === this._stageName) { + lazy.logger.info(`Ignoring request for current stage ${stage}`); + return; + } + if ( + !overrideBootstrapped && + this._stageName === TorConnectStage.Bootstrapped + ) { + lazy.logger.warn(`Cannot move to ${stage} when bootstrapped`); + return; + } + if (this._stageName === TorConnectStage.Loading) { + if (stage === TorConnectStage.Start) { + // Will transition to "Start" stage when loading completes. + lazy.logger.info("Still in the Loading stage"); + } else { + lazy.logger.warn(`Cannot move to ${stage} when Loading`); + } + return; + } + + if (!this._bootstrapAttempt) { + // Transition immediately. + this._setStage(stage); + return; + } + + if (this._requestedStage === stage) { + lazy.logger.info(`Already requesting stage ${stage}`); + return; + } + if (this._requestedStage) { + lazy.logger.warn( + `Overriding request for ${this._requestedStage} with ${stage}` + ); + } + // Move to stage *after* bootstrap completes. + this._requestedStage = stage; + this._bootstrapAttempt?.cancel(); + }, + + /** + * Restart the TorConnect stage to the start. + */ + startAgain() { + this._makeStageRequest(TorConnectStage.Start); + }, + + /** + * Set the stage to be "ChooseRegion". + */ + chooseRegion() { + if (!this._potentiallyBlocked) { + lazy.logger.error("chooseRegion request before getting an error"); + return; + } + // NOTE: The ChooseRegion stage needs _errorDetails to be displayed in + // about:torconnect. The _potentiallyBlocked condition should be + // sufficient to ensure this. + this._makeStageRequest(TorConnectStage.ChooseRegion); + }, + + /* + Further external commands and helper methods + */ + + /** + * Open the "about:torconnect" tab. + * + * Bootstrapping or AutoBootstrapping can also be automatically triggered at + * the same time, if the current state allows for it. + * + * Bootstrapping will not be triggered if the connection is + * potentially blocked. + * + * @param {object} [options] - extra options. + * @property {"soft"|"hard"} [options.beginBootstrapping] - Whether to try and + * begin bootstrapping. "soft" will only trigger the bootstrap if we are not + * `potentiallyBlocked`. "hard" will try begin the bootstrap regardless. + * @property {string} [options.regionCode] - A region to pass in for + * auto-bootstrapping. + */ + openTorConnect(options) { + // FIXME: Should we move this to the about:torconnect actor? + const win = lazy.BrowserWindowTracker.getTopWindow(); + win.switchToTabHavingURI("about:torconnect", true, { + ignoreQueryString: true, + }); + + if (!options?.beginBootstrapping || !this.canBeginBootstrap) { + return; + } + + if (options.beginBootstrapping === "hard") { + if (this.canBeginAutoBootstrap && !options.regionCode) { + // Treat as an addition startAgain request to first move back to the + // "Start" stage before bootstrapping. + this.startAgain(); + } + } else if (this.potentiallyBlocked) { + // Do not trigger the bootstrap if we have ever had an error. + return; + } + + this.beginBootstrapping(options.regionCode); + }, + + async getCountryCodes() { + // Difference with the getter: this is to be called by TorConnectParent, and + // downloads the country codes if they are not already in cache. + if (this._countryCodes.length) { + return this._countryCodes; + } + const mrpc = new lazy.MoatRPC(); + try { + await mrpc.init(); + this._countryCodes = await mrpc.circumvention_countries(); + } catch (err) { + lazy.logger.error("An error occurred while fetching country codes", err); + } finally { + mrpc.uninit(); + } + return this._countryCodes; + }, + + getRedirectURL(url) { + return `about:torconnect?redirect=${encodeURIComponent(url)}`; + }, + + /** + * Convert the given object into a list of valid URIs. + * + * The object is either from the user's homepage preference (which may + * contain multiple domains separated by "|") or uris passed to the browser + * via command-line. + * + * @param {string|string[]} uriVariant - The string to extract uris from. + * + * @return {string[]} - The array of uris found. + */ + fixupURIs(uriVariant) { + let uriArray; + if (typeof uriVariant === "string") { + uriArray = uriVariant.split("|"); + } else if ( + Array.isArray(uriVariant) && + uriVariant.every(entry => typeof entry === "string") + ) { + uriArray = uriVariant; + } else { + // about:tor as safe fallback + lazy.logger.error( + `Received unknown variant '${JSON.stringify(uriVariant)}'` + ); + uriArray = ["about:tor"]; + } + + // Attempt to convert user-supplied string to a uri, fallback to + // about:tor if cannot convert to valid uri object + return uriArray.map( + uriString => + Services.uriFixup.getFixupURIInfo( + uriString, + Ci.nsIURIFixup.FIXUP_FLAG_NONE + ).preferredURI?.spec ?? "about:tor" + ); + }, + + // called from browser.js on browser startup, passed in either the user's homepage(s) + // or uris passed via command-line; we want to replace them with about:torconnect uris + // which redirect after bootstrapping + getURIsToLoad(uriVariant) { + const uris = this.fixupURIs(uriVariant); + const localUriRx = /^(file:\/\/\/|moz-extension:)/; + lazy.logger.debug( + `Will load after bootstrap => [${uris + .filter(uri => !localUriRx.test(uri)) + .join(", ")}]` + ); + + return uris.map(uri => + localUriRx.test(uri) ? uri : this.getRedirectURL(uri) + ); + }, +}; diff --git a/toolkit/modules/TorSettings.sys.mjs b/toolkit/modules/TorSettings.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..f3661b8e34b416cc28eb9bb169b6c2490a277975 --- /dev/null +++ b/toolkit/modules/TorSettings.sys.mjs @@ -0,0 +1,1144 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", + Lox: "resource://gre/modules/Lox.sys.mjs", + LoxTopics: "resource://gre/modules/Lox.sys.mjs", + TorParsers: "resource://gre/modules/TorParsers.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", +}); + +ChromeUtils.defineLazyGetter(lazy, "logger", () => { + return console.createInstance({ + maxLogLevelPref: "browser.torsettings.log_level", + prefix: "TorSettings", + }); +}); + +/* TorSettings observer topics */ +export const TorSettingsTopics = Object.freeze({ + Ready: "torsettings:ready", + SettingsChanged: "torsettings:settings-changed", +}); + +/* Prefs used to store settings in TorBrowser prefs */ +const TorSettingsPrefs = Object.freeze({ + // NOTE: torbrowser.settings.quickstart.enabled used to be managed by + // TorSettings but was moved to TorConnect.quickstart in tor-browser#41921. + bridges: { + /* bool: does tor use bridges */ + enabled: "torbrowser.settings.bridges.enabled", + /* int: See TorBridgeSource */ + source: "torbrowser.settings.bridges.source", + /* string: output of crypto.randomUUID() */ + lox_id: "torbrowser.settings.bridges.lox_id", + /* string: obfs4|meek-azure|snowflake|etc */ + builtin_type: "torbrowser.settings.bridges.builtin_type", + /* preference branch: each child branch should be a bridge string */ + bridge_strings: "torbrowser.settings.bridges.bridge_strings", + }, + proxy: { + /* bool: does tor use a proxy */ + enabled: "torbrowser.settings.proxy.enabled", + /* See TorProxyType */ + type: "torbrowser.settings.proxy.type", + /* string: proxy server address */ + address: "torbrowser.settings.proxy.address", + /* int: [1,65535], proxy port */ + port: "torbrowser.settings.proxy.port", + /* string: username */ + username: "torbrowser.settings.proxy.username", + /* string: password */ + password: "torbrowser.settings.proxy.password", + }, + firewall: { + /* bool: does tor have a port allow list */ + enabled: "torbrowser.settings.firewall.enabled", + /* string: comma-delimitted list of port numbers */ + allowed_ports: "torbrowser.settings.firewall.allowed_ports", + }, +}); + +export const TorBridgeSource = Object.freeze({ + Invalid: -1, + BuiltIn: 0, + BridgeDB: 1, + UserProvided: 2, + Lox: 3, +}); + +export const TorProxyType = Object.freeze({ + Invalid: -1, + Socks4: 0, + Socks5: 1, + HTTPS: 2, +}); + +/** + * Split a blob of bridge lines into an array with single lines. + * Lines are delimited by \r\n or \n and each bridge string can also optionally + * have 'bridge' at the beginning. + * We split the text by \r\n, we trim the lines, remove the bridge prefix. + * + * @param {string} bridgeLines The text with the lines + * @returns {string[]} An array where each bridge line is an item + */ +function splitBridgeLines(bridgeLines) { + // Split on the newline and for each bridge string: trim, remove starting + // 'bridge' string. + // Replace whitespace with standard " ". + // NOTE: We only remove the bridge string part if it is followed by a + // non-whitespace. + return bridgeLines.split(/\r?\n/).map(val => + val + .trim() + .replace(/^bridge\s+(\S)/i, "$1") + .replace(/\s+/, " ") + ); +} + +/** + * @typedef {Object} BridgeValidationResult + * + * @property {integer[]} errorLines - The lines that contain errors. Counting + * from 1. + * @property {boolean} empty - Whether the given string contains no bridges. + * @property {string[]} validBridges - The valid bridge lines found. + */ +/** + * Validate the given bridge lines. + * + * @param {string} bridgeLines - The bridge lines to validate, separated by + * newlines. + * + * @returns {BridgeValidationResult} + */ +export function validateBridgeLines(bridgeLines) { + let empty = true; + const errorLines = []; + const validBridges = []; + for (const [index, bridge] of splitBridgeLines(bridgeLines).entries()) { + if (!bridge) { + // Empty line. + continue; + } + empty = false; + try { + // TODO: Have a more comprehensive validation parser. + lazy.TorParsers.parseBridgeLine(bridge); + } catch { + errorLines.push(index + 1); + continue; + } + validBridges.push(bridge); + } + return { empty, errorLines, validBridges }; +} + +/** + * Return a shuffled (Fisher-Yates) copy of an array. + * + * @template T + * @param {T[]} array + * @returns {T[]} + */ +function arrayShuffle(array) { + array = [...array]; + for (let i = array.length - 1; i > 0; --i) { + // number n such that 0.0 <= n < 1.0 + const n = Math.random(); + // integer j such that 0 <= j <= i + const j = Math.floor(n * (i + 1)); + + // swap values at indices i and j + const tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + return array; +} + +/* TorSettings module */ + +class TorSettingsImpl { + /** + * The underlying settings values. + * + * @type {object} + */ + #settings = { + bridges: { + /** + * Whether the bridges are enabled or not. + * + * @type {boolean} + */ + enabled: false, + source: TorBridgeSource.Invalid, + /** + * The lox id is used with the Lox "source", and remains set with the + * stored value when other sources are used. + * + * @type {string} + */ + lox_id: "", + /** + * The built-in type to use when using the BuiltIn "source", or empty when + * using any other source. + * + * @type {string} + */ + builtin_type: "", + /** + * The current bridge strings. + * + * Can only be non-empty if the "source" is not Invalid. + * + * @type {Array<string>} + */ + bridge_strings: [], + }, + proxy: { + enabled: false, + type: TorProxyType.Invalid, + address: "", + port: 0, + username: "", + password: "", + }, + firewall: { + enabled: false, + allowed_ports: [], + }, + }; + + /** + * Temporary bridge settings to apply instead of #settings.bridges. + * + * @type {?Object} + */ + #temporaryBridgeSettings = null; + + /** + * The recommended pluggable transport. + * + * @type {string} + */ + #recommendedPT = ""; + + /** + * The bridge lines for built-in bridges. + * Keys are pluggable transports, and values are arrays of bridge lines. + * + * @type {Object.<string, string[]>} + */ + #builtinBridges = {}; + + /** + * A promise that resolves once we are initialized, or throws if there was an + * initialization error. + * + * @type {Promise} + */ + #initializedPromise; + /** + * Resolve callback of the initializedPromise. + */ + #initComplete; + /** + * Reject callback of the initializedPromise. + */ + #initFailed; + /** + * Tell whether the initializedPromise has been resolved. + * We keep this additional member to avoid making everything async. + * + * @type {boolean} + */ + #initialized = false; + + /** + * Whether uninit cleanup has been called. + * + * @type {boolean} + */ + #uninitCalled = false; + + /** + * Whether Lox was initialized. + * + * @type {boolean} + */ + #initializedLox = false; + + /** + * Whether observers were initialized. + * + * @type {boolean} + */ + #initializedObservers = false; + + constructor() { + this.#initializedPromise = new Promise((resolve, reject) => { + this.#initComplete = resolve; + this.#initFailed = reject; + }); + + // Add some read-only getters for the #settings object. + // E.g. TorSetting.#settings.bridges.source is exposed publicly as + // TorSettings.bridges.source. + for (const groupname in this.#settings) { + const publicGroup = {}; + for (const name in this.#settings[groupname]) { + // Public group only has a getter for the property. + Object.defineProperty(publicGroup, name, { + get: () => { + this.#checkIfInitialized(); + return structuredClone(this.#settings[groupname][name]); + }, + set: () => { + throw new Error( + `TorSettings.${groupname}.${name} cannot be set directly` + ); + }, + }); + } + // The group object itself should not be writable. + Object.preventExtensions(publicGroup); + Object.defineProperty(this, groupname, { + writable: false, + value: publicGroup, + }); + } + } + + /** + * The proxy URI for the current settings, or `null` if no proxy is + * configured. + * + * @type {?string} + */ + get proxyUri() { + const { type, address, port, username, password } = this.#settings.proxy; + switch (type) { + case TorProxyType.Socks4: + return `socks4a://${address}:${port}`; + case TorProxyType.Socks5: + if (username) { + return `socks5://${username}:${password}@${address}:${port}`; + } + return `socks5://${address}:${port}`; + case TorProxyType.HTTPS: + if (username) { + return `http://${username}:${password}@${address}:${port}`; + } + return `http://${address}:${port}`; + } + return null; + } + + /** + * Regular expression for a decimal non-negative integer. + * + * @type {RegExp} + */ + #portRegex = /^[0-9]+$/; + /** + * Parse a string as a port number. + * + * @param {string|integer} val - The value to parse. + * @param {boolean} trim - Whether a string value can be stripped of + * whitespace before parsing. + * + * @return {integer?} - The port number, or null if the given value was not + * valid. + */ + #parsePort(val, trim) { + if (typeof val === "string") { + if (trim) { + val = val.trim(); + } + // ensure port string is a valid positive integer + if (this.#portRegex.test(val)) { + val = Number.parseInt(val, 10); + } else { + throw new Error(`Invalid port string "${val}"`); + } + } + if (!Number.isInteger(val) || val < 1 || val > 65535) { + throw new Error(`Port out of range: ${val}`); + } + return val; + } + /** + * Test whether two arrays have equal members and order. + * + * @param {Array} val1 - The first array to test. + * @param {Array} val2 - The second array to compare against. + * + * @return {boolean} - Whether the two arrays are equal. + */ + #arrayEqual(val1, val2) { + if (val1.length !== val2.length) { + return false; + } + return val1.every((v, i) => v === val2[i]); + } + + /** + * Return the bridge lines associated to a certain pluggable transport. + * + * @param {string} pt The pluggable transport to return the lines for + * @returns {string[]} The bridge lines in random order + */ + #getBuiltinBridges(pt) { + return this.#builtinBridges[pt] ?? []; + } + + /** + * Whether this module is enabled. + * + * @type {boolean} + */ + get enabled() { + return lazy.TorLauncherUtil.shouldStartAndOwnTor; + } + + /** + * Load or init our settings. + */ + async init() { + if (this.#initialized) { + lazy.logger.warn("Called init twice."); + await this.#initializedPromise; + return; + } + try { + await this.#initInternal(); + this.#initialized = true; + this.#initComplete(); + Services.obs.notifyObservers(null, TorSettingsTopics.Ready); + } catch (e) { + this.#initFailed(e); + throw e; + } + } + + /** + * The actual implementation of the initialization, which is wrapped to make + * it easier to update initializatedPromise. + */ + async #initInternal() { + if (!this.enabled || this.#uninitCalled) { + // Nothing to do. + return; + } + + try { + const req = await fetch("chrome://global/content/pt_config.json"); + const config = await req.json(); + lazy.logger.debug("Loaded pt_config.json", config); + this.#recommendedPT = config.recommendedDefault; + this.#builtinBridges = config.bridges; + for (const type in this.#builtinBridges) { + // Shuffle so that Tor Browser users do not all try the built-in bridges + // in the same order. + // Only do this once per session. In particular, we don't re-shuffle if + // changeSettings is called with the same bridges.builtin_type value. + this.#builtinBridges[type] = arrayShuffle(this.#builtinBridges[type]); + } + } catch (e) { + lazy.logger.error("Could not load the built-in PT config.", e); + } + + // `uninit` may have been called whilst we awaited pt_config. + if (this.#uninitCalled) { + lazy.logger.warn("unint was called before init completed."); + return; + } + + // Initialize this before loading from prefs because we need Lox initialized + // before any calls to Lox.getBridges(). + if (!lazy.TorLauncherUtil.isAndroid) { + try { + // Set as initialized before calling to ensure it is cleaned up by our + // `uninit` method. + this.#initializedLox = true; + await lazy.Lox.init(); + } catch (e) { + lazy.logger.error("Could not initialize Lox.", e); + } + } + + // `uninit` may have been called whilst we awaited Lox.init. + if (this.#uninitCalled) { + lazy.logger.warn("unint was called before init completed."); + return; + } + + this.#loadFromPrefs(); + // We do not pass on the loaded settings to the TorProvider yet. Instead + // TorProvider will ask for these once it has initialised. + + Services.obs.addObserver(this, lazy.LoxTopics.UpdateBridges); + this.#initializedObservers = true; + + lazy.logger.info("Ready"); + } + + /** + * Unload or uninit our settings. + */ + async uninit() { + if (this.#uninitCalled) { + lazy.logger.warn("Called uninit twice"); + return; + } + + this.#uninitCalled = true; + // NOTE: We do not reset #initialized to false because we want it to remain + // in place for external callers, and we do not want `#initInternal` to be + // re-entered. + + if (this.#initializedObservers) { + Services.obs.removeObserver(this, lazy.LoxTopics.UpdateBridges); + } + if (this.#initializedLox) { + await lazy.Lox.uninit(); + } + } + + observe(subject, topic) { + switch (topic) { + case lazy.LoxTopics.UpdateBridges: + if ( + this.#settings.bridges.lox_id && + this.#settings.bridges.source === TorBridgeSource.Lox + ) { + // Re-trigger the call to lazy.Lox.getBridges. + // FIXME: This can compete with TorConnect to reach TorProvider. + // tor-browser#42316 + this.changeSettings({ + bridges: { + source: TorBridgeSource.Lox, + lox_id: this.#settings.bridges.lox_id, + }, + }); + } + break; + } + } + + /** + * Check whether the module is enabled and successfully initialized, and throw + * if it is not. + */ + #checkIfInitialized() { + if (!this.enabled) { + throw new Error("TorSettings is not enabled"); + } + if (!this.#initialized) { + lazy.logger.trace("Not initialized code path."); + throw new Error( + "TorSettings has not been initialized yet, or its initialization failed" + ); + } + } + + /** + * Tell whether TorSettings has been successfully initialized. + * + * @returns {boolean} + */ + get initialized() { + return this.#initialized; + } + + /** + * A promise that resolves once we are initialized, or throws if there was an + * initialization error. + * + * @type {Promise} + */ + get initializedPromise() { + return this.#initializedPromise; + } + + /** + * Load our settings from prefs. + */ + #loadFromPrefs() { + lazy.logger.debug("loadFromPrefs()"); + + /* Bridges */ + const bridges = {}; + bridges.enabled = Services.prefs.getBoolPref( + TorSettingsPrefs.bridges.enabled, + false + ); + bridges.source = Services.prefs.getIntPref( + TorSettingsPrefs.bridges.source, + TorBridgeSource.Invalid + ); + switch (bridges.source) { + case TorBridgeSource.BridgeDB: + case TorBridgeSource.UserProvided: + bridges.bridge_strings = Services.prefs + .getBranch(TorSettingsPrefs.bridges.bridge_strings) + .getChildList("") + .map(pref => + Services.prefs.getStringPref( + `${TorSettingsPrefs.bridges.bridge_strings}${pref}` + ) + ); + break; + case TorBridgeSource.BuiltIn: + // bridge_strings is set via builtin_type. + bridges.builtin_type = Services.prefs.getStringPref( + TorSettingsPrefs.bridges.builtin_type, + "" + ); + break; + case TorBridgeSource.Lox: + // bridge_strings is set via lox id. + bridges.lox_id = Services.prefs.getStringPref( + TorSettingsPrefs.bridges.lox_id, + "" + ); + break; + } + try { + this.#fixupBridgeSettings(bridges); + this.#settings.bridges = bridges; + } catch (error) { + lazy.logger.error("Loaded bridge preferences failed", error); + // Keep the default #settings.bridges. + } + + /* Proxy */ + const proxy = {}; + proxy.enabled = Services.prefs.getBoolPref( + TorSettingsPrefs.proxy.enabled, + false + ); + if (proxy.enabled) { + proxy.type = Services.prefs.getIntPref( + TorSettingsPrefs.proxy.type, + TorProxyType.Invalid + ); + proxy.address = Services.prefs.getStringPref( + TorSettingsPrefs.proxy.address, + "" + ); + proxy.port = Services.prefs.getIntPref(TorSettingsPrefs.proxy.port, 0); + proxy.username = Services.prefs.getStringPref( + TorSettingsPrefs.proxy.username, + "" + ); + proxy.password = Services.prefs.getStringPref( + TorSettingsPrefs.proxy.password, + "" + ); + } + try { + this.#fixupProxySettings(proxy); + this.#settings.proxy = proxy; + } catch (error) { + lazy.logger.error("Loaded proxy preferences failed", error); + // Keep the default #settings.proxy. + } + + /* Firewall */ + const firewall = {}; + firewall.enabled = Services.prefs.getBoolPref( + TorSettingsPrefs.firewall.enabled, + false + ); + if (firewall.enabled) { + firewall.allowed_ports = Services.prefs.getStringPref( + TorSettingsPrefs.firewall.allowed_ports, + "" + ); + } + try { + this.#fixupFirewallSettings(firewall); + this.#settings.firewall = firewall; + } catch (error) { + lazy.logger.error("Loaded firewall preferences failed", error); + // Keep the default #settings.firewall. + } + } + + /** + * Save our settings to prefs. + */ + #saveToPrefs() { + lazy.logger.debug("saveToPrefs()"); + + this.#checkIfInitialized(); + + /* Bridges */ + Services.prefs.setBoolPref( + TorSettingsPrefs.bridges.enabled, + this.#settings.bridges.enabled + ); + Services.prefs.setIntPref( + TorSettingsPrefs.bridges.source, + this.#settings.bridges.source + ); + Services.prefs.setStringPref( + TorSettingsPrefs.bridges.builtin_type, + this.#settings.bridges.builtin_type + ); + Services.prefs.setStringPref( + TorSettingsPrefs.bridges.lox_id, + this.#settings.bridges.lox_id + ); + // erase existing bridge strings + const bridgeBranchPrefs = Services.prefs + .getBranch(TorSettingsPrefs.bridges.bridge_strings) + .getChildList(""); + bridgeBranchPrefs.forEach(pref => { + Services.prefs.clearUserPref( + `${TorSettingsPrefs.bridges.bridge_strings}${pref}` + ); + }); + // write new ones + if ( + this.#settings.bridges.source !== TorBridgeSource.Lox && + this.#settings.bridges.source !== TorBridgeSource.BuiltIn + ) { + this.#settings.bridges.bridge_strings.forEach((string, index) => { + Services.prefs.setStringPref( + `${TorSettingsPrefs.bridges.bridge_strings}.${index}`, + string + ); + }); + } + /* Proxy */ + Services.prefs.setBoolPref( + TorSettingsPrefs.proxy.enabled, + this.#settings.proxy.enabled + ); + if (this.#settings.proxy.enabled) { + Services.prefs.setIntPref( + TorSettingsPrefs.proxy.type, + this.#settings.proxy.type + ); + Services.prefs.setStringPref( + TorSettingsPrefs.proxy.address, + this.#settings.proxy.address + ); + Services.prefs.setIntPref( + TorSettingsPrefs.proxy.port, + this.#settings.proxy.port + ); + Services.prefs.setStringPref( + TorSettingsPrefs.proxy.username, + this.#settings.proxy.username + ); + Services.prefs.setStringPref( + TorSettingsPrefs.proxy.password, + this.#settings.proxy.password + ); + } else { + Services.prefs.clearUserPref(TorSettingsPrefs.proxy.type); + Services.prefs.clearUserPref(TorSettingsPrefs.proxy.address); + Services.prefs.clearUserPref(TorSettingsPrefs.proxy.port); + Services.prefs.clearUserPref(TorSettingsPrefs.proxy.username); + Services.prefs.clearUserPref(TorSettingsPrefs.proxy.password); + } + /* Firewall */ + Services.prefs.setBoolPref( + TorSettingsPrefs.firewall.enabled, + this.#settings.firewall.enabled + ); + if (this.#settings.firewall.enabled) { + Services.prefs.setStringPref( + TorSettingsPrefs.firewall.allowed_ports, + this.#settings.firewall.allowed_ports.join(",") + ); + } else { + Services.prefs.clearUserPref(TorSettingsPrefs.firewall.allowed_ports); + } + } + + /** + * Push our settings down to the tor provider. + * + * Even though this introduces a circular depdency, it makes the API nicer for + * frontend consumers. + * + * @param {boolean} flush - Whether to also flush the settings to disk. + */ + async #applySettings(flush) { + const provider = await lazy.TorProviderBuilder.build(); + await provider.writeSettings(); + if (flush) { + provider.flushSettings(); + } + } + + /** + * Fixup the given bridges settings to fill in details, establish the correct + * types and clean up. + * + * May throw if there is an error in the given values. + * + * @param {Object} bridges - The bridges settings to fix up. + */ + #fixupBridgeSettings(bridges) { + if (!Object.values(TorBridgeSource).includes(bridges.source)) { + throw new Error(`Not a valid bridge source: "${bridges.source}"`); + } + + if ("enabled" in bridges) { + bridges.enabled = Boolean(bridges.enabled); + } + + // Set bridge_strings + switch (bridges.source) { + case TorBridgeSource.UserProvided: + case TorBridgeSource.BridgeDB: + // Only accept an Array for UserProvided and BridgeDB bridge_strings. + break; + case TorBridgeSource.BuiltIn: + bridges.builtin_type = String(bridges.builtin_type); + bridges.bridge_strings = this.#getBuiltinBridges(bridges.builtin_type); + break; + case TorBridgeSource.Lox: + bridges.lox_id = String(bridges.lox_id); + bridges.bridge_strings = lazy.Lox.getBridges(bridges.lox_id); + break; + case TorBridgeSource.Invalid: + bridges.bridge_strings = []; + break; + } + + if ( + !Array.isArray(bridges.bridge_strings) || + bridges.bridge_strings.some(str => typeof str !== "string") + ) { + throw new Error("bridge_strings should be an Array of strings"); + } + + if ( + bridges.source !== TorBridgeSource.Invalid && + !bridges.bridge_strings?.length + ) { + throw new Error( + `Missing bridge_strings for bridge source ${bridges.source}` + ); + } + + if (bridges.source !== TorBridgeSource.BuiltIn) { + bridges.builtin_type = ""; + } + if (bridges.source !== TorBridgeSource.Lox) { + bridges.lox_id = ""; + } + + if (bridges.source === TorBridgeSource.Invalid) { + bridges.enabled = false; + } + } + + /** + * Fixup the given proxy settings to fill in details, establish the correct + * types and clean up. + * + * May throw if there is an error in the given values. + * + * @param {Object} proxy - The proxy settings to fix up. + */ + #fixupProxySettings(proxy) { + proxy.enabled = Boolean(proxy.enabled); + if (!proxy.enabled) { + proxy.type = TorProxyType.Invalid; + proxy.address = ""; + proxy.port = 0; + proxy.username = ""; + proxy.password = ""; + return; + } + + if (!Object.values(TorProxyType).includes(proxy.type)) { + throw new Error(`Invalid proxy type: ${proxy.type}`); + } + proxy.port = this.#parsePort(proxy.port, false); + proxy.address = String(proxy.address); + proxy.username = String(proxy.username); + proxy.password = String(proxy.password); + } + + /** + * Fixup the given firewall settings to fill in details, establish the correct + * types and clean up. + * + * May throw if there is an error in the given values. + * + * @param {Object} firewall - The proxy settings to fix up. + */ + #fixupFirewallSettings(firewall) { + firewall.enabled = Boolean(firewall.enabled); + if (!firewall.enabled) { + firewall.allowed_ports = []; + return; + } + + let allowed_ports = firewall.allowed_ports; + if (!Array.isArray(allowed_ports)) { + allowed_ports = allowed_ports === "" ? [] : allowed_ports.split(","); + } + // parse and remove duplicates + const portSet = new Set(); + + for (const port of allowed_ports) { + try { + portSet.add(this.#parsePort(port, true)); + } catch (e) { + // Do not throw for individual ports. + lazy.logger.error(`Failed to parse the port ${port}. Ignoring.`, e); + } + } + firewall.allowed_ports = [...portSet]; + } + + /** + * Change the Tor settings in use. + * + * It is possible to set all settings, or only some sections: + * + * + bridges.enabled can be set individually. + * + bridges.source can be set with a corresponding bridge specification for + * the source (bridge_strings, lox_id, builtin_type). + * + proxy settings can be set as a group. + * + firewall settings can be set a group. + * + * @param {object} newValues - The new setting values, a subset of the + * complete settings that should be changed. + */ + async changeSettings(newValues) { + lazy.logger.debug("changeSettings()", newValues); + this.#checkIfInitialized(); + + // Make a structured clone since we change the object and may adopt some of + // the Array values. + newValues = structuredClone(newValues); + + const completeSettings = structuredClone(this.#settings); + const changes = []; + + /** + * Change the given setting to a new value. Does nothing if the new value + * equals the old one, otherwise the change will be recorded in `changes`. + * + * @param {string} group - The group name for the property. + * @param {string} prop - The property name within the group. + * @param {any} value - The value to set. + * @param [Function?] equal - A method to test equality between the old and + * new value. Otherwise uses `===` to check equality. + */ + const changeSetting = (group, prop, value, equal = null) => { + const currentValue = this.#settings[group][prop]; + if (equal ? equal(currentValue, value) : currentValue === value) { + return; + } + completeSettings[group][prop] = value; + changes.push(`${group}.${prop}`); + }; + + if ("bridges" in newValues) { + const changesLength = changes.length; + if ("source" in newValues.bridges) { + this.#fixupBridgeSettings(newValues.bridges); + changeSetting("bridges", "source", newValues.bridges.source); + changeSetting( + "bridges", + "bridge_strings", + newValues.bridges.bridge_strings, + this.#arrayEqual + ); + changeSetting("bridges", "lox_id", newValues.bridges.lox_id); + changeSetting( + "bridges", + "builtin_type", + newValues.bridges.builtin_type + ); + } else if ("enabled" in newValues.bridges) { + // Don't need to fixup all the settings, just need to ensure that the + // enabled value is compatible with the current source. + newValues.bridges.enabled = Boolean(newValues.bridges.enabled); + if ( + newValues.bridges.enabled && + completeSettings.bridges.source === TorBridgeSource.Invalid + ) { + throw new Error("Cannot enable bridges without a bridge source."); + } + } + if ("enabled" in newValues.bridges) { + changeSetting("bridges", "enabled", newValues.bridges.enabled); + } + + if (this.#temporaryBridgeSettings && changes.length !== changesLength) { + // A change in the bridges settings. + // We want to clear the temporary bridge settings to ensure that they + // cannot be used to overwrite these user-provided settings. + // See tor-browser#41921. + // NOTE: This should also trigger TorConnect to cancel any ongoing + // AutoBootstrap that would have otherwise used these settings. + this.#temporaryBridgeSettings = null; + lazy.logger.warn( + "Cleared temporary bridges since bridge settings were changed" + ); + } + } + + if ("proxy" in newValues) { + // proxy settings have to be set as a group. + this.#fixupProxySettings(newValues.proxy); + changeSetting("proxy", "enabled", Boolean(newValues.proxy.enabled)); + changeSetting("proxy", "type", newValues.proxy.type); + changeSetting("proxy", "address", newValues.proxy.address); + changeSetting("proxy", "port", newValues.proxy.port); + changeSetting("proxy", "username", newValues.proxy.username); + changeSetting("proxy", "password", newValues.proxy.password); + } + + if ("firewall" in newValues) { + // firewall settings have to be set as a group. + this.#fixupFirewallSettings(newValues.firewall); + changeSetting("firewall", "enabled", Boolean(newValues.firewall.enabled)); + changeSetting( + "firewall", + "allowed_ports", + newValues.firewall.allowed_ports, + this.#arrayEqual + ); + } + + // No errors so far, so save and commit. + this.#settings = completeSettings; + this.#saveToPrefs(); + + if (changes.length) { + Services.obs.notifyObservers( + { changes }, + TorSettingsTopics.SettingsChanged + ); + } + + lazy.logger.debug("setSettings result", this.#settings, changes); + + // After we have sent out the notifications for the changed settings and + // saved the preferences we send the new settings to TorProvider. + // Some properties are unread by TorProvider. So if only these values change + // there is no need to re-apply the settings. + const unreadProps = ["bridges.builtin_type", "bridges.lox_id"]; + const shouldApply = changes.some(prop => !unreadProps.includes(prop)); + if (shouldApply) { + await this.#applySettings(true); + } + } + + /** + * Get a copy of all our settings. + * + * @param {boolean} [useTemporary=false] - Whether the returned settings + * should use the temporary bridge settings, if any, instead. + * + * @returns {object} A copy of the settings object + */ + getSettings(useTemporary = false) { + lazy.logger.debug("getSettings()"); + this.#checkIfInitialized(); + const settings = structuredClone(this.#settings); + if (useTemporary && this.#temporaryBridgeSettings) { + // Override the bridge settings with our temporary ones. + settings.bridges = structuredClone(this.#temporaryBridgeSettings); + } + return settings; + } + + /** + * Return an array with the pluggable transports for which we have at least a + * built-in bridge line. + * + * @returns {string[]} An array with PT identifiers + */ + get builtinBridgeTypes() { + this.#checkIfInitialized(); + const types = Object.keys(this.#builtinBridges); + const recommendedIndex = types.indexOf(this.#recommendedPT); + if (recommendedIndex > 0) { + types.splice(recommendedIndex, 1); + types.unshift(this.#recommendedPT); + } + return types; + } + + /** + * Apply some Moat bridges temporarily. + * + * These bridges will not yet be saved to settings. + * + * @param {MoatBridges} bridges - The bridges to apply. + */ + async applyTemporaryBridges(bridges) { + this.#checkIfInitialized(); + + if ( + bridges.source !== TorBridgeSource.BuiltIn && + bridges.source !== TorBridgeSource.BridgeDB + ) { + throw new Error(`Invalid bridge source ${bridges.source}`); + } + + const bridgeSettings = { + enabled: true, + source: bridges.source, + builtin_type: String(bridges.builtin_type), + bridge_strings: structuredClone(bridges.bridge_strings), + }; + + this.#fixupBridgeSettings(bridgeSettings); + + // After checks are complete, we commit them. + this.#temporaryBridgeSettings = bridgeSettings; + // Do not flush the temporary bridge settings until they are saved. + await this.#applySettings(false); + } + + /** + * Save to current temporary bridges to be permanent instead. + */ + async saveTemporaryBridges() { + this.#checkIfInitialized(); + if (!this.#temporaryBridgeSettings) { + lazy.logger.warn("No temporary bridges to save"); + return; + } + const bridgeSettings = this.#temporaryBridgeSettings; + this.#temporaryBridgeSettings = null; + await this.changeSettings({ bridges: bridgeSettings }); + } + + /** + * Clear the current temporary bridges. + */ + async clearTemporaryBridges() { + this.#checkIfInitialized(); + if (!this.#temporaryBridgeSettings) { + lazy.logger.debug("No temporary bridges to clear"); + return; + } + this.#temporaryBridgeSettings = null; + await this.#applySettings(); + } +} + +export const TorSettings = new TorSettingsImpl(); diff --git a/toolkit/modules/TorStrings.sys.mjs b/toolkit/modules/TorStrings.sys.mjs new file mode 100644 index 0000000000000000000000000000000000000000..5c45b2532fadfafd2f2fb4d4733ed39ce7557ba3 --- /dev/null +++ b/toolkit/modules/TorStrings.sys.mjs @@ -0,0 +1,274 @@ +// Copyright (c) 2022, The Tor Project, Inc. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + +function getLocale() { + const locale = Services.locale.appLocaleAsBCP47; + return locale === "ja-JP-macos" ? "ja" : locale; +} + +/* + Tor Property String Bundle + + Property strings loaded from torbutton/tor-launcher, but provide a fallback in case they aren't available +*/ +class TorPropertyStringBundle { + constructor(aBundleURL, aPrefix) { + try { + this._bundle = Services.strings.createBundle(aBundleURL); + this._bundleURL = aBundleURL; + } catch (e) { + console.error(`[TorStrings] Cannot load ${aBundleURL}`, e); + } + + this._prefix = aPrefix; + } + + getString(key, fallback) { + const reportError = + AppConstants.BASE_BROWSER_VERSION === "dev-build" && !!this._bundle; + if (key) { + try { + return this._bundle.GetStringFromName(`${this._prefix}${key}`); + } catch (e) { + if (reportError) { + console.warn( + `[TorStrings] Cannot get ${this._prefix}${key} from ${this._bundleURL}`, + e + ); + } + } + } + + // on failure, assign the fallback if it exists + if (fallback) { + return fallback; + } + // otherwise return string key + return `$(${key})`; + } + + getStrings(strings, additionalPrefix = "") { + return Object.fromEntries( + Object.entries(strings).map(([key, fallback]) => [ + key, + this.getString(additionalPrefix + key, fallback), + ]) + ); + } +} + +const Loader = { + /* + Tor about:preferences#connection Strings + */ + settings() { + const strings = { + // Message box + torPreferencesDescription: + "Tor Browser routes your traffic over the Tor Network, run by thousands of volunteers around the world.", + // Quickstart + quickstartCheckbox: "Always connect automatically", + bridgeLocation: "Your location", + bridgeLocationAutomatic: "Automatic", + bridgeLocationFrequent: "Frequently selected locations", + bridgeLocationOther: "Other locations", + bridgeChooseForMe: "Choose a Bridge For Me…", + }; + + const tsb = new TorPropertyStringBundle( + "chrome://torbutton/locale/settings.properties", + "settings." + ); + return tsb.getStrings(strings); + } /* Tor Network Settings Strings */, + + torConnect() { + const strings = { + torConnect: "Connect to Tor", + + torConnecting: "Establishing a Connection", + + tryingAgain: "Trying again…", + + noInternet: "Tor Browser couldn’t reach the Internet", + noInternetDescription: + "This could be due to a connection issue rather than Tor being blocked. Check your Internet connection, proxy and firewall settings before trying again.", + torBootstrapFailed: "Tor failed to establish a Tor network connection.", + couldNotConnect: "Tor Browser could not connect to Tor", + configureConnection: "configure your connection", + assistDescription: + "If Tor is blocked in your location, trying a bridge may help. Connection assist can choose one for you using your location, or you can %S manually instead.", + tryingBridge: "Trying a bridge…", + + tryingBridgeAgain: "Trying one more time…", + errorLocation: "Tor Browser couldn’t locate you", + errorLocationDescription: + "Tor Browser needs to know your location in order to choose the right bridge for you. If you’d rather not share your location, %S manually instead.", + isLocationCorrect: "Are these location settings correct?", + isLocationCorrectDescription: + "Tor Browser still couldn’t connect to Tor. Please check your location settings are correct and try again, or %S instead.", + finalError: "Tor Browser still cannot connect", + + finalErrorDescription: + "Despite its best efforts, connection assist was not able to connect to Tor. Try troubleshooting your connection and adding a bridge manually instead.", + breadcrumbAssist: "Connection assist", + breadcrumbLocation: "Location settings", + breadcrumbTryBridge: "Try a bridge", + + restartTorBrowser: "Restart Tor Browser", + + torConfigure: "Configure Connection…", + + viewLog: "View logs…", + + torConnectButton: "Connect", + + cancel: "Cancel", + + torConnected: "Connected to the Tor network", + + tryAgain: "Try Again", + + yourLocation: "Your Location", + unblockInternetIn: "Unblock the Internet in", + + tryBridge: "Try a Bridge", + + automatic: "Automatic", + selectCountryRegion: "Select Country or Region", + frequentLocations: "Frequently selected locations", + otherLocations: "Other locations", + + // TorConnect error messages + offline: "Internet not reachable", + autoBootstrappingFailed: "Automatic configuration failed", + autoBootstrappingAllFailed: "None of the configurations we tried worked", + cannotDetermineCountry: "Unable to determine user country", + noSettingsForCountry: "No settings available for your location", + + // Titlebar status. + titlebarStatusName: "Tor connection", + titlebarStatusNotConnected: "Not connected", + titlebarStatusConnecting: "Connecting…", + titlebarStatusPotentiallyBlocked: "Potentially blocked", + titlebarStatusConnected: "Connected", + }; + + // Some strings were used through TorLauncherUtils. + // However, we need to use them in about:torconnect, which cannot access + // privileged code. + const bootstrapStatus = { + starting: "Starting", + conn_pt: "Connecting to bridge", + conn_done_pt: "Connected to bridge", + conn_proxy: "Connecting to proxy", + conn_done_proxy: "Connected to proxy", + conn: "Connecting to a Tor relay", + conn_done: "Connected to a Tor relay", + handshake: "Negotiating with a Tor relay", + handshake_done: "Finished negotiating with a Tor relay", + onehop_create: "Establishing an encrypted directory connection", + requesting_status: "Retrieving network status", + loading_status: "Loading network status", + loading_keys: "Loading authority certificates", + requesting_descriptors: "Requesting relay information", + loading_descriptors: "Loading relay information", + enough_dirinfo: "Finished loading relay information", + ap_conn_pt: "Building circuits: Connecting to bridge", + ap_conn_done_pt: "Building circuits: Connected to bridge", + ap_conn_proxy: "Building circuits: Connecting to proxy", + ap_conn_done_proxy: "Building circuits: Connected to proxy", + ap_conn: "Building circuits: Connecting to a Tor relay", + ap_conn_done: "Building circuits: Connected to a Tor relay", + ap_handshake: "Building circuits: Negotiating with a Tor relay", + ap_handshake_done: + "Building circuits: Finished negotiating with a Tor relay", + circuit_create: "Building circuits: Establishing a Tor circuit", + done: "Connected to the Tor network!", + }; + const bootstrapWarning = { + done: "done", + connectrefused: "connection refused", + misc: "miscellaneous", + resourcelimit: "insufficient resources", + identity: "identity mismatch", + timeout: "connection timeout", + noroute: "no route to host", + ioerror: "read/write error", + pt_missing: "missing pluggable transport", + }; + + const tsb = new TorPropertyStringBundle( + "chrome://torbutton/locale/torConnect.properties", + "torConnect." + ); + const tlsb = new TorPropertyStringBundle( + "chrome://torbutton/locale/torlauncher.properties", + "torlauncher." + ); + return { + ...tsb.getStrings(strings), + bootstrapFailedDetails: tlsb.getString( + "tor_bootstrap_failed_details", + "%1$S failed (%2$S)." + ), + bootstrapStatus: tlsb.getStrings(bootstrapStatus, "bootstrapStatus."), + bootstrapWarning: tlsb.getStrings(bootstrapWarning, "bootstrapWarning."), + }; + }, + + /* + OnionLocation + */ + onionLocation() { + const strings = { + learnMore: "Learn more…", + loadOnion: "Visit the .onion", + loadOnionAccessKey: "V", + notNow: "Not Now", + notNowAccessKey: "n", + description: + "There's a more private and secure version of this site available over the Tor network via onion services. Onion services help website publishers and their visitors defeat surveillance and censorship.", + tryThis: "Try Onion Services", + onionAvailable: ".onion available", + }; + + const tsb = new TorPropertyStringBundle( + ["chrome://torbutton/locale/onionLocation.properties"], + "onionLocation." + ); + return { + ...tsb.getStrings(strings), + learnMoreURL: "about:manual#onion-services", + // XUL popups cannot open about: URLs, but we are online when showing the notification, so just use the online version + learnMoreURLNotification: `https://tb-manual.torproject.org/${getLocale()}/onion-services/`, + }; + } /* OnionLocation */, +}; + +export const TorStrings = { + get settings() { + if (!this._settings) { + this._settings = Loader.settings(); + } + return this._settings; + }, + + get torConnect() { + if (!this._torConnect) { + this._torConnect = Loader.torConnect(); + } + return this._torConnect; + }, + + get onionLocation() { + if (!this._onionLocation) { + this._onionLocation = Loader.onionLocation(); + } + return this._onionLocation; + }, +}; diff --git a/toolkit/modules/UpdateUtils.sys.mjs b/toolkit/modules/UpdateUtils.sys.mjs index be9ce9d5402c30bf4a9712f1ce9026503c191a53..6cb58d5959326cd64c8460fa301ebf1dc4f8e897 100644 --- a/toolkit/modules/UpdateUtils.sys.mjs +++ b/toolkit/modules/UpdateUtils.sys.mjs @@ -81,7 +81,7 @@ export var UpdateUtils = { replacement = Services.appinfo.name; break; case "VERSION": - replacement = Services.appinfo.version; + replacement = AppConstants.BASE_BROWSER_VERSION; break; case "BUILD_ID": replacement = Services.appinfo.appBuildID; @@ -169,7 +169,8 @@ export var UpdateUtils = { * downloads and installs updates. This corresponds to whether or not the user * has selected "Automatically install updates" in about:preferences. * - * On Windows, this setting is shared across all profiles for the installation + * On Windows (except in Base Browser and derivatives), this setting is shared + * across all profiles for the installation * and is read asynchronously from the file. On other operating systems, this * setting is stored in a pref and is thus a per-profile setting. * @@ -185,7 +186,8 @@ export var UpdateUtils = { * updates" and "Check for updates but let you choose to install them" options * in about:preferences. * - * On Windows, this setting is shared across all profiles for the installation + * On Windows (except in Base Browser and derivatives), this setting is shared + * across all profiles for the installation * and is written asynchronously to the file. On other operating systems, this * setting is stored in a pref and is thus a per-profile setting. * @@ -257,7 +259,10 @@ export var UpdateUtils = { // setting is just to propagate it from a pref observer. This ensures that // the expected observers still get notified, even if a user manually // changes the pref value. - if (!UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED) { + if ( + AppConstants.BASE_BROWSER_UPDATE || + !UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED + ) { let initialConfig = {}; for (const [prefName, pref] of Object.entries( UpdateUtils.PER_INSTALLATION_PREFS @@ -326,7 +331,10 @@ export var UpdateUtils = { } } - if (!this.PER_INSTALLATION_PREFS_SUPPORTED) { + if ( + AppConstants.BASE_BROWSER_UPDATE || + !this.PER_INSTALLATION_PREFS_SUPPORTED + ) { // If we don't have per-installation prefs, we use regular preferences. let prefValue = prefTypeFns.getProfilePref(prefName, pref.defaultValue); return Promise.resolve(prefValue); @@ -421,7 +429,10 @@ export var UpdateUtils = { ); } - if (!this.PER_INSTALLATION_PREFS_SUPPORTED) { + if ( + AppConstants.BASE_BROWSER_UPDATE || + !this.PER_INSTALLATION_PREFS_SUPPORTED + ) { // If we don't have per-installation prefs, we use regular preferences. if (options.setDefaultOnly) { prefTypeFns.setProfileDefaultPref(prefName, value); @@ -557,14 +568,6 @@ UpdateUtils.PER_INSTALLATION_PREFS = { migrate: true, observerTopic: "auto-update-config-change", policyFn: () => { - if (!Services.policies.isAllowed("app-auto-updates-off")) { - // We aren't allowed to turn off auto-update - it is forced on. - return true; - } - if (!Services.policies.isAllowed("app-auto-updates-on")) { - // We aren't allowed to turn on auto-update - it is forced off. - return false; - } return null; }, }, diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build index 865c60d9cf2a8d701ecc19720d3d413137a9645a..6814ffebeff774a4c6ef91faaf71ef46e3e3c0af 100644 --- a/toolkit/modules/moz.build +++ b/toolkit/modules/moz.build @@ -153,7 +153,9 @@ EXTRA_JS_MODULES += [ "ActorManagerParent.sys.mjs", "AppMenuNotifications.sys.mjs", "AsyncPrefs.sys.mjs", + "Bech32Decode.sys.mjs", "BinarySearch.sys.mjs", + "BridgeDB.sys.mjs", "BrowserTelemetryUtils.sys.mjs", "BrowserUtils.sys.mjs", "CanonicalJSON.sys.mjs", @@ -164,6 +166,8 @@ EXTRA_JS_MODULES += [ "CreditCard.sys.mjs", "DateTimePickerPanel.sys.mjs", "DeferredTask.sys.mjs", + "DomainFrontedRequests.sys.mjs", + "DragDropFilter.sys.mjs", "E10SUtils.sys.mjs", "EventEmitter.sys.mjs", "FileUtils.sys.mjs", @@ -187,6 +191,7 @@ EXTRA_JS_MODULES += [ "LayoutUtils.sys.mjs", "Log.sys.mjs", "LogManager.sys.mjs", + "Moat.sys.mjs", "NewTabUtils.sys.mjs", "NLP.sys.mjs", "ObjectUtils.sys.mjs", @@ -198,6 +203,7 @@ EXTRA_JS_MODULES += [ "PrivateBrowsingUtils.sys.mjs", "ProcessType.sys.mjs", "ProfileAge.sys.mjs", + "QRCode.sys.mjs", "Region.sys.mjs", "RemotePageAccessManager.sys.mjs", "ResetProfile.sys.mjs", @@ -208,6 +214,10 @@ EXTRA_JS_MODULES += [ "Sqlite.sys.mjs", "SubDialog.sys.mjs", "Timer.sys.mjs", + "TorAndroidIntegration.sys.mjs", + "TorConnect.sys.mjs", + "TorSettings.sys.mjs", + "TorStrings.sys.mjs", "Troubleshoot.sys.mjs", "UpdateUtils.sys.mjs", "WebChannel.sys.mjs", @@ -298,6 +308,9 @@ for var in ( if CONFIG[var]: DEFINES[var] = True +if CONFIG["BASE_BROWSER_UPDATE"]: + DEFINES["BASE_BROWSER_UPDATE"] = True + JAR_MANIFESTS += ["jar.mn"] DEFINES["TOPOBJDIR"] = TOPOBJDIR diff --git a/toolkit/moz.build b/toolkit/moz.build index fa9afa2e449b8b47ad2feccf91ba6a5302f0b155..3ffe5ae1b1d60995e928432e09bf7f161487483e 100644 --- a/toolkit/moz.build +++ b/toolkit/moz.build @@ -22,6 +22,7 @@ DIRS += [ "mozapps/preferences", "profile", "themes", + "torbutton", ] if CONFIG["OS_ARCH"] == "WINNT": diff --git a/toolkit/mozapps/extensions/AddonManager.sys.mjs b/toolkit/mozapps/extensions/AddonManager.sys.mjs index 4d09048eacb8e5d81cd55c58eb058a400ace792e..ae5b46388e230263da3a40abd7f98639c4fb7224 100644 --- a/toolkit/mozapps/extensions/AddonManager.sys.mjs +++ b/toolkit/mozapps/extensions/AddonManager.sys.mjs @@ -36,6 +36,7 @@ const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; const PREF_SYS_ADDON_UPDATE_ENABLED = "extensions.systemAddon.update.enabled"; const PREF_REMOTESETTINGS_DISABLED = "extensions.remoteSettings.disabled"; const PREF_USE_REMOTE = "extensions.webextensions.remote"; +const PREF_EM_LAST_FORK_VERSION = "extensions.lastTorBrowserVersion"; const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion"; @@ -82,7 +83,10 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { AbuseReporter: "resource://gre/modules/AbuseReporter.sys.mjs", AddonRepository: "resource://gre/modules/addons/AddonRepository.sys.mjs", + GeckoViewWebExtension: "resource://gre/modules/GeckoViewWebExtension.sys.mjs", + EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", Extension: "resource://gre/modules/Extension.sys.mjs", + PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", RemoteSettings: "resource://services-settings/remote-settings.sys.mjs", TelemetryTimestamps: "resource://gre/modules/TelemetryTimestamps.sys.mjs", isGatedPermissionType: @@ -637,6 +641,24 @@ var AddonManagerInternal = { ); } + // To ensure that extension and plugin code gets a chance to run after + // each browser update, set appChanged = true when BASE_BROWSER_VERSION + // has changed even if the Mozilla app version has not changed. + const forkChanged = + AppConstants.BASE_BROWSER_VERSION !== + Services.prefs.getCharPref(PREF_EM_LAST_FORK_VERSION, ""); + if (forkChanged) { + // appChanged could be undefined (in case of a new profile) + if (appChanged === false) { + appChanged = true; + } + + Services.prefs.setCharPref( + PREF_EM_LAST_FORK_VERSION, + AppConstants.BASE_BROWSER_VERSION + ); + } + if (!MOZ_COMPATIBILITY_NIGHTLY) { PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + @@ -2327,6 +2349,24 @@ var AddonManagerInternal = { return promiseInstall; }, + async installGeckoViewWebExtension(extensionUri) { + const installId = Services.uuid.generateUUID().toString(); + let { extension } = await lazy.GeckoViewWebExtension.installWebExtension( + installId, + extensionUri + ); + if (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) { + extension = await lazy.GeckoViewWebExtension.setPrivateBrowsingAllowed( + extension.webExtensionId, + true + ); + } + await lazy.EventDispatcher.instance.sendRequest({ + type: "GeckoView:WebExtension:OnInstalled", + extension, + }); + }, + /** * Starts installation of an AddonInstall notifying the registered * web install listener of a blocked or started install. @@ -2499,6 +2539,11 @@ var AddonManagerInternal = { ); if (installAllowed) { + if (AppConstants.platform == "android") { + aInstall.cancel(); + this.installGeckoViewWebExtension(aInstall.sourceURI); + return; + } startInstall("AMO"); } else if (installPerm === Ci.nsIPermissionManager.DENY_ACTION) { // Block without prompt diff --git a/toolkit/mozapps/extensions/components.conf b/toolkit/mozapps/extensions/components.conf index 680aa57c07b053607fb634d5a20e06f3fcc27d5b..5c26a1593f1b67dbd0d3e5aa1ec54be06b6f87b6 100644 --- a/toolkit/mozapps/extensions/components.conf +++ b/toolkit/mozapps/extensions/components.conf @@ -32,14 +32,13 @@ Classes = [ 'esModule': 'resource://gre/modules/amWebAPI.sys.mjs', 'constructor': 'WebAPI', }, + # tor-browser#43132: re-enable XPI handler on Android to allow scriptless extensions installation. + # This reverts https://bugzilla.mozilla.org/show_bug.cgi?id=1610571, which made sense for generic + # GeckoView extensionless embedders and for Firefox, relying on navigator.mozAddonManager. + { + 'cid': '{7beb3ba8-6ec3-41b4-b67c-da89b8518922}', + 'contract_ids': ['@mozilla.org/uriloader/content-handler;1?type=application/x-xpinstall'], + 'esModule': 'resource://gre/modules/amContentHandler.sys.mjs', + 'constructor': 'amContentHandler', + }, ] - -if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android': - Classes += [ - { - 'cid': '{7beb3ba8-6ec3-41b4-b67c-da89b8518922}', - 'contract_ids': ['@mozilla.org/uriloader/content-handler;1?type=application/x-xpinstall'], - 'esModule': 'resource://gre/modules/amContentHandler.sys.mjs', - 'constructor': 'amContentHandler', - }, - ] diff --git a/toolkit/mozapps/extensions/content/aboutaddons.html b/toolkit/mozapps/extensions/content/aboutaddons.html index be4cadae28eb8f9b3e8bd1b9024148850cd004f8..650bea84d57399242deae99a04faf3b87755ef68 100644 --- a/toolkit/mozapps/extensions/content/aboutaddons.html +++ b/toolkit/mozapps/extensions/content/aboutaddons.html @@ -31,6 +31,8 @@ <link rel="localization" href="branding/brand.ftl" /> <link rel="localization" href="toolkit/about/aboutAddons.ftl" /> + <link rel="localization" href="toolkit/global/base-browser.ftl" /> + <!-- Defer scripts so all the templates are loaded by the time they run. --> <script defer @@ -357,7 +359,7 @@ is="moz-support-link" support-page="add-on-badges" utm-content="promoted-addon-badge" - data-l10n-id="addon-badge-recommended2" + data-basebrowser-l10n-fixup="basebrowser-addon-badge-recommended" hidden > </a> @@ -375,7 +377,7 @@ is="moz-support-link" support-page="add-on-badges" utm-content="promoted-addon-badge" - data-l10n-id="addon-badge-verified2" + data-basebrowser-l10n-fixup="basebrowser-addon-badge-verified" hidden > </a> @@ -508,6 +510,32 @@ <div class="addon-detail-sitepermissions"> <addon-sitepermissions-list></addon-sitepermissions-list> </div> + <!-- Add an option to show the NoScript toolbar button, if this is the + - NoScript addon. See tor-browser#41581. --> + <div + class="addon-detail-row addon-detail-row-noscript-visibility" + role="radiogroup" + hidden="hidden" + > + <span + class="addon-noscript-visibility-label" + data-l10n-id="basebrowser-addon-noscript-visibility-label" + ></span> + <div class="addon-detail-actions"> + <label class="radio-container-with-text"> + <input type="radio" name="noscript-visibility" value="show" /> + <span + data-l10n-id="basebrowser-addon-noscript-visibility-show" + ></span> + </label> + <label class="radio-container-with-text"> + <input type="radio" name="noscript-visibility" value="hide" /> + <span + data-l10n-id="basebrowser-addon-noscript-visibility-hide" + ></span> + </label> + </div> + </div> <div class="addon-detail-row addon-detail-row-updates" role="group" diff --git a/toolkit/mozapps/extensions/content/aboutaddons.js b/toolkit/mozapps/extensions/content/aboutaddons.js index 670ad0f01f69566408398663d32c40b61b736226..22a716495db4b9f113a99d6715e11abb687f1ea9 100644 --- a/toolkit/mozapps/extensions/content/aboutaddons.js +++ b/toolkit/mozapps/extensions/content/aboutaddons.js @@ -1532,8 +1532,11 @@ class AddonOptions extends HTMLElement { el.disabled = false; el.hidden = false; document.l10n.setAttributes(el, "remove-addon-button"); - } else if (addon.isBuiltin) { - // Likely the built-in themes, can't be removed, that's fine. + // eslint-disable-next-line max-len + // eslint-disable-next-line no-constant-condition, no-constant-binary-expression + } else if (true || addon.isBuiltin) { + // Just hide the uninstall button for any "special" add-on + // which can't be removed (tor-browser#41834) el.hidden = true; } else { // Likely sideloaded, mention that it can't be removed with a link. @@ -2043,6 +2046,8 @@ class AddonSitePermissionsList extends HTMLElement { } customElements.define("addon-sitepermissions-list", AddonSitePermissionsList); +const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript"; + class AddonDetails extends HTMLElement { connectedCallback() { if (!this.children.length) { @@ -2050,12 +2055,61 @@ class AddonDetails extends HTMLElement { } this.deck.addEventListener("view-changed", this); this.descriptionShowMoreButton.addEventListener("click", this); + + // If this is for the NoScript extension, we listen for changes in the + // visibility of its toolbar button. + // See tor-browser#41581. + // NOTE: The addon should be set before being connected, so isNoScript will + // return a correct value. + if (this.isNoScript && !this._noScriptVisibilityObserver) { + this._noScriptVisibilityObserver = () => this.updateNoScriptVisibility(); + Services.prefs.addObserver( + HIDE_NO_SCRIPT_PREF, + this._noScriptVisibilityObserver + ); + } } disconnectedCallback() { this.inlineOptions.destroyBrowser(); this.deck.removeEventListener("view-changed", this); this.descriptionShowMoreButton.removeEventListener("click", this); + + if (this._noScriptVisibilityObserver) { + Services.prefs.removeObserver( + HIDE_NO_SCRIPT_PREF, + this._noScriptVisibilityObserver + ); + // Clear in case this is called again, or if connectedCallback is called. + delete this._noScriptVisibilityObserver; + } + } + + /** + * Whether this is a description for the NoScript extension. + * + * @type {boolean} + */ + get isNoScript() { + return this.addon?.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}"; + } + + /** + * Update the shown visibility value for the NoScript extension's toolbar + * button. + */ + updateNoScriptVisibility() { + if (!this.isNoScript) { + return; + } + const visibility = Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true) + ? "hide" + : "show"; + for (const input of this.querySelectorAll( + ".addon-detail-row-noscript-visibility input" + )) { + input.checked = input.value === visibility; + } } handleEvent(e) { @@ -2268,6 +2322,27 @@ class AddonDetails extends HTMLElement { "upgrade" ); + // If this is the NoScript extension, we want to show an option to change + // the visibility of its toolbar button. + // See tor-browser#41581. + const visibilityRow = this.querySelector( + ".addon-detail-row-noscript-visibility" + ); + visibilityRow.hidden = !this.isNoScript; + if (this.isNoScript) { + // Set up the aria-label for the role="radiogroup". + const visibilityLabel = visibilityRow.querySelector( + ".addon-noscript-visibility-label" + ); + visibilityLabel.id = ExtensionCommon.makeWidgetId( + `${addon.id}-noscript-visibility-label` + ); + visibilityRow.setAttribute("aria-labelledby", visibilityLabel.id); + + // Set the initial displayed value. + this.updateNoScriptVisibility(); + } + if (addon.type != "extension") { // Don't show any private browsing related section for non-extension // addon types, because not relevant or they are either always allowed @@ -2652,6 +2727,13 @@ class AddonCard extends HTMLElement { addon.quarantineIgnoredByUser = e.target.value == "1"; break; } + case "noscript-visibility": { + // Update the NoScript toolbar button visibility. + // See tor-browser#41581. + const hide = e.target.value !== "show"; + Services.prefs.setBoolPref(HIDE_NO_SCRIPT_PREF, hide); + break; + } } } else if (e.type == "mousedown") { // Open panel on mousedown when the mouse is used. diff --git a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs index 17219a88b42b0954f7bd7f7ea7ae8dcad55cc77c..0ab828f78b89489c14f44bca7f494ece210ed1eb 100644 --- a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs +++ b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs @@ -897,6 +897,15 @@ export class AddonInternal { } } + // Bug 41598: prevent NoScript from being uninstalled/disabled + if (this.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}") { + permissions &= ~( + lazy.AddonManager.PERM_CAN_UNINSTALL | + lazy.AddonManager.PERM_CAN_DISABLE | + lazy.AddonManager.PERM_CAN_CHANGE_PRIVATEBROWSING_ACCESS + ); + } + return permissions; } diff --git a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs index 2b6f4cca81be72829ac9557285879066f543ff2d..549d3f4c7dc2bed04c2ea579be844a2be5ac5f78 100644 --- a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs +++ b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs @@ -4469,6 +4469,14 @@ export var XPIInstall = { return false; } + // tor-browser#43132: short-circuit permission check on Android scriptless install from AMO + if ( + AppConstants.platform == "android" && + uri.prePath == "https://addons.mozilla.org" + ) { + return true; + } + let requireWhitelist = Services.prefs.getBoolPref( PREF_XPI_WHITELIST_REQUIRED, true diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs index 259ed226fbf5ee5d01bc4dbc7d0daf7e9016991c..b812ac1318e66a5640ba23ae189b14a522221eec 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs +++ b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs @@ -468,7 +468,7 @@ class XPIState { // Builds prior to be 1512436 did not include the rootURI property. // If we're updating from such a build, add that property now. - if (!("rootURI" in this) && this.file) { + if (this.file) { this.rootURI = getURIForResourceInFile(this.file, "").spec; } @@ -481,7 +481,10 @@ class XPIState { saved.currentModifiedTime != this.lastModifiedTime ) { this.lastModifiedTime = saved.currentModifiedTime; - } else if (saved.currentModifiedTime === null) { + } else if ( + saved.currentModifiedTime === null && + (!this.file || !this.file.exists()) + ) { this.missing = true; } } @@ -1452,6 +1455,7 @@ var XPIStates = { if (shouldRestoreLocationData && oldState[loc.name]) { loc.restore(oldState[loc.name]); + changed = changed || loc.path != oldState[loc.name].path; } changed = changed || loc.changed; diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index 1af7240e6a7ca8305d0da4fe69780fd974c3cd5a..70b585a9ff1633681265bb9aca0a35d93531cd28 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -39,6 +39,7 @@ var PREF_CHECK_COMPATIBILITY; var channel = Services.prefs.getCharPref("app.update.channel", "default"); if ( channel != "aurora" && + channel != "alpha" && channel != "beta" && channel != "release" && channel != "esr" diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index 2f26d940f04a540f54df79228fd934cfce3202cb..eb36b94eb999d76037535683a9e39f8bbca375b1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -344,6 +344,7 @@ function isNightlyChannel() { return ( channel != "aurora" && + channel != "alpha" && channel != "beta" && channel != "release" && channel != "esr" diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs index f7a6f11d510b895869673f842f29d9de9e433766..a5bd1eee96e1b54ee532b3318a849a04b661c5e3 100644 --- a/toolkit/mozapps/update/UpdateService.sys.mjs +++ b/toolkit/mozapps/update/UpdateService.sys.mjs @@ -22,6 +22,7 @@ ChromeUtils.defineESModuleGetters(lazy, { AddonManager: "resource://gre/modules/AddonManager.sys.mjs", AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs", DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs", + TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", UpdateLog: "resource://gre/modules/UpdateLog.sys.mjs", UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs", WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs", @@ -231,6 +232,7 @@ const SERVICE_ERRORS = [ // Custom update error codes const BACKGROUNDCHECK_MULTIPLE_FAILURES = 110; const NETWORK_ERROR_OFFLINE = 111; +const PROXY_SERVER_CONNECTION_REFUSED = 2152398920; // Error codes should be < 1000. Errors above 1000 represent http status codes const HTTP_ERROR_OFFSET = 1000; @@ -344,6 +346,15 @@ ChromeUtils.defineLazyGetter( } ); +async function _shouldRegisterBootstrapObserver() { + try { + const provider = await lazy.TorProviderBuilder.build(); + return !provider.isBootstrapDone && provider.ownsTorDaemon; + } catch { + return false; + } +} + /** * Changes `nsIApplicationUpdateService.currentState` and causes * `nsIApplicationUpdateService.stateTransition` to resolve. @@ -669,6 +680,11 @@ function areDirectoryEntriesWriteable(aDir) { * @return true if elevation is required, false otherwise */ function getElevationRequired() { + if (AppConstants.BASE_BROWSER_UPDATE) { + // To avoid potential security holes associated with running the updater + // process with elevated privileges, Tor Browser does not support elevation. + return false; + } if (AppConstants.platform != "macosx") { return false; } @@ -788,7 +804,7 @@ function getCanApplyUpdates() { return false; } - if (AppConstants.platform == "macosx") { + if (!AppConstants.BASE_BROWSER_UPDATE && AppConstants.platform == "macosx") { LOG( "getCanApplyUpdates - bypass the write since elevation can be used " + "on Mac OS X" @@ -796,7 +812,7 @@ function getCanApplyUpdates() { return true; } - if (shouldUseService()) { + if (!AppConstants.BASE_BROWSER_UPDATE && shouldUseService()) { LOG( "getCanApplyUpdates - bypass the write checks because the Windows " + "Maintenance Service can be used" @@ -1677,7 +1693,11 @@ function handleUpdateFailure(update) { ); cancelations++; Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS, cancelations); - if (AppConstants.platform == "macosx") { + if (AppConstants.platform == "macosx" && AppConstants.BASE_BROWSER_UPDATE) { + cleanupActiveUpdates(); + update.statusText = + lazy.gUpdateBundle.GetStringFromName("elevationFailure"); + } else if (AppConstants.platform == "macosx") { let osxCancelations = Services.prefs.getIntPref( PREF_APP_UPDATE_CANCELATIONS_OSX, 0 @@ -1942,6 +1962,15 @@ function updateIsAtLeastAsOldAs(update, version, buildID) { ); } +/** + * This returns the current version of the browser to use to check updates. + */ +function getCompatVersion() { + return AppConstants.BASE_BROWSER_VERSION + ? AppConstants.BASE_BROWSER_VERSION + : Services.appinfo.version; +} + /** * This returns true if the passed update is the same version or older than * currently installed Firefox version. @@ -1949,7 +1978,7 @@ function updateIsAtLeastAsOldAs(update, version, buildID) { function updateIsAtLeastAsOldAsCurrentVersion(update) { return updateIsAtLeastAsOldAs( update, - Services.appinfo.version, + getCompatVersion(), Services.appinfo.appBuildID ); } @@ -2343,7 +2372,34 @@ class Update { this._patches.push(patch); } - if (!this._patches.length && !update.hasAttribute("unsupported")) { + if (update.hasAttribute("unsupported")) { + this.unsupported = "true" == update.getAttribute("unsupported"); + } else if (update.hasAttribute("minSupportedOSVersion")) { + let minOSVersion = update.getAttribute("minSupportedOSVersion"); + try { + let osVersion = Services.sysinfo.getProperty("version"); + this.unsupported = Services.vc.compare(osVersion, minOSVersion) < 0; + } catch (e) {} + } + if ( + !this.unsupported && + update.hasAttribute("minSupportedInstructionSet") + ) { + let minInstructionSet = update.getAttribute("minSupportedInstructionSet"); + if ( + ["MMX", "SSE", "SSE2", "SSE3", "SSE4A", "SSE4_1", "SSE4_2"].includes( + minInstructionSet + ) + ) { + try { + this.unsupported = !Services.sysinfo.getProperty( + "has" + minInstructionSet + ); + } catch (e) {} + } + } + + if (!this._patches.length && !this.unsupported) { throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE); } @@ -2381,9 +2437,7 @@ class Update { if (!isNaN(attr.value)) { this.promptWaitTime = parseInt(attr.value); } - } else if (attr.name == "unsupported") { - this.unsupported = attr.value == "true"; - } else { + } else if (attr.name != "unsupported") { switch (attr.name) { case "appVersion": case "buildID": @@ -2409,7 +2463,7 @@ class Update { } if (!this.previousAppVersion) { - this.previousAppVersion = Services.appinfo.version; + this.previousAppVersion = getCompatVersion(); } if (!this.elevationFailure) { @@ -2739,6 +2793,9 @@ export class UpdateService { case "network:offline-status-changed": await this._offlineStatusChanged(data); break; + case "torconnect:bootstrap-complete": + this._bootstrapComplete(); + break; case "quit-application": Services.obs.removeObserver(this, topic); @@ -3247,6 +3304,35 @@ export class UpdateService { await this._attemptResume(); } + _registerBootstrapObserver() { + if (this._registeredBootstrapObserver) { + LOG( + "UpdateService:_registerBootstrapObserver - observer already registered" + ); + return; + } + + LOG( + "UpdateService:_registerBootstrapObserver - waiting for tor bootstrap " + + "to be complete, then forcing another check" + ); + + Services.obs.addObserver(this, "torconnect:bootstrap-complete"); + this._registeredBootstrapObserver = true; + } + + _bootstrapComplete() { + Services.obs.removeObserver(this, "torconnect:bootstrap-complete"); + this._registeredBootstrapObserver = false; + + LOG( + "UpdateService:_bootstrapComplete - bootstrapping complete, forcing " + + "another background check" + ); + + this._attemptResume(); + } + /** * See nsIUpdateService.idl */ @@ -3280,6 +3366,14 @@ export class UpdateService { AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_OFFLINE); } return; + } else if ( + update.errorCode === PROXY_SERVER_CONNECTION_REFUSED && + (await _shouldRegisterBootstrapObserver()) + ) { + // Register boostrap observer to try again, but only when we own the + // tor process. + this._registerBootstrapObserver(); + return; } // Send the error code to telemetry @@ -4126,7 +4220,7 @@ export class UpdateService { "UpdateService:downloadUpdate - Skipping download of update since " + "it is for an earlier or same application version and build ID.\n" + "current application version: " + - Services.appinfo.version + + getCompatVersion() + "\n" + "update application version : " + update.appVersion + @@ -5064,7 +5158,7 @@ export class CheckerService { } #getCanMigrate() { - if (AppConstants.platform != "win") { + if (AppConstants.platform != "win" || AppConstants.BASE_BROWSER_UPDATE) { return false; } @@ -6528,6 +6622,7 @@ class Downloader { var state = this._patch.state; var shouldShowPrompt = false; var shouldRegisterOnlineObserver = false; + var shouldRegisterBootstrapObserver = false; var shouldRetrySoon = false; var deleteActiveUpdate = false; let migratedToReadyUpdate = false; @@ -6658,7 +6753,23 @@ class Downloader { ); shouldRegisterOnlineObserver = true; deleteActiveUpdate = false; - + } else if ( + status === PROXY_SERVER_CONNECTION_REFUSED && + (await _shouldRegisterBootstrapObserver()) + ) { + // Register a bootstrap observer to try again. + // The bootstrap observer will continue the incremental download by + // calling downloadUpdate on the active update which continues + // downloading the file from where it was. + LOG( + "Downloader:onStopRequest - not bootstrapped, register bootstrap observer: true" + ); + AUSTLMY.pingDownloadCode( + this.isCompleteUpdate, + AUSTLMY.DWNLD_RETRY_OFFLINE + ); + shouldRegisterBootstrapObserver = true; + deleteActiveUpdate = false; // Each of NS_ERROR_NET_TIMEOUT, ERROR_CONNECTION_REFUSED, // NS_ERROR_NET_RESET and NS_ERROR_DOCUMENT_NOT_CACHED can be returned // when disconnecting the internet while a download of a MAR is in @@ -6781,7 +6892,11 @@ class Downloader { // Only notify listeners about the stopped state if we // aren't handling an internal retry. - if (!shouldRetrySoon && !shouldRegisterOnlineObserver) { + if ( + !shouldRetrySoon && + !shouldRegisterOnlineObserver && + !shouldRegisterBootstrapObserver + ) { this.updateService.forEachDownloadListener(listener => { listener.onStopRequest(request, status); }); @@ -6980,6 +7095,9 @@ class Downloader { if (shouldRegisterOnlineObserver) { LOG("Downloader:onStopRequest - Registering online observer"); this.updateService._registerOnlineObserver(); + } else if (shouldRegisterBootstrapObserver) { + LOG("Downloader:onStopRequest - Registering bootstrap observer"); + this.updateService._registerBootstrapObserver(); } else if (shouldRetrySoon) { LOG("Downloader:onStopRequest - Retrying soon"); this.updateService._consecutiveSocketErrors++; diff --git a/toolkit/mozapps/update/UpdateServiceStub.sys.mjs b/toolkit/mozapps/update/UpdateServiceStub.sys.mjs index f0952d8c80d0f48d3d12048ef117fbc78e498ed5..b3e8716193a0c925afb67227385d325990daa6e0 100644 --- a/toolkit/mozapps/update/UpdateServiceStub.sys.mjs +++ b/toolkit/mozapps/update/UpdateServiceStub.sys.mjs @@ -93,10 +93,15 @@ export class UpdateServiceStub { #initOnlyStub(updateDir) { // We may need to migrate update data + // In Base Browser and derivatives, we skip this because we do not use an + // update agent and we do not want to store any data outside of the browser + // installation directory. + // For more info, see https://bugzilla.mozilla.org/show_bug.cgi?id=1458314 let prefUpdateDirMigrated = PREF_PREFIX_UPDATE_DIR_MIGRATED + updateDir.leafName; if ( AppConstants.platform == "win" && + !AppConstants.BASE_BROWSER_UPDATE && !Services.prefs.getBoolPref(prefUpdateDirMigrated, false) ) { Services.prefs.setBoolPref(prefUpdateDirMigrated, true); diff --git a/toolkit/mozapps/update/common/updatehelper.cpp b/toolkit/mozapps/update/common/updatehelper.cpp index c62120414223f35ea4741689fa66e5f950fe8abf..e29ec7221b27a168f9586485c58553de2302bcaa 100644 --- a/toolkit/mozapps/update/common/updatehelper.cpp +++ b/toolkit/mozapps/update/common/updatehelper.cpp @@ -67,6 +67,13 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, * @return TRUE if successful */ BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf) { +#ifdef BASE_BROWSER_UPDATE + // This function is used to support the maintenance service and elevated + // updates and is therefore not called by Base Browser's updater. We stub + // it out to avoid any chance that the Base Browser updater will create + // files under C:\Program Files (x86)\ or a similar location. + return FALSE; +#else PWSTR progFilesX86; if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_CREATE, nullptr, &progFilesX86))) { @@ -100,6 +107,7 @@ BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf) { } return TRUE; +#endif } /** diff --git a/toolkit/mozapps/update/updater/launchchild_osx.mm b/toolkit/mozapps/update/updater/launchchild_osx.mm index 6f91571ef22c3cecb7ba591a4d835ff70f4e899e..9663a7be11d208a4a11ceb8d90b1a004077a8cb6 100644 --- a/toolkit/mozapps/update/updater/launchchild_osx.mm +++ b/toolkit/mozapps/update/updater/launchchild_osx.mm @@ -377,6 +377,7 @@ bool ObtainUpdaterArguments(int* aArgc, char*** aArgv, @end +#ifndef BASE_BROWSER_UPDATE bool ServeElevatedUpdate(int aArgc, const char** aArgv, const char* aMARChannelID) { MacAutoreleasePool pool; @@ -395,6 +396,7 @@ bool ServeElevatedUpdate(int aArgc, const char** aArgv, [updater release]; return didSucceed; } +#endif bool IsOwnedByGroupAdmin(const char* aAppBundle) { MacAutoreleasePool pool; diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index 9620dde22ce79b4b00aaff73302773613a9f855a..58aff62f34705d26768ab6bf74b0e5f7cf058265 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -54,7 +54,7 @@ xpcshell_cert.script = "gen_cert_header.py:create_header" dep1_cert.script = "gen_cert_header.py:create_header" dep2_cert.script = "gen_cert_header.py:create_header" -if CONFIG["MOZ_UPDATE_CHANNEL"] in ("beta", "release", "esr"): +if CONFIG["MOZ_UPDATE_CHANNEL"] in ("alpha", "beta", "release", "esr"): primary_cert.inputs += ["release_primary.der"] secondary_cert.inputs += ["release_secondary.der"] elif CONFIG["MOZ_UPDATE_CHANNEL"] in ( diff --git a/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der b/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der index 44fd95dcff89aab3540ebc1922dd7b809af7d837..d579cf801e1a3ef89e743a2cfa13ccdd1375a39d 100644 Binary files a/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der and b/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der differ diff --git a/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der b/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der index 90f8e6e82c63a442288e1ac97d6c0824fda59d3c..7cbfa77d06e7a30ff9ba8be81bc483aa21f48c02 100644 Binary files a/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der and b/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der differ diff --git a/toolkit/mozapps/update/updater/release_primary.der b/toolkit/mozapps/update/updater/release_primary.der index 1d94f88ad73b0f05a06417ddb2482b6658177334..0103a171de88ab508c0110510e8dc99ff649b80c 100644 Binary files a/toolkit/mozapps/update/updater/release_primary.der and b/toolkit/mozapps/update/updater/release_primary.der differ diff --git a/toolkit/mozapps/update/updater/release_secondary.der b/toolkit/mozapps/update/updater/release_secondary.der index 474706c4b73c95ee15aff7a94582f26853d883cd..fcee3944e9b7ad5b35f766296054f01c68cdbb73 100644 Binary files a/toolkit/mozapps/update/updater/release_secondary.der and b/toolkit/mozapps/update/updater/release_secondary.der differ diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index 89fa838717652ae5e2ee3fc300e13fd74dd6aadc..5dbb726f9a48765eeb382d55434c5a0293395713 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -16,7 +16,7 @@ * updatev3.manifest * ----------------- * method = "add" | "add-if" | "add-if-not" | "patch" | "patch-if" | - * "remove" | "rmdir" | "rmrfdir" | type + * "remove" | "rmdir" | "rmrfdir" | "addsymlink" | type * * 'add-if-not' adds a file if it doesn't exist. * @@ -78,8 +78,10 @@ void LaunchMacApp(int argc, const char** argv); void LaunchMacPostProcess(const char* aAppBundle); bool ObtainUpdaterArguments(int* aArgc, char*** aArgv, MARChannelStringTable* aMARStrings); +# ifndef BASE_BROWSER_UPDATE bool ServeElevatedUpdate(int aArgc, const char** aArgv, const char* aMARChannelID); +# endif void SetGroupOwnershipAndPermissions(const char* aAppBundle); bool PerformInstallationFromDMG(int argc, char** argv); struct UpdateServerThreadArgs { @@ -511,7 +513,8 @@ static const NS_tchar* get_relative_path(const NS_tchar* fullpath) { * Whether the path is a directory path. Defaults to false. * @return valid filesystem path or nullptr if the path checks fail. */ -static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false) { +static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false, + bool islinktarget = false) { NS_tchar* path = mstrtok(kQuote, line); if (!path) { LOG(("get_valid_path: unable to determine path: " LOG_S, *line)); @@ -547,10 +550,12 @@ static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false) { path[NS_tstrlen(path) - 1] = NS_T('\0'); } - // Don't allow relative paths that resolve to a parent directory. - if (NS_tstrstr(path, NS_T("..")) != nullptr) { - LOG(("get_valid_path: paths must not contain '..': " LOG_S, path)); - return nullptr; + if (!islinktarget) { + // Don't allow relative paths that resolve to a parent directory. + if (NS_tstrstr(path, NS_T("..")) != nullptr) { + LOG(("get_valid_path: paths must not contain '..': " LOG_S, path)); + return nullptr; + } } return path; @@ -590,7 +595,7 @@ static void ensure_write_permissions(const NS_tchar* path) { (void)_wchmod(path, _S_IREAD | _S_IWRITE); #else struct stat fs; - if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) { + if (!lstat(path, &fs) && !S_ISLNK(fs.st_mode) && !(fs.st_mode & S_IWUSR)) { (void)chmod(path, fs.st_mode | S_IWUSR); } #endif @@ -777,11 +782,9 @@ static int ensure_copy(const NS_tchar* path, const NS_tchar* dest) { return READ_ERROR; } -# ifdef XP_UNIX if (S_ISLNK(ss.st_mode)) { return ensure_copy_symlink(path, dest); } -# endif AutoFile infile(ensure_open(path, NS_T("rb"), ss.st_mode)); if (!infile) { @@ -868,12 +871,19 @@ static int ensure_copy_recursive(const NS_tchar* path, const NS_tchar* dest, return READ_ERROR; } -#ifdef XP_UNIX +#ifndef XP_WIN if (S_ISLNK(sInfo.st_mode)) { return ensure_copy_symlink(path, dest); } #endif +#ifdef XP_UNIX + // Ignore Unix domain sockets. See #20691. + if (S_ISSOCK(sInfo.st_mode)) { + return 0; + } +#endif + if (!S_ISDIR(sInfo.st_mode)) { return ensure_copy(path, dest); } @@ -930,7 +940,7 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath, } struct NS_tstat_t spathInfo; - rv = NS_tstat(spath, &spathInfo); + rv = NS_tlstat(spath, &spathInfo); // Get info about file or symlink. if (rv) { LOG(("rename_file: failed to read file status info: " LOG_S ", " "err: %d", @@ -938,7 +948,12 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath, return READ_ERROR; } - if (!S_ISREG(spathInfo.st_mode)) { +#ifdef XP_WIN + if (!S_ISREG(spathInfo.st_mode)) +#else + if (!S_ISREG(spathInfo.st_mode) && !S_ISLNK(spathInfo.st_mode)) +#endif + { if (allowDirs && !S_ISDIR(spathInfo.st_mode)) { LOG(("rename_file: path present, but not a file: " LOG_S ", err: %d", spath, errno)); @@ -947,7 +962,12 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath, LOG(("rename_file: proceeding to rename the directory")); } - if (!NS_taccess(dpath, F_OK)) { +#ifdef XP_WIN + if (!NS_taccess(dpath, F_OK)) +#else + if (!S_ISLNK(spathInfo.st_mode) && !NS_taccess(dpath, F_OK)) +#endif + { if (ensure_remove(dpath)) { LOG( ("rename_file: destination file exists and could not be " @@ -967,7 +987,7 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath, return OK; } -#ifdef XP_WIN +#if defined(XP_WIN) && !defined(BASE_BROWSER_UPDATE) // Remove the directory pointed to by path and all of its files and // sub-directories. If a file is in use move it to the tobedeleted directory // and attempt to schedule removal of the file on reboot @@ -1066,7 +1086,19 @@ static int backup_restore(const NS_tchar* path, const NS_tchar* relPath) { NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]), NS_T("%s") BACKUP_EXT, relPath); - if (NS_taccess(backup, F_OK)) { + bool isLink = false; +#ifndef XP_WIN + struct stat linkInfo; + int rv = lstat(backup, &linkInfo); + if (rv) { + LOG(("backup_restore: cannot get info for backup file: " LOG_S ", err: %d", + relBackup, errno)); + return OK; + } + isLink = S_ISLNK(linkInfo.st_mode); +#endif + + if (!isLink && NS_taccess(backup, F_OK)) { LOG(("backup_restore: backup file doesn't exist: " LOG_S, relBackup)); return OK; } @@ -1084,8 +1116,18 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) { NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]), NS_T("%s") BACKUP_EXT, relPath); + bool isLink = false; +#ifndef XP_WIN + struct stat linkInfo; + int rv2 = lstat(backup, &linkInfo); + if (rv2) { + return OK; // File does not exist; nothing to do. + } + isLink = S_ISLNK(linkInfo.st_mode); +#endif + // Nothing to discard - if (NS_taccess(backup, F_OK)) { + if (!isLink && NS_taccess(backup, F_OK)) { return OK; } @@ -1100,6 +1142,8 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) { relBackup, relPath)); return WRITE_ERROR_DELETE_BACKUP; } + +# if !defined(BASE_BROWSER_UPDATE) // The MoveFileEx call to remove the file on OS reboot will fail if the // process doesn't have write access to the HKEY_LOCAL_MACHINE registry key // but this is ok since the installer / uninstaller will delete the @@ -1116,6 +1160,7 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) { "file: " LOG_S, relPath)); } +# endif } #else if (rv) { @@ -1170,7 +1215,7 @@ class Action { class RemoveFile : public Action { public: - RemoveFile() : mSkip(0) {} + RemoveFile() : mSkip(0), mIsLink(0) {} int Parse(NS_tchar* line) override; int Prepare() override; @@ -1181,6 +1226,7 @@ class RemoveFile : public Action { mozilla::UniquePtr<NS_tchar[]> mFile; mozilla::UniquePtr<NS_tchar[]> mRelPath; int mSkip; + int mIsLink; }; int RemoveFile::Parse(NS_tchar* line) { @@ -1203,28 +1249,39 @@ int RemoveFile::Parse(NS_tchar* line) { } int RemoveFile::Prepare() { - // Skip the file if it already doesn't exist. - int rv = NS_taccess(mFile.get(), F_OK); - if (rv) { - mSkip = 1; - mProgressCost = 0; - return OK; + int rv; +#ifndef XP_WIN + struct stat linkInfo; + rv = lstat(mFile.get(), &linkInfo); + mIsLink = ((0 == rv) && S_ISLNK(linkInfo.st_mode)); +#endif + + if (!mIsLink) { + // Skip the file if it already doesn't exist. + rv = NS_taccess(mFile.get(), F_OK); + if (rv) { + mSkip = 1; + mProgressCost = 0; + return OK; + } } LOG(("PREPARE REMOVEFILE " LOG_S, mRelPath.get())); - // Make sure that we're actually a file... - struct NS_tstat_t fileInfo; - rv = NS_tstat(mFile.get(), &fileInfo); - if (rv) { - LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(), - errno)); - return READ_ERROR; - } + if (!mIsLink) { + // Make sure that we're actually a file... + struct NS_tstat_t fileInfo; + rv = NS_tstat(mFile.get(), &fileInfo); + if (rv) { + LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(), + errno)); + return READ_ERROR; + } - if (!S_ISREG(fileInfo.st_mode)) { - LOG(("path present, but not a file: " LOG_S, mFile.get())); - return DELETE_ERROR_EXPECTED_FILE; + if (!S_ISREG(fileInfo.st_mode)) { + LOG(("path present, but not a file: " LOG_S, mFile.get())); + return DELETE_ERROR_EXPECTED_FILE; + } } NS_tchar* slash = (NS_tchar*)NS_tstrrchr(mFile.get(), NS_T('/')); @@ -1976,6 +2033,92 @@ void PatchIfFile::Finish(int status) { PatchFile::Finish(status); } +#ifndef XP_WIN +class AddSymlink : public Action { + public: + AddSymlink() : mAdded(false) {} + + virtual int Parse(NS_tchar* line); + virtual int Prepare(); + virtual int Execute(); + virtual void Finish(int status); + + private: + mozilla::UniquePtr<NS_tchar[]> mLinkPath; + mozilla::UniquePtr<NS_tchar[]> mRelPath; + mozilla::UniquePtr<NS_tchar[]> mTarget; + bool mAdded; +}; + +int AddSymlink::Parse(NS_tchar* line) { + // format "<linkname>" "target" + + NS_tchar* validPath = get_valid_path(&line); + if (!validPath) return PARSE_ERROR; + + mRelPath = mozilla::MakeUnique<NS_tchar[]>(MAXPATHLEN); + NS_tstrcpy(mRelPath.get(), validPath); + mLinkPath.reset(get_full_path(validPath)); + if (!mLinkPath) { + return PARSE_ERROR; + } + + // consume whitespace between args + NS_tchar* q = mstrtok(kQuote, &line); + if (!q) return PARSE_ERROR; + + validPath = get_valid_path(&line, false, true); + if (!validPath) return PARSE_ERROR; + + mTarget = mozilla::MakeUnique<NS_tchar[]>(MAXPATHLEN); + NS_tstrcpy(mTarget.get(), validPath); + + return OK; +} + +int AddSymlink::Prepare() { + LOG(("PREPARE ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(), + mTarget.get())); + + return OK; +} + +int AddSymlink::Execute() { + LOG(("EXECUTE ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(), + mTarget.get())); + + // First make sure that we can actually get rid of any existing file or link. + struct stat linkInfo; + int rv = lstat(mLinkPath.get(), &linkInfo); + if ((0 == rv) && !S_ISLNK(linkInfo.st_mode)) { + rv = NS_taccess(mLinkPath.get(), F_OK); + } + if (rv == 0) { + rv = backup_create(mLinkPath.get()); + if (rv) return rv; + } else { + rv = ensure_parent_dir(mLinkPath.get()); + if (rv) return rv; + } + + // Create the link. + rv = symlink(mTarget.get(), mLinkPath.get()); + if (!rv) { + mAdded = true; + } + + return rv; +} + +void AddSymlink::Finish(int status) { + LOG(("FINISH ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(), mTarget.get())); + // When there is an update failure and a link has been added it is removed + // here since there might not be a backup to replace it. + if (status && mAdded) NS_tremove(mLinkPath.get()); + backup_finish(mLinkPath.get(), mRelPath.get(), status); +} +#endif + //----------------------------------------------------------------------------- #ifdef XP_WIN @@ -2488,11 +2631,11 @@ static bool IsServiceSpecificErrorCode(int errorCode) { static int CopyInstallDirToDestDir() { // These files should not be copied over to the updated app #ifdef XP_WIN -# define SKIPLIST_COUNT 3 +# define SKIPLIST_COUNT 5 #elif XP_MACOSX # define SKIPLIST_COUNT 0 #else -# define SKIPLIST_COUNT 2 +# define SKIPLIST_COUNT 4 #endif copy_recursive_skiplist<SKIPLIST_COUNT> skiplist; #ifndef XP_MACOSX @@ -2503,6 +2646,21 @@ static int CopyInstallDirToDestDir() { # endif #endif + // Remove the following block if we move the profile outside the Browser + // directory. +#if defined(BASE_BROWSER_UPDATE) && !defined(XP_MACOSX) +# ifdef XP_WIN + skiplist.append(SKIPLIST_COUNT - 2, gInstallDirPath, + NS_T("TorBrowser/Data/Browser/profile.default/parent.lock")); +# else + skiplist.append(SKIPLIST_COUNT - 2, gInstallDirPath, + NS_T("TorBrowser/Data/Browser/profile.default/.parentlock")); +# endif + + skiplist.append(SKIPLIST_COUNT - 1, gInstallDirPath, + NS_T("TorBrowser/Data/Tor/lock")); +#endif + return ensure_copy_recursive(gInstallDirPath, gWorkingDirPath, skiplist); } @@ -2640,7 +2798,9 @@ static int ProcessReplaceRequest() { if (NS_taccess(deleteDir, F_OK)) { NS_tmkdir(deleteDir, 0755); } +# if !defined(BASE_BROWSER_UPDATE) remove_recursive_on_reboot(tmpDir, deleteDir); +# endif #endif } @@ -2755,8 +2915,14 @@ static void UpdateThreadFunc(void* param) { if (rv == OK) { rv = PopulategMARStrings(); if (rv == OK) { +# ifdef BASE_BROWSER_VERSION_QUOTED + // Use the base browser version to prevent downgrade attacks. + const char* appVersion = BASE_BROWSER_VERSION_QUOTED; +# else + const char* appVersion = MOZ_APP_VERSION; +# endif rv = gArchiveReader.VerifyProductInformation( - gMARStrings.MARChannelID.get(), MOZ_APP_VERSION); + gMARStrings.MARChannelID.get(), appVersion); } } #endif @@ -2860,12 +3026,16 @@ static void UpdateThreadFunc(void* param) { #ifdef XP_MACOSX static void ServeElevatedUpdateThreadFunc(void* param) { +# ifdef BASE_BROWSER_UPDATE + WriteStatusFile(ELEVATION_CANCELED); +# else UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param; gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv, threadArgs->marChannelID); if (!gSucceeded) { WriteStatusFile(ELEVATION_CANCELED); } +# endif QuitProgressUI(); } @@ -2914,7 +3084,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, #endif if (argc > callbackIndex) { -#if defined(XP_WIN) +#if defined(XP_WIN) && !defined(TOR_BROWSER) if (gSucceeded) { LOG(("Launching Windows post update process")); if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) { @@ -3043,8 +3213,12 @@ int NS_main(int argc, NS_tchar** argv) { // This will be used to set `gIsElevated`, but we are going to do it later // when we are ready to set it for every OS to avoid inconsistency. bool isElevated = +# ifdef BASE_BROWSER_UPDATE + false; +# else strstr(argv[0], "/Library/PrivilegedHelperTools/org.mozilla.updater") != 0; +# endif if (isElevated) { if (!ObtainUpdaterArguments(&argc, &argv, &gMARStrings)) { // Won't actually get here because ObtainUpdaterArguments will terminate @@ -3823,6 +3997,14 @@ int NS_main(int argc, NS_tchar** argv) { if (!useService && !noServiceFallback && (updateLockFileHandle == INVALID_HANDLE_VALUE || forceServiceFallback)) { +# ifdef BASE_BROWSER_UPDATE + // To avoid potential security issues such as CVE-2015-0833, do not + // attempt to elevate privileges. Instead, write a "failed" message to + // the update status file (this function will return immediately after + // the CloseHandle(elevatedFileHandle) call below). + LOG(("Refusing to elevate in Base Browser.")); + WriteStatusFile(WRITE_ERROR_ACCESS_DENIED); +# else LOG(("Elevating via a UAC prompt")); // Get the secure ID before trying to update so it is possible to // determine if the updater has created a new one. @@ -3896,6 +4078,7 @@ int NS_main(int argc, NS_tchar** argv) { WriteStatusFile(ELEVATION_CANCELED); LOG(("Elevation canceled.")); } +# endif /* BASE_BROWSER_UPDATE */ } else { LOG(("Not showing a UAC prompt.")); LOG(("useService=%s", useService ? "true" : "false")); @@ -4279,6 +4462,7 @@ int NS_main(int argc, NS_tchar** argv) { if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath)) { LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", DELETE_DIR, errno)); +# if !defined(BASE_BROWSER_UPDATE) // The directory probably couldn't be removed due to it containing files // that are in use and will be removed on OS reboot. The call to remove // the directory on OS reboot is done after the calls to remove the files @@ -4298,6 +4482,7 @@ int NS_main(int argc, NS_tchar** argv) { "directory: " LOG_S, DELETE_DIR)); } +# endif /* BASE_BROWSER_UPDATE */ } #endif /* XP_WIN */ @@ -4944,6 +5129,10 @@ int DoUpdate() { action = new AddIfNotFile(); } else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) { // Patch if exists action = new PatchIfFile(); +#ifndef XP_WIN + } else if (NS_tstrcmp(token, NS_T("addsymlink")) == 0) { + action = new AddSymlink(); +#endif } else { LOG(("DoUpdate: unknown token: " LOG_S, token)); free(buf); diff --git a/toolkit/themes/shared/aboutNetError.css b/toolkit/themes/shared/aboutNetError.css index 6581b089dcf8ad0e74d6e1f821a456912249b508..2531af24729966c3976693006f1d76b2877a3841 100644 --- a/toolkit/themes/shared/aboutNetError.css +++ b/toolkit/themes/shared/aboutNetError.css @@ -8,6 +8,13 @@ body { --warning-color: #ffa436; } +/** + * Blank page whilst we show the prompt. + */ +body.onionAuthPrompt { + display: none !important; +} + @media (prefers-color-scheme: dark) { body { --warning-color: #ffbd4f; @@ -39,6 +46,13 @@ body.certerror .title { fill: var(--warning-color); } +body.onion-error .title { + background-image: url("chrome://global/skin/icons/onion-warning.svg"); + -moz-context-properties: fill, stroke; + fill: currentColor; + stroke: var(--warning-color); +} + body.blocked .title { background-image: url("chrome://global/skin/icons/blocked.svg"); } diff --git a/toolkit/themes/shared/desktop-jar.inc.mn b/toolkit/themes/shared/desktop-jar.inc.mn index 4b30af216bcbf7300b40d54e2c58eb152c865736..217868d3f0fd683b4f4faeab36e98f46759d395f 100644 --- a/toolkit/themes/shared/desktop-jar.inc.mn +++ b/toolkit/themes/shared/desktop-jar.inc.mn @@ -42,10 +42,13 @@ skin/classic/global/notification.css (../../shared/notification.css) skin/classic/global/numberinput.css (../../shared/numberinput.css) skin/classic/global/offlineSupportPages.css (../../shared/offlineSupportPages.css) + skin/classic/global/onion-pattern.css (../../shared/onion-pattern.css) + skin/classic/global/onion-pattern.svg (../../shared/onion-pattern.svg) skin/classic/global/popup.css (../../shared/popup.css) skin/classic/global/popupnotification.css (../../shared/popupnotification.css) skin/classic/global/splitter.css (../../shared/splitter.css) skin/classic/global/toolbarbutton.css (../../shared/toolbarbutton.css) + skin/classic/global/tor-colors.css (../../shared/tor-colors.css) skin/classic/global/tree/tree.css (../../shared/tree/tree.css) skin/classic/global/dirListing/dirListing.css (../../shared/dirListing/dirListing.css) #ifdef XP_MACOSX @@ -96,6 +99,9 @@ skin/classic/global/icons/mdn.svg (../../shared/icons/mdn.svg) skin/classic/global/icons/more.svg (../../shared/icons/more.svg) skin/classic/global/icons/newsfeed.svg (../../shared/icons/newsfeed.svg) + skin/classic/global/icons/onion-site.svg (../../shared/icons/onion-site.svg) + skin/classic/global/icons/onion-slash.svg (../../shared/icons/onion-slash.svg) + skin/classic/global/icons/onion-warning.svg (../../shared/icons/onion-warning.svg) skin/classic/global/icons/open-in-new.svg (../../shared/icons/open-in-new.svg) skin/classic/global/icons/page-portrait.svg (../../shared/icons/page-portrait.svg) skin/classic/global/icons/page-landscape.svg (../../shared/icons/page-landscape.svg) @@ -117,6 +123,10 @@ skin/classic/global/icons/security-warning.svg (../../shared/icons/security-warning.svg) skin/classic/global/icons/settings.svg (../../shared/icons/settings.svg) skin/classic/global/icons/sort-arrow.svg (../../shared/icons/sort-arrow.svg) + skin/classic/global/icons/tor-light-loading.png (../../shared/icons/tor-light-loading.png) + skin/classic/global/icons/tor-light-loading@2x.png (../../shared/icons/tor-light-loading@2x.png) + skin/classic/global/icons/tor-dark-loading.png (../../shared/icons/tor-dark-loading.png) + skin/classic/global/icons/tor-dark-loading@2x.png (../../shared/icons/tor-dark-loading@2x.png) skin/classic/global/icons/trending.svg (../../shared/icons/trending.svg) skin/classic/global/icons/thumbs-down-20.svg (../../shared/icons/thumbs-down-20.svg) skin/classic/global/icons/thumbs-up-20.svg (../../shared/icons/thumbs-up-20.svg) diff --git a/toolkit/themes/shared/findbar.css b/toolkit/themes/shared/findbar.css index 01486a0a57ad026f9f8dc807e30e8660be5f9ff1..e954267e42f59df43d373379177f7e15daa12890 100644 --- a/toolkit/themes/shared/findbar.css +++ b/toolkit/themes/shared/findbar.css @@ -39,6 +39,14 @@ xul|findbar { transition-duration: 0s; transition-delay: 0s; } + + /* When letterboxing is in use, we do not transition to avoid layout jank. + * This has an additional benefit that the find bar cannot be used to + * fingerprint prefers-reduced-motion. See tor-browser#42764. */ + .letterboxing & { + transition-duration: 0s; + transition-delay: 0s; + } } .findbar-container { diff --git a/toolkit/themes/shared/icons/onion-site.svg b/toolkit/themes/shared/icons/onion-site.svg new file mode 100644 index 0000000000000000000000000000000000000000..7be8b10dd4097ce3ac297881aa23a3c0b9cc24e1 --- /dev/null +++ b/toolkit/themes/shared/icons/onion-site.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 13C9.65685 13 11 11.6569 11 10C11 8.34315 9.65685 7 8 7C6.34315 7 5 8.34315 5 10C5 11.6569 6.34315 13 8 13ZM8 14C10.2091 14 12 12.2091 12 10C12 7.79086 10.2091 6 8 6C5.79086 6 4 7.79086 4 10C4 12.2091 5.79086 14 8 14Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 11C8.55228 11 9 10.5523 9 10C9 9.44772 8.55228 9 8 9C7.44772 9 7 9.44772 7 10C7 10.5523 7.44772 11 8 11ZM8 12C9.10457 12 10 11.1046 10 10C10 8.89543 9.10457 8 8 8C6.89543 8 6 8.89543 6 10C6 11.1046 6.89543 12 8 12Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M12 5.52779C13.2275 6.62643 14 8.223 14 10C14 13.3137 11.3137 16 8 16C4.68629 16 2 13.3137 2 10C2 8.223 2.7725 6.62643 4 5.52779V4C4 1.79086 5.79086 0 8 0C10.2091 0 12 1.79086 12 4V5.52779ZM5.25 4.66591C6.0738 4.24033 7.00883 4 8 4C8.99117 4 9.9262 4.24033 10.75 4.66591V4C10.75 2.48122 9.51878 1.25 8 1.25C6.48122 1.25 5.25 2.48122 5.25 4V4.66591ZM13 10C13 12.7614 10.7614 15 8 15C5.23858 15 3 12.7614 3 10C3 7.23858 5.23858 5 8 5C10.7614 5 13 7.23858 13 10Z" fill="context-fill" fill-opacity="context-fill-opacity"/> +</svg> diff --git a/toolkit/themes/shared/icons/onion-slash.svg b/toolkit/themes/shared/icons/onion-slash.svg new file mode 100644 index 0000000000000000000000000000000000000000..36cf2db5f289e8433f933e17f0d9e26f40ad6d7b --- /dev/null +++ b/toolkit/themes/shared/icons/onion-slash.svg @@ -0,0 +1,9 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.62435 8.54824C6.23983 8.91273 6 9.42836 6 10C6 11.1046 6.89543 12 8 12C8.57164 12 9.08727 11.7602 9.45176 11.3757L8.74414 10.668C8.56107 10.8718 8.29551 11 8 11C7.44772 11 7 10.5523 7 10C7 9.70449 7.12818 9.43893 7.33197 9.25586L6.62435 8.54824Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M9.99442 10.1505C9.99812 10.1008 10 10.0506 10 10C10 8.89543 9.10457 8 8 8C7.94936 8 7.89915 8.00188 7.84946 8.00558L9.99442 10.1505Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M5.20988 7.13377C4.46354 7.86041 4 8.87607 4 10C4 12.2091 5.79086 14 8 14C9.12393 14 10.1396 13.5365 10.8662 12.7901L10.159 12.0829C9.61343 12.6483 8.84778 13 8 13C6.34315 13 5 11.6569 5 10C5 9.15222 5.35166 8.38657 5.91707 7.84097L5.20988 7.13377Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M10.8331 10.9892C10.9412 10.6795 11 10.3466 11 10C11 8.34315 9.65685 7 8 7C7.65339 7 7.32052 7.05878 7.01079 7.16692L6.24731 6.40343C6.77658 6.14502 7.37135 6 8 6C10.2091 6 12 7.79086 12 10C12 10.6286 11.855 11.2234 11.5966 11.7527L10.8331 10.9892Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M14 10C14 8.223 13.2275 6.62643 12 5.52779V4C12 1.79086 10.2091 0 8 0C5.79086 0 4 1.79086 4 4V4.15613L5.50811 5.66423C6.2417 5.2417 7.09263 5 8 5C10.7614 5 13 7.23858 13 10C13 10.9074 12.7583 11.7583 12.3358 12.4919L13.0637 13.2199C13.6565 12.2896 14 11.1849 14 10ZM8 4C7.00883 4 6.0738 4.24033 5.25 4.66591V4C5.25 2.48122 6.48122 1.25 8 1.25C9.51878 1.25 10.75 2.48122 10.75 4V4.66591C9.9262 4.24033 8.99117 4 8 4Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M12.2805 14.2044C11.1919 15.3126 9.67621 16 8 16C4.68629 16 2 13.3137 2 10C2 8.32379 2.68736 6.80812 3.79558 5.71948L4.50272 6.42662C3.57545 7.33427 3 8.59993 3 10C3 12.7614 5.23858 15 8 15C9.40007 15 10.6657 14.4246 11.5734 13.4973L12.2805 14.2044Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M1.25801 3.93806C1.50209 3.69398 1.89782 3.69398 2.14189 3.93806L13.1419 14.9381C13.386 15.1821 13.386 15.5779 13.1419 15.8219C12.8978 16.066 12.5021 16.066 12.258 15.8219L1.25801 4.82194C1.01393 4.57787 1.01393 4.18214 1.25801 3.93806Z" fill="#F90D3F"/> +</svg> diff --git a/toolkit/themes/shared/icons/onion-warning.svg b/toolkit/themes/shared/icons/onion-warning.svg new file mode 100644 index 0000000000000000000000000000000000000000..c1c7fd2496055df811e32e690f41ff7644a7218b --- /dev/null +++ b/toolkit/themes/shared/icons/onion-warning.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7.92788 10.5342L7.42044 11.408C7.05803 11.7736 6.55546 12 6 12C4.89543 12 4 11.1046 4 10C4 8.89543 4.89543 8 6 8C7.10457 8 8 8.89543 8 10C8 10.185 7.97488 10.3641 7.92788 10.5342ZM7 10C7 10.5523 6.55228 11 6 11C5.44772 11 5 10.5523 5 10C5 9.44772 5.44772 9 6 9C6.55228 9 7 9.44772 7 10Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M6.52221 12.9547C6.35262 12.9845 6.17812 13 6 13C4.34315 13 3 11.6569 3 10C3 8.34315 4.34315 7 6 7C7.30202 7 8.41032 7.82945 8.8253 8.98878L9.35089 8.08372C9.37772 8.03755 9.40587 7.99285 9.43523 7.94962C8.73673 6.78186 7.45967 6 6 6C3.79086 6 2 7.79086 2 10C2 12.1857 3.75302 13.9619 5.92975 13.9994C5.96208 13.9274 5.99884 13.8558 6.0402 13.7847L6.52221 12.9547Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1978 7.00088C10.8782 6.44807 10.4728 5.95098 10 5.52779V4C10 1.79086 8.20914 0 6 0C3.79086 0 2 1.79086 2 4V5.52779C0.772501 6.62643 0 8.223 0 10C0 13.3137 2.68629 16 6 16C6.03024 16 6.06043 15.9998 6.09057 15.9993C5.89561 15.7007 5.77424 15.3557 5.749 14.9938C3.10419 14.8631 1 12.6773 1 10C1 7.23858 3.23858 5 6 5C7.75288 5 9.29509 5.90201 10.1878 7.26719C10.5002 7.0977 10.8482 7.00893 11.1978 7.00088ZM6 4C5.00883 4 4.0738 4.24033 3.25 4.66591V4C3.25 2.48122 4.48122 1.25 6 1.25C7.51878 1.25 8.75 2.48122 8.75 4V4.66591C7.9262 4.24033 6.99117 4 6 4Z" fill-opacity="context-fill-opacity" fill="context-fill"/> +<path d="M15.5956 14.2875L12.2846 8.58591C11.8306 7.8047 10.6696 7.8047 10.2156 8.58591L6.90465 14.2875C6.45865 15.0529 7.03065 16 7.93865 16H14.5616C15.4686 16 16.0406 15.0529 15.5956 14.2875ZM11.8746 12.4189C11.8746 12.5826 11.8088 12.7396 11.6916 12.8553C11.5744 12.9711 11.4154 13.0361 11.2496 13.0361C11.0839 13.0361 10.9249 12.9711 10.8077 12.8553C10.6905 12.7396 10.6246 12.5826 10.6246 12.4189V10.6935C10.6246 10.5298 10.6905 10.3728 10.8077 10.257C10.9249 10.1413 11.0839 10.0762 11.2496 10.0762C11.4154 10.0762 11.5744 10.1413 11.6916 10.257C11.8088 10.3728 11.8746 10.5298 11.8746 10.6935V12.4189ZM11.2496 15.0124C11.0839 15.0124 10.9249 14.9473 10.8077 14.8316C10.6905 14.7158 10.6246 14.5588 10.6246 14.3951C10.6246 14.2314 10.6905 14.0744 10.8077 13.9586C10.9249 13.8429 11.0839 13.7778 11.2496 13.7778C11.4154 13.7778 11.5744 13.8429 11.6916 13.9586C11.8088 14.0744 11.8746 14.2314 11.8746 14.3951C11.8746 14.5588 11.8088 14.7158 11.6916 14.8316C11.5744 14.9473 11.4154 15.0124 11.2496 15.0124Z" fill-opacity="context-fill-opacity" fill="context-stroke"/> +</svg> diff --git a/toolkit/themes/shared/icons/tor-dark-loading.png b/toolkit/themes/shared/icons/tor-dark-loading.png new file mode 100644 index 0000000000000000000000000000000000000000..e7e90f51a296de36fab655840f0d6fa20440291a Binary files /dev/null and b/toolkit/themes/shared/icons/tor-dark-loading.png differ diff --git a/toolkit/themes/shared/icons/tor-dark-loading@2x.png b/toolkit/themes/shared/icons/tor-dark-loading@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..31adc32e53b0093b8a21dff9a1987b91e44cfe37 Binary files /dev/null and b/toolkit/themes/shared/icons/tor-dark-loading@2x.png differ diff --git a/toolkit/themes/shared/icons/tor-light-loading.png b/toolkit/themes/shared/icons/tor-light-loading.png new file mode 100644 index 0000000000000000000000000000000000000000..0ded12d09406075ea84302591f7bdd3c389d1ac3 Binary files /dev/null and b/toolkit/themes/shared/icons/tor-light-loading.png differ diff --git a/toolkit/themes/shared/icons/tor-light-loading@2x.png b/toolkit/themes/shared/icons/tor-light-loading@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7dc2ffef7cc5ebbb84611d4c395e82b982c94b Binary files /dev/null and b/toolkit/themes/shared/icons/tor-light-loading@2x.png differ diff --git a/toolkit/themes/shared/icons/torbrowser.png b/toolkit/themes/shared/icons/torbrowser.png new file mode 100644 index 0000000000000000000000000000000000000000..073fcf40a183b676abf6e88f4b49e74326de60a1 Binary files /dev/null and b/toolkit/themes/shared/icons/torbrowser.png differ diff --git a/toolkit/themes/shared/minimal-toolkit.jar.inc.mn b/toolkit/themes/shared/minimal-toolkit.jar.inc.mn index a30a507f521120ed8375cd214215590f24c85c35..e5a1b08ac76ffbd3a072767b8a3eddd5db20f186 100644 --- a/toolkit/themes/shared/minimal-toolkit.jar.inc.mn +++ b/toolkit/themes/shared/minimal-toolkit.jar.inc.mn @@ -45,3 +45,6 @@ toolkit.jar: # Text recognition widget skin/classic/global/media/textrecognition.css (../../shared/media/textrecognition.css) + +# For testing purposes + skin/classic/global/icons/torbrowser.png (../../shared/icons/torbrowser.png) diff --git a/toolkit/themes/shared/onion-pattern.css b/toolkit/themes/shared/onion-pattern.css new file mode 100644 index 0000000000000000000000000000000000000000..05c53ffa64f453f74fa0bb8bcb710c53b13a4d5f --- /dev/null +++ b/toolkit/themes/shared/onion-pattern.css @@ -0,0 +1,18 @@ +:root { + /* color-grey-light-20, color-grey-dark-40 */ + --onion-pattern-stroke-color: light-dark(#f0f0f4, #3a3944); + /* color-grey-light-10, color-grey-dark-60 */ + --onion-pattern-fill-color: light-dark(#f9f9fb, #2b2a33); + --onion-pattern-height: 150px; +} + +.onion-pattern-background { + -moz-context-properties: stroke, fill; + stroke: var(--onion-pattern-stroke-color); + fill: var(--onion-pattern-fill-color); + background: + local + url("chrome://global/skin/onion-pattern.svg") + center bottom + repeat-x; +} diff --git a/toolkit/themes/shared/onion-pattern.svg b/toolkit/themes/shared/onion-pattern.svg new file mode 100644 index 0000000000000000000000000000000000000000..3bee04c8fb31baa633776faca1b7bc00af3495e0 --- /dev/null +++ b/toolkit/themes/shared/onion-pattern.svg @@ -0,0 +1,30 @@ +<svg width="1200" height="150" viewBox="0 0 1200 150" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="3" cy="75" r="72.5" stroke="context-stroke" stroke-width="5"/> +<circle cx="3" cy="75" r="53.75" stroke="context-stroke" stroke-width="5"/> +<circle cx="3" cy="75" r="35" stroke="context-stroke" stroke-width="5"/> +<circle cx="3" cy="75" r="16.25" stroke="context-stroke" stroke-width="5"/> +<path d="M223 0C225.761 0 228.017 2.24554 227.836 5.001C225.262 44.0907 192.741 75 153 75C113.259 75 80.7375 44.0907 78.1641 5.001C77.9827 2.24554 80.2386 0 83 0H223Z" fill="context-stroke"/> +<path d="M223 75C225.761 75 228.017 77.2455 227.836 80.001C225.262 119.091 192.741 150 153 150C113.259 150 80.7375 119.091 78.1641 80.001C77.9827 77.2455 80.2386 75 83 75H223Z" fill="context-fill"/> +<circle cx="303" cy="75" r="72.5" stroke="context-stroke" stroke-width="5"/> +<circle cx="303" cy="75" r="53.75" stroke="context-stroke" stroke-width="5"/> +<circle cx="303" cy="75" r="35" stroke="context-stroke" stroke-width="5"/> +<circle cx="303" cy="75" r="16.25" stroke="context-stroke" stroke-width="5"/> +<path d="M378 5C378 2.23859 380.246 -0.0173187 383.001 0.164093C422.091 2.7375 453 35.2591 453 75C453 114.741 422.091 147.262 383.001 149.836C380.246 150.017 378 147.761 378 145V5Z" fill="context-stroke"/> +<path d="M453 5C453 2.23859 455.246 -0.0173187 458.001 0.164093C497.091 2.7375 528 35.2591 528 75C528 114.741 497.091 147.262 458.001 149.836C455.246 150.017 453 147.761 453 145V5Z" fill="context-fill"/> +<circle cx="603" cy="75" r="72.5" stroke="context-stroke" stroke-width="5"/> +<circle cx="603" cy="75" r="53.75" stroke="context-stroke" stroke-width="5"/> +<circle cx="603" cy="75" r="35" stroke="context-stroke" stroke-width="5"/> +<circle cx="603" cy="75" r="16.25" stroke="context-stroke" stroke-width="5"/> +<path d="M823 0C825.761 0 828.017 2.24554 827.836 5.001C825.262 44.0907 792.741 75 753 75C713.259 75 680.738 44.0907 678.164 5.001C677.983 2.24554 680.239 0 683 0H823Z" fill="context-stroke"/> +<path d="M823 75C825.761 75 828.017 77.2455 827.836 80.001C825.262 119.091 792.741 150 753 150C713.259 150 680.738 119.091 678.164 80.001C677.983 77.2455 680.239 75 683 75H823Z" fill="context-fill"/> +<circle cx="903" cy="75" r="72.5" stroke="context-stroke" stroke-width="5"/> +<circle cx="903" cy="75" r="53.75" stroke="context-stroke" stroke-width="5"/> +<circle cx="903" cy="75" r="35" stroke="context-stroke" stroke-width="5"/> +<circle cx="903" cy="75" r="16.25" stroke="context-stroke" stroke-width="5"/> +<path d="M1128 145C1128 147.761 1125.75 150.017 1123 149.836C1083.91 147.262 1053 114.741 1053 75C1053 35.2591 1083.91 2.73751 1123 0.164089C1125.75 -0.0173134 1128 2.23858 1128 5V145Z" fill="context-stroke"/> +<path d="M1053 145C1053 147.761 1050.75 150.017 1048 149.836C1008.91 147.262 978 114.741 978 75C978 35.2591 1008.91 2.73751 1048 0.164089C1050.75 -0.0173134 1053 2.23858 1053 5V145Z" fill="context-fill"/> +<circle cx="1203" cy="75" r="72.5" stroke="context-stroke" stroke-width="5"/> +<circle cx="1203" cy="75" r="53.75" stroke="context-stroke" stroke-width="5"/> +<circle cx="1203" cy="75" r="35" stroke="context-stroke" stroke-width="5"/> +<circle cx="1203" cy="75" r="16.25" stroke="context-stroke" stroke-width="5"/> +</svg> diff --git a/toolkit/themes/shared/tor-colors.css b/toolkit/themes/shared/tor-colors.css new file mode 100644 index 0000000000000000000000000000000000000000..12caef69f16576901843dcec8fef6e73c402c627 --- /dev/null +++ b/toolkit/themes/shared/tor-colors.css @@ -0,0 +1,161 @@ +@namespace xul "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +:root { + /* Photon colors not available in Firefox. */ + --purple-30: #c069ff; + --purple-40: #ad3bff; + --purple-50: #9400ff; + --purple-60: #8000d7; + --purple-70: #6200a4; + --purple-80: #440071; + --purple-90: #25003e; + + /* On light backgrounds. */ + --tor-accent-color-light: var(--purple-60); + --tor-accent-color-hover-light: var(--purple-70); + --tor-accent-color-active-light: var(--purple-80); + + /* Acorn color grey light 05. */ + --tor-button-text-color-light: var(--color-gray-05); + --tor-button-text-color-hover-light: var(--color-gray-05); + --tor-button-text-color-active-light: var(--color-gray-05); + --tor-button-background-color-light: var(--tor-accent-color-light); + --tor-button-background-color-hover-light: var(--tor-accent-color-hover-light); + --tor-button-background-color-active-light: var(--tor-accent-color-active-light); + --tor-focus-outline-color-light: var(--tor-accent-color-light); + --tor-link-color-light: var(--tor-accent-color-light); + --tor-link-color-hover-light: var(--tor-accent-color-hover-light); + --tor-link-color-active-light: var(--tor-accent-color-active-light); + + + /* On dark backgrounds. */ + /* TODO: Need a dark theme purple color that gets *lighter* with hover and + * active states, see tor-browser#42025 */ + --tor-accent-color-dark: var(--purple-30); + --tor-accent-color-hover-dark: var(--purple-40); + --tor-accent-color-active-dark: var(--purple-50); + + /* TODO: Use a dark text color for dark theme. tor-browser#41787. */ + --tor-button-text-color-dark: var(--color-gray-05); + --tor-button-text-color-hover-dark: var(--color-gray-05); + --tor-button-text-color-active-dark: var(--color-gray-05); + --tor-button-background-color-dark: var(--tor-accent-color-dark); + --tor-button-background-color-hover-dark: var(--tor-accent-color-hover-dark); + --tor-button-background-color-active-dark: var(--tor-accent-color-active-dark); + --tor-focus-outline-color-dark: var(--tor-accent-color-dark); + --tor-link-color-dark: var(--tor-accent-color-dark); + --tor-link-color-hover-dark: var(--tor-accent-color-hover-dark); + --tor-link-color-active-dark: var(--tor-accent-color-active-dark); + + + /* Generic colors that adapt to theme. */ + --tor-accent-color: light-dark( + var(--tor-accent-color-light), + var(--tor-accent-color-dark) + ); + --tor-accent-color-hover: light-dark( + var(--tor-accent-color-hover-light), + var(--tor-accent-color-hover-dark) + ); + --tor-accent-color-active: light-dark( + var(--tor-accent-color-active-light), + var(--tor-accent-color-active-dark) + ); + --tor-button-text-color: light-dark( + var(--tor-button-text-color-light), + var(--tor-button-text-color-dark) + ); + --tor-button-text-color-hover: light-dark( + var(--tor-button-text-color-hover-light), + var(--tor-button-text-color-hover-dark) + ); + --tor-button-text-color-active: light-dark( + var(--tor-button-text-color-active-light), + var(--tor-button-text-color-active-dark) + ); + --tor-button-background-color: light-dark( + var(--tor-button-background-color-light), + var(--tor-button-background-color-dark) + ); + --tor-button-background-color-hover: light-dark( + var(--tor-button-background-color-hover-light), + var(--tor-button-background-color-hover-dark) + ); + --tor-button-background-color-active: light-dark( + var(--tor-button-background-color-active-light), + var(--tor-button-background-color-active-dark) + ); + --tor-focus-outline-color: light-dark( + var(--tor-focus-outline-color-light), + var(--tor-focus-outline-color-dark) + ); + --tor-link-color: light-dark( + var(--tor-link-color-light), + var(--tor-link-color-dark) + ); + --tor-link-color-hover: light-dark( + var(--tor-link-color-hover-light), + var(--tor-link-color-hover-dark) + ); + --tor-link-color-active: light-dark( + var(--tor-link-color-active-light), + var(--tor-link-color-active-dark) + ); +} + +@media ((prefers-contrast) or (forced-colors)) { + :root { + /* Use Firefox design system accent colors. */ + --tor-accent-color: var(--color-accent-primary); + --tor-accent-color-hover: var(--color-accent-primary-hover); + --tor-accent-color-active: var(--color-accent-primary-active); + + /* Use Firefox design system primary button colors. */ + --tor-button-text-color: var(--button-text-color-primary); + --tor-button-text-color-hover: var(--button-text-color-primary-hover); + --tor-button-text-color-active: var(--button-text-color-primary-active); + --tor-button-background-color: var(--button-background-color-primary); + --tor-button-background-color-hover: var(--button-background-color-primary-hover); + --tor-button-background-color-active: var(--button-background-color-primary-active); + + /* Use Firefox design system default colors. */ + --tor-focus-outline-color: var(--focus-outline-color); + --tor-link-color: var(--link-color); + --tor-link-color-hover: var(--link-color-hover); + --tor-link-color-active: var(--link-color-active); + } +} + +/* Has a higher specificity than `button` and `button.primary`. */ +button.tor-button:is(*, .primary), +xul|button.tor-button:is(*, [default]), +.tor-button { + color: var(--tor-button-text-color); + background-color: var(--tor-button-background-color); +} + +:is( + button.tor-button:is(*, .primary), + xul|button.tor-button:is(*, [default]), + .tor-button +):not([disabled]):hover { + color: var(--tor-button-text-color-hover); + background-color: var(--tor-button-background-color-hover); +} + +:is( + button.tor-button:is(*, .primary), + xul|button.tor-button:is(*, [default]), + .tor-button +):not([disabled]):hover:active { + color: var(--tor-button-text-color-active); + background-color: var(--tor-button-background-color-active); +} + +:is( + button.tor-button:is(*, .primary), + xul|button.tor-button:is(*, [default]), + .tor-button +):focus-visible { + outline-color: var(--tor-focus-outline-color); +} diff --git a/toolkit/torbutton/chrome/locale/en-US/onionLocation.properties b/toolkit/torbutton/chrome/locale/en-US/onionLocation.properties new file mode 100644 index 0000000000000000000000000000000000000000..6ecb17ee8193ce838ccec7ebed31daae317bf653 --- /dev/null +++ b/toolkit/torbutton/chrome/locale/en-US/onionLocation.properties @@ -0,0 +1,18 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Onion-Location strings. +onionLocation.loadOnion=Visit the .onion +# Localization note: this is the access key for "Visit the .onion". +# It should be a character that appears in that string. +onionLocation.loadOnionAccessKey=V +onionLocation.notNow=Not Now +# Localization note: this is the access key for "Not now". +# It should be a character that appears in that string. +onionLocation.notNowAccessKey=n +onionLocation.description=There's a more private and secure version of this site available over the Tor network via onion services. Onion services help website publishers and their visitors defeat surveillance and censorship. +onionLocation.tryThis=Try Onion Services +onionLocation.onionAvailable=.onion available +onionLocation.learnMore=Learn more… diff --git a/toolkit/torbutton/chrome/locale/en-US/settings.properties b/toolkit/torbutton/chrome/locale/en-US/settings.properties new file mode 100644 index 0000000000000000000000000000000000000000..e57f5b80451aeb4f8bbf8a79eee64ee90ff68a11 --- /dev/null +++ b/toolkit/torbutton/chrome/locale/en-US/settings.properties @@ -0,0 +1,19 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Still used in TorConnect. + +# Message box +settings.torPreferencesDescription=Tor Browser routes your traffic over the Tor Network, run by thousands of volunteers around the world. + +settings.quickstartCheckbox=Always connect automatically + +# Might be removed in tor-browser#42477 + +settings.bridgeLocation=Your location +settings.bridgeLocationAutomatic=Automatic +settings.bridgeLocationFrequent=Frequently selected locations +settings.bridgeLocationOther=Other locations +settings.bridgeChooseForMe=Choose a Bridge For Me… diff --git a/toolkit/torbutton/chrome/locale/en-US/torConnect.properties b/toolkit/torbutton/chrome/locale/en-US/torConnect.properties new file mode 100644 index 0000000000000000000000000000000000000000..bb1459d826cc93fbaed7b1d87717e23558781d72 --- /dev/null +++ b/toolkit/torbutton/chrome/locale/en-US/torConnect.properties @@ -0,0 +1,54 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +torConnect.titlebarStatusName=Tor connection +torConnect.titlebarStatusNotConnected=Not connected +torConnect.titlebarStatusConnecting=Connecting… +torConnect.titlebarStatusPotentiallyBlocked=Potentially blocked +torConnect.titlebarStatusConnected=Connected + +torConnect.torConnect=Connect to Tor +torConnect.torConnecting=Establishing a Connection +torConnect.tryingAgain=Trying again… +torConnect.noInternet=Tor Browser couldn’t reach the Internet +torConnect.noInternetDescription=This could be due to a connection issue rather than Tor being blocked. Check your Internet connection, proxy and firewall settings before trying again. +torConnect.torBootstrapFailed=Tor failed to establish a Tor network connection. +torConnect.couldNotConnect=Tor Browser could not connect to Tor +# Translation note: used as a text to insert as a link on several strings (%S) +torConnect.configureConnection=configure your connection +# Translation note: %S = "configure your connection" link +torConnect.assistDescription=If Tor is blocked in your location, trying a bridge may help. Connection assist can choose one for you using your location, or you can %S manually instead. +torConnect.tryingBridge=Trying a bridge… +torConnect.tryingBridgeAgain=Trying one more time… +torConnect.errorLocation=Tor Browser couldn’t locate you +# Translation note: %S = "configure your connection" link +torConnect.errorLocationDescription=Tor Browser needs to know your location in order to choose the right bridge for you. If you’d rather not share your location, %S manually instead. +torConnect.isLocationCorrect=Are these location settings correct? +# Translation note: %S = "configure your connection" link +torConnect.isLocationCorrectDescription=Tor Browser still couldn’t connect to Tor. Please check your location settings are correct and try again, or %S instead. +torConnect.finalError=Tor Browser still cannot connect +torConnect.finalErrorDescription=Despite its best efforts, connection assist was not able to connect to Tor. Try troubleshooting your connection and adding a bridge manually instead. +torConnect.breadcrumbAssist=Connection assist +torConnect.breadcrumbLocation=Location settings +torConnect.breadcrumbTryBridge=Try a bridge +torConnect.restartTorBrowser=Restart Tor Browser +torConnect.torConfigure=Configure Connection… +torConnect.viewLog=View logs… +torConnect.torConnectButton=Connect +torConnect.cancel=Cancel +torConnect.torConnected=Connected to the Tor network! +torConnect.tryAgain=Try Again +torConnect.yourLocation=Your Location +torConnect.unblockInternetIn=Unblock the Internet in +torConnect.tryBridge=Try a Bridge +torConnect.automatic=Automatic +torConnect.selectCountryRegion=Select Country or Region +torConnect.frequentLocations=Frequently selected locations +torConnect.otherLocations=Other locations +torConnect.offline=Internet not reachable +torConnect.autoBootstrappingFailed=Automatic configuration failed +torConnect.autoBootstrappingAllFailed=None of the configurations we tried worked +torConnect.cannotDetermineCountry=Unable to determine user country +torConnect.noSettingsForCountry=No settings available for your location diff --git a/toolkit/torbutton/chrome/locale/en-US/torlauncher.properties b/toolkit/torbutton/chrome/locale/en-US/torlauncher.properties new file mode 100644 index 0000000000000000000000000000000000000000..ccb4111ebabc63af06b7593cf917ca531eeb1286 --- /dev/null +++ b/toolkit/torbutton/chrome/locale/en-US/torlauncher.properties @@ -0,0 +1,52 @@ +# Copyright (c) 2022, The Tor Project, Inc. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +torlauncher.error_title=Tor Launcher +torlauncher.tor_exited_during_startup=Tor exited during startup. This might be due to an error in your torrc file, a bug in Tor or another program on your system, or faulty hardware. Until you fix the underlying problem and restart Tor, Tor Browser will not start. +torlauncher.tor_exited=Tor unexpectedly exited. This might be due to a bug in Tor itself, another program on your system, or faulty hardware. Until you restart Tor, Tor Browser will not be able to reach any websites. If the problem persists, please send a copy of your Tor Log to the support team. +torlauncher.tor_exited2=Restarting Tor will not close your browser tabs. +torlauncher.restart_tor=Restart Tor + + +# Translation note: %1$S is a bootstrap phase from torlauncher.bootstrapStatus, +# %2$S is the error from torlauncher.bootstrapWarning +torlauncher.tor_bootstrap_failed_details=%1$S failed (%2$S). + +torlauncher.bootstrapStatus.starting=Starting +torlauncher.bootstrapStatus.conn_pt=Connecting to bridge +torlauncher.bootstrapStatus.conn_done_pt=Connected to bridge +torlauncher.bootstrapStatus.conn_proxy=Connecting to proxy +torlauncher.bootstrapStatus.conn_done_proxy=Connected to proxy +torlauncher.bootstrapStatus.conn=Connecting to a Tor relay +torlauncher.bootstrapStatus.conn_done=Connected to a Tor relay +torlauncher.bootstrapStatus.handshake=Negotiating with a Tor relay +torlauncher.bootstrapStatus.handshake_done=Finished negotiating with a Tor relay +torlauncher.bootstrapStatus.onehop_create=Establishing an encrypted directory connection +torlauncher.bootstrapStatus.requesting_status=Retrieving network status +torlauncher.bootstrapStatus.loading_status=Loading network status +torlauncher.bootstrapStatus.loading_keys=Loading authority certificates +torlauncher.bootstrapStatus.requesting_descriptors=Requesting relay information +torlauncher.bootstrapStatus.loading_descriptors=Loading relay information +torlauncher.bootstrapStatus.enough_dirinfo=Finished loading relay information +torlauncher.bootstrapStatus.ap_conn_pt=Building circuits: Connecting to bridge +torlauncher.bootstrapStatus.ap_conn_done_pt=Building circuits: Connected to bridge +torlauncher.bootstrapStatus.ap_conn_proxy=Building circuits: Connecting to proxy +torlauncher.bootstrapStatus.ap_conn_done_proxy=Building circuits: Connected to proxy +torlauncher.bootstrapStatus.ap_conn=Building circuits: Connecting to a Tor relay +torlauncher.bootstrapStatus.ap_conn_done=Building circuits: Connected to a Tor relay +torlauncher.bootstrapStatus.ap_handshake=Building circuits: Negotiating with a Tor relay +torlauncher.bootstrapStatus.ap_handshake_done=Building circuits: Finished negotiating with a Tor relay +torlauncher.bootstrapStatus.circuit_create=Building circuits: Establishing a Tor circuit +torlauncher.bootstrapStatus.done=Connected to the Tor network! + +torlauncher.bootstrapWarning.done=done +torlauncher.bootstrapWarning.connectrefused=connection refused +torlauncher.bootstrapWarning.misc=miscellaneous +torlauncher.bootstrapWarning.resourcelimit=insufficient resources +torlauncher.bootstrapWarning.identity=identity mismatch +torlauncher.bootstrapWarning.timeout=connection timeout +torlauncher.bootstrapWarning.noroute=no route to host +torlauncher.bootstrapWarning.ioerror=read/write error +torlauncher.bootstrapWarning.pt_missing=missing pluggable transport diff --git a/toolkit/torbutton/jar.mn b/toolkit/torbutton/jar.mn new file mode 100644 index 0000000000000000000000000000000000000000..e95e8cf585351383e59ce53cd88deafc3630a335 --- /dev/null +++ b/toolkit/torbutton/jar.mn @@ -0,0 +1,8 @@ +#filter substitution + +torbutton.jar: +% resource torbutton % +% category l10n-registry torbutton resource://torbutton/locale/{locale}/ + +% locale torbutton en-US %locale/en-US/ + locale/en-US/ (chrome/locale/en-US/*) diff --git a/toolkit/torbutton/moz.build b/toolkit/torbutton/moz.build new file mode 100644 index 0000000000000000000000000000000000000000..696f1be9bda0bfef46291e101ca01f34e4702501 --- /dev/null +++ b/toolkit/torbutton/moz.build @@ -0,0 +1,6 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +JAR_MANIFESTS += ["jar.mn"] diff --git a/toolkit/xre/LauncherRegistryInfo.cpp b/toolkit/xre/LauncherRegistryInfo.cpp index b80ee77f4d00c1504d54ef2fd180da889d606786..50b447b7eb80bfc8910c7d53630238cd7f99befd 100644 --- a/toolkit/xre/LauncherRegistryInfo.cpp +++ b/toolkit/xre/LauncherRegistryInfo.cpp @@ -17,6 +17,9 @@ #include <string> #include <type_traits> +// tor-browser#42163 +#include <filesystem> + #define EXPAND_STRING_MACRO2(t) t #define EXPAND_STRING_MACRO(t) EXPAND_STRING_MACRO2(t) @@ -586,6 +589,45 @@ LauncherRegistryInfo::GetBrowserStartTimestamp() { LauncherResult<std::wstring> LauncherRegistryInfo::BuildDefaultBlocklistFilename() { + // tor-browser#42163: Make the DLL blocklist obey portable mode + { + std::filesystem::path appDir; + { + mozilla::UniquePtr<wchar_t[]> appDirStr = GetFullBinaryPath(); + if (!appDirStr) { + return LAUNCHER_ERROR_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + appDir = std::filesystem::path(appDirStr.get()).parent_path(); + } + std::error_code ec; + const bool isPortable = + !std::filesystem::exists(appDir / L"system-install", ec); + if (ec) { + // exists is supposed not to set an error when a file does not exist + // (whereas other functions such as is_regular_file sets it). + // The standard is quite opaque about the meaning of the numeric codes. + // Moreover, we use libcxx on Windows, and it seems they created a sort of + // POSIX compatibility layer (e.g., for stat), see + // libcxx/src/filesystem/posix_compat.h. + // std::error_code has a message function, but all the various macro are + // specific to handle Windows errors, so we have to use the generic error. + // At least, at the moment the error is dropped eventually. + return LAUNCHER_ERROR_GENERIC(); + } + if (isPortable) { + // RELATIVE_DATA_DIR must have forward slashes, but weakly_canonical + // already changes them to backslashes. + const std::filesystem::path blocklistPath = + std::filesystem::weakly_canonical( + appDir / L"" RELATIVE_DATA_DIR / L"blocklist", ec); + if (ec) { + return LAUNCHER_ERROR_GENERIC(); + } + return blocklistPath.wstring(); + } + // Normal installation, continue on Mozilla's path + } + // These flags are chosen to avoid I/O, see bug 1363398. const DWORD flags = KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_ALIAS; @@ -618,6 +660,8 @@ LauncherRegistryInfo::BuildDefaultBlocklistFilename() { } LauncherResult<std::wstring> LauncherRegistryInfo::GetBlocklistFileName() { + // tor-browser#42163: Make the DLL blocklist obey portable mode +#ifndef BASE_BROWSER_VERSION LauncherResult<Disposition> disposition = Open(); if (disposition.isErr()) { return disposition.propagateErr(); @@ -633,19 +677,19 @@ LauncherResult<std::wstring> LauncherRegistryInfo::GetBlocklistFileName() { UniquePtr<wchar_t[]> buf = readResult.unwrap(); return std::wstring(buf.get()); } - +#endif LauncherResult<std::wstring> defaultBlocklistPath = BuildDefaultBlocklistFilename(); if (defaultBlocklistPath.isErr()) { return defaultBlocklistPath.propagateErr(); } - +#ifndef BASE_BROWSER_VERSION LauncherVoidResult writeResult = WriteRegistryValueString( mRegKey, ResolveBlocklistValueName(), defaultBlocklistPath.inspect()); if (writeResult.isErr()) { return writeResult.propagateErr(); } - +#endif return defaultBlocklistPath; } diff --git a/toolkit/xre/MacLaunchHelper.h b/toolkit/xre/MacLaunchHelper.h index a21ec0c483c6d849c112d252c9d5322eb3d7d939..c95400ad0b955fa5a9873fa7cb99fe9d1f4e0bf5 100644 --- a/toolkit/xre/MacLaunchHelper.h +++ b/toolkit/xre/MacLaunchHelper.h @@ -28,9 +28,11 @@ extern "C" { */ void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid = 0); void LaunchMacApp(int aArgc, char** aArgv); +#ifndef BASE_BROWSER_UPDATE bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid = 0); bool InstallPrivilegedHelper(); void AbortElevatedUpdate(); +#endif } #endif diff --git a/toolkit/xre/MacLaunchHelper.mm b/toolkit/xre/MacLaunchHelper.mm index d75abeff8cc2c530d6bbd063402fbed40ae28bb2..bf437e1358c04fba600a311f834f049d5c34b5e6 100644 --- a/toolkit/xre/MacLaunchHelper.mm +++ b/toolkit/xre/MacLaunchHelper.mm @@ -130,6 +130,7 @@ void LaunchMacApp(int aArgc, char** aArgv) { LaunchMacAppWithBundle(launchPath, arguments); } +#ifndef BASE_BROWSER_UPDATE bool InstallPrivilegedHelper() { AuthorizationRef authRef = NULL; OSStatus status = AuthorizationCreate( @@ -213,3 +214,4 @@ bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid) { } return didSucceed; } +#endif diff --git a/toolkit/xre/MacRunFromDmgUtils.mm b/toolkit/xre/MacRunFromDmgUtils.mm index e486e12401eb92722e8c4291518ba83a9e27bf71..108c4a31d5be9e2380d59ce63e204cf20264cc8d 100644 --- a/toolkit/xre/MacRunFromDmgUtils.mm +++ b/toolkit/xre/MacRunFromDmgUtils.mm @@ -263,7 +263,7 @@ static void ShowInstallFailedDialog() { NS_OBJC_END_TRY_IGNORE_BLOCK; } -#ifdef MOZ_UPDATER +#if defined(MOZ_UPDATER) && !defined(BASE_BROWSER_VERSION) bool LaunchElevatedDmgInstall(NSString* aBundlePath, NSArray* aArguments) { NSTask* task = [[NSTask alloc] init]; [task setExecutableURL:[NSURL fileURLWithPath:aBundlePath]]; @@ -292,7 +292,7 @@ static bool InstallFromPath(NSString* aBundlePath, NSString* aDestPath) { installSuccessful = true; } -#ifdef MOZ_UPDATER +#if defined(MOZ_UPDATER) && !defined(BASE_BROWSER_VERSION) // The installation may have been unsuccessful if the user did not have the // rights to write to the Applications directory. Check for this situation and // launch an elevated installation if necessary. Rather than creating a new, diff --git a/toolkit/xre/ProfileReset.cpp b/toolkit/xre/ProfileReset.cpp index 8ed01e6535e21aafd52bfdea96ac0d1cb05fcfbf..c8c1e69645dddb78a80054d32aea7e28fd203492 100644 --- a/toolkit/xre/ProfileReset.cpp +++ b/toolkit/xre/ProfileReset.cpp @@ -23,8 +23,8 @@ using namespace mozilla; -extern const XREAppData* gAppData; - +static const char kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -49,12 +49,21 @@ nsresult ProfileResetCleanup(nsToolkitProfileService* aService, mozilla::components::StringBundle::Service(); if (!sbs) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> brandBundle; + Unused << sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + if (!brandBundle) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> sb; Unused << sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); if (!sb) return NS_ERROR_FAILURE; - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + if (NS_FAILED(rv)) return rv; + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString resetBackupDirectoryName; diff --git a/toolkit/xre/dllservices/mozglue/WindowsDllBlocklist.cpp b/toolkit/xre/dllservices/mozglue/WindowsDllBlocklist.cpp index 4f97ccc39f66feb7164d2c118f2a5a71fb51a8b6..9355e5f7d80780a8f50bc5254fa59e4aab06c488 100644 --- a/toolkit/xre/dllservices/mozglue/WindowsDllBlocklist.cpp +++ b/toolkit/xre/dllservices/mozglue/WindowsDllBlocklist.cpp @@ -517,7 +517,7 @@ continue_loading: return ret; } -#if defined(BLOCK_LOADLIBRARY_INJECTION) +#if defined(BLOCK_LOADLIBRARY_INJECTION) || defined(BASE_BROWSER_VERSION) // Map of specific thread proc addresses we should block. In particular, // LoadLibrary* APIs which indicate DLL injection static void* gStartAddressesToBlock[4]; @@ -530,7 +530,7 @@ static bool ShouldBlockThread(void* aStartAddress) { return false; } -#if defined(BLOCK_LOADLIBRARY_INJECTION) +#if defined(BLOCK_LOADLIBRARY_INJECTION) || defined(BASE_BROWSER_VERSION) for (auto p : gStartAddressesToBlock) { if (p == aStartAddress) { return true; @@ -593,7 +593,7 @@ MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags) { } } -#if defined(BLOCK_LOADLIBRARY_INJECTION) +#if defined(BLOCK_LOADLIBRARY_INJECTION) || defined(BASE_BROWSER_VERSION) // Populate a list of thread start addresses to block. HMODULE hKernel = GetModuleHandleW(L"kernel32.dll"); if (hKernel) { diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 318ee7e293b917534128d2c0fa631ecf369b5119..f76be3fc601b8c49b48f7d40c6043c2edbbd5393 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -295,6 +295,7 @@ static const char kPrefThemeId[] = "extensions.activeThemeID"; static const char kPrefBrowserStartupBlankWindow[] = "browser.startup.blankWindow"; static const char kPrefPreXulSkeletonUI[] = "browser.startup.preXulSkeletonUI"; +static const char kPrefResistFingerprinting[] = "privacy.resistFingerprinting"; #endif // defined(XP_WIN) #if defined(MOZ_WIDGET_GTK) @@ -456,13 +457,14 @@ bool IsWaylandEnabled() { return true; } } + // Keep wayland disabled in Base Browser. See tor-browser#43092. + return false; // Enable by default when we're running on a recent enough GTK version. We'd // like to check further details like compositor version and so on ideally // to make sure we don't enable it on old Mutter or what not, but we can't, // so let's assume that if the user is running on a Wayland session by // default we're ok, since either the distro has enabled Wayland by default, // or the user has gone out of their way to use Wayland. - return !gtk_check_version(3, 24, 30); }(); return isWaylandEnabled; } @@ -2256,6 +2258,7 @@ static void ReflectSkeletonUIPrefToRegistry(const char* aPref, void* aData) { bool shouldBeEnabled = Preferences::GetBool(kPrefPreXulSkeletonUI, false) && Preferences::GetBool(kPrefBrowserStartupBlankWindow, false) && + !Preferences::GetBool(kPrefResistFingerprinting, false) && LookAndFeel::DrawInTitlebar(); if (shouldBeEnabled && Preferences::HasUserValue(kPrefThemeId)) { nsCString themeId; @@ -2577,6 +2580,8 @@ nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) { return NS_ERROR_LAUNCHED_CHILD_PROCESS; } +static const char kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -2646,12 +2651,20 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); // profileMissing nsAutoString missingMessage; @@ -2673,6 +2686,8 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { #endif // MOZ_WIDGET_ANDROID } +// If aUnlocker is NULL, it is also OK for the following arguments to be NULL: +// aProfileDir, aProfileLocalDir, aResult. static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir, nsIProfileUnlocker* aUnlocker, @@ -2680,10 +2695,12 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, nsIProfileLock** aResult) { nsresult rv; - bool exists; - aProfileDir->Exists(&exists); - if (!exists) { - return ProfileMissingDialog(aNative); + if (aProfileDir) { + bool exists; + aProfileDir->Exists(&exists); + if (!exists) { + return ProfileMissingDialog(aNative); + } } ScopedXPCOMStartup xpcom; @@ -2693,7 +2710,7 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, #if defined(MOZ_TELEMETRY_REPORTING) // We cannot check if telemetry has been disabled by the user, yet. // So, rely on the build time settings, instead. - mozilla::Telemetry::WriteFailedProfileLock(aProfileDir); + if (aProfileDir) mozilla::Telemetry::WriteFailedProfileLock(aProfileDir); #endif rv = xpcom.SetWindowCreator(aNative); @@ -2709,12 +2726,21 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 3> params = {appName, appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); + + AutoTArray<nsString, 3> params; + params.AppendElement(appName); + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString killMessage; #ifndef XP_MACOSX @@ -3444,6 +3470,11 @@ static bool CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion, gLastAppBuildID.Assign(gAppData->buildID); nsAutoCString buf; + + nsAutoCString forkVersion(BASE_BROWSER_VERSION_QUOTED); + rv = parser.GetString("Compatibility", "LastTorBrowserVersion", buf); + if (NS_FAILED(rv) || !forkVersion.Equals(buf)) return false; + rv = parser.GetString("Compatibility", "LastOSABI", buf); if (NS_FAILED(rv) || !aOSABI.Equals(buf)) return false; @@ -3529,6 +3560,12 @@ static void WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion, PR_Write(fd, kHeader, sizeof(kHeader) - 1); PR_Write(fd, aVersion.get(), aVersion.Length()); + nsAutoCString forkVersion(BASE_BROWSER_VERSION_QUOTED); + static const char kForkVersionHeader[] = + NS_LINEBREAK "LastTorBrowserVersion="; + PR_Write(fd, kForkVersionHeader, sizeof(kForkVersionHeader) - 1); + PR_Write(fd, forkVersion.get(), forkVersion.Length()); + static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI="; PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1); PR_Write(fd, aOSABI.get(), aOSABI.Length()); @@ -5063,8 +5100,18 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { NS_ENSURE_SUCCESS(rv, 1); rv = exeFile->GetParent(getter_AddRefs(exeDir)); NS_ENSURE_SUCCESS(rv, 1); + +# ifdef BASE_BROWSER_VERSION_QUOTED + nsAutoCString compatVersion(BASE_BROWSER_VERSION_QUOTED); +# endif ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc, - gRestartArgv, mAppData->version); + gRestartArgv, +# ifdef BASE_BROWSER_VERSION_QUOTED + compatVersion.get() +# else + mAppData->version +# endif + ); if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) { SaveToEnv("MOZ_TEST_PROCESS_UPDATES="); *aExitFlag = true; diff --git a/toolkit/xre/nsIXREDirProvider.idl b/toolkit/xre/nsIXREDirProvider.idl index ce599a83bcdf1b2779ea7fdc858920c4aa427c73..564cfbc7d8afff238664cb9e4b143650223093fb 100644 --- a/toolkit/xre/nsIXREDirProvider.idl +++ b/toolkit/xre/nsIXREDirProvider.idl @@ -20,4 +20,9 @@ interface nsIXREDirProvider : nsISupports * Gets the hash for the current installation directory. */ AString getInstallHash(); + + /** + * Tells whether the browser has been started in portable mode. + */ + readonly attribute boolean isPortableMode; }; diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 0446d951008c3acc13e67116b06e48fa57392c13..105dd5cecec32b1249ba87bc4e3f6d3b335c7d64 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -54,7 +54,6 @@ # include "commonupdatedir.h" # include "nsWindowsHelpers.h" # include "pathhash.h" -# include "WinUtils.h" # define getcwd(path, size) _getcwd(path, size) # define getpid() GetCurrentProcessId() #elif defined(XP_UNIX) @@ -123,6 +122,13 @@ static nsresult GetInstallDirPath(nsIFile* appDir, nsACString& installDirPath) { return NS_OK; } +#ifdef DEBUG +static void dump_argv(const char* aPrefix, char** argv, int argc) { + printf("%s - %d args\n", aPrefix, argc); + for (int i = 0; i < argc; ++i) printf(" %d: %s\n", i, argv[i]); +} +#endif + static bool GetFile(nsIFile* dir, const nsACString& name, nsCOMPtr<nsIFile>& result) { nsresult rv; @@ -184,6 +190,34 @@ enum UpdateStatus { eAppliedService, }; +#ifdef DEBUG +static const char* UpdateStatusToString(UpdateStatus aStatus) { + const char* rv = "unknown"; + switch (aStatus) { + case eNoUpdateAction: + rv = "NoUpdateAction"; + break; + case ePendingUpdate: + rv = "PendingUpdate"; + break; + case ePendingService: + rv = "PendingService"; + break; + case ePendingElevate: + rv = "PendingElevate"; + break; + case eAppliedUpdate: + rv = "AppliedUpdate"; + break; + case eAppliedService: + rv = "AppliedService"; + break; + } + + return rv; +} +#endif + /** * Returns a value indicating what needs to be done in order to handle an * update. @@ -256,6 +290,11 @@ static bool IsOlderVersion(nsIFile* versionFile, const char* appVersion) { return false; } +#ifdef DEBUG + printf("IsOlderVersion checking appVersion %s against updateVersion %s\n", + appVersion, buf); +#endif + return mozilla::Version(appVersion) > buf; } @@ -412,6 +451,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir, gfxPlatformMac::WaitForFontRegistration(); } +# ifndef BASE_BROWSER_UPDATE // We need to detect whether elevation is required for this update. This can // occur when an admin user installs the application, but another admin // user attempts to update (see bug 394984). @@ -438,6 +478,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir, } } } +# endif #endif nsAutoCString applyToDirPath; @@ -550,6 +591,9 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir, } LOG(("spawning updater process [%s]\n", updaterPath.get())); +#ifdef DEBUG + dump_argv("ApplyUpdate updater", argv, argc); +#endif #if defined(XP_UNIX) && !defined(XP_MACOSX) // We use execv to spawn the updater process on all UNIX systems except Mac @@ -587,11 +631,15 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir, } } #elif defined(XP_MACOSX) +# ifdef DEBUG +dump_argv("ApplyUpdate after SetupMacCommandLine", argv, argc); +# endif if (restart) { // Ensure we've added URLs to load into the app command line if we're // restarting. CommandLineServiceMac::SetupMacCommandLine(argc, argv, restart); +# ifndef BASE_BROWSER_UPDATE if (needElevation) { bool hasLaunched = LaunchElevatedUpdate(argc, argv, outpid); free(argv); @@ -601,6 +649,7 @@ if (restart) { } exit(0); } +# endif } if (isStaged) { @@ -672,14 +721,25 @@ nsresult ProcessUpdates(nsIFile* greDir, nsIFile* appDir, nsIFile* updRootDir, bool restart, ProcessType* pid) { nsresult rv; -#ifdef XP_WIN - // If we're in a package, we know any updates that we find are not for us. - if (mozilla::widget::WinUtils::HasPackageIdentity()) { - return NS_OK; +#if defined(XP_WIN) && defined(BASE_BROWSER_UPDATE) + // Try to remove the "tobedeleted" directory which, if present, contains + // files that could not be removed during a previous update (e.g., DLLs + // that were in use and therefore locked by Windows). + nsCOMPtr<nsIFile> deleteDir; + nsresult winrv = appDir->Clone(getter_AddRefs(deleteDir)); + if (NS_SUCCEEDED(winrv)) { + winrv = deleteDir->AppendNative("tobedeleted"_ns); + if (NS_SUCCEEDED(winrv)) { + winrv = deleteDir->Remove(true); + } } #endif nsCOMPtr<nsIFile> updatesDir; +#ifdef DEBUG + printf("ProcessUpdates updateRootDir: %s appVersion: %s\n", + updRootDir->HumanReadablePath().get(), appVersion); +#endif rv = updRootDir->Clone(getter_AddRefs(updatesDir)); NS_ENSURE_SUCCESS(rv, rv); rv = updatesDir->AppendNative("updates"_ns); @@ -699,6 +759,12 @@ nsresult ProcessUpdates(nsIFile* greDir, nsIFile* appDir, nsIFile* updRootDir, nsCOMPtr<nsIFile> statusFile; UpdateStatus status = GetUpdateStatus(updatesDir, statusFile); +#ifdef DEBUG + printf("ProcessUpdates status: %s (%d)\n", UpdateStatusToString(status), + status); + printf("ProcessUpdates updatesDir: %s\n", + updatesDir->HumanReadablePath().get()); +#endif switch (status) { case ePendingUpdate: case ePendingService: { @@ -766,13 +832,16 @@ nsUpdateProcessor::ProcessUpdate() { NS_ENSURE_SUCCESS(rv, rv); } + nsAutoCString appVersion; +#ifdef BASE_BROWSER_VERSION_QUOTED + appVersion = BASE_BROWSER_VERSION_QUOTED; +#else nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1", &rv); NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString appVersion; rv = appInfo->GetVersion(appVersion); NS_ENSURE_SUCCESS(rv, rv); +#endif // Copy the parameters to the StagedUpdateInfo structure shared with the // worker thread. diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 988da8e20b85c3e465cec8c23b2dbf9ba7905876..bcf8e771570f3e67a2000d3232624651ea9fc41e 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -96,6 +96,10 @@ nsIFile* gDataDirHome = nullptr; nsCOMPtr<nsIFile> gDataDirProfileLocal = nullptr; nsCOMPtr<nsIFile> gDataDirProfile = nullptr; +#if defined(RELATIVE_DATA_DIR) +mozilla::Maybe<nsCOMPtr<nsIFile>> gDataDirPortable; +#endif + // These are required to allow nsXREDirProvider to be usable in xpcshell tests. // where gAppData is null. #if defined(XP_MACOSX) || defined(XP_UNIX) @@ -215,7 +219,9 @@ nsresult nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult) { nsresult rv = GetUserDataDirectory(getter_AddRefs(file), false); if (NS_SUCCEEDED(rv)) { -#if !defined(XP_UNIX) || defined(XP_MACOSX) + // For some reason, we have decided not to append "Profiles" in Tor Browser. + // So, let's keep removing it, or we should somehow migrate the profile. +#if !defined(TOR_BROWSER) && (!defined(XP_UNIX) || defined(XP_MACOSX)) rv = file->AppendNative("Profiles"_ns); #endif // We must create the profile directory here if it does not exist. @@ -233,7 +239,7 @@ nsresult nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult) { nsresult rv = GetUserDataDirectory(getter_AddRefs(file), true); if (NS_SUCCEEDED(rv)) { -#if !defined(XP_UNIX) || defined(XP_MACOSX) +#if !defined(TOR_BROWSER) && (!defined(XP_UNIX) || defined(XP_MACOSX)) rv = file->AppendNative("Profiles"_ns); #endif // We must create the profile directory here if it does not exist. @@ -552,6 +558,25 @@ void nsXREDirProvider::FinishInitializingUserPrefs() { } } +#ifdef MOZ_WIDGET_GTK +static nsresult SetFontconfigConfigFile(nsCOMPtr<nsIFile> appDir) { + NS_ENSURE_TRUE(appDir, NS_ERROR_NULL_POINTER); + nsCOMPtr<nsIFile> confDir; + nsresult rv = appDir->Clone(getter_AddRefs(confDir)); + NS_ENSURE_SUCCESS(rv, rv); + rv = confDir->AppendNative("fonts"_ns); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoCString confPath; + rv = confDir->GetNativePath(confPath); + NS_ENSURE_SUCCESS(rv, rv); + if (NS_WARN_IF(setenv("FONTCONFIG_PATH", confPath.BeginReading(), 1) != 0 || + setenv("FONTCONFIG_FILE", "fonts.conf", 1) != 0)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} +#endif + NS_IMETHODIMP nsXREDirProvider::DoStartup() { nsresult rv; @@ -570,6 +595,13 @@ nsXREDirProvider::DoStartup() { */ MOZ_ASSERT(mPrefsInitialized); +#ifdef MOZ_WIDGET_GTK + // FontConfig might be initialized by GTK/Pango, so we need to define its + // config variables before doing anything. + rv = SetFontconfigConfigFile(mGREDir); + NS_ENSURE_SUCCESS(rv, rv); +#endif + bool safeModeNecessary = false; nsCOMPtr<nsIAppStartup> appStartup( mozilla::components::AppStartup::Service()); @@ -909,7 +941,52 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult, rv = appFile->GetParent(getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); -#ifdef XP_MACOSX +#if defined(BASE_BROWSER_UPDATE) + // For Base Browser and derivatives, we store update history, etc. within the + // UpdateInfo directory under the user data directory. +# if defined(ANDROID) +# error "The Base Browser updater is not supported on Android." +# endif + nsCOMPtr<nsIFile> dataDir; + rv = GetUserDataDirectoryHome(getter_AddRefs(dataDir), false); + NS_ENSURE_SUCCESS(rv, rv); + rv = dataDir->GetParent(getter_AddRefs(updRoot)); + NS_ENSURE_SUCCESS(rv, rv); +# if !defined(XP_MACOSX) + // For Tor Browser, the profile directory is TorBrowser/Data/Browser. + // Updates used to be in TorBrowser/updateInfo, so go up two directories. + // If we switch to data directory outside also on Windows and on Linux, we + // should remove this block. + dataDir = updRoot; + rv = dataDir->GetParent(getter_AddRefs(updRoot)); + NS_ENSURE_SUCCESS(rv, rv); +# endif + rv = updRoot->AppendNative("UpdateInfo"_ns); + NS_ENSURE_SUCCESS(rv, rv); + +# if defined(XP_MACOSX) + // Since the data directory may be shared among different installations of the + // application, embed the app path in the update dir so that the update + // history is partitioned. This is much less likely to be an issue on Linux or + // Windows, because our packages for those platforms include a "container" + // folder that provides partitioning by default, and we do not support use of + // a shared, OS-recommended area for user data on those platforms. + nsAutoString appPath; + rv = appFile->GetPath(appPath); + NS_ENSURE_SUCCESS(rv, rv); + int32_t dotIndex = appPath.RFind(u".app"); + if (dotIndex == kNotFound) { + dotIndex = appPath.Length(); + } + appPath = Substring(appPath, 1, dotIndex - 1); + rv = updRoot->AppendRelativePath(appPath); + NS_ENSURE_SUCCESS(rv, rv); +# endif + + updRoot.forget(aResult); + return NS_OK; +// The rest of the function is for ! BASE_BROWSER_UPDATE +#elif defined(XP_MACOSX) nsCOMPtr<nsIFile> appRootDirFile; nsCOMPtr<nsIFile> localDir; nsAutoString appDirPath; @@ -1025,10 +1102,124 @@ nsresult nsXREDirProvider::SetUserDataProfileDirectory(nsCOMPtr<nsIFile>& aFile, return NS_OK; } +#if defined(RELATIVE_DATA_DIR) +nsresult nsXREDirProvider::GetPortableDataDir(nsIFile** aFile, + bool& aIsPortable) { + if (gDataDirPortable) { + if (*gDataDirPortable) { + nsresult rv = (*gDataDirPortable)->Clone(aFile); + NS_ENSURE_SUCCESS(rv, rv); + aIsPortable = true; + } else { + aIsPortable = false; + } + return NS_OK; + } + + nsCOMPtr<nsIFile> exeFile, exeDir; + bool persistent = false; + nsresult rv = + GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(exeFile)); + NS_ENSURE_SUCCESS(rv, rv); + rv = exeFile->Normalize(); + NS_ENSURE_SUCCESS(rv, rv); + rv = exeFile->GetParent(getter_AddRefs(exeDir)); + NS_ENSURE_SUCCESS(rv, rv); + +# if defined(XP_MACOSX) + nsAutoString exeDirPath; + rv = exeDir->GetPath(exeDirPath); + NS_ENSURE_SUCCESS(rv, rv); + // When the browser is installed in /Applications, we never run in portable + // mode. + if (exeDirPath.LowerCaseFindASCII("/applications/") == 0) { + aIsPortable = false; + gDataDirPortable.emplace(nullptr); + return NS_OK; + } +# endif + +# if defined(MOZ_WIDGET_GTK) + // On Linux, Firefox supports the is-packaged-app for the .deb distribution. + // We cannot use mozilla::widget::IsPackagedAppFileExists because it relies on + // this service to be initialized, but this function is called during the + // initialization. Therefore, we need to re-implement this check. + nsLiteralCString systemInstallNames[] = {"system-install"_ns, + "is-packaged-app"_ns}; +# else + nsLiteralCString systemInstallNames[] = {"system-install"_ns}; +# endif + for (const nsLiteralCString& fileName : systemInstallNames) { + nsCOMPtr<nsIFile> systemInstallFile; + rv = exeDir->Clone(getter_AddRefs(systemInstallFile)); + NS_ENSURE_SUCCESS(rv, rv); + rv = systemInstallFile->AppendNative(fileName); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists = false; + rv = systemInstallFile->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + if (exists) { + gDataDirPortable.emplace(nullptr); + return NS_OK; + } + } + + nsCOMPtr<nsIFile> localDir = exeDir; +# if defined(XP_MACOSX) + rv = exeDir->GetParent(getter_AddRefs(localDir)); + NS_ENSURE_SUCCESS(rv, rv); + exeDir = localDir; + rv = exeDir->GetParent(getter_AddRefs(localDir)); + NS_ENSURE_SUCCESS(rv, rv); +# endif + rv = localDir->SetRelativePath(localDir.get(), + nsLiteralCString(RELATIVE_DATA_DIR)); + NS_ENSURE_SUCCESS(rv, rv); + +# if defined(XP_MACOSX) + // On macOS we try to create the directory immediately to switch to + // system-install mode if needed (e.g., when running from the DMG). + bool exists = false; + rv = localDir->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + if (!exists) { + rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700); + if (NS_FAILED(rv)) { + aIsPortable = false; + gDataDirPortable.emplace(nullptr); + return NS_OK; + } + } +# endif + + gDataDirPortable.emplace(localDir); + rv = (*gDataDirPortable)->Clone(aFile); + NS_ENSURE_SUCCESS(rv, rv); + aIsPortable = true; + return rv; +} +#endif + +NS_IMETHODIMP nsXREDirProvider::GetIsPortableMode(bool* aIsPortableMode) { +#ifdef RELATIVE_DATA_DIR + if (gDataDirPortable) { + *aIsPortableMode = *gDataDirPortable; + } else { + nsCOMPtr<nsIFile> dir; + GetPortableDataDir(getter_AddRefs(dir), *aIsPortableMode); + } +#else + *aIsPortableMode = false; +#endif + return NS_OK; +} + nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal) { // Copied from nsAppFileLocationProvider (more or less) nsresult rv; + NS_ENSURE_ARG_POINTER(aFile); nsCOMPtr<nsIFile> localDir; if (aLocal && gDataDirHomeLocal) { @@ -1038,18 +1229,40 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, return gDataDirHome->Clone(aFile); } +#if defined(RELATIVE_DATA_DIR) + RefPtr<nsXREDirProvider> singleton = GetSingleton(); + if (!singleton) { + return NS_ERROR_OUT_OF_MEMORY; + } + bool isPortable = false; + rv = singleton->GetPortableDataDir(getter_AddRefs(localDir), isPortable); + NS_ENSURE_SUCCESS(rv, rv); + if (isPortable) { + if (aLocal) { + rv = localDir->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); + } + NS_IF_ADDREF(*aFile = localDir); + return rv; + } +#endif + #if defined(XP_MACOSX) FSRef fsRef; +# if defined(TOR_BROWSER) + OSType folderType = kApplicationSupportFolderType; +# else OSType folderType; if (aLocal) { folderType = kCachedDataFolderType; } else { -# ifdef MOZ_THUNDERBIRD +# ifdef MOZ_THUNDERBIRD folderType = kDomainLibraryFolderType; -# else +# else folderType = kApplicationSupportFolderType; -# endif +# endif } +# endif OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef); NS_ENSURE_FALSE(err, NS_ERROR_FAILURE); @@ -1062,6 +1275,17 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, rv = dirFileMac->InitWithFSRef(&fsRef); NS_ENSURE_SUCCESS(rv, rv); +# if defined(TOR_BROWSER) + rv = dirFileMac->AppendNative("TorBrowser-Data"_ns); + NS_ENSURE_SUCCESS(rv, rv); + rv = dirFileMac->AppendNative("Browser"_ns); + NS_ENSURE_SUCCESS(rv, rv); + if (aLocal) { + rv = dirFileMac->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); + } +# endif + localDir = dirFileMac; #elif defined(XP_IOS) nsAutoCString userDir; @@ -1231,6 +1455,13 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { return NS_OK; } +#if defined(RELATIVE_DATA_DIR) + if (gDataDirPortable && *gDataDirPortable) { + // Do nothing in portable mode + return NS_OK; + } +#endif + nsAutoCString profile; nsAutoCString appName; nsAutoCString vendor; @@ -1244,6 +1475,9 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { nsresult rv = NS_OK; #if defined(XP_MACOSX) +# ifndef TOR_BROWSER + // For Tor Browser we already prepare the data directory as we need it, even + // when we are running a system install. if (!profile.IsEmpty()) { rv = AppendProfileString(aFile, profile.get()); } else { @@ -1253,6 +1487,7 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { rv = aFile->AppendNative(appName); } NS_ENSURE_SUCCESS(rv, rv); +# endif #elif defined(XP_WIN) if (!profile.IsEmpty()) { @@ -1337,3 +1572,21 @@ nsresult nsXREDirProvider::AppendProfileString(nsIFile* aFile, return NS_OK; } + +nsresult nsXREDirProvider::GetTorBrowserUserDataDir(nsIFile** aFile) { +#ifdef ANDROID + // We expect this function not to be called on Android. + // But, for sake of completeness, we handle also this case. + const char* homeDir = getenv("HOME"); + if (!homeDir || !*homeDir) { + return NS_ERROR_FAILURE; + } + return NS_NewNativeLocalFile(nsDependentCString(homeDir), true, aFile); +#endif + + NS_ENSURE_ARG_POINTER(aFile); + nsCOMPtr<nsIFile> dataDir; + nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(dataDir), false); + NS_ENSURE_SUCCESS(rv, rv); + return dataDir->GetParent(aFile); +} diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index d139f8fa3db234a06eb29ed292af5c03e1cc4bbd..89be849a5ab7d73399d1f8f2001496bceff2f5bc 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -109,6 +109,13 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2, */ nsresult GetProfileDir(nsIFile** aResult); + /** + * Get the Tor Browser user data directory. + * We take for granted that for Tor Browser we can take the parent directory + * of the one returned by GetUserDataDirectoryHome (with aLocal = false). + */ + nsresult GetTorBrowserUserDataDir(nsIFile** aFile); + private: nsresult GetFilesInternal(const char* aProperty, nsISimpleEnumerator** aResult); @@ -134,6 +141,14 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2, void Append(nsIFile* aDirectory); +#if defined(RELATIVE_DATA_DIR) + /** + * Get the path to the portable data dir, if the application is running in + * portable mode. + */ + nsresult GetPortableDataDir(nsIFile** aFile, bool& aIsPortable); +#endif + // On OSX, mGREDir points to .app/Contents/Resources nsCOMPtr<nsIFile> mGREDir; // On OSX, mGREBinDir points to .app/Contents/MacOS diff --git a/tools/base-browser/git-rebase-fixup-preprocessor b/tools/base-browser/git-rebase-fixup-preprocessor new file mode 100755 index 0000000000000000000000000000000000000000..309740710085eb41f65487da74b4c50a44dfba84 --- /dev/null +++ b/tools/base-browser/git-rebase-fixup-preprocessor @@ -0,0 +1,93 @@ +#!/usr/bin/python +""" +Pre-process a git todo file before passing it on to an editor. +""" + +import sys +import os +import subprocess +import re + +EDITOR_ENV_NAME = "GIT_REBASE_FIXUP_PREPROCESSOR_USER_EDITOR" + +try: + editor = os.environ[EDITOR_ENV_NAME] +except KeyError: + print(f"Missing {EDITOR_ENV_NAME} in environment", file=sys.stderr) + exit(1) + +if len(sys.argv) < 2: + print("Missing filename argument", file=sys.stderr) + exit(1) + +filename = sys.argv[1] + + +class TodoLine: + """ + Represents a line in the git todo file. + """ + + _PICK_REGEX = re.compile(r"^pick [a-f0-9]+ (?P<fixups>(fixup! )*)(?P<title>.*)") + + def __init__(self, line): + """ + Create a new line with the given text content. + """ + self._line = line + self._make_fixup = False + + match = self._PICK_REGEX.match(line) + if match: + self._is_pick = True + self._num_fixups = len(match.group("fixups")) / len("fixup! ") + self._title = match.group("title") + else: + self._is_pick = False + self._num_fixups = False + self._title = None + + def add_to_list_try_fixup(self, existing_lines): + """ + Add the TodoLine to the given list of other TodoLine, trying to fix up + one of the existing lines. + """ + if not self._num_fixups: # Not a fixup line. + existing_lines.append(self) + return + + # Search from the end of the list upwards. + for index in reversed(range(len(existing_lines))): + other = existing_lines[index] + if ( + other._is_pick + and self._num_fixups == other._num_fixups + 1 + and other._title == self._title + ): + self._make_fixup = True + existing_lines.insert(index + 1, self) + return + + # No line found to fixup. + existing_lines.append(self) + + def get_text(self): + """ + Get the text for the line to save. + """ + line = self._line + if self._make_fixup: + line = line.replace("pick", "fixup", 1) + return line + + +todo_lines = [] +with open(filename, "r", encoding="utf8") as todo_file: + for line in todo_file: + TodoLine(line).add_to_list_try_fixup(todo_lines) + +with open(filename, "w", encoding="utf8") as todo_file: + for line in todo_lines: + todo_file.write(line.get_text()) + +exit(subprocess.run([editor, *sys.argv[1:]], check=False).returncode) diff --git a/tools/base-browser/l10n/combine-translation-versions.py b/tools/base-browser/l10n/combine-translation-versions.py new file mode 100644 index 0000000000000000000000000000000000000000..45010344b6bf2b94c1b0c989a490ca7af48111c7 --- /dev/null +++ b/tools/base-browser/l10n/combine-translation-versions.py @@ -0,0 +1,372 @@ +import argparse +import json +import logging +import os +import re +import subprocess + +from combine import combine_files + +arg_parser = argparse.ArgumentParser( + description="Combine a translation file across two different versions" +) + +arg_parser.add_argument( + "current_branch", metavar="<current-branch>", help="branch for the newest version" +) +arg_parser.add_argument( + "files", metavar="<files>", help="JSON specifying the translation files" +) +arg_parser.add_argument("outname", metavar="<json>", help="name of the json output") + +args = arg_parser.parse_args() + +logging.basicConfig() +logger = logging.getLogger("combine-translation-versions") +logger.setLevel(logging.INFO) + + +def in_pink(msg: str) -> str: + """Present a message as pink in the terminal output. + + :param msg: The message to wrap in pink. + :returns: The message to print to terminal. + """ + # Pink and bold. + return f"\x1b[1;38;5;212m{msg}\x1b[0m" + + +def git_run(git_args: list[str]) -> None: + """Run a git command. + + :param git_args: The arguments that should follow "git". + """ + # Add some text to give context to git's stderr appearing in log. + logger.info("Running: " + in_pink("git " + " ".join(git_args))) + subprocess.run(["git", *git_args], check=True) + + +def git_text(git_args: list[str]) -> str: + """Get the text output for a git command. + + :param git_args: The arguments that should follow "git". + :returns: The stdout of the command. + """ + logger.info("Running: " + in_pink("git " + " ".join(git_args))) + return subprocess.run( + ["git", *git_args], text=True, check=True, stdout=subprocess.PIPE + ).stdout + + +def git_lines(git_args: list[str]) -> list[str]: + """Get the lines from a git command. + + :param git_args: The arguments that should follow "git". + :returns: The non-empty lines from stdout of the command. + """ + return [line for line in git_text(git_args).split("\n") if line] + + +class TranslationFile: + """Represents a translation file.""" + + def __init__(self, path: str, content: str) -> None: + self.path = path + self.content = content + + +class BrowserBranch: + """Represents a browser git branch.""" + + def __init__(self, branch_name: str, is_head: bool = False) -> None: + """Create a new instance. + + :param branch_name: The branch's git name. + :param is_head: Whether the branch matches "HEAD". + """ + version_match = re.match( + r"(?P<prefix>[a-z]+\-browser)\-" + r"(?P<firefox>[0-9]+(?:\.[0-9]+){1,2})esr\-" + r"(?P<browser>[0-9]+\.[05])\-" + r"(?P<number>[0-9]+)$", + branch_name, + ) + + if not version_match: + raise ValueError(f"Unable to parse the version from the ref {branch_name}") + + self.name = branch_name + self.prefix = version_match.group("prefix") + self.browser_version = version_match.group("browser") + # Convert tor-browser to "Tor Browser", and similar. + browser_name = self.prefix.replace("-", " ").title() + self.browser_version_name = f"{browser_name} {self.browser_version}" + + self._is_head = is_head + self._ref = "HEAD" if is_head else f"origin/{branch_name}" + + firefox_nums = [int(n) for n in version_match.group("firefox").split(".")] + if len(firefox_nums) == 2: + firefox_nums.append(0) + browser_nums = [int(n) for n in self.browser_version.split(".")] + branch_number = int(version_match.group("number")) + # Prioritise the firefox ESR version, then the browser version then the + # branch number. + self._ordered = ( + firefox_nums[0], + firefox_nums[1], + firefox_nums[2], + browser_nums[0], + browser_nums[1], + branch_number, + ) + + # Minor version for browser is only ever "0" or "5", so we can convert + # the version to an integer. + self._browser_int_version = int(2 * float(self.browser_version)) + + self._file_paths: list[str] | None = None + + def release_below(self, other: "BrowserBranch", num: int) -> bool: + """Determine whether another branch is within range of a previous + browser release. + + The browser versions are expected to increment by "0.5", and a previous + release branch's version is expected to be `num * 0.5` behind the + current one. + + :param other: The branch to compare. + :param num: The number of "0.5" releases behind to test with. + """ + return other._browser_int_version == self._browser_int_version - num + + def __lt__(self, other: "BrowserBranch") -> bool: + return self._ordered < other._ordered + + def __gt__(self, other: "BrowserBranch") -> bool: + return self._ordered > other._ordered + + def _matching_dirs(self, path: str, dir_list: list[str]) -> bool: + """Test that a path is contained in the list of dirs. + + :param path: The path to check. + :param dir_list: The list of directories to check against. + :returns: Whether the path matches. + """ + for dir_path in dir_list: + if os.path.commonpath([dir_path, path]) == dir_path: + return True + return False + + def get_file( + self, filename: str, search_dirs: list[str] | None + ) -> TranslationFile | None: + """Fetch the file content for the named file in this branch. + + :param filename: The name of the file to fetch the content for. + :param search_dirs: The directories to restrict the search to, or None + to search for the file anywhere. + :returns: The file, or `None` if no file could be found. + """ + if self._file_paths is None: + if not self._is_head: + # Minimal fetch of non-HEAD branch to get the file paths. + # Individual file blobs will be downloaded as needed. + git_run( + ["fetch", "--depth=1", "--filter=blob:none", "origin", self.name] + ) + self._file_paths = git_lines( + ["ls-tree", "-r", "--format=%(path)", self._ref] + ) + + matching = [ + path + for path in self._file_paths + if os.path.basename(path) == filename + and (search_dirs is None or self._matching_dirs(path, search_dirs)) + ] + if not matching: + return None + if len(matching) > 1: + raise Exception(f"Multiple occurrences of {filename}") + + path = matching[0] + + return TranslationFile( + path=path, content=git_text(["cat-file", "blob", f"{self._ref}:{path}"]) + ) + + +def get_stable_branch( + compare_version: BrowserBranch, +) -> tuple[BrowserBranch, BrowserBranch | None]: + """Find the most recent stable branch in the origin repository. + + :param compare_version: The development branch to compare against. + :returns: The stable and legacy branches. If no legacy branch is found, + `None` will be returned instead. + """ + # We search for build1 tags. These are added *after* the rebase of browser + # commits, so the corresponding branch should contain our strings. + # Moreover, we *assume* that the branch with the most recent ESR version + # with such a tag will be used in the *next* stable build in + # tor-browser-build. + tag_glob = f"{compare_version.prefix}-*-build1" + + # To speed up, only fetch the tags without blobs. + git_run( + ["fetch", "--depth=1", "--filter=object:type=tag", "origin", "tag", tag_glob] + ) + stable_branches = [] + legacy_branches = [] + stable_annotation_regex = re.compile(r"\bstable\b") + legacy_annotation_regex = re.compile(r"\blegacy\b") + tag_pattern = re.compile( + rf"^{re.escape(compare_version.prefix)}-[^-]+esr-[^-]+-[^-]+-build1$" + ) + + for build_tag, annotation in ( + line.split(" ", 1) for line in git_lines(["tag", "-n1", "--list", tag_glob]) + ): + if not tag_pattern.match(build_tag): + continue + is_stable = bool(stable_annotation_regex.search(annotation)) + is_legacy = bool(legacy_annotation_regex.search(annotation)) + if not is_stable and not is_legacy: + continue + try: + # Branch name is the same as the tag, minus "-build1". + branch = BrowserBranch(re.sub(r"-build1$", "", build_tag)) + except ValueError: + logger.warning(f"Could not read the version for {build_tag}") + continue + if branch.prefix != compare_version.prefix: + continue + if is_stable: + # Stable can be one release version behind. + # NOTE: In principle, when switching between versions there may be a + # window of time where the development branch has not yet progressed + # to the next "0.5" release, so has the same browser version as the + # stable branch. So we also allow for matching browser versions. + # NOTE: + # 1. The "Will be unused in" message will not make sense, but we do + # not expect string differences in this scenario. + # 2. We do not expect this scenario to last for long. + if not ( + compare_version.release_below(branch, 1) + or compare_version.release_below(branch, 0) + ): + continue + stable_branches.append(branch) + elif is_legacy: + # Legacy can be two release versions behind. + # We also allow for being just one version behind. + if not ( + compare_version.release_below(branch, 2) + or compare_version.release_below(branch, 1) + ): + continue + legacy_branches.append(branch) + + if not stable_branches: + raise Exception("No stable build1 branch found") + + return ( + # Return the stable branch with the highest version. + max(stable_branches), + max(legacy_branches) if legacy_branches else None, + ) + + +current_branch = BrowserBranch(args.current_branch, is_head=True) + +stable_branch, legacy_branch = get_stable_branch(current_branch) + +if os.environ.get("TRANSLATION_INCLUDE_LEGACY", "") != "true": + legacy_branch = None + +files_list = [] + +for file_dict in json.loads(args.files): + name = file_dict["name"] + where_dirs = file_dict.get("where", None) + current_file = current_branch.get_file(name, where_dirs) + stable_file = stable_branch.get_file(name, where_dirs) + + if current_file is None and stable_file is None: + # No file in either branch. + logger.warning(f"{name} does not exist in either the current or stable branch") + elif current_file is None: + logger.warning(f"{name} deleted in the current branch") + elif stable_file is None: + logger.warning(f"{name} does not exist in the stable branch") + elif current_file.path != stable_file.path: + logger.warning( + f"{name} has different paths in the current and stable branch. " + f"{current_file.path} : {stable_file.path}" + ) + + content = combine_files( + name, + None if current_file is None else current_file.content, + None if stable_file is None else stable_file.content, + f"Will be unused in {current_branch.browser_version_name}!", + ) + + if legacy_branch and not file_dict.get("exclude-legacy", False): + legacy_file = legacy_branch.get_file(name, where_dirs) + if legacy_file is not None and current_file is None and stable_file is None: + logger.warning(f"{name} still exists in the legacy branch") + elif legacy_file is None: + logger.warning(f"{name} does not exist in the legacy branch") + elif stable_file is not None and legacy_file.path != stable_file.path: + logger.warning( + f"{name} has different paths in the stable and legacy branch. " + f"{stable_file.path} : {legacy_file.path}" + ) + elif current_file is not None and legacy_file.path != current_file.path: + logger.warning( + f"{name} has different paths in the current and legacy branch. " + f"{current_file.path} : {legacy_file.path}" + ) + + content = combine_files( + name, + content, + legacy_file.content, + f"Unused in {stable_branch.browser_version_name}!", + ) + elif legacy_branch: + logger.info(f"Excluding legacy branch for {name}") + + files_list.append( + { + "name": name, + # If "directory" is unspecified, we place the file directly beneath + # en-US/ in the translation repository. i.e. "". + "directory": file_dict.get("directory", ""), + "branch": file_dict["branch"], + "content": content, + } + ) + + +ci_commit = os.environ.get("CI_COMMIT_SHA", "") +ci_url_base = os.environ.get("CI_PROJECT_URL", "") + +json_data = { + "commit": ci_commit, + "commit-url": f"{ci_url_base}/-/commit/{ci_commit}" + if (ci_commit and ci_url_base) + else "", + "project-path": os.environ.get("CI_PROJECT_PATH", ""), + "current-branch": current_branch.name, + "stable-branch": stable_branch.name, + "files": files_list, +} + +if legacy_branch: + json_data["legacy-branch"] = legacy_branch.name + +with open(args.outname, "w") as file: + json.dump(json_data, file) diff --git a/tools/base-browser/l10n/combine/__init__.py b/tools/base-browser/l10n/combine/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..67dc30efbea0d1727f767a9c68a15930d1e8a28c --- /dev/null +++ b/tools/base-browser/l10n/combine/__init__.py @@ -0,0 +1,3 @@ +# flake8: noqa + +from .combine import combine_files diff --git a/tools/base-browser/l10n/combine/combine.py b/tools/base-browser/l10n/combine/combine.py new file mode 100644 index 0000000000000000000000000000000000000000..1d8edddb5be37008678ce5211f76d17268c47dc6 --- /dev/null +++ b/tools/base-browser/l10n/combine/combine.py @@ -0,0 +1,181 @@ +import re +from typing import TYPE_CHECKING, Any + +from compare_locales.parser import getParser +from compare_locales.parser.android import AndroidEntity, DocumentWrapper +from compare_locales.parser.base import Comment, Entity, Junk, Whitespace +from compare_locales.parser.dtd import DTDEntity +from compare_locales.parser.fluent import FluentComment, FluentEntity +from compare_locales.parser.properties import PropertiesEntity + +if TYPE_CHECKING: + from collections.abc import Iterable + + +def combine_files( + filename: str, + new_content: str | None, + old_content: str | None, + comment_prefix: str, +) -> str | None: + """Combine two translation files into one to include all strings from both. + The new content is presented first, and any strings only found in the old + content are placed at the end with an additional comment. + + :param filename: The filename for the file, determines the format. + :param new_content: The new content for the file, or None if it has been + deleted. + :param old_content: The old content for the file, or None if it did not + exist before. + :comment_prefix: A comment to include for any strings that are only found in + the old content. This will be placed before any other comments for the + string. + + :returns: The combined content, or None if both given contents are None. + """ + if new_content is None and old_content is None: + return None + + # getParser from compare_locale returns the same instance for the same file + # extension. + parser = getParser(filename) + + is_android = filename.endswith(".xml") + if new_content is None: + if is_android: + # File was deleted, add some document parts. + content_start = ( + '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\n<resources>\n' + ) + content_end = "</resources>\n" + else: + # Treat as an empty file. + content_start = "" + content_end = "" + existing_keys = [] + else: + parser.readUnicode(new_content) + + # Start with the same content as the current file. + # For android strings, we want to keep the final "</resources>" until after. + if is_android: + closing_match = re.match( + r"^(.*)(</resources>\s*)$", parser.ctx.contents, re.DOTALL + ) + if not closing_match: + raise ValueError("Missing a final </resources>") + content_start = closing_match.group(1) + content_end = closing_match.group(2) + else: + content_start = parser.ctx.contents + content_end = "" + existing_keys = [entry.key for entry in parser.walk(only_localizable=True)] + + # For Fluent, we want to prefix the strings using GroupComments. + # On weblate this will cause all the strings that fall under the GroupComment's + # scope to have the prefix added to their "notes". + # We set up an initial GroupComment for the first string we find. This will also + # end the scope of the last GroupComment in the new translation file. + # This will be replaced with a the next GroupComment when it is found. + fluent_group_comment_prefix = f"\n## {comment_prefix}\n" + fluent_group_comment: str | None = fluent_group_comment_prefix + + # For other formats, we want to keep all the comment lines that come directly + # before the string. + # In compare_locales.parser, only the comment line directly before an Entity + # counts as the pre_comment for that Entity. I.e. only this line will be + # included in Entity.all + # However, in weblate every comment line that comes before the Entity is + # included as a comment. So we also want to keep these additional comments to + # preserve them for weblate. + # We gather these extra comments in stacked_comments, and clear them whenever we + # reach an Entity or a blank line (Whitespace is more than "\n"). + stacked_comments: list[str] = [] + + additions: list[str] = [] + + entry_iter: Iterable[Any] = () + # If the file does not exist in the old branch, don't make any additions. + if old_content is not None: + parser.readUnicode(old_content) + entry_iter = parser.walk(only_localizable=False) + for entry in entry_iter: + if isinstance(entry, Junk): + raise ValueError(f"Unexpected Junk: {entry.all}") + if isinstance(entry, Whitespace): + # Clear stacked comments if more than one empty line. + if entry.all != "\n": + stacked_comments.clear() + continue + if isinstance(entry, Comment): + if isinstance(entry, FluentComment): + # Don't stack Fluent comments. + # Only the comments included in Entity.pre_comment count towards + # that Entity's comment. + if entry.all.startswith("##"): + # A Fluent GroupComment + if entry.all == "##": + # Empty GroupComment. Used to end the scope of a previous + # GroupComment. + # Replace this with our prefix comment. + fluent_group_comment = fluent_group_comment_prefix + else: + # Prefix the group comment. + fluent_group_comment = ( + f"{fluent_group_comment_prefix}{entry.all}\n" + ) + else: + stacked_comments.append(entry.all) + continue + if isinstance(entry, DocumentWrapper): + # Not needed. + continue + + if not isinstance(entry, Entity): + raise ValueError(f"Unexpected type: {entry.__class__.__name__}") + + if entry.key in existing_keys: + # Already included this string in the new translation file. + # Drop the gathered comments for this Entity. + stacked_comments.clear() + continue + + if isinstance(entry, FluentEntity): + if fluent_group_comment is not None: + # We have a found GroupComment which has not been included yet. + # All following Entity's will be under its scope, until the next + # GroupComment. + additions.append(fluent_group_comment) + # Added GroupComment, so don't need to add again. + fluent_group_comment = None + elif isinstance(entry, DTDEntity): + # Include our additional comment before we print the rest for this + # Entity. + additions.append(f"<!-- LOCALIZATION NOTE: {comment_prefix} -->") + elif isinstance(entry, PropertiesEntity): + additions.append(f"# {comment_prefix}") + elif isinstance(entry, AndroidEntity): + additions.append(f"<!-- {comment_prefix} -->") + else: + raise ValueError(f"Unexpected Entity type: {entry.__class__.__name__}") + + # Add any other comment lines that came directly before this Entity. + additions.extend(stacked_comments) + stacked_comments.clear() + additions.append(entry.all) + + content_middle = "" + + if additions: + # New line before and after the additions + additions.insert(0, "") + additions.append("") + if is_android: + content_middle = "\n ".join(additions) + else: + content_middle = "\n".join(additions) + + # Remove " " in otherwise blank lines. + content_middle = re.sub("^ +$", "", content_middle, flags=re.MULTILINE) + + return content_start + content_middle + content_end diff --git a/tools/base-browser/l10n/combine/tests/README b/tools/base-browser/l10n/combine/tests/README new file mode 100644 index 0000000000000000000000000000000000000000..c7403e87a4a5297277f4e6b65b1281dcf50b901a --- /dev/null +++ b/tools/base-browser/l10n/combine/tests/README @@ -0,0 +1,2 @@ +python tests to be run with pytest. +Requires the compare-locales package. diff --git a/tools/base-browser/l10n/combine/tests/__init__.py b/tools/base-browser/l10n/combine/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/base-browser/l10n/combine/tests/test_android.py b/tools/base-browser/l10n/combine/tests/test_android.py new file mode 100644 index 0000000000000000000000000000000000000000..0e83248d42ab9ed0b15f6a264f5c78d2c815bd4d --- /dev/null +++ b/tools/base-browser/l10n/combine/tests/test_android.py @@ -0,0 +1,330 @@ +import textwrap + +from combine import combine_files + + +def wrap_in_xml(content): + if content is None: + return None + # Allow for indents to make the tests more readable. + content = textwrap.dedent(content) + return f"""\ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<resources> +{textwrap.indent(content, " ")}</resources> +""" + + +def assert_result(new_content, old_content, expect): + new_content = wrap_in_xml(new_content) + old_content = wrap_in_xml(old_content) + expect = wrap_in_xml(expect) + assert expect == combine_files( + "test_strings.xml", new_content, old_content, "REMOVED STRING" + ) + + +def test_combine_empty(): + assert_result(None, None, None) + + +def test_combine_new_file(): + # New file with no old content. + assert_result( + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + None, + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + ) + + +def test_combine_removed_file(): + # Entire file was removed. + assert_result( + None, + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + """\ + + <!-- REMOVED STRING --> + <string name="string_1">First</string> + <!-- REMOVED STRING --> + <string name="string_2">Second</string> + """, + ) + + +def test_no_change(): + content = """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """ + assert_result(content, content, content) + + +def test_added_string(): + assert_result( + """\ + <string name="string_1">First</string> + <string name="string_new">NEW</string> + <string name="string_2">Second</string> + """, + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + """\ + <string name="string_1">First</string> + <string name="string_new">NEW</string> + <string name="string_2">Second</string> + """, + ) + + +def test_removed_string(): + assert_result( + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + """\ + <string name="string_1">First</string> + <string name="removed">REMOVED</string> + <string name="string_2">Second</string> + """, + """\ + <string name="string_1">First</string> + <string name="string_2">Second</string> + + <!-- REMOVED STRING --> + <string name="removed">REMOVED</string> + """, + ) + + +def test_removed_and_added(): + assert_result( + """\ + <string name="new_1">New string</string> + <string name="string_1">First</string> + <string name="string_2">Second</string> + <string name="new_2">New string 2</string> + """, + """\ + <string name="string_1">First</string> + <string name="removed_1">First removed</string> + <string name="removed_2">Second removed</string> + <string name="string_2">Second</string> + <string name="removed_3">Third removed</string> + """, + """\ + <string name="new_1">New string</string> + <string name="string_1">First</string> + <string name="string_2">Second</string> + <string name="new_2">New string 2</string> + + <!-- REMOVED STRING --> + <string name="removed_1">First removed</string> + <!-- REMOVED STRING --> + <string name="removed_2">Second removed</string> + <!-- REMOVED STRING --> + <string name="removed_3">Third removed</string> + """, + ) + + +def test_updated(): + # String content was updated. + assert_result( + """\ + <string name="changed_string">NEW</string> + """, + """\ + <string name="changed_string">OLD</string> + """, + """\ + <string name="changed_string">NEW</string> + """, + ) + + +def test_updated_comment(): + # String comment was updated. + assert_result( + """\ + <!-- NEW --> + <string name="changed_string">string</string> + """, + """\ + <!-- OLD --> + <string name="changed_string">string</string> + """, + """\ + <!-- NEW --> + <string name="changed_string">string</string> + """, + ) + # Comment added. + assert_result( + """\ + <!-- NEW --> + <string name="changed_string">string</string> + """, + """\ + <string name="changed_string">string</string> + """, + """\ + <!-- NEW --> + <string name="changed_string">string</string> + """, + ) + # Comment removed. + assert_result( + """\ + <string name="changed_string">string</string> + """, + """\ + <!-- OLD --> + <string name="changed_string">string</string> + """, + """\ + <string name="changed_string">string</string> + """, + ) + + # With file comments + assert_result( + """\ + <!-- NEW file comment --> + + <!-- NEW --> + <string name="changed_string">string</string> + """, + """\ + <!-- OLD file comment --> + + <!-- OLD --> + <string name="changed_string">string</string> + """, + """\ + <!-- NEW file comment --> + + <!-- NEW --> + <string name="changed_string">string</string> + """, + ) + + +def test_reordered(): + # String was re_ordered. + assert_result( + """\ + <string name="string_1">value</string> + <string name="moved_string">move</string> + """, + """\ + <string name="moved_string">move</string> + <string name="string_1">value</string> + """, + """\ + <string name="string_1">value</string> + <string name="moved_string">move</string> + """, + ) + + +def test_removed_string_with_comment(): + assert_result( + """\ + <!-- Comment for first. --> + <string name="string_1">First</string> + <string name="string_2">Second</string> + """, + """\ + <!-- Comment for first. --> + <string name="string_1">First</string> + <!-- Comment for removed. --> + <string name="removed">REMOVED</string> + <string name="string_2">Second</string> + """, + """\ + <!-- Comment for first. --> + <string name="string_1">First</string> + <string name="string_2">Second</string> + + <!-- REMOVED STRING --> + <!-- Comment for removed. --> + <string name="removed">REMOVED</string> + """, + ) + + # With file comments and multi-line. + # All comments prior to a removed string are moved with it, until another + # entity or blank line is reached. + assert_result( + """\ + <!-- First File comment --> + + <!-- Comment for first. --> + <!-- Comment 2 for first. --> + <string name="string_1">First</string> + + <!-- Second --> + <!-- File comment --> + + <string name="string_2">Second</string> + """, + """\ + <!-- First File comment --> + + <!-- Comment for first. --> + <!-- Comment 2 for first. --> + <string name="string_1">First</string> + <string name="removed_1">First removed</string> + <!-- Comment for second removed. --> + <string name="removed_2">Second removed</string> + + <!-- Removed file comment --> + + <!-- Comment 1 for third removed --> + <!-- Comment 2 for third removed --> + <string name="removed_3">Third removed</string> + + <!-- Second --> + <!-- File comment --> + + <string name="removed_4">Fourth removed</string> + <string name="string_2">Second</string> + """, + """\ + <!-- First File comment --> + + <!-- Comment for first. --> + <!-- Comment 2 for first. --> + <string name="string_1">First</string> + + <!-- Second --> + <!-- File comment --> + + <string name="string_2">Second</string> + + <!-- REMOVED STRING --> + <string name="removed_1">First removed</string> + <!-- REMOVED STRING --> + <!-- Comment for second removed. --> + <string name="removed_2">Second removed</string> + <!-- REMOVED STRING --> + <!-- Comment 1 for third removed --> + <!-- Comment 2 for third removed --> + <string name="removed_3">Third removed</string> + <!-- REMOVED STRING --> + <string name="removed_4">Fourth removed</string> + """, + ) diff --git a/tools/base-browser/l10n/combine/tests/test_dtd.py b/tools/base-browser/l10n/combine/tests/test_dtd.py new file mode 100644 index 0000000000000000000000000000000000000000..644439db7f12e9822526fa78bfd7944bc0d82c22 --- /dev/null +++ b/tools/base-browser/l10n/combine/tests/test_dtd.py @@ -0,0 +1,325 @@ +import textwrap + +from combine import combine_files + + +def assert_result(new_content, old_content, expect): + # Allow for indents to make the tests more readable. + if new_content is not None: + new_content = textwrap.dedent(new_content) + if old_content is not None: + old_content = textwrap.dedent(old_content) + if expect is not None: + expect = textwrap.dedent(expect) + assert expect == combine_files( + "test.dtd", new_content, old_content, "REMOVED STRING" + ) + + +def test_combine_empty(): + assert_result(None, None, None) + + +def test_combine_new_file(): + # New file with no old content. + assert_result( + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + None, + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + ) + + +def test_combine_removed_file(): + # Entire file was removed. + assert_result( + None, + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + """\ + + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY string.1 "First"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY string.2 "Second"> + """, + ) + + +def test_no_change(): + content = """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """ + assert_result(content, content, content) + + +def test_added_string(): + assert_result( + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.new "NEW"> + <!ENTITY string.2 "Second"> + """, + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.new "NEW"> + <!ENTITY string.2 "Second"> + """, + ) + + +def test_removed_string(): + assert_result( + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + """\ + <!ENTITY string.1 "First"> + <!ENTITY removed "REMOVED"> + <!ENTITY string.2 "Second"> + """, + """\ + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed "REMOVED"> + """, + ) + + +def test_removed_and_added(): + assert_result( + """\ + <!ENTITY new.1 "New string"> + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + <!ENTITY new.2 "New string 2"> + """, + """\ + <!ENTITY string.1 "First"> + <!ENTITY removed.1 "First removed"> + <!ENTITY removed.2 "Second removed"> + <!ENTITY string.2 "Second"> + <!ENTITY removed.3 "Third removed"> + """, + """\ + <!ENTITY new.1 "New string"> + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + <!ENTITY new.2 "New string 2"> + + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed.1 "First removed"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed.2 "Second removed"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed.3 "Third removed"> + """, + ) + + +def test_updated(): + # String content was updated. + assert_result( + """\ + <!ENTITY changed.string "NEW"> + """, + """\ + <!ENTITY changed.string "OLD"> + """, + """\ + <!ENTITY changed.string "NEW"> + """, + ) + + +def test_updated_comment(): + # String comment was updated. + assert_result( + """\ + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + """\ + <!-- LOCALIZATION NOTE: OLD --> + <!ENTITY changed.string "string"> + """, + """\ + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + ) + # Comment added. + assert_result( + """\ + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + """\ + <!ENTITY changed.string "string"> + """, + """\ + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + ) + # Comment removed. + assert_result( + """\ + <!ENTITY changed.string "string"> + """, + """\ + <!-- LOCALIZATION NOTE: OLD --> + <!ENTITY changed.string "string"> + """, + """\ + <!ENTITY changed.string "string"> + """, + ) + + # With multiple comments + assert_result( + """\ + <!-- NEW FILE COMMENT --> + + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + """\ + <!-- OLD --> + + <!-- LOCALIZATION NOTE: OLD --> + <!ENTITY changed.string "string"> + """, + """\ + <!-- NEW FILE COMMENT --> + + <!-- LOCALIZATION NOTE: NEW --> + <!ENTITY changed.string "string"> + """, + ) + + +def test_reordered(): + # String was re.ordered. + assert_result( + """\ + <!ENTITY string.1 "value"> + <!ENTITY moved.string "move"> + """, + """\ + <!ENTITY moved.string "move"> + <!ENTITY string.1 "value"> + """, + """\ + <!ENTITY string.1 "value"> + <!ENTITY moved.string "move"> + """, + ) + + +def test_removed_string_with_comment(): + assert_result( + """\ + <!-- LOCALIZATION NOTE: Comment for first. --> + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + """, + """\ + <!-- LOCALIZATION NOTE: Comment for first. --> + <!ENTITY string.1 "First"> + <!-- LOCALIZATION NOTE: Comment for removed. --> + <!ENTITY removed "REMOVED"> + <!ENTITY string.2 "Second"> + """, + """\ + <!-- LOCALIZATION NOTE: Comment for first. --> + <!ENTITY string.1 "First"> + <!ENTITY string.2 "Second"> + + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!-- LOCALIZATION NOTE: Comment for removed. --> + <!ENTITY removed "REMOVED"> + """, + ) + + # With multiple lines of comments. + + assert_result( + """\ + <!-- First file comment --> + + <!-- LOCALIZATION NOTE: Comment for first. --> + <!-- LOCALIZATION NOTE: Comment 2 for first. --> + <!ENTITY string.1 "First"> + + <!-- Second + - file + - comment --> + + <!ENTITY string.2 "Second"> + """, + """\ + <!-- First file comment --> + + <!-- LOCALIZATION NOTE: Comment for first. --> + <!ENTITY string.1 "First"> + <!ENTITY removed.1 "First removed"> + <!-- LOCALIZATION NOTE: Comment for second removed. --> + <!ENTITY removed.2 "Second removed"> + + <!-- Removed file comment --> + + <!-- LOCALIZATION NOTE: Comment for third removed. --> + <!-- LOCALIZATION NOTE: Comment 2 for + third removed. --> + <!ENTITY removed.3 "Third removed"> + + <!-- Second + - file + - comment --> + + <!ENTITY removed.4 "Fourth removed"> + <!ENTITY string.2 "Second"> + """, + """\ + <!-- First file comment --> + + <!-- LOCALIZATION NOTE: Comment for first. --> + <!-- LOCALIZATION NOTE: Comment 2 for first. --> + <!ENTITY string.1 "First"> + + <!-- Second + - file + - comment --> + + <!ENTITY string.2 "Second"> + + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed.1 "First removed"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!-- LOCALIZATION NOTE: Comment for second removed. --> + <!ENTITY removed.2 "Second removed"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!-- LOCALIZATION NOTE: Comment for third removed. --> + <!-- LOCALIZATION NOTE: Comment 2 for + third removed. --> + <!ENTITY removed.3 "Third removed"> + <!-- LOCALIZATION NOTE: REMOVED STRING --> + <!ENTITY removed.4 "Fourth removed"> + """, + ) diff --git a/tools/base-browser/l10n/combine/tests/test_fluent.py b/tools/base-browser/l10n/combine/tests/test_fluent.py new file mode 100644 index 0000000000000000000000000000000000000000..928fff5aec2cbe576bfbc081ba1a392893908439 --- /dev/null +++ b/tools/base-browser/l10n/combine/tests/test_fluent.py @@ -0,0 +1,344 @@ +import textwrap + +from combine import combine_files + + +def assert_result(new_content, old_content, expect): + # Allow for indents to make the tests more readable. + if new_content is not None: + new_content = textwrap.dedent(new_content) + if old_content is not None: + old_content = textwrap.dedent(old_content) + if expect is not None: + expect = textwrap.dedent(expect) + assert expect == combine_files( + "test.ftl", new_content, old_content, "REMOVED STRING" + ) + + +def test_combine_empty(): + assert_result(None, None, None) + + +def test_combine_new_file(): + # New file with no old content. + assert_result( + """\ + string-1 = First + string-2 = Second + """, + None, + """\ + string-1 = First + string-2 = Second + """, + ) + + +def test_combine_removed_file(): + # Entire file was removed. + assert_result( + None, + """\ + string-1 = First + string-2 = Second + """, + """\ + + + ## REMOVED STRING + + string-1 = First + string-2 = Second + """, + ) + + +def test_no_change(): + content = """\ + string-1 = First + string-2 = Second + """ + assert_result(content, content, content) + + +def test_added_string(): + assert_result( + """\ + string-1 = First + string-new = NEW + string-2 = Second + """, + """\ + string-1 = First + string-2 = Second + """, + """\ + string-1 = First + string-new = NEW + string-2 = Second + """, + ) + + +def test_removed_string(): + assert_result( + """\ + string-1 = First + string-2 = Second + """, + """\ + string-1 = First + removed = REMOVED + string-2 = Second + """, + """\ + string-1 = First + string-2 = Second + + + ## REMOVED STRING + + removed = REMOVED + """, + ) + + +def test_removed_and_added(): + assert_result( + """\ + new-1 = New string + string-1 = + .attr = First + string-2 = Second + new-2 = + .title = New string 2 + """, + """\ + string-1 = + .attr = First + removed-1 = First removed + removed-2 = + .attr = Second removed + string-2 = Second + removed-3 = Third removed + """, + """\ + new-1 = New string + string-1 = + .attr = First + string-2 = Second + new-2 = + .title = New string 2 + + + ## REMOVED STRING + + removed-1 = First removed + removed-2 = + .attr = Second removed + removed-3 = Third removed + """, + ) + + +def test_updated(): + # String content was updated. + assert_result( + """\ + changed-string = NEW + """, + """\ + changed-string = OLD + """, + """\ + changed-string = NEW + """, + ) + + +def test_updated_comment(): + # String comment was updated. + assert_result( + """\ + # NEW + changed-string = string + """, + """\ + # OLD + changed-string = string + """, + """\ + # NEW + changed-string = string + """, + ) + # Comment added. + assert_result( + """\ + # NEW + changed-string = string + """, + """\ + changed-string = string + """, + """\ + # NEW + changed-string = string + """, + ) + # Comment removed. + assert_result( + """\ + changed-string = string + """, + """\ + # OLD + changed-string = string + """, + """\ + changed-string = string + """, + ) + + # With group comments. + assert_result( + """\ + ## GROUP NEW + + # NEW + changed-string = string + """, + """\ + ## GROUP OLD + + # OLD + changed-string = string + """, + """\ + ## GROUP NEW + + # NEW + changed-string = string + """, + ) + + +def test_reordered(): + # String was re-ordered. + assert_result( + """\ + string-1 = value + moved-string = move + """, + """\ + moved-string = move + string-1 = value + """, + """\ + string-1 = value + moved-string = move + """, + ) + + +def test_removed_string_with_comment(): + assert_result( + """\ + # Comment for first. + string-1 = First + string-2 = Second + """, + """\ + # Comment for first. + string-1 = First + # Comment for removed. + removed = REMOVED + string-2 = Second + """, + """\ + # Comment for first. + string-1 = First + string-2 = Second + + + ## REMOVED STRING + + # Comment for removed. + removed = REMOVED + """, + ) + + # Group comments are combined with the "REMOVED STRING" comments. + # If strings have no group comment, then a single "REMOVED STRING" is + # included for them. + assert_result( + """\ + ## First Group comment + + # Comment for first. + string-1 = First + + ## + + no-group = No group comment + + ## Second + ## Group comment + + string-2 = Second + """, + """\ + ## First Group comment + + # Comment for first. + string-1 = First + removed-1 = First removed + # Comment for second removed. + removed-2 = Second removed + + ## + + no-group = No group comment + removed-3 = Third removed + + ## Second + ## Group comment + + removed-4 = Fourth removed + string-2 = Second + """, + """\ + ## First Group comment + + # Comment for first. + string-1 = First + + ## + + no-group = No group comment + + ## Second + ## Group comment + + string-2 = Second + + + ## REMOVED STRING + ## First Group comment + + removed-1 = First removed + # Comment for second removed. + removed-2 = Second removed + + ## REMOVED STRING + + removed-3 = Third removed + + ## REMOVED STRING + ## Second + ## Group comment + + removed-4 = Fourth removed + """, + ) diff --git a/tools/base-browser/l10n/combine/tests/test_properties.py b/tools/base-browser/l10n/combine/tests/test_properties.py new file mode 100644 index 0000000000000000000000000000000000000000..da9626b559df504e1f80011122932abf55e122f0 --- /dev/null +++ b/tools/base-browser/l10n/combine/tests/test_properties.py @@ -0,0 +1,322 @@ +import textwrap + +from combine import combine_files + + +def assert_result(new_content, old_content, expect): + # Allow for indents to make the tests more readable. + if new_content is not None: + new_content = textwrap.dedent(new_content) + if old_content is not None: + old_content = textwrap.dedent(old_content) + if expect is not None: + expect = textwrap.dedent(expect) + assert expect == combine_files( + "test.properties", new_content, old_content, "REMOVED STRING" + ) + + +def test_combine_empty(): + assert_result(None, None, None) + + +def test_combine_new_file(): + # New file with no old content. + assert_result( + """\ + string.1 = First + string.2 = Second + """, + None, + """\ + string.1 = First + string.2 = Second + """, + ) + + +def test_combine_removed_file(): + # Entire file was removed. + assert_result( + None, + """\ + string.1 = First + string.2 = Second + """, + """\ + + # REMOVED STRING + string.1 = First + # REMOVED STRING + string.2 = Second + """, + ) + + +def test_no_change(): + content = """\ + string.1 = First + string.2 = Second + """ + assert_result(content, content, content) + + +def test_added_string(): + assert_result( + """\ + string.1 = First + string.new = NEW + string.2 = Second + """, + """\ + string.1 = First + string.2 = Second + """, + """\ + string.1 = First + string.new = NEW + string.2 = Second + """, + ) + + +def test_removed_string(): + assert_result( + """\ + string.1 = First + string.2 = Second + """, + """\ + string.1 = First + removed = REMOVED + string.2 = Second + """, + """\ + string.1 = First + string.2 = Second + + # REMOVED STRING + removed = REMOVED + """, + ) + + +def test_removed_and_added(): + assert_result( + """\ + new.1 = New string + string.1 = First + string.2 = Second + new.2 = New string 2 + """, + """\ + string.1 = First + removed.1 = First removed + removed.2 = Second removed + string.2 = Second + removed.3 = Third removed + """, + """\ + new.1 = New string + string.1 = First + string.2 = Second + new.2 = New string 2 + + # REMOVED STRING + removed.1 = First removed + # REMOVED STRING + removed.2 = Second removed + # REMOVED STRING + removed.3 = Third removed + """, + ) + + +def test_updated(): + # String content was updated. + assert_result( + """\ + changed.string = NEW + """, + """\ + changed.string = OLD + """, + """\ + changed.string = NEW + """, + ) + + +def test_updated_comment(): + # String comment was updated. + assert_result( + """\ + # NEW + changed.string = string + """, + """\ + # OLD + changed.string = string + """, + """\ + # NEW + changed.string = string + """, + ) + # Comment added. + assert_result( + """\ + # NEW + changed.string = string + """, + """\ + changed.string = string + """, + """\ + # NEW + changed.string = string + """, + ) + # Comment removed. + assert_result( + """\ + changed.string = string + """, + """\ + # OLD + changed.string = string + """, + """\ + changed.string = string + """, + ) + + # With file comments + assert_result( + """\ + # NEW file comment + + # NEW + changed.string = string + """, + """\ + # OLD file comment + + # OLD + changed.string = string + """, + """\ + # NEW file comment + + # NEW + changed.string = string + """, + ) + + +def test_reordered(): + # String was re.ordered. + assert_result( + """\ + string.1 = value + moved.string = move + """, + """\ + moved.string = move + string.1 = value + """, + """\ + string.1 = value + moved.string = move + """, + ) + + +def test_removed_string_with_comment(): + assert_result( + """\ + # Comment for first. + string.1 = First + string.2 = Second + """, + """\ + # Comment for first. + string.1 = First + # Comment for removed. + removed = REMOVED + string.2 = Second + """, + """\ + # Comment for first. + string.1 = First + string.2 = Second + + # REMOVED STRING + # Comment for removed. + removed = REMOVED + """, + ) + + # With file comments and multi-line. + # All comments prior to a removed string are moved with it, until another + # entity or blank line is reached. + assert_result( + """\ + # First File comment + + # Comment for first. + # Comment 2 for first. + string.1 = First + + # Second + # File comment + + string.2 = Second + """, + """\ + # First File comment + + # Comment for first. + # Comment 2 for first. + string.1 = First + removed.1 = First removed + # Comment for second removed. + removed.2 = Second removed + + # Removed file comment + + # Comment 1 for third removed + # Comment 2 for third removed + removed.3 = Third removed + + # Second + # File comment + + removed.4 = Fourth removed + string.2 = Second + """, + """\ + # First File comment + + # Comment for first. + # Comment 2 for first. + string.1 = First + + # Second + # File comment + + string.2 = Second + + # REMOVED STRING + removed.1 = First removed + # REMOVED STRING + # Comment for second removed. + removed.2 = Second removed + # REMOVED STRING + # Comment 1 for third removed + # Comment 2 for third removed + removed.3 = Third removed + # REMOVED STRING + removed.4 = Fourth removed + """, + ) diff --git a/tools/base-browser/tb-dev b/tools/base-browser/tb-dev new file mode 100755 index 0000000000000000000000000000000000000000..937d7a419289f668414766c29f08238bd681acc2 --- /dev/null +++ b/tools/base-browser/tb-dev @@ -0,0 +1,817 @@ +#!/usr/bin/env python3 +# PYTHON_ARGCOMPLETE_OK +""" +Useful tools for working on tor-browser repository. +""" + +import argparse +import atexit +import json +import os +import re +import subprocess +import sys +import tempfile +import termios +import urllib.request + +import argcomplete + +GIT_PATH = "/usr/bin/git" +UPSTREAM_URLS = { + "tor-browser": [ + "https://gitlab.torproject.org/tpo/applications/tor-browser.git", + "git@gitlab.torproject.org:tpo/applications/tor-browser.git", + ], + "mullvad-browser": [ + "https://gitlab.torproject.org/tpo/applications/mullvad-browser.git", + "git@gitlab.torproject.org:tpo/applications/mullvad-browser.git", + ], +} +FIXUP_PREPROCESSOR_EDITOR = "git-rebase-fixup-preprocessor" +USER_EDITOR_ENV_NAME = "GIT_REBASE_FIXUP_PREPROCESSOR_USER_EDITOR" + + +class TbDevException(Exception): + pass + + +def git_run(args, check=True, env=None): + """ + Run a git command with output sent to stdout. + """ + if env is not None: + tmp_env = dict(os.environ) + for key, value in env.items(): + tmp_env[key] = value + env = tmp_env + try: + subprocess.run([GIT_PATH, *args], check=check, env=env) + except subprocess.CalledProcessError as err: + raise TbDevException(str(err)) from err + + +def git_get(args): + """ + Run a git command with each non-empty line returned in a list. + """ + try: + git_process = subprocess.run( + [GIT_PATH, *args], text=True, stdout=subprocess.PIPE, check=True + ) + except subprocess.CalledProcessError as err: + raise TbDevException(str(err)) from err + return [line for line in git_process.stdout.split("\n") if line] + + +local_root = None + + +def get_local_root(): + """ + Get the path for the tor-browser root directory. + """ + global local_root + if local_root is None: + try: + # Make sure we have a matching remote in this git repository. + if get_upstream_details()["is-browser-repo"]: + local_root = git_get(["rev-parse", "--show-toplevel"])[0] + else: + local_root = "" + except TbDevException: + local_root = "" + return local_root + + +def determine_upstream_details(): + """ + Determine details about the upstream. + """ + remote_urls = { + remote: git_get(["remote", "get-url", remote])[0] + for remote in git_get(["remote"]) + } + + matches = { + remote: repo + for repo, url_list in UPSTREAM_URLS.items() + for url in url_list + for remote, fetch_url in remote_urls.items() + if fetch_url == url + } + + is_browser_repo = len(matches) > 0 + details = {"is-browser-repo": is_browser_repo} + + origin_remote_repo = matches.get("origin", None) + upstream_remote_repo = matches.get("upstream", None) + + if origin_remote_repo is not None: + if upstream_remote_repo is None: + details["remote"] = "origin" + details["repo-name"] = origin_remote_repo + # Else, both "upstream" and "origin" point to a remote repo. Not clear + # which should be used. + elif upstream_remote_repo is not None: + details["remote"] = "upstream" + details["repo-name"] = upstream_remote_repo + elif len(matches) == 1: + remote = next(iter(matches.keys())) + details["remote"] = remote + details["repo-name"] = matches[remote] + # Else, the upstream is ambiguous. + + return details + + +cached_upstream_details = None + + +def get_upstream_details(): + """ + Get details about the upstream repository. + """ + global cached_upstream_details + if cached_upstream_details is None: + cached_upstream_details = determine_upstream_details() + return cached_upstream_details + + +class Reference: + """Represents a git reference to a commit.""" + + def __init__(self, name, commit): + self.name = name + self.commit = commit + + +def get_refs(ref_type, name_start): + """ + Get a list of references that match the given 'ref_type' ("tag" or "remote" + or "head") that starts with the given 'name_start'. + """ + if ref_type == "tag": + # Instead of returning tag hash, return the commit hash it points to. + fstring = "%(*objectname)" + ref_start = "refs/tags/" + elif ref_type == "remote": + fstring = "%(objectname)" + ref_start = "refs/remotes/" + elif ref_type == "head": + fstring = "%(objectname)" + ref_start = "refs/heads/" + else: + raise TypeError(f"Unknown type {ref_type}") + + fstring = f"{fstring},%(refname)" + pattern = f"{ref_start}{name_start}**" + + def line_to_ref(line): + [commit, ref_name] = line.split(",", 1) + return Reference(ref_name.replace(ref_start, "", 1), commit) + + return [ + line_to_ref(line) + for line in git_get(["for-each-ref", f"--format={fstring}", pattern]) + ] + + +def get_nearest_ref(ref_type, name_start, search_from): + """ + Search backwards from the 'search_from' commit to find the first commit + that matches the given 'ref_type' that starts with the given 'name_start'. + """ + ref_list = get_refs(ref_type, name_start) + + for commit in git_get(["rev-list", "-1000", search_from]): + for ref in ref_list: + if commit == ref.commit: + return ref + + raise TbDevException(f"No {name_start} commit found in the last 1000 commits") + + +def get_firefox_ref(search_from): + """ + Search backwards from the 'search_from' commit to find the commit that comes + from firefox. + """ + return get_nearest_ref("tag", "FIREFOX_", search_from) + + +def get_upstream_tracking_branch(search_from): + return git_get(["rev-parse", "--abbrev-ref", f"{search_from}@{{upstream}}"])[0] + + +def get_upstream_basis_commit(search_from): + """ + Get the first common ancestor of search_from that is also in its upstream + branch. + """ + upstream_branch = get_upstream_tracking_branch(search_from) + commit = git_get(["merge-base", search_from, upstream_branch])[0] + # Verify that the upstream commit shares the same firefox basis. Otherwise, + # this would indicate that the upstream is on an early or later FIREFOX + # base. + upstream_firefox = get_firefox_ref(upstream_branch).commit + search_firefox = get_firefox_ref(search_from).commit + if upstream_firefox != search_firefox: + raise TbDevException( + f"Upstream of {search_from} has a different FIREFOX base. " + "You might want to set the upstream tracking branch to a new value." + ) + return commit + + +def get_changed_files(from_commit, staged=False): + """ + Get a list of filenames relative to the current working directory that have + been changed since 'from_commit' (non-inclusive). + """ + args = ["diff"] + if staged: + args.append("--staged") + args.append("--name-only") + args.append(from_commit) + return [ + os.path.relpath(os.path.join(get_local_root(), filename)) + for filename in git_get(args) + ] + + +def file_contains(filename, regex): + """ + Return whether the file is a utf-8 text file containing the regular + expression given by 'regex'. + """ + with open(filename, "r", encoding="utf-8") as file: + try: + for line in file: + if regex.search(line): + return True + except UnicodeDecodeError: + # Not a text file + pass + return False + + +def get_gitlab_default(): + """ + Get the name of the default branch on gitlab. + """ + repo_name = get_upstream_details().get("repo-name", None) + if repo_name is None: + raise TbDevException("Cannot determine the repository name") + query = f""" + query {{ + project(fullPath: "tpo/applications/{repo_name}") {{ + repository {{ rootRef }} + }} + }} + """ + request_data = {"query": re.sub(r"\s+", "", query)} + gitlab_request = urllib.request.Request( + "https://gitlab.torproject.org/api/graphql", + headers={ + "Content-Type": "application/json", + "User-Agent": "", + }, + data=json.dumps(request_data).encode("ascii"), + ) + + with urllib.request.urlopen(gitlab_request, timeout=20) as response: + return json.load(response)["data"]["project"]["repository"]["rootRef"] + + +def within_browser_root(): + """ + Whether we are with the tor browser root. + """ + root = get_local_root() + if not root: + return False + return os.path.commonpath([os.getcwd(), root]) == root + + +# * -------------------- * +# | Methods for commands | +# * -------------------- * + + +def show_firefox_commit(_args): + """ + Print the tag name and commit for the last firefox commit below the current + HEAD. + """ + ref = get_firefox_ref("HEAD") + print(ref.name) + print(ref.commit) + + +def show_upstream_basis_commit(_args): + """ + Print the last upstream commit for the current HEAD. + """ + print(get_upstream_basis_commit("HEAD")) + + +def show_log(args): + """ + Show the git log between the current HEAD and the last firefox commit. + """ + commit = get_firefox_ref("HEAD").commit + git_run(["log", f"{commit}..HEAD", *args.gitargs], check=False) + + +def show_files_containing(args): + """ + List all the files that that have been modified for tor browser, that also + contain a regular expression. + """ + try: + regex = re.compile(args.regex) + except re.error as err: + raise TbDevException(f"{args.regex} is not a valid python regex") from err + + file_list = get_changed_files(get_firefox_ref("HEAD").commit) + + for filename in file_list: + if not os.path.isfile(filename): + # deleted ofile + continue + if file_contains(filename, regex): + print(filename) + + +def show_changed_files(_args): + """ + List all the files that have been modified relative to upstream. + """ + for filename in get_changed_files(get_upstream_basis_commit("HEAD")): + print(filename) + + +def lint_changed_files(args): + """ + Lint all the files that have been modified relative to upstream. + """ + os.chdir(get_local_root()) + file_list = [ + f + for f in get_changed_files(get_upstream_basis_commit("HEAD")) + if os.path.isfile(f) # Not deleted + ] + # We add --warnings since clang only reports whitespace issues as warnings. + subprocess.run( + ["./mach", "lint", "--warnings", "soft", *args.lintargs, *file_list], + check=False, + ) + + +def prompt_user(prompt, convert): + """ + Ask the user for some input until the given converter returns without + throwing a ValueError. + """ + while True: + # Flush out stdin. + termios.tcflush(sys.stdin, termios.TCIFLUSH) + print(prompt, end="") + sys.stdout.flush() + try: + return convert(sys.stdin.readline().strip()) + except ValueError: + # Continue to prompt. + pass + + +def binary_reply_default_no(value): + """Process a 'y' or 'n' reply, defaulting to 'n' if empty.""" + if value == "": + return False + if value.lower() == "y": + return True + if value.lower() == "n": + return False + raise ValueError() + + +def get_fixup_for_file(filename, firefox_commit): + """Find the commit the given file should fix up.""" + + def parse_log_line(line): + [commit, short_ref, title] = line.split(",", 2) + return {"commit": commit, "short-ref": short_ref, "title": title} + + options = [ + parse_log_line(line) + for line in git_get( + [ + "log", + "--pretty=format:%H,%h,%s", + f"{firefox_commit}..HEAD", + "--", + filename, + ] + ) + ] + if not options: + print(f"No commit found for {filename}") + return None + + def valid_index(val): + if val == "d": + return val + + is_patch = val.startswith("p") + if is_patch: + val = val[1:] + + # May raise a ValueError. + as_index = int(val) + if as_index < 0 or as_index > len(options): + raise ValueError() + + if as_index == 0: + if is_patch: + raise ValueError() + return None + + return (is_patch, options[as_index - 1]["commit"]) + + while True: + print(f"For {filename}:\n") + print(" \x1b[1m0\x1b[0m: None") + for index, opt in enumerate(options): + print( + f" \x1b[1m{index + 1}\x1b[0m: " + + f"\x1b[1;38;5;212m{opt['short-ref']}\x1b[0m " + + opt["title"] + ) + print("") + response = prompt_user( + "Choose an <index> to fixup, or '0' to skip this file, " + "or 'd' to view the pending diff, " + "or 'p<index>' to view the patch for the index: ", + valid_index, + ) + if response is None: + # Skip this file. + return None + + if response == "d": + git_run(["diff", "--", filename]) + continue + + view_patch, commit = response + if view_patch: + git_run(["log", "-p", "-1", commit, "--", filename]) + continue + + return commit + + +def auto_fixup(_args): + """ + Automatically find and fix up commits using the current unstaged changes. + """ + # Only want to search as far back as the firefox commit. + firefox_commit = get_firefox_ref("HEAD").commit + + staged_files = get_changed_files("HEAD", staged=True) + if staged_files: + raise TbDevException(f"Have already staged files: {staged_files}") + + fixups = {} + for filename in get_changed_files("HEAD"): + commit = get_fixup_for_file(filename, firefox_commit) + if commit is None: + continue + if commit not in fixups: + fixups[commit] = [filename] + else: + fixups[commit].append(filename) + print("") + + for commit, files in fixups.items(): + print("") + git_run(["add", *files]) + git_run(["commit", f"--fixup={commit}"]) + print("") + + if prompt_user( + "Edit fixup commit message? (y/\x1b[4mn\x1b[0m)", binary_reply_default_no + ): + git_run(["commit", "--amend"]) + + +def clean_fixups(_args): + """ + Perform an interactive rebase that automatically applies fixups, similar to + --autosquash but also works on fixups of fixups. + """ + user_editor = git_get(["var", "GIT_SEQUENCE_EDITOR"])[0] + sub_editor = os.path.join( + os.path.dirname(os.path.realpath(__file__)), FIXUP_PREPROCESSOR_EDITOR + ) + + git_run( + ["rebase", "--interactive"], + check=False, + env={"GIT_SEQUENCE_EDITOR": sub_editor, USER_EDITOR_ENV_NAME: user_editor}, + ) + + +def show_default(_args): + """ + Print the default branch name from gitlab. + """ + default_branch = get_gitlab_default() + upstream = get_upstream_details().get("remote", None) + if upstream is None: + raise TbDevException("Cannot determine the upstream remote") + print(f"{upstream}/{default_branch}") + + +def branch_from_default(args): + """ + Fetch the default gitlab branch from upstream and create a new local branch. + """ + default_branch = get_gitlab_default() + upstream = get_upstream_details().get("remote", None) + if upstream is None: + raise TbDevException("Cannot determine the upstream remote") + + git_run(["fetch", upstream, default_branch]) + git_run( + [ + "switch", + "--create", + args.branchname, + "--track", + f"{upstream}/{default_branch}", + ] + ) + + +def move_to_default(args): + """ + Fetch the default gitlab branch from upstream and move the specified + branch's commits on top. A new branch will be created tracking the default + branch, and the old branch will be renamed with a suffix for the old + tracking branch. This method will switch to the new branch, but will avoid + switching to the old branch to prevent triggering a CLOBBER build. + """ + branch_name = args.branch + if branch_name is None: + # Use current branch as default. + try: + branch_name = git_get(["branch", "--show-current"])[0] + except IndexError: + raise TbDevException("No current branch") + + current_upstream_branch = get_upstream_tracking_branch(branch_name) + default_branch = get_gitlab_default() + upstream = get_upstream_details().get("remote", None) + if upstream is None: + raise TbDevException("Cannot determine the upstream remote") + + git_run(["fetch", upstream, default_branch]) + + new_upstream_branch = f"{upstream}/{default_branch}" + if current_upstream_branch == new_upstream_branch: + print( + f"{branch_name} is already set to track the default branch {new_upstream_branch}." + ) + return + + # We want to avoid checking out the old branch because this can cause + # mozilla ./mach to do a CLOBBER build. + # Instead we create a new branch with the same name and cherry pick. + current_basis = get_upstream_basis_commit(branch_name) + old_branch_name = branch_name + "-" + get_firefox_ref(branch_name).name + + print(f"Moving old branch {branch_name} to {old_branch_name}") + git_run(["branch", "-m", branch_name, old_branch_name]) + + try: + git_run(["switch", "--create", branch_name, "--track", new_upstream_branch]) + except subprocess.CalledProcessError as err: + print(f"Moving {old_branch_name} back to {branch_name}") + git_run(["branch", "-m", old_branch_name, branch_name]) + raise err + + # Set check to False since cherry-pick might fail due to a merge conflict. + git_run(["cherry-pick", f"{current_basis}..{old_branch_name}"], check=False) + + +def show_range_diff(args): + """ + Show the range diff between two branches, from their firefox bases. + """ + firefox_commit_1 = get_firefox_ref(args.branch1).commit + firefox_commit_2 = get_firefox_ref(args.branch2).commit + git_run( + [ + "range-diff", + f"{firefox_commit_1}..{args.branch1}", + f"{firefox_commit_2}..{args.branch2}", + ], + check=False, + ) + + +def show_diff_diff(args): + """ + Show the diff between the diffs of two branches, relative to their firefox + bases. + """ + config_res = git_get(["config", "--get", "diff.tool"]) + if not config_res: + raise TbDevException("No diff.tool configured for git") + diff_tool = config_res[0] + + # Filter out parts of the diff we expect to be different. + index_regex = re.compile(r"index [0-9a-f]{12}\.\.[0-9a-f]{12}") + lines_regex = re.compile(r"@@ -[0-9]+,[0-9]+ \+[0-9]+,[0-9]+ @@(?P<rest>.*)") + + def save_diff(branch): + firefox_commit = get_firefox_ref(branch).commit + file_desc, file_name = tempfile.mkstemp( + text=True, prefix=f'{branch.split("/")[-1]}-' + ) + # Register deleting the file at exit. + atexit.register(os.remove, file_name) + + diff_process = subprocess.Popen( + [GIT_PATH, "diff", f"{firefox_commit}..{branch}"], + stdout=subprocess.PIPE, + text=True, + ) + + with os.fdopen(file_desc, "w") as file: + for line in diff_process.stdout: + if index_regex.match(line): + # Fake data that will match. + file.write("index ????????????..????????????\n") + continue + lines_match = lines_regex.match(line) + if lines_match: + # Fake data that will match. + file.write("@@ ?,? ?,? @@" + lines_match.group("rest")) + continue + file.write(line) + + status = diff_process.poll() + if status != 0: + raise TbDevException(f"git diff exited with status {status}") + + return file_name + + file_1 = save_diff(args.branch1) + file_2 = save_diff(args.branch2) + subprocess.run([diff_tool, file_1, file_2], check=False) + + +# * -------------------- * +# | Command line parsing | +# * -------------------- * + + +def branch_complete(prefix, parsed_args, **kwargs): + """ + Complete the argument with a branch name. + """ + if not within_browser_root(): + return [] + try: + branches = [ref.name for ref in get_refs("head", "")] + branches.extend([ref.name for ref in get_refs("remote", "")]) + branches.append("HEAD") + except Exception: + return [] + return [br for br in branches if br.startswith(prefix)] + + +parser = argparse.ArgumentParser() +subparsers = parser.add_subparsers(required=True) + +for name, details in { + "show-upstream-basis-commit": { + "func": show_upstream_basis_commit, + }, + "changed-files": { + "func": show_changed_files, + }, + "lint-changed-files": { + "func": lint_changed_files, + "args": { + "lintargs": { + "help": "argument to pass to ./mach lint", + "metavar": "-- lint-arg", + "nargs": "*", + }, + }, + }, + "auto-fixup": { + "func": auto_fixup, + }, + "clean-fixups": { + "func": clean_fixups, + }, + "show-default": { + "func": show_default, + }, + "branch-from-default": { + "func": branch_from_default, + "args": { + "branchname": { + "help": "the name for the new local branch", + "metavar": "<branch-name>", + }, + }, + }, + "move-to-default": { + "func": move_to_default, + "args": { + "branch": { + "help": "the branch to move, else uses the current branch", + "metavar": "<branch>", + "nargs": "?", + "completer": branch_complete, + }, + }, + }, + "show-firefox-commit": { + "func": show_firefox_commit, + }, + "log": { + "func": show_log, + "args": { + "gitargs": { + "help": "argument to pass to git log", + "metavar": "-- git-log-arg", + "nargs": "*", + }, + }, + }, + "branch-range-diff": { + "func": show_range_diff, + "args": { + "branch1": { + "help": "the first branch to compare", + "metavar": "<branch-1>", + "completer": branch_complete, + }, + "branch2": { + "help": "the second branch to compare", + "metavar": "<branch-2>", + "completer": branch_complete, + }, + }, + }, + "branch-diff-diff": { + "func": show_diff_diff, + "args": { + "branch1": { + "help": "the first branch to compare", + "metavar": "<branch-1>", + "completer": branch_complete, + }, + "branch2": { + "help": "the second branch to compare", + "metavar": "<branch-2>", + "completer": branch_complete, + }, + }, + }, + "files-containing": { + "func": show_files_containing, + "args": { + "regex": {"help": "the regex that the files must contain"}, + }, + }, +}.items(): + help_message = re.sub(r"\s+", " ", details["func"].__doc__).strip() + sub = subparsers.add_parser(name, help=help_message) + sub.set_defaults(func=details["func"]) + for arg, keywords in details.get("args", {}).items(): + completer = None + if "completer" in keywords: + completer = keywords["completer"] + del keywords["completer"] + sub_arg = sub.add_argument(arg, **keywords) + if completer is not None: + sub_arg.completer = completer + +argcomplete.autocomplete(parser) + +try: + if not within_browser_root(): + raise TbDevException("Must be within a browser directory") + parsed_args = parser.parse_args() + + parsed_args.func(parsed_args) +except TbDevException as err: + print(f"\x1b[1m{err}\x1b[0m", file=sys.stderr) diff --git a/tools/geckoview/.gitignore b/tools/geckoview/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..04271c04b9ba9f75e341bf409c2e0583bcedfc48 --- /dev/null +++ b/tools/geckoview/.gitignore @@ -0,0 +1 @@ +android-env.sh diff --git a/tools/geckoview/Makefile b/tools/geckoview/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bf57f7257c62d29d18aacf172479732094971984 --- /dev/null +++ b/tools/geckoview/Makefile @@ -0,0 +1,59 @@ +.DEFAULT_GOAL := all + +# one of armv7 aarch64 x86 x86_64 +ARCH := aarch64 +ANDROID_ARCH := $(ARCH) +ifeq ($(ANDROID_ARCH),aarch64) + ANDROID_ARCH := arm64-v8a +endif +ifeq ($(ANDROID_ARCH),armv7) + ANDROID_ARCH := armeabi-v7a +endif + +OS="${shell uname}" + +# https://stackoverflow.com/questions/18136918/how-to-get-current-relative-directory-of-your-makefile +mkfile_path := "$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))" + +DEV_ROOT = "$(mkfile_path)/../.." + +clobber: env + ./clobber.sh $(DEV_ROOT) $(ARCH) + +config: env + ./config.sh $(DEV_ROOT) $(ARCH) + +geckoview: env + ./build-geckoview.sh $(DEV_ROOT) $(ARCH) + +# These targets do not depend on GeckoView so that you can build only Fenix if +# you are not changing GV code. +fenix-release: env + ./build-fenix.sh $(DEV_ROOT) $(ARCH) Release +fenix-beta: env + ./build-fenix.sh $(DEV_ROOT) $(ARCH) Beta +fenix-nightly: env + ./build-fenix.sh $(DEV_ROOT) $(ARCH) Nightly +fenix-debug: env + ./build-fenix.sh $(DEV_ROOT) $(ARCH) Debug + +env: + test -e android-env.sh || { echo "copy android-env-...-template.sh to android-env.sh and edit appropriatly"; exit 1; } + +install-release: + adb install "$(DEV_ROOT)/mobile/android/fenix/app/build/outputs/apk/fenix/release/app-fenix-$(ANDROID_ARCH)-release-signed.apk" +install-beta: + adb install "$(DEV_ROOT)/mobile/android/fenix/app/build/outputs/apk/fenix/beta/app-fenix-$(ANDROID_ARCH)-beta-signed.apk" +install-nightly: + adb install "$(DEV_ROOT)/mobile/android/fenix/app/build/outputs/apk/fenix/nightly/app-fenix-$(ANDROID_ARCH)-nightly-signed.apk" + +all: env geckoview fenix-nightly install-nightly +all-release: env geckoview fenix-release install-release +all-beta: env geckoview fenix-beta install-beta + +jslint: + ./jslint.sh $(DEV_ROOT) $(JS) + +clean: + rm -rf $(BUILD_OUTPUT) + diff --git a/tools/geckoview/android-env-linux-template.sh b/tools/geckoview/android-env-linux-template.sh new file mode 100644 index 0000000000000000000000000000000000000000..81b517c5640c5192b76c4fc879a62fbcb7804ad9 --- /dev/null +++ b/tools/geckoview/android-env-linux-template.sh @@ -0,0 +1,6 @@ +export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 +export ANDROID_HOME=$HOME/.mozbuild/android-sdk-linux/ # or $HOME/Android/Sdk/ # Or .../android-toolchain/android-sdk-linux if you extract android-toolchain from tor-browser-build +export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/r26c/ # for 128esr +export GRADLE_HOME=/FULL/PATH/TO/tor-browser-build/out/gradle/gradle-8.8 # Or the version that we currently use +export LOCAL_DEV_BUILD=1 +export PATH=/FULL/PATH/TO/tor-browser-build/out/clang/clang-16.x.y-arm/bin/:$PATH # prepend our newly built and assembled clang to the path so it gets used to build geckoview diff --git a/tools/geckoview/android-env-macos-template.sh b/tools/geckoview/android-env-macos-template.sh new file mode 100644 index 0000000000000000000000000000000000000000..a41dc0aed1847dd55ae590036647cf65a33c765f --- /dev/null +++ b/tools/geckoview/android-env-macos-template.sh @@ -0,0 +1,6 @@ +export JAVA_HOME=/opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk/Contents/Home/ # for arm64. Or JAVA_HOME=/usr/local/opt/openjdk@11/libexec/openjdk.jdk/Contents/Home/ for x86_64. +export ANDROID_HOME=$HOME/Library/Android/sdk # or $HOME/.mozbuild/android-sdk-macosx/ +export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313 # will need to download NDK 23.2.8568313 via android studio +export GRADLE_HOME=/opt/homebrew/Cellar/gradle@7/7.6.4 # for arm64 or /usr/local/Cellar/gradle@7/7.6.4 for x86_64. Make sure the version is up to date +export LOCAL_DEV_BUILD=1 +export PATH=$ANDROID_HOME/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/:$PATH # prepend android studios latest ndk to the path so it's clang gets used to build geckoview. NDK 25.2.9519653 uses clang 14.0.7, ideally we'd use clang 16 (to be the same as Linux) but that's not an option yet for android studio. NDK 26.1.10909125 uses clang 17.0.2, which we should evaluate with the esr128 migration diff --git a/tools/geckoview/build-fenix.sh b/tools/geckoview/build-fenix.sh new file mode 100755 index 0000000000000000000000000000000000000000..fdef3d3f712bdf122ef41946545c7cd11a054daf --- /dev/null +++ b/tools/geckoview/build-fenix.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +ARCH=$2 +VARIANT=$3 + +source android-env.sh + +cd $DEV_ROOT/mobile/android/fenix +MOZCONFIG=mozconfig-android-$ARCH $GRADLE_HOME/bin/gradle --no-daemon -Dorg.gradle.jvmargs=-Xmx20g -PdisableOptimization assemble$VARIANT +tools/tba-sign-devbuilds.sh diff --git a/tools/geckoview/build-geckoview.sh b/tools/geckoview/build-geckoview.sh new file mode 100755 index 0000000000000000000000000000000000000000..2dab107f9d90b0439ad8cd5a2404bc98a2a743b4 --- /dev/null +++ b/tools/geckoview/build-geckoview.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +ARCH=$2 + +source android-env.sh + +cd $DEV_ROOT +MOZCONFIG=mozconfig-android-$ARCH ./mach build diff --git a/tools/geckoview/clobber.sh b/tools/geckoview/clobber.sh new file mode 100755 index 0000000000000000000000000000000000000000..4aa29f9287bd7ec99d5c3c64d21a32c221158785 --- /dev/null +++ b/tools/geckoview/clobber.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +ARCH=$2 + +source android-env.sh + +cd $DEV_ROOT +MOZCONFIG=mozconfig-android-$ARCH ./mach clobber diff --git a/tools/geckoview/config.sh b/tools/geckoview/config.sh new file mode 100755 index 0000000000000000000000000000000000000000..7c0f5500c5e530ba3a19eeac989c9d70e59ae011 --- /dev/null +++ b/tools/geckoview/config.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +ARCH=$2 + +source android-env.sh + +cd $DEV_ROOT +MOZCONFIG=mozconfig-android-$ARCH ./mach configure --without-wasm-sandboxed-libraries diff --git a/tools/geckoview/jslint.sh b/tools/geckoview/jslint.sh new file mode 100755 index 0000000000000000000000000000000000000000..d81e9bc062a317de27427b516a772814a6eb7fdf --- /dev/null +++ b/tools/geckoview/jslint.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +JS_FILE=$2 + +source android-env.sh + +cd $DEV_ROOT +./mach lint -l eslint --fix $JS_FILE diff --git a/tools/lint/fluent-lint/exclusions.yml b/tools/lint/fluent-lint/exclusions.yml index 2b8b286c3fccc270ab53445f8c3ae92da079232c..5b75f843c485a9dd0afc07c9d0a4ecb1539227b8 100644 --- a/tools/lint/fluent-lint/exclusions.yml +++ b/tools/lint/fluent-lint/exclusions.yml @@ -181,6 +181,10 @@ CO01: - webext-perms-description-management # toolkit/locales/en-US/toolkit/global/processTypes.ftl - process-type-privilegedmozilla + # toolkit/locales/en-US/toolkit/global/base-browser.ftl + - basebrowser-addon-badge-recommended + - basebrowser-addon-badge-verified + - basebrowser-about-dialog-version files: - browser/components/ion/content/ion.ftl - browser/locales/en-US/browser/profile/default-bookmarks.ftl diff --git a/tools/torbrowser/Makefile b/tools/torbrowser/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2c94e0be5d552c21e7e430d6b29b9fd530652725 --- /dev/null +++ b/tools/torbrowser/Makefile @@ -0,0 +1,69 @@ +.DEFAULT_GOAL := all + +# https://stackoverflow.com/questions/18136918/how-to-get-current-relative-directory-of-your-makefile +mkfile_path := "$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))" + +DEV_ROOT = "$(mkfile_path)/../.." +BINARIES = "$(DEV_ROOT)/.binaries" +ARCHITECTURE = "$(shell uname -m)" + +# Correct the architecture naming for ARM to match what mozilla has +ifeq ($(ARCHITECTURE), "arm64") + ARCHITECTURE = "aarch64" +endif + +ifeq ($(ARCHITECTURE), "aarch64") + LINUX_VENDOR = "unknown" +else + LINUX_VENDOR = "pc" +endif + +# Define build output path based on the platform. +ifeq ("$(shell uname)", "Darwin") + BUILD_OUTPUT = "$(DEV_ROOT)/obj-$(ARCHITECTURE)-apple-darwin$(shell uname -r)" +else + BUILD_OUTPUT = "$(DEV_ROOT)/obj-$(ARCHITECTURE)-$(LINUX_VENDOR)-linux-gnu" +endif + +# Define the run command based on the platform. +ifeq ("$(shell uname)", "Darwin") + RUN_CMD := cd "$(BINARIES)/Tor Browser.app/Contents/MacOS/" && ./firefox --purgecaches +else + RUN_CMD := "$(BINARIES)/dev/Browser/start-tor-browser" -v --purgecaches $(ARGS) +endif + +config: + ./config.sh $(DEV_ROOT) + +ide-vscode: + ./ide.sh vscode $(DEV_ROOT) + +ide-eclipse: + ./ide.sh eclipse $(DEV_ROOT) + +ide-visualstudio: + ./ide.sh visualstudio $(DEV_ROOT) + +fetch: + ./fetch.sh $(BINARIES) + +build: + ./build.sh $(DEV_ROOT) + +deploy: + ./deploy.sh $(BINARIES) $(BUILD_OUTPUT) + +all: build deploy + +run: + $(RUN_CMD) + +jslint: + ./jslint.sh $(DEV_ROOT) $(JS) + +clobber: + ./clobber.sh $(DEV_ROOT) + +clean: + rm -rf $(BUILD_OUTPUT) + diff --git a/tools/torbrowser/browser-self-sign-macos.sh b/tools/torbrowser/browser-self-sign-macos.sh new file mode 100755 index 0000000000000000000000000000000000000000..570f2c8b454305a478fbd3fc6df62a7c9179561f --- /dev/null +++ b/tools/torbrowser/browser-self-sign-macos.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +CERTNAME=my-codesign-cert-tor +BROWSERPATH=. + +if [ $# -ge 1 ] +then + BROWSERPATH=$1 +fi + + +security find-certificate -c $CERTNAME > /dev/null + +if [ $? -ne 0 ] +then + echo "" + echo "ERROR: Self Signing Certificate not found, please create:" + echo " 1. In the Keychain Access app on your Mac, choose Keychain Access > Certificate Assistant > Create a Certificate." + echo " 2. Enter the name '$CERTNAME' for the certificate" + echo " 3. Choose an identity type: Self Signed Root" + echo " 4. Certificate Type > Code Signing" + echo " 5. Check 'Let me override defaults' & click Continue." + echo " 6. Enter a unique Serial Number. (123 is fine)" + echo " 7. Enter a big Validity Period (days), like 3560 & click Continue." + echo " 8. Fill in your personal information & click Continue." + echo " 9. Accept defaults for the rest of the dialog boxes. (Continue several times)" + echo " 10. Certificate Created! Click Done." + echo "" + echo "For additional help see:" + echo " https://support.apple.com/en-ca/guide/keychain-access/kyca8916/mac" + echo " https://stackoverflow.com/questions/58356844/what-are-the-ways-or-technologies-to-sign-an-executable-application-file-in-mac" + + echo "" + read -n 1 -r -s -p $'Press enter to launch "Keychain Access"...\n' + open /System/Applications/Utilities/Keychain\ Access.app + + exit -1 +fi + +echo "Found $CERTNAME, looking for browser to sign..." + +if [ ! -f "$BROWSERPATH/XUL" ] +then + TESTPATH="$BROWSERPATH/Contents/MacOS" + if [ -f "$TESTPATH/XUL" ] + then + BROWSERPATH=$TESTPATH + else + echo "Error: browser files not detected in $BROWSERPATH!" + echo " This script needs to be run in the 'Contents/MacOS' directory of a SomeBrowser.app directory" + exit -1 + fi +fi + +echo "Mozilla based browser found, signing..." +echo ' Will be asked for password to certificate for all the things that need to be signed. Click "Always Allow" to automate' + +cd "$BROWSERPATH" + +codesign -s $CERTNAME *.dylib +codesign -s $CERTNAME plugin-container.app + +if [ -d Tor ] +then + codesign -s $CERTNAME Tor/PluggableTransports/* + codesign -s $CERTNAME Tor/libevent-2.1.7.dylib + if [ -f Tor/tor.real ] + then + codesign -s $CERTNAME Tor/tor.real + fi + if [ -f Tor/tor ] + then + codesign -s $CERTNAME Tor/tor + fi +fi + +codesign -s $CERTNAME XUL + +if [ -d updater.app ] +then + codesign -s $CERTNAME updater.app +fi + +# mullvadbrowser +if [ -f mullvadbrowser ] +then + codesign -s $CERTNAME mullvadbrowser +fi + +# BB or TB +if [ -f firefox ] +then + codesign -s $CERTNAME firefox +fi + +echo "" +echo "Browser signing step done!" +echo "" + +echo "App still needs one more override to be easily opened with double click in Finder" +echo "Alternatively you can right click it, select 'Open' and then select 'Open' from the override popup" +echo "Or to enable it to be double clicked to open perform the following" +echo "" +echo "Double click the app and select either 'Ok' or 'Cancel' from the warning popup depending on which you get (Do Not 'Move to Trash')" +echo 'Go to Preferences -> Security & Privacy and click on padlock to allow changes. ' +echo ' Then in "Allow appications downloaded from" select either:' +echo ' - App Store and identified developers' +echo ' - Anywhere' +echo ' Below that may be a notice about your specific app saying it was blocked because it was not from an identified developer. Click "Open Anyways" and "Open"' + diff --git a/tools/torbrowser/build.sh b/tools/torbrowser/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..4ec7c7544d168af9b5c6283e836692c0b7ca5231 --- /dev/null +++ b/tools/torbrowser/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 + +cd $DEV_ROOT +./mach build + +if [ -z "$LOCALES" ]; then + ./mach build stage-package +else + export MOZ_CHROME_MULTILOCALE=$LOCALES + # No quotes on purpose + ./mach package-multi-locale --locales en-US $MOZ_CHROME_MULTILOCALE + AB_CD=multi ./mach build stage-package +fi diff --git a/tools/torbrowser/clobber.sh b/tools/torbrowser/clobber.sh new file mode 100755 index 0000000000000000000000000000000000000000..5073454b23c10501a36d6e84eaca3d6f424284a9 --- /dev/null +++ b/tools/torbrowser/clobber.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 + +cd $DEV_ROOT +./mach clobber diff --git a/tools/torbrowser/config.sh b/tools/torbrowser/config.sh new file mode 100755 index 0000000000000000000000000000000000000000..d35311961379248118d462faa44f29f744cc417d --- /dev/null +++ b/tools/torbrowser/config.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 + +cd $DEV_ROOT +./mach configure diff --git a/tools/torbrowser/deploy.sh b/tools/torbrowser/deploy.sh new file mode 100755 index 0000000000000000000000000000000000000000..2f59449ee07ffdeb7a872ffb7e82cc7b48c2e891 --- /dev/null +++ b/tools/torbrowser/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e + +BINARIES="$1" +BUILD_OUTPUT="$2" +SCRIPT_DIR="$(realpath "$(dirname "$0")")" + +RESDIR="$BUILD_OUTPUT/dist/firefox" +if [ "$(uname)" = "Darwin" ]; then + RESDIR="$RESDIR/Tor Browser.app/Contents/Resources" +fi + +# Repackage the manual +# rm -rf $BUILD_OUTPUT/_omni +# mkdir $BUILD_OUTPUT/_omni +# unzip $BINARIES/dev/Browser/browser/omni.ja -d $BUILD_OUTPUT/_omni +# cd $BUILD_OUTPUT/_omni && zip -Xmr $RESDIR/browser/omni.ja chrome/browser/content/browser/manual +# rm -rf $BUILD_OUTPUT/_omni + +if [ "$(uname)" = "Darwin" ]; then + + # copy binaries + cp -r "$BUILD_OUTPUT/dist/firefox/"*.app/Contents/* "$BINARIES/Tor Browser.app/Contents/" + rm -rf "$BINARIES/TorBrowser-Data/Browser/Caches/*.default/startupCache" + + # Self sign the Binaries + cd "$BINARIES/Tor Browser.app/Contents/MacOS" + "$SCRIPT_DIR/browser-self-sign-macos.sh" + +else + + # backup the startup script + mv "$BINARIES/dev/Browser/firefox" "$BINARIES/dev/Browser/firefox.bak" + + # copy binaries + cp -r "$RESDIR/"* "$BINARIES/dev/Browser" + rm -rf "$BINARIES/dev/Browser/TorBrowser/Data/Browser/profile.default/startupCache" + + # shuffle firefox bin around and restore script to match a real deployment + mv "$BINARIES/dev/Browser/firefox" "$BINARIES/dev/Browser/firefox.real" + mv "$BINARIES/dev/Browser/firefox.bak" "$BINARIES/dev/Browser/firefox" + +fi diff --git a/tools/torbrowser/fetch.sh b/tools/torbrowser/fetch.sh new file mode 100755 index 0000000000000000000000000000000000000000..f55bd7d6ca752a29086c6a10e71443232a007641 --- /dev/null +++ b/tools/torbrowser/fetch.sh @@ -0,0 +1,40 @@ +#!/bin/sh +set -e + +BINARIES_DIR="$1" + +# download the current downloads.json +wget https://aus1.torproject.org/torbrowser/update_3/alpha/downloads.json +# get url for latest alpha linux package +TOR_BROWSER_VERSION=$(grep -Eo "\"version\":\"[0-9.a]+\"" downloads.json | grep -Eo "[0-9.a]+") +if [ "$(uname)" = "Darwin" ]; then + TOR_BROWSER_PACKAGE="tor-browser-macos-${TOR_BROWSER_VERSION}.dmg" + else + TOR_BROWSER_PACKAGE="tor-browser-linux-$(uname -m)-${TOR_BROWSER_VERSION}.tar.xz" +fi +TOR_BROWSER_PACKAGE_URL="https://dist.torproject.org/torbrowser/${TOR_BROWSER_VERSION}/${TOR_BROWSER_PACKAGE}" + +# remove download manifest +rm downloads.json + +# clear out previous tor-browser and previous package +rm -rf "${BINARIES_DIR}" +rm -f "${TOR_BROWSER_PACKAGE}" + +# download +wget "${TOR_BROWSER_PACKAGE_URL}" +mkdir -p "${BINARIES_DIR}" + +# and extract +if [ "$(uname)" = "Darwin" ] + then + hdiutil attach "${TOR_BROWSER_PACKAGE}" + cp -R "/Volumes/Tor Browser Alpha/Tor Browser Alpha.app" "${BINARIES_DIR}/Tor Browser.app" + hdiutil detach "/Volumes/Tor Browser Alpha" + else + tar -xf "${TOR_BROWSER_PACKAGE}" -C "${BINARIES_DIR}" + mv "${BINARIES_DIR}/tor-browser" "${BINARIES_DIR}/dev" +fi + +# Final cleanup +rm -f "${TOR_BROWSER_PACKAGE}" diff --git a/tools/torbrowser/generate-bugzilla-triage-csv.sh b/tools/torbrowser/generate-bugzilla-triage-csv.sh new file mode 100755 index 0000000000000000000000000000000000000000..0dc791dd77436b5f075bced2160138c6ad55709a --- /dev/null +++ b/tools/torbrowser/generate-bugzilla-triage-csv.sh @@ -0,0 +1,239 @@ +#!/usr/bin/env bash + +# prints to stderr +function echoerr() { echo "$@" 1>&2; } + +# help dialog +if [ "$#" -lt 5 ]; then + echoerr "Usage: $0 ff-version begin-commit end-commit gitlab-audit-issue reviewers..." + echoerr "" + echoerr "Writes a CSV to stdout of Bugzilla issues to triage for a particular Firefox version. This" + echoerr "script performs a union of the labeled Bugzilla issues in Mozilla's issue tracker and the" + echoerr "labeled commits in the provided commit range" + echoerr + echoerr " ff-version rapid-release Firefox version to audit" + echoerr " begin-commit starting gecko-dev commit of this Firefox version" + echoerr " end-commit ending gecko-dev commit of this Firefox version" + echoerr " gitlab-audit-issue tor-browser-spec Gitlab issue number for this audit" + echoerr " reviewers... space-separated list of reviewers responsible for this audit" + echoerr "" + echoerr "Example:" + echoerr "" + echoerr "$0 116 FIREFOX_ESR_115_BASE FIREFOX_116_0_3_RELEASE 40064 richard pierov henry" + exit 1 +fi + +# set -x +set -e + + +# Ensure various required tools are available +function check_exists() { + local cmd=$1 + if ! which ${cmd} > /dev/null ; then + echoerr "missing ${cmd} dependency" + exit 1 + fi +} + +check_exists git +check_exists jq +check_exists mktemp +check_exists perl +check_exists printf +check_exists sed +check_exists sort +check_exists touch +check_exists uniq +check_exists wget + +# Assign arguments to named variables +firefox_version=$1 +git_begin=$2 +git_end=$3 +audit_issue=$4 +reviewers="${@:5}" + +# Check valid Firefox version +if ! [[ "${firefox_version}" =~ ^[1-9][0-9]{2}$ ]]; then + echoerr "invalid Firefox version (probably)" + exit 1 +fi + +# Check valid Gitlab issue number +if ! [[ "${audit_issue}" =~ ^[1-9][0-9]{4}$ ]]; then + echoerr "invalid gitlab audit issue number (probably)" + exit 1 +fi + +# +# Encoding/Decoding Functions +# + +# escape " and \ +function json_escape() { + local input="$1" + echo "${input}" | sed 's/["\]/\\"/g' +} + + +# un-escape \" +function jq_unescape() { + local input="$1" + echo "${input}" | sed 's/\\"/"/g' +} + +# change quotes to double-quotes +function csv_escape() { + local input="$1" + echo "${input}" | sed 's/"/""/g' +} + +# we need to urlencode the strings used in the new issue link +function url_encode() { + local input="$1" + echo "${input}" | perl -MURI::Escape -wlne 'print uri_escape $_' +} + + +# +# Create temp json files +# +git_json=$(mktemp -t git-audit-${firefox_version}-XXXXXXXXXXX.json) +bugzilla_json=$(mktemp -t bugzilla-audit-${firefox_version}-XXXXXXXXXXX.json) +union_json=$(mktemp -t union-audit-${firefox_version}-XXXXXXXXXXX.json) +touch "${git_json}" +touch "${bugzilla_json}" +touch "${union_json}" + +function json_cleanup { + rm -f "${git_json}" + rm -f "${bugzilla_json}" + rm -f "${union_json}" +} +trap json_cleanup EXIT + +# +# Generate Git Commit Triage List +# + +# Try and extract bug id and summary from git log +# Mozilla's commits are not always 100% consistently named, so this +# regex is a bit flexible to handle various inputs such as: +# "Bug 1234 -", "Bug 1234:", "Bug Bug 1234 -", "[Bug 1234] -", " bug 1234 -". +sed_extract_id_summary="s/^[[ ]*[bug –-]+ ([1-9][0-9]*)[]:\., –-]*(.*)\$/\\1 \\2/pI" + +# Generate a json array of objects in the same format as bugzilla: {id: number, summary: string} +printf "[\n" >> "${git_json}" + +first_object=true +git log --format='%s' $git_begin..$git_end \ +| sed -En "${sed_extract_id_summary}" \ +| sort -h \ +| uniq \ +| while IFS= read -r line; do + read -r id summary <<< "${line}" + summary=$(json_escape "${summary}") + + # json does not allow trailing commas + if [[ "${first_object}" = true ]]; then + first_object=false + else + printf ",\n" >> "${git_json}" + fi + + printf " { \"id\": %s, \"summary\": \"%s\" }" ${id} "${summary}" >> "${git_json}" +done +printf "\n]\n" >> "${git_json}" + +# +# Download Bugzilla Triage List +# + +# search for: +# + Product is NOT "Thunderbird,Calander,Chat Core,MailNews Core" (&f1=product&n1=1&o1=anyexact&v1=Thunderbird%2CCalendar%2CChat%20Core%2CMailNews%20Core). AND +# + Target Milestone contains "${firefox_version}" (115 Branch or Firefox 115) (&f2=target_milestone&o2=substring&v2=${firefox_version}). +# "&limit=0" shows all matching bugs. + +query_tail="&f1=product&n1=1&o1=anyexact&v1=Thunderbird%2CCalendar%2CChat%20Core%2CMailNews%20Core&f2=target_milestone&o2=substring&v2=${firefox_version}&limit=0" + +bugzilla_query="https://bugzilla.mozilla.org/buglist.cgi?${query_tail}" +bugzilla_json_query="https://bugzilla.mozilla.org/rest/bug?include_fields=id,component,summary${query_tail}" + +wget "${bugzilla_json_query}" -O ${bugzilla_json} + + +# +# Create Union of these two sets of issues +# + +# bugzilla array is actually on a root object: { bugs: [...] } +jq -s '[ (.[0].bugs)[], (.[1])[] ] | group_by(.id) | map(.[0])' "${bugzilla_json}" "${git_json}" > "${union_json}" + +# +# Generate Triage CSV +# + +echo "\"Review\",,\"Bugzilla Component\",\"Bugzilla Bug\"" + +jq '. | sort_by([.component, .id])[] | "\(.id)|\(.component)|\(.summary)"' ${union_json} \ +| while IFS='|' read -r id component summary; do + + # bugzilla info + id="${id:1}" + component="${component:0}" + summary="${summary:0:-1}" + summary=$(jq_unescape "${summary}") + # short summary for gitlab issue title + [[ ${#summary} -gt 80 ]] && summary_short="${summary:0:77}..." || summary_short="${summary}" + + # filter out some issue types that we never care about + skip_issue=false + + # skip `[wpt-sync] Sync PR` + if [[ "${summary}" =~ ^\[wpt-sync\]\ Sync\ PR.*$ ]]; then + skip_issue=true + # skip `Crash in [@` and variants + elif [[ "${summary}" =~ ^Crash[esin\ ]*\ \[\@.*$ ]]; then + skip_issue=true + # skip `Assertion failuire: ` + elif [[ "${summary}" =~ ^Assertion\ failure:\ .*$ ]]; then + skip_issue=true + # skip `Hit MOZ_CRASH` + elif [[ "${summary}" =~ ^Hit\ MOZ_CRASH.*$ ]]; then + skip_issue=true + fi + + if [[ "${skip_issue}" = true ]]; then + echoerr "Skipped Bugzilla ${id}: ${summary_short}" + else + csv_summary=$(csv_escape "${summary}") + csv_component=$(csv_escape "${component}") + + # parent issue + bugzilla_url="https://bugzilla.mozilla.org/show_bug.cgi?id=${id}" + # review issue title + new_issue_title=$(url_encode "Review Mozilla ${id}: ${summary_short}") + # review issue description + labeling (14.0 stable, FF128-esr, Next) + new_issue_description=$(url_encode "### Bugzilla: ${bugzilla_url}")%0A$(url_encode "/label ~\"14.0 stable\" ~FF128-esr ~Next")%0A$(url_encode "/relate tpo/applications/tor-browser-spec#${audit_issue}")%0A%0A$(url_encode "<!-- briefly describe why this issue needs further review -->")%0A + # url which create's new issue with title and description pre-populated + new_issue_url="https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/new?issue[title]=${new_issue_title}&issue[description]=${new_issue_description}" + + # this link will start the creation of a new gitlab issue to review + create_issue=$(csv_escape "=HYPERLINK(\"${new_issue_url}\", \"New Issue\")") + bugzilla_link=$(csv_escape "=HYPERLINK(\"${bugzilla_url}\", \"Bugzilla ${id}: ${csv_summary}\")") + + echo "FALSE,\"${create_issue}\",\"${csv_component}\",\"${bugzilla_link}\"," + fi +done + +echo +echo "\"Triaged by:\"" +for reviewer in $reviewers; do + reviewer=$(csv_escape "${reviewer}") + echo "\"FALSE\",\"${reviewer}\"" +done +echo + +bugzilla_query="=HYPERLINK(\"${bugzilla_query}\", \"Bugzilla query\")" +echo \"$(csv_escape "${bugzilla_query}")\" diff --git a/tools/torbrowser/generate_tor_loading_png.py b/tools/torbrowser/generate_tor_loading_png.py new file mode 100644 index 0000000000000000000000000000000000000000..861e154dc7970b20a658f467325d898afb510a3f --- /dev/null +++ b/tools/torbrowser/generate_tor_loading_png.py @@ -0,0 +1,74 @@ +""" +Script to convert the loading.png and loading@2x.png blue spinners to purple +spinners for Tor Browser, for both the light and dark themes. +""" + +import argparse +import colorsys +import os + +from PIL import ExifTags, Image, ImageFilter + +parser = argparse.ArgumentParser(description="Convert the loading APNG to be purple.") +parser.add_argument("loading_png", help="The loading png to convert") +parser.add_argument( + "--light", required=True, help="The name of the light-theme purple output image" +) +parser.add_argument( + "--dark", required=True, help="The name of the dark-theme purple output image" +) + +parsed_args = parser.parse_args() + +orig_im = Image.open(parsed_args.loading_png) + + +def filter_to_light_theme(r, g, b): + h, s, v = colorsys.rgb_to_hsv(r, g, b) + # Convert from HSV 0.58, 1.0, 255 (start of the circle) + # to --purple-60 #8000d7 HSV 0.766, 1.0, 215 + h = 0.766 + v = v * 215 / 255 + return colorsys.hsv_to_rgb(h, s, v) + + +def filter_to_dark_theme(r, g, b): + h, s, v = colorsys.rgb_to_hsv(r, g, b) + # Convert from HSV 0.58, 1.0, 255 (start of the circle) + # to --purple-30 #c069ff HSV 0.766, 0.59, 255 + h = 0.766 + s = s * 0.59 / 1.0 + return colorsys.hsv_to_rgb(h, s, v) + + +filt_light = ImageFilter.Color3DLUT.generate(65, filter_to_light_theme) +filt_dark = ImageFilter.Color3DLUT.generate(65, filter_to_dark_theme) + +transformed_light = [] +transformed_dark = [] +duration = orig_im.info["duration"] + +# Transform each APNG frame individually. +for frame in range(orig_im.n_frames): + orig_im.seek(frame) + transformed_light.append(orig_im.filter(filt_light)) + transformed_dark.append(orig_im.filter(filt_dark)) + +exif = Image.Exif() +exif[ExifTags.Base.ImageDescription] = f"Generated by {os.path.basename(__file__)}" + +transformed_light[0].save( + parsed_args.light, + save_all=True, + append_images=transformed_light[1:], + duration=duration, + exif=exif, +) + +transformed_dark[0].save( + parsed_args.dark, + save_all=True, + append_images=transformed_dark[1:], + duration=duration, + exif=exif, +) diff --git a/tools/torbrowser/ide.sh b/tools/torbrowser/ide.sh new file mode 100755 index 0000000000000000000000000000000000000000..5da0c670d8c5baf9336dff99102507341c5525c3 --- /dev/null +++ b/tools/torbrowser/ide.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e +IDE=$1 +DEV_ROOT=$2 + +cd $DEV_ROOT +./mach ide $IDE diff --git a/tools/torbrowser/jslint.sh b/tools/torbrowser/jslint.sh new file mode 100755 index 0000000000000000000000000000000000000000..be1016275c289b7843eb8d1f5725f5ec525b7e40 --- /dev/null +++ b/tools/torbrowser/jslint.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e +DEV_ROOT=$1 +JS_FILE=$2 + +cd $DEV_ROOT +./mach lint -l eslint --fix $JS_FILE diff --git a/tools/torbrowser/l10n/migrate.py b/tools/torbrowser/l10n/migrate.py new file mode 100644 index 0000000000000000000000000000000000000000..6e03619fdb75bae02244781e80e3c5705bce81a6 --- /dev/null +++ b/tools/torbrowser/l10n/migrate.py @@ -0,0 +1,672 @@ +""" +Migration script for running migration recipes. + +Requires the mozilla fluent.migrate package (available with pip). + +NOTE: This will likely send queries to the weblate API as part of the run. +Weblate may have a query limit of 100 requests per day for unauthorised users. + + +Based on the firefox migration script, adapted for tor browser. See +https://firefox-source-docs.mozilla.org/l10n/migrations/ for more context and +information on how to write the migration recipes. + + +Usage with an example: + +We have some en-US file "updated.ftl" in the tor-browser repository that we have +added new strings to. Some of these strings are copies or concatenations of some +already existing strings in a `.dtd`, `.properties` or `.ftl` file (including +strings within "updated.ftl"). + +So we also write a migration recipe in +`./l10n_migrations/bug-xxxx-my-migration-recipe.py` +which includes a `migrate(ctx)` method. This method takes the old strings and +create new Messages or Terms for "updated.ftl" using `ctx.add_transforms`. These +should match what was already done manually in "updated.ftl". + +Then we copy the en-US file to our local translation repository, say at +`/home/user/translation/en-US/updated.ftl`. The en-US file is needed as a +reference during migration to know where in the new file the new Messages or +Terms should be placed. Moreover, the migration can be verified against the +en-US file to ensure it is working as intended. + +Then we run the migration for individual locales: + +``` + python migrate_l10n.py --translation-git /home/user/translation --locales 'es-ES sr' l10n_migrations.bug-xxxx-my-migration-recipe +``` + +This will first run a mock migration using the en-US localization files. This is +to help ensure that the migration will work as intended. I.e. if we ran the +migration recipe for en-US, using it as both the source of old strings and as a +reference, then each transformation using these old strings should produce a +Message or Term that is identical to the one in the reference file. + +Then this will run `migrate(ctx)` for the es-ES and sr locales. Some of the +transformations will not be completed for a locale if that locale does not +contain a translated version of the old strings the transformation requires +(because there is no string to copy). + +If one of the old strings is from a `.dtd` or `.properties` file, this will +check whether they are marked as translated on weblate using its API. This +prevents copying "placeholder" en-US values into the locale's fluent files. + +Any warnings or errors will be logged to stderr in the console. +""" + +import argparse +import atexit +import importlib +import json +import logging +import os +import sys +import urllib.request + +from fluent.migrate.context import MigrationContext +from fluent.migrate.errors import EmptyLocalizationError, UnreadableReferenceError +from fluent.syntax import ast, parse, serialize + + +def in_red(string): + """ + Wrap a string so that it is shown as red in the console. + """ + return f"\x1b[1;91m{string}\x1b[0m" + + +class WeblateMetadata: + """ + Manages and fetches string metadata from weblate. + """ + + def __init__(self): + self.logger = logging.getLogger("weblate-metadata") + self.logger.setLevel(logging.INFO) + + # The _components property will be lazy-loaded with weblate data. + # + # On weblate, for monolingual formats, the component will have a + # "template" file, which matches the en-US file path in the + # "translation" git repo. So we can find a component through a matching + # template. + # + # Each translation in that component will have a "filename" that will + # match the locale's file path in the "translation" git repo. So we can + # find a translation through a matching filename. + # + # Each translation can be queried for its units, including metadata. + # Each unit's "context" will match the string's id in the corresponding + # file. + # + # Expect the final structure to be: + # { + # template: { + # "translations-url": str, # Used for API translations query. + # "translations": { + # filename: { + # "units-url": str, # Used for API units query. + # "units": { + # context: { + # "translated": bool, + # }, + # }, + # }, + # }, + # }, + # } + self._components = None + + def _get_weblate_response(self, url): + weblate_request = urllib.request.Request( + url, + # NOTE: can set the request header: + # "Authorization": "Token WEBLATE_TOKEN" + # to get around rate-limiting + headers={"User-Agent": ""}, + ) + + with urllib.request.urlopen(weblate_request, timeout=20) as response: + return json.load(response) + + def _get_from_weblate(self, url): + ret = [] + while url: + response = self._get_weblate_response(url) + # Continue to fetch the next page, if it is present. + # Expect the "next" url to be empty + # or the same url with "?page=2", etc. + url = response["next"] + ret.extend(response["results"]) + return ret + + def _get_components(self): + if self._components is None: + self._components = { + comp["template"]: { + "translations": None, + "translations-url": comp["translations_url"], + } + for comp in self._get_from_weblate( + "https://hosted.weblate.org/api/projects/tor/components/" + ) + if comp["template"] + } + return self._components + + def _get_translations(self, template): + component = self._get_components().get(template, None) + if not component: + self.logger.warning(f"No component in weblate for {template}.") + return None + if component["translations"] is None: + component["translations"] = { + trans["filename"]: { + "units": None, + "units-url": trans["units_list_url"], + } + for trans in self._get_from_weblate(component["translations-url"]) + } + return component["translations"] + + def _get_units(self, template, file): + translation_dict = self._get_translations(template) + if translation_dict is None: + return None + translation = translation_dict.get(file, None) + if translation is None: + self.logger.warning(f"No translation in weblate for {file}.") + return None + if translation["units"] is None: + translation["units"] = { + unit["context"]: { + "translated": unit["translated"], + } + for unit in self._get_from_weblate(translation["units-url"]) + } + return translation["units"] + + def is_translated(self, template_path, locale_path, string_id): + """ + Whether the given string is marked as translated on weblate. + """ + unit_dict = self._get_units(template_path, locale_path) + if unit_dict is None: + return False + unit = unit_dict.get(string_id, None) + if unit is None: + self.logger.warning(f"No unit in weblate for {locale_path}:{string_id}.") + return False + return unit["translated"] + + +class TorBrowserMigrationContext(MigrationContext): + """ + Extension which adds some extra methods to use for tor-browser. + """ + + def __init__(self, locale, reference_dir, localization_dir): + super().__init__(locale, reference_dir, localization_dir) + + def _fluent_keys(self, resource): + # ast.Resource, want to extract all Message and Term identifiers, as + # well as their + for entry in resource.body: + if not isinstance(entry, (ast.Term, ast.Message)): + continue + key = entry.id.name + if isinstance(entry, ast.Term): + key = f"-{key}" + if entry.value: + yield key + for attr in entry.attributes: + yield f"{key}.{attr.id.name}" + + def tb_get_available_strings(self): + """ + Return all the (path, string_id) pairs for all loaded localization + resources. + """ + all_strings = set() + # ctx.localization_resources is a dict containing all the loaded + # localization_resources that have been added during add_transforms. + # { localization_path: resource } + for path, resource in self.localization_resources.items(): + if path.endswith(".ftl"): + all_strings.update((path, key) for key in self._fluent_keys(resource)) + else: + # dictionary of { identifies: value } in legacy resource. + # For tor-browser, + # Only include references that differ from the en-US strings. + all_strings.update((path, key) for key in resource.keys()) + return all_strings + + def tb_get_missing_resources(self): + """ + Return the missing localization resources. + """ + return set( + path + for dep_set in self.dependencies.values() + for path, string_id in dep_set + if path not in self.localization_resources + ) + + def tb_get_transform(self, target_path, transform_id): + """ + Find the transformation node with the given id for the given path. + """ + for node in self.transforms[target_path]: + if node.id.name == transform_id: + return node + return None + + def tb_get_reference_entry(self, target_path, entry_id): + """ + Find the reference node that would be used for the given id and path. + """ + for entry in self.reference_resources[target_path].body: + if isinstance(entry, (ast.Term, ast.Message)) and entry.id.name == entry_id: + return entry.clone() + return None + + +class TorBrowserMigrator: + """ + Performs a tor-browser migration. + """ + + def __init__( + self, + en_US_dir, + locale_dirs, + migrate_module, + weblate_metadata, + ): + self.logger = logging.getLogger("tor-browser-migrator") + self.logger.setLevel(logging.INFO) + self.en_US_dir = en_US_dir + self.locale_dirs = locale_dirs + self.migrate_module = migrate_module + self.weblate_metadata = weblate_metadata + + def run(self): + """ + Run the migration. + """ + if not self._check_en_US_resources(): + sys.exit(1) + + fluent_errors = [] + for locale, locale_dir in self.locale_dirs.items(): + if locale == "en-US": + print("", file=sys.stderr) + self.logger.warning( + "Skipping running migration on 'en-US' files since this " + "locale should act as a reference only.\n" + ) + continue + fluent_errors.extend(self._run_locale(locale, locale_dir)) + + if fluent_errors: + print("\n", file=sys.stderr) + self.logger.error( + "Fluent parsing errors found for the following files. " + "Migration does not need to be run again, but the following " + "syntax errors should be fixed manually.\n" + + "\n".join( + f"{in_red(full_path)}: line {line}: {message}: [[{sample}]]" + for full_path, message, line, sample in fluent_errors + ) + ) + + def _run_locale(self, locale, locale_dir): + print("\n\n", file=sys.stderr) + self.logger.info(f"Migrating '{in_red(locale)}' locale\n") + + ctx = self._get_migration_context(locale, locale_dir) + + # NOTE: We do not use the existing ctx.serialize_changeset method. + # The problem with this approach was that it would re-shuffle the order + # of already existing strings to match the en-US locale. + # But Weblate currently does not preserve the order of translated + # strings: https://github.com/WeblateOrg/weblate/issues/11134 + # so this created extra noise in the diff. + # Instead, we just always append transformations to the end of the + # existing file. + # Moreover, it would inject group comments into the translated files, + # which Weblate does not handle well. Instead, we just do not add any + # comments. + # + # In case we want to use it again in the future, here is a reference + # to how it works: + # + # ctx.serialize_changeset expects a set of (path, identifier) of + # localization resources that can be used to evaluate the + # transformations. + # e.g. ("example.dtd", "exampleStringInDTD") + # ("example.ftl", "some-message") + # ("example.ftl", "some-message.attribute") + # + # Mozilla splits its changesets into the authors/users who are + # attributed to creating the identified sources, using hg blame and + # checking the author to identify the user. + # For tor-browser, we just want to apply all the changes possible in + # one step, so we want to fill the changeset with all required + # (path, identifier) pairs found in the localization resources. + + available_strings = ctx.tb_get_available_strings() + wrote_file = False + errors = [] + + for target_path, reference in ctx.reference_resources.items(): + translated_ids = [ + entry.id.name + for entry in ctx.target_resources[target_path].body + if isinstance(entry, (ast.Message, ast.Term)) + # NOTE: We're assuming that the Message and Term ids do not + # conflict with each other. + ] + new_entries = [] + + # Apply transfomations in the order they appear in the reference + # (en-US) file. + for entry in reference.body: + if not isinstance(entry, (ast.Message, ast.Term)): + continue + transform_id = entry.id.name + transform = ctx.tb_get_transform(target_path, transform_id) + if not transform: + # No transformation for this reference entry. + continue + + if transform_id in translated_ids: + self.logger.info( + f"Skipping transform {target_path}:{transform_id} " + f"for '{locale}' locale because it already has a " + f"translation." + ) + continue + + # ctx.dependencies is a dict of dependencies for all + # transformations + # { (target_path, transform_identifier): set( + # (localization_path, string_identifier), + # )} + # + # e.g. if we want to create a new fluent Message called + # "new-string1", and it uses "oldString1" from "old-file1.dtd" + # and "oldString2" from "old-file2.dtd". And "new-string2" using + # "oldString3" from "old-file2.dtd", it would be + # { + # ("new-file.ftl", "new-string1"): set( + # ("old-file1.dtd", "oldString1"), + # ("old-file2.dtd", "oldString2"), + # ), + # ("new-file.ftl", "new-string2"): set( + # ("old-file2.dtd", "oldString3"), + # ), + # } + dep_set = ctx.dependencies[(target_path, transform_id)] + can_transform = True + for dep in dep_set: + path, string_id = dep + if dep not in available_strings: + can_transform = False + self.logger.info( + f"Skipping transform {target_path}:{transform_id} " + f"for '{locale}' locale because it is missing the " + f"string {path}:{string_id}." + ) + break + # Strings in legacy formats might have an entry in the file + # that is just a copy of the en-US strings. + # For these we want to check the weblate metadata to ensure + # it is a translated string. + if not path.endswith( + ".ftl" + ) and not self.weblate_metadata.is_translated( + os.path.join("en-US", path), + os.path.join(locale, path), + string_id, + ): + can_transform = False + self.logger.info( + f"Skipping transform {target_path}:{transform_id} " + f"for '{locale}' locale because the string " + f"{path}:{string_id} has not been translated on " + "weblate." + ) + break + if not can_transform: + continue + + # Run the transformation. + new_entries.append(ctx.evaluate(transform)) + + if not new_entries: + continue + + full_path = os.path.join(locale_dir, target_path) + print("", file=sys.stderr) + self.logger.info(f"Writing to {full_path}") + + # For Fluent we can just serialize the transformations and append + # them to the end of the existing file. + resource = ast.Resource(new_entries) + with open(full_path, "a") as file: + file.write(serialize(resource)) + + with open(full_path, "r") as file: + full_content = file.read() + wrote_file = True + # Collect any fluent parsing errors from the newly written file. + errors.extend( + (full_path, message, line, sample) + for message, line, sample in self._fluent_errors(full_content) + ) + + if not wrote_file: + self.logger.info(f"No files written for '{locale}' locale.") + return errors + + def _fluent_errors(self, fluent): + """ + Verify that the given fluent string can be parsed correctly. + """ + resource = parse(fluent) + for entry in resource.body: + if not isinstance(entry, ast.Junk): + continue + for annotation in entry.annotations: + line = fluent[0 : annotation.span.start].count("\n") + 1 + sample_start = max(annotation.span.start - 15, 0) + sample = "…" + fluent[sample_start : sample_start + 30] + "…" + yield annotation.message, line, sample + + def _get_migration_context(self, locale, locale_dir): + prev_missing_resources = set() + while True: + ctx = TorBrowserMigrationContext(locale, self.en_US_dir, locale_dir) + + try: + self.migrate_module.migrate(ctx) + except EmptyLocalizationError: + # This case will be handled by missing_resources below. + # NOTE: At the time of writing, add_transforms only throws if + # ctx.localization_resources is empty after add_transforms, + # which means whether it throws can depend on whether the + # missing resource was found missing before or after some + # non-missing resource was found. I.e. the order in which + # add_transforms is called can influence whether add_transforms + # will throw. + # Therefore, we want to handle the case where it throws or does + # not throw in the same way. We also need to create a new + # context for the next run so that the early exit from + # add_transforms in this run does not make a difference. + pass + + missing_resources = ctx.tb_get_missing_resources() + + if not missing_resources: + return ctx + + still_missing = missing_resources & prev_missing_resources + if still_missing: + # Unexpected to still be missing the same files after the + # previous run. + self.logger.error( + f"Still missing files in '{locale}' locale: " + + ", ".join(in_red(path) for path in still_missing) + ) + sys.exit(1) + + for path in missing_resources: + # Create an empty file to try and get migrate() to succeed + # the next round. + # NOTE: Missing strings within a resource is ok, we just want to + # add the missing file to prevent add_transforms from throwing + # to allow us to proceed. + full_path = os.path.join(locale_dir, path) + self.logger.info(f"Creating temporary empty file: {full_path}") + # Throw if it already exists. + file = open(full_path, "x") + # Remove the empty file on exit if it is still empty. + atexit.register(self._remove_if_empty, full_path) + # Immediately close. + file.close() + + # Try again with the newly added resources. + # Don't expect it to throw EmptyLocalizationError the second time, + # although it may still be missing resources if the last run threw + # before localization_resources was fully populated. + prev_missing_resources = missing_resources + + def _remove_if_empty(self, path): + if os.stat(path).st_size: + self.logger.warning(f"{path} is no longer empty. Not deleting.") + return + os.remove(path) + + def _check_en_US_resources(self): + # We pass in the en-US directory as the localization directory, as well + # as the reference directory. + ctx = TorBrowserMigrationContext("en-US", self.en_US_dir, self.en_US_dir) + + have_error = False + try: + self.migrate_module.migrate(ctx) + except EmptyLocalizationError: + # Handle with localization_resources check. + # NOTE: This throwing may have prevented further add_transforms from + # proceeding, so we will only report missing string errors up to + # this point. + # Set have_error here just in case. + have_error = True + except UnreadableReferenceError: + # Reference filename is printed before this. + self.logger.error("Missing an en-US reference file.") + return False + + # Check each transform would create the same entry in the target as the + # already existing reference file for en-US, using the existing en-US + # localization files. + # I.e. if we ran the transforms for en-US we expect to get the same file + # as the reference. + available_strings = ctx.tb_get_available_strings() + for (target_path, transform_id), dep_set in ctx.dependencies.items(): + transform_name = in_red(f"{target_path}:{transform_id}") + has_deps = True + for dep in dep_set: + path, string_id = dep + if path not in ctx.localization_resources: + has_deps = False + self.logger.error( + f"Missing en-US localization file {in_red(path)} " + f" for transform {transform_name}" + ) + continue + if dep not in available_strings: + has_deps = False + self.logger.error( + "Missing en-US localization string " + + in_red(f"{path}:{string_id}") + + f" for transform {transform_name}" + ) + if not has_deps: + have_error = True + continue + + transformed = ctx.evaluate(ctx.tb_get_transform(target_path, transform_id)) + reference_entry = ctx.tb_get_reference_entry(target_path, transform_id) + if reference_entry is None: + self.logger.error( + f"Missing en-US reference entry for transform {transform_name}" + ) + have_error = True + continue + + # Serialized the single transformed and reference and compare. + transform_serialized = serialize(ast.Resource([transformed])) + # Remove comment in reference for comparison. + reference_entry.comment = None + ref_serialized = serialize(ast.Resource([reference_entry])) + if transform_serialized != ref_serialized: + self.logger.error( + f"Transform {transform_name} would not produce the same " + "entry as the existing en-US reference when acting on " + "en-US localization files.\n" + f"Transform result:\n{transform_serialized}\n" + f"Reference entry:\n{ref_serialized}" + ) + have_error = True + + return not have_error + + +parser = argparse.ArgumentParser( + description="Run a tor-browser localization migration. " + "See documentation within migrate_l10n.py." +) +parser.add_argument( + "--translation-git", + required=True, + metavar="<dir>", + help="Location of the translation-git directory to read and write to.", +) +parser.add_argument( + "--locales", + required=True, + metavar="<locale1> <locale2> ...", + help="Set of locales to restrict the migration to, separated by space.", +) +parser.add_argument( + "migration", + help="Migration to run, given as a python module. " + 'E.g. "l10n_migrations.my-migration-script".', +) + + +parsed_args = parser.parse_args() + + +def check_dir(path): + if not os.path.isdir(path): + print(f"{in_red(path)} is not a directory.", file=sys.stderr) + sys.exit(1) + return path + + +translation_dir = check_dir(os.path.abspath(parsed_args.translation_git)) + +TorBrowserMigrator( + check_dir(os.path.join(translation_dir, "en-US")), + { + locale: check_dir(os.path.join(translation_dir, locale)) + for locale in (l.strip() for l in parsed_args.locales.split(" ")) + if locale + }, + importlib.import_module(parsed_args.migration), + WeblateMetadata(), +).run() diff --git a/tools/torbrowser/l10n/migrations/__init__.py b/tools/torbrowser/l10n/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/torbrowser/l10n/migrations/bug-41333-new-about-tor.py b/tools/torbrowser/l10n/migrations/bug-41333-new-about-tor.py new file mode 100644 index 0000000000000000000000000000000000000000..d2d37a0a77fb0fec55600932c259583a51ed0bc7 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-41333-new-about-tor.py @@ -0,0 +1,24 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +menu-open-tor-manual = + .label = { COPY(path, "aboutTor.torbrowser_user_manual.label") } + .accesskey = { COPY(path, "aboutTor.torbrowser_user_manual.accesskey") } + +tor-browser-home-heading-stable = { COPY(path, "aboutTor.ready.label") } +tor-browser-home-heading-testing = { COPY(path, "aboutTor.alpha.ready.label") } + +tor-browser-home-duck-duck-go-input = + .placeholder = { COPY(path, "aboutTor.search.label") } + +tor-browser-home-message-introduction = { COPY(path, "aboutTor.ready2.label") } +""", + path="aboutTor.dtd", + ), + ) diff --git a/tools/torbrowser/l10n/migrations/bug-41622-neterror.py b/tools/torbrowser/l10n/migrations/bug-41622-neterror.py new file mode 100644 index 0000000000000000000000000000000000000000..0a9d3e23cf59b0c266332e480a43ae7e75a99db4 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-41622-neterror.py @@ -0,0 +1,21 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +onion-neterror-not-found-description = { COPY(path, "onionServices.descNotFound") } +onion-neterror-unreachable-description = { COPY(path, "onionServices.descInvalid") } +onion-neterror-disconnected-description = { COPY(path, "onionServices.introFailed") } +onion-neterror-connection-failed-description = { COPY(path, "onionServices.rendezvousFailed") } +onion-neterror-missing-authentication-description = { COPY(path, "onionServices.clientAuthMissing") } +onion-neterror-incorrect-authetication-description = { COPY(path, "onionServices.clientAuthIncorrect") } +onion-neterror-invalid-address-description = { COPY(path, "onionServices.badAddress") } +onion-neterror-timed-out-description = { COPY(path, "onionServices.introTimedOut") } +""", + path="torbutton.properties", + ), + ) diff --git a/tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py b/tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py new file mode 100644 index 0000000000000000000000000000000000000000..0192252c9e2fb8c38209c555149743067aed203f --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py @@ -0,0 +1,67 @@ +import re + +import fluent.syntax.ast as FTL +from fluent.migrate.transforms import COPY_PATTERN, FluentSource +from fluent.syntax.visitor import Visitor + + +class RemoveAnchorVisitor(Visitor): + """Class to remove <a> and </a> wrappers from a Fluent TextElement.""" + + def __init__(self): + # Good enough regex for our needs that will match starting and ending + # tags. + self._anchor_regex = re.compile(r"<\/?[aA](| [^>]*)>") + super().__init__() + + def visit_TextElement(self, node): + node.value = self._anchor_regex.sub("", node.value) + + +class RemoveAnchorTransform(FluentSource): + """Class to remove <a> and </a> wrappers from a Fluent source.""" + + def __call__(self, ctx): + pattern = ctx.get_fluent_source_pattern(self.path, self.key).clone() + # Visit every node in the pattern, replacing each TextElement's content. + RemoveAnchorVisitor().visit(pattern) + return pattern + + +def migrate(ctx): + # Convert + # + # downloads-tor-warning-title = A + # downloads-tor-warning-description = B<a data-l10n-name="tails-link">C</a>D + # + # to + # + # downloads-tor-warning-message-bar = + # .heading = A + # .message = BCD + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + [ + FTL.Message( + id=FTL.Identifier("downloads-tor-warning-message-bar"), + value=None, + attributes=[ + FTL.Attribute( + id=FTL.Identifier("heading"), + value=COPY_PATTERN( + "tor-browser.ftl", + "downloads-tor-warning-title", + ), + ), + FTL.Attribute( + id=FTL.Identifier("message"), + value=RemoveAnchorTransform( + "tor-browser.ftl", + "downloads-tor-warning-description", + ), + ), + ], + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42202-crypto-safety.py b/tools/torbrowser/l10n/migrations/bug-42202-crypto-safety.py new file mode 100644 index 0000000000000000000000000000000000000000..ca25fe749bd143d0f039dd1da341117cec456b4f --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42202-crypto-safety.py @@ -0,0 +1,34 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migrate.transforms import REPLACE + + +def migrate(ctx): + legacy_path = "cryptoSafetyPrompt.properties" + + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +crypto-safety-prompt-title = { COPY(path, "cryptoSafetyPrompt.cryptoTitle") } +crypto-safety-prompt-reload-button = { COPY(path, "cryptoSafetyPrompt.primaryAction") } +crypto-safety-prompt-dismiss-button = { COPY(path, "cryptoSafetyPrompt.secondaryAction") } +""", + path=legacy_path, + ) + + [ + # Replace "%1$S" and "%2$S" with "{ $address }" and "{ $host }" + FTL.Message( + id=FTL.Identifier("crypto-safety-prompt-body"), + value=REPLACE( + legacy_path, + "cryptoSafetyPrompt.cryptoBody", + { + "%1$S": VARIABLE_REFERENCE("address"), + "%2$S": VARIABLE_REFERENCE("host"), + }, + ), + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42203-about-dialog.py b/tools/torbrowser/l10n/migrations/bug-42203-about-dialog.py new file mode 100644 index 0000000000000000000000000000000000000000..6429deae2fddc5506d9c3004d866903ae647eda6 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42203-about-dialog.py @@ -0,0 +1,75 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import TERM_REFERENCE, transforms_from +from fluent.migrate.transforms import CONCAT, COPY, REPLACE + + +def migrate(ctx): + legacy_path = "aboutDialog.dtd" + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +about-dialog-questions-link = { COPY(path, "bottomLinks.questions") } +about-dialog-grow-tor-network-link = { COPY(path, "bottomLinks.grow") } +about-dialog-browser-license-link = { COPY(path, "bottomLinks.license") } +""", + path=legacy_path, + ) + + [ + # Concatenate as + # &project.start; + # <label data-l10n-name="project-link">&project.tpoLink;</a> + # &project.end; + # + # And replace any occurrence of "&brandShortName;" and + # "&vendorShortName;" with "-brand-short-name" and + # "-vendor-short-name", wherever they may appear. + FTL.Message( + id=FTL.Identifier("about-dialog-tor-project"), + value=CONCAT( + REPLACE( + legacy_path, + "project.start", + { + "&brandShortName;": TERM_REFERENCE("brand-short-name"), + "&vendorShortName;": TERM_REFERENCE("vendor-short-name"), + }, + ), + FTL.TextElement('<label data-l10n-name="project-link">'), + REPLACE( + legacy_path, + "project.tpoLink", + { + "&brandShortName;": TERM_REFERENCE("brand-short-name"), + "&vendorShortName;": TERM_REFERENCE("vendor-short-name"), + }, + ), + FTL.TextElement("</label>"), + REPLACE( + legacy_path, + "project.end", + { + "&brandShortName;": TERM_REFERENCE("brand-short-name"), + "&vendorShortName;": TERM_REFERENCE("vendor-short-name"), + }, + ), + ), + ), + # Concatenate with two link labels. + FTL.Message( + id=FTL.Identifier("about-dialog-help-out"), + value=CONCAT( + COPY(legacy_path, "help.start"), + FTL.TextElement('<label data-l10n-name="donate-link">'), + COPY(legacy_path, "help.donateLink"), + FTL.TextElement("</label>"), + COPY(legacy_path, "help.or"), + FTL.TextElement('<label data-l10n-name="community-link">'), + COPY(legacy_path, "help.getInvolvedLink"), + FTL.TextElement("</label>"), + COPY(legacy_path, "help.end"), + ), + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42206-rulesets.py b/tools/torbrowser/l10n/migrations/bug-42206-rulesets.py new file mode 100644 index 0000000000000000000000000000000000000000..1252b56bd723f0210aa6b67e281b35e947194320 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42206-rulesets.py @@ -0,0 +1,70 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import transforms_from +from fluent.migrate.transforms import REPLACE + + +def migrate(ctx): + legacy_path = "rulesets.properties" + + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +rulesets-warning-heading = { COPY(path, "rulesets.warningTitle") } +rulesets-warning-description = { COPY(path, "rulesets.warningDescription") } +rulesets-warning-checkbox = { COPY(path, "rulesets.warningEnable") } +rulesets-warning-continue-button = { COPY(path, "rulesets.warningButton") } + +rulesets-side-panel-heading = { COPY(path, "rulesets.rulesets") } +rulesets-side-panel-no-rules = { COPY(path, "rulesets.noRulesets") } + +rulesets-update-never = { COPY(path, "rulesets.neverUpdated") } +rulesets-update-rule-disabled = { COPY(path, "rulesets.disabled") } + +rulesets-details-edit-button = { COPY(path, "rulesets.edit") } +rulesets-details-enable-checkbox = { COPY(path, "rulesets.enable") } +rulesets-details-update-button = { COPY(path, "rulesets.checkUpdates") } +rulesets-details-save-button = { COPY(path, "rulesets.save") } +rulesets-details-cancel-button = { COPY(path, "rulesets.cancel") } +rulesets-details-jwk-input = + .placeholder = { COPY(path, "rulesets.jwkPlaceholder") } +rulesets-details-jwk-input-invalid = { COPY(path, "rulesets.jwkInvalid") } +rulesets-details-path = { COPY(path, "rulesets.pathPrefix") } +rulesets-details-path-input = + .placeholder = { COPY(path, "rulesets.pathPrefixPlaceholder") } +rulesets-details-path-input-invalid = { COPY(path, "rulesets.pathPrefixInvalid") } +rulesets-details-scope = { COPY(path, "rulesets.scope") } +rulesets-details-scope-input = + .placeholder = { COPY(path, "rulesets.scopePlaceholder") } +rulesets-details-scope-input-invalid = { COPY(path, "rulesets.scopeInvalid") } +""", + path=legacy_path, + ) + + [ + # Replace "%1$S" with "{ DATETIME($date, dateStyle: "long") }" + FTL.Message( + FTL.Identifier("rulesets-update-last"), + value=REPLACE( + legacy_path, + "rulesets.lastUpdated", + { + "%1$S": FTL.FunctionReference( + FTL.Identifier("DATETIME"), + arguments=FTL.CallArguments( + positional=[ + FTL.VariableReference(FTL.Identifier("date")) + ], + named=[ + FTL.NamedArgument( + FTL.Identifier("dateStyle"), + value=FTL.StringLiteral("long"), + ) + ], + ), + ) + }, + ), + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42207-settings.py b/tools/torbrowser/l10n/migrations/bug-42207-settings.py new file mode 100644 index 0000000000000000000000000000000000000000..4c93491af14d7236310e838ddd6b08d777d71aa2 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42207-settings.py @@ -0,0 +1,88 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + legacy_path = "settings.properties" + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +tor-connection-settings-heading = { COPY(path, "settings.categoryTitle") } +tor-connection-browser-learn-more-link = { COPY(path, "settings.learnMore") } + +tor-connection-quickstart-heading = { COPY(path, "settings.quickstartHeading") } +tor-connection-quickstart-checkbox = + .label = { COPY(path, "settings.quickstartCheckbox") } + +tor-connection-internet-status-label = { COPY(path, "settings.statusInternetLabel") } +tor-connection-internet-status-test-button = { COPY(path, "settings.statusInternetTest") } +tor-connection-internet-status-online = { COPY(path, "settings.statusInternetOnline") } +tor-connection-internet-status-offline = { COPY(path, "settings.statusInternetOffline") } + +tor-bridges-heading = { COPY(path, "settings.bridgesHeading") } +tor-bridges-overview = { COPY(path, "settings.bridgesDescription2") } +tor-bridges-learn-more-link = { COPY(path, "settings.learnMore") } + +tor-bridges-built-in-obfs4-description = { COPY(path, "settings.builtinBridgeObfs4Description2") } +tor-bridges-built-in-snowflake-name = { COPY(path, "settings.builtinBridgeSnowflake") } +tor-bridges-built-in-snowflake-description = { COPY(path, "settings.builtinBridgeSnowflakeDescription2") } +tor-bridges-built-in-meek-azure-name = { COPY(path, "settings.builtinBridgeMeekAzure") } +tor-bridges-built-in-meek-azure-description = { COPY(path, "settings.builtinBridgeMeekAzureDescription2") } + +remove-all-bridges-warning-title = { COPY(path, "settings.bridgeRemoveAllDialogTitle") } +remove-all-bridges-warning-description = { COPY(path, "settings.bridgeRemoveAllDialogDescription") } +remove-all-bridges-warning-remove-button = { COPY(path, "settings.remove") } + +bridge-qr-dialog-title = + .title = { COPY(path, "settings.scanQrTitle") } + +bridge-dialog-button-connect = { COPY(path, "settings.bridgeButtonConnect") } +bridge-dialog-button-accept = { COPY(path, "settings.bridgeButtonAccept") } +bridge-dialog-button-submit = { COPY(path, "settings.submitCaptcha") } + +built-in-dialog-title = + .title = { COPY(path, "settings.builtinBridgeHeader") } +built-in-dialog-snowflake-radio-option = + .label = { COPY(path, "settings.builtinBridgeSnowflake") } +built-in-dialog-meek-azure-radio-option = + .label = { COPY(path, "settings.builtinBridgeMeekAzure") } + +request-bridge-dialog-title = + .title = { COPY(path, "settings.requestBridgeDialogTitle") } +request-bridge-dialog-top-wait = { COPY(path, "settings.contactingBridgeDB") } +request-bridge-dialog-top-solve = { COPY(path, "settings.solveTheCaptcha") } +request-bridge-dialog-captcha-input = + .placeholder = { COPY(path, "settings.captchaTextboxPlaceholder") } +request-bridge-dialog-captcha-failed = { COPY(path, "settings.incorrectCaptcha") } + +tor-advanced-settings-heading = { COPY(path, "settings.advancedHeading") } +tor-advanced-settings-button = { COPY(path, "settings.advancedButton") } + +tor-log-dialog-copy-button-copied = + .label = { COPY(path, "settings.copied") } + +tor-advanced-dialog-proxy-socks4-menuitem = + .label = { COPY(path, "settings.proxyTypeSOCKS4") } +tor-advanced-dialog-proxy-socks5-menuitem = + .label = { COPY(path, "settings.proxyTypeSOCKS5") } +tor-advanced-dialog-proxy-http-menuitem = + .label = { COPY(path, "settings.proxyTypeHTTP") } +tor-advanced-dialog-proxy-address-input-label = { COPY(path, "settings.proxyAddress") } +tor-advanced-dialog-proxy-address-input = + .placeholder = { COPY(path, "settings.proxyAddressPlaceholder") } +tor-advanced-dialog-proxy-port-input-label = { COPY(path, "settings.proxyPort") } +tor-advanced-dialog-proxy-username-input-label = { COPY(path, "settings.proxyUsername") } +tor-advanced-dialog-proxy-username-input = + .placeholder = { COPY(path, "settings.proxyUsernamePasswordPlaceholder") } +tor-advanced-dialog-proxy-password-input-label = { COPY(path, "settings.proxyPassword") } +tor-advanced-dialog-proxy-password-input = + .placeholder = { COPY(path, "settings.proxyUsernamePasswordPlaceholder") } +tor-advanced-dialog-firewall-checkbox = + .label = { COPY(path, "settings.useFirewall") } +tor-advanced-dialog-firewall-ports-input = + .placeholder = { COPY(path, "settings.allowedPortsPlaceholder") } +""", + path=legacy_path, + ), + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42209-tor-circuit.py b/tools/torbrowser/l10n/migrations/bug-42209-tor-circuit.py new file mode 100644 index 0000000000000000000000000000000000000000..592902ea5e27e534e20b285b239f4d4c49cb93cd --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42209-tor-circuit.py @@ -0,0 +1,83 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migrate.transforms import CONCAT, REPLACE + + +def migrate(ctx): + legacy_dtd = "torbutton.dtd" + legacy_properties = "torbutton.properties" + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +menu-new-tor-circuit = + .label = { COPY(dtd_path, "torbutton.context_menu.new_circuit") } + .accesskey = { COPY(dtd_path, "torbutton.context_menu.new_circuit_key") } +appmenuitem-new-tor-circuit = + .label = { COPY(dtd_path, "torbutton.context_menu.new_circuit_sentence_case") } +toolbar-new-tor-circuit = + .label = { COPY(dtd_path, "torbutton.context_menu.new_circuit_sentence_case") } + .tooltiptext = { toolbar-new-tor-circuit.label } + +tor-circuit-urlbar-button = + .tooltiptext = { COPY(dtd_path, "torbutton.circuit_display.title") } + +tor-circuit-panel-node-list-introduction = { COPY(dtd_path, "torbutton.circuit_display.title") } +tor-circuit-panel-node-browser = { COPY(path, "torbutton.circuit_display.this_browser") } +tor-circuit-panel-node-onion-relays = { COPY(path, "torbutton.circuit_display.onion-site-relays") } +tor-circuit-panel-node-bridge = { COPY(path, "torbutton.circuit_display.tor_bridge") } +tor-circuit-panel-node-unknown-region = { COPY(path, "torbutton.circuit_display.unknown_region") } + +tor-circuit-panel-new-button = { COPY(dtd_path, "torbutton.context_menu.new_circuit_sentence_case") } +tor-circuit-panel-new-button-description-guard = { COPY(path, "torbutton.circuit_display.new-circuit-guard-description") } +tor-circuit-panel-new-button-description-bridge = { COPY(path, "torbutton.circuit_display.new-circuit-bridge-description") } +""", + dtd_path=legacy_dtd, + path=legacy_properties, + ) + + [ + # Replace "%S" with "{ $host }" + FTL.Message( + id=FTL.Identifier("tor-circuit-panel-heading"), + value=REPLACE( + legacy_properties, + "torbutton.circuit_display.heading", + {"%1$S": VARIABLE_REFERENCE("host")}, + ), + ), + # Replace "%S" with "<a data-l10n-name="alias-link">{ $alias }</a>" + FTL.Message( + id=FTL.Identifier("tor-circuit-panel-alias"), + value=REPLACE( + legacy_properties, + "torbutton.circuit_display.connected-to-alias", + { + "%1$S": CONCAT( + FTL.TextElement('<a data-l10n-name="alias-link">'), + VARIABLE_REFERENCE("alias"), + FTL.TextElement("</a>"), + ) + }, + ), + ), + # Replace "%S" with "{ $region }" + FTL.Message( + id=FTL.Identifier("tor-circuit-panel-node-region-guard"), + value=REPLACE( + legacy_properties, + "torbutton.circuit_display.region-guard-node", + {"%1$S": VARIABLE_REFERENCE("region")}, + ), + ), + # Replace "%S" with "{ $bridge-type }" + FTL.Message( + id=FTL.Identifier("tor-circuit-panel-node-typed-bridge"), + value=REPLACE( + legacy_properties, + "torbutton.circuit_display.tor_typed_bridge", + {"%1$S": VARIABLE_REFERENCE("bridge-type")}, + ), + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42210-download-warning.py b/tools/torbrowser/l10n/migrations/bug-42210-download-warning.py new file mode 100644 index 0000000000000000000000000000000000000000..5bbedd50af56b89ed4132d6b39b503f405c00ac2 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42210-download-warning.py @@ -0,0 +1,39 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import transforms_from +from fluent.migrate.transforms import CONCAT, COPY, REPLACE + + +def migrate(ctx): + legacy_path = "torbutton.properties" + + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +downloads-tor-warning-title = { COPY(path, "torbutton.download.warning.title") } +downloads-tor-warning-dismiss-button = { COPY(path, "torbutton.download.warning.dismiss") } +""", + path=legacy_path, + ) + + [ + # Replace "%S" with link to Tails website. + FTL.Message( + id=FTL.Identifier("downloads-tor-warning-description"), + value=REPLACE( + legacy_path, + "torbutton.download.warning.description", + { + "%1$S": CONCAT( + FTL.TextElement('<a data-l10n-name="tails-link">'), + COPY( + legacy_path, + "torbutton.download.warning.tails_brand_name", + ), + FTL.TextElement("</a>"), + ) + }, + ), + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42211-new-identity.py b/tools/torbrowser/l10n/migrations/bug-42211-new-identity.py new file mode 100644 index 0000000000000000000000000000000000000000..c7a661c2bbde08e5b9d16ab895e812d38f756cfb --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42211-new-identity.py @@ -0,0 +1,48 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import TERM_REFERENCE, transforms_from +from fluent.migrate.transforms import REPLACE + + +def migrate(ctx): + legacy_path = "newIdentity.properties" + + ctx.add_transforms( + "base-browser.ftl", + "base-browser.ftl", + transforms_from( + """ +menu-new-identity = + .label = { COPY(path, "new_identity") } + .accesskey = { COPY(path, "new_identity_menu_accesskey") } +appmenuitem-new-identity = + .label = { COPY(path, "new_identity_sentence_case") } +toolbar-new-identity = + .label = { COPY(path, "new_identity_sentence_case") } + .tooltiptext = { toolbar-new-identity.label } + +new-identity-dialog-title = { COPY(path, "new_identity_prompt_title") } +new-identity-dialog-never-ask-checkbox = + .label = { COPY(path, "new_identity_ask_again") } + +new-identity-blocked-home-ignore-button = { COPY(path, "new_identity_home_load_button") } +""", + path=legacy_path, + ) + + [ + # Replace "%S" with "{ -brand-short-name }" in confirm button. + FTL.Message( + id=FTL.Identifier("new-identity-dialog-confirm"), + value=None, + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=REPLACE( + legacy_path, + "new_identity_restart", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + ], + ), + ], + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42212-onion-services.py b/tools/torbrowser/l10n/migrations/bug-42212-onion-services.py new file mode 100644 index 0000000000000000000000000000000000000000..f3ee2c36a6edfc0463d67286416a16c135722f67 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42212-onion-services.py @@ -0,0 +1,27 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + dtd_path = "torbutton.dtd" + properties_path = "torbutton.properties" + + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +onion-site-authentication-prompt-learn-more = { COPY(path, "onionServices.learnMore") } +onion-site-authentication-prompt-remember-checkbox = + .label = { COPY(dtd_path, "torbutton.onionServices.authPrompt.persistCheckboxLabel") } +onion-site-authentication-prompt-invalid-key = { COPY(path, "onionServices.authPrompt.invalidKey") } +onion-site-authentication-prompt-setting-key-failed = { COPY(path, "onionServices.authPrompt.failedToSetKey") } +onion-site-authentication-preferences-learn-more = { COPY(path, "onionServices.learnMore") } +onion-site-saved-keys-dialog-table-header-key = + .label = { COPY(path, "onionServices.authPreferences.onionKey") } +onion-site-saved-keys-dialog-remove-button = { COPY(path, "onionServices.authPreferences.remove") } +onion-site-saved-keys-dialog-remove-keys-error-message = { COPY(path, "onionServices.authPreferences.failedToRemoveKey") } +""", + dtd_path=dtd_path, + path=properties_path, + ), + ) diff --git a/tools/torbrowser/l10n/migrations/bug-42214-security-level.py b/tools/torbrowser/l10n/migrations/bug-42214-security-level.py new file mode 100644 index 0000000000000000000000000000000000000000..35e20425d900ffb5fba01994ec666834128c9b92 --- /dev/null +++ b/tools/torbrowser/l10n/migrations/bug-42214-security-level.py @@ -0,0 +1,43 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + ctx.add_transforms( + "base-browser.ftl", + "base-browser.ftl", + transforms_from( + """ +security-level-panel-level-standard = { COPY(path, "security_level_standard") } +security-level-panel-level-safer = { COPY(path, "security_level_safer") } +security-level-panel-level-safest = { COPY(path, "security_level_safest") } +security-level-panel-learn-more-link = { COPY(path, "security_level_learn_more") } +security-level-panel-open-settings-button = { COPY(path, "security_level_open_settings") } + +security-level-preferences-heading = { COPY(path, "security_level") } +security-level-preferences-overview = { COPY(path, "security_level_overview") } +security-level-preferences-learn-more-link = { COPY(path, "security_level_learn_more") } +security-level-preferences-level-standard = + .label = { COPY(path, "security_level_standard") } +security-level-preferences-level-safer = + .label = { COPY(path, "security_level_safer") } +security-level-preferences-level-safest = + .label = { COPY(path, "security_level_safest") } + +security-level-summary-standard = { COPY(path, "security_level_standard_summary") } +security-level-summary-safer = { COPY(path, "security_level_safer_summary") } +security-level-summary-safest = { COPY(path, "security_level_safest_summary") } + + +security-level-preferences-bullet-https-only-javascript = { COPY(path, "security_level_js_https_only") } +security-level-preferences-bullet-limit-font-and-symbols = { COPY(path, "security_level_limit_typography") } +security-level-preferences-bullet-limit-media = { COPY(path, "security_level_limit_media") } +security-level-preferences-bullet-disabled-javascript = { COPY(path, "security_level_js_disabled") } +security-level-preferences-bullet-limit-font-and-symbols-and-images = { COPY(path, "security_level_limit_typography_svg") } + +security-level-panel-custom-badge = { COPY(path, "security_level_custom") } +security-level-preferences-custom-heading = { COPY(path, "security_level_custom_heading") } +security-level-summary-custom = { COPY(path, "security_level_custom_summary") } +""", + path="securityLevel.properties", + ), + ) diff --git a/tools/torbrowser/update_emojis.py b/tools/torbrowser/update_emojis.py new file mode 100755 index 0000000000000000000000000000000000000000..ed566f1b08574821721da85aa79e88d5087a8c5c --- /dev/null +++ b/tools/torbrowser/update_emojis.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +"""Script to update flag emojis and bridg emojis SVG files from Twemoji, and to +pull locale emoji descriptions form Unicode CLDR. +""" + +import argparse +import datetime +import json +import re +from pathlib import Path +from shutil import copyfile +from xml.dom.minidom import parse + +# Currently the script is in tools/torbrowser/ +FIREFOX_ROOT = Path(__file__).parents[2] +SCRIPT_PATH = Path(__file__).relative_to(FIREFOX_ROOT) + +LANGS = [ + "ar", + "be", + "bg", + "ca", + "cs", + "da", + "de", + "el", + "en", + "es", + "fa", + "fi", + "fr", + "ga", + "he", + "hu", + "id", + "is", + "it", + "ja", + "ka", + "ko", + "lt", + "mk", + "ms", + "my", + "nb", # no + "nl", + "pl", + "pt", + "ro", + "ru", + "sq", + "sv", + "th", + "tr", + "uk", + "vi", + "zh-CN", # zh, zh-hans + "zh-TW", # zh_Hant, zh-hant +] + + +def generated_message(): + """Get the message describing the generation script and time.""" + date = datetime.date.isoformat(datetime.datetime.now(datetime.UTC)) + return f"Generated by {SCRIPT_PATH} on {date}" + + +def copy_emoji_svgs(emoji_codepoints, from_dir, to_dir): + """Copy the emojis specified in `emoji_codepoints` in `from_dir` to + `to_dir`. Each item in the `emoji_codepoints` list should be an + iterable over an emoji's codepoints. + """ + + to_dir.mkdir(exist_ok=True) + filename_set = set() + for codepoint in emoji_codepoints: + filename = codepoint + ".svg" + filename_set.add(filename) + src = from_dir / filename + dst = to_dir / filename + copyfile(src, dst) + + # Clean up old svgs. + for file in to_dir.iterdir(): + if file.suffix != ".svg" or file.name in filename_set: + continue + file.unlink() + + with open(to_dir / "README.txt", "w", encoding="utf8") as file: + file.write(generated_message() + "\n") + + +def get_flag_codepoints(file): + """Get the codepoint hex strings for all the region flags in the given + `file`. + """ + + flag_line_regex = re.compile( + r"^([0-9A-F]+) ([0-9A-F]+) +; RGI_Emoji_Flag_Sequence +;" + ) + + codepoints = [] + + for line in file: + match = flag_line_regex.match(line) + if not match: + continue + # The emoji name includes a dash "-" between the codepoints. + codepoints.append(f"{match.group(1).lower()}-{match.group(2).lower()}") + + return codepoints + + +def copy_flag_svgs(from_dir): + """Copy the flag svgs from `from_dir`.""" + with open( + FIREFOX_ROOT / "intl/icu/source/data/unidata/emoji-sequences.txt", + "r", + encoding="utf8", + ) as file: + flag_codepoints = get_flag_codepoints(file) + + flag_dest_dir = ( + FIREFOX_ROOT / "browser/components/torcircuit/content/tor-circuit-flags" + ) + + copy_emoji_svgs(flag_codepoints, from_dir, flag_dest_dir) + + +BRIDGE_DIR = FIREFOX_ROOT / "browser/components/torpreferences/content/bridgemoji" + + +def get_bridge_codepoints(): + """Get the list of codepoints for the bridge emojis as hex strings.""" + emoji_list = [] + with open(BRIDGE_DIR / "bridge-emojis.json", "r", encoding="utf8") as file: + for emoji in json.load(file): + if len(emoji) > 2 or (len(emoji) == 2 and ord(emoji[1]) != 0xFE0F): + # U+FE0F is "VARIATION SELECTOR-16" is the emoji variant + # selector (as opposed to the text selector U+FE0E). But this is + # not included in the emoji's svg name or the annotations. + raise ValueError(f"Unsupported emoji {emoji}: too many codepoints") + # Only keep the first character's codepoint. + emoji_list.append(f"{ord(emoji[0]):x}") + + return emoji_list + + +def copy_bridge_svgs(from_dir): + """Copy the bridge svgs from `from_dir`.""" + bridge_codepoints = get_bridge_codepoints() + + bridge_dest_dir = BRIDGE_DIR / "svgs" + + copy_emoji_svgs(bridge_codepoints, from_dir, bridge_dest_dir) + + +def get_emoji_descriptions(emoji_codepoints, annotations_file): + """Get the emoji descriptions for the given `emoji_strings` found in the + given `annotation_file`. + """ + descriptions = {} + doc = parse(annotations_file) + for annotation in doc.getElementsByTagName("annotation"): + if annotation.getAttribute("type") != "tts": + continue + + emoji = annotation.getAttribute("cp") + if len(emoji) != 1: + continue + + codepoint = f"{ord(emoji):x}" + if codepoint not in emoji_codepoints: + continue + + annotation.normalize() + descriptions[codepoint] = annotation.firstChild.data + + missing = ",".join( + chr(int(codepoint, 16)) + for codepoint in emoji_codepoints + if codepoint not in descriptions + ) + if missing: + raise ValueError( + f"Missing descriptions in {annotations_file.name} for {missing}" + ) + + return descriptions + + +def save_bridge_emoji_descriptions(from_dir): + """Save the emoji descriptions found under the directory `from_dir`.""" + bridge_codepoints = get_bridge_codepoints() + data = {"_comment": generated_message()} + + for lang in LANGS: + if lang == "zh-CN": + filename = "zh" + elif lang == "zh-TW": + filename = "zh_Hant" + elif lang == "nb": + filename = "no" + else: + filename = lang + with open( + from_dir / f"common/annotations/{filename}.xml", "r", encoding="utf8" + ) as file: + data[lang] = get_emoji_descriptions(bridge_codepoints, file) + + with open(BRIDGE_DIR / "annotations.json", "w", encoding="utf8") as file: + json.dump(data, file, ensure_ascii=False, indent=2) + file.write("\n") + + +parser = argparse.ArgumentParser( + description="Update the emojis SVGs from Twemoji and their descriptions.\n" + "SVGs can be extracted from twe-svg.zip from " + "https://github.com/mozilla/twemoji-colr\n" + "The unicode CLDR repository is taken from " + "https://github.com/unicode-org/cldr.git" +) +parser.add_argument( + "--flag-svgs", metavar="<dir>", help="location of the flag emoji SVGs directory" +) +parser.add_argument( + "--bridge-svgs", metavar="<dir>", help="location of the bridge emoji SVGs directory" +) +parser.add_argument( + "--svgs", metavar="<dir>", help="defines both --bridge-svgs and --flag-svgs" +) +parser.add_argument( + "--cldr", metavar="<dir>", help="location of the unicode CLDR repository" +) + +parsed_args = parser.parse_args() + +flag_svg_dir = parsed_args.flag_svgs or parsed_args.svgs +bridge_svg_dir = parsed_args.bridge_svgs or parsed_args.svgs +cldr_dir = parsed_args.cldr + +if not flag_svg_dir and not bridge_svg_dir and not cldr_dir: + print("No arguments") + +if flag_svg_dir: + copy_flag_svgs(Path(flag_svg_dir)) + +if bridge_svg_dir: + copy_bridge_svgs(Path(bridge_svg_dir)) + +if cldr_dir: + save_bridge_emoji_descriptions(Path(cldr_dir)) diff --git a/tools/update-packaging/common.sh b/tools/update-packaging/common.sh index e055b1c24efd546bf7f98868a1c9b3de59e949d0..591d347ab878f2ab969968fc11087f0389591bf7 100755 --- a/tools/update-packaging/common.sh +++ b/tools/update-packaging/common.sh @@ -8,6 +8,10 @@ # Author: Darin Fisher # +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove all lines in this file that contain: +# TorBrowser/Data + # ----------------------------------------------------------------------------- QUIET=0 @@ -111,6 +115,15 @@ make_add_if_not_instruction() { echo "add-if-not \"$f\" \"$f\"" >> "$filev3" } +make_addsymlink_instruction() { + link="$1" + target="$2" + filev3="$3" + + verbose_notice " addsymlink: $link -> $target" + echo "addsymlink \"$link\" \"$target\"" >> "$filev3" +} + make_patch_instruction() { f="$1" filev3="$2" @@ -170,6 +183,10 @@ append_remove_instructions() { # List all files in the current directory, stripping leading "./" # Pass a variable name and it will be filled as an array. +# To support Tor Browser updates, skip the following files: +# TorBrowser/Data/Browser/profiles.ini +# TorBrowser/Data/Browser/profile.default/bookmarks.html +# TorBrowser/Data/Tor/torrc list_files() { count=0 temp_filelist=$(mktemp) @@ -180,6 +197,11 @@ list_files() { | sed 's/\.\/\(.*\)/\1/' \ | sort -r > "${temp_filelist}" while read file; do + if [ "$file" = "TorBrowser/Data/Browser/profiles.ini" -o \ + "$file" = "TorBrowser/Data/Browser/profile.default/bookmarks.html" -o \ + "$file" = "TorBrowser/Data/Tor/torrc" ]; then + continue; + fi eval "${1}[$count]=\"$file\"" (( count++ )) done < "${temp_filelist}" @@ -201,3 +223,19 @@ list_dirs() { done < "${temp_dirlist}" rm "${temp_dirlist}" } + +# List all symbolic links in the current directory, stripping leading "./" +list_symlinks() { + count=0 + + find . -type l \ + | sed 's/\.\/\(.*\)/\1/' \ + | sort -r > "temp-symlinklist" + while read symlink; do + target=$(readlink "$symlink") + eval "${1}[$count]=\"$symlink\"" + eval "${2}[$count]=\"$target\"" + (( count++ )) + done < "temp-symlinklist" + rm "temp-symlinklist" +} diff --git a/tools/update-packaging/make_full_update.sh b/tools/update-packaging/make_full_update.sh index db2c5898efdc2f68a59ff58cafddedc3b7c6cb1f..603988997405dd2e79347e82345e5ab98fa40dd3 100755 --- a/tools/update-packaging/make_full_update.sh +++ b/tools/update-packaging/make_full_update.sh @@ -71,6 +71,7 @@ if [ ! -f "precomplete" ]; then fi list_files files +list_symlinks symlinks symlink_targets popd @@ -81,6 +82,21 @@ notice "Adding type instruction to update manifests" notice " type complete" echo "type \"complete\"" >> "$updatemanifestv3" +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove the following lines: +# If removal of any old, existing directories is desired, emit the appropriate +# rmrfdir commands. +notice "" +notice "Adding directory removal instructions to update manifests" +for dir_to_remove in $directories_to_remove; do + # rmrfdir requires a trailing slash; if slash is missing, add one. + if ! [[ "$dir_to_remove" =~ /$ ]]; then + dir_to_remove="${dir_to_remove}/" + fi + echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3" +done +# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal + notice "" notice "Adding file add instructions to update manifests" num_files=${#files[*]} @@ -102,6 +118,15 @@ for ((i=0; $i<$num_files; i=$i+1)); do targetfiles="$targetfiles \"$f\"" done +notice "" +notice "Adding symlink add instructions to update manifests" +num_symlinks=${#symlinks[*]} +for ((i=0; $i<$num_symlinks; i=$i+1)); do + link="${symlinks[$i]}" + target="${symlink_targets[$i]}" + make_addsymlink_instruction "$link" "$target" "$updatemanifestv3" +done + # Append remove instructions for any dead files. notice "" notice "Adding file and directory remove instructions from file 'removed-files'" diff --git a/tools/update-packaging/make_incremental_update.sh b/tools/update-packaging/make_incremental_update.sh index 31b74813e50e2535e7d95b621feb9db5c4a2866d..21fe57a401632ad961543629b944ce76eefae98e 100755 --- a/tools/update-packaging/make_incremental_update.sh +++ b/tools/update-packaging/make_incremental_update.sh @@ -79,6 +79,8 @@ if [ $# = 0 ]; then fi requested_forced_updates='Contents/MacOS/firefox' +directories_to_remove="" +extra_files_to_remove="" while getopts "hqf:" flag do @@ -114,6 +116,28 @@ workdir="$(mktemp -d)" updatemanifestv3="$workdir/updatev3.manifest" archivefiles="updatev3.manifest" +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove the following lines: +# If the NoScript extension has changed between +# releases, add it to the "force updates" list. +ext_path='TorBrowser/Data/Browser/profile.default/extensions' +if [ -d "$newdir/$ext_path" ]; then + noscript='{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi' + + # NoScript is a packed extension, so we simply compare the old and the new + # .xpi files. + noscript_path="$ext_path/$noscript" + diff -a "$olddir/$noscript_path" "$newdir/$noscript_path" > /dev/null + rc=$? + if [ $rc -gt 1 ]; then + notice "Unexpected exit $rc from $noscript_path diff command" + exit 2 + elif [ $rc -eq 1 ]; then + requested_forced_updates="$requested_forced_updates $noscript_path" + fi +fi +# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal + mkdir -p "$workdir" # Generate a list of all files in the target directory. @@ -124,6 +148,7 @@ fi list_files oldfiles list_dirs olddirs +list_symlinks oldsymlinks oldsymlink_targets popd @@ -141,6 +166,7 @@ fi list_dirs newdirs list_files newfiles +list_symlinks newsymlinks newsymlink_targets popd @@ -151,6 +177,22 @@ notice "Adding type instruction to update manifests" notice " type partial" echo "type \"partial\"" >> $updatemanifestv3 +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove the following lines: +# If removal of any old, existing directories is desired, emit the appropriate +# rmrfdir commands. +notice "" +notice "Adding directory removal instructions to update manifests" +for dir_to_remove in $directories_to_remove; do + # rmrfdir requires a trailing slash, so add one if missing. + if ! [[ "$dir_to_remove" =~ /$ ]]; then + dir_to_remove="${dir_to_remove}/" + fi + echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3" +done +# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal + + notice "" notice "Adding file patch and add instructions to update manifests" @@ -242,6 +284,23 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); do fi done +# Remove and re-add symlinks +notice "" +notice "Adding symlink remove/add instructions to update manifests" +num_oldsymlinks=${#oldsymlinks[*]} +for ((i=0; $i<$num_oldsymlinks; i=$i+1)); do + link="${oldsymlinks[$i]}" + verbose_notice " remove: $link" + echo "remove \"$link\"" >> "$updatemanifestv3" +done + +num_newsymlinks=${#newsymlinks[*]} +for ((i=0; $i<$num_newsymlinks; i=$i+1)); do + link="${newsymlinks[$i]}" + target="${newsymlink_targets[$i]}" + make_addsymlink_instruction "$link" "$target" "$updatemanifestv3" +done + # Newly added files notice "" notice "Adding file add instructions to update manifests" @@ -286,6 +345,14 @@ notice "" notice "Adding file and directory remove instructions from file 'removed-files'" append_remove_instructions "$newdir" "$updatemanifestv3" +# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms, +# we should remove the following lines: +for f in $extra_files_to_remove; do + notice " remove \"$f\"" + echo "remove \"$f\"" >> "$updatemanifestv3" +done +# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal + notice "" notice "Adding directory remove instructions for directories that no longer exist" num_olddirs=${#olddirs[*]} diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp index 01ca680039edcc9f56900a40e0a94cb77a367383..6fb753210eeab9f51e78016836a27a0a683ff537 100644 --- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp @@ -1205,7 +1205,7 @@ NS_IMETHODIMP nsDocLoader::OnStatus(nsIRequest* aRequest, nsresult aStatus, mozilla::components::StringBundle::Service(); if (!sbs) return NS_ERROR_FAILURE; nsAutoString msg; - nsresult rv = sbs->FormatStatusMessage(aStatus, aStatusArg, msg); + nsresult rv = sbs->FormatStatusMessage(aStatus, aStatusArg, false, msg); if (NS_FAILED(rv)) return rv; // Keep around the message. In case a request finishes, we need to make sure diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp index 490674c1822186dcd8c780d94df00307a9383415..f80378840775b898c060d1c3ea8087fdd5c679f3 100644 --- a/uriloader/base/nsURILoader.cpp +++ b/uriloader/base/nsURILoader.cpp @@ -292,34 +292,42 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request) { LOG((" forceExternalHandling: %s", forceExternalHandling ? "yes" : "no")); if (forceExternalHandling && - mozilla::StaticPrefs::browser_download_open_pdf_attachments_inline()) { + (mozilla::StaticPrefs::browser_download_open_pdf_attachments_inline() || + mozilla::StaticPrefs::browser_download_ignore_content_disposition())) { // Check if this is a PDF which should be opened internally. We also handle // octet-streams that look like they might be PDFs based on their extension. bool isPDF = mContentType.LowerCaseEqualsASCII(APPLICATION_PDF); - if (!isPDF && - (mContentType.LowerCaseEqualsASCII(APPLICATION_OCTET_STREAM) || - mContentType.IsEmpty())) { + nsAutoCString ext; + if (mContentType.LowerCaseEqualsASCII(APPLICATION_OCTET_STREAM) || + mContentType.IsEmpty()) { nsAutoString flname; aChannel->GetContentDispositionFilename(flname); - isPDF = StringEndsWith(flname, u".pdf"_ns); - if (!isPDF) { + if (!flname.IsEmpty()) { + int32_t extStart = flname.RFindChar(u'.'); + if (extStart != kNotFound) { + CopyUTF16toUTF8(Substring(flname, extStart + 1), ext); + } + } + if (ext.IsEmpty() || (!mozilla::StaticPrefs:: + browser_download_ignore_content_disposition() && + !ext.EqualsLiteral("pdf"))) { nsCOMPtr<nsIURI> uri; aChannel->GetURI(getter_AddRefs(uri)); nsCOMPtr<nsIURL> url(do_QueryInterface(uri)); if (url) { - nsAutoCString ext; url->GetFileExtension(ext); - isPDF = ext.EqualsLiteral("pdf"); } } + isPDF = ext.EqualsLiteral("pdf"); } - // For a PDF, check if the preference is set that forces attachments to be - // opened inline. If so, treat it as a non-attachment by clearing - // 'forceExternalHandling' again. This allows it open a PDF directly - // instead of downloading it first. It may still end up being handled by - // a helper app depending anyway on the later checks. - if (isPDF) { + // One of the preferences to forces attachments to be opened inline is set. + // If so, treat it as a non-attachment by clearing 'forceExternalHandling' + // again. This allows it open a file directly instead of downloading it + // first. It may still end up being handled by a helper app depending anyway + // on the later checks. + if (mozilla::StaticPrefs::browser_download_ignore_content_disposition() || + isPDF) { nsCOMPtr<nsILoadInfo> loadInfo; aChannel->GetLoadInfo(getter_AddRefs(loadInfo)); @@ -328,8 +336,13 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request) { nsCOMPtr<nsIMIMEService> mimeSvc( do_GetService(NS_MIMESERVICE_CONTRACTID)); NS_ENSURE_TRUE(mimeSvc, NS_ERROR_FAILURE); - mimeSvc->GetFromTypeAndExtension(nsLiteralCString(APPLICATION_PDF), ""_ns, - getter_AddRefs(mimeInfo)); + if (isPDF) { + mimeSvc->GetFromTypeAndExtension(nsLiteralCString(APPLICATION_PDF), + ""_ns, getter_AddRefs(mimeInfo)); + } else { + mimeSvc->GetFromTypeAndExtension(mContentType, ext, + getter_AddRefs(mimeInfo)); + } if (mimeInfo) { int32_t action = nsIMIMEInfo::saveToDisk; diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index 2c27ae5c68810557ab4b60efd4b4893433dff77d..74069c0251024957409cb6aee041c295f8d9b4eb 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -898,8 +898,32 @@ nsresult nsExternalHelperAppService::GetFileTokenForPath( ////////////////////////////////////////////////////////////////////////////////////////////////////// // begin external protocol service default implementation... ////////////////////////////////////////////////////////////////////////////////////////////////////// + +static const char kExternalProtocolPrefPrefix[] = + "network.protocol-handler.external."; +static const char kExternalProtocolDefaultPref[] = + "network.protocol-handler.external-default"; + NS_IMETHODIMP nsExternalHelperAppService::ExternalProtocolHandlerExists( const char* aProtocolScheme, bool* aHandlerExists) { + // Replicate the same check performed in LoadURI. + // Deny load if the prefs say to do so + nsAutoCString externalPref(kExternalProtocolPrefPrefix); + externalPref += aProtocolScheme; + bool allowLoad = false; + *aHandlerExists = false; + if (NS_FAILED(Preferences::GetBool(externalPref.get(), &allowLoad))) { + // no scheme-specific value, check the default + if (NS_FAILED( + Preferences::GetBool(kExternalProtocolDefaultPref, &allowLoad))) { + return NS_OK; // missing default pref + } + } + + if (!allowLoad) { + return NS_OK; // explicitly denied + } + nsCOMPtr<nsIHandlerInfo> handlerInfo; nsresult rv = GetProtocolHandlerInfo(nsDependentCString(aProtocolScheme), getter_AddRefs(handlerInfo)); @@ -942,11 +966,6 @@ NS_IMETHODIMP nsExternalHelperAppService::IsExposedProtocol( return NS_OK; } -static const char kExternalProtocolPrefPrefix[] = - "network.protocol-handler.external."; -static const char kExternalProtocolDefaultPref[] = - "network.protocol-handler.external-default"; - // static nsresult nsExternalHelperAppService::EscapeURI(nsIURI* aURI, nsIURI** aResult) { MOZ_ASSERT(aURI); @@ -1920,6 +1939,12 @@ bool nsExternalAppHandler::IsDownloadSpam(nsIChannel* aChannel) { nsCOMPtr<nsIPermissionManager> permissionManager = mozilla::services::GetPermissionManager(); nsCOMPtr<nsIPrincipal> principal = loadInfo->TriggeringPrincipal(); + + // Always allow WebExtensions + if (principal && principal->SchemeIs("moz-extension")) { + return false; + } + bool exactHostMatch = false; constexpr auto type = "automatic-download"_ns; nsCOMPtr<nsIPermission> permission; @@ -1943,13 +1968,11 @@ bool nsExternalAppHandler::IsDownloadSpam(nsIChannel* aChannel) { if (capability == nsIPermissionManager::PROMPT_ACTION) { nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); - RefPtr<BrowsingContext> browsingContext; - loadInfo->GetBrowsingContext(getter_AddRefs(browsingContext)); nsAutoCString cStringURI; loadInfo->TriggeringPrincipal()->GetPrePath(cStringURI); observerService->NotifyObservers( - browsingContext, "blocked-automatic-download", + loadInfo, "blocked-automatic-download", NS_ConvertASCIItoUTF16(cStringURI.get()).get()); // FIXME: In order to escape memory leaks, currently we cancel blocked // downloads. This is temporary solution, because download data should be diff --git a/widget/ScrollbarDrawingWin.cpp b/widget/ScrollbarDrawingWin.cpp index c2d85ae671b0915793bf53d558f0262c364479e0..510175458df97b960bc3f8a628775972b3e8850e 100644 --- a/widget/ScrollbarDrawingWin.cpp +++ b/widget/ScrollbarDrawingWin.cpp @@ -11,6 +11,7 @@ #include "nsLayoutUtils.h" #include "Theme.h" #include "nsNativeTheme.h" +#include "nsContentUtils.h" namespace mozilla::widget { @@ -164,7 +165,10 @@ void ScrollbarDrawingWin::RecomputeScrollbarParams() { } ConfigureScrollbarSize(defaultSize); - if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) { + // Do not leak system size when using ResistFingerprinting. + if (!nsContentUtils::ShouldResistFingerprinting("No context available", + RFPTarget::CSSResolution) && + StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) { ConfigureScrollbarSize(LookAndFeel::GetInt( LookAndFeel::IntID::SystemScrollbarSize, defaultSize)); } diff --git a/widget/ScrollbarDrawingWin11.cpp b/widget/ScrollbarDrawingWin11.cpp index 8517b60baa81a1a32a25c6bff1e1cd1d35fbfca9..548dbc79fc59d089bb94e650420a799893851f83 100644 --- a/widget/ScrollbarDrawingWin11.cpp +++ b/widget/ScrollbarDrawingWin11.cpp @@ -11,6 +11,7 @@ #include "nsLayoutUtils.h" #include "Theme.h" #include "nsNativeTheme.h" +#include "nsContentUtils.h" using mozilla::gfx::sRGBColor; @@ -352,6 +353,11 @@ bool ScrollbarDrawingWin11::PaintScrollbarThumb( void ScrollbarDrawingWin11::RecomputeScrollbarParams() { ScrollbarDrawingWin::RecomputeScrollbarParams(); + if (nsContentUtils::ShouldResistFingerprinting("No context available", + RFPTarget::CSSResolution)) { + // Do not distinguish sizes between windows 10 and 11. + return; + } // TODO(emilio): Maybe make this configurable? Though this doesn't respect // classic Windows registry settings, and cocoa overlay scrollbars also don't // respect the override it seems, so this should be fine. diff --git a/widget/android/WebExecutorSupport.cpp b/widget/android/WebExecutorSupport.cpp index 44b9a4696eb83434e4524adecfd3b18863c487e8..6154ff192cd1b8de4f3cd8af07dda9732a9f899c 100644 --- a/widget/android/WebExecutorSupport.cpp +++ b/widget/android/WebExecutorSupport.cpp @@ -405,6 +405,14 @@ nsresult WebExecutorSupport::CreateStreamLoader( MOZ_ASSERT(cookieJarSettings); nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); + if (const auto origin = req->Origin(); origin) { + RefPtr<nsIURI> originUri; + rv = NS_NewURI(getter_AddRefs(originUri), origin->ToString()); + NS_ENSURE_SUCCESS(rv, NS_ERROR_MALFORMED_URI); + OriginAttributes attrs = loadInfo->GetOriginAttributes(); + attrs.SetFirstPartyDomain(true, originUri); + loadInfo->SetOriginAttributes(attrs); + } loadInfo->SetCookieJarSettings(cookieJarSettings); // setup http/https specific things diff --git a/widget/gtk/MPRISServiceHandler.cpp b/widget/gtk/MPRISServiceHandler.cpp index 1ce4aa519a7e1116e6249b3cfa5c60a93677fffc..a5a79c70278e43e69bdd9c14b175f901b99f7f06 100644 --- a/widget/gtk/MPRISServiceHandler.cpp +++ b/widget/gtk/MPRISServiceHandler.cpp @@ -450,8 +450,10 @@ void MPRISServiceHandler::InitIdentity() { do_GetService("@mozilla.org/xre/app-info;1", &rv); MOZ_ASSERT(NS_SUCCEEDED(rv)); +#ifndef BASE_BROWSER_VERSION rv = appInfo->GetVendor(mIdentity); MOZ_ASSERT(NS_SUCCEEDED(rv)); +#endif if (gAppData) { mDesktopEntry = gAppData->remotingName; @@ -460,7 +462,9 @@ void MPRISServiceHandler::InitIdentity() { MOZ_ASSERT(NS_SUCCEEDED(rv)); } +#ifndef BASE_BROWSER_VERSION mIdentity.Append(' '); +#endif mIdentity.Append(mDesktopEntry); // Compute the desktop entry name like nsAppRunner does for g_set_prgname diff --git a/widget/gtk/WidgetUtilsGtk.cpp b/widget/gtk/WidgetUtilsGtk.cpp index 0d2425b3d0d9a2270865c7961c942beba7364355..c717a132342c4569d0ec8a6500e78387a124caaf 100644 --- a/widget/gtk/WidgetUtilsGtk.cpp +++ b/widget/gtk/WidgetUtilsGtk.cpp @@ -143,6 +143,12 @@ void SetLastMousePressEvent(GdkEvent* aEvent) { bool IsRunningUnderSnap() { return !!GetSnapInstanceName(); } bool IsRunningUnderFlatpak() { + // tor-browser#42293: Don't disable updater when run by torbrowser-launcher + // flatpak + const char* torbrowserLauncher = g_getenv("TORBROWSER_LAUNCHER"); + if (torbrowserLauncher) { + return false; + } // https://gitlab.gnome.org/GNOME/gtk/-/blob/4300a5c609306ce77cbc8a3580c19201dccd8d13/gdk/gdk.c#L472 static bool sRunning = [] { return g_file_test("/.flatpak-info", G_FILE_TEST_EXISTS); diff --git a/widget/windows/WinTaskbar.cpp b/widget/windows/WinTaskbar.cpp index 67717499bc6617c4901e1cf94783df0fdf02dc52..9cf396b2162a9b75b8cc0c94b19ef44f1f47951c 100644 --- a/widget/windows/WinTaskbar.cpp +++ b/widget/windows/WinTaskbar.cpp @@ -206,7 +206,21 @@ bool WinTaskbar::GenerateAppUserModelID(nsAString& aAppUserModelId, bool aPrivateBrowsing) { // If marked as such in prefs, use a hash of the profile path for the id // instead of the install path hash setup by the installer. - if (Preferences::GetBool("taskbar.grouping.useprofile", false)) { + bool useProfile = Preferences::GetBool("taskbar.grouping.useprofile", false); + + { + // For portable mode, force the AUMID to be based on the profile directory + // instead of reading it from the registry. + bool isPortable = true; + // Do not even check if taskbar.grouping.useprofile is already true. + if (!useProfile && + NS_SUCCEEDED(gDirServiceProvider->GetIsPortableMode(&isPortable)) && + isPortable) { + useProfile = true; + } + } + + if (useProfile) { nsCOMPtr<nsIFile> profileDir; NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir)); diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index ead7bae51280cad3938dad3db34f94303401c4fb..440b37031115725cfb5f11a742fc2eb317fd662c 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -520,11 +520,13 @@ nsDataObj::nsDataObj(nsIURI* uri) m_enumFE = new CEnumFormatEtc(); m_enumFE->AddRef(); +#if !defined(BASE_BROWSER_VERSION) if (uri) { // A URI was obtained, so pass this through to the DataObject // so it can create a SourceURL for CF_HTML flavour uri->GetSpec(mSourceURL); } +#endif } //----------------------------------------------------- // destruction @@ -1969,6 +1971,7 @@ nsresult nsDataObj ::BuildPlatformHTML(const char* inOurHTML, *outPlatformHTML = nullptr; nsDependentCString inHTMLString(inOurHTML); +#if !defined(BASE_BROWSER_VERSION) // Do we already have mSourceURL from a drag? if (mSourceURL.IsEmpty()) { nsAutoString url; @@ -1976,6 +1979,7 @@ nsresult nsDataObj ::BuildPlatformHTML(const char* inOurHTML, AppendUTF16toUTF8(url, mSourceURL); } +#endif constexpr auto kStartHTMLPrefix = "Version:0.9\r\nStartHTML:"_ns; constexpr auto kEndHTMLPrefix = "\r\nEndHTML:"_ns; diff --git a/xpcom/base/ErrorList.py b/xpcom/base/ErrorList.py index fb5558204fa818e35798d5d2878c93c701e4c5a6..08c326125b10aefabe75932d4905876ce28ece18 100755 --- a/xpcom/base/ErrorList.py +++ b/xpcom/base/ErrorList.py @@ -89,6 +89,7 @@ modules["ERRORRESULT"] = Mod(43) # see Bug 1686041. modules["WIN32"] = Mod(44) modules["WDBA"] = Mod(45) +modules["TOR"] = Mod(46) # NS_ERROR_MODULE_GENERAL should be used by modules that do not # care if return code values overlap. Callers of methods that @@ -1242,6 +1243,28 @@ with modules["WDBA"]: errors["NS_ERROR_WDBA_BUILD"] = FAILURE(4) +# ======================================================================= +# 46: Tor-specific error codes. +# ======================================================================= +with modules["TOR"]: + # Tor onion service descriptor can not be found. + errors["NS_ERROR_TOR_ONION_SVC_NOT_FOUND"] = FAILURE(1) + # Tor onion service descriptor is invalid. + errors["NS_ERROR_TOR_ONION_SVC_IS_INVALID"] = FAILURE(2) + # Tor onion service introduction failed. + errors["NS_ERROR_TOR_ONION_SVC_INTRO_FAILED"] = FAILURE(3) + # Tor onion service rendezvous failed. + errors["NS_ERROR_TOR_ONION_SVC_REND_FAILED"] = FAILURE(4) + # Tor onion service missing client authorization. + errors["NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH"] = FAILURE(5) + # Tor onion service wrong client authorization. + errors["NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH"] = FAILURE(6) + # Tor onion service bad address. + errors["NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS"] = FAILURE(7) + # Tor onion service introduction timed out. + errors["NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT"] = FAILURE(8) + + # ======================================================================= # 51: NS_ERROR_MODULE_GENERAL # ======================================================================= diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index 1ad2dd24dd198e3c7e741bf4e54c74846ba9e8b5..9ab7ba510083e4710146be1e53a629e28de77995 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -844,6 +844,7 @@ STATIC_ATOMS = [ Atom("oninputsourceschange", "oninputsourceschange"), Atom("oninstall", "oninstall"), Atom("oninvalid", "oninvalid"), + Atom("headerOnionLocation", "onion-location"), Atom("onkeydown", "onkeydown"), Atom("onkeypress", "onkeypress"), Atom("onkeyup", "onkeyup"), diff --git a/xpcom/io/CocoaFileUtils.mm b/xpcom/io/CocoaFileUtils.mm index f45da3ec66615cdadeacad559d865882c2c719f0..fb3224345fbef36cdfe521f2510999f5b73106fa 100644 --- a/xpcom/io/CocoaFileUtils.mm +++ b/xpcom/io/CocoaFileUtils.mm @@ -330,8 +330,12 @@ CFTypeRefPtr<CFURLRef> GetTemporaryFolder() { CFTypeRefPtr<CFURLRef> GetProductDirectory(bool aLocal) { nsAutoreleasePool localPool; +#if defined(TOR_BROWSER) + NSSearchPathDirectory folderType = NSApplicationSupportDirectory; +#else NSSearchPathDirectory folderType = aLocal ? NSCachesDirectory : NSLibraryDirectory; +#endif NSFileManager* manager = [NSFileManager defaultManager]; return CFTypeRefPtr<CFURLRef>::WrapUnderGetRule((__bridge CFURLRef)[[manager URLsForDirectory:folderType diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp index 189f1efe130f404c09fc9697a9e4ea656d1159e1..e0128c024d868e25a7c8758c50ca46ecc1d8ac43 100644 --- a/xpcom/io/nsAppFileLocationProvider.cpp +++ b/xpcom/io/nsAppFileLocationProvider.cpp @@ -164,13 +164,118 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) { return NS_OK; } +#ifdef RELATIVE_DATA_DIR +static nsresult SetupPortableMode(nsIFile** aDirectory, bool aLocal, + bool& aIsPortable) { + // This is almost the same as nsXREDirProvider::GetPortableDataDir. + // However, it seems that this is never called, at least during simple usage + // of the browser. + + nsresult rv = NS_ERROR_UNEXPECTED; + nsCOMPtr<nsIProperties> directoryService( + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIFile> exeFile, exeDir; + rv = directoryService->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile), + getter_AddRefs(exeFile)); + rv = exeFile->Normalize(); + NS_ENSURE_SUCCESS(rv, rv); + rv = exeFile->GetParent(getter_AddRefs(exeDir)); + NS_ENSURE_SUCCESS(rv, rv); + +# if defined(XP_MACOSX) + nsAutoString exeDirPath; + rv = exeDir->GetPath(exeDirPath); + NS_ENSURE_SUCCESS(rv, rv); + // When the browser is installed in /Applications, we never run in portable + // mode. + if (exeDirPath.LowerCaseFindASCII("/applications/") == 0) { + aIsPortable = false; + return NS_OK; + } +# endif + +# if defined(MOZ_WIDGET_GTK) + // On Linux, Firefox supports the is-packaged-app for the .deb distribution. + nsLiteralCString systemInstallNames[] = {"system-install"_ns, + "is-packaged-app"_ns}; +# else + nsLiteralCString systemInstallNames[] = {"system-install"_ns}; +# endif + for (const nsLiteralCString& fileName : systemInstallNames) { + nsCOMPtr<nsIFile> systemInstallFile; + rv = exeDir->Clone(getter_AddRefs(systemInstallFile)); + NS_ENSURE_SUCCESS(rv, rv); + rv = systemInstallFile->AppendNative(fileName); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists = false; + rv = systemInstallFile->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + if (exists) { + aIsPortable = false; + return NS_OK; + } + } + + nsCOMPtr<nsIFile> localDir = exeDir; +# if defined(XP_MACOSX) + rv = exeDir->GetParent(getter_AddRefs(localDir)); + NS_ENSURE_SUCCESS(rv, rv); + exeDir = localDir; + rv = exeDir->GetParent(getter_AddRefs(localDir)); + NS_ENSURE_SUCCESS(rv, rv); +# endif + + rv = localDir->SetRelativePath(localDir.get(), + nsLiteralCString(RELATIVE_DATA_DIR)); + NS_ENSURE_SUCCESS(rv, rv); + if (aLocal) { + rv = localDir->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); + } + + bool exists = false; + rv = localDir->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + if (!exists) { + rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700); +# if defined(XP_MACOSX) + if (NS_FAILED(rv)) { + // On macOS, we forgive this failure to allow running from the DMG. + aIsPortable = false; + return NS_OK; + } +# else + NS_ENSURE_SUCCESS(rv, rv); +# endif + } + + localDir.forget(aDirectory); + aIsPortable = true; + return rv; +} +#endif + //---------------------------------------------------------------------------------------- // GetProductDirectory - Gets the directory which contains the application data // folder // -// UNIX : ~/.mozilla/ -// WIN : <Application Data folder on user's machine>\Mozilla -// Mac : :Documents:Mozilla: +// If portable mode is enabled: +// - aLocal == false: $APP_ROOT/$RELATIVE_DATA_DIR +// - aLocal == true: $APP_ROOT/$RELATIVE_DATA_DIR/Caches +// where $APP_ROOT is: +// - the parent directory of the executable on Windows and Linux +// - the root of the app bundle on macOS +// +// Otherwise: +// - Windows: +// - aLocal == false: %APPDATA%/$MOZ_USER_DIR +// - aLocal == true: %LOCALAPPDATA%/$MOZ_USER_DIR +// - macOS: +// - aLocal == false: kDomainLibraryFolderType/$MOZ_USER_DIR +// - aLocal == true: kCachedDataFolderType/$MOZ_USER_DIR +// - Unix: ~/$MOZ_USER_DIR //---------------------------------------------------------------------------------------- nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, bool aLocal) { @@ -178,10 +283,20 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, return NS_ERROR_INVALID_ARG; } - nsresult rv; + nsresult rv = NS_ERROR_UNEXPECTED; bool exists; nsCOMPtr<nsIFile> localDir; +#if defined(RELATIVE_DATA_DIR) + bool isPortable = false; + rv = SetupPortableMode(aLocalFile, aLocal, isPortable); + // If portable mode is enabled, we absolutely want it (e.g., to be sure there + // will not be disk leaks), so a failure is to be propagated. + if (NS_FAILED(rv) || isPortable) { + return rv; + } +#endif + #if defined(MOZ_WIDGET_COCOA) NS_NewLocalFile(u""_ns, true, getter_AddRefs(localDir)); if (!localDir) { @@ -194,6 +309,17 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, if (NS_FAILED(rv)) { return rv; } + +# if defined(TOR_BROWSER) + rv = localDir->AppendNative("TorBrowser-Data"_ns); + NS_ENSURE_SUCCESS(rv, rv); + rv = localDir->AppendNative("Browser"_ns); + NS_ENSURE_SUCCESS(rv, rv); + if (aLocal) { + rv = localDir->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); + } +# endif #elif defined(XP_WIN) nsCOMPtr<nsIProperties> directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); @@ -216,10 +342,12 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, # error dont_know_how_to_get_product_dir_on_your_platform #endif +#if !defined(TOR_BROWSER) rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR); if (NS_FAILED(rv)) { return rv; } +#endif rv = localDir->Exists(&exists); if (NS_SUCCEEDED(rv) && !exists) { @@ -239,9 +367,10 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, // GetDefaultUserProfileRoot - Gets the directory which contains each user // profile dir // -// UNIX : ~/.mozilla/ -// WIN : <Application Data folder on user's machine>\Mozilla\Profiles -// Mac : :Documents:Mozilla:Profiles: +// - Windows and macOS: $PRODUCT_DIRECTORY/Profiles +// - Unix: $PRODUCT_DIRECTORY +// See also GetProductDirectory for instructions on how $PRODUCT_DIRECTORY is +// generated. //---------------------------------------------------------------------------------------- nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot( nsIFile** aLocalFile, bool aLocal) { @@ -259,10 +388,13 @@ nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot( #if defined(MOZ_WIDGET_COCOA) || defined(XP_WIN) // These 3 platforms share this part of the path - do them as one +# ifndef TOR_BROWSER + // Legacy: we do not use "Profiles" on Tor Browser. rv = localDir->AppendRelativeNativePath("Profiles"_ns); if (NS_FAILED(rv)) { return rv; } +# endif bool exists; rv = localDir->Exists(&exists); diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp index 13decaea43f781d84cb2b503f483b82df085ec1f..c0221c561fa29f48ee803f972db23ff32442d53c 100644 --- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -1049,8 +1049,9 @@ NS_IMETHODIMP AppWindow::GetAvailScreenSize(int32_t* aAvailWidth, return NS_OK; } -// Rounds window size to 1000x1000, or, if there isn't enough available -// screen space, to a multiple of 200x100. +// Rounds window size to privacy.window.maxInnerWidth x +// privacy.window.maxInnerWidth, or, if there isn't enough available screen +// space, to a multiple of 200x100. NS_IMETHODIMP AppWindow::ForceRoundedDimensions() { if (mIsHiddenWindow) { return NS_OK; @@ -1090,6 +1091,11 @@ NS_IMETHODIMP AppWindow::ForceRoundedDimensions() { SetPrimaryContentSize(targetSizeDev.width, targetSizeDev.height); + // Ensure we force initial rounded size at least once, as checked by + // nsContentUtils::ShouldRoundWindowSizeForResistingFingerprinting(). + Preferences::SetBool("privacy.resistFingerprinting.letterboxing.didForceSize", + true); + return NS_OK; } @@ -2483,7 +2489,8 @@ void AppWindow::SizeShell() { "if RFP is enabled we want to round the dimensions of the new" "new pop up window regardless of their origin", RFPTarget::RoundWindowSize) && - windowType.EqualsLiteral("navigator:browser")) { + windowType.EqualsLiteral("navigator:browser") && + nsContentUtils::ShouldRoundWindowSizeForResistingFingerprinting()) { // Once we've got primary content, force dimensions. if (mPrimaryContentShell || mPrimaryBrowserParent) { ForceRoundedDimensions();