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 "nsILoadInfo.h" 17 #include "nsWrapperCache.h" 18 19 class nsIGlobalObject; 20 21 class nsGlobalWindowInner; 22 23 namespace mozilla { 24 class LogModule; 25 26 namespace dom { 27 28 class WindowGlobalChild; 29 class WindowGlobalParent; 30 class WindowGlobalInit; 31 class BrowsingContext; 32 class BrowsingContextGroup; 33 34 #define MOZ_EACH_WC_FIELD(FIELD) \ 35 /* Whether the SHEntry associated with the current top-level \ 36 * window has already seen user interaction. \ 37 * As such, this will be reset to false when a new SHEntry is \ 38 * created without changing the WC (e.g. when using pushState or \ 39 * sub-frame navigation) \ 40 * This flag is set for optimization purposes, to avoid \ 41 * having to get the top SHEntry and update it on every \ 42 * user interaction. \ 43 * This is only meaningful on the top-level WC. */ \ 44 FIELD(SHEntryHasUserInteraction, bool) \ 45 FIELD(CookieBehavior, Maybe<uint32_t>) \ 46 FIELD(IsOnContentBlockingAllowList, bool) \ 47 /* Whether the given window hierarchy is third party. See \ 48 * ThirdPartyUtil::IsThirdPartyWindow for details */ \ 49 FIELD(IsThirdPartyWindow, bool) \ 50 /* Whether this window's channel has been marked as a third-party \ 51 * tracking resource */ \ 52 FIELD(IsThirdPartyTrackingResourceWindow, bool) \ 53 FIELD(IsSecureContext, bool) \ 54 FIELD(IsOriginalFrameSource, bool) \ 55 /* Mixed-Content: If the corresponding documentURI is https, \ 56 * then this flag is true. */ \ 57 FIELD(IsSecure, bool) \ 58 /* Whether the user has overriden the mixed content blocker to allow \ 59 * mixed content loads to happen */ \ 60 FIELD(AllowMixedContent, bool) \ 61 /* Whether this window has registered a "beforeunload" event \ 62 * handler */ \ 63 FIELD(HasBeforeUnload, bool) \ 64 /* Controls whether the WindowContext is currently considered to be \ 65 * activated by a gesture */ \ 66 FIELD(UserActivationState, UserActivation::State) \ 67 FIELD(EmbedderPolicy, nsILoadInfo::CrossOriginEmbedderPolicy) \ 68 /* True if this document tree contained at least a HTMLMediaElement. \ 69 * This should only be set on top level context. */ \ 70 FIELD(DocTreeHadMedia, bool) \ 71 FIELD(AutoplayPermission, uint32_t) \ 72 FIELD(ShortcutsPermission, uint32_t) \ 73 /* Store the Id of the browsing context where active media session \ 74 * exists on the top level window context */ \ 75 FIELD(ActiveMediaSessionContextId, Maybe<uint64_t>) \ 76 /* ALLOW_ACTION if it is allowed to open popups for the sub-tree \ 77 * starting and including the current WindowContext */ \ 78 FIELD(PopupPermission, uint32_t) \ 79 FIELD(DelegatedPermissions, \ 80 PermissionDelegateHandler::DelegatedPermissionList) \ 81 FIELD(DelegatedExactHostMatchPermissions, \ 82 PermissionDelegateHandler::DelegatedPermissionList) \ 83 FIELD(HasReportedShadowDOMUsage, bool) \ 84 /* Whether the principal of this window is for a local \ 85 * IP address */ \ 86 FIELD(IsLocalIP, bool) \ 87 /* Whether the corresponding document has `loading='lazy'` \ 88 * images; It won't become false if the image becomes non-lazy */ \ 89 FIELD(HadLazyLoadImage, bool) \ 90 /* Whether we can execute scripts in this WindowContext. Has no effect \ 91 * unless scripts are also allowed in the BrowsingContext. */ \ 92 FIELD(AllowJavascript, bool) \ 93 /* If this field is `true`, it means that this WindowContext's \ 94 * WindowState was saved to be stored in the legacy (non-SHIP) BFCache \ 95 * implementation. Always false for SHIP */ \ 96 FIELD(WindowStateSaved, bool) 97 98 class WindowContext : public nsISupports, public nsWrapperCache { 99 MOZ_DECL_SYNCED_CONTEXT(WindowContext, MOZ_EACH_WC_FIELD) 100 101 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 102 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WindowContext) 103 104 public: 105 static already_AddRefed<WindowContext> GetById(uint64_t aInnerWindowId); 106 static LogModule* GetLog(); 107 static LogModule* GetSyncLog(); 108 GetBrowsingContext()109 BrowsingContext* GetBrowsingContext() const { return mBrowsingContext; } 110 BrowsingContextGroup* Group() const; Id()111 uint64_t Id() const { return InnerWindowId(); } InnerWindowId()112 uint64_t InnerWindowId() const { return mInnerWindowId; } OuterWindowId()113 uint64_t OuterWindowId() const { return mOuterWindowId; } IsDiscarded()114 bool IsDiscarded() const { return mIsDiscarded; } 115 116 bool IsCached() const; 117 118 // Returns `true` if this WindowContext is currently in the BFCache. 119 bool IsInBFCache(); 120 IsInProcess()121 bool IsInProcess() const { return mIsInProcess; } 122 HasBeforeUnload()123 bool HasBeforeUnload() const { return GetHasBeforeUnload(); } 124 IsLocalIP()125 bool IsLocalIP() const { return GetIsLocalIP(); } 126 127 nsGlobalWindowInner* GetInnerWindow() const; 128 Document* GetDocument() const; 129 Document* GetExtantDoc() const; 130 131 WindowGlobalChild* GetWindowGlobalChild() const; 132 133 // Get the parent WindowContext of this WindowContext, taking the BFCache into 134 // account. This will not cross chrome/content <browser> boundaries. 135 WindowContext* GetParentWindowContext(); 136 WindowContext* TopWindowContext(); 137 138 bool SameOriginWithTop() const; 139 140 bool IsTop() const; 141 Children()142 Span<RefPtr<BrowsingContext>> Children() { return mChildren; } 143 144 // Cast this object to it's parent-process canonical form. 145 WindowGlobalParent* Canonical(); 146 147 nsIGlobalObject* GetParentObject() const; 148 JSObject* WrapObject(JSContext* cx, 149 JS::Handle<JSObject*> aGivenProto) override; 150 151 void Discard(); 152 153 struct IPCInitializer { 154 uint64_t mInnerWindowId; 155 uint64_t mOuterWindowId; 156 uint64_t mBrowsingContextId; 157 158 FieldValues mFields; 159 }; 160 IPCInitializer GetIPCInitializer(); 161 162 static void CreateFromIPC(IPCInitializer&& aInit); 163 164 // Add new security state flags. 165 // These should be some of the nsIWebProgressListener 'HTTPS_ONLY_MODE' or 166 // 'MIXED' state flags, and should only be called on the top window context. 167 void AddSecurityState(uint32_t aStateFlags); 168 169 // This function would be called when its corresponding window is activated 170 // by user gesture. 171 void NotifyUserGestureActivation(); 172 173 // This function would be called when we want to reset the user gesture 174 // activation flag. 175 void NotifyResetUserGestureActivation(); 176 177 // Return true if its corresponding window has been activated by user 178 // gesture. 179 bool HasBeenUserGestureActivated(); 180 181 // Return true if its corresponding window has transient user gesture 182 // activation and the transient user gesture activation haven't yet timed 183 // out. 184 bool HasValidTransientUserGestureActivation(); 185 186 // Return true if the corresponding window has valid transient user gesture 187 // activation and the transient user gesture activation had been consumed 188 // successfully. 189 bool ConsumeTransientUserGestureActivation(); 190 191 bool CanShowPopup(); 192 HadLazyLoadImage()193 bool HadLazyLoadImage() const { return GetHadLazyLoadImage(); } 194 AllowJavascript()195 bool AllowJavascript() const { return GetAllowJavascript(); } CanExecuteScripts()196 bool CanExecuteScripts() const { return mCanExecuteScripts; } 197 198 protected: 199 WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId, 200 uint64_t aOuterWindowId, FieldValues&& aFields); 201 virtual ~WindowContext(); 202 203 virtual void Init(); 204 205 private: 206 friend class BrowsingContext; 207 friend class WindowGlobalChild; 208 friend class WindowGlobalActor; 209 210 void AppendChildBrowsingContext(BrowsingContext* aBrowsingContext); 211 void RemoveChildBrowsingContext(BrowsingContext* aBrowsingContext); 212 213 // Send a given `BaseTransaction` object to the correct remote. 214 void SendCommitTransaction(ContentParent* aParent, 215 const BaseTransaction& aTxn, uint64_t aEpoch); 216 void SendCommitTransaction(ContentChild* aChild, const BaseTransaction& aTxn, 217 uint64_t aEpoch); 218 219 bool CheckOnlyOwningProcessCanSet(ContentParent* aSource); 220 221 // Overload `CanSet` to get notifications for a particular field being set. 222 bool CanSet(FieldIndex<IDX_IsSecure>, const bool& aIsSecure, 223 ContentParent* aSource); 224 bool CanSet(FieldIndex<IDX_AllowMixedContent>, const bool& aAllowMixedContent, 225 ContentParent* aSource); 226 227 bool CanSet(FieldIndex<IDX_HasBeforeUnload>, const bool& aHasBeforeUnload, 228 ContentParent* aSource); 229 230 bool CanSet(FieldIndex<IDX_CookieBehavior>, const Maybe<uint32_t>& aValue, 231 ContentParent* aSource); 232 233 bool CanSet(FieldIndex<IDX_IsOnContentBlockingAllowList>, const bool& aValue, 234 ContentParent* aSource); 235 CanSet(FieldIndex<IDX_EmbedderPolicy>,const bool & aValue,ContentParent * aSource)236 bool CanSet(FieldIndex<IDX_EmbedderPolicy>, const bool& aValue, 237 ContentParent* aSource) { 238 return true; 239 } 240 241 bool CanSet(FieldIndex<IDX_IsThirdPartyWindow>, 242 const bool& IsThirdPartyWindow, ContentParent* aSource); 243 bool CanSet(FieldIndex<IDX_IsThirdPartyTrackingResourceWindow>, 244 const bool& aIsThirdPartyTrackingResourceWindow, 245 ContentParent* aSource); 246 bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext, 247 ContentParent* aSource); 248 bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>, 249 const bool& aIsOriginalFrameSource, ContentParent* aSource); 250 bool CanSet(FieldIndex<IDX_DocTreeHadMedia>, const bool& aValue, 251 ContentParent* aSource); 252 bool CanSet(FieldIndex<IDX_AutoplayPermission>, const uint32_t& aValue, 253 ContentParent* aSource); 254 bool CanSet(FieldIndex<IDX_ShortcutsPermission>, const uint32_t& aValue, 255 ContentParent* aSource); 256 bool CanSet(FieldIndex<IDX_ActiveMediaSessionContextId>, 257 const Maybe<uint64_t>& aValue, ContentParent* aSource); 258 bool CanSet(FieldIndex<IDX_PopupPermission>, const uint32_t&, 259 ContentParent* aSource); CanSet(FieldIndex<IDX_SHEntryHasUserInteraction>,const bool & aSHEntryHasUserInteraction,ContentParent * aSource)260 bool CanSet(FieldIndex<IDX_SHEntryHasUserInteraction>, 261 const bool& aSHEntryHasUserInteraction, ContentParent* aSource) { 262 return true; 263 } 264 bool CanSet(FieldIndex<IDX_DelegatedPermissions>, 265 const PermissionDelegateHandler::DelegatedPermissionList& aValue, 266 ContentParent* aSource); 267 bool CanSet(FieldIndex<IDX_DelegatedExactHostMatchPermissions>, 268 const PermissionDelegateHandler::DelegatedPermissionList& aValue, 269 ContentParent* aSource); CanSet(FieldIndex<IDX_UserActivationState>,const UserActivation::State & aUserActivationState,ContentParent * aSource)270 bool CanSet(FieldIndex<IDX_UserActivationState>, 271 const UserActivation::State& aUserActivationState, 272 ContentParent* aSource) { 273 return true; 274 } 275 CanSet(FieldIndex<IDX_HasReportedShadowDOMUsage>,const bool & aValue,ContentParent * aSource)276 bool CanSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, const bool& aValue, 277 ContentParent* aSource) { 278 return true; 279 } 280 281 bool CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue, 282 ContentParent* aSource); 283 284 bool CanSet(FieldIndex<IDX_HadLazyLoadImage>, const bool& aValue, 285 ContentParent* aSource); 286 287 bool CanSet(FieldIndex<IDX_AllowJavascript>, bool aValue, 288 ContentParent* aSource); 289 void DidSet(FieldIndex<IDX_AllowJavascript>, bool aOldValue); 290 291 void DidSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, bool aOldValue); 292 293 void DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>, bool aOldValue); 294 295 bool CanSet(FieldIndex<IDX_WindowStateSaved>, bool aValue, 296 ContentParent* aSource); 297 298 // Overload `DidSet` to get notifications for a particular field being set. 299 // 300 // You can also overload the variant that gets the old value if you need it. 301 template <size_t I> DidSet(FieldIndex<I>)302 void DidSet(FieldIndex<I>) {} 303 template <size_t I, typename T> DidSet(FieldIndex<I>,T && aOldValue)304 void DidSet(FieldIndex<I>, T&& aOldValue) {} 305 void DidSet(FieldIndex<IDX_UserActivationState>); 306 307 // Recomputes whether we can execute scripts in this WindowContext based on 308 // the value of AllowJavascript() and whether scripts are allowed in the 309 // BrowsingContext. 310 void RecomputeCanExecuteScripts(bool aApplyChanges = true); 311 312 const uint64_t mInnerWindowId; 313 const uint64_t mOuterWindowId; 314 RefPtr<BrowsingContext> mBrowsingContext; 315 WeakPtr<WindowGlobalChild> mWindowGlobalChild; 316 317 // --- NEVER CHANGE `mChildren` DIRECTLY! --- 318 // Changes to this list need to be synchronized to the list within our 319 // `mBrowsingContext`, and should only be performed through the 320 // `AppendChildBrowsingContext` and `RemoveChildBrowsingContext` methods. 321 nsTArray<RefPtr<BrowsingContext>> mChildren; 322 323 bool mIsDiscarded = false; 324 bool mIsInProcess = false; 325 326 // Determines if we can execute scripts in this WindowContext. True if 327 // AllowJavascript() is true and script execution is allowed in the 328 // BrowsingContext. 329 bool mCanExecuteScripts = true; 330 331 // The start time of user gesture, this is only available if the window 332 // context is in process. 333 TimeStamp mUserGestureStart; 334 }; 335 336 using WindowContextTransaction = WindowContext::BaseTransaction; 337 using WindowContextInitializer = WindowContext::IPCInitializer; 338 using MaybeDiscardedWindowContext = MaybeDiscarded<WindowContext>; 339 340 // Don't specialize the `Transaction` object for every translation unit it's 341 // used in. This should help keep code size down. 342 extern template class syncedcontext::Transaction<WindowContext>; 343 344 } // namespace dom 345 346 namespace ipc { 347 template <> 348 struct IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>> { 349 static void Write(IPC::Message* aMsg, IProtocol* aActor, 350 const dom::MaybeDiscarded<dom::WindowContext>& aParam); 351 static bool Read(const IPC::Message* aMsg, PickleIterator* aIter, 352 IProtocol* aActor, 353 dom::MaybeDiscarded<dom::WindowContext>* aResult); 354 }; 355 356 template <> 357 struct IPDLParamTraits<dom::WindowContext::IPCInitializer> { 358 static void Write(IPC::Message* aMessage, IProtocol* aActor, 359 const dom::WindowContext::IPCInitializer& aInitializer); 360 361 static bool Read(const IPC::Message* aMessage, PickleIterator* aIterator, 362 IProtocol* aActor, 363 dom::WindowContext::IPCInitializer* aInitializer); 364 }; 365 } // namespace ipc 366 } // namespace mozilla 367 368 #endif // !defined(mozilla_dom_WindowContext_h) 369