Mullvad Browser Extension

repository·main·Indexed 43 days ago

https://github.com/mullvad/browser-extension

A Firefox extension designed to improve the Mullvad VPN user experience. It provides connection information, DNS recommendations, and one-click access to proxy servers. Version 0.9.11.

Tokens
8K
Snippets
42
Records
49
Agent score
56%

What's inside Mullvad Browser Extension

  1. Build the extension

    main

    Use the following commands to generate extension builds:

    • Build assets: Run npm run build first to prepare the extension files.
    • Create XPI package: Run npm run pack:xpi to generate an .xpi file in the root directory.

    Additional build options are available in package.json.

    npm run build
    npm run pack:xpi
  2. Develop and run the extension locally

    main

    Follow these steps to start a development workflow:

    1. Install dependencies: Run npm install to install necessary packages.
    2. Start watcher: Run npm run dev in one terminal to enable automatic rebuilding when files are saved.
    3. Launch browser: Run npm start in a separate terminal to launch a development instance of Firefox with the extension pre-loaded. The extension will reload automatically upon changes.
    npm install
    npm run dev
    npm start
  3. Set up the development environment

    main

    To develop the Mullvad Browser Extension, ensure your environment meets the following requirements:

    • Node.js: version 24 LTS
    • NPM: version 11
    • Firefox: last version (>91.1.0)

    If you use nvm, you can run nvm use to automatically switch to the required Node and NPM versions.

  4. Test restart and persisting features

    main

    To test features like settings saved to local storage during restarts, follow these manual configuration steps:

    1. Create a new Firefox profile via about:profiles.
    2. Update the restart script in package.json with the path to your new Firefox profile.
    3. In Firefox, go to about:config and set the following preferences to true:
      • extensions.webextensions.keepStorageOnUninstall
      • extensions.webextensions.keepUuidOnUninstall
  5. Install the extension temporarily in Firefox

    main

    Since the extension is not signed by Mozilla, you must load it as a temporary add-on:

    1. Open Firefox.
    2. Navigate to about:debugging#/runtime/this-firefox in the URL bar.
    3. Click Load Temporary Add-on.
    4. Select the extension.xpi file.

    Note: The extension will be automatically unloaded when Firefox is closed.

  6. Understand the SOCKS proxy request priority logic

    main

    The extension determines which proxy to use for a network request by evaluating several layers of configuration in a specific order. If a request does not match any proxy criteria, it defaults to a direct connection.

    Proxy Selection Order:

    1. Speculative Requests: Any request with type: 'speculative' is automatically blocked ({ cancel: true }).
    2. Local/Reserved IPs: Requests to local or reserved IP addresses (e.g., localhost, private ranges, loopback) use a direct connection.
    3. Extension Connection Checks: If the request is an internal connection or DNS check originating from the extension, it inherits the proxy settings of the currently active tab to ensure consistency.
    4. Random Proxy Mode: If randomProxyMode is enabled, it overrides all other settings and uses a proxy returned by getRandomSessionProxy(domain).
    5. Domain/Subdomain Level:
      • If the domain is in excludedHosts, it uses a direct connection.
      • If a specific proxy is configured for the current domain and socksEnabled is true, that proxy is used.
      • If the current domain is a subdomain, it falls back to the parent domain's proxy settings if they are configured and enabled.
    6. Global Proxy: If no domain-specific rules apply, the globalProxy is used if globalProxyDetails.socksEnabled is true.
    7. Default: If no conditions are met, the request uses a direct connection.
  7. ESLint configuration for Mullvad Browser Extension

    main

    The project uses a flat configuration format for ESLint. It integrates recommended settings for JavaScript, TypeScript, and Vue.js, along with Prettier for formatting.

    Key environment globals provided include:

    • browser (Browser APIs)
    • node (Node.js APIs)
    • webextensions (WebExtension APIs)

    Supported ECMAScript version is latest and the source type is module.

    import vuePlugin from 'eslint-plugin-vue';
    import ts from 'typescript-eslint';
    import globals from 'globals';
    import prettier from 'eslint-config-prettier';
    import js from '@eslint/js';
    
    export default [
      js.configs.recommended,
      ...ts.configs.recommended,
      ...vuePlugin.configs['flat/recommended'],
      prettier,
      // ... configuration details
    ];
  8. Configure UnoCSS for the Mullvad Browser Extension

    main

    The project uses UnoCSS for utility-first CSS. The configuration uses the presetWind3 preset with dark mode enabled via the class strategy. The default sans-serif font family is set to 'Source Sans Pro', Helvetica, Arial, sans-serif. Additionally, certain whitespace utility classes are safelisted to ensure they are not purged during build time.

    import { defineConfig, presetWind3 } from 'unocss';
    
    export default defineConfig({
      presets: [
        presetWind3({
          dark: 'class',
        }),
      ],
      theme: {
        fontFamily: {
          sans: "'Source Sans Pro', Helvetica, Arial, sans-serif",
        },
      },
      safelist: ['whitespace-normal', 'whitespace-nowrap'],
    });
  9. Reference network requests

    main

    The extension makes two external network requests:

    EndpointPurposeFrequency
    api.mullvad.netGet latest proxy serversEach time the Select proxy server location drawer is opened
    am.i.mullvad.netGet connection informationEach time the popup is started and each time the proxy connects/disconnects
  10. Reference the extension permissions

    main

    The extension uses the following permissions:

    Required Permissions:

    • management: To recommend third-party extensions.
    • privacy: To disable WebRTC and check HTTPS-Only status.
    • storage: To save user preferences.
    • search: To recommend search engines.
    • *://*.mullvad.net/*: To fetch proxy server lists and connection info.

    Optional Permissions (Required for Proxy features):

    • proxy: To configure and use Mullvad proxy servers.
    • tabs: To show proxy settings from the active tab.
    • <all_urls>: To specify proxy configurations per domain (requires request interception).
  11. Get details of the active tab

    main

    Use getActiveTabDetails to retrieve metadata about the currently active tab.

    Note: This function requires the tabs permission. If permission is not granted or the tab has no URL, it returns a default object with empty strings and false flags.

    Return Object Shape:

    • host: The hostname of the active tab.
    • protocol: The protocol of the active tab (e.g., https:).
    • isAboutPage: Boolean indicating if the protocol is about:.
    • isExtensionPage: Boolean indicating if the protocol is moz-extension:.
    import { getActiveTabDetails } from '@/helpers/tabs';
    
    const details = await getActiveTabDetails();
    console.log(details.host, details.isExtensionPage);
  12. Reload the options page

    main

    The reloadOptions function reloads the extension's options page (dist/options/index.html). If called from the popup context, it searches for the existing options tab by URL and triggers a reload on that specific tab ID.

    import { reloadOptions } from './helpers/browserExtension';
    
    // Reload the options page to apply changes
    await reloadOptions();