`
+})
+
+// Start the application and render it to the given querySelector
+app.mount('#root')
+
+// Set page title and header translation
+document.title = i18n.getMessage('request_permissions_page_title')
diff --git a/add-on/src/lib/constants.js b/add-on/src/lib/constants.js
index ef2f7c61a..179f80943 100644
--- a/add-on/src/lib/constants.js
+++ b/add-on/src/lib/constants.js
@@ -4,4 +4,5 @@
export const welcomePage = '/dist/landing-pages/welcome/index.html'
export const optionsPage = '/dist/options/options.html'
export const recoveryPagePath = '/dist/recovery/recovery.html'
+export const requestRequiredPermissionsPage = '/dist/landing-pages/permissions/request.html'
export const tickMs = 250 // no CPU spike, but still responsive enough
diff --git a/add-on/src/lib/ipfs-request.js b/add-on/src/lib/ipfs-request.js
index 2a400d1f7..8ae67d078 100644
--- a/add-on/src/lib/ipfs-request.js
+++ b/add-on/src/lib/ipfs-request.js
@@ -240,7 +240,7 @@ export function createRequestModifier (getState, dnslinkResolver, ipfsPathValida
const { requestHeaders } = request
if (isCompanionRequest(request)) {
- // '403 - Forbidden' fix for Chrome and Firefox
+ // '403 - Forbidden' fix for browsers that support blocking webRequest API (e.g. Firefox)
// --------------------------------------------
// We update "Origin: *-extension://" HTTP headers in requests made to API
// by js-kubo-rpc-client running in the background page of browser
diff --git a/add-on/src/lib/on-installed.js b/add-on/src/lib/on-installed.js
index 11dae33fe..b40d88a35 100644
--- a/add-on/src/lib/on-installed.js
+++ b/add-on/src/lib/on-installed.js
@@ -3,7 +3,7 @@
import browser from 'webextension-polyfill'
import debug from 'debug'
-import { welcomePage } from './constants.js'
+import { requestRequiredPermissionsPage, welcomePage } from './constants.js'
import { brave, braveNodeType } from './ipfs-client/brave.js'
const { version } = browser.runtime.getManifest()
@@ -21,6 +21,15 @@ export async function onInstalled (details) {
export async function runPendingOnInstallTasks () {
const { onInstallTasks, displayReleaseNotes } = await browser.storage.local.get(['onInstallTasks', 'displayReleaseNotes'])
await browser.storage.local.remove('onInstallTasks')
+ // this is needed because `permissions.request` cannot be called from a script. If that happens the browser will
+ // throws: Error: permissions.request may only be called from a user input handler
+ // To avoid this, we open a new tab with the permissions page and ask the user to grant the permissions.
+ // That makes the request valid and allows us to gain access to the permissions.
+ if (!(await browser.permissions.contains({ origins: [''] }))) {
+ return browser.tabs.create({
+ url: requestRequiredPermissionsPage
+ })
+ }
switch (onInstallTasks) {
case 'onFirstInstall':
await useNativeNodeIfFeasible(browser)
diff --git a/add-on/src/recovery/recovery.js b/add-on/src/recovery/recovery.js
index 1cc3447e3..7339e7d41 100644
--- a/add-on/src/recovery/recovery.js
+++ b/add-on/src/recovery/recovery.js
@@ -19,7 +19,7 @@ const optionsPageLink = html` {
- browser.runtime.sendMessage({ telemetry: { trackView: 'recovery' } })
+ runtime.sendMessage({ telemetry: { trackView: 'recovery' } })
const { hash } = window.location
const { href: publicURI } = new URL(decodeURIComponent(hash.slice(1)))
diff --git a/webpack.config.js b/webpack.config.js
index 82fa0f5ec..37ee165b0 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -190,7 +190,8 @@ const uiConfig = merge(commonConfig, {
importPage: './add-on/src/popup/quick-import.js',
optionsPage: './add-on/src/options/options.js',
recoveryPage: './add-on/src/recovery/recovery.js',
- welcomePage: './add-on/src/landing-pages/welcome/index.js'
+ welcomePage: './add-on/src/landing-pages/welcome/index.js',
+ requestPermissionsPage: './add-on/src/landing-pages/permissions/request.js',
},
optimization: {
splitChunks: {