Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Build

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
name: Build Chrome & Firefox
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Type check
run: yarn compile

- name: Build Chrome (MV3)
run: yarn build
env:
VITE_VPN_SERVER_ADDRESS: ${{ secrets.VITE_VPN_SERVER_ADDRESS }}
VITE_VPN_SERVER_PORT: ${{ secrets.VITE_VPN_SERVER_PORT }}
VITE_VPN_USERNAME: ${{ secrets.VITE_VPN_USERNAME }}
VITE_VPN_PASSWORD: ${{ secrets.VITE_VPN_PASSWORD }}
VITE_VPN_API_URL: ${{ secrets.VITE_VPN_API_URL }}
VITE_VPN_API_URL_STAGING: ${{ secrets.VITE_VPN_API_URL_STAGING }}
VITE_VPN_API_URL_DEVELOPMENT: ${{ secrets.VITE_VPN_API_URL_DEVELOPMENT }}
VITE_IP_API_URL: ${{ secrets.VITE_IP_API_URL }}
VITE_AUTH_HOST_URL: ${{ secrets.VITE_AUTH_HOST_URL }}
VITE_AUTH_HOST_URL_STAGING: ${{ secrets.VITE_AUTH_HOST_URL_STAGING }}
VITE_AUTH_HOST_URL_DEVELOPMENT: ${{ secrets.VITE_AUTH_HOST_URL_DEVELOPMENT }}
VITE_DRIVE_API_URL: ${{ secrets.VITE_DRIVE_API_URL }}
VITE_DRIVE_API_URL_STAGING: ${{ secrets.VITE_DRIVE_API_URL_STAGING }}
VITE_DRIVE_API_URL_DEVELOPMENT: ${{ secrets.VITE_DRIVE_API_URL_DEVELOPMENT }}

- name: Build Firefox (MV2)
run: yarn build:firefox
env:
VITE_VPN_SERVER_ADDRESS: ${{ secrets.VITE_VPN_SERVER_ADDRESS }}
VITE_VPN_SERVER_PORT: ${{ secrets.VITE_VPN_SERVER_PORT }}
VITE_VPN_USERNAME: ${{ secrets.VITE_VPN_USERNAME }}
VITE_VPN_PASSWORD: ${{ secrets.VITE_VPN_PASSWORD }}
VITE_VPN_API_URL: ${{ secrets.VITE_VPN_API_URL }}
VITE_VPN_API_URL_STAGING: ${{ secrets.VITE_VPN_API_URL_STAGING }}
VITE_VPN_API_URL_DEVELOPMENT: ${{ secrets.VITE_VPN_API_URL_DEVELOPMENT }}
VITE_IP_API_URL: ${{ secrets.VITE_IP_API_URL }}
VITE_AUTH_HOST_URL: ${{ secrets.VITE_AUTH_HOST_URL }}
VITE_AUTH_HOST_URL_STAGING: ${{ secrets.VITE_AUTH_HOST_URL_STAGING }}
VITE_AUTH_HOST_URL_DEVELOPMENT: ${{ secrets.VITE_AUTH_HOST_URL_DEVELOPMENT }}
VITE_DRIVE_API_URL: ${{ secrets.VITE_DRIVE_API_URL }}
VITE_DRIVE_API_URL_STAGING: ${{ secrets.VITE_DRIVE_API_URL_STAGING }}
VITE_DRIVE_API_URL_DEVELOPMENT: ${{ secrets.VITE_DRIVE_API_URL_DEVELOPMENT }}

- name: Upload Chrome build
uses: actions/upload-artifact@v4
with:
name: chrome-mv3
path: .output/chrome-mv3/
retention-days: 7

