parent
09b2b4be10
commit
9925dec0f4
@ -57,7 +57,7 @@ type Header = {name: string; value: string};
|
|||||||
|
|
||||||
export interface DownloadOptions {
|
export interface DownloadOptions {
|
||||||
conflictAction: string;
|
conflictAction: string;
|
||||||
filename: string;
|
filename?: string;
|
||||||
saveAs: boolean;
|
saveAs: boolean;
|
||||||
url: string;
|
url: string;
|
||||||
method?: string;
|
method?: string;
|
||||||
@ -85,6 +85,7 @@ interface Downloads {
|
|||||||
onCreated: ExtensionListener;
|
onCreated: ExtensionListener;
|
||||||
onChanged: ExtensionListener;
|
onChanged: ExtensionListener;
|
||||||
onErased: ExtensionListener;
|
onErased: ExtensionListener;
|
||||||
|
onDeterminingFilename?: ExtensionListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WebRequest {
|
interface WebRequest {
|
||||||
|
@ -22,7 +22,8 @@ import {
|
|||||||
RUNNING,
|
RUNNING,
|
||||||
RETRYING
|
RETRYING
|
||||||
} from "./state";
|
} from "./state";
|
||||||
import { Preroller } from "./preroller";
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
import { Preroller, PrerollResults } from "./preroller";
|
||||||
|
|
||||||
function isRecoverable(error: string) {
|
function isRecoverable(error: string) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
@ -130,11 +131,13 @@ export class Download extends BaseDownload {
|
|||||||
}
|
}
|
||||||
const options: DownloadOptions = {
|
const options: DownloadOptions = {
|
||||||
conflictAction: await Prefs.get("conflict-action"),
|
conflictAction: await Prefs.get("conflict-action"),
|
||||||
filename: this.dest.full,
|
|
||||||
saveAs: false,
|
saveAs: false,
|
||||||
url: this.url,
|
url: this.url,
|
||||||
headers: [],
|
headers: [],
|
||||||
};
|
};
|
||||||
|
if (!CHROME) {
|
||||||
|
options.filename = this.dest.full;
|
||||||
|
}
|
||||||
if (!CHROME && this.private) {
|
if (!CHROME && this.private) {
|
||||||
options.incognito = true;
|
options.incognito = true;
|
||||||
}
|
}
|
||||||
@ -194,15 +197,7 @@ export class Download extends BaseDownload {
|
|||||||
if (!res) {
|
if (!res) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res.mime) {
|
this.adoptPrerollResults(res);
|
||||||
this.mime = res.mime;
|
|
||||||
}
|
|
||||||
if (res.name) {
|
|
||||||
this.serverName = res.name;
|
|
||||||
}
|
|
||||||
if (res.error) {
|
|
||||||
this.cancelAccordingToError(res.error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
console.error("Failed to preroll", this, ex.toString(), ex.stack, ex);
|
console.error("Failed to preroll", this, ex.toString(), ex.stack, ex);
|
||||||
@ -215,6 +210,18 @@ export class Download extends BaseDownload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adoptPrerollResults(res: PrerollResults) {
|
||||||
|
if (res.mime) {
|
||||||
|
this.mime = res.mime;
|
||||||
|
}
|
||||||
|
if (res.name) {
|
||||||
|
this.serverName = res.name;
|
||||||
|
}
|
||||||
|
if (res.error) {
|
||||||
|
this.cancelAccordingToError(res.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resume(forced = false) {
|
resume(forced = false) {
|
||||||
if (!(FORCABLE & this.state)) {
|
if (!(FORCABLE & this.state)) {
|
||||||
return;
|
return;
|
||||||
@ -391,4 +398,27 @@ export class Download extends BaseDownload {
|
|||||||
this.setMissing();
|
this.setMissing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatefromSuggestion(state: any) {
|
||||||
|
const res: PrerollResults = {};
|
||||||
|
if (state.mime) {
|
||||||
|
res.mime = state.mime;
|
||||||
|
}
|
||||||
|
if (state.filename) {
|
||||||
|
res.name = state.filename;
|
||||||
|
}
|
||||||
|
if (state.finalUrl) {
|
||||||
|
res.finalURL = state.finalUrl;
|
||||||
|
const detected = Preroller.maybeFindNameFromSearchParams(this, res);
|
||||||
|
if (detected) {
|
||||||
|
res.name = detected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.adoptPrerollResults(res);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.markDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,10 @@ export class Manager extends EventEmitter {
|
|||||||
|
|
||||||
downloads.onChanged.addListener(this.onChanged.bind(this));
|
downloads.onChanged.addListener(this.onChanged.bind(this));
|
||||||
downloads.onErased.addListener(this.onErased.bind(this));
|
downloads.onErased.addListener(this.onErased.bind(this));
|
||||||
|
if (CHROME && downloads.onDeterminingFilename) {
|
||||||
|
downloads.onDeterminingFilename.addListener(
|
||||||
|
this.onDeterminingFilename.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
Bus.onPort("manager", (port: Port) => {
|
Bus.onPort("manager", (port: Port) => {
|
||||||
const mport = new ManagerPort(this, port);
|
const mport = new ManagerPort(this, port);
|
||||||
@ -157,6 +161,20 @@ export class Manager extends EventEmitter {
|
|||||||
this.manIds.delete(downloadId);
|
this.manIds.delete(downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDeterminingFilename(state: any, suggest: Function) {
|
||||||
|
const download = this.manIds.get(state.id);
|
||||||
|
if (!download) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
download.updatefromSuggestion(state);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
const suggestion = {filename: download.dest.full};
|
||||||
|
suggest(suggestion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async resetScheduler() {
|
async resetScheduler() {
|
||||||
this.scheduler = null;
|
this.scheduler = null;
|
||||||
await this.startNext();
|
await this.startNext();
|
||||||
|
@ -54,6 +54,9 @@ export class Preroller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get shouldPreroll() {
|
get shouldPreroll() {
|
||||||
|
if (CHROME) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const {uURL, renamer} = this.download;
|
const {uURL, renamer} = this.download;
|
||||||
const {pathname, search, host} = uURL;
|
const {pathname, search, host} = uURL;
|
||||||
if (PREROLL_NOPE.has(host)) {
|
if (PREROLL_NOPE.has(host)) {
|
||||||
@ -167,39 +170,15 @@ export class Preroller {
|
|||||||
rv.mime = type.essence;
|
rv.mime = type.essence;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {p_ext: ext} = this.download.renamer;
|
|
||||||
const dispHeader = headers.get("content-disposition");
|
const dispHeader = headers.get("content-disposition");
|
||||||
if (dispHeader) {
|
if (dispHeader) {
|
||||||
const file = CDPARSER.parse(dispHeader);
|
const file = CDPARSER.parse(dispHeader);
|
||||||
// Sanitize
|
// Sanitize
|
||||||
rv.name = sanitizePath(file.replace(/[/\\]+/g, "-"));
|
rv.name = sanitizePath(file.replace(/[/\\]+/g, "-"));
|
||||||
}
|
}
|
||||||
else if (!ext || PREROLL_SEARCHEXTS.has(ext.toLocaleLowerCase())) {
|
else {
|
||||||
const {searchParams} = this.download.uURL;
|
const detected = Preroller.maybeFindNameFromSearchParams(
|
||||||
let detected = "";
|
this.download, rv);
|
||||||
for (const [, value] of searchParams) {
|
|
||||||
if (!NAME_TESTER.test(value)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const p = parsePath(value);
|
|
||||||
if (!p.base || !p.ext) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!MimeDB.hasExtension(p.ext)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (rv.mime) {
|
|
||||||
const mime = MimeDB.getMime(rv.mime);
|
|
||||||
if (mime && !mime.extensions.has(p.ext.toLowerCase())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const sanitized = sanitizePath(p.name);
|
|
||||||
if (sanitized.length <= detected.length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
detected = sanitized;
|
|
||||||
}
|
|
||||||
if (detected) {
|
if (detected) {
|
||||||
rv.name = detected;
|
rv.name = detected;
|
||||||
}
|
}
|
||||||
@ -231,4 +210,43 @@ export class Preroller {
|
|||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static maybeFindNameFromSearchParams(
|
||||||
|
download: Download, res: PrerollResults) {
|
||||||
|
const {p_ext: ext} = download.renamer;
|
||||||
|
if (ext && !PREROLL_SEARCHEXTS.has(ext.toLocaleLowerCase())) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return Preroller.findNameFromSearchParams(download.uURL, res.mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
static findNameFromSearchParams(url: URL, mimetype?: string) {
|
||||||
|
const {searchParams} = url;
|
||||||
|
let detected = "";
|
||||||
|
for (const [, value] of searchParams) {
|
||||||
|
if (!NAME_TESTER.test(value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const p = parsePath(value);
|
||||||
|
if (!p.base || !p.ext) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!MimeDB.hasExtension(p.ext)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mimetype) {
|
||||||
|
const mime = MimeDB.getMime(mimetype);
|
||||||
|
if (mime && !mime.extensions.has(p.ext.toLowerCase())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sanitized = sanitizePath(p.name);
|
||||||
|
if (sanitized.length <= detected.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
detected = sanitized;
|
||||||
|
}
|
||||||
|
return detected;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user