diff --git a/package.json b/package.json
index 778c6f8c..3d6e777f 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"typedoc-default-themes": "^0.10.2"
},
"devDependencies": {
+ "@types/firefox-webext-browser": "^78.0.0",
"@types/jest": "^26.0.3",
"@types/node": "^14.0.14",
"@types/selenium-webdriver": "^4.0.9",
diff --git a/src/background.ts b/src/background.ts
index 19cec122..dc9b0a13 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -89,7 +89,7 @@ browser.webNavigation.onDOMContentLoaded.addListener(() => {
// Prevent Tridactyl from being updated while it is running in the hope of fixing #290
browser.runtime.onUpdateAvailable.addListener(_ => undefined)
-browser.runtime.onStartup.addListener(_ => {
+browser.runtime.onStartup.addListener(() => {
config.getAsync("autocmds", "TriStart").then(aucmds => {
const hosts = Object.keys(aucmds)
// If there's only one rule and it's "all", no need to check the hostname
diff --git a/src/completions/History.ts b/src/completions/History.ts
index a1ef6d25..b6e00837 100644
--- a/src/completions/History.ts
+++ b/src/completions/History.ts
@@ -17,14 +17,12 @@ class HistoryCompletionOption extends Completions.CompletionOptionHTML
// Create HTMLElement
this.html = html`
- ${"".padEnd(2)} |
- ${page.title} |
-
- ${page.url}
- |
-
`
+ ${"".padEnd(2)} |
+ ${page.title} |
+
+ ${page.url}
+ |
+ `
}
}
@@ -78,8 +76,13 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
options += options ? " " : ""
// Options are pre-trimmed to the right length.
- this.options = (await this.scoreOptions(query, config.get("historyresults"))).map(
- page => new HistoryCompletionOption(options + page.url, page as any),
+ // Typescript throws an error here - further investigation is probably warranted
+ this.options = ((await this.scoreOptions(
+ query,
+ config.get("historyresults"),
+ )) as any).map(
+ page =>
+ new HistoryCompletionOption(options + page.url, page),
)
// Deselect any selected, but remember what they were.
@@ -88,9 +91,13 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
// Set initial state to normal, unless the option was selected a moment
// ago, then reselect it so that users don't lose their selections.
- this.options.forEach(option => option.state = "normal")
+ this.options.forEach(option => (option.state = "normal"))
for (const option of this.options) {
- if (lastFocused !== undefined && lastFocused.value === option.value && prevStr.length <= exstr.length) {
+ if (
+ lastFocused !== undefined &&
+ lastFocused.value === option.value &&
+ prevStr.length <= exstr.length
+ ) {
this.select(option)
break
}
@@ -103,7 +110,6 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
// eslint-disable-next-line @typescript-eslint/no-empty-function
updateChain() {}
-
private async scoreOptions(query: string, n: number) {
if (!query || config.get("historyresults") === 0) {
return (await providers.getTopSites()).slice(0, n)
diff --git a/src/completions/Window.ts b/src/completions/Window.ts
index 9cc3f498..1abd6682 100644
--- a/src/completions/Window.ts
+++ b/src/completions/Window.ts
@@ -5,7 +5,7 @@ class WindowCompletionOption extends Completions.CompletionOptionHTML
implements Completions.CompletionOptionFuse {
public fuseKeys = []
- constructor(win) {
+ constructor(win: browser.windows.Window) {
super()
this.value = win.id
this.fuseKeys.push(`${win.title}`)
diff --git a/src/lib/autocontainers.ts b/src/lib/autocontainers.ts
index 7b6aa9ce..1e274929 100644
--- a/src/lib/autocontainers.ts
+++ b/src/lib/autocontainers.ts
@@ -35,32 +35,26 @@ interface ICancelledRequest {
}
interface IAutoContain {
- autoContain(details: browser.webRequest.IDetails): any
- cancelEarly(
- tab: browser.tabs.Tab,
- details: browser.webRequest.IDetails,
- ): boolean
- cancelRequest(
- tab: browser.tabs.Tab,
- details: browser.webRequest.IDetails,
- ): void
+ autoContain(details): any
+ cancelEarly(tab: browser.tabs.Tab, details): boolean
+ cancelRequest(tab: browser.tabs.Tab, details): void
clearCancelledRequests(tabId: number): void
getCancelledRequest(tabId: number): ICancelledRequest
- completedRequestListener(details: browser.webRequest.IDetails): void
+ completedRequestListener(details): void
autocontainConfigured(): boolean
getAuconForUrl(url: string): Promise
- getAuconForDetails(details: browser.webRequest.IDetails): Promise
+ getAuconForDetails(details): Promise
}
export class AutoContain implements IAutoContain {
private cancelledRequests: ICancelledRequest[] = []
private lastCreatedTab = null
- tabCreatedListener = (tab) => {
+ tabCreatedListener = tab => {
this.lastCreatedTab = tab
}
- completedRequestListener = (details: browser.webRequest.IDetails) => {
+ completedRequestListener = details => {
if (this.getCancelledRequest(details.tabId)) {
this.clearCancelledRequests(details.tabId)
}
@@ -73,12 +67,13 @@ export class AutoContain implements IAutoContain {
}
autoContain = async (
- details: browser.webRequest.IDetails,
+ details,
): Promise => {
if (!this.autocontainConfigured()) return { cancel: false }
// Only handle in strict mode.
- if (Config.get("autocontainmode") === "relaxed") return { cancel: false }
+ if (Config.get("autocontainmode") === "relaxed")
+ return { cancel: false }
// Only handle http requests.
if (details.url.search("^https?://") < 0) return { cancel: false }
@@ -87,13 +82,15 @@ export class AutoContain implements IAutoContain {
if (details.tabId === -1) return { cancel: false }
// Do all of our async lookups in parallel.
- const [tab, otherExtensionHasPriority, cookieStoreId] = await Promise.all(
- [
- browser.tabs.get(details.tabId),
- this.checkOtherExtensionsHavePriority(details),
- this.getAuconForDetails(details),
- ],
- )
+ const [
+ tab,
+ otherExtensionHasPriority,
+ cookieStoreId,
+ ] = await Promise.all([
+ browser.tabs.get(details.tabId),
+ this.checkOtherExtensionsHavePriority(details),
+ this.getAuconForDetails(details),
+ ])
// If any other extensions claim this request, we'll ignore it and let them handle it.
if (otherExtensionHasPriority) return { cancel: false }
@@ -108,22 +105,30 @@ export class AutoContain implements IAutoContain {
// If this navigation created a tab, we cancel and then kill
// the newly-created tab after opening.
- const removeTab = this.lastCreatedTab && (this.lastCreatedTab.id === tab.id)
+ const removeTab =
+ this.lastCreatedTab && this.lastCreatedTab.id === tab.id
// Figure out which tab should be the parent of the tab we'll
// be creating in the selected container.
const openerTabId = removeTab ? tab.openerTabId : tab.id
- logger.debug("in tab %o and with details %o, reopening from container %o to container %o",
- tab, details, tab.cookieStoreId, cookieStoreId)
- browser.tabs.create({
+ logger.debug(
+ "in tab %o and with details %o, reopening from container %o to container %o",
+ tab,
+ details,
+ tab.cookieStoreId,
+ cookieStoreId,
+ )
+ browser.tabs
+ .create({
url: details.url,
cookieStoreId,
active: tab.active,
windowId: tab.windowId,
index: tab.index + 1,
openerTabId,
- }).then(result => {
+ })
+ .then(result => {
logger.debug("Autocontainer created tab %o", result)
})
@@ -136,10 +141,7 @@ export class AutoContain implements IAutoContain {
}
// Handles the requests after the initial checks made in this.autoContain.
- cancelEarly = (
- tab: browser.tabs.Tab,
- details: browser.webRequest.IDetails,
- ): boolean => {
+ cancelEarly = (tab: browser.tabs.Tab, details): boolean => {
if (!this.cancelledRequests[tab.id]) {
this.cancelRequest(tab, details)
} else {
@@ -160,10 +162,7 @@ export class AutoContain implements IAutoContain {
return false
}
- cancelRequest = (
- tab: browser.tabs.Tab,
- details: browser.webRequest.IDetails,
- ): void => {
+ cancelRequest = (tab: browser.tabs.Tab, details): void => {
this.cancelledRequests[tab.id] = {
requestIds: {
[details.requestId]: true,
@@ -180,7 +179,8 @@ export class AutoContain implements IAutoContain {
}, 2000)
}
- getCancelledRequest = (tabId: number): ICancelledRequest => this.cancelledRequests[tabId]
+ getCancelledRequest = (tabId: number): ICancelledRequest =>
+ this.cancelledRequests[tabId]
// Clear the cancelled requests.
clearCancelledRequests = (tabId: number): void => {
@@ -191,9 +191,7 @@ export class AutoContain implements IAutoContain {
// Checks to see if there are any other container-related extensions and avoids getting into
// fights with them.
- checkOtherExtensionsHavePriority = async (
- details: browser.webRequest.IDetails,
- ): Promise => {
+ checkOtherExtensionsHavePriority = async (details): Promise => {
// The checks for each extension can be done in parallel.
const priorities = await Promise.all([
this.checkMACPriority(details),
@@ -202,18 +200,14 @@ export class AutoContain implements IAutoContain {
return priorities.some(t => t)
}
- checkMACPriority = async (
- details: browser.webRequest.IDetails,
- ): Promise => {
+ checkMACPriority = async (details): Promise => {
if (
!ExtensionInfo.getExtensionEnabled(
ExtensionInfo.KNOWN_EXTENSIONS.multi_account_containers,
)
) {
// It can't take priority if it's not enabled.
- logger.debug(
- "multi-account containers extension does not exist",
- )
+ logger.debug("multi-account containers extension does not exist")
return false
}
@@ -229,8 +223,10 @@ export class AutoContain implements IAutoContain {
},
)
.catch(error => {
- logger.warning("failed to communicate with multi-account containers extension: %o",
- error)
+ logger.warning(
+ "failed to communicate with multi-account containers extension: %o",
+ error,
+ )
return false
})
@@ -247,18 +243,14 @@ export class AutoContain implements IAutoContain {
}
}
- checkTempContainersPriority = async (
- details: browser.webRequest.IDetails,
- ): Promise => {
+ checkTempContainersPriority = async (details): Promise => {
if (
!ExtensionInfo.getExtensionEnabled(
ExtensionInfo.KNOWN_EXTENSIONS.temp_containers,
)
) {
// It can't take priority if it's not enabled.
- logger.debug(
- "temporary containers extension does not exist",
- )
+ logger.debug("temporary containers extension does not exist")
return false
}
@@ -281,9 +273,7 @@ export class AutoContain implements IAutoContain {
getAuconForUrl = async (url: string): Promise => {
const aucons = Config.get("autocontain")
const ausites = Object.keys(aucons)
- const aukeyarr = ausites.filter(
- e => url.search(e) >= 0,
- )
+ const aukeyarr = ausites.filter(e => url.search(e) >= 0)
if (aukeyarr.length > 1) {
logger.error(
"Too many autocontain directives match this url. Not containing.",
@@ -307,7 +297,6 @@ export class AutoContain implements IAutoContain {
}
// Parses autocontain directives and returns valid cookieStoreIds or errors.
- getAuconForDetails = async (
- details: browser.webRequest.IDetails,
- ): Promise => this.getAuconForUrl(details.url)
+ getAuconForDetails = async (details): Promise =>
+ this.getAuconForUrl(details.url)
}
diff --git a/src/lib/containers.ts b/src/lib/containers.ts
index 9bfc170e..e54494ca 100644
--- a/src/lib/containers.ts
+++ b/src/lib/containers.ts
@@ -84,8 +84,8 @@ export function update(
containerId: string,
updateObj: {
name: string
- color: browser.contextualIdentities.IdentityColor
- icon: browser.contextualIdentities.IdentityIcon
+ color: string
+ icon: string
},
) {
const { name, color, icon } = updateObj
@@ -147,8 +147,8 @@ export async function exists(cname: string): Promise {
export function fromString(name: string, color: string, icon: string, id = "") {
return {
name,
- color: color as browser.contextualIdentities.IdentityColor,
- icon: icon as browser.contextualIdentities.IdentityIcon,
+ color,
+ icon,
cookieStoreId: id,
} as browser.contextualIdentities.ContextualIdentity // rules are made to be broken
}
diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts
index 576b5385..893b2945 100644
--- a/src/lib/messaging.ts
+++ b/src/lib/messaging.ts
@@ -69,7 +69,11 @@ export function attributeCaller(obj) {
return handler
}
-interface TypedMessage {
+interface TypedMessage<
+ Root,
+ Type extends keyof Root,
+ Command extends keyof Root[Type]
+> {
type: Type
command: Command
args: Parameters
@@ -79,23 +83,80 @@ function backgroundHandler<
Root,
Type extends keyof Root,
Command extends keyof Root[Type]
- >(root: Root,
- message: TypedMessage,
- sender: browser.runtime.MessageSender,
- ): ReturnType {
+>(
+ root: Root,
+ message: TypedMessage,
+ sender: browser.runtime.MessageSender,
+): ReturnType {
return root[message.type][message.command](...message.args)
}
export function setupListener(root: Root) {
- browser.runtime.onMessage.addListener((message: any, sender: browser.runtime.MessageSender) => {
- if (message.type in root) {
- if (!(message.command in root[message.type]))
- throw new Error(`missing handler in protocol ${message.type} ${message.command}`)
- if (!Array.isArray(message.args))
- throw new Error(`wrong arguments in protocol ${message.type} ${message.command}`)
- return backgroundHandler(root, message, sender)
- }
- });
+ // What part of
+ //
+ // ```
+ // ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts
+ // ./src/lib/messaging.ts
+ // [tsl] ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts(90,43)
+ // TS2345: Argument of type '(message: any, sender: browser.runtime.MessageSender) => ReturnType' is not assignable to parameter of type '(message: any, sender: MessageSender, sendResponse: (response?: any) => void) => boolean | void | Promise'.
+ // Type 'ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType | ReturnType | ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType | ReturnType | ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'ReturnType' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'boolean | void | Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType | ReturnType | ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type 'unknown' is not assignable to type 'Promise'.
+ // Type 'ReturnType | ReturnType | ReturnType' is not assignable to type 'Promise'.
+ // Type 'ReturnType' is not assignable to type 'Promise'.
+ // Type '{}' is missing the following properties from type 'Promise': then, catch, [Symbol.toStringTag], finally
+ //
+ // ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts
+ // ./src/lib/messaging.ts
+ // [tsl] ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts(115,40)
+ // TS2558: Expected 0 type arguments, but got 2.
+ // ```
+ //
+ // don't you understand?
+ //
+ // (This is why there is an `: any => `)
+ browser.runtime.onMessage.addListener(
+ (message: any, sender: browser.runtime.MessageSender): any => {
+ if (message.type in root) {
+ if (!(message.command in root[message.type]))
+ throw new Error(
+ `missing handler in protocol ${message.type} ${message.command}`,
+ )
+ if (!Array.isArray(message.args))
+ throw new Error(
+ `wrong arguments in protocol ${message.type} ${message.command}`,
+ )
+ return backgroundHandler(root, message, sender)
+ }
+ },
+ )
}
type StripPromise = T extends Promise ? U : T
@@ -105,14 +166,16 @@ export async function message<
Type extends keyof Messages.Background,
Command extends keyof Messages.Background[Type],
F extends((...args: any) => any) & Messages.Background[Type][Command]
- >(type: Type, command: Command, ...args: Parameters) {
+>(type: Type, command: Command, ...args: Parameters) {
const message: TypedMessage = {
type,
command,
- args
+ args,
}
- return browser.runtime.sendMessage>>(message)
+ // Typescript didn't like this
+ // return browser.runtime.sendMessage>>(message)
+ return browser.runtime.sendMessage(message)
}
/** Message the active tab of the currentWindow */
@@ -124,7 +187,12 @@ export async function messageActiveTab(
return messageTab(await activeTabId(), type, command, args)
}
-export async function messageTab(tabId, type: TabMessageType, command, args?): Promise {
+export async function messageTab(
+ tabId,
+ type: TabMessageType,
+ command,
+ args?,
+): Promise {
const message: Message = {
type,
command,
@@ -154,7 +222,10 @@ export async function messageAllTabs(
responses.push(await messageTab(tab.id, type, command, args))
} catch (e) {
// Skip errors caused by tabs we aren't running on
- if (e.message != "Could not establish connection. Receiving end does not exist.") {
+ if (
+ e.message !=
+ "Could not establish connection. Receiving end does not exist."
+ ) {
logger.error(e)
}
}
diff --git a/src/tridactyl.d.ts b/src/tridactyl.d.ts
index 3eb066fd..6607ecf5 100644
--- a/src/tridactyl.d.ts
+++ b/src/tridactyl.d.ts
@@ -186,29 +186,6 @@ declare namespace browser.management {
const onUninstalled: WebExtEvent<(info: IExtensionInfo) => void>
}
-/** An interface for the additional object that's supplied in the BlockingResponse callback.
-
- Details here:
- https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/onBeforeRequest#details
-
-*/
-declare namespace browser.webRequest {
- interface IDetails {
- // frameAncestors: any[]
- frameId: number
- method: string
- originUrl: string
- parentFrameId: number
- proxyInfo?: any
- requestBody?: any
- requestId: string
- tabId: number
- timeStamp: number
- type: ResourceType
- url: string
- }
-}
-
// html-tagged-template.js
declare function html(
strings: TemplateStringsArray,
diff --git a/tsconfig.json b/tsconfig.json
index 98d43549..965e9dd1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,13 +7,13 @@
"sourceMap": true,
"target": "es2017",
"lib": ["es2017","es2019.array", "es2018.promise", "dom", "dom.iterable"],
- "types": ["web-ext-types"],
"experimentalDecorators": true,
"alwaysStrict": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"baseUrl": "src/",
+ "types": ["@types/firefox-webext-browser", "web-ext-types"],
"paths": {
"@src/*": ["*"]
}
diff --git a/yarn.lock b/yarn.lock
index ffbaf6f3..6c27f7a4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -672,6 +672,11 @@
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
+"@types/firefox-webext-browser@^78.0.0":
+ version "78.0.0"
+ resolved "https://registry.yarnpkg.com/@types/firefox-webext-browser/-/firefox-webext-browser-78.0.0.tgz#9f175355beb3824dce8d5811e59585fba84dca6b"
+ integrity sha512-ExCtjncdA1ITEjEitvtjGcXslGPA/ZMxOxzMGfpLHZ6ZJAAx6itQi+ZEctgPFN6uPW4lSJalSsEC+lAz0Wkz9A==
+
"@types/graceful-fs@^4.1.2":
version "4.1.3"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f"