Skip to content

Commit

Permalink
Allow proxy to be set per domain instead of the whole browser
Browse files Browse the repository at this point in the history
This is a major refactor of the way proxy work in the extension.
Instead of a proxy config being used for the whole browser,
each requests are intercepted and can use a specific proxy config
based on arbitrary rules.

The use of the pageAction is removed, because it is non-standard and will eventually be removed by Firefox.

Finally, the interface has been adapted and improved.
  • Loading branch information
ruihildt committed Feb 19, 2024
1 parent dfb25e3 commit de538a7
Show file tree
Hide file tree
Showing 61 changed files with 1,137 additions and 738 deletions.
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"recommendations": [
"johnsoncodehk.volar",
"Vue.volar",
"dbaeumer.vscode-eslint",
"voorjaar.windicss-intellisense",
"csstools.postcss"
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ Mullvad Browser Extension requires the following permissions:
- `proxy` to configure and use Mullvad proxy servers
- `storage` to save preferences
- `search` to recommend other search engines
- `tabs` to be able to show proxy settings based on the active tab
- `*://*.mullvad.net/*` to get proxy servers list and display your connection information (See
`Network requests` for details)
- `<all_urls>` to have granular proxy settings

_Permissions are automatically accepted when testing the extension._

Expand Down
7 changes: 0 additions & 7 deletions extension/assets/route.svg

This file was deleted.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mullvad-browser-extension",
"displayName": "Mullvad Browser Extension",
"version": "0.8.5",
"version": "0.9.0",
"description": "Improve your Mullvad VPN experience, in your browser.",
"private": true,
"engines": {
Expand All @@ -22,7 +22,7 @@
"pack:xpi": "cross-env WEB_EXT_ARTIFACTS_DIR=./ web-ext build --source-dir ./extension --filename mullvad-browser-extension-$npm_package_version.xpi --overwrite-dest",
"start:chromium": "web-ext run --source-dir ./extension --target=chromium",
"start": "web-ext run --source-dir ./extension --target=firefox-desktop --start-url=about:debugging#/runtime/this-firefox",
"restart": "web-ext run --firefox-profile ~/.cache/mozilla/firefox/md0hl4g1.MBE-Testing-Profile --keep-profile-changes --source-dir ./extension --target=firefox-desktop --start-url=about:debugging#/runtime/this-firefox",
"restart": "web-ext run --firefox-profile ~/.mozilla/firefox/md0hl4g1.MBE-Testing-Profile --keep-profile-changes --source-dir ./extension --target=firefox-desktop --start-url=about:debugging#/runtime/this-firefox",
"clear": "rimraf extension/dist extension/manifest.json extension/README.md extension/LICENSE.md mullvad-browser-extension* key.pem",
"lint": "npm run eslint && npm run lint:style",
"eslint": "eslint . --ext=.ts,.js,.vue",
Expand Down
19 changes: 7 additions & 12 deletions scripts/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import { r, port, isDev, log } from './utils';
* Stub index.html to use Vite in development
*/
async function stubIndexHtml() {
const views = [
'popup',
'background',
];
const views = ['popup', 'background'];

for (const view of views) {
await fs.ensureDir(r(`extension/dist/${view}`));
Expand All @@ -32,12 +29,10 @@ writeManifest();

if (isDev) {
stubIndexHtml();
chokidar.watch(r('src/**/*.html'))
.on('change', () => {
stubIndexHtml();
});
chokidar.watch([r('src/manifest.ts'), r('package.json')])
.on('change', () => {
writeManifest();
});
chokidar.watch(r('src/**/*.html')).on('change', () => {
stubIndexHtml();
});
chokidar.watch([r('src/manifest.ts'), r('package.json')]).on('change', () => {
writeManifest();
});
}
15 changes: 6 additions & 9 deletions src/background/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { onMessage } from 'webext-bridge/background';

import { addExtListeners } from '@/helpers/extensions';
import { initPageAction, updateTabs } from '@/helpers/pageAction';
import { initBrowserAction } from '@/helpers/browserAction';
import { initProxyRequests } from '@/helpers/socksProxy';

// only on dev mode
if (import.meta.hot) {
Expand All @@ -12,10 +11,8 @@ if (import.meta.hot) {
// Add listeners on extension actions
addExtListeners();

// Update pageAction in tabs and add listeners
initPageAction();
// Update browserAction for tabs and add listeners
initBrowserAction();

// Add message listeners
onMessage('update-socks', () => {
updateTabs();
});
// Add listener for proxy requests
initProxyRequests();
39 changes: 20 additions & 19 deletions src/components/ConnectionDetails/ConnectionDetails.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
<script lang="ts" setup>
import { computed, inject } from 'vue';
import { inject } from 'vue';
import ConnectionLocation from '@/components/ConnectionLocation/ConnectionLocation.vue';
import AdvancedDns from '@/components/ConnectionDetails/AdvancedDns.vue';
import AdvancedInfo from '@/components/ConnectionDetails/AdvancedInfo.vue';
import AdvancedWebRTC from '@/components/ConnectionDetails/AdvancedWebTRC.vue';
import Button from '@/components/Buttons/Button.vue';
import ConnectionLocation from '@/components/ConnectionLocation/ConnectionLocation.vue';
import IconLabel from '@/components/IconLabel.vue';
import ProxyDetails from '@/components/ProxyDetails/ProxyDetails.vue';
import UsingMullvadConnectionStatus from '@/components/ConnectionStatus/UsingMullvadConnectionStatus.vue';
import DnsLeakStatus from '@/components/ConnectionStatus/DnsLeakStatus.vue';
import { ConnectionKey, defaultConnection } from '@/composables/useConnection';
import useSocksProxy from '@/composables/useSocksProxy';
const { globalProxyEnabled } = useSocksProxy();
const { isLoading, isError, connection } = inject(ConnectionKey, defaultConnection);
const connected = computed(() => connection.value.isMullvad);
</script>

<template>
<div class="p-2 pt-0">
<IconLabel
v-if="!connected && !isLoading"
text="Not using Mullvad"
type="info"
class="my-2 text-lg"
/>
<div v-if="isLoading || isError">
<p class="mb-2">
<IconLabel v-if="isLoading" text="Checking connection" type="spinner" />
<IconLabel v-if="isError" text="Couldn't get connection details" type="warning" />
</p>

<p class="text-xl mb-2">
<IconLabel v-if="isLoading" text="Checking connection" type="spinner" />
<IconLabel v-else-if="isError" text="Couldn't get connection details" type="warning" />
<ConnectionLocation v-else />
</p>
<div v-if="globalProxyEnabled">
<p>Either disconnect the proxy for all websites or connect to Mullvad VPN.</p>
<router-link to="/proxy">
<Button color="info" class="mt-2">Review proxy settings</Button>
</router-link>
</div>
</div>

<div v-if="!isLoading && !isError">
<div v-if="connected" class="my-2">
<div v-else>
<ConnectionLocation />
<div v-if="connection.isMullvad" class="my-2">
<UsingMullvadConnectionStatus class="text-lg" />
<AdvancedInfo :disabled="isLoading" />

Expand Down Expand Up @@ -62,7 +65,5 @@ const connected = computed(() => connection.value.isMullvad);
</div>
</div>
</div>

<ProxyDetails />
</div>
</template>
1 change: 0 additions & 1 deletion src/components/ConnectionDetails/LocationDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { NDrawer, NDrawerContent } from 'naive-ui';
import Location from '@/components/Location.vue';
import useLocations from '@/composables/useLocations';
const { showLocations } = useLocations();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
<script lang="ts" setup>
import { computed, inject } from 'vue';
import IconLabel from '@/components/IconLabel.vue';
import { ConnectionKey, defaultConnection } from '@/composables/useConnection';
const { connection } = inject(ConnectionKey, defaultConnection);
const protocol = computed(() => connection.value.protocol);
const isUsingProxy = computed(() => protocol?.value?.startsWith('SOCKS') ?? false);
const isUsingProxy = computed(() => connection.value.protocol?.startsWith('SOCKS') ?? false);
const connectionStatus = computed(() =>
isUsingProxy.value ? 'Using Mullvad VPN (via proxy)' : 'Using Mullvad VPN',
);
Expand Down
39 changes: 39 additions & 0 deletions src/components/Headers/HomeHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts" setup>
import { NIcon } from 'naive-ui';
import FeCog from '@/components/Icons/FeCog.vue';
import FeGlobe from '@/components/Icons/FeGlobe.vue';
import TaRoute from '@/components/Icons/TaRoute.vue';
</script>

<template>
<div class="flex">
<div class="grid grid-cols-2 flex-1">
<div class="flex flex-row items-center justify-center p-2 text-white">
<n-icon size="20">
<FeGlobe />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Status</h1>
</div>

<router-link
to="/proxy"
class="flex flex-row items-center justify-center p-2 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<TaRoute />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Proxy</h1>
</router-link>
</div>

<router-link
to="/settings"
class="flex flex-row items-center justify-center px-4 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<FeCog />
</n-icon>
</router-link>
</div>
</template>
File renamed without changes.
39 changes: 39 additions & 0 deletions src/components/Headers/ProxyHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts" setup>
import { NIcon } from 'naive-ui';
import FeCog from '@/components/Icons/FeCog.vue';
import FeGlobe from '@/components/Icons/FeGlobe.vue';
import TaRoute from '@/components/Icons/TaRoute.vue';
</script>

<template>
<div class="flex">
<div class="grid grid-cols-2 flex-1">
<router-link
to="/"
class="flex flex-row items-center justify-center p-2 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<FeGlobe />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Status</h1>
</router-link>

<div class="flex flex-row items-center justify-center p-2 text-white">
<n-icon size="20">
<TaRoute />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Proxy</h1>
</div>
</div>

<router-link
to="/settings"
class="flex flex-row items-center justify-center px-4 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<FeCog />
</n-icon>
</router-link>
</div>
</template>
39 changes: 39 additions & 0 deletions src/components/Headers/SettingsHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts" setup>
import { NIcon } from 'naive-ui';
import FeCog from '@/components/Icons/FeCog.vue';
import FeGlobe from '@/components/Icons/FeGlobe.vue';
import TaRoute from '@/components/Icons/TaRoute.vue';
</script>

<template>
<div class="flex">
<div class="grid grid-cols-2 flex-1">
<router-link
to="/"
class="flex flex-row items-center justify-center p-2 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<FeGlobe />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Status</h1>
</router-link>

<router-link
to="/proxy"
class="flex flex-row items-center justify-center p-2 hover:text-white bg-[var(--blue)]"
>
<n-icon size="20">
<TaRoute />
</n-icon>
<h1 class="text-xl font-semibold pl-2">Proxy</h1>
</router-link>
</div>

<div class="flex flex-row items-center justify-center px-4 text-white">
<n-icon size="20">
<FeCog />
</n-icon>
</div>
</div>
</template>
18 changes: 7 additions & 11 deletions src/components/IconLabel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import FeDrop from '@/components/Icons/FeDrop.vue';
export type IconType = 'warning' | 'success' | 'info' | 'spinner' | 'leak' | 'check';
defineProps<{ text: string; type: IconType }>();
defineProps<{ text?: string; type: IconType }>();
</script>

<template>
<span>
<div class="flex items-center">
<n-icon class="mr-2" size="25">
<FeCheckCircle v-if="type === 'success'" class="text-success" />
<FeCheck v-if="type === 'check'" class="text-success" />
Expand All @@ -24,13 +24,9 @@ defineProps<{ text: string; type: IconType }>();
<FeDrop v-if="type === 'leak'" class="text-error" />
</n-icon>

{{ text }}
</span>
<span v-if="text">{{ text }}</span>
<span v-else>
<slot></slot>
</span>
</div>
</template>

<style scoped>
span {
display: flex;
align-items: center;
}
</style>
18 changes: 18 additions & 0 deletions src/components/Icons/FeGlobe.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<svg
width="1em"
height="1em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="2" y1="12" x2="22" y2="12"></line>
<path
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"
></path>
</svg>
</template>
Loading

0 comments on commit de538a7

Please sign in to comment.