diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a84784475714..9dd4ff6ff43e 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -704,6 +704,14 @@ nsDocShell::LoadURI(nsDocShellLoadState* aLoadState) { } } + PopupBlocker::PopupControlState popupState; + if (aLoadState->LoadFlags() & LOAD_FLAGS_ALLOW_POPUPS) { + popupState = PopupBlocker::openAllowed; + } else { + popupState = PopupBlocker::openOverridden; + } + AutoPopupStatePusher statePusher(popupState); + if (aLoadState->GetOriginalURIString().isSome()) { // Save URI string in case it's needed later when // sending to search engine service in EndPageLoad() @@ -3819,140 +3827,28 @@ nsDocShell::GotoIndex(int32_t aIndex) { nsresult nsDocShell::LoadURI(const nsAString& aURI, const LoadURIOptions& aLoadURIOptions) { - uint32_t loadFlags = aLoadURIOptions.mLoadFlags; - - NS_ASSERTION((loadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0, - "Unexpected flags"); - if (!IsNavigationAllowed()) { return NS_OK; // JS may not handle returning of an error code } - auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); - mIsNavigating = true; - - nsCOMPtr uri; - nsCOMPtr postData(aLoadURIOptions.mPostData); - nsresult rv = NS_OK; - - NS_ConvertUTF16toUTF8 uriString(aURI); - // Cleanup the empty spaces that might be on each end. - uriString.Trim(" "); - // Eliminate embedded newlines, which single-line text fields now allow: - uriString.StripCRLF(); - NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); - - if (mUseStrictSecurityChecks && !aLoadURIOptions.mTriggeringPrincipal) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr fixupInfo; - if (sURIFixup) { - uint32_t fixupFlags; - rv = sURIFixup->WebNavigationFlagsToFixupFlags(uriString, loadFlags, - &fixupFlags); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - - // If we don't allow keyword lookups for this URL string, make sure to - // update loadFlags to indicate this as well. - if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) { - loadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - } - - nsCOMPtr fixupStream; - rv = sURIFixup->GetFixupURIInfo(uriString, fixupFlags, - getter_AddRefs(fixupStream), - getter_AddRefs(fixupInfo)); - - if (NS_SUCCEEDED(rv)) { - fixupInfo->GetPreferredURI(getter_AddRefs(uri)); - fixupInfo->SetConsumer(GetAsSupports(this)); - } - - if (fixupStream) { - // GetFixupURIInfo only returns a post data stream if it succeeded - // and changed the URI, in which case we should override the - // passed-in post data. - postData = fixupStream; - } - - if (loadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) { - nsCOMPtr serv = services::GetObserverService(); - if (serv) { - serv->NotifyObservers(fixupInfo, "keyword-uri-fixup", - PromiseFlatString(aURI).get()); - } - } - } else { - // No fixup service so just create a URI and see what happens... - rv = NS_NewURI(getter_AddRefs(uri), uriString); - loadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - } + RefPtr loadState; + nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( + GetAsSupports(this), sURIFixup, aURI, aLoadURIOptions, + getter_AddRefs(loadState)); + uint32_t loadFlags = aLoadURIOptions.mLoadFlags; if (NS_ERROR_MALFORMED_URI == rv) { - if (DisplayLoadError(rv, uri, PromiseFlatString(aURI).get(), nullptr) && + if (DisplayLoadError(rv, nullptr, PromiseFlatString(aURI).get(), nullptr) && (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) { return NS_ERROR_LOAD_SHOWED_ERRORPAGE; } } - if (NS_FAILED(rv) || !uri) { + if (NS_FAILED(rv) || !loadState) { return NS_ERROR_FAILURE; } - PopupBlocker::PopupControlState popupState; - if (loadFlags & LOAD_FLAGS_ALLOW_POPUPS) { - popupState = PopupBlocker::openAllowed; - loadFlags &= ~LOAD_FLAGS_ALLOW_POPUPS; - } else { - popupState = PopupBlocker::openOverridden; - } - AutoPopupStatePusher statePusher(popupState); - - bool forceAllowDataURI = loadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI; - - // Don't pass certain flags that aren't needed and end up confusing - // ConvertLoadTypeToDocShellInfoLoadType. We do need to ensure that they are - // passed to LoadURI though, since it uses them. - uint32_t extraFlags = (loadFlags & EXTRA_LOAD_FLAGS); - loadFlags &= ~EXTRA_LOAD_FLAGS; - - RefPtr loadState = new nsDocShellLoadState(uri); - loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo); - - /* - * If the user "Disables Protection on This Page", we have to make sure to - * remember the users decision when opening links in child tabs [Bug 906190] - */ - if (loadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) { - loadState->SetLoadType( - MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, loadFlags)); - } else { - loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)); - } - - loadState->SetLoadFlags(extraFlags); - loadState->SetFirstParty(true); - loadState->SetPostDataStream(postData); - loadState->SetHeadersStream(aLoadURIOptions.mHeaders); - loadState->SetBaseURI(aLoadURIOptions.mBaseURI); - loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal); - loadState->SetCsp(aLoadURIOptions.mCsp); - loadState->SetForceAllowDataURI(forceAllowDataURI); - - if (fixupInfo) { - nsAutoString searchProvider, keyword; - fixupInfo->GetKeywordProviderName(searchProvider); - fixupInfo->GetKeywordAsSent(keyword); - MaybeNotifyKeywordSearchLoading(searchProvider, keyword); - } - rv = LoadURI(loadState); - - // Save URI string in case it's needed later when - // sending to search engine service in EndPageLoad() - mOriginalUriString = uriString; - return rv; } @@ -13505,6 +13401,7 @@ void nsDocShell::NotifyJSRunToCompletionStop() { } } +/* static */ void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, const nsString& aKeyword) { if (aProvider.IsEmpty()) { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index c3e9487e9e70..6338967342ed 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -486,6 +486,10 @@ class nsDocShell final : public nsDocLoader, const nsString* aInitiatorType, uint32_t aLoadType, uint32_t aCacheKey); + // Notify consumers of a search being loaded through the observer service: + static void MaybeNotifyKeywordSearchLoading(const nsString& aProvider, + const nsString& aKeyword); + private: // member functions friend class nsDSURIContentListener; friend class FramingChecker; @@ -956,10 +960,6 @@ class nsDocShell final : public nsDocLoader, // OriginAttributes.mPrivateBrowsingId void AssertOriginAttributesMatchPrivateBrowsing(); - // Notify consumers of a search being loaded through the observer service: - void MaybeNotifyKeywordSearchLoading(const nsString& aProvider, - const nsString& aKeyword); - // Internal implementation of nsIDocShell::FirePageHideNotification. // If aSkipCheckingDynEntries is true, it will not try to remove dynamic // subframe entries. This is to avoid redundant RemoveDynEntries calls in all diff --git a/docshell/base/nsDocShellLoadState.cpp b/docshell/base/nsDocShellLoadState.cpp index 2718abe75a82..d7f33033fbe4 100644 --- a/docshell/base/nsDocShellLoadState.cpp +++ b/docshell/base/nsDocShellLoadState.cpp @@ -11,6 +11,7 @@ #include "nsIWebNavigation.h" #include "nsIChildChannel.h" #include "ReferrerInfo.h" +#include "mozilla/dom/LoadURIOptionsBinding.h" #include "mozilla/OriginAttributes.h" #include "mozilla/NullPrincipal.h" @@ -109,6 +110,142 @@ nsresult nsDocShellLoadState::CreateFromPendingChannel( return NS_OK; } +nsresult nsDocShellLoadState::CreateFromLoadURIOptions( + nsISupports* aConsumer, nsIURIFixup* aURIFixup, const nsAString& aURI, + const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) { + uint32_t loadFlags = aLoadURIOptions.mLoadFlags; + + NS_ASSERTION( + (loadFlags & nsDocShell::INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0, + "Unexpected flags"); + + nsCOMPtr uri; + nsCOMPtr postData(aLoadURIOptions.mPostData); + nsresult rv = NS_OK; + + NS_ConvertUTF16toUTF8 uriString(aURI); + // Cleanup the empty spaces that might be on each end. + uriString.Trim(" "); + // Eliminate embedded newlines, which single-line text fields now allow: + uriString.StripCRLF(); + NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); + + nsCOMPtr fixupInfo; + if (aURIFixup) { + uint32_t fixupFlags; + rv = aURIFixup->WebNavigationFlagsToFixupFlags(uriString, loadFlags, + &fixupFlags); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + // If we don't allow keyword lookups for this URL string, make sure to + // update loadFlags to indicate this as well. + if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) { + loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + } + + nsCOMPtr fixupStream; + rv = aURIFixup->GetFixupURIInfo(uriString, fixupFlags, + getter_AddRefs(fixupStream), + getter_AddRefs(fixupInfo)); + + if (NS_SUCCEEDED(rv)) { + fixupInfo->GetPreferredURI(getter_AddRefs(uri)); + fixupInfo->SetConsumer(aConsumer); + } + + if (fixupStream) { + // GetFixupURIInfo only returns a post data stream if it succeeded + // and changed the URI, in which case we should override the + // passed-in post data. + postData = fixupStream; + } + + if (loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) { + nsCOMPtr serv = services::GetObserverService(); + if (serv) { + serv->NotifyObservers(fixupInfo, "keyword-uri-fixup", + PromiseFlatString(aURI).get()); + } + } + } else { + // No fixup service so just create a URI and see what happens... + rv = NS_NewURI(getter_AddRefs(uri), uriString); + loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + } + + if (rv == NS_ERROR_MALFORMED_URI) { + MOZ_ASSERT(!uri); + return rv; + } + + if (NS_FAILED(rv) || !uri) { + return NS_ERROR_FAILURE; + } + + uint64_t available; + if (postData) { + rv = postData->Available(&available); + NS_ENSURE_SUCCESS(rv, rv); + if (available == 0) { + return NS_ERROR_INVALID_ARG; + } + } + + if (aLoadURIOptions.mHeaders) { + rv = aLoadURIOptions.mHeaders->Available(&available); + NS_ENSURE_SUCCESS(rv, rv); + if (available == 0) { + return NS_ERROR_INVALID_ARG; + } + } + + bool forceAllowDataURI = + loadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_DATA_URI; + + // Don't pass certain flags that aren't needed and end up confusing + // ConvertLoadTypeToDocShellInfoLoadType. We do need to ensure that they are + // passed to LoadURI though, since it uses them. + uint32_t extraFlags = (loadFlags & EXTRA_LOAD_FLAGS); + loadFlags &= ~EXTRA_LOAD_FLAGS; + + RefPtr loadState = new nsDocShellLoadState(uri); + loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo); + + /* + * If the user "Disables Protection on This Page", we have to make sure to + * remember the users decision when opening links in child tabs [Bug 906190] + */ + if (loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_MIXED_CONTENT) { + loadState->SetLoadType( + MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, loadFlags)); + } else { + loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)); + } + + loadState->SetLoadFlags(extraFlags); + loadState->SetFirstParty(true); + loadState->SetPostDataStream(postData); + loadState->SetHeadersStream(aLoadURIOptions.mHeaders); + loadState->SetBaseURI(aLoadURIOptions.mBaseURI); + loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal); + loadState->SetCsp(aLoadURIOptions.mCsp); + loadState->SetForceAllowDataURI(forceAllowDataURI); + loadState->SetOriginalURIString(uriString); + if (aLoadURIOptions.mCancelContentJSEpoch) { + loadState->SetCancelContentJSEpoch(aLoadURIOptions.mCancelContentJSEpoch); + } + + if (fixupInfo) { + nsAutoString searchProvider, keyword; + fixupInfo->GetKeywordProviderName(searchProvider); + fixupInfo->GetKeywordAsSent(keyword); + nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword); + } + + loadState.forget(aResult); + return NS_OK; +} + nsIReferrerInfo* nsDocShellLoadState::GetReferrerInfo() const { return mReferrerInfo; } diff --git a/docshell/base/nsDocShellLoadState.h b/docshell/base/nsDocShellLoadState.h index 67584ccabe73..66ce7503b89f 100644 --- a/docshell/base/nsDocShellLoadState.h +++ b/docshell/base/nsDocShellLoadState.h @@ -41,6 +41,11 @@ class nsDocShellLoadState final { static nsresult CreateFromPendingChannel(nsIChildChannel* aPendingChannel, nsDocShellLoadState** aResult); + static nsresult CreateFromLoadURIOptions( + nsISupports* aConsumer, nsIURIFixup* aURIFixup, const nsAString& aURI, + const mozilla::dom::LoadURIOptions& aLoadURIOptions, + nsDocShellLoadState** aResult); + // Getters and Setters nsIReferrerInfo* GetReferrerInfo() const; diff --git a/docshell/base/nsDocShellLoadTypes.h b/docshell/base/nsDocShellLoadTypes.h index 2c22e6f0204a..e694843b2daf 100644 --- a/docshell/base/nsDocShellLoadTypes.h +++ b/docshell/base/nsDocShellLoadTypes.h @@ -28,8 +28,9 @@ * above 0xffff (e.g. LOAD_FLAGS_BYPASS_CLASSIFIER), since MAKE_LOAD_TYPE would * just shift them out anyway. */ -# define EXTRA_LOAD_FLAGS \ - (LOAD_FLAGS_FIRST_LOAD | LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000) +# define EXTRA_LOAD_FLAGS \ + (nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | \ + nsIWebNavigation::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000) /* load types are legal combinations of load commands and flags *