Bug 1939658 - Replace new URL usage with URL.parse/URL.canParse where possible. r=robwu,Standard8,Gijs,mtigley,pdahiya,settings-reviewers,credential-management-reviewers,devtools-reviewers,tabbrowser-reviewers,places-reviewers,omc-reviewers,migration-reviewers,firefox-desktop-core-reviewers ,home-newtab-reviewers,webcompat-reviewers,urlbar-reviewers,twisniewski,mossop,dao,nchevobbe,webdriver-reviewers,whimboo,issammani,mconley,nbarrett,beth
Differential Revision: https://phabricator.services.mozilla.com/D233071
This commit is contained in:
@@ -259,8 +259,10 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
let ctx = canvas.getContext("2d");
|
let ctx = canvas.getContext("2d");
|
||||||
ctx.drawImage(target, 0, 0);
|
ctx.drawImage(target, 0, 0);
|
||||||
let dataURL = canvas.toDataURL();
|
let dataURL = canvas.toDataURL();
|
||||||
let url = new URL(target.ownerDocument.location.href).pathname;
|
let url = target.ownerDocument.location;
|
||||||
let imageName = url.substr(url.lastIndexOf("/") + 1);
|
let imageName = url.pathname.substr(
|
||||||
|
url.pathname.lastIndexOf("/") + 1
|
||||||
|
);
|
||||||
return Promise.resolve({ failed: false, dataURL, imageName });
|
return Promise.resolve({ failed: false, dataURL, imageName });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@@ -309,7 +311,7 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
if (href) {
|
if (href) {
|
||||||
// Handle SVG links:
|
// Handle SVG links:
|
||||||
if (typeof href == "object" && href.animVal) {
|
if (typeof href == "object" && href.animVal) {
|
||||||
return this._makeURLAbsolute(this.context.link.baseURI, href.animVal);
|
return new URL(href.animVal, this.context.link.baseURI).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
return href;
|
return href;
|
||||||
@@ -325,7 +327,7 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
throw new Error("Empty href");
|
throw new Error("Empty href");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._makeURLAbsolute(this.context.link.baseURI, href);
|
return new URL(href, this.context.link.baseURI).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getLinkURI() {
|
_getLinkURI() {
|
||||||
@@ -436,10 +438,6 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
return urls[0];
|
return urls[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
_makeURLAbsolute(aBase, aUrl) {
|
|
||||||
return Services.io.newURI(aUrl, null, Services.io.newURI(aBase)).spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isProprietaryDRM() {
|
_isProprietaryDRM() {
|
||||||
return (
|
return (
|
||||||
this.context.target.isEncrypted &&
|
this.context.target.isEncrypted &&
|
||||||
@@ -998,10 +996,10 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
const descURL = context.target.getAttribute("longdesc");
|
const descURL = context.target.getAttribute("longdesc");
|
||||||
|
|
||||||
if (descURL) {
|
if (descURL) {
|
||||||
context.imageDescURL = this._makeURLAbsolute(
|
context.imageDescURL = new URL(
|
||||||
context.target.ownerDocument.body.baseURI,
|
descURL,
|
||||||
descURL
|
context.target.ownerDocument.body.baseURI
|
||||||
);
|
).href;
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
this.contentWindow.HTMLCanvasElement.isInstance(context.target)
|
this.contentWindow.HTMLCanvasElement.isInstance(context.target)
|
||||||
@@ -1088,10 +1086,7 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
|
|
||||||
if (computedURL) {
|
if (computedURL) {
|
||||||
context.hasBGImage = true;
|
context.hasBGImage = true;
|
||||||
context.bgImageURL = this._makeURLAbsolute(
|
context.bgImageURL = new URL(computedURL, bodyElt.baseURI).href;
|
||||||
bodyElt.baseURI,
|
|
||||||
computedURL
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1177,7 +1172,7 @@ export class ContextMenuChild extends JSWindowActorChild {
|
|||||||
|
|
||||||
if (bgImgUrl) {
|
if (bgImgUrl) {
|
||||||
context.hasBGImage = true;
|
context.hasBGImage = true;
|
||||||
context.bgImageURL = this._makeURLAbsolute(elem.baseURI, bgImgUrl);
|
context.bgImageURL = new URL(bgImgUrl, elem.baseURI).href;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,18 +189,14 @@ export class PageInfoChild extends JSWindowActorChild {
|
|||||||
!elem.hasAttribute("alt")
|
!elem.hasAttribute("alt")
|
||||||
);
|
);
|
||||||
} else if (content.SVGImageElement.isInstance(elem)) {
|
} else if (content.SVGImageElement.isInstance(elem)) {
|
||||||
try {
|
// Note: makeURLAbsolute will throw if either the baseURI is not a valid URI
|
||||||
// Note: makeURLAbsolute will throw if either the baseURI is not a valid URI
|
// or the URI formed from the baseURI and the URL is not a valid URI.
|
||||||
// or the URI formed from the baseURI and the URL is not a valid URI.
|
if (elem.href.baseVal) {
|
||||||
if (elem.href.baseVal) {
|
let href = URL.parse(elem.href.baseVal, elem.baseURI)?.href;
|
||||||
let href = Services.io.newURI(
|
if (href) {
|
||||||
elem.href.baseVal,
|
|
||||||
null,
|
|
||||||
Services.io.newURI(elem.baseURI)
|
|
||||||
).spec;
|
|
||||||
addMedia(href, "img", "", elem, false);
|
addMedia(href, "img", "", elem, false);
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
}
|
||||||
} else if (content.HTMLVideoElement.isInstance(elem)) {
|
} else if (content.HTMLVideoElement.isInstance(elem)) {
|
||||||
addMedia(elem.currentSrc, "video", "", elem, false);
|
addMedia(elem.currentSrc, "video", "", elem, false);
|
||||||
} else if (content.HTMLAudioElement.isInstance(elem)) {
|
} else if (content.HTMLAudioElement.isInstance(elem)) {
|
||||||
|
|||||||
@@ -1227,10 +1227,8 @@ class DomainExtractor {
|
|||||||
|
|
||||||
let href = element.getAttribute("href");
|
let href = element.getAttribute("href");
|
||||||
|
|
||||||
let url;
|
let url = URL.parse(href, origin);
|
||||||
try {
|
if (!url) {
|
||||||
url = new URL(href, origin);
|
|
||||||
} catch (ex) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,9 +1240,8 @@ class DomainExtractor {
|
|||||||
if (queryParam) {
|
if (queryParam) {
|
||||||
let paramValue = url.searchParams.get(queryParam);
|
let paramValue = url.searchParams.get(queryParam);
|
||||||
if (queryParamValueIsHref) {
|
if (queryParamValueIsHref) {
|
||||||
try {
|
paramValue = URL.parse(paramValue)?.hostname;
|
||||||
paramValue = new URL(paramValue).hostname;
|
if (!paramValue) {
|
||||||
} catch (e) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
paramValue = this.#processDomain(paramValue, providerName);
|
paramValue = this.#processDomain(paramValue, providerName);
|
||||||
@@ -1339,9 +1336,8 @@ class DomainExtractor {
|
|||||||
textContent = "https://" + textContent;
|
textContent = "https://" + textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
domain = URL.parse(textContent)?.hostname;
|
||||||
domain = new URL(textContent).hostname;
|
if (!domain) {
|
||||||
} catch (e) {
|
|
||||||
domain = fixup(textContent);
|
domain = fixup(textContent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -203,13 +203,11 @@ var gBrowserInit = {
|
|||||||
// Hack to ensure that the various initial pages favicon is loaded
|
// Hack to ensure that the various initial pages favicon is loaded
|
||||||
// instantaneously, to avoid flickering and improve perceived performance.
|
// instantaneously, to avoid flickering and improve perceived performance.
|
||||||
this._callWithURIToLoad(uriToLoad => {
|
this._callWithURIToLoad(uriToLoad => {
|
||||||
let url;
|
let url = URL.parse(uriToLoad);
|
||||||
try {
|
if (!url) {
|
||||||
url = Services.io.newURI(uriToLoad);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let nonQuery = url.prePath + url.filePath;
|
let nonQuery = url.URI.prePath + url.pathname;
|
||||||
if (nonQuery in gPageIcons) {
|
if (nonQuery in gPageIcons) {
|
||||||
gBrowser.setIcon(gBrowser.selectedTab, gPageIcons[nonQuery]);
|
gBrowser.setIcon(gBrowser.selectedTab, gPageIcons[nonQuery]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4597,7 +4597,7 @@ function setToolbarVisibility(
|
|||||||
break;
|
break;
|
||||||
case "newtab":
|
case "newtab":
|
||||||
default: {
|
default: {
|
||||||
let currentURI = gBrowser?.currentURI;
|
let currentURI;
|
||||||
if (!gBrowserInit.domContentLoaded) {
|
if (!gBrowserInit.domContentLoaded) {
|
||||||
let uriToLoad = gBrowserInit.uriToLoadPromise;
|
let uriToLoad = gBrowserInit.uriToLoadPromise;
|
||||||
if (uriToLoad) {
|
if (uriToLoad) {
|
||||||
@@ -4605,10 +4605,13 @@ function setToolbarVisibility(
|
|||||||
// We only care about the first tab being loaded
|
// We only care about the first tab being loaded
|
||||||
uriToLoad = uriToLoad[0];
|
uriToLoad = uriToLoad[0];
|
||||||
}
|
}
|
||||||
try {
|
currentURI = URL.parse(uriToLoad)?.URI;
|
||||||
currentURI = Services.io.newURI(uriToLoad);
|
if (!currentURI) {
|
||||||
} catch (ex) {}
|
currentURI = gBrowser?.currentURI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
currentURI = gBrowser.currentURI;
|
||||||
}
|
}
|
||||||
isVisible = BookmarkingUI.isOnNewTabPage(currentURI);
|
isVisible = BookmarkingUI.isOnNewTabPage(currentURI);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2625,12 +2625,9 @@ export class nsContextMenu {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (URL.canParse(linkText)) {
|
||||||
// If the underlying link text is a URL, we should not offer to translate.
|
// The underlying link text is a URL, we should not offer to translate.
|
||||||
new URL(linkText);
|
|
||||||
return "";
|
return "";
|
||||||
} catch {
|
|
||||||
// A URL could not be parsed from the unerlying link text.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the underlying link text is not a URL, we should offer to translate it.
|
// Since the underlying link text is not a URL, we should offer to translate it.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ ChromeUtils.defineLazyGetter(lazy, "gWindowsAlertsService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// One-time startup homepage override configurations
|
// One-time startup homepage override configurations
|
||||||
const ONCE_DOMAINS = ["mozilla.org", "firefox.com"];
|
const ONCE_DOMAINS = new Set(["mozilla.org", "firefox.com"]);
|
||||||
const ONCE_PREF = "browser.startup.homepage_override.once";
|
const ONCE_PREF = "browser.startup.homepage_override.once";
|
||||||
|
|
||||||
// Index of Private Browsing icon in firefox.exe
|
// Index of Private Browsing icon in firefox.exe
|
||||||
@@ -1023,20 +1023,18 @@ nsBrowserContentHandler.prototype = {
|
|||||||
overridePage = url
|
overridePage = url
|
||||||
.split("|")
|
.split("|")
|
||||||
.map(val => {
|
.map(val => {
|
||||||
try {
|
let parsed = URL.parse(val);
|
||||||
return new URL(val);
|
if (!parsed) {
|
||||||
} catch (ex) {
|
|
||||||
// Invalid URL, so filter out below
|
// Invalid URL, so filter out below
|
||||||
console.error("Invalid once url:", ex);
|
console.error(`Invalid once url: ${val}`);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return parsed;
|
||||||
})
|
})
|
||||||
.filter(
|
.filter(
|
||||||
parsed =>
|
parsed =>
|
||||||
parsed &&
|
parsed?.protocol == "https:" &&
|
||||||
parsed.protocol == "https:" &&
|
|
||||||
// Only accept exact hostname or subdomain; without port
|
// Only accept exact hostname or subdomain; without port
|
||||||
ONCE_DOMAINS.includes(
|
ONCE_DOMAINS.has(
|
||||||
Services.eTLD.getBaseDomainFromHost(parsed.host)
|
Services.eTLD.getBaseDomainFromHost(parsed.host)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -101,11 +101,8 @@ export class LoginBreachAlert extends MozLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get displayHostname() {
|
get displayHostname() {
|
||||||
try {
|
let url = URL.parse(this.hostname);
|
||||||
return new URL(this.hostname).hostname;
|
return url?.hostname ?? this.hostname;
|
||||||
} catch (err) {
|
|
||||||
return this.hostname;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ async function insertBookmark(bookmark) {
|
|||||||
let parentGuid = await getParentGuid(bookmark.Placement, bookmark.Folder);
|
let parentGuid = await getParentGuid(bookmark.Placement, bookmark.Folder);
|
||||||
|
|
||||||
await lazy.PlacesUtils.bookmarks.insert({
|
await lazy.PlacesUtils.bookmarks.insert({
|
||||||
url: Services.io.newURI(bookmark.URL.href),
|
url: bookmark.URL.URI,
|
||||||
title: bookmark.Title,
|
title: bookmark.Title,
|
||||||
guid: lazy.PlacesUtils.generateGuidWithPrefix(
|
guid: lazy.PlacesUtils.generateGuidWithPrefix(
|
||||||
BookmarksPolicies.BOOKMARK_GUID_PREFIX
|
BookmarksPolicies.BOOKMARK_GUID_PREFIX
|
||||||
|
|||||||
@@ -89,12 +89,10 @@ export var ProxyPolicies = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setProxyHostAndPort(type, address) {
|
function setProxyHostAndPort(type, address) {
|
||||||
let url;
|
// Prepend https just so we can use the URL parser
|
||||||
try {
|
// instead of parsing manually.
|
||||||
// Prepend https just so we can use the URL parser
|
let url = URL.parse(`https://${address}`);
|
||||||
// instead of parsing manually.
|
if (!url) {
|
||||||
url = new URL(`https://${address}`);
|
|
||||||
} catch (e) {
|
|
||||||
lazy.log.error(`Invalid address for ${type} proxy: ${address}`);
|
lazy.log.error(`Invalid address for ${type} proxy: ${address}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,22 +107,20 @@ export let WebsiteFilter = {
|
|||||||
|
|
||||||
shouldLoad(contentLocation, loadInfo) {
|
shouldLoad(contentLocation, loadInfo) {
|
||||||
let contentType = loadInfo.externalContentPolicyType;
|
let contentType = loadInfo.externalContentPolicyType;
|
||||||
let url = contentLocation.spec;
|
let url = contentLocation.spec.toLowerCase();
|
||||||
if (contentLocation.scheme == "view-source") {
|
if (contentLocation.scheme == "view-source") {
|
||||||
url = contentLocation.pathQueryRef;
|
url = contentLocation.pathQueryRef.toLowerCase();
|
||||||
} else if (url.toLowerCase().startsWith("about:reader")) {
|
} else if (url.startsWith("about:reader?url=")) {
|
||||||
url = decodeURIComponent(
|
url = decodeURIComponent(url.substr(17));
|
||||||
url.toLowerCase().substr("about:reader?url=".length)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT ||
|
contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT ||
|
||||||
contentType == Ci.nsIContentPolicy.TYPE_SUBDOCUMENT
|
contentType == Ci.nsIContentPolicy.TYPE_SUBDOCUMENT
|
||||||
) {
|
) {
|
||||||
if (this._blockPatterns.matches(url.toLowerCase())) {
|
if (this._blockPatterns.matches(url)) {
|
||||||
if (
|
if (
|
||||||
!this._exceptionsPatterns ||
|
!this._exceptionsPatterns ||
|
||||||
!this._exceptionsPatterns.matches(url.toLowerCase())
|
!this._exceptionsPatterns.matches(url)
|
||||||
) {
|
) {
|
||||||
return Ci.nsIContentPolicy.REJECT_POLICY;
|
return Ci.nsIContentPolicy.REJECT_POLICY;
|
||||||
}
|
}
|
||||||
@@ -145,13 +143,11 @@ export let WebsiteFilter = {
|
|||||||
}
|
}
|
||||||
let location = channel.getResponseHeader("location");
|
let location = channel.getResponseHeader("location");
|
||||||
// location might not be a fully qualified URL
|
// location might not be a fully qualified URL
|
||||||
let url;
|
let url = URL.parse(location);
|
||||||
try {
|
if (!url) {
|
||||||
url = new URL(location);
|
url = URL.parse(location, channel.URI.spec);
|
||||||
} catch (e) {
|
|
||||||
url = new URL(location, channel.URI.spec);
|
|
||||||
}
|
}
|
||||||
if (this._blockPatterns.matches(url.href.toLowerCase())) {
|
if (url && this._blockPatterns.matches(url.href.toLowerCase())) {
|
||||||
if (
|
if (
|
||||||
!this._exceptionsPatterns ||
|
!this._exceptionsPatterns ||
|
||||||
!this._exceptionsPatterns.matches(url.href.toLowerCase())
|
!this._exceptionsPatterns.matches(url.href.toLowerCase())
|
||||||
|
|||||||
@@ -72,12 +72,9 @@ Bookmarks.prototype = {
|
|||||||
};
|
};
|
||||||
folderMap.set(id, bmToInsert);
|
folderMap.set(id, bmToInsert);
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!URL.canParse(url)) {
|
||||||
new URL(url);
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(
|
console.error(
|
||||||
`Ignoring ${url} when importing from 360se because of exception:`,
|
`Ignoring ${url} when importing from 360se because it is not a valid URL.`
|
||||||
ex
|
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,6 +451,7 @@ export class ChromeProfileMigrator extends MigratorBase {
|
|||||||
|
|
||||||
let logins = [];
|
let logins = [];
|
||||||
let fallbackCreationDate = new Date();
|
let fallbackCreationDate = new Date();
|
||||||
|
const kValidSchemes = new Set(["https", "http", "ftp"]);
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
try {
|
try {
|
||||||
let origin_url = lazy.NetUtil.newURI(
|
let origin_url = lazy.NetUtil.newURI(
|
||||||
@@ -458,7 +459,6 @@ export class ChromeProfileMigrator extends MigratorBase {
|
|||||||
);
|
);
|
||||||
// Ignore entries for non-http(s)/ftp URLs because we likely can't
|
// Ignore entries for non-http(s)/ftp URLs because we likely can't
|
||||||
// use them anyway.
|
// use them anyway.
|
||||||
const kValidSchemes = new Set(["https", "http", "ftp"]);
|
|
||||||
if (!kValidSchemes.has(origin_url.scheme)) {
|
if (!kValidSchemes.has(origin_url.scheme)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { MSMigrationUtils } from "resource:///modules/MSMigrationUtils.sys.mjs";
|
|||||||
const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
|
const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
|
||||||
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
||||||
|
|
||||||
|
const ALLOWED_PROTOCOLS = new Set(["http:", "https:", "ftp:"]);
|
||||||
|
|
||||||
const lazy = {};
|
const lazy = {};
|
||||||
ChromeUtils.defineESModuleGetters(lazy, {
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
ESEDBReader: "resource:///modules/ESEDBReader.sys.mjs",
|
ESEDBReader: "resource:///modules/ESEDBReader.sys.mjs",
|
||||||
@@ -136,14 +138,8 @@ EdgeTypedURLMigrator.prototype = {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let url;
|
let url = URL.parse(urlString);
|
||||||
try {
|
if (!url || !ALLOWED_PROTOCOLS.has(url.protocol)) {
|
||||||
url = new URL(urlString);
|
|
||||||
if (!["http:", "https:", "ftp:"].includes(url.protocol)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(ex);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,31 +219,27 @@ EdgeTypedURLDBMigrator.prototype = {
|
|||||||
Date.now() - MigrationUtils.HISTORY_MAX_AGE_IN_MILLISECONDS
|
Date.now() - MigrationUtils.HISTORY_MAX_AGE_IN_MILLISECONDS
|
||||||
);
|
);
|
||||||
for (let typedUrlInfo of typedUrls) {
|
for (let typedUrlInfo of typedUrls) {
|
||||||
try {
|
let date = typedUrlInfo.AccessDateTimeUTC;
|
||||||
let date = typedUrlInfo.AccessDateTimeUTC;
|
if (!date) {
|
||||||
if (!date) {
|
date = kDateCutOff;
|
||||||
date = kDateCutOff;
|
} else if (date < kDateCutOff) {
|
||||||
} else if (date < kDateCutOff) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = new URL(typedUrlInfo.URL);
|
|
||||||
if (!["http:", "https:", "ftp:"].includes(url.protocol)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pageInfos.push({
|
|
||||||
url,
|
|
||||||
visits: [
|
|
||||||
{
|
|
||||||
transition: lazy.PlacesUtils.history.TRANSITIONS.TYPED,
|
|
||||||
date,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let url = URL.parse(typedUrlInfo.URL);
|
||||||
|
if (!url || !ALLOWED_PROTOCOLS.has(url.protocol)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pageInfos.push({
|
||||||
|
url,
|
||||||
|
visits: [
|
||||||
|
{
|
||||||
|
transition: lazy.PlacesUtils.history.TRANSITIONS.TYPED,
|
||||||
|
date,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await MigrationUtils.insertVisitsWrapper(pageInfos);
|
await MigrationUtils.insertVisitsWrapper(pageInfos);
|
||||||
},
|
},
|
||||||
@@ -319,9 +311,7 @@ EdgeReadingListMigrator.prototype = {
|
|||||||
for (let item of readingListItems) {
|
for (let item of readingListItems) {
|
||||||
let dateAdded = item.AddedDate || new Date();
|
let dateAdded = item.AddedDate || new Date();
|
||||||
// Avoid including broken URLs:
|
// Avoid including broken URLs:
|
||||||
try {
|
if (!URL.canParse(item.URL)) {
|
||||||
new URL(item.URL);
|
|
||||||
} catch (ex) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bookmarks.push({ url: item.URL, title: item.Title, dateAdded });
|
bookmarks.push({ url: item.URL, title: item.Title, dateAdded });
|
||||||
@@ -426,11 +416,9 @@ EdgeBookmarksMigrator.prototype = {
|
|||||||
let bmToInsert;
|
let bmToInsert;
|
||||||
// Ignore invalid URLs:
|
// Ignore invalid URLs:
|
||||||
if (!bookmark.IsFolder) {
|
if (!bookmark.IsFolder) {
|
||||||
try {
|
if (!URL.canParse(bookmark.URL)) {
|
||||||
new URL(bookmark.URL);
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(
|
console.error(
|
||||||
`Ignoring ${bookmark.URL} when importing from Edge because of exception: ${ex}`
|
`Ignoring ${bookmark.URL} when importing from Edge because it is not a valid URL.`
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -638,13 +638,11 @@ WindowsVaultFormPasswords.prototype = {
|
|||||||
}
|
}
|
||||||
let url =
|
let url =
|
||||||
item.contents.pResourceElement.contents.itemValue.readString();
|
item.contents.pResourceElement.contents.itemValue.readString();
|
||||||
let realURL;
|
let realURL = URL.parse(url);
|
||||||
try {
|
if (
|
||||||
realURL = Services.io.newURI(url);
|
!realURL ||
|
||||||
} catch (ex) {
|
!["http:", "https:", "ftp:"].includes(realURL.protocol)
|
||||||
/* leave realURL as null */
|
) {
|
||||||
}
|
|
||||||
if (!realURL || !["http", "https", "ftp"].includes(realURL.scheme)) {
|
|
||||||
// Ignore items for non-URLs or URLs that aren't HTTP(S)/FTP
|
// Ignore items for non-URLs or URLs that aren't HTTP(S)/FTP
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -690,7 +688,7 @@ WindowsVaultFormPasswords.prototype = {
|
|||||||
logins.push({
|
logins.push({
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
origin: realURL.prePath,
|
origin: realURL.URI.prePath,
|
||||||
timeCreated: creation,
|
timeCreated: creation,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1042,13 +1042,9 @@ class MigrationUtils {
|
|||||||
let url = pageInfo.url;
|
let url = pageInfo.url;
|
||||||
if (url instanceof Ci.nsIURI) {
|
if (url instanceof Ci.nsIURI) {
|
||||||
url = pageInfo.url.spec;
|
url = pageInfo.url.spec;
|
||||||
} else if (typeof url != "string") {
|
|
||||||
pageInfo.url.href;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (!URL.canParse(url)) {
|
||||||
new URL(url);
|
|
||||||
} catch (ex) {
|
|
||||||
// This won't save and we won't need to 'undo' it, so ignore this URL.
|
// This won't save and we won't need to 'undo' it, so ignore this URL.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ Bookmarks.prototype = {
|
|||||||
if (rows) {
|
if (rows) {
|
||||||
// Convert the rows from our SQLite database into a map from bookmark url to uuid
|
// Convert the rows from our SQLite database into a map from bookmark url to uuid
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
let uniqueURL = Services.io.newURI(row.getResultByName("url")).spec;
|
let uniqueURL = new URL(row.getResultByName("url")).href;
|
||||||
|
|
||||||
// Normalize the URL by removing any trailing slashes. We'll make sure to do
|
// Normalize the URL by removing any trailing slashes. We'll make sure to do
|
||||||
// the same when doing look-ups during a migration.
|
// the same when doing look-ups during a migration.
|
||||||
@@ -292,12 +292,9 @@ Bookmarks.prototype = {
|
|||||||
} else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
|
} else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
|
||||||
// Check we understand this URL before adding it:
|
// Check we understand this URL before adding it:
|
||||||
let url = entry.get("URLString");
|
let url = entry.get("URLString");
|
||||||
try {
|
if (!URL.canParse(url)) {
|
||||||
new URL(url);
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(
|
console.error(
|
||||||
`Ignoring ${url} when importing from Safari because of exception:`,
|
`Ignoring ${url} when importing from Safari because it is not a valid URL.`
|
||||||
ex
|
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||||||
300
|
300
|
||||||
);
|
);
|
||||||
|
|
||||||
const ALLOWED_SCHEMES = ["http", "https", "data", "blob"];
|
const ALLOWED_PROTOCOLS = new Set(["http:", "https:", "data:", "blob:"]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shifts the first element out of the set.
|
* Shifts the first element out of the set.
|
||||||
@@ -358,8 +358,7 @@ export const PageDataService = new (class PageDataService extends EventEmitter {
|
|||||||
* The url of the page.
|
* The url of the page.
|
||||||
*/
|
*/
|
||||||
async pageLoaded(actor, url) {
|
async pageLoaded(actor, url) {
|
||||||
let uri = Services.io.newURI(url);
|
if (!ALLOWED_PROTOCOLS.has(new URL(url).protocol)) {
|
||||||
if (!ALLOWED_SCHEMES.includes(uri.scheme)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,15 +140,11 @@ function parseMicrodataProp(propElement) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let url = URL.parse(
|
||||||
let url = new URL(
|
urlElement.getAttribute(attr),
|
||||||
urlElement.getAttribute(attr),
|
urlElement.ownerDocument.documentURI
|
||||||
urlElement.ownerDocument.documentURI
|
);
|
||||||
);
|
return url ? url.toString() : "";
|
||||||
return url.toString();
|
|
||||||
} catch (e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (propElement.localName) {
|
switch (propElement.localName) {
|
||||||
|
|||||||
@@ -179,15 +179,10 @@ class _InteractionsBlocklist {
|
|||||||
|
|
||||||
// First, find the URL's base host: the hostname without any subdomains or a
|
// First, find the URL's base host: the hostname without any subdomains or a
|
||||||
// public suffix.
|
// public suffix.
|
||||||
let url;
|
let url = URL.parse(urlToCheck);
|
||||||
try {
|
if (!url) {
|
||||||
url = new URL(urlToCheck);
|
|
||||||
if (!url) {
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
lazy.logConsole.warn(
|
lazy.logConsole.warn(
|
||||||
`Invalid URL passed to InteractionsBlocklist.isUrlBlocklisted: ${url}`
|
`Invalid URL passed to InteractionsBlocklist.isUrlBlocklisted: ${urlToCheck}`
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -679,10 +679,8 @@ var gPrivacyPane = {
|
|||||||
|
|
||||||
async updateDoHStatus() {
|
async updateDoHStatus() {
|
||||||
let trrURI = Services.dns.currentTrrURI;
|
let trrURI = Services.dns.currentTrrURI;
|
||||||
let hostname = "";
|
let hostname = URL.parse(trrURI)?.hostname;
|
||||||
try {
|
if (!hostname) {
|
||||||
hostname = new URL(trrURI).hostname;
|
|
||||||
} catch (e) {
|
|
||||||
hostname = await document.l10n.formatValue("preferences-doh-bad-url");
|
hostname = await document.l10n.formatValue("preferences-doh-bad-url");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -799,9 +799,8 @@ class TelemetryHandler {
|
|||||||
* tracking, since they're inside a WeakMap.
|
* tracking, since they're inside a WeakMap.
|
||||||
*/
|
*/
|
||||||
_findBrowserItemForURL(url) {
|
_findBrowserItemForURL(url) {
|
||||||
try {
|
url = URL.parse(url);
|
||||||
url = new URL(url);
|
if (!url) {
|
||||||
} catch (ex) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,13 +810,12 @@ class TelemetryHandler {
|
|||||||
if (currentBestMatch === Infinity) {
|
if (currentBestMatch === Infinity) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
// Make sure to cache the parsed URL object, since there's no reason to
|
||||||
// Make sure to cache the parsed URL object, since there's no reason to
|
// do it twice.
|
||||||
// do it twice.
|
trackingURL =
|
||||||
trackingURL =
|
candidateItem._trackingURL ||
|
||||||
candidateItem._trackingURL ||
|
(candidateItem._trackingURL = URL.parse(trackingURL));
|
||||||
(candidateItem._trackingURL = new URL(trackingURL));
|
if (!trackingURL) {
|
||||||
} catch (ex) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let score = this.compareUrls(url, trackingURL);
|
let score = this.compareUrls(url, trackingURL);
|
||||||
@@ -1448,19 +1446,18 @@ class ContentHandler {
|
|||||||
info.nonAdsLinkQueryParamNames.length &&
|
info.nonAdsLinkQueryParamNames.length &&
|
||||||
info.nonAdsLinkRegexps.some(r => r.test(url))
|
info.nonAdsLinkRegexps.some(r => r.test(url))
|
||||||
) {
|
) {
|
||||||
let newParsedUrl;
|
|
||||||
for (let key of info.nonAdsLinkQueryParamNames) {
|
for (let key of info.nonAdsLinkQueryParamNames) {
|
||||||
let paramValue = parsedUrl.searchParams.get(key);
|
let paramValue = parsedUrl.searchParams.get(key);
|
||||||
if (paramValue) {
|
if (paramValue) {
|
||||||
try {
|
let newParsedUrl = /^https?:\/\//.test(paramValue)
|
||||||
newParsedUrl = /^https?:\/\//.test(paramValue)
|
? URL.parse(paramValue)
|
||||||
? new URL(paramValue)
|
: URL.parse(paramValue, parsedUrl.origin);
|
||||||
: new URL(paramValue, parsedUrl.origin);
|
if (newParsedUrl) {
|
||||||
|
parsedUrl = newParsedUrl;
|
||||||
break;
|
break;
|
||||||
} catch (e) {}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsedUrl = newParsedUrl ?? parsedUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the component type of the link.
|
// Determine the component type of the link.
|
||||||
|
|||||||
@@ -25,13 +25,11 @@ ChromeUtils.registerWindowActor("Screenshot", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function loadContentWindow(browser, url) {
|
function loadContentWindow(browser, url) {
|
||||||
let uri;
|
let uri = URL.parse(url)?.URI;
|
||||||
try {
|
if (!uri) {
|
||||||
uri = Services.io.newURI(url);
|
let err = new Error(`Invalid URL passed to loadContentWindow(): ${url}`);
|
||||||
} catch (e) {
|
console.error(err);
|
||||||
let msg = `Invalid URL passed to loadContentWindow(): ${url}`;
|
return Promise.reject(err);
|
||||||
console.error(msg);
|
|
||||||
return Promise.reject(new Error(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||||
|
|||||||
@@ -255,14 +255,12 @@ export class ShoppingContainer extends MozLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHostnameFromProductUrl() {
|
getHostnameFromProductUrl() {
|
||||||
let hostname;
|
let hostname = URL.parse(this.productUrl)?.hostname;
|
||||||
try {
|
if (hostname) {
|
||||||
hostname = new URL(this.productUrl)?.hostname;
|
|
||||||
return hostname;
|
return hostname;
|
||||||
} catch (e) {
|
|
||||||
console.warn(`Unknown product url ${this.productUrl}.`);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
console.warn(`Unknown product url ${this.productUrl}.`);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
analysisDetailsTemplate() {
|
analysisDetailsTemplate() {
|
||||||
|
|||||||
@@ -98,19 +98,19 @@ export default class TabHoverPreviewPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPrettyURI(uri) {
|
getPrettyURI(uri) {
|
||||||
try {
|
let url = URL.parse(uri);
|
||||||
let url = new URL(uri);
|
if (!url) {
|
||||||
if (url.protocol == "about:" && url.pathname == "reader") {
|
|
||||||
url = new URL(url.searchParams.get("url"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.protocol === "about:") {
|
|
||||||
return url.href;
|
|
||||||
}
|
|
||||||
return `${url.hostname}`.replace(/^w{3}\./, "");
|
|
||||||
} catch {
|
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (url.protocol == "about:" && url.pathname == "reader") {
|
||||||
|
url = URL.parse(url.searchParams.get("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url?.protocol === "about:") {
|
||||||
|
return url.href;
|
||||||
|
}
|
||||||
|
return url ? url.hostname.replace(/^w{3}\./, "") : uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
_hasValidWireframeState(tab) {
|
_hasValidWireframeState(tab) {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ const TIPPYTOP_JSON_PATH =
|
|||||||
* Get a domain from a url optionally stripping subdomains.
|
* Get a domain from a url optionally stripping subdomains.
|
||||||
*/
|
*/
|
||||||
export function getDomain(url, strip = "www.") {
|
export function getDomain(url, strip = "www.") {
|
||||||
let domain = "";
|
let domain = URL.parse(url)?.hostname;
|
||||||
try {
|
if (!domain) {
|
||||||
domain = new URL(url).hostname;
|
return "";
|
||||||
} catch (ex) {}
|
}
|
||||||
if (strip === "*") {
|
if (strip === "*") {
|
||||||
try {
|
try {
|
||||||
domain = Services.eTLD.getBaseDomainFromHost(domain);
|
domain = Services.eTLD.getBaseDomainFromHost(domain);
|
||||||
|
|||||||
@@ -168,10 +168,9 @@ export class MerinoClient {
|
|||||||
if (!endpointString) {
|
if (!endpointString) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
let url;
|
let url = URL.parse(endpointString);
|
||||||
try {
|
if (!url) {
|
||||||
url = new URL(endpointString);
|
let error = new Error(`${endpointString} is not a valid URL`);
|
||||||
} catch (error) {
|
|
||||||
this.logger.error("Error creating endpoint URL", error);
|
this.logger.error("Error creating endpoint URL", error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -854,12 +854,7 @@ export class UrlbarInput {
|
|||||||
result: selectedResult || this._resultForCurrentValue || null,
|
result: selectedResult || this._resultForCurrentValue || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
let isValidUrl = false;
|
if (URL.canParse(url)) {
|
||||||
try {
|
|
||||||
new URL(url);
|
|
||||||
isValidUrl = true;
|
|
||||||
} catch (ex) {}
|
|
||||||
if (isValidUrl) {
|
|
||||||
// Annotate if the untrimmed value contained a scheme, to later potentially
|
// Annotate if the untrimmed value contained a scheme, to later potentially
|
||||||
// be upgraded by schemeless HTTPS-First.
|
// be upgraded by schemeless HTTPS-First.
|
||||||
openParams.schemelessInput = this.#getSchemelessInput(
|
openParams.schemelessInput = this.#getSchemelessInput(
|
||||||
@@ -2808,9 +2803,8 @@ export class UrlbarInput {
|
|||||||
return result.payload.url;
|
return result.payload.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
uri = URL.parse(this._untrimmedValue)?.URI;
|
||||||
uri = Services.io.newURI(this._untrimmedValue);
|
if (!uri) {
|
||||||
} catch (ex) {
|
|
||||||
return selectedVal;
|
return selectedVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2846,10 +2840,11 @@ export class UrlbarInput {
|
|||||||
// Unless decodeURLsOnCopy is set. Do not encode data: URIs.
|
// Unless decodeURLsOnCopy is set. Do not encode data: URIs.
|
||||||
if (!lazy.UrlbarPrefs.get("decodeURLsOnCopy") && !uri.schemeIs("data")) {
|
if (!lazy.UrlbarPrefs.get("decodeURLsOnCopy") && !uri.schemeIs("data")) {
|
||||||
try {
|
try {
|
||||||
new URL(selectedVal);
|
if (URL.canParse(selectedVal)) {
|
||||||
// Use encodeURI instead of URL.href because we don't want
|
// Use encodeURI instead of URL.href because we don't want
|
||||||
// trailing slash.
|
// trailing slash.
|
||||||
selectedVal = encodeURI(selectedVal);
|
selectedVal = encodeURI(selectedVal);
|
||||||
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// URL is invalid. Return original selected value.
|
// URL is invalid. Return original selected value.
|
||||||
}
|
}
|
||||||
@@ -3375,10 +3370,9 @@ export class UrlbarInput {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let strippedURI = null;
|
let strippedURI = null;
|
||||||
let uri = null;
|
|
||||||
|
|
||||||
// Error check occurs during isClipboardURIValid
|
// Error check occurs during isClipboardURIValid
|
||||||
uri = Services.io.newURI(copyString);
|
let uri = Services.io.newURI(copyString);
|
||||||
try {
|
try {
|
||||||
strippedURI = lazy.QueryStringStripper.stripForCopyOrShare(uri);
|
strippedURI = lazy.QueryStringStripper.stripForCopyOrShare(uri);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -3402,14 +3396,8 @@ export class UrlbarInput {
|
|||||||
if (!copyString) {
|
if (!copyString) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// throws if the selected string is not a valid URI
|
|
||||||
try {
|
|
||||||
Services.io.newURI(copyString);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return URL.canParse(copyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4781,7 +4769,7 @@ function getDroppableData(event) {
|
|||||||
}
|
}
|
||||||
// The URL bar automatically handles inputs with newline characters,
|
// The URL bar automatically handles inputs with newline characters,
|
||||||
// so we can get away with treating text/x-moz-url flavours as text/plain.
|
// so we can get away with treating text/x-moz-url flavours as text/plain.
|
||||||
if (links.length && links[0].url) {
|
if (links[0]?.url) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let href = links[0].url;
|
let href = links[0].url;
|
||||||
if (lazy.UrlbarUtils.stripUnsafeProtocolOnPaste(href) != href) {
|
if (lazy.UrlbarUtils.stripUnsafeProtocolOnPaste(href) != href) {
|
||||||
@@ -4791,13 +4779,13 @@ function getDroppableData(event) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// If this fails, checkLoadURIStrWithPrincipal would also fail,
|
||||||
// If this throws, checkLoadURStrWithPrincipal would also throw,
|
// as that's what it does with things that don't pass the IO
|
||||||
// as that's what it does with things that don't pass the IO
|
// service's newURI constructor without fixup. It's conceivable we
|
||||||
// service's newURI constructor without fixup. It's conceivable we
|
// may want to relax this check in the future (so e.g. www.foo.com
|
||||||
// may want to relax this check in the future (so e.g. www.foo.com
|
// gets fixed up), but not right now.
|
||||||
// gets fixed up), but not right now.
|
let url = URL.parse(href);
|
||||||
let url = new URL(href);
|
if (url) {
|
||||||
// If we succeed, try to pass security checks. If this works, return the
|
// If we succeed, try to pass security checks. If this works, return the
|
||||||
// URL object. If the *security checks* fail, return null.
|
// URL object. If the *security checks* fail, return null.
|
||||||
try {
|
try {
|
||||||
@@ -4812,9 +4800,8 @@ function getDroppableData(event) {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
|
||||||
// We couldn't make a URL out of this. Continue on, and return text below.
|
|
||||||
}
|
}
|
||||||
|
// We couldn't make a URL out of this. Continue on, and return text below.
|
||||||
}
|
}
|
||||||
// Handle as text.
|
// Handle as text.
|
||||||
return event.dataTransfer.getData("text/plain");
|
return event.dataTransfer.getData("text/plain");
|
||||||
|
|||||||
@@ -985,10 +985,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
|||||||
);
|
);
|
||||||
if (param) {
|
if (param) {
|
||||||
let [key, value] = param.split("=");
|
let [key, value] = param.split("=");
|
||||||
let searchParams;
|
let searchParams = URL.parse(result.payload.url)?.searchParams;
|
||||||
try {
|
|
||||||
({ searchParams } = new URL(result.payload.url));
|
|
||||||
} catch (error) {}
|
|
||||||
if (
|
if (
|
||||||
(value === undefined && searchParams?.has(key)) ||
|
(value === undefined && searchParams?.has(key)) ||
|
||||||
(value !== undefined && searchParams?.getAll(key).includes(value))
|
(value !== undefined && searchParams?.getAll(key).includes(value))
|
||||||
|
|||||||
@@ -89,15 +89,16 @@ class ProviderClipboard extends UrlbarProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#validUrl(clipboardVal) {
|
#validUrl(clipboardVal) {
|
||||||
try {
|
let givenUrl = URL.parse(clipboardVal);
|
||||||
let givenUrl;
|
if (!givenUrl) {
|
||||||
givenUrl = new URL(clipboardVal);
|
|
||||||
if (givenUrl.protocol == "http:" || givenUrl.protocol == "https:") {
|
|
||||||
return givenUrl.href;
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
// Not a valid URI.
|
// Not a valid URI.
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (givenUrl.protocol == "http:" || givenUrl.protocol == "https:") {
|
||||||
|
return givenUrl.href;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,9 +86,7 @@ class ProviderHeuristicFallback extends UrlbarProvider {
|
|||||||
// to visit or search for it, we provide an alternative searchengine
|
// to visit or search for it, we provide an alternative searchengine
|
||||||
// match if the string looks like an alphanumeric origin or an e-mail.
|
// match if the string looks like an alphanumeric origin or an e-mail.
|
||||||
let str = queryContext.searchString;
|
let str = queryContext.searchString;
|
||||||
try {
|
if (!URL.canParse(str)) {
|
||||||
new URL(str);
|
|
||||||
} catch (ex) {
|
|
||||||
if (
|
if (
|
||||||
lazy.UrlbarPrefs.get("keyword.enabled") &&
|
lazy.UrlbarPrefs.get("keyword.enabled") &&
|
||||||
(lazy.UrlbarTokenizer.looksLikeOrigin(str, {
|
(lazy.UrlbarTokenizer.looksLikeOrigin(str, {
|
||||||
|
|||||||
@@ -491,11 +491,8 @@ async function isDefaultEngineHomepage(urlStr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The URL object throws if the string isn't a valid URL.
|
let url = URL.parse(urlStr);
|
||||||
let url;
|
if (!url) {
|
||||||
try {
|
|
||||||
url = new URL(urlStr);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -311,10 +311,7 @@ class ProviderTopSites extends UrlbarProvider {
|
|||||||
|
|
||||||
if (!engine && site.url) {
|
if (!engine && site.url) {
|
||||||
// Look up the engine by its domain.
|
// Look up the engine by its domain.
|
||||||
let host;
|
let host = URL.parse(site.url)?.hostname;
|
||||||
try {
|
|
||||||
host = new URL(site.url).hostname;
|
|
||||||
} catch (err) {}
|
|
||||||
if (host) {
|
if (host) {
|
||||||
engine = (
|
engine = (
|
||||||
await lazy.UrlbarSearchUtils.enginesForDomainPrefix(host)
|
await lazy.UrlbarSearchUtils.enginesForDomainPrefix(host)
|
||||||
|
|||||||
@@ -382,10 +382,8 @@ class _UrlbarSearchTermsPersistence {
|
|||||||
* first matched query parameter to be persisted.
|
* first matched query parameter to be persisted.
|
||||||
*/
|
*/
|
||||||
isDefaultPage(currentURI, provider) {
|
isDefaultPage(currentURI, provider) {
|
||||||
let searchParams;
|
let { searchParams } = URL.fromURI(currentURI);
|
||||||
try {
|
if (!searchParams.size) {
|
||||||
searchParams = new URL(currentURI.spec).searchParams;
|
|
||||||
} catch (ex) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (provider.includeParams) {
|
if (provider.includeParams) {
|
||||||
|
|||||||
@@ -798,12 +798,11 @@ export var UrlbarUtils = {
|
|||||||
* if there is no ref and undefined if url is not well-formed.
|
* if there is no ref and undefined if url is not well-formed.
|
||||||
*/
|
*/
|
||||||
extractRefFromUrl(url) {
|
extractRefFromUrl(url) {
|
||||||
try {
|
let uri = URL.parse(url)?.URI;
|
||||||
let nsUri = Services.io.newURI(url);
|
if (uri) {
|
||||||
return { base: nsUri.specIgnoringRef, ref: nsUri.ref };
|
return { base: uri.specIgnoringRef, ref: uri.ref };
|
||||||
} catch {
|
|
||||||
return { base: url };
|
|
||||||
}
|
}
|
||||||
|
return { base: url };
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1200,10 +1199,10 @@ export var UrlbarUtils = {
|
|||||||
if (!lazy.UrlbarTokenizer.REGEXP_PREFIX.test(candidate)) {
|
if (!lazy.UrlbarTokenizer.REGEXP_PREFIX.test(candidate)) {
|
||||||
candidate = "http://" + candidate;
|
candidate = "http://" + candidate;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
url = new URL(url);
|
url = URL.parse(url);
|
||||||
candidate = new URL(candidate);
|
candidate = URL.parse(candidate);
|
||||||
} catch (e) {
|
if (!url || !candidate) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,16 @@ this.shot = (function () {
|
|||||||
Object.prototype.toString.call(process) === "[object process]";
|
Object.prototype.toString.call(process) === "[object process]";
|
||||||
const URL = (isNode && require("url").URL) || window.URL;
|
const URL = (isNode && require("url").URL) || window.URL;
|
||||||
|
|
||||||
|
if (typeof URL.parse !== "function") {
|
||||||
|
URL.parse = function (url, base) {
|
||||||
|
try {
|
||||||
|
return new URL(url, base);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Throws an error if the condition isn't true. Any extra arguments after the condition
|
/** Throws an error if the condition isn't true. Any extra arguments after the condition
|
||||||
are used as console.error() arguments. */
|
are used as console.error() arguments. */
|
||||||
function assert(condition, ...args) {
|
function assert(condition, ...args) {
|
||||||
@@ -25,17 +35,14 @@ this.shot = (function () {
|
|||||||
|
|
||||||
/** True if `url` is a valid URL */
|
/** True if `url` is a valid URL */
|
||||||
function isUrl(url) {
|
function isUrl(url) {
|
||||||
try {
|
const parsed = URL.parse(url);
|
||||||
const parsed = new URL(url);
|
if (parsed) {
|
||||||
|
|
||||||
if (parsed.protocol === "view-source:") {
|
if (parsed.protocol === "view-source:") {
|
||||||
return isUrl(url.substr("view-source:".length));
|
return isUrl(url.substr(12));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidClipImageUrl(url) {
|
function isValidClipImageUrl(url) {
|
||||||
@@ -59,7 +66,7 @@ this.shot = (function () {
|
|||||||
|
|
||||||
function assertOrigin(url) {
|
function assertOrigin(url) {
|
||||||
assertUrl(url);
|
assertUrl(url);
|
||||||
if (url.search(/^https?:/i) !== -1) {
|
if (/^https?:/i.test(url)) {
|
||||||
let newUrl = new URL(url);
|
let newUrl = new URL(url);
|
||||||
if (newUrl.pathname != "/") {
|
if (newUrl.pathname != "/") {
|
||||||
throw new Error("Bad origin, might include path");
|
throw new Error("Bad origin, might include path");
|
||||||
@@ -71,16 +78,15 @@ this.shot = (function () {
|
|||||||
if (!url) {
|
if (!url) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (url.search(/^https?:/i) === -1) {
|
if (!/^https?:/i.test(url)) {
|
||||||
// Non-HTTP URLs don't have an origin
|
// Non-HTTP URLs don't have an origin
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
let tryUrl = URL.parse(url);
|
||||||
let tryUrl = new URL(url);
|
if (tryUrl) {
|
||||||
return tryUrl.origin;
|
return tryUrl.origin;
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if the given object has all of the required attributes, and no extra
|
/** Check if the given object has all of the required attributes, and no extra
|
||||||
|
|||||||
@@ -164,11 +164,9 @@ export let LaterRun = {
|
|||||||
let rv = [];
|
let rv = [];
|
||||||
for (let [, pageData] of pageDataStore) {
|
for (let [, pageData] of pageDataStore) {
|
||||||
if (pageData.url) {
|
if (pageData.url) {
|
||||||
let uri = null;
|
let urlString = Services.urlFormatter.formatURL(pageData.url.trim());
|
||||||
try {
|
let uri = URL.parse(urlString)?.URI;
|
||||||
let urlString = Services.urlFormatter.formatURL(pageData.url.trim());
|
if (!uri) {
|
||||||
uri = Services.io.newURI(urlString);
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(
|
console.error(
|
||||||
"Invalid LaterRun page URL ",
|
"Invalid LaterRun page URL ",
|
||||||
pageData.url,
|
pageData.url,
|
||||||
|
|||||||
@@ -504,9 +504,7 @@ export const URILoadingHelper = {
|
|||||||
if (where == "current") {
|
if (where == "current") {
|
||||||
targetBrowser = params.targetBrowser || w.gBrowser.selectedBrowser;
|
targetBrowser = params.targetBrowser || w.gBrowser.selectedBrowser;
|
||||||
loadInBackground = false;
|
loadInBackground = false;
|
||||||
try {
|
uriObj = URL.parse(url)?.URI;
|
||||||
uriObj = Services.io.newURI(url);
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
// In certain tabs, we restrict what if anything may replace the loaded
|
// In certain tabs, we restrict what if anything may replace the loaded
|
||||||
// page. If a load request bounces off for the currently selected tab,
|
// page. If a load request bounces off for the currently selected tab,
|
||||||
|
|||||||
@@ -306,14 +306,7 @@ var Builder = class {
|
|||||||
*/
|
*/
|
||||||
_clearHistory(uriSpecsToRemove) {
|
_clearHistory(uriSpecsToRemove) {
|
||||||
let URIsToRemove = uriSpecsToRemove
|
let URIsToRemove = uriSpecsToRemove
|
||||||
.map(spec => {
|
.map(spec => URL.parse(spec)?.URI)
|
||||||
try {
|
|
||||||
// in case we get a bad uri
|
|
||||||
return Services.io.newURI(spec);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(uri => !!uri);
|
.filter(uri => !!uri);
|
||||||
|
|
||||||
if (URIsToRemove.length) {
|
if (URIsToRemove.length) {
|
||||||
|
|||||||
@@ -3462,11 +3462,11 @@ Toolbox.prototype = {
|
|||||||
* @return {String} pathname
|
* @return {String} pathname
|
||||||
*/
|
*/
|
||||||
getExtensionPathName(url) {
|
getExtensionPathName(url) {
|
||||||
if (!URL.canParse(url)) {
|
const parsedURL = URL.parse(url);
|
||||||
|
if (!parsedURL) {
|
||||||
// Return the url if unable to resolve the pathname.
|
// Return the url if unable to resolve the pathname.
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
const parsedURL = new URL(url);
|
|
||||||
// Only moz-extension URL should be shortened into the URL pathname.
|
// Only moz-extension URL should be shortened into the URL pathname.
|
||||||
if (parsedURL.protocol !== "moz-extension:") {
|
if (parsedURL.protocol !== "moz-extension:") {
|
||||||
return url;
|
return url;
|
||||||
|
|||||||
@@ -288,10 +288,12 @@ function TargetMixin(parentClass) {
|
|||||||
if (this._title) {
|
if (this._title) {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
return URL.canParse(this._url)
|
const parsedURL = URL.parse(this._url);
|
||||||
? new URL(this._url).pathname
|
if (parsedURL) {
|
||||||
: // If document URL can't be parsed, fallback to the raw URL.
|
return parsedURL.pathname;
|
||||||
this._url;
|
}
|
||||||
|
// If document URL can't be parsed, fallback to the raw URL.
|
||||||
|
return this._url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isContentProcess) {
|
if (this.isContentProcess) {
|
||||||
|
|||||||
@@ -190,14 +190,10 @@ function getFileName(baseNameWithQuery) {
|
|||||||
* @return {URL} The URL object
|
* @return {URL} The URL object
|
||||||
*/
|
*/
|
||||||
function getUrl(url) {
|
function getUrl(url) {
|
||||||
try {
|
if (URL.isInstance(url)) {
|
||||||
if (url instanceof URL) {
|
return url;
|
||||||
return url;
|
|
||||||
}
|
|
||||||
return new URL(url);
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return URL.parse(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,7 +205,7 @@ function getUrl(url) {
|
|||||||
*/
|
*/
|
||||||
function getUrlProperty(input, property) {
|
function getUrlProperty(input, property) {
|
||||||
const url = getUrl(input);
|
const url = getUrl(input);
|
||||||
return url?.[property] ? url[property] : "";
|
return url?.[property] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -705,7 +701,7 @@ function removeXSSIString(payloadUnclean) {
|
|||||||
const xssiRegexMatch = payloadUnclean.match(xssiRegex);
|
const xssiRegexMatch = payloadUnclean.match(xssiRegex);
|
||||||
|
|
||||||
// Remove XSSI string if there was one found
|
// Remove XSSI string if there was one found
|
||||||
if (xssiRegexMatch?.length > 0) {
|
if (xssiRegexMatch?.length) {
|
||||||
const xssiLen = xssiRegexMatch[0].length;
|
const xssiLen = xssiRegexMatch[0].length;
|
||||||
try {
|
try {
|
||||||
// substring the payload by the length of the XSSI match to remove it
|
// substring the payload by the length of the XSSI match to remove it
|
||||||
@@ -743,7 +739,7 @@ function getRequestHeadersRawText(
|
|||||||
requestHeaders,
|
requestHeaders,
|
||||||
urlDetails
|
urlDetails
|
||||||
) {
|
) {
|
||||||
const url = new URL(urlDetails.url);
|
const url = getUrl(urlDetails.url);
|
||||||
const path = url ? `${url.pathname}${url.search}` : "<unknown>";
|
const path = url ? `${url.pathname}${url.search}` : "<unknown>";
|
||||||
const preHeaderText = `${method} ${path} ${httpVersion}`;
|
const preHeaderText = `${method} ${path} ${httpVersion}`;
|
||||||
return writeHeaderText(requestHeaders.headers, preHeaderText).trim();
|
return writeHeaderText(requestHeaders.headers, preHeaderText).trim();
|
||||||
|
|||||||
@@ -448,15 +448,10 @@ define(function (require, exports, module) {
|
|||||||
* Whether the token is a URL.
|
* Whether the token is a URL.
|
||||||
*/
|
*/
|
||||||
function isURL(token) {
|
function isURL(token) {
|
||||||
try {
|
if (!validProtocols.test(token)) {
|
||||||
if (!validProtocols.test(token)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
new URL(token);
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return URL.canParse(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2027,8 +2027,8 @@ class OutputParser {
|
|||||||
*/
|
*/
|
||||||
#appendURL(match, url, options) {
|
#appendURL(match, url, options) {
|
||||||
if (options.urlClass) {
|
if (options.urlClass) {
|
||||||
// Sanitize the URL. Note that if we modify the URL, we just
|
// Sanitize the URL. Note that if we modify the URL, we just
|
||||||
// leave the termination characters. This isn't strictly
|
// leave the termination characters. This isn't strictly
|
||||||
// "as-authored", but it makes a bit more sense.
|
// "as-authored", but it makes a bit more sense.
|
||||||
match = this.#sanitizeURL(match);
|
match = this.#sanitizeURL(match);
|
||||||
const urlParts = URL_REGEX.exec(match);
|
const urlParts = URL_REGEX.exec(match);
|
||||||
@@ -2043,21 +2043,14 @@ class OutputParser {
|
|||||||
|
|
||||||
this.#appendTextNode(leader);
|
this.#appendTextNode(leader);
|
||||||
|
|
||||||
let href = url;
|
|
||||||
if (options.baseURI) {
|
|
||||||
try {
|
|
||||||
href = new URL(url, options.baseURI).href;
|
|
||||||
} catch (e) {
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#appendNode(
|
this.#appendNode(
|
||||||
"a",
|
"a",
|
||||||
{
|
{
|
||||||
target: "_blank",
|
target: "_blank",
|
||||||
class: options.urlClass,
|
class: options.urlClass,
|
||||||
href,
|
href: options.baseURI
|
||||||
|
? (URL.parse(url, options.baseURI)?.href ?? url)
|
||||||
|
: url,
|
||||||
},
|
},
|
||||||
body
|
body
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -40,18 +40,19 @@ const windowsDrive = /^([a-zA-Z]:)/;
|
|||||||
|
|
||||||
function resolveSourceURL(sourceURL, targetActor) {
|
function resolveSourceURL(sourceURL, targetActor) {
|
||||||
if (sourceURL) {
|
if (sourceURL) {
|
||||||
try {
|
let baseURL;
|
||||||
let baseURL;
|
if (targetActor.window) {
|
||||||
if (targetActor.window) {
|
baseURL = targetActor.window.location?.href;
|
||||||
baseURL = targetActor.window.location?.href;
|
}
|
||||||
}
|
// For worker, we don't have easy access to location,
|
||||||
// For worker, we don't have easy access to location,
|
// so pull extra information directly from the target actor.
|
||||||
// so pull extra information directly from the target actor.
|
if (targetActor.workerUrl) {
|
||||||
if (targetActor.workerUrl) {
|
baseURL = targetActor.workerUrl;
|
||||||
baseURL = targetActor.workerUrl;
|
}
|
||||||
}
|
const parsedURL = URL.parse(sourceURL, baseURL);
|
||||||
return new URL(sourceURL, baseURL || undefined).href;
|
if (parsedURL) {
|
||||||
} catch (err) {}
|
return parsedURL.href;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function getSourcemapBaseURL(url, global) {
|
|||||||
} else if (global?.location?.href) {
|
} else if (global?.location?.href) {
|
||||||
// If there is no URL for the source, the map comment is relative to the
|
// If there is no URL for the source, the map comment is relative to the
|
||||||
// page being viewed, so we use the document href.
|
// page being viewed, so we use the document href.
|
||||||
sourceMapBaseURL = global?.location?.href;
|
sourceMapBaseURL = global.location.href;
|
||||||
} else {
|
} else {
|
||||||
// If there is no valid base, the sourcemap URL will need to be an absolute
|
// If there is no valid base, the sourcemap URL will need to be an absolute
|
||||||
// URL of some kind.
|
// URL of some kind.
|
||||||
@@ -30,12 +30,11 @@ function getSourcemapBaseURL(url, global) {
|
|||||||
// If the base URL is a blob, we want to resolve relative to the origin
|
// If the base URL is a blob, we want to resolve relative to the origin
|
||||||
// that created the blob URL, if there is one.
|
// that created the blob URL, if there is one.
|
||||||
if (sourceMapBaseURL.startsWith("blob:")) {
|
if (sourceMapBaseURL.startsWith("blob:")) {
|
||||||
try {
|
const parsedBaseURL = URL.parse(sourceMapBaseURL);
|
||||||
const parsedBaseURL = new URL(sourceMapBaseURL);
|
if (parsedBaseURL) {
|
||||||
return parsedBaseURL.origin === "null" ? null : parsedBaseURL.origin;
|
return parsedBaseURL.origin === "null" ? null : parsedBaseURL.origin;
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sourceMapBaseURL;
|
return sourceMapBaseURL;
|
||||||
|
|||||||
@@ -205,17 +205,16 @@ class SourcesManager extends EventEmitter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const url = URL.parse(uri);
|
||||||
const url = new URL(uri);
|
if (url) {
|
||||||
const pathname = url.pathname;
|
const pathname = url.pathname;
|
||||||
return MINIFIED_SOURCE_REGEXP.test(
|
return MINIFIED_SOURCE_REGEXP.test(
|
||||||
pathname.slice(pathname.lastIndexOf("/") + 1)
|
pathname.slice(pathname.lastIndexOf("/") + 1)
|
||||||
);
|
);
|
||||||
} catch (e) {
|
|
||||||
// Not a valid URL so don't try to parse out the filename, just test the
|
|
||||||
// whole thing with the minified source regexp.
|
|
||||||
return MINIFIED_SOURCE_REGEXP.test(uri);
|
|
||||||
}
|
}
|
||||||
|
// Not a valid URL so don't try to parse out the filename, just test the
|
||||||
|
// whole thing with the minified source regexp.
|
||||||
|
return MINIFIED_SOURCE_REGEXP.test(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -865,12 +865,8 @@ exports.WatcherActor = class WatcherActor extends Actor {
|
|||||||
* @param {String} newTargetUrl
|
* @param {String} newTargetUrl
|
||||||
*/
|
*/
|
||||||
async updateDomainSessionDataForServiceWorkers(newTargetUrl) {
|
async updateDomainSessionDataForServiceWorkers(newTargetUrl) {
|
||||||
let host = "";
|
// If the url could not be parsed the host defaults to an empty string.
|
||||||
// Accessing `host` can throw on some URLs with no valid host like about:home.
|
const host = URL.parse(newTargetUrl)?.host ?? "";
|
||||||
// In such scenario, reset the host to an empty string.
|
|
||||||
try {
|
|
||||||
host = new URL(newTargetUrl).host;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
ParentProcessWatcherRegistry.addOrSetSessionDataEntry(
|
ParentProcessWatcherRegistry.addOrSetSessionDataEntry(
|
||||||
this,
|
this,
|
||||||
|
|||||||
@@ -289,13 +289,12 @@ class LegacyServiceWorkersWatcher extends LegacyWorkersWatcher {
|
|||||||
// For local tabs, we match ServiceWorkerRegistrations and the target
|
// For local tabs, we match ServiceWorkerRegistrations and the target
|
||||||
// if they share the same hostname for their "url" properties.
|
// if they share the same hostname for their "url" properties.
|
||||||
const targetDomain = this.#currentTargetURL.hostname;
|
const targetDomain = this.#currentTargetURL.hostname;
|
||||||
try {
|
const registrationDomain = URL.parse(registration.url)?.hostname;
|
||||||
const registrationDomain = new URL(registration.url).hostname;
|
if (registrationDomain) {
|
||||||
return registrationDomain === targetDomain;
|
return registrationDomain === targetDomain;
|
||||||
} catch (e) {
|
|
||||||
// XXX: Some registrations have an empty URL.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
// XXX: Some registrations have an empty URL.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,23 +166,19 @@ exports.shortSource = function (sheet) {
|
|||||||
: dataUrl[1];
|
: dataUrl[1];
|
||||||
} else {
|
} else {
|
||||||
// We try, in turn, the filename, filePath, query string, whole thing
|
// We try, in turn, the filename, filePath, query string, whole thing
|
||||||
let url = {};
|
const url = URL.parse(sheet.href);
|
||||||
try {
|
if (url) {
|
||||||
url = new URL(sheet.href);
|
if (url.pathname) {
|
||||||
} catch (ex) {
|
const index = url.pathname.lastIndexOf("/");
|
||||||
// Some UA-provided stylesheets are not valid URLs.
|
if (index !== -1 && index < url.pathname.length) {
|
||||||
}
|
name = url.pathname.slice(index + 1);
|
||||||
|
} else {
|
||||||
if (url.pathname) {
|
name = url.pathname;
|
||||||
const index = url.pathname.lastIndexOf("/");
|
}
|
||||||
if (index !== -1 && index < url.pathname.length) {
|
} else if (url.query) {
|
||||||
name = url.pathname.slice(index + 1);
|
name = url.query;
|
||||||
} else {
|
|
||||||
name = url.pathname;
|
|
||||||
}
|
}
|
||||||
} else if (url.query) {
|
} // else some UA-provided stylesheets are not valid URLs.
|
||||||
name = url.query;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -9,11 +9,8 @@
|
|||||||
* The initial path must be an full URI with a protocol (i.e. http://).
|
* The initial path must be an full URI with a protocol (i.e. http://).
|
||||||
*/
|
*/
|
||||||
exports.joinURI = (initialPath, ...paths) => {
|
exports.joinURI = (initialPath, ...paths) => {
|
||||||
let url;
|
let url = URL.parse(initialPath);
|
||||||
|
if (!url) {
|
||||||
try {
|
|
||||||
url = new URL(initialPath);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ interface WebExtensionPolicy {
|
|||||||
static WebExtensionPolicy? getByHostname(ByteString hostname);
|
static WebExtensionPolicy? getByHostname(ByteString hostname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currently-active policy for the extension extension URI, or
|
* Returns the currently-active policy for the extension URI, or
|
||||||
* null if the URI is not an extension URI, or no policy is currently active
|
* null if the URI is not an extension URI, or no policy is currently active
|
||||||
* for it.
|
* for it.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -209,16 +209,14 @@ export var ManifestProcessor = {
|
|||||||
expectedType: "string",
|
expectedType: "string",
|
||||||
trim: false,
|
trim: false,
|
||||||
};
|
};
|
||||||
let scopeURL;
|
|
||||||
const startURL = new URL(processedManifest.start_url);
|
const startURL = new URL(processedManifest.start_url);
|
||||||
const defaultScope = new URL(".", startURL).href;
|
const defaultScope = new URL(".", startURL).href;
|
||||||
const value = extractor.extractValue(spec);
|
const value = extractor.extractValue(spec);
|
||||||
if (value === undefined || value === "") {
|
if (value === undefined || value === "") {
|
||||||
return defaultScope;
|
return defaultScope;
|
||||||
}
|
}
|
||||||
try {
|
let scopeURL = URL.parse(value, manifestURL);
|
||||||
scopeURL = new URL(value, manifestURL);
|
if (!scopeURL) {
|
||||||
} catch (e) {
|
|
||||||
const warn = domBundle.GetStringFromName("ManifestScopeURLInvalid");
|
const warn = domBundle.GetStringFromName("ManifestScopeURLInvalid");
|
||||||
errors.push({ warn });
|
errors.push({ warn });
|
||||||
return defaultScope;
|
return defaultScope;
|
||||||
@@ -259,10 +257,8 @@ export var ManifestProcessor = {
|
|||||||
if (value === undefined || value === "") {
|
if (value === undefined || value === "") {
|
||||||
return defaultStartURL;
|
return defaultStartURL;
|
||||||
}
|
}
|
||||||
let potentialResult;
|
let potentialResult = URL.parse(value, manifestURL);
|
||||||
try {
|
if (!potentialResult) {
|
||||||
potentialResult = new URL(value, manifestURL);
|
|
||||||
} catch (e) {
|
|
||||||
const warn = domBundle.GetStringFromName("ManifestStartURLInvalid");
|
const warn = domBundle.GetStringFromName("ManifestStartURLInvalid");
|
||||||
errors.push({ warn });
|
errors.push({ warn });
|
||||||
return defaultStartURL;
|
return defaultStartURL;
|
||||||
@@ -328,10 +324,8 @@ export var ManifestProcessor = {
|
|||||||
return startURL.href;
|
return startURL.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
let appId;
|
let appId = URL.parse(extractedValue, startURL.origin);
|
||||||
try {
|
if (!appId) {
|
||||||
appId = new URL(extractedValue, startURL.origin);
|
|
||||||
} catch {
|
|
||||||
const warn = domBundle.GetStringFromName("ManifestIdIsInvalid");
|
const warn = domBundle.GetStringFromName("ManifestIdIsInvalid");
|
||||||
errors.push({ warn });
|
errors.push({ warn });
|
||||||
return startURL.href;
|
return startURL.href;
|
||||||
|
|||||||
@@ -273,13 +273,11 @@ export class Network extends Domain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve host. Check domain first because it has precedence.
|
// Retrieve host. Check domain first because it has precedence.
|
||||||
let hostname = cookie.domain || "";
|
let hostname = cookie.domain ?? "";
|
||||||
let cookieURL;
|
|
||||||
let schemeType = Ci.nsICookie.SCHEME_UNSET;
|
let schemeType = Ci.nsICookie.SCHEME_UNSET;
|
||||||
if (!hostname.length) {
|
if (!hostname) {
|
||||||
try {
|
let cookieURL = URL.parse(cookie.url);
|
||||||
cookieURL = new URL(cookie.url);
|
if (!cookieURL) {
|
||||||
} catch (e) {
|
|
||||||
return { success: false };
|
return { success: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
|
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
|
||||||
TimedPromise: "chrome://remote/content/marionette/sync.sys.mjs",
|
TimedPromise: "chrome://remote/content/marionette/sync.sys.mjs",
|
||||||
Timeouts: "chrome://remote/content/shared/webdriver/Capabilities.sys.mjs",
|
Timeouts: "chrome://remote/content/shared/webdriver/Capabilities.sys.mjs",
|
||||||
|
truncate: "chrome://remote/content/shared/Format.sys.mjs",
|
||||||
unregisterCommandsActor:
|
unregisterCommandsActor:
|
||||||
"chrome://remote/content/marionette/actors/MarionetteCommandsParent.sys.mjs",
|
"chrome://remote/content/marionette/actors/MarionetteCommandsParent.sys.mjs",
|
||||||
waitForInitialNavigationCompleted:
|
waitForInitialNavigationCompleted:
|
||||||
@@ -1047,11 +1048,13 @@ GeckoDriver.prototype.navigateTo = async function (cmd) {
|
|||||||
);
|
);
|
||||||
await this._handleUserPrompts();
|
await this._handleUserPrompts();
|
||||||
|
|
||||||
let validURL;
|
let { url } = cmd.parameters;
|
||||||
try {
|
|
||||||
validURL = new URL(cmd.parameters.url);
|
let validURL = URL.parse(url);
|
||||||
} catch (e) {
|
if (!validURL) {
|
||||||
throw new lazy.error.InvalidArgumentError(`Malformed URL: ${e.message}`);
|
throw new lazy.error.InvalidArgumentError(
|
||||||
|
lazy.truncate`Expected "url" to be a valid URL, got ${url}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch to the top-level browsing context before navigating
|
// Switch to the top-level browsing context before navigating
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
|
error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
|
||||||
pprint: "chrome://remote/content/shared/Format.sys.mjs",
|
pprint: "chrome://remote/content/shared/Format.sys.mjs",
|
||||||
RemoteAgent: "chrome://remote/content/components/RemoteAgent.sys.mjs",
|
RemoteAgent: "chrome://remote/content/components/RemoteAgent.sys.mjs",
|
||||||
|
truncate: "chrome://remote/content/shared/Format.sys.mjs",
|
||||||
UserPromptHandler:
|
UserPromptHandler:
|
||||||
"chrome://remote/content/shared/webdriver/UserPromptHandler.sys.mjs",
|
"chrome://remote/content/shared/webdriver/UserPromptHandler.sys.mjs",
|
||||||
});
|
});
|
||||||
@@ -277,31 +278,21 @@ export class Proxy {
|
|||||||
throw new lazy.error.InvalidArgumentError(`${host} contains a scheme`);
|
throw new lazy.error.InvalidArgumentError(`${host} contains a scheme`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To parse the host a scheme has to be added temporarily.
|
||||||
|
// If the returned value for the port is an empty string it
|
||||||
|
// could mean no port or the default port for this scheme was
|
||||||
|
// specified. In such a case parse again with a different
|
||||||
|
// scheme to ensure we filter out the default port.
|
||||||
let url;
|
let url;
|
||||||
try {
|
for (let _url of [`http://${host}`, `https://${host}`]) {
|
||||||
// To parse the host a scheme has to be added temporarily.
|
url = URL.parse(_url);
|
||||||
// If the returned value for the port is an empty string it
|
if (!url) {
|
||||||
// could mean no port or the default port for this scheme was
|
throw new lazy.error.InvalidArgumentError(
|
||||||
// specified. In such a case parse again with a different
|
lazy.truncate`Expected "url" to be a valid URL, got ${_url}`
|
||||||
// scheme to ensure we filter out the default port.
|
);
|
||||||
url = new URL("http://" + host);
|
|
||||||
if (url.port == "") {
|
|
||||||
url = new URL("https://" + host);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
if (url.port != "") {
|
||||||
throw new lazy.error.InvalidArgumentError(e.message);
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
let hostname = stripBracketsFromIpv6Hostname(url.hostname);
|
|
||||||
|
|
||||||
// If the port hasn't been set, use the default port of
|
|
||||||
// the selected scheme (except for socks which doesn't have one).
|
|
||||||
let port = parseInt(url.port);
|
|
||||||
if (!Number.isInteger(port)) {
|
|
||||||
if (scheme === "socks") {
|
|
||||||
port = null;
|
|
||||||
} else {
|
|
||||||
port = Services.io.getDefaultPort(scheme);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,6 +308,19 @@ export class Proxy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let hostname = stripBracketsFromIpv6Hostname(url.hostname);
|
||||||
|
|
||||||
|
// If the port hasn't been set, use the default port of
|
||||||
|
// the selected scheme (except for socks which doesn't have one).
|
||||||
|
let port = parseInt(url.port);
|
||||||
|
if (!Number.isInteger(port)) {
|
||||||
|
if (scheme === "socks") {
|
||||||
|
port = null;
|
||||||
|
} else {
|
||||||
|
port = Services.io.getDefaultPort(scheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [hostname, port];
|
return [hostname, port];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -829,7 +829,7 @@ class StorageModule extends RootBiDiModule {
|
|||||||
const hostname = url.hostname;
|
const hostname = url.hostname;
|
||||||
|
|
||||||
const principal = Services.scriptSecurityManager.createContentPrincipal(
|
const principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||||
Services.io.newURI(url),
|
url.URI,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
const isSecureProtocol = principal.isOriginPotentiallyTrustworthy;
|
const isSecureProtocol = principal.isOriginPotentiallyTrustworthy;
|
||||||
|
|||||||
@@ -32,20 +32,17 @@ import { RESTRequest } from "resource://services-common/rest.sys.mjs";
|
|||||||
* @param {String} options.serverURL
|
* @param {String} options.serverURL
|
||||||
* The URL of the profile server to query.
|
* The URL of the profile server to query.
|
||||||
* Example: https://profile.accounts.firefox.com/v1
|
* Example: https://profile.accounts.firefox.com/v1
|
||||||
* @param {String} options.token
|
|
||||||
* The bearer token to access the profile server
|
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export var FxAccountsProfileClient = function (options) {
|
export var FxAccountsProfileClient = function (options) {
|
||||||
if (!options || !options.serverURL) {
|
if (!options?.serverURL) {
|
||||||
throw new Error("Missing 'serverURL' configuration option");
|
throw new Error("Missing 'serverURL' configuration option");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fxai = options.fxai || fxAccounts._internal;
|
this.fxai = options.fxai || fxAccounts._internal;
|
||||||
|
|
||||||
try {
|
this.serverURL = URL.parse(options.serverURL);
|
||||||
this.serverURL = new URL(options.serverURL);
|
if (!this.serverURL) {
|
||||||
} catch (e) {
|
|
||||||
throw new Error("Invalid 'serverURL'");
|
throw new Error("Invalid 'serverURL'");
|
||||||
}
|
}
|
||||||
log.debug("FxAccountsProfileClient: Initialized");
|
log.debug("FxAccountsProfileClient: Initialized");
|
||||||
@@ -53,7 +50,7 @@ export var FxAccountsProfileClient = function (options) {
|
|||||||
|
|
||||||
FxAccountsProfileClient.prototype = {
|
FxAccountsProfileClient.prototype = {
|
||||||
/**
|
/**
|
||||||
* {nsIURI}
|
* {URL}
|
||||||
* The server to fetch profile information from.
|
* The server to fetch profile information from.
|
||||||
*/
|
*/
|
||||||
serverURL: null,
|
serverURL: null,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// sync script tags that could appear between desired meta tags
|
// sync script tags that could appear between desired meta tags
|
||||||
const TIMEOUT_DELAY = 1000;
|
const TIMEOUT_DELAY = 1000;
|
||||||
|
|
||||||
const ACCEPTED_PROTOCOLS = ["http:", "https:"];
|
const ACCEPTED_PROTOCOLS = new Set(["http:", "https:"]);
|
||||||
|
|
||||||
// Possible description tags, listed in order from least favourable to most favourable
|
// Possible description tags, listed in order from least favourable to most favourable
|
||||||
const DESCRIPTION_RULES = [
|
const DESCRIPTION_RULES = [
|
||||||
@@ -51,7 +51,7 @@ function shouldExtractMetadata(aRules, aTag, aEntry) {
|
|||||||
* @returns {Boolean} true if the preview URL is safe and can be stored, false otherwise
|
* @returns {Boolean} true if the preview URL is safe and can be stored, false otherwise
|
||||||
*/
|
*/
|
||||||
function checkLoadURIStr(aURL) {
|
function checkLoadURIStr(aURL) {
|
||||||
if (!ACCEPTED_PROTOCOLS.includes(aURL.protocol)) {
|
if (!ACCEPTED_PROTOCOLS.has(aURL.protocol)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -140,13 +140,11 @@ export class ContentMetaChild extends JSWindowActorChild {
|
|||||||
entry.description.currMaxScore = DESCRIPTION_RULES.indexOf(tag);
|
entry.description.currMaxScore = DESCRIPTION_RULES.indexOf(tag);
|
||||||
} else if (shouldExtractMetadata(PREVIEW_IMAGE_RULES, tag, entry.image)) {
|
} else if (shouldExtractMetadata(PREVIEW_IMAGE_RULES, tag, entry.image)) {
|
||||||
// Extract the preview image
|
// Extract the preview image
|
||||||
let value;
|
let value = URL.parse(content, url);
|
||||||
try {
|
if (!value) {
|
||||||
value = new URL(content, url);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value && checkLoadURIStr(value)) {
|
if (checkLoadURIStr(value)) {
|
||||||
entry.image.value = value.href;
|
entry.image.value = value.href;
|
||||||
entry.image.currMaxScore = PREVIEW_IMAGE_RULES.indexOf(tag);
|
entry.image.currMaxScore = PREVIEW_IMAGE_RULES.indexOf(tag);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -427,10 +427,8 @@ EnterprisePoliciesManager.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
isExemptExecutableExtension(url, extension) {
|
isExemptExecutableExtension(url, extension) {
|
||||||
let urlObject;
|
let urlObject = URL.parse(url);
|
||||||
try {
|
if (!urlObject) {
|
||||||
urlObject = new URL(url);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let { hostname } = urlObject;
|
let { hostname } = urlObject;
|
||||||
|
|||||||
@@ -1101,21 +1101,13 @@ class InjectionContext extends Context {
|
|||||||
*
|
*
|
||||||
* Each method either returns a normalized version of the original
|
* Each method either returns a normalized version of the original
|
||||||
* value, or throws an error if the value is not valid for the given
|
* value, or throws an error if the value is not valid for the given
|
||||||
* format.
|
* format. The original input is always a string.
|
||||||
*/
|
*/
|
||||||
const FORMATS = {
|
const FORMATS = {
|
||||||
hostname(string) {
|
hostname(string) {
|
||||||
// TODO bug 1797376: Despite the name, this format is NOT a "hostname",
|
// TODO bug 1797376: Despite the name, this format is NOT a "hostname",
|
||||||
// but hostname + port and may fail with IPv6. Use canonicalDomain instead.
|
// but hostname + port and may fail with IPv6. Use canonicalDomain instead.
|
||||||
let valid = true;
|
if (URL.parse(`http://${string}`)?.host !== string) {
|
||||||
|
|
||||||
try {
|
|
||||||
valid = new URL(`http://${string}`).host === string;
|
|
||||||
} catch (e) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
throw new Error(`Invalid hostname ${string}`);
|
throw new Error(`Invalid hostname ${string}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1123,15 +1115,7 @@ const FORMATS = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
canonicalDomain(string) {
|
canonicalDomain(string) {
|
||||||
let valid;
|
if (URL.parse(`http://${string}`)?.hostname !== string) {
|
||||||
|
|
||||||
try {
|
|
||||||
valid = new URL(`http://${string}`).hostname === string;
|
|
||||||
} catch (e) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
// Require the input to be a canonical domain.
|
// Require the input to be a canonical domain.
|
||||||
// Rejects obvious non-domains such as URLs,
|
// Rejects obvious non-domains such as URLs,
|
||||||
// but also catches non-IDN (punycode) domains.
|
// but also catches non-IDN (punycode) domains.
|
||||||
@@ -1151,10 +1135,8 @@ const FORMATS = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
origin(string, context) {
|
origin(string, context) {
|
||||||
let url;
|
let url = URL.parse(string);
|
||||||
try {
|
if (!url) {
|
||||||
url = new URL(string);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Invalid origin: ${string}`);
|
throw new Error(`Invalid origin: ${string}`);
|
||||||
}
|
}
|
||||||
if (!/^https?:/.test(url.protocol)) {
|
if (!/^https?:/.test(url.protocol)) {
|
||||||
@@ -1178,9 +1160,7 @@ const FORMATS = {
|
|||||||
if (!context.url) {
|
if (!context.url) {
|
||||||
// If there's no context URL, return relative URLs unresolved, and
|
// If there's no context URL, return relative URLs unresolved, and
|
||||||
// skip security checks for them.
|
// skip security checks for them.
|
||||||
try {
|
if (!URL.canParse(string)) {
|
||||||
new URL(string);
|
|
||||||
} catch (e) {
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1199,12 +1179,8 @@ const FORMATS = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
unresolvedRelativeUrl(string) {
|
unresolvedRelativeUrl(string) {
|
||||||
if (!string.startsWith("//")) {
|
if (!string.startsWith("//") && !URL.canParse(string)) {
|
||||||
try {
|
return string;
|
||||||
new URL(string);
|
|
||||||
} catch (e) {
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new SyntaxError(
|
throw new SyntaxError(
|
||||||
|
|||||||
@@ -45,31 +45,29 @@ this.identity = class extends ExtensionAPI {
|
|||||||
},
|
},
|
||||||
launchWebAuthFlow: function (details) {
|
launchWebAuthFlow: function (details) {
|
||||||
// Validate the url and retreive redirect_uri if it was provided.
|
// Validate the url and retreive redirect_uri if it was provided.
|
||||||
let url, redirectURI;
|
|
||||||
let baseRedirectURL = this.getRedirectURL();
|
let baseRedirectURL = this.getRedirectURL();
|
||||||
|
|
||||||
// Allow using loopback address for native OAuth flows as some
|
// Allow using loopback address for native OAuth flows as some
|
||||||
// providers do not accept the URL provided by getRedirectURL.
|
// providers do not accept the URL provided by getRedirectURL.
|
||||||
// For more context, see bug 1635344.
|
// For more context, see bug 1635344.
|
||||||
let loopbackURL = `http://127.0.0.1/mozoauth2/${computeHash(
|
let loopbackURL = `http://127.0.0.1/mozoauth2/${computeHash(
|
||||||
extension.id
|
extension.id
|
||||||
)}`;
|
)}`;
|
||||||
try {
|
let url = URL.parse(details.url);
|
||||||
url = new URL(details.url);
|
if (!url) {
|
||||||
} catch (e) {
|
|
||||||
return Promise.reject({ message: "details.url is invalid" });
|
return Promise.reject({ message: "details.url is invalid" });
|
||||||
}
|
}
|
||||||
try {
|
let redirectURI = URL.parse(
|
||||||
redirectURI = new URL(
|
url.searchParams.get("redirect_uri") || baseRedirectURL
|
||||||
url.searchParams.get("redirect_uri") || baseRedirectURL
|
);
|
||||||
);
|
if (redirectURI) {
|
||||||
if (
|
if (
|
||||||
!redirectURI.href.startsWith(baseRedirectURL) &&
|
!redirectURI.href.startsWith(baseRedirectURL) &&
|
||||||
!redirectURI.href.startsWith(loopbackURL)
|
!redirectURI.href.startsWith(loopbackURL)
|
||||||
) {
|
) {
|
||||||
return Promise.reject({ message: "redirect_uri not allowed" });
|
return Promise.reject({ message: "redirect_uri not allowed" });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
return Promise.reject({ message: "redirect_uri is invalid" });
|
return Promise.reject({ message: "redirect_uri is invalid" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ const isIPv4 = host => {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isIPv6 = host => host.includes(":");
|
const isIPv6 = host => host.includes(":");
|
||||||
|
|
||||||
const addBracketIfIPv6 = host =>
|
const addBracketIfIPv6 = host =>
|
||||||
isIPv6(host) && !host.startsWith("[") ? `[${host}]` : host;
|
isIPv6(host) && !host.startsWith("[") ? `[${host}]` : host;
|
||||||
|
|
||||||
const dropBracketIfIPv6 = host =>
|
const dropBracketIfIPv6 = host =>
|
||||||
isIPv6(host) && host.startsWith("[") && host.endsWith("]")
|
isIPv6(host) && host.startsWith("[") && host.endsWith("]")
|
||||||
? host.slice(1, -1)
|
? host.slice(1, -1)
|
||||||
@@ -47,13 +50,13 @@ function fromExtPartitionKey(extPartitionKey, cookieUrl) {
|
|||||||
try {
|
try {
|
||||||
// This is subtle! We define the ancestor bit in our code in a different
|
// This is subtle! We define the ancestor bit in our code in a different
|
||||||
// way than the extension API, but they are isomorphic.
|
// way than the extension API, but they are isomorphic.
|
||||||
// If we have cookieUrl (which is guaranteed to be the case in get, set,
|
// If we have cookieUrl (which is guaranteed to be the case in get, set,
|
||||||
// and remove) this will return the topLevelSite parsed partition key,
|
// and remove) this will return the topLevelSite parsed partition key,
|
||||||
// and include the foreign ancestor bit iff the details.url is
|
// and include the foreign ancestor bit iff the details.url is
|
||||||
// same-site and a truthy value was passed in the hasCrossSiteAncestor
|
// same-site and a truthy value was passed in the hasCrossSiteAncestor
|
||||||
// property. If we don't have cookieUrl, we handle the difference in
|
// property. If we don't have cookieUrl, we handle the difference in
|
||||||
// ancestor bit definition by returning a OA pattern that matches both
|
// ancestor bit definition by returning a OA pattern that matches both
|
||||||
// values and filtering them later on in matches.
|
// values and filtering them later on in matches.
|
||||||
if (cookieUrl == null) {
|
if (cookieUrl == null) {
|
||||||
let topLevelSiteURI = Services.io.newURI(topLevelSite);
|
let topLevelSiteURI = Services.io.newURI(topLevelSite);
|
||||||
let topLevelSiteFilter = Services.eTLD.getSite(topLevelSiteURI);
|
let topLevelSiteFilter = Services.eTLD.getSite(topLevelSiteURI);
|
||||||
@@ -399,11 +402,11 @@ const query = function* (detailsIn, props, context, allowPattern) {
|
|||||||
let host;
|
let host;
|
||||||
let url;
|
let url;
|
||||||
if ("url" in details) {
|
if ("url" in details) {
|
||||||
try {
|
url = URL.parse(details.url);
|
||||||
url = new URL(details.url);
|
if (url) {
|
||||||
host = dropBracketIfIPv6(url.hostname);
|
host = dropBracketIfIPv6(url.hostname);
|
||||||
} catch (ex) {
|
} else {
|
||||||
// This often happens for about: URLs
|
// The url could not be parsed successfully
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if ("domain" in details) {
|
} else if ("domain" in details) {
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ this.proxy = class extends ExtensionAPIPersistent {
|
|||||||
extensionApi: self,
|
extensionApi: self,
|
||||||
}).api(),
|
}).api(),
|
||||||
|
|
||||||
// Leaving as non-persistent. By itself it's not useful since proxy-error
|
// Leaving as non-persistent. By itself it's not useful since proxy-error
|
||||||
// is emitted from the proxy filter.
|
// is emitted from the proxy filter.
|
||||||
onError: new EventManager({
|
onError: new EventManager({
|
||||||
context,
|
context,
|
||||||
@@ -283,15 +283,21 @@ this.proxy = class extends ExtensionAPIPersistent {
|
|||||||
for (let prop of ["http", "ssl", "socks"]) {
|
for (let prop of ["http", "ssl", "socks"]) {
|
||||||
let host = value[prop];
|
let host = value[prop];
|
||||||
if (host) {
|
if (host) {
|
||||||
try {
|
let valid = true;
|
||||||
// Fixup in case a full url is passed.
|
// Fixup in case a full url is passed.
|
||||||
if (host.includes("://")) {
|
if (host.includes("://")) {
|
||||||
value[prop] = new URL(host).host;
|
host = URL.parse(host)?.host;
|
||||||
|
if (host) {
|
||||||
|
value[prop] = host;
|
||||||
} else {
|
} else {
|
||||||
// Validate the host value.
|
valid = false;
|
||||||
new URL(`http://${host}`);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
|
// Validate the host value.
|
||||||
|
valid = URL.canParse(`http://${host}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
throw new ExtensionError(
|
throw new ExtensionError(
|
||||||
`${value[prop]} is not a valid value for ${prop}.`
|
`${value[prop]} is not a valid value for ${prop}.`
|
||||||
);
|
);
|
||||||
@@ -300,9 +306,7 @@ this.proxy = class extends ExtensionAPIPersistent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value.proxyType === "autoConfig" || value.autoConfigUrl) {
|
if (value.proxyType === "autoConfig" || value.autoConfigUrl) {
|
||||||
try {
|
if (!URL.canParse(value.autoConfigUrl)) {
|
||||||
new URL(value.autoConfigUrl);
|
|
||||||
} catch (e) {
|
|
||||||
throw new ExtensionError(
|
throw new ExtensionError(
|
||||||
`${value.autoConfigUrl} is not a valid value for autoConfigUrl.`
|
`${value.autoConfigUrl} is not a valid value for autoConfigUrl.`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -358,10 +358,8 @@ this.runtime = class extends ExtensionAPIPersistent {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
let uri;
|
let uri = URL.parse(url);
|
||||||
try {
|
if (!uri) {
|
||||||
uri = new URL(url);
|
|
||||||
} catch (e) {
|
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
message: `Invalid URL: ${JSON.stringify(url)}`,
|
message: `Invalid URL: ${JSON.stringify(url)}`,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -559,16 +559,12 @@ export class URLChecker {
|
|||||||
* @returns {string} - Normalized URL.
|
* @returns {string} - Normalized URL.
|
||||||
*/
|
*/
|
||||||
normalizeLocalhost(url) {
|
normalizeLocalhost(url) {
|
||||||
try {
|
const parsedURL = URL.parse(url);
|
||||||
const parsedURL = new URL(url);
|
if (parsedURL?.hostname === "localhost") {
|
||||||
if (parsedURL.hostname === "localhost") {
|
// Normalize to only scheme and localhost without port or user info
|
||||||
// Normalize to only scheme and localhost without port or user info
|
return `${parsedURL.protocol}//localhost/`;
|
||||||
return `${parsedURL.protocol}//localhost/`;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
} catch (error) {
|
|
||||||
return url;
|
|
||||||
}
|
}
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function sendPageEvent(action, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readOptinParams() {
|
function readOptinParams() {
|
||||||
let searchParams = new URLSearchParams(new URL(location).search);
|
let { searchParams } = new URL(location);
|
||||||
return {
|
return {
|
||||||
slug: searchParams.get("optin_slug"),
|
slug: searchParams.get("optin_slug"),
|
||||||
branch: searchParams.get("optin_branch"),
|
branch: searchParams.get("optin_branch"),
|
||||||
|
|||||||
@@ -93,11 +93,7 @@ export var Heartbeat = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.learnMoreUrl) {
|
if (options.learnMoreUrl) {
|
||||||
try {
|
options.learnMoreUrl = URL.parse(options.learnMoreUrl);
|
||||||
options.learnMoreUrl = new URL(options.learnMoreUrl);
|
|
||||||
} catch (e) {
|
|
||||||
options.learnMoreUrl = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chromeWindow = chromeWindow;
|
this.chromeWindow = chromeWindow;
|
||||||
|
|||||||
@@ -532,13 +532,13 @@ export class LoginManagerParent extends JSWindowActorParent {
|
|||||||
async #getRecipesForHost(origin) {
|
async #getRecipesForHost(origin) {
|
||||||
let recipes;
|
let recipes;
|
||||||
if (origin) {
|
if (origin) {
|
||||||
try {
|
const formHost = URL.parse(origin)?.host;
|
||||||
const formHost = new URL(origin).host;
|
if (!formHost) {
|
||||||
let recipeManager = await LoginManagerParent.recipeParentPromise;
|
|
||||||
recipes = recipeManager.getRecipesForHost(formHost);
|
|
||||||
} catch (ex) {
|
|
||||||
// Some schemes e.g. chrome aren't supported by URL
|
// Some schemes e.g. chrome aren't supported by URL
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
let recipeManager = await LoginManagerParent.recipeParentPromise;
|
||||||
|
recipes = recipeManager.getRecipesForHost(formHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
return recipes ?? [];
|
return recipes ?? [];
|
||||||
|
|||||||
@@ -1867,8 +1867,10 @@ export var Bookmarks = Object.freeze({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (query.url) {
|
if (query.url) {
|
||||||
if (typeof query.url === "string" || URL.isInstance(query.url)) {
|
if (typeof query.url === "string") {
|
||||||
query.url = new URL(query.url).href;
|
query.url = new URL(query.url).href;
|
||||||
|
} else if (URL.isInstance(query.url)) {
|
||||||
|
query.url = query.url.href;
|
||||||
} else if (query.url instanceof Ci.nsIURI) {
|
} else if (query.url instanceof Ci.nsIURI) {
|
||||||
query.url = query.url.spec;
|
query.url = query.url.spec;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1141,10 +1141,8 @@ var fetchAnnotatedPages = async function (db, annotations) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
let uri;
|
let uri = URL.parse(row.getResultByName("url"));
|
||||||
try {
|
if (!uri) {
|
||||||
uri = new URL(row.getResultByName("url"));
|
|
||||||
} catch (ex) {
|
|
||||||
console.error("Invalid URL read from database in fetchAnnotatedPages");
|
console.error("Invalid URL read from database in fetchAnnotatedPages");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,9 @@ function serializeNode(aNode) {
|
|||||||
|
|
||||||
if (PlacesUtils.nodeIsURI(aNode)) {
|
if (PlacesUtils.nodeIsURI(aNode)) {
|
||||||
// Check for url validity.
|
// Check for url validity.
|
||||||
new URL(aNode.uri);
|
if (!URL.canParse(aNode.uri)) {
|
||||||
|
throw new Error(aNode.uri + " is not a valid URL");
|
||||||
|
}
|
||||||
data.type = PlacesUtils.TYPE_X_MOZ_PLACE;
|
data.type = PlacesUtils.TYPE_X_MOZ_PLACE;
|
||||||
data.uri = aNode.uri;
|
data.uri = aNode.uri;
|
||||||
if (aNode.tags) {
|
if (aNode.tags) {
|
||||||
@@ -501,7 +503,7 @@ export var PlacesUtils = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string or n URL object to an nsIURI.
|
* Converts a string or an URL object to an nsIURI.
|
||||||
*
|
*
|
||||||
* @param url (URL) or (String)
|
* @param url (URL) or (String)
|
||||||
* the URL to convert.
|
* the URL to convert.
|
||||||
@@ -1142,33 +1144,31 @@ export var PlacesUtils = {
|
|||||||
if (!uriString) {
|
if (!uriString) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let titleString = "";
|
let uri = null;
|
||||||
if (parts.length > i + 1) {
|
|
||||||
titleString = parts[i + 1];
|
|
||||||
} else {
|
|
||||||
// for drag and drop of files, try to use the leafName as title
|
|
||||||
try {
|
|
||||||
titleString = Services.io
|
|
||||||
.newURI(uriString)
|
|
||||||
.QueryInterface(Ci.nsIURL).fileName;
|
|
||||||
} catch (ex) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let uri = Services.io.newURI(uriString);
|
uri = Services.io.newURI(uriString);
|
||||||
if (uri.scheme != "place") {
|
|
||||||
validNodes.push({
|
|
||||||
uri: uriString,
|
|
||||||
title: titleString ? titleString : uriString,
|
|
||||||
type: this.TYPE_X_MOZ_URL,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
invalidNodes.push({
|
invalidNodes.push({
|
||||||
uri: uriString,
|
uri: uriString,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!uri || uri.scheme == "place") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let titleString = "";
|
||||||
|
if (parts.length > i + 1) {
|
||||||
|
titleString = parts[i + 1];
|
||||||
|
} else if (uri instanceof Ci.nsIURL) {
|
||||||
|
// for drag and drop of files, use the fileName as title
|
||||||
|
titleString = uri.fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
validNodes.push({
|
||||||
|
uri: uriString,
|
||||||
|
title: titleString || uriString,
|
||||||
|
type: this.TYPE_X_MOZ_URL,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1661,10 +1661,9 @@ export var PlacesUtils = {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case PlacesUtils.bookmarks.TYPE_BOOKMARK: {
|
case PlacesUtils.bookmarks.TYPE_BOOKMARK: {
|
||||||
item.type = PlacesUtils.TYPE_X_MOZ_PLACE;
|
item.type = PlacesUtils.TYPE_X_MOZ_PLACE;
|
||||||
// If this throws due to an invalid url, the item will be skipped.
|
// If this fails due to an invalid url, the item will be skipped.
|
||||||
try {
|
item.uri = URL.parse(aRow.getResultByName("url"))?.href;
|
||||||
item.uri = new URL(aRow.getResultByName("url")).href;
|
if (!item.uri) {
|
||||||
} catch (ex) {
|
|
||||||
let error = new Error("Invalid bookmark URL");
|
let error = new Error("Invalid bookmark URL");
|
||||||
error.becauseInvalidURL = true;
|
error.becauseInvalidURL = true;
|
||||||
throw error;
|
throw error;
|
||||||
@@ -2941,14 +2940,15 @@ function promiseKeywordsCache() {
|
|||||||
let brokenKeywords = [];
|
let brokenKeywords = [];
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
let keyword = row.getResultByName("keyword");
|
let keyword = row.getResultByName("keyword");
|
||||||
try {
|
let url = URL.parse(row.getResultByName("url"));
|
||||||
|
if (url) {
|
||||||
let entry = {
|
let entry = {
|
||||||
keyword,
|
keyword,
|
||||||
url: new URL(row.getResultByName("url")),
|
url,
|
||||||
postData: row.getResultByName("post_data") || null,
|
postData: row.getResultByName("post_data") || null,
|
||||||
};
|
};
|
||||||
cache.set(keyword, entry);
|
cache.set(keyword, entry);
|
||||||
} catch (ex) {
|
} else {
|
||||||
// The url is invalid, don't load the keyword and remove it, or it
|
// The url is invalid, don't load the keyword and remove it, or it
|
||||||
// would break the whole keywords API.
|
// would break the whole keywords API.
|
||||||
brokenKeywords.push(keyword);
|
brokenKeywords.push(keyword);
|
||||||
|
|||||||
@@ -363,15 +363,15 @@ export class ReportBrokenSiteChild extends JSWindowActorChild {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// If the user enters a URL unrelated to the current tab,
|
// If the user enters a URL unrelated to the current tab,
|
||||||
// don't bother sending a screnshot or logs/etc
|
// don't bother sending a screenshot or logs/etc
|
||||||
let sendRecordedPageSpecificDetails = false;
|
let sendRecordedPageSpecificDetails = false;
|
||||||
try {
|
const givenUri = URL.parse(reportUrl);
|
||||||
const givenUri = new URL(reportUrl);
|
const recordedUri = URL.parse(url);
|
||||||
const recordedUri = new URL(url);
|
if (givenUri && recordedUri) {
|
||||||
sendRecordedPageSpecificDetails =
|
sendRecordedPageSpecificDetails =
|
||||||
givenUri.origin == recordedUri.origin &&
|
givenUri.origin == recordedUri.origin &&
|
||||||
givenUri.pathname == recordedUri.pathname;
|
givenUri.pathname == recordedUri.pathname;
|
||||||
} catch (_) {}
|
}
|
||||||
|
|
||||||
if (sendRecordedPageSpecificDetails) {
|
if (sendRecordedPageSpecificDetails) {
|
||||||
payload.screenshot = screenshot;
|
payload.screenshot = screenshot;
|
||||||
|
|||||||
@@ -1264,7 +1264,7 @@ export class SearchEngine {
|
|||||||
// path of the URL from search config is not percent encoded. Thus, we
|
// path of the URL from search config is not percent encoded. Thus, we
|
||||||
// convert both strings into URL objects to ensure consistent comparisons.
|
// convert both strings into URL objects to ensure consistent comparisons.
|
||||||
let url1 = new URL(url.template);
|
let url1 = new URL(url.template);
|
||||||
let url2 = new URL(uri.spec);
|
let url2 = URL.fromURI(uri);
|
||||||
if (url1.origin != url2.origin || url1.pathname != url2.pathname) {
|
if (url1.origin != url2.origin || url1.pathname != url2.pathname) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -488,9 +488,8 @@ export class JsonSchemaValidator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
parsedParam = URL.parse(param);
|
||||||
parsedParam = new URL(param);
|
if (parsedParam) {
|
||||||
|
|
||||||
if (parsedParam.protocol == "file:") {
|
if (parsedParam.protocol == "file:") {
|
||||||
// Treat the entire file URL as an origin.
|
// Treat the entire file URL as an origin.
|
||||||
// Note this is stricter than the current Firefox policy,
|
// Note this is stricter than the current Firefox policy,
|
||||||
@@ -509,7 +508,7 @@ export class JsonSchemaValidator {
|
|||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} else {
|
||||||
lazy.log.error(`Ignoring parameter "${param}" - not a valid origin.`);
|
lazy.log.error(`Ignoring parameter "${param}" - not a valid origin.`);
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
@@ -526,10 +525,10 @@ export class JsonSchemaValidator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
parsedParam = URL.parse(param);
|
||||||
parsedParam = new URL(param);
|
if (parsedParam) {
|
||||||
valid = true;
|
valid = true;
|
||||||
} catch (ex) {
|
} else {
|
||||||
if (!param.startsWith("http")) {
|
if (!param.startsWith("http")) {
|
||||||
lazy.log.error(
|
lazy.log.error(
|
||||||
`Ignoring parameter "${param}" - scheme (http or https) must be specified.`
|
`Ignoring parameter "${param}" - scheme (http or https) must be specified.`
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ class ParseError extends Error {
|
|||||||
function parseURL() {
|
function parseURL() {
|
||||||
let options = new URL(document.location.href).searchParams;
|
let options = new URL(document.location.href).searchParams;
|
||||||
|
|
||||||
if (!options) {
|
if (!options.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1276,12 +1276,12 @@ var ActivityStreamProvider = {
|
|||||||
if (options.hideWithSearchParam) {
|
if (options.hideWithSearchParam) {
|
||||||
let [key, value] = options.hideWithSearchParam.split("=");
|
let [key, value] = options.hideWithSearchParam.split("=");
|
||||||
links = links.filter(link => {
|
links = links.filter(link => {
|
||||||
try {
|
let searchParams = URL.parse(link.url)?.searchParams;
|
||||||
let { searchParams } = new URL(link.url);
|
if (searchParams) {
|
||||||
return value === undefined
|
return value === undefined
|
||||||
? !searchParams.has(key)
|
? !searchParams.has(key)
|
||||||
: !searchParams.getAll(key).includes(value);
|
: !searchParams.getAll(key).includes(value);
|
||||||
} catch (error) {}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4981,11 +4981,8 @@ AMTelemetry = {
|
|||||||
* are defined in `AMO_ATTRIBUTION_DATA_KEYS`. Values are strings.
|
* are defined in `AMO_ATTRIBUTION_DATA_KEYS`. Values are strings.
|
||||||
*/
|
*/
|
||||||
parseAttributionDataForAMO(sourceURL) {
|
parseAttributionDataForAMO(sourceURL) {
|
||||||
let searchParams;
|
let searchParams = URL.parse(sourceURL)?.searchParams;
|
||||||
|
if (!searchParams) {
|
||||||
try {
|
|
||||||
searchParams = new URL(sourceURL).searchParams;
|
|
||||||
} catch {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ export class AddonInternal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const [name, uri] of Object.entries({ installFrom, source })) {
|
for (const [name, uri] of Object.entries({ installFrom, source })) {
|
||||||
if (!installOrigins.includes(new URL(uri.spec).origin)) {
|
if (!installOrigins.includes(URL.fromURI(uri).origin)) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`Addon ${this.id} Installation not allowed, ${name} "${uri.spec}" is not included in the Addon install_origins`
|
`Addon ${this.id} Installation not allowed, ${name} "${uri.spec}" is not included in the Addon install_origins`
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user