- name: Upload Firefox build
uses: actions/upload-artifact@v4
with:
name: firefox-mv2
path: .output/firefox-mv2/
retention-days: 7
96 changes: 61 additions & 35 deletions src/entrypoints/background.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { browser } from 'wxt/browser'
import { handleUserToken } from './utils/handleUserToken'
import { clearProxySettings } from './popup/proxy.service'
import { clearProxySettings, updateProxySettings } from './popup/proxy.service'

const FOUR_DAYS_IN_MS = 4 * 24 * 60 * 60 * 1000
let interval: NodeJS.Timeout | null = null

function startInterval() {
if (interval) clearInterval(interval)
interval = setInterval(() => {
console.log('Refresh token')
handleUserToken()
}, FOUR_DAYS_IN_MS)
}

export default defineBackground(() => {
const IP_API_URL = import.meta.env.VITE_IP_API_URL

chrome.runtime.onInstalled.addListener((details) => {
browser.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
chrome.tabs.create({ url: 'https://internxt.com/vpn' })
browser.tabs.create({ url: 'https://internxt.com/vpn' })
}
})

chrome.runtime.onMessage.addListener((message, _, sendResponse) => {
browser.runtime.onMessage.addListener((message, _, sendResponse) => {
if (message === 'GET_DATA') {
fetch(`${IP_API_URL}/json`, {
method: 'GET',
Expand All @@ -30,14 +30,21 @@ export default defineBackground(() => {
.then((items) => {
const { ip, city, region, country } = items
const locationText = `${city}, ${region}, ${country}`

sendResponse({
location: locationText,
ip,
})
})
.catch(() => {
// NO OP
sendResponse(null)
})
} else if (message === 'SET_PROXY') {
updateProxySettings()
.then(() => {
sendResponse({})
})
.catch(() => {
sendResponse({})
})
} else if (message === 'RESET_PROXY') {
clearProxySettings()
Expand All @@ -55,53 +62,72 @@ export default defineBackground(() => {
const localCache = {
token: null as string | null,
connection: null as string | null,
vpnEnabled: false as boolean,
}

async function initializeLocalCache() {
const { userToken, connection } = await chrome.storage.local.get([
'userToken',
'connection',
])
const result = await browser.storage.local.get(['userToken', 'connection', 'vpnEnabled'])
const userToken = result.userToken as { token: string } | undefined
const connection = result.connection as string | undefined
console.log('INITIAL LOCAL STORAGE: ', userToken)
localCache.token = userToken?.token ?? null
localCache.connection = connection ?? null
localCache.vpnEnabled = (result.vpnEnabled as boolean) ?? false
}

startInterval()
initializeLocalCache()

chrome.storage.onChanged.addListener((changes, areaName) => {
browser.storage.onChanged.addListener((changes, areaName) => {
if (areaName === 'local') {
if (changes.userToken?.newValue) {
localCache.token = changes.userToken.newValue?.token ?? null
localCache.token = (changes.userToken.newValue as { token: string })?.token ?? null
startInterval()
}
if (changes.connection?.newValue) {
localCache.connection = changes.connection.newValue ?? null
localCache.connection = (changes.connection.newValue as string) ?? null
}
if ('vpnEnabled' in changes) {
localCache.vpnEnabled = (changes.vpnEnabled.newValue as boolean) ?? false
}
}
})

browser.webRequest.onAuthRequired.addListener(
function (details) {
if (details.isProxy) {
return {
authCredentials: {
username: localCache.connection ?? 'FR',
password: localCache.token ?? '',
},
}
}
return {}
},
{ urls: ['<all_urls>'] },
['blocking']
)
if (import.meta.env.BROWSER === 'firefox') {
const VPN_HOST = import.meta.env.VITE_VPN_SERVER_ADDRESS
const VPN_PORT = Number(import.meta.env.VITE_VPN_SERVER_PORT)
;(browser as any).proxy.onRequest.addListener(
(details: any) => {
if (details.tabId === -1 || details.originUrl?.startsWith('moz-extension://')) return { type: 'direct' }
if (!localCache.vpnEnabled) return { type: 'direct' }
return { type: 'http', host: VPN_HOST, port: VPN_PORT, username: localCache.connection ?? 'FR', password: localCache.token ?? '' }
},
{ urls: ['<all_urls>'] },
)

browser.webRequest.onErrorOccurred.addListener(
(error) => {
console.log('[AN ERROR OCURRED]:', error)
},
{ urls: ['<all_urls>'] }
)
browser.webRequest.onAuthRequired.addListener(
function (details) {
if (!details.isProxy) return {}
return { authCredentials: { username: localCache.connection ?? 'FR', password: localCache.token ?? '' } }
},
{ urls: ['<all_urls>'] },
['blocking'],
)
} else {
browser.webRequest.onAuthRequired.addListener(
function (details) {
if (details.isProxy) {
return {
authCredentials: {
username: localCache.connection ?? 'FR',
password: localCache.token ?? '',
},
}
}
return {}
},
{ urls: ['<all_urls>'] },
['blocking'],
)
}
})
29 changes: 29 additions & 0 deletions src/entrypoints/components/RestartBrowserModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { translate } from '@/constants'

interface RestartBrowserModalProps {
onClose: () => void
}

export const RestartBrowserModal = ({ onClose }: RestartBrowserModalProps) => {
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div className="bg-white rounded-xl mx-4 p-6 flex flex-col space-y-5 shadow-xl">
<div className="flex flex-col space-y-2">
<p className="text-gray-100 font-semibold text-base">
{translate('firefoxLocationModal.title')}
</p>
<p className="text-sm text-gray-60">
{translate('firefoxLocationModal.description')}
</p>
</div>
<button
onClick={onClose}
style={{ backgroundColor: 'rgb(0, 102, 255)' }}
className="w-full py-2 px-4 rounded-lg text-sm font-medium text-white transition-colors"
>
{translate('firefoxLocationModal.confirm')}
</button>
</div>
</div>
)
}
4 changes: 2 additions & 2 deletions src/entrypoints/components/StatusComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { VPN_STATUS_SWITCH } from '../constants'
import { VPN_STATUS } from '~/entrypoints/popup/App'

interface StatusComponentProps {
status: VPN_STATUS_SWITCH
status: VPN_STATUS
}

export const StatusComponent = ({ status }: StatusComponentProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { browser } from 'wxt/browser'
import { translate } from '@/constants'
import { SectionItemProps, SectionProps } from '../Dropdown'
import { DropdownItem } from './DropdownItem'
Expand All @@ -16,7 +17,7 @@ export const DropdownSection = ({
onItemClicked,
}: DropdownSectionProps) => {
const handleUpgradeButtonClicked = () => {
chrome.tabs.create({ url: 'https://internxt.com/pricing' })
browser.tabs.create({ url: 'https://internxt.com/pricing' })
}
return (
<div
Expand Down
20 changes: 4 additions & 16 deletions src/entrypoints/content/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { browser } from 'wxt/browser'
import { getAppUrl } from '../utils/getUrl'

const POST_MESSAGE_SOURCE = 'drive-extension'
Expand Down Expand Up @@ -51,23 +52,10 @@ export default defineContentScript({
if (eventMessage === MESSAGES.USER_TOKEN) {
const token = event.data.payload.token

chrome.storage.local.set(
{
userToken: {
token,
type: 'user',
},
},
() => {
console.log(
'The user has been authenticated in the VPN extension',
)
},
)
browser.storage.local.set({ userToken: { token, type: 'user' } })
} else if (eventMessage === MESSAGES.USER_LOG_OUT) {
chrome.storage.local.clear(async () => {
await chrome.runtime.sendMessage('RESET_PROXY')
console.log('The user has been logged out from the VPN extension')
browser.storage.local.clear().then(async () => {
await browser.runtime.sendMessage('RESET_PROXY')
})
}
}
Expand Down
Loading
Loading