Bug 1812192 - Address bar should mark navigations that were schemeless r=mak,Gijs,tabbrowser-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D179794
This commit is contained in:
Frederik Braun 2023-10-10 08:42:59 +00:00
parent 2c5cd37344
commit 9301710e8e
6 changed files with 94 additions and 26 deletions

View File

@ -2203,6 +2203,7 @@ var gBrowserInit = {
let globalHistoryOptions = undefined;
let triggeringRemoteType = undefined;
let forceAllowDataURI = false;
let wasSchemelessInput = false;
if (window.arguments[1]) {
if (!(window.arguments[1] instanceof Ci.nsIPropertyBag2)) {
throw new Error(
@ -2241,6 +2242,10 @@ var gBrowserInit = {
forceAllowDataURI =
extraOptions.getPropertyAsBool("forceAllowDataURI");
}
if (extraOptions.hasKey("wasSchemelessInput")) {
wasSchemelessInput =
extraOptions.getPropertyAsBool("wasSchemelessInput");
}
}
try {
@ -2264,6 +2269,7 @@ var gBrowserInit = {
fromExternal,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
});
} catch (e) {
console.error(e);

View File

@ -2590,6 +2590,7 @@
insertTab = true,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
} = {}
) {
// all callers of addTab that pass a params object need to pass
@ -2779,6 +2780,7 @@
csp,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
});
}
@ -3020,6 +3022,7 @@
csp,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
}
) {
if (
@ -3083,6 +3086,7 @@
csp,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
});
} catch (ex) {
console.error(ex);

View File

@ -741,6 +741,9 @@ export class UrlbarInput {
isValidUrl = true;
} catch (ex) {}
if (isValidUrl) {
// Annotate if the untrimmed value contained a scheme, to later potentially
// be upgraded by schemeless HTTPS-First.
openParams.wasSchemelessInput = this.#isSchemeless(this.untrimmedValue);
this._loadURL(url, event, where, openParams);
return;
}
@ -788,13 +791,24 @@ export class UrlbarInput {
if (this.isPrivate) {
flags |= Ci.nsIURIFixup.FIXUP_FLAG_PRIVATE_CONTEXT;
}
let { preferredURI: uri, postData } =
Services.uriFixup.getFixupURIInfo(url, flags);
let {
preferredURI: uri,
postData,
keywordAsSent,
} = Services.uriFixup.getFixupURIInfo(url, flags);
if (
where != "current" ||
browser.lastLocationChange == lastLocationChange
) {
openParams.postData = postData;
if (!keywordAsSent) {
// `uri` is not a search engine url, so we annotate if the untrimmed
// value contained a scheme, to potentially be later upgraded by
// schemeless HTTPS-First.
openParams.wasSchemelessInput = this.#isSchemeless(
this.untrimmedValue
);
}
this._loadURL(uri.spec, event, where, openParams, null, browser);
}
}
@ -992,30 +1006,36 @@ export class UrlbarInput {
switch (result.type) {
case lazy.UrlbarUtils.RESULT_TYPE.URL: {
// Bug 1578856: both the provider and the docshell run heuristics to
// decide how to handle a non-url string, either fixing it to a url, or
// searching for it.
// Some preferences can control the docshell behavior, for example
// if dns_first_for_single_words is true, the docshell looks up the word
// against the dns server, and either loads it as an url or searches for
// it, depending on the lookup result. The provider instead will always
// return a fixed url in this case, because URIFixup is synchronous and
// can't do a synchronous dns lookup. A possible long term solution
// would involve sharing the docshell logic with the provider, along
// with the dns lookup.
// For now, in this specific case, we'll override the result's url
// with the input value, and let it pass through to _loadURL(), and
// finally to the docshell.
// This also means that in some cases the heuristic result will show a
// Visit entry, but the docshell will instead execute a search. It's a
// rare case anyway, most likely to happen for enterprises customizing
// the urifixup prefs.
if (
result.heuristic &&
lazy.UrlbarPrefs.get("browser.fixup.dns_first_for_single_words") &&
lazy.UrlbarUtils.looksLikeSingleWordHost(originalUntrimmedValue)
) {
url = originalUntrimmedValue;
if (result.heuristic) {
// Bug 1578856: both the provider and the docshell run heuristics to
// decide how to handle a non-url string, either fixing it to a url, or
// searching for it.
// Some preferences can control the docshell behavior, for example
// if dns_first_for_single_words is true, the docshell looks up the word
// against the dns server, and either loads it as an url or searches for
// it, depending on the lookup result. The provider instead will always
// return a fixed url in this case, because URIFixup is synchronous and
// can't do a synchronous dns lookup. A possible long term solution
// would involve sharing the docshell logic with the provider, along
// with the dns lookup.
// For now, in this specific case, we'll override the result's url
// with the input value, and let it pass through to _loadURL(), and
// finally to the docshell.
// This also means that in some cases the heuristic result will show a
// Visit entry, but the docshell will instead execute a search. It's a
// rare case anyway, most likely to happen for enterprises customizing
// the urifixup prefs.
if (
lazy.UrlbarPrefs.get("browser.fixup.dns_first_for_single_words") &&
lazy.UrlbarUtils.looksLikeSingleWordHost(originalUntrimmedValue)
) {
url = originalUntrimmedValue;
}
// Annotate if the untrimmed value contained a scheme, to later potentially
// be upgraded by schemeless HTTPS-First.
openParams.wasSchemelessInput = this.#isSchemeless(
originalUntrimmedValue
);
}
break;
}
@ -2718,6 +2738,8 @@ export class UrlbarInput {
* The POST data associated with a search submission.
* @param {boolean} [params.allowInheritPrincipal]
* Whether the principal can be inherited.
* @param {boolean} [params.wasSchemelessInput]
* Whether the search/URL term was without an explicit scheme.
* @param {object} [resultDetails]
* Details of the selected result, if any.
* @param {UrlbarUtils.RESULT_TYPE} [resultDetails.type]
@ -3948,6 +3970,18 @@ export class UrlbarInput {
this._initPasteAndGo();
this._initStripOnShare();
}
/**
* @param {string} value A untrimmed address bar input.
* @returns {boolean}
* `true` if the input doesn't start with a scheme relevant for
* schemeless HTTPS-First (http://, https:// and file://).
*/
#isSchemeless(value) {
return ["http://", "https://", "file://"].every(
scheme => !value.trim().startsWith(scheme)
);
}
}
/**

View File

@ -129,6 +129,12 @@ function openInWindow(url, params, sourceWindow) {
);
}
}
if (params.wasSchemelessInput !== undefined) {
extraOptions.setPropertyAsBool(
"wasSchemelessInput",
params.wasSchemelessInput
);
}
var allowThirdPartyFixupSupports = Cc[
"@mozilla.org/supports-PRBool;1"
@ -260,6 +266,7 @@ function openInCurrentTab(targetBrowser, url, uriObj, params) {
hasValidUserGestureActivation,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
} = params;
targetBrowser.fixupAndLoadURIString(url, {
@ -272,6 +279,7 @@ function openInCurrentTab(targetBrowser, url, uriObj, params) {
hasValidUserGestureActivation,
globalHistoryOptions,
triggeringRemoteType,
wasSchemelessInput,
});
params.resolveOnContentBrowserCreated?.(targetBrowser);
}
@ -363,6 +371,8 @@ export const URILoadingHelper = {
* @param {string} params.charset
* Character set to use for the load. Only honoured for tabs.
* Legacy argument - do not use.
* @param {string} params.wasSchemelessInput
* Whether the search/URL term was without an explicit scheme.
*
* Options relating to security, whether the load is allowed to happen,
* and what cookie container to use for the load:
@ -577,6 +587,7 @@ export const URILoadingHelper = {
openerBrowser: params.openerBrowser,
fromExternal: params.fromExternal,
globalHistoryOptions,
wasSchemelessInput: params.wasSchemelessInput,
});
targetBrowser = tabUsedForLoad.linkedBrowser;

View File

@ -384,6 +384,7 @@ URIFixup.prototype = {
if (uriWithProtocol) {
info.fixedURI = uriWithProtocol;
info.fixupChangedProtocol = true;
info.wasSchemelessInput = true;
maybeSetAlternateFixedURI(info, fixupFlags);
info.preferredURI = info.fixedURI;
// Check if it's a forced visit. The user can enforce a visit by
@ -686,6 +687,13 @@ URIFixupInfo.prototype = {
return this._keywordAsSent || "";
},
set wasSchemelessInput(changed) {
this._wasSchemelessInput = changed;
},
get wasSchemelessInput() {
return !!this._wasSchemelessInput;
},
set fixupChangedProtocol(changed) {
this._fixupChangedProtocol = changed;
},

View File

@ -49,6 +49,11 @@ interface nsIURIFixupInfo : nsISupports
*/
attribute AString keywordAsSent;
/**
* Whether there was no protocol at all and we had to add one in the first place.
*/
attribute boolean wasSchemelessInput;
/**
* Whether we changed the protocol instead of using one from the input as-is.
*/