Bug 1810141 - make docshell/nsIWebNavigation's loadURI actually take a URI object rather than a string, r=nika

Depends on D168390

Differential Revision: https://phabricator.services.mozilla.com/D168391
This commit is contained in:
Gijs Kruitbosch 2023-02-13 12:55:23 +00:00
parent e460aa10f3
commit 60d67bb0ad
7 changed files with 184 additions and 68 deletions

View File

@ -3399,22 +3399,50 @@ nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
return rv.StealNSResult();
}
nsresult nsDocShell::LoadURI(const nsAString& aURI,
nsresult nsDocShell::LoadURI(nsIURI* aURI,
const LoadURIOptions& aLoadURIOptions) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
RefPtr<nsDocShellLoadState> loadState;
nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
MOZ_ASSERT(rv != NS_ERROR_MALFORMED_URI);
if (NS_FAILED(rv) || !loadState) {
return NS_ERROR_FAILURE;
}
return LoadURI(loadState, true);
}
NS_IMETHODIMP
nsDocShell::LoadURIFromScript(nsIURI* aURI,
JS::Handle<JS::Value> aLoadURIOptions,
JSContext* aCx) {
// generate dictionary for aLoadURIOptions and forward call
LoadURIOptions loadURIOptions;
if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
return NS_ERROR_INVALID_ARG;
}
return LoadURI(aURI, loadURIOptions);
}
nsresult nsDocShell::FixupAndLoadURIString(
const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
RefPtr<nsDocShellLoadState> loadState;
nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
if (NS_ERROR_MALFORMED_URI == rv) {
MOZ_LOG(gSHLog, LogLevel::Debug,
("Creating an active entry on nsDocShell %p to %s (because "
"we're showing an error page)",
this, NS_ConvertUTF16toUTF8(aURI).get()));
this, NS_ConvertUTF16toUTF8(aURIString).get()));
// We need to store a session history entry. We don't have a valid URI, so
// we use about:blank instead.
@ -3434,7 +3462,8 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags),
/* aUpdatedCacheKey = */ 0);
}
if (DisplayLoadError(rv, nullptr, PromiseFlatString(aURI).get(), nullptr) &&
if (DisplayLoadError(rv, nullptr, PromiseFlatString(aURIString).get(),
nullptr) &&
(loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
}
@ -3448,15 +3477,15 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
}
NS_IMETHODIMP
nsDocShell::LoadURIFromScript(const nsAString& aURI,
JS::Handle<JS::Value> aLoadURIOptions,
JSContext* aCx) {
nsDocShell::FixupAndLoadURIStringFromScript(
const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
JSContext* aCx) {
// generate dictionary for aLoadURIOptions and forward call
LoadURIOptions loadURIOptions;
if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
return NS_ERROR_INVALID_ARG;
}
return LoadURI(aURI, loadURIOptions);
return FixupAndLoadURIString(aURIString, loadURIOptions);
}
void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {

View File

@ -966,7 +966,7 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
nsCOMPtr<nsIContentSecurityPolicy> csp;
handler->GetCsp(dragEvent, getter_AddRefs(csp));
loadURIOptions.mCsp = csp;
webnav->LoadURI(url, loadURIOptions);
webnav->FixupAndLoadURIString(url, loadURIOptions);
}
}
}

View File

