diff options
Diffstat (limited to 'dom/base/Document.cpp')
-rw-r--r-- | dom/base/Document.cpp | 156 |
1 files changed, 103 insertions, 53 deletions
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 4e9286a91e..8cbf8b8075 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -172,6 +172,8 @@ #include "mozilla/dom/FeaturePolicy.h" #include "mozilla/dom/FeaturePolicyUtils.h" #include "mozilla/dom/FontFaceSet.h" +#include "mozilla/dom/FragmentDirective.h" +#include "mozilla/dom/fragmentdirectives_ffi_generated.h" #include "mozilla/dom/FromParser.h" #include "mozilla/dom/HighlightRegistry.h" #include "mozilla/dom/HTMLAllCollection.h" @@ -198,6 +200,7 @@ #include "mozilla/dom/NetErrorInfoBinding.h" #include "mozilla/dom/NodeInfo.h" #include "mozilla/dom/NodeIterator.h" +#include "mozilla/dom/nsHTTPSOnlyUtils.h" #include "mozilla/dom/PContentChild.h" #include "mozilla/dom/PWindowGlobalChild.h" #include "mozilla/dom/PageTransitionEvent.h" @@ -1437,7 +1440,6 @@ Document::Document(const char* aContentType) mThrowOnDynamicMarkupInsertionCounter(0), mIgnoreOpensDuringUnloadCounter(0), mSavedResolution(1.0f), - mSavedResolutionBeforeMVM(1.0f), mGeneration(0), mCachedTabSizeGeneration(0), mNextFormNumber(0), @@ -2484,6 +2486,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReadyForIdle) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentL10n) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFragmentDirective) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHighlightRegistry) // Traverse all Document nsCOMPtrs. @@ -2631,6 +2634,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document) NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet) NS_IMPL_CYCLE_COLLECTION_UNLINK(mReadyForIdle) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentL10n) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mFragmentDirective) NS_IMPL_CYCLE_COLLECTION_UNLINK(mHighlightRegistry) NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOnloadBlocker) @@ -4065,6 +4069,21 @@ void Document::StopDocumentLoad() { void Document::SetDocumentURI(nsIURI* aURI) { nsCOMPtr<nsIURI> oldBase = GetDocBaseURI(); mDocumentURI = aURI; + // This loosely implements ยง3.4.1 of Text Fragments + // https://wicg.github.io/scroll-to-text-fragment/#invoking-text-directives + // Unlike specified in the spec, the fragment directive is not stripped from + // the URL in the session history entry. Instead it is removed when the URL is + // set in the `Document`. Also, instead of storing the `uninvokedDirective` in + // `Document` as mentioned in the spec, the extracted directives are moved to + // the `FragmentDirective` object which deals with finding the ranges to + // highlight in `ScrollToRef()`. + // XXX(:jjaschke): This is only a temporary solution. + // https://bugzil.la/1881429 is filed for revisiting this. + nsTArray<TextDirective> textDirectives; + FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragment( + mDocumentURI, &textDirectives); + FragmentDirective()->SetTextDirectives(std::move(textDirectives)); + nsIURI* newBase = GetDocBaseURI(); mChromeRulesEnabled = URLExtraData::ChromeRulesEnabled(aURI); @@ -4103,10 +4122,11 @@ void Document::SetDocumentURI(nsIURI* aURI) { } } -static void GetFormattedTimeString(PRTime aTime, +static void GetFormattedTimeString(PRTime aTime, bool aUniversal, nsAString& aFormattedTimeString) { PRExplodedTime prtime; - PR_ExplodeTime(aTime, PR_LocalTimeParameters, &prtime); + PR_ExplodeTime(aTime, aUniversal ? PR_GMTParameters : PR_LocalTimeParameters, + &prtime); // "MM/DD/YYYY hh:mm:ss" char formatedTime[24]; if (SprintfLiteral(formatedTime, "%02d/%02d/%04d %02d:%02d:%02d", @@ -4124,7 +4144,9 @@ void Document::GetLastModified(nsAString& aLastModified) const { if (!mLastModified.IsEmpty()) { aLastModified.Assign(mLastModified); } else { - GetFormattedTimeString(PR_Now(), aLastModified); + GetFormattedTimeString(PR_Now(), + ShouldResistFingerprinting(RFPTarget::JSDateTimeUTC), + aLastModified); } } @@ -6401,7 +6423,7 @@ void Document::SetLastFocusTime(const TimeStamp& aFocusTime) { mLastFocusTime = aFocusTime; } -void Document::GetReferrer(nsAString& aReferrer) const { +void Document::GetReferrer(nsACString& aReferrer) const { aReferrer.Truncate(); if (!mReferrerInfo) { return; @@ -6412,13 +6434,7 @@ void Document::GetReferrer(nsAString& aReferrer) const { return; } - nsAutoCString uri; - nsresult rv = URLDecorationStripper::StripTrackingIdentifiers(referrer, uri); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - CopyUTF8toUTF16(uri, aReferrer); + URLDecorationStripper::StripTrackingIdentifiers(referrer, aReferrer); } void Document::GetCookie(nsAString& aCookie, ErrorResult& aRv) { @@ -7683,6 +7699,10 @@ static void NotifyActivityChangedCallback(nsISupports* aSupports) { void Document::NotifyActivityChanged() { EnumerateActivityObservers(NotifyActivityChangedCallback); + // https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-full-activity + if (!IsActive()) { + UnlockAllWakeLocks(WakeLockType::Screen); + } } void Document::SetContainer(nsDocShell* aContainer) { @@ -11111,7 +11131,9 @@ void Document::RetrieveRelevantHeaders(nsIChannel* aChannel) { mLastModified.Truncate(); if (modDate != 0) { - GetFormattedTimeString(modDate, mLastModified); + GetFormattedTimeString(modDate, + ShouldResistFingerprinting(RFPTarget::JSDateTimeUTC), + mLastModified); } } @@ -12537,14 +12559,6 @@ void Document::UpdateDocumentStates(DocumentState aMaybeChangedStates, } } - if (aMaybeChangedStates.HasAtLeastOneOfStates(DocumentState::LWTHEME)) { - if (ComputeDocumentLWTheme()) { - mState |= DocumentState::LWTHEME; - } else { - mState &= ~DocumentState::LWTHEME; - } - } - if (aMaybeChangedStates.HasState(DocumentState::WINDOW_INACTIVE)) { BrowsingContext* bc = GetBrowsingContext(); if (!bc || !bc->GetIsActiveBrowserWindow()) { @@ -13089,25 +13103,29 @@ void Document::SetScrollToRef(nsIURI* aDocumentURI) { // https://html.spec.whatwg.org/#scrolling-to-a-fragment void Document::ScrollToRef() { - if (mScrolledToRefAlready) { - RefPtr<PresShell> presShell = GetPresShell(); - if (presShell) { - presShell->ScrollToAnchor(); - } + RefPtr<PresShell> presShell = GetPresShell(); + if (!presShell) { return; } - - // 2. If fragment is the empty string, then return the special value top of - // the document. - if (mScrollToRef.IsEmpty()) { + if (mScrolledToRefAlready) { + presShell->ScrollToAnchor(); return; } - RefPtr<PresShell> presShell = GetPresShell(); - if (!presShell) { + // If text directives is non-null, then highlight the text directives and + // scroll to the last one. + // XXX(:jjaschke): Document policy integration should happen here + // as soon as https://bugzil.la/1860915 lands. + // XXX(:jjaschke): Same goes for User Activation and security aspects, + // tracked in https://bugzil.la/1888756. + const bool didScrollToTextFragment = + presShell->HighlightAndGoToTextFragment(true); + + // 2. If fragment is the empty string and no text directives have been + // scrolled to, then return the special value top of the document. + if (didScrollToTextFragment || mScrollToRef.IsEmpty()) { return; } - // 3. Let potentialIndicatedElement be the result of finding a potential // indicated element given document and fragment. NS_ConvertUTF8toUTF16 ref(mScrollToRef); @@ -15089,11 +15107,6 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint, } while (repeatingHide); } -MOZ_CAN_RUN_SCRIPT_BOUNDARY void -Document::HideAllPopoversWithoutRunningScript() { - return HideAllPopoversUntil(*this, false, false); -} - void Document::HidePopover(Element& aPopover, bool aFocusPreviousElement, bool aFireEvents, ErrorResult& aRv) { RefPtr<nsGenericHTMLElement> popoverHTMLEl = @@ -15548,13 +15561,21 @@ bool Document::HasPendingFullscreenRequests() { return !iter.AtEnd(); } +MOZ_CAN_RUN_SCRIPT_BOUNDARY bool Document::ApplyFullscreen(UniquePtr<FullscreenRequest> aRequest) { if (!FullscreenElementReadyCheck(*aRequest)) { return false; } + Element* elem = aRequest->Element(); + + RefPtr<nsINode> hideUntil = elem->GetTopmostPopoverAncestor(nullptr, false); + if (!hideUntil) { + hideUntil = OwnerDoc(); + } + RefPtr<Document> doc = aRequest->Document(); - doc->HideAllPopoversWithoutRunningScript(); + doc->HideAllPopoversUntil(*hideUntil, false, true); // Stash a reference to any existing fullscreen doc, we'll use this later // to detect if the origin which is fullscreen has changed. @@ -15580,7 +15601,6 @@ bool Document::ApplyFullscreen(UniquePtr<FullscreenRequest> aRequest) { // Set the fullscreen element. This sets the fullscreen style on the // element, and the fullscreen-ancestor styles on ancestors of the element // in this document. - Element* elem = aRequest->Element(); SetFullscreenElement(*elem); // Set the iframe fullscreen flag. if (auto* iframe = HTMLIFrameElement::FromNode(elem)) { @@ -15698,6 +15718,11 @@ void Document::UpdateVisibilityState(DispatchVisibilityChange aDispatchEvent) { for (auto* listener : mWorkerListeners) { listener->OnVisible(visible); } + + // https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-visibility + if (!visible) { + UnlockAllWakeLocks(WakeLockType::Screen); + } } } @@ -16558,16 +16583,6 @@ void Document::SetStateObject(nsIStructuredCloneContainer* scContainer) { mCachedStateObjectValid = false; } -bool Document::ComputeDocumentLWTheme() const { - if (!NodePrincipal()->IsSystemPrincipal()) { - return false; - } - - Element* element = GetRootElement(); - return element && element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::lwtheme, - nsGkAtoms::_true, eCaseMatters); -} - already_AddRefed<Element> Document::CreateHTMLElement(nsAtom* aTag) { RefPtr<mozilla::dom::NodeInfo> nodeInfo; nodeInfo = mNodeInfoManager->GetNodeInfo(aTag, nullptr, kNameSpaceID_XHTML, @@ -17525,6 +17540,18 @@ Document::CreatePermissionGrantPromise( p = new StorageAccessAPIHelper::StorageAccessPermissionGrantPromise:: Private(__func__); + // Before we prompt, see if we are same-site + if (aFrameOnly) { + nsIChannel* channel = self->GetChannel(); + if (channel) { + nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); + if (!loadInfo->GetIsThirdPartyContextToTopWindow()) { + p->Resolve(StorageAccessAPIHelper::eAllow, __func__); + return p; + } + } + } + RefPtr<PWindowGlobalChild::GetStorageAccessPermissionPromise> promise; // Test the permission MOZ_ASSERT(XRE_IsContentProcess()); @@ -18357,9 +18384,13 @@ class UnlockAllWakeLockRunnable final : public Runnable { void Document::UnlockAllWakeLocks(WakeLockType aType) { // Perform unlock in a runnable to prevent UnlockAll being MOZ_CAN_RUN_SCRIPT - RefPtr<UnlockAllWakeLockRunnable> runnable = - MakeRefPtr<UnlockAllWakeLockRunnable>(aType, this); - NS_DispatchToMainThread(runnable); + if (!ActiveWakeLocks(aType).IsEmpty()) { + RefPtr<UnlockAllWakeLockRunnable> runnable = + MakeRefPtr<UnlockAllWakeLockRunnable>(aType, this); + nsresult rv = NS_DispatchToMainThread(runnable); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + Unused << rv; + } } RefPtr<Document::AutomaticStorageAccessPermissionGrantPromise> @@ -18637,12 +18668,24 @@ nsICookieJarSettings* Document::CookieJarSettings() { net::CookieJarSettings::Cast(mCookieJarSettings) ->SetFingerprintingRandomizationKey(randomKey); } + + // Inerit the top level windowContext id from the parent. + net::CookieJarSettings::Cast(mCookieJarSettings) + ->SetTopLevelWindowContextId( + net::CookieJarSettings::Cast(inProcessParent->CookieJarSettings()) + ->GetTopLevelWindowContextId()); } else { mCookieJarSettings = net::CookieJarSettings::Create(NodePrincipal()); + + if (IsTopLevelContentDocument()) { + net::CookieJarSettings::Cast(mCookieJarSettings) + ->SetTopLevelWindowContextId(InnerWindowID()); + } } if (auto* wgc = GetWindowGlobalChild()) { net::CookieJarSettingsArgs csArgs; + net::CookieJarSettings::Cast(mCookieJarSettings)->Serialize(csArgs); // Update cookie settings in the parent process if (!wgc->SendUpdateCookieJarSettings(csArgs)) { @@ -19042,6 +19085,13 @@ HighlightRegistry& Document::HighlightRegistry() { return *mHighlightRegistry; } +FragmentDirective* Document::FragmentDirective() { + if (!mFragmentDirective) { + mFragmentDirective = MakeRefPtr<class FragmentDirective>(this); + } + return mFragmentDirective; +} + RadioGroupContainer& Document::OwnedRadioGroupContainer() { if (!mRadioGroupContainer) { mRadioGroupContainer = MakeUnique<RadioGroupContainer>(); |