summaryrefslogtreecommitdiffstats
path: root/dom/base/Document.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/Document.cpp')
-rw-r--r--dom/base/Document.cpp156
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>();