diff --git a/_locales/en/messages.json b/_locales/en/messages.json index a766cd2..7bdb5cf 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -418,6 +418,10 @@ } } }, + "Extension_list": { + "message": "Intercept download of files with those extensions (space/colon separated)", + "description": "Header for settings section." + }, "Debugging_Output": { "message": "Debugging Output", "description": "Header for settings section." diff --git a/src/background/backgroundState.ts b/src/background/backgroundState.ts index 2e6eecb..a586c77 100644 --- a/src/background/backgroundState.ts +++ b/src/background/backgroundState.ts @@ -11,6 +11,7 @@ export interface BackgroundState { notificationInterval: number | undefined; showNonErrorNotifications: boolean; isInitializingExtension: boolean; + interceptExtensions: string; } const state: BackgroundState = { @@ -21,6 +22,7 @@ const state: BackgroundState = { notificationInterval: undefined, showNonErrorNotifications: true, isInitializingExtension: true, + interceptExtensions: '', }; export function getMutableStateSingleton() { diff --git a/src/background/downloadInterceptor.ts b/src/background/downloadInterceptor.ts new file mode 100644 index 0000000..c3f7413 --- /dev/null +++ b/src/background/downloadInterceptor.ts @@ -0,0 +1,30 @@ +import { getMutableStateSingleton } from "./backgroundState"; +import { addDownloadTasksAndPoll } from "./actions"; + +export function initializeDownloadInterceptor() { + downloads.onCreated.addListener((itm)=>{ + + const state = getMutableStateSingleton(); + var ext, ext_list; + + ext_list = state.interceptExtensions.split(' '); + + // has no extension + if (itm.filename.index('.') < 0) return; + + ext = itm.filename.split('.').pop().toLowerCase(); + + // extension not in the list + if (ext_list.indexOf(ext) < 0) return; + + // stop download and add NAS task + downloads.cancel(itm.id); + addDownloadTasksAndPoll( + state.api, + state.pollRequestManager, + state.showNonErrorNotifications, + [itm.url], + ); + + }); +} diff --git a/src/background/index.ts b/src/background/index.ts index 7638916..bdbaea6 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -4,9 +4,11 @@ import { saveLastSevereError } from "../common/errorHandlers"; import { onStoredStateChange as onStoredStateChangeListener } from "./onStateChange"; import { initializeContextMenus } from "./contextMenus"; import { initializeMessageHandler } from "./messages"; +import { initializeDownloadInterceptor } from "./downloadInterceptor"; initializeContextMenus(); initializeMessageHandler(); +initializeDownloadInterceptor(); maybeMigrateState() .then(() => { diff --git a/src/background/onStateChange.ts b/src/background/onStateChange.ts index 6dd1dd9..b048f61 100644 --- a/src/background/onStateChange.ts +++ b/src/background/onStateChange.ts @@ -133,5 +133,7 @@ export function onStoredStateChange(storedState: State) { backgroundState.finishedTaskIds = new Set(updatedFinishedTaskIds); } + backgroundState.interceptExtensions = storedState.settings.interceptExtensions; + backgroundState.isInitializingExtension = false; } diff --git a/src/common/state/listen.ts b/src/common/state/listen.ts index 059a92f..0266400 100644 --- a/src/common/state/listen.ts +++ b/src/common/state/listen.ts @@ -9,6 +9,7 @@ export const SETTING_NAMES = typesafeUnionMembers({ shouldHandleDownloadLinks: true, badgeDisplayType: true, showInactiveTasks: true, + interceptExtensions: true, }); const ALL_STORED_STATE_NAMES = typesafeUnionMembers({ diff --git a/src/settings/SettingsForm.tsx b/src/settings/SettingsForm.tsx index af0f137..2b5efc4 100644 --- a/src/settings/SettingsForm.tsx +++ b/src/settings/SettingsForm.tsx @@ -160,6 +160,23 @@ export class SettingsForm extends React.PureComponent { DOWNLOAD_ONLY_PROTOCOLS.join(", "), ])} /> + + {browser.i18n.getMessage("Extension_list")} +
+ { + var interceptExtensions = e.currentTarget.value + .replace(/[\;\,\.]/g,' ')// unify various separators into spaces + .toLowerCase() + .split(' ') + .filter((s)=>{ return s; }) + .join(' '); + this.saveExtList(interceptExtensions); + }} + /> +
{this.maybeRenderDebuggingOutputAndSeparator()} @@ -265,6 +282,12 @@ export class SettingsForm extends React.PureComponent { }); } + private saveExtList(interceptExtensions: string) { + this.saveSettings({ + interceptExtensions, + }); + } + private saveSettings = async (settings: Partial) => { const success = await this.props.saveSettings({ ...typesafePick(this.props.extensionState.settings, ...SETTING_NAMES),