@ -275,24 +275,53 @@ interface nsIWebNavigation : nsISupports
* loading.
*
* @param aURI
* The URI string to load. For HTTP and FTP URLs and possibly others,
* characters above U+007F will be converted to UTF-8 and then URL-
* escaped per the rules of RFC 2396.
* The URI to load.
* @param aLoadURIOptions
* A JSObject defined in LoadURIOptions.webidl holding info like e.g.
* the triggeringPrincipal, the referrer info.
*/
[implicit_jscontext, binaryname(LoadURIFromScript)]
void loadURI(in AString aURI,
in jsval aLoadURIOptions);
void loadURI(in nsIURI aURI,
in jsval aLoadURIOptions);
/**
* Parse / fix up a URI out of the string and load it.
* This will give priority to loading the requested URI
* in the object implementing this interface. If it can't be loaded here
* however, the URI dispatcher will go through its normal process of content
* loading.
*
* @param aURIString
* The URI string to load. For HTTP and FTP URLs and possibly others,
* characters above U+007F will be converted to UTF-8 and then URL-
* escaped per the rules of RFC 2396.
* This method may use nsIURIFixup to try to fix up typos etc. in the
* input string based on the load flag arguments in aLoadURIOptions.
* It can even convert the input to a search results page using the
* default search service.
* If you have an nsIURI anyway, prefer calling `loadURI`, above.
* @param aLoadURIOptions
* A JSObject defined in LoadURIOptions.webidl holding info like e.g.
* the triggeringPrincipal, the referrer info.
*/
[implicit_jscontext, binaryname(FixupAndLoadURIStringFromScript)]
void fixupAndLoadURIString(in AString aURIString,
in jsval aLoadURIOptions);
/**
* A C++ friendly version of loadURI
*/
[nostdcall, binaryname(LoadURI)]
void binaryLoadURI(in AString aURI,
void binaryLoadURI(in nsIURI aURI,
in LoadURIOptionsRef aLoadURIOptions);
/**
* A C++ friendly version of fixupAndLoadURIString
*/
[nostdcall, binaryname(FixupAndLoadURIString)]
void binaryFixupAndLoadURIString(in AString aURIString,
in LoadURIOptionsRef aLoadURIOptions);
/**
* Tells the Object to reload the current page. There may be cases where the
* user will be asked to confirm the reload (for example, when it is

View File

@ -917,7 +917,9 @@ void nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure) {
LoadURIOptions loadURIOptions;
loadURIOptions.mTriggeringPrincipal =
nsContentUtils::GetSystemPrincipal();
webNav->LoadURI(u"about:blank"_ns, loadURIOptions);
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns));
webNav->LoadURI(uri, loadURIOptions);
}
}
}

View File

@ -469,7 +469,7 @@ nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
return mDocShell->GoForward(aRequireUserInteraction, aUserActivation);
}
nsresult nsWebBrowser::LoadURI(const nsAString& aURI,
nsresult nsWebBrowser::LoadURI(nsIURI* aURI,
const dom::LoadURIOptions& aLoadURIOptions) {
#ifndef ANDROID
MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal,
@ -481,7 +481,7 @@ nsresult nsWebBrowser::LoadURI(const nsAString& aURI,
}
NS_IMETHODIMP
nsWebBrowser::LoadURIFromScript(const nsAString& aURI,
nsWebBrowser::LoadURIFromScript(nsIURI* aURI,
JS::Handle<JS::Value> aLoadURIOptions,
JSContext* aCx) {
// generate dictionary for loadURIOptions and forward call
@ -492,6 +492,30 @@ nsWebBrowser::LoadURIFromScript(const nsAString& aURI,
return LoadURI(aURI, loadURIOptions);
}
nsresult nsWebBrowser::FixupAndLoadURIString(
const nsAString& aURI, const dom::LoadURIOptions& aLoadURIOptions) {
#ifndef ANDROID
MOZ_ASSERT(
aLoadURIOptions.mTriggeringPrincipal,
"nsWebBrowser::FixupAndLoadURIString - Need a valid triggeringPrincipal");
#endif
NS_ENSURE_STATE(mDocShell);
return mDocShell->FixupAndLoadURIString(aURI, aLoadURIOptions);
}
NS_IMETHODIMP
nsWebBrowser::FixupAndLoadURIStringFromScript(
const nsAString& aURI, JS::Handle<JS::Value> aLoadURIOptions,
JSContext* aCx) {
// generate dictionary for loadURIOptions and forward call
dom::LoadURIOptions loadURIOptions;
if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
return NS_ERROR_INVALID_ARG;
}
return FixupAndLoadURIString(aURI, loadURIOptions);
}
NS_IMETHODIMP
nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier,
int32_t aHistoryIndex) {

View File

@ -74,29 +74,18 @@ class RemoteWebNavigation {
);
this._browser.browsingContext.goToIndex(aIndex, cancelContentJSEpoch, true);
}
loadURI(aURI, aLoadURIOptions) {
let uri;
_speculativeConnect(uri, loadURIOptions) {
try {
let fixupFlags = Services.uriFixup.webNavigationFlagsToFixupFlags(
aURI,
aLoadURIOptions.loadFlags
);
let isBrowserPrivate = lazy.PrivateBrowsingUtils.isBrowserPrivate(
this._browser
);
if (isBrowserPrivate) {
fixupFlags |= Services.uriFixup.FIXUP_FLAG_PRIVATE_CONTEXT;
}
uri = Services.uriFixup.getFixupURIInfo(aURI, fixupFlags).preferredURI;
// We know the url is going to be loaded, let's start requesting network
// connection before the content process asks.
// Note that we might have already setup the speculative connection in
// Let's start a network connection before the content process asks.
// Note that we might have already set up the speculative connection in
// some cases, especially when the url is from location bar or its popup
// menu.
if (uri.schemeIs("http") || uri.schemeIs("https")) {
let principal = aLoadURIOptions.triggeringPrincipal;
let isBrowserPrivate = lazy.PrivateBrowsingUtils.isBrowserPrivate(
this._browser
);
let principal = loadURIOptions.triggeringPrincipal;
// We usually have a triggeringPrincipal assigned, but in case we
// don't have one or if it's a SystemPrincipal, let's create it with OA
// inferred from the current context.
@ -113,19 +102,61 @@ class RemoteWebNavigation {
Services.io.speculativeConnect(uri, principal, null);
}
} catch (ex) {
// Can't setup speculative connection for this uri string for some
// reason (such as failing to parse the URI), just ignore it.
// Can't setup speculative connection for this uri for some
// reason, just ignore it.
}
}
loadURI(uri, loadURIOptions) {
this._speculativeConnect(uri, loadURIOptions);
let cancelContentJSEpoch = this.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_URL,
{ uri }
);
this._browser.browsingContext.fixupAndLoadURIString(aURI, {
...aLoadURIOptions,
this._browser.browsingContext.loadURI(uri, {
...loadURIOptions,
cancelContentJSEpoch,
});
}
fixupAndLoadURIString(uriString, loadURIOptions) {
let uri;
try {
let fixupFlags = Services.uriFixup.webNavigationFlagsToFixupFlags(
uriString,
loadURIOptions.loadFlags
);
let isBrowserPrivate = lazy.PrivateBrowsingUtils.isBrowserPrivate(
this._browser
);
if (isBrowserPrivate) {
fixupFlags |= Services.uriFixup.FIXUP_FLAG_PRIVATE_CONTEXT;
}
uri = Services.uriFixup.getFixupURIInfo(uriString, fixupFlags)
.preferredURI;
} catch (ex) {
// In rare cases `uriFixup` can throw. We ignore this here, but it's
// likely that the fixupAndLoadURIString call below will still throw,
// hopefully with more details.
}
if (uri) {
this._speculativeConnect(uri, loadURIOptions);
}
// For now, continue to use fixup here, but note that ideally we should be
// doing fixup only once and reusing the URI we created above. Addressing
// this is bug 1815509.
let cancelContentJSEpoch = this.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_URL,
{ uri: null }
);
this._browser.browsingContext.fixupAndLoadURIString(uriString, {
...loadURIOptions,
cancelContentJSEpoch,
});
}
reload(aReloadFlags) {
this._browser.browsingContext.reload(aReloadFlags);
}

View File

@ -29,6 +29,10 @@
SelectParentHelper: "resource://gre/actors/SelectParent.jsm",
});
XPCOMUtils.defineLazyGetter(lazy, "blankURI", () =>
Services.io.newURI("about:blank")
);
let lazyPrefs = {};
XPCOMUtils.defineLazyPreferenceGetter(
lazyPrefs,
@ -812,38 +816,35 @@
this.webNavigation.stop(flags);
}
_fixLoadParamsToLoadURIOptions(params) {
let loadFlags =
params.loadFlags || params.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
delete params.flags;
params.loadFlags = loadFlags;
}
/**
* throws exception for unknown schemes
*/
loadURI(aURI, aParams = {}) {
if (!aURI) {
aURI = "about:blank";
loadURI(uri, params = {}) {
if (!uri) {
uri = lazy.blankURI;
}
let {
referrerInfo,
triggeringPrincipal,
triggeringRemoteType,
postData,
headers,
csp,
remoteTypeOverride,
} = aParams;
let loadFlags =
aParams.loadFlags ||
aParams.flags ||
Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let loadURIOptions = {
triggeringPrincipal,
triggeringRemoteType,
csp,
referrerInfo,
loadFlags,
postData,
headers,
remoteTypeOverride,
};
this._fixLoadParamsToLoadURIOptions(params);
this._wrapURIChangeCall(() => this.webNavigation.loadURI(uri, params));
}
/**
* throws exception for unknown schemes
*/
fixupAndLoadURIString(uriString, params = {}) {
if (!uriString) {
this.loadURI(null, params);
return;
}
this._fixLoadParamsToLoadURIOptions(params);
this._wrapURIChangeCall(() =>
this.webNavigation.loadURI(aURI, loadURIOptions)
this.webNavigation.fixupAndLoadURIString(uriString, params)
);
}