uBlock/platform/firefox/vapi-background-ext.js

329 lines
11 KiB
JavaScript
Raw Normal View History

2017-09-02 04:11:33 -06:00
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2017-present Raymond Hill
2017-09-02 04:11:33 -06:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/
/* globals browser */
2017-09-02 04:11:33 -06:00
'use strict';
/******************************************************************************/
import {
domainFromHostname,
hostnameFromNetworkURL,
} from './uri-utils.js';
/******************************************************************************/
2022-11-29 10:00:38 -07:00
// Canonical name-uncloaking feature.
let cnameUncloakEnabled = browser.dns instanceof Object;
let cnameUncloakProxied = false;
2017-09-02 04:11:33 -06:00
2022-11-29 10:00:38 -07:00
// https://github.com/uBlockOrigin/uBlock-issues/issues/911
// We detect here whether network requests are proxied, and if so,
// de-aliasing of hostnames will be disabled to avoid possible
// DNS leaks.
const proxyDetector = function(details) {
if ( details.proxyInfo instanceof Object ) {
cnameUncloakEnabled = false;
proxyDetectorTryCount = 0;
}
if ( proxyDetectorTryCount === 0 ) {
browser.webRequest.onHeadersReceived.removeListener(proxyDetector);
return;
}
proxyDetectorTryCount -= 1;
};
let proxyDetectorTryCount = 0;
2022-11-29 10:00:38 -07:00
// Related issues:
// - https://github.com/gorhill/uBlock/issues/1327
// - https://github.com/uBlockOrigin/uBlock-issues/issues/128
// - https://bugzilla.mozilla.org/show_bug.cgi?id=1503721
2017-09-02 04:11:33 -06:00
2022-11-29 10:00:38 -07:00
// Extend base class to normalize as per platform.
2017-09-02 04:11:33 -06:00
2022-11-29 10:00:38 -07:00
vAPI.Net = class extends vAPI.Net {
constructor() {
super();
this.pendingRequests = [];
this.canUncloakCnames = browser.dns instanceof Object;
this.cnames = new Map([ [ '', null ] ]);
this.cnameIgnoreList = null;
this.cnameIgnore1stParty = true;
this.cnameIgnoreExceptions = true;
this.cnameIgnoreRootDocument = true;
this.cnameMaxTTL = 120;
this.cnameReplayFullURL = false;
this.cnameFlushTime = Date.now() + this.cnameMaxTTL * 60000;
}
setOptions(options) {
super.setOptions(options);
if ( 'cnameUncloakEnabled' in options ) {
cnameUncloakEnabled =
this.canUncloakCnames &&
options.cnameUncloakEnabled !== false;
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
2022-11-29 10:00:38 -07:00
if ( 'cnameUncloakProxied' in options ) {
cnameUncloakProxied = options.cnameUncloakProxied === true;
}
if ( 'cnameIgnoreList' in options ) {
this.cnameIgnoreList =
this.regexFromStrList(options.cnameIgnoreList);
}
if ( 'cnameIgnore1stParty' in options ) {
this.cnameIgnore1stParty =
options.cnameIgnore1stParty !== false;
}
if ( 'cnameIgnoreExceptions' in options ) {
this.cnameIgnoreExceptions =
options.cnameIgnoreExceptions !== false;
}
if ( 'cnameIgnoreRootDocument' in options ) {
this.cnameIgnoreRootDocument =
options.cnameIgnoreRootDocument !== false;
}
if ( 'cnameMaxTTL' in options ) {
this.cnameMaxTTL = options.cnameMaxTTL || 120;
}
if ( 'cnameReplayFullURL' in options ) {
this.cnameReplayFullURL = options.cnameReplayFullURL === true;
}
this.cnames.clear(); this.cnames.set('', null);
this.cnameFlushTime = Date.now() + this.cnameMaxTTL * 60000;
// https://github.com/uBlockOrigin/uBlock-issues/issues/911
// Install/remove proxy detector.
if ( vAPI.webextFlavor.major < 80 ) {
const wrohr = browser.webRequest.onHeadersReceived;
if ( cnameUncloakEnabled === false || cnameUncloakProxied ) {
if ( wrohr.hasListener(proxyDetector) ) {
wrohr.removeListener(proxyDetector);
}
2022-11-29 10:00:38 -07:00
} else if ( wrohr.hasListener(proxyDetector) === false ) {
wrohr.addListener(
proxyDetector,
{ urls: [ '*://*/*' ] },
[ 'blocking' ]
);
}
2022-11-29 10:00:38 -07:00
proxyDetectorTryCount = 32;
2017-09-02 04:11:33 -06:00
}
2022-11-29 10:00:38 -07:00
}
normalizeDetails(details) {
const type = details.type;
2022-11-29 10:00:38 -07:00
if ( type === 'imageset' ) {
details.type = 'image';
return;
}
2022-11-29 10:00:38 -07:00
// https://github.com/uBlockOrigin/uBlock-issues/issues/345
// Re-categorize an embedded object as a `sub_frame` if its
// content type is that of a HTML document.
if ( type === 'object' && Array.isArray(details.responseHeaders) ) {
for ( const header of details.responseHeaders ) {
if ( header.name.toLowerCase() === 'content-type' ) {
if ( header.value.startsWith('text/html') ) {
details.type = 'sub_frame';
}
2022-11-29 10:00:38 -07:00
break;
}
}
}
2022-11-29 10:00:38 -07:00
}
denormalizeTypes(types) {
if ( types.length === 0 ) {
return Array.from(this.validTypes);
}
const out = new Set();
for ( const type of types ) {
if ( this.validTypes.has(type) ) {
out.add(type);
2017-09-02 04:11:33 -06:00
}
2022-11-29 10:00:38 -07:00
if ( type === 'image' && this.validTypes.has('imageset') ) {
out.add('imageset');
2017-09-02 04:11:33 -06:00
}
2022-11-29 10:00:38 -07:00
if ( type === 'sub_frame' ) {
out.add('object');
}
}
2022-11-29 10:00:38 -07:00
return Array.from(out);
}
canonicalNameFromHostname(hn) {
const cnRecord = this.cnames.get(hn);
if ( cnRecord !== undefined && cnRecord !== null ) {
return cnRecord.cname;
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
2022-11-29 10:00:38 -07:00
}
processCanonicalName(hn, cnRecord, details) {
if ( cnRecord === null ) { return; }
if ( cnRecord.isRootDocument ) { return; }
const hnBeg = details.url.indexOf(hn);
if ( hnBeg === -1 ) { return; }
const oldURL = details.url;
let newURL = oldURL.slice(0, hnBeg) + cnRecord.cname;
const hnEnd = hnBeg + hn.length;
if ( this.cnameReplayFullURL ) {
newURL += oldURL.slice(hnEnd);
} else {
const pathBeg = oldURL.indexOf('/', hnEnd);
if ( pathBeg !== -1 ) {
newURL += oldURL.slice(hnEnd, pathBeg + 1);
}
2022-11-29 10:00:38 -07:00
}
details.url = newURL;
details.aliasURL = oldURL;
return super.onBeforeSuspendableRequest(details);
}
recordCanonicalName(hn, record, isRootDocument) {
if ( (this.cnames.size & 0b111111) === 0 ) {
const now = Date.now();
if ( now >= this.cnameFlushTime ) {
this.cnames.clear(); this.cnames.set('', null);
this.cnameFlushTime = now + this.cnameMaxTTL * 60000;
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
}
2022-11-29 10:00:38 -07:00
let cname =
typeof record.canonicalName === 'string' &&
record.canonicalName !== hn
? record.canonicalName
: '';
if (
cname !== '' &&
this.cnameIgnore1stParty &&
domainFromHostname(cname) === domainFromHostname(hn)
) {
cname = '';
}
if (
cname !== '' &&
this.cnameIgnoreList !== null &&
this.cnameIgnoreList.test(cname)
) {
cname = '';
}
const cnRecord = cname !== '' ? { cname, isRootDocument } : null;
this.cnames.set(hn, cnRecord);
return cnRecord;
}
regexFromStrList(list) {
if (
typeof list !== 'string' ||
list.length === 0 ||
list === 'unset' ||
browser.dns instanceof Object === false
) {
return null;
}
if ( list === '*' ) {
return /^./;
}
return new RegExp(
'(?:^|\.)(?:' +
list.trim()
.split(/\s+/)
.map(a => a.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join('|') +
')$'
);
}
onBeforeSuspendableRequest(details) {
const r = super.onBeforeSuspendableRequest(details);
if ( cnameUncloakEnabled === false ) { return r; }
if ( r !== undefined ) {
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
if (
2022-11-29 10:00:38 -07:00
r.cancel === true ||
r.redirectUrl !== undefined ||
this.cnameIgnoreExceptions
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
) {
2022-11-29 10:00:38 -07:00
return r;
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
}
2022-11-29 10:00:38 -07:00
const hn = hostnameFromNetworkURL(details.url);
const cnRecord = this.cnames.get(hn);
if ( cnRecord !== undefined ) {
return this.processCanonicalName(hn, cnRecord, details);
}
const documentUrl = details.documentUrl || details.url;
const isRootDocument = this.cnameIgnoreRootDocument &&
hn === hostnameFromNetworkURL(documentUrl);
2022-11-29 10:00:38 -07:00
return browser.dns.resolve(hn, [ 'canonical_name' ]).then(
rec => {
const cnRecord = this.recordCanonicalName(hn, rec, isRootDocument);
return this.processCanonicalName(hn, cnRecord, details);
2022-11-29 10:00:38 -07:00
},
( ) => {
this.cnames.set(hn, null);
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
2022-11-29 10:00:38 -07:00
);
}
suspendOneRequest(details) {
const pending = {
details: Object.assign({}, details),
resolve: undefined,
promise: undefined
};
pending.promise = new Promise(resolve => {
pending.resolve = resolve;
});
this.pendingRequests.push(pending);
return pending.promise;
}
unsuspendAllRequests(discard = false) {
const pendingRequests = this.pendingRequests;
this.pendingRequests = [];
for ( const entry of pendingRequests ) {
entry.resolve(
discard !== true
? this.onBeforeSuspendableRequest(entry.details)
: undefined
);
Add ability to uncloak CNAME records Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/780 New webext permission added: `dns`, which purpose is to allow an extension to fetch the DNS record of specific hostnames, reference documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns The webext API `dns` is available in Firefox 60+ only. The new API will enable uBO to "uncloak" the actual hostname used in network requests. The ability is currently disabled by default for now -- this is only a first commit related to the above issue to allow advanced users to immediately use the new ability. Four advanced settings have been created to control the uncloaking of actual hostnames: cnameAliasList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to "uncloak" the hostnames in the list will. cnameIgnoreList: a space-separated list of hostnames. Default value: unset => empty list. Special value: * => all hostnames. A space-separated list of hostnames => this tells uBO to NOT re-run the network request through uBO's filtering engine with the CNAME hostname. This is useful to exclude commonly used actual hostnames from being re-run through uBO's filtering engine, so as to avoid pointless overhead. cnameIgnore1stParty: boolean. Default value: true. Whether uBO should ignore to re-run a network request through the filtering engine when the CNAME hostname is 1st-party to the alias hostname. cnameMaxTTL: number of minutes. Default value: 120. This tells uBO to clear its CNAME cache after the specified time. For efficiency purpose, uBO will cache alias=>CNAME associations for reuse so as to reduce calls to `browser.dns.resolve`. All the associations will be cleared after the specified time to ensure the map does not grow too large and too ensure uBO uses up to date CNAME information.
2019-11-19 10:05:33 -07:00
}
2022-11-29 10:00:38 -07:00
}
static canSuspend() {
return true;
}
};
/******************************************************************************/
vAPI.scriptletsInjector = ((doc, details) => {
let script, url;
try {
const blob = new self.Blob(
[ details.scriptlets ],
{ type: 'text/javascript; charset=utf-8' }
);
url = self.URL.createObjectURL(blob);
script = doc.createElement('script');
script.async = false;
script.src = url;
(doc.head || doc.documentElement).appendChild(script);
self.uBO_scriptletsInjected = details.filters;
} catch (ex) {
}
if ( url ) {
if ( script ) { script.remove(); }
self.URL.revokeObjectURL(url);
}
}).toString();
/******************************************************************************/