WindowContext.h (20323B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_WindowContext_h 8 #define mozilla_dom_WindowContext_h 9 10 #include "mozilla/PermissionDelegateHandler.h" 11 #include "mozilla/WeakPtr.h" 12 #include "mozilla/Span.h" 13 #include "mozilla/dom/MaybeDiscarded.h" 14 #include "mozilla/dom/SyncedContext.h" 15 #include "mozilla/dom/UserActivation.h" 16 #include "nsDOMNavigationTiming.h" 17 #include "nsILoadInfo.h" 18 #include "nsWrapperCache.h" 19 20 class nsIGlobalObject; 21 22 class nsGlobalWindowInner; 23 24 namespace mozilla { 25 class LogModule; 26 class nsRFPTargetSetIDL; 27 28 namespace dom { 29 30 class WindowGlobalChild; 31 class WindowGlobalParent; 32 class WindowGlobalInit; 33 class BrowsingContext; 34 class BrowsingContextGroup; 35 36 #define MOZ_EACH_WC_FIELD(FIELD) \ 37 /* Whether the SHEntry associated with the current top-level \ 38 * window has already seen user interaction. \ 39 * As such, this will be reset to false when a new SHEntry is \ 40 * created without changing the WC (e.g. when using pushState or \ 41 * sub-frame navigation) \ 42 * This flag is set for optimization purposes, to avoid \ 43 * having to get the top SHEntry and update it on every \ 44 * user interaction. \ 45 * This is only meaningful on the top-level WC. */ \ 46 FIELD(SHEntryHasUserInteraction, bool) \ 47 FIELD(CookieBehavior, Maybe<uint32_t>) \ 48 FIELD(IsOnContentBlockingAllowList, bool) \ 49 /* Whether the given window hierarchy is third party. See \ 50 * ThirdPartyUtil::IsThirdPartyWindow for details */ \ 51 FIELD(IsThirdPartyWindow, bool) \ 52 /* Whether this window's channel has been marked as a third-party \ 53 * tracking resource */ \ 54 FIELD(IsThirdPartyTrackingResourceWindow, bool) \ 55 /* Whether this window is using its unpartitioned cookies due to \ 56 * the Storage Access API */ \ 57 FIELD(UsingStorageAccess, bool) \ 58 FIELD(ShouldResistFingerprinting, bool) \ 59 FIELD(OverriddenFingerprintingSettings, Maybe<RFPTargetSet>) \ 60 FIELD(IsSecureContext, bool) \ 61 FIELD(IsOriginalFrameSource, bool) \ 62 /* Mixed-Content: If the corresponding documentURI is https, \ 63 * then this flag is true. */ \ 64 FIELD(IsSecure, bool) \ 65 /* Whether this window has registered a "beforeunload" event \ 66 * handler */ \ 67 FIELD(NeedsBeforeUnload, bool) \ 68 /* Whether this window's navigation object has registered any \ 69 * event handlers or has ongoing or upcoming method trackers. Only \ 70 * valid for the top-level context. */ \ 71 FIELD(NeedsTraverse, bool) \ 72 /* Controls whether the WindowContext is currently considered to be \ 73 * activated by a gesture */ \ 74 FIELD(UserActivationStateAndModifiers, \ 75 UserActivation::StateAndModifiers::DataT) \ 76 FIELD(EmbedderPolicy, nsILoadInfo::CrossOriginEmbedderPolicy) \ 77 /* True if this document tree contained at least a HTMLMediaElement. \ 78 * This should only be set on top level context. */ \ 79 FIELD(DocTreeHadMedia, bool) \ 80 FIELD(AutoplayPermission, uint32_t) \ 81 FIELD(ShortcutsPermission, uint32_t) \ 82 /* Store the Id of the browsing context where active media session \ 83 * exists on the top level window context */ \ 84 FIELD(ActiveMediaSessionContextId, Maybe<uint64_t>) \ 85 /* ALLOW_ACTION if it is allowed to open popups for the sub-tree \ 86 * starting and including the current WindowContext */ \ 87 FIELD(PopupPermission, uint32_t) \ 88 FIELD(DelegatedPermissions, \ 89 PermissionDelegateHandler::DelegatedPermissionList) \ 90 FIELD(DelegatedExactHostMatchPermissions, \ 91 PermissionDelegateHandler::DelegatedPermissionList) \ 92 FIELD(HasReportedShadowDOMUsage, bool) \ 93 /* Whether the principal of this window is for a local \ 94 * IP address */ \ 95 FIELD(IsLocalIP, bool) \ 96 /* Whether any of the windows in the subtree rooted at this window has \ 97 * active peer connections or not (only set on the top window). */ \ 98 FIELD(HasActivePeerConnections, bool) \ 99 /* Whether we can execute scripts in this WindowContext. Has no effect \ 100 * unless scripts are also allowed in the BrowsingContext. */ \ 101 FIELD(AllowJavascript, bool) \ 102 /* If this field is `true`, it means that this WindowContext's \ 103 * WindowState was saved to be stored in the legacy (non-SHIP) BFCache \ 104 * implementation. Always false for SHIP */ \ 105 FIELD(WindowStateSaved, bool) \ 106 /* If this field is `true`, it means that this WindowContext's \ 107 * CloseWatcherManager has active CloseWatchers, which some UIs may \ 108 * want to dismiss (for example the Android "back button"). */ \ 109 FIELD(HasActiveCloseWatcher, bool) 110 111 class WindowContext : public nsISupports, public nsWrapperCache { 112 MOZ_DECL_SYNCED_CONTEXT(WindowContext, MOZ_EACH_WC_FIELD) 113 114 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 115 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WindowContext) 116 117 public: 118 static already_AddRefed<WindowContext> GetById(uint64_t aInnerWindowId); 119 static LogModule* GetLog(); 120 static LogModule* GetSyncLog(); 121 122 BrowsingContext* GetBrowsingContext() const { return mBrowsingContext; } 123 BrowsingContextGroup* Group() const; 124 uint64_t Id() const { return InnerWindowId(); } 125 uint64_t InnerWindowId() const { return mInnerWindowId; } 126 uint64_t OuterWindowId() const { return mOuterWindowId; } 127 bool IsDiscarded() const { return mIsDiscarded; } 128 129 // Returns `true` if this WindowContext is the current WindowContext in its 130 // BrowsingContext. 131 bool IsCurrent() const; 132 133 // Returns `true` if this WindowContext is currently in the BFCache. 134 bool IsInBFCache(); 135 136 bool IsInProcess() const { return mIsInProcess; } 137 138 bool NeedsBeforeUnload() const { return GetNeedsBeforeUnload(); } 139 140 bool HasBeforeUnload() const { return NeedsBeforeUnload(); } 141 142 bool IsLocalIP() const { return GetIsLocalIP(); } 143 144 bool ShouldResistFingerprinting() const { 145 return GetShouldResistFingerprinting(); 146 } 147 148 bool UsingStorageAccess() const { return GetUsingStorageAccess(); } 149 150 already_AddRefed<nsIRFPTargetSetIDL> 151 GetOverriddenFingerprintingSettingsWebIDL() const; 152 153 nsGlobalWindowInner* GetInnerWindow() const; 154 Document* GetDocument() const; 155 Document* GetExtantDoc() const; 156 157 WindowGlobalChild* GetWindowGlobalChild() const; 158 159 // Get the parent WindowContext of this WindowContext, taking the BFCache into 160 // account. This will not cross chrome/content <browser> boundaries. 161 WindowContext* GetParentWindowContext(); 162 WindowContext* TopWindowContext(); 163 164 bool SameOriginWithTop() const; 165 166 bool IsTop() const; 167 168 Span<RefPtr<BrowsingContext>> Children() { return mChildren; } 169 170 // The filtered version of `Children()`, which contains no browsing contexts 171 // for synthetic documents as created by object loading content. 172 Span<RefPtr<BrowsingContext>> NonSyntheticChildren() { 173 return mNonSyntheticChildren; 174 } 175 176 BrowsingContext* NonSyntheticLightDOMChildAt(uint32_t aIndex); 177 uint32_t NonSyntheticLightDOMChildrenCount(); 178 179 // Cast this object to it's parent-process canonical form. 180 WindowGlobalParent* Canonical(); 181 182 nsIGlobalObject* GetParentObject() const; 183 JSObject* WrapObject(JSContext* cx, 184 JS::Handle<JSObject*> aGivenProto) override; 185 186 void Discard(); 187 188 struct IPCInitializer { 189 uint64_t mInnerWindowId; 190 uint64_t mOuterWindowId; 191 uint64_t mBrowsingContextId; 192 193 FieldValues mFields; 194 }; 195 IPCInitializer GetIPCInitializer(); 196 197 static void CreateFromIPC(IPCInitializer&& aInit); 198 199 // Add new security state flags. 200 // These should be some of the nsIWebProgressListener 'HTTPS_ONLY_MODE' or 201 // 'MIXED' state flags, and should only be called on the top window context. 202 void AddSecurityState(uint32_t aStateFlags); 203 204 UserActivation::State GetUserActivationState() const { 205 return UserActivation::StateAndModifiers( 206 GetUserActivationStateAndModifiers()) 207 .GetState(); 208 } 209 210 // This function would be called when its corresponding window is activated 211 // by user gesture. 212 void NotifyUserGestureActivation( 213 UserActivation::Modifiers aModifiers = UserActivation::Modifiers::None()); 214 215 // This function would be called when we want to reset the user gesture 216 // activation flag. 217 void NotifyResetUserGestureActivation(); 218 219 // Return true if its corresponding window has been activated by user 220 // gesture. 221 bool HasBeenUserGestureActivated(); 222 223 // Return true if its corresponding window has transient user gesture 224 // activation and the transient user gesture activation haven't yet timed 225 // out. 226 bool HasValidTransientUserGestureActivation(); 227 228 // See `mLastActivationTimestamp`. 229 const TimeStamp& GetUserGestureStart() const; 230 231 // Return true if the corresponding window has valid transient user gesture 232 // activation and the transient user gesture activation had been consumed 233 // successfully. 234 bool ConsumeTransientUserGestureActivation(); 235 236 // Return true if its corresponding window has history activation. 237 bool HasValidHistoryActivation() const; 238 239 // Consume the history-action user activation. 240 void ConsumeHistoryActivation(); 241 242 // Update the history-action user activation for this window context 243 void UpdateLastHistoryActivation(); 244 245 bool GetTransientUserGestureActivationModifiers( 246 UserActivation::Modifiers* aModifiers); 247 248 bool CanShowPopup(); 249 250 bool AllowJavascript() const { return GetAllowJavascript(); } 251 bool CanExecuteScripts() const { return mCanExecuteScripts; } 252 253 void TransientSetHasActivePeerConnections(); 254 255 bool HasActiveCloseWatcher() const { return GetHasActiveCloseWatcher(); } 256 257 void ProcessCloseRequest(); 258 259 protected: 260 WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId, 261 uint64_t aOuterWindowId, FieldValues&& aFields); 262 virtual ~WindowContext(); 263 264 virtual void Init(); 265 266 private: 267 friend class BrowsingContext; 268 friend class WindowGlobalChild; 269 friend class WindowGlobalActor; 270 271 void AppendChildBrowsingContext(BrowsingContext* aBrowsingContext); 272 void RemoveChildBrowsingContext(BrowsingContext* aBrowsingContext); 273 274 // Update non-synthetic children based on whether `aBrowsingContext` 275 // is synthetic or not. Regardless the synthetic of `aBrowsingContext`, it is 276 // kept in this WindowContext's all children list. 277 void UpdateChildSynthetic(BrowsingContext* aBrowsingContext, 278 bool aIsSynthetic); 279 280 // Send a given `BaseTransaction` object to the correct remote. 281 void SendCommitTransaction(ContentParent* aParent, 282 const BaseTransaction& aTxn, uint64_t aEpoch); 283 void SendCommitTransaction(ContentChild* aChild, const BaseTransaction& aTxn, 284 uint64_t aEpoch); 285 286 bool CheckOnlyOwningProcessCanSet(ContentParent* aSource); 287 288 // Overload `CanSet` to get notifications for a particular field being set. 289 bool CanSet(FieldIndex<IDX_IsSecure>, const bool& aIsSecure, 290 ContentParent* aSource); 291 292 bool CanSet(FieldIndex<IDX_NeedsBeforeUnload>, const bool& aHasBeforeUnload, 293 ContentParent* aSource); 294 295 bool CanSet(FieldIndex<IDX_NeedsTraverse>, const bool& aNeedsTraverse, 296 ContentParent* aSource); 297 298 bool CanSet(FieldIndex<IDX_CookieBehavior>, const Maybe<uint32_t>& aValue, 299 ContentParent* aSource); 300 301 bool CanSet(FieldIndex<IDX_IsOnContentBlockingAllowList>, const bool& aValue, 302 ContentParent* aSource); 303 304 bool CanSet(FieldIndex<IDX_EmbedderPolicy>, const bool& aValue, 305 ContentParent* aSource) { 306 return true; 307 } 308 309 bool CanSet(FieldIndex<IDX_IsThirdPartyWindow>, 310 const bool& IsThirdPartyWindow, ContentParent* aSource); 311 bool CanSet(FieldIndex<IDX_IsThirdPartyTrackingResourceWindow>, 312 const bool& aIsThirdPartyTrackingResourceWindow, 313 ContentParent* aSource); 314 bool CanSet(FieldIndex<IDX_UsingStorageAccess>, 315 const bool& aUsingStorageAccess, ContentParent* aSource); 316 bool CanSet(FieldIndex<IDX_ShouldResistFingerprinting>, 317 const bool& aShouldResistFingerprinting, ContentParent* aSource); 318 bool CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>, 319 const Maybe<RFPTargetSet>& aValue, ContentParent* aSource); 320 bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext, 321 ContentParent* aSource); 322 bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>, 323 const bool& aIsOriginalFrameSource, ContentParent* aSource); 324 bool CanSet(FieldIndex<IDX_DocTreeHadMedia>, const bool& aValue, 325 ContentParent* aSource); 326 bool CanSet(FieldIndex<IDX_AutoplayPermission>, const uint32_t& aValue, 327 ContentParent* aSource); 328 bool CanSet(FieldIndex<IDX_ShortcutsPermission>, const uint32_t& aValue, 329 ContentParent* aSource); 330 bool CanSet(FieldIndex<IDX_ActiveMediaSessionContextId>, 331 const Maybe<uint64_t>& aValue, ContentParent* aSource); 332 bool CanSet(FieldIndex<IDX_PopupPermission>, const uint32_t&, 333 ContentParent* aSource); 334 bool CanSet(FieldIndex<IDX_SHEntryHasUserInteraction>, 335 const bool& aSHEntryHasUserInteraction, ContentParent* aSource) { 336 return true; 337 } 338 bool CanSet(FieldIndex<IDX_DelegatedPermissions>, 339 const PermissionDelegateHandler::DelegatedPermissionList& aValue, 340 ContentParent* aSource); 341 bool CanSet(FieldIndex<IDX_DelegatedExactHostMatchPermissions>, 342 const PermissionDelegateHandler::DelegatedPermissionList& aValue, 343 ContentParent* aSource); 344 bool CanSet(FieldIndex<IDX_UserActivationStateAndModifiers>, 345 const UserActivation::StateAndModifiers::DataT& 346 aUserActivationStateAndModifiers, 347 ContentParent* aSource) { 348 return true; 349 } 350 351 bool CanSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, const bool& aValue, 352 ContentParent* aSource) { 353 return true; 354 } 355 356 bool CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue, 357 ContentParent* aSource); 358 359 bool CanSet(FieldIndex<IDX_AllowJavascript>, bool aValue, 360 ContentParent* aSource); 361 void DidSet(FieldIndex<IDX_AllowJavascript>, bool aOldValue); 362 363 bool CanSet(FieldIndex<IDX_HasActivePeerConnections>, bool, ContentParent*); 364 365 void DidSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, bool aOldValue); 366 367 void DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>, bool aOldValue); 368 369 void DidSet(FieldIndex<IDX_HasActivePeerConnections>, bool aOldValue); 370 371 bool CanSet(FieldIndex<IDX_WindowStateSaved>, bool aValue, 372 ContentParent* aSource); 373 374 bool CanSet(FieldIndex<IDX_HasActiveCloseWatcher>, bool, ContentParent*) { 375 return true; 376 } 377 378 // Overload `DidSet` to get notifications for a particular field being set. 379 // 380 // You can also overload the variant that gets the old value if you need it. 381 template <size_t I> 382 void DidSet(FieldIndex<I>) {} 383 template <size_t I, typename T> 384 void DidSet(FieldIndex<I>, T&& aOldValue) {} 385 void DidSet(FieldIndex<IDX_UserActivationStateAndModifiers>); 386 387 // Recomputes whether we can execute scripts in this WindowContext based on 388 // the value of AllowJavascript() and whether scripts are allowed in the 389 // BrowsingContext. 390 void RecomputeCanExecuteScripts(bool aApplyChanges = true); 391 392 void ClearLightDOMChildren(); 393 394 void EnsureLightDOMChildren(); 395 396 const uint64_t mInnerWindowId; 397 const uint64_t mOuterWindowId; 398 RefPtr<BrowsingContext> mBrowsingContext; 399 WeakPtr<WindowGlobalChild> mWindowGlobalChild; 400 401 // --- NEVER CHANGE `mChildren` DIRECTLY! --- 402 // Changes to this list need to be synchronized to the list within our 403 // `mBrowsingContext`, and should only be performed through the 404 // `AppendChildBrowsingContext` and `RemoveChildBrowsingContext` methods. 405 nsTArray<RefPtr<BrowsingContext>> mChildren; 406 407 // --- NEVER CHANGE `mNonSyntheticChildren` DIRECTLY! --- 408 // Same reason as for mChildren. 409 // mNonSyntheticChildren contains the same browsing contexts except browsing 410 // contexts created by the synthetic document for object loading contents 411 // loading images. This is used to discern browsing contexts created when 412 // loading images in <object> or <embed> elements, so that they can be hidden 413 // from named targeting, `Window.frames` etc. 414 nsTArray<RefPtr<BrowsingContext>> mNonSyntheticChildren; 415 416 // mNonSyntheticLightDOMChildren is otherwise the same as 417 // mNonSyntheticChildren, but it contains only those BrowsingContexts where 418 // embedder is in light DOM. The contents of the array are computed lazily and 419 // cleared if there are changes to mChildren. 420 Maybe<nsTArray<RefPtr<BrowsingContext>>> mNonSyntheticLightDOMChildren; 421 422 bool mIsDiscarded = false; 423 bool mIsInProcess = false; 424 425 // Determines if we can execute scripts in this WindowContext. True if 426 // AllowJavascript() is true and script execution is allowed in the 427 // BrowsingContext. 428 bool mCanExecuteScripts = true; 429 430 // https://html.spec.whatwg.org/multipage/interaction.html#last-activation-timestamp 431 // The start time of user gesture, this is only available if the window 432 // context is in process. 433 TimeStamp mLastActivationTimestamp; 434 435 // https://html.spec.whatwg.org/#history-action-activation 436 // This is set to mLastActivationTimestamp every time ConsumeHistoryActivation 437 // is called. 438 TimeStamp mHistoryActivation; 439 }; 440 441 using WindowContextTransaction = WindowContext::BaseTransaction; 442 using WindowContextInitializer = WindowContext::IPCInitializer; 443 using MaybeDiscardedWindowContext = MaybeDiscarded<WindowContext>; 444 445 // Don't specialize the `Transaction` object for every translation unit it's 446 // used in. This should help keep code size down. 447 extern template class syncedcontext::Transaction<WindowContext>; 448 449 } // namespace dom 450 } // namespace mozilla 451 452 namespace IPC { 453 template <> 454 struct ParamTraits<mozilla::dom::MaybeDiscarded<mozilla::dom::WindowContext>> { 455 using paramType = mozilla::dom::MaybeDiscarded<mozilla::dom::WindowContext>; 456 static void Write(MessageWriter* aWriter, const paramType& aParam); 457 static bool Read(MessageReader* aReader, paramType* aResult); 458 }; 459 460 template <> 461 struct ParamTraits<mozilla::dom::WindowContext::IPCInitializer> { 462 using paramType = mozilla::dom::WindowContext::IPCInitializer; 463 static void Write(MessageWriter* aWriter, const paramType& aInitializer); 464 static bool Read(MessageReader* aReader, paramType* aInitializer); 465 }; 466 } // namespace IPC 467 468 #endif // !defined(mozilla_dom_WindowContext_h)