nsDocShell.h (61945B)
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 nsDocShell_h__ 8 #define nsDocShell_h__ 9 10 #include "Units.h" 11 #include "mozilla/Encoding.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/NotNull.h" 14 #include "mozilla/ScrollbarPreferences.h" 15 #include "mozilla/UniquePtr.h" 16 #include "mozilla/WeakPtr.h" 17 #include "mozilla/dom/BrowsingContext.h" 18 #include "mozilla/dom/NavigationBinding.h" 19 #include "mozilla/dom/WindowProxyHolder.h" 20 #include "nsCOMPtr.h" 21 #include "nsCharsetSource.h" 22 #include "nsDocLoader.h" 23 #include "nsIAuthPromptProvider.h" 24 #include "nsIBaseWindow.h" 25 #include "nsIDocShell.h" 26 #include "nsIDocShellTreeItem.h" 27 #include "nsIDocumentViewer.h" 28 #include "nsIInterfaceRequestor.h" 29 #include "nsILoadContext.h" 30 #include "nsINetworkInterceptController.h" 31 #include "nsIRefreshURI.h" 32 #include "nsIWebNavigation.h" 33 #include "nsIWebPageDescriptor.h" 34 #include "nsIWebProgressListener.h" 35 #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences 36 #include "nsRect.h" 37 #include "nsString.h" 38 #include "nsThreadUtils.h" 39 #include "prtime.h" 40 41 // Interfaces Needed 42 43 namespace mozilla { 44 class Encoding; 45 class HTMLEditor; 46 class ObservedDocShell; 47 class ScrollContainerFrame; 48 enum class TaskCategory; 49 class PresShell; 50 namespace dom { 51 class ClientInfo; 52 class ClientSource; 53 class EventTarget; 54 class WindowGlobalChild; 55 enum class NavigationHistoryBehavior : uint8_t; 56 struct NavigationAPIMethodTracker; 57 class SessionHistoryInfo; 58 struct LoadingSessionHistoryInfo; 59 struct Wireframe; 60 } // namespace dom 61 namespace net { 62 class LoadInfo; 63 class DocumentLoadListener; 64 } // namespace net 65 } // namespace mozilla 66 67 class nsIController; 68 class nsIDocShellTreeOwner; 69 class nsIDocumentViewer; 70 class nsIHttpChannel; 71 class nsIMutableArray; 72 class nsIPolicyContainer; 73 class nsIPrompt; 74 class nsIStringBundle; 75 class nsIURIFixup; 76 class nsIURIFixupInfo; 77 class nsIURILoader; 78 class nsIWebBrowserFind; 79 class nsIWidget; 80 class nsIReferrerInfo; 81 class nsIOpenWindowInfo; 82 83 class nsBrowserStatusFilter; 84 class nsCommandManager; 85 class nsDocShellEditorData; 86 class nsDOMNavigationTiming; 87 class nsDSURIContentListener; 88 class nsGlobalWindowOuter; 89 90 class FramingChecker; 91 class OnLinkClickEvent; 92 93 /* internally used ViewMode types */ 94 enum ViewMode { viewNormal = 0x0, viewSource = 0x1 }; 95 96 enum eCharsetReloadState { 97 eCharsetReloadInit, 98 eCharsetReloadRequested, 99 eCharsetReloadStopOrigional 100 }; 101 102 struct SameDocumentNavigationState; 103 104 class nsDocShell final : public nsDocLoader, 105 public nsIDocShell, 106 public nsIWebNavigation, 107 public nsIBaseWindow, 108 public nsIRefreshURI, 109 public nsIWebProgressListener, 110 public nsIWebPageDescriptor, 111 public nsIAuthPromptProvider, 112 public nsILoadContext, 113 public nsINetworkInterceptController, 114 public mozilla::SupportsWeakPtr { 115 public: 116 enum InternalLoad : uint32_t { 117 INTERNAL_LOAD_FLAGS_NONE = 0x0, 118 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL = 0x1, 119 INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER = 0x2, 120 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 0x4, 121 122 // This flag marks the first load in this object 123 // @see nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD 124 INTERNAL_LOAD_FLAGS_FIRST_LOAD = 0x8, 125 126 // The set of flags that should not be set before calling into 127 // nsDocShell::LoadURI and other nsDocShell loading functions. 128 INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS = 0xf, 129 130 INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10, 131 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES = 0x20, 132 133 // Whether the load should be treated as srcdoc load, rather than a URI one. 134 INTERNAL_LOAD_FLAGS_IS_SRCDOC = 0x40, 135 136 // Whether this is the load of a frame's original src attribute 137 INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC = 0x80, 138 139 INTERNAL_LOAD_FLAGS_NO_OPENER = 0x100, 140 141 // Whether a top-level data URI navigation is allowed for that load 142 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI = 0x200, 143 144 // Whether the load should go through LoadURIDelegate. 145 INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE = 0x2000, 146 }; 147 148 // Event type dispatched by RestorePresentation 149 class RestorePresentationEvent : public mozilla::Runnable { 150 public: 151 NS_DECL_NSIRUNNABLE 152 explicit RestorePresentationEvent(nsDocShell* aDs) 153 : mozilla::Runnable("nsDocShell::RestorePresentationEvent"), 154 mDocShell(aDs) {} 155 void Revoke() { mDocShell = nullptr; } 156 157 private: 158 RefPtr<nsDocShell> mDocShell; 159 }; 160 161 class InterfaceRequestorProxy : public nsIInterfaceRequestor { 162 public: 163 explicit InterfaceRequestorProxy(nsIInterfaceRequestor* aRequestor); 164 NS_DECL_THREADSAFE_ISUPPORTS 165 NS_DECL_NSIINTERFACEREQUESTOR 166 167 private: 168 virtual ~InterfaceRequestorProxy(); 169 InterfaceRequestorProxy() = default; 170 nsWeakPtr mWeakPtr; 171 }; 172 173 NS_DECL_ISUPPORTS_INHERITED 174 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDocShell, nsDocLoader) 175 NS_DECL_NSIDOCSHELL 176 NS_DECL_NSIDOCSHELLTREEITEM 177 NS_DECL_NSIWEBNAVIGATION 178 NS_DECL_NSIBASEWINDOW 179 NS_DECL_NSIINTERFACEREQUESTOR 180 NS_DECL_NSIWEBPROGRESSLISTENER 181 NS_DECL_NSIREFRESHURI 182 NS_DECL_NSIWEBPAGEDESCRIPTOR 183 NS_DECL_NSIAUTHPROMPTPROVIDER 184 NS_DECL_NSINETWORKINTERCEPTCONTROLLER 185 186 using nsIBaseWindow::GetMainWidget; 187 188 // Create a new nsDocShell object. 189 static already_AddRefed<nsDocShell> Create( 190 mozilla::dom::BrowsingContext* aBrowsingContext, 191 uint64_t aContentWindowID = 0); 192 193 bool Initialize(nsIOpenWindowInfo* aOpenWindowInfo, 194 mozilla::dom::WindowGlobalChild* aWindowActor); 195 196 nsresult InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY, 197 int32_t aWidth, int32_t aHeight, 198 nsIOpenWindowInfo* aOpenWindowInfo, 199 mozilla::dom::WindowGlobalChild* aWindowActor); 200 201 NS_IMETHOD Stop() override { 202 // Need this here because otherwise nsIWebNavigation::Stop 203 // overrides the docloader's Stop() 204 return nsDocLoader::Stop(); 205 } 206 207 mozilla::ScrollbarPreference ScrollbarPreference() const { 208 return mScrollbarPref; 209 } 210 void SetScrollbarPreference(mozilla::ScrollbarPreference); 211 212 /* 213 * The size, in CSS pixels, of the margins for the <body> of an HTML document 214 * in this docshell; used to implement the marginwidth attribute on HTML 215 * <frame>/<iframe> elements. A value smaller than zero indicates that the 216 * attribute was not set. 217 */ 218 const mozilla::CSSIntSize& GetFrameMargins() const { return mFrameMargins; } 219 220 bool UpdateFrameMargins(const mozilla::CSSIntSize& aMargins) { 221 if (mFrameMargins == aMargins) { 222 return false; 223 } 224 mFrameMargins = aMargins; 225 return true; 226 } 227 228 /** 229 * Process a click on a link. 230 * 231 * @param aContent the content object used for triggering the link. 232 * @param aURI a URI object that defines the destination for the link 233 * @param aTargetSpec indicates where the link is targeted (may be an empty 234 * string) 235 * @param aFileName non-null when the link should be downloaded as the given 236 * file 237 * @param aPostDataStream the POST data to send 238 * @param aHeadersDataStream ??? (only used for plugins) 239 * @param aTriggeringPrincipal, if not passed explicitly we fall back to 240 * the document's principal. 241 * @param aPolicyContainer, the policyContainer to be used for the load, that 242 * is the policyContainer of the entity responsible for causing the load to 243 * occur. Most likely this is the policyContainer of the document that started 244 * the load. In case aPolicyContainer was not passed explicitly we fall back 245 * to using aContent's document's policyContainer if that document holds any. 246 */ 247 MOZ_CAN_RUN_SCRIPT 248 nsresult OnLinkClick(nsIContent* aContent, nsIURI* aURI, 249 const nsAString& aTargetSpec, const nsAString& aFileName, 250 nsIInputStream* aPostDataStream, 251 nsIInputStream* aHeadersDataStream, 252 bool aIsUserTriggered, 253 mozilla::dom::UserNavigationInvolvement aUserInvolvement, 254 nsIPrincipal* aTriggeringPrincipal, 255 nsIPolicyContainer* aPolicyContainer); 256 /** 257 * Process a click on a link. 258 * 259 * Works the same as OnLinkClick() except it happens immediately rather than 260 * through an event. 261 * 262 * @param aContent the content object used for triggering the link. 263 * @param aDocShellLoadState the extended load info for this load. 264 * @param aNoOpenerImplied if the link implies "noopener" 265 * @param aTriggeringPrincipal, if not passed explicitly we fall back to 266 * the document's principal. 267 */ 268 nsresult OnLinkClickSync(nsIContent* aContent, 269 nsDocShellLoadState* aLoadState, 270 bool aNoOpenerImplied, 271 nsIPrincipal* aTriggeringPrincipal); 272 273 /** 274 * Process a mouse-over a link. 275 * 276 * @param aContent the linked content. 277 * @param aURI an URI object that defines the destination for the link 278 * @param aTargetSpec indicates where the link is targeted (it may be an empty 279 * string) 280 */ 281 nsresult OnOverLink(nsIContent* aContent, nsIURI* aURI, 282 const nsAString& aTargetSpec); 283 /** 284 * Process the mouse leaving a link. 285 */ 286 nsresult OnLeaveLink(); 287 288 // Don't use NS_DECL_NSILOADCONTEXT because some of nsILoadContext's methods 289 // are shared with nsIDocShell and can't be declared twice. 290 NS_IMETHOD GetAssociatedWindow(mozIDOMWindowProxy**) override; 291 NS_IMETHOD GetTopWindow(mozIDOMWindowProxy**) override; 292 NS_IMETHOD GetTopFrameElement(mozilla::dom::Element**) override; 293 NS_IMETHOD GetIsContent(bool*) override; 294 NS_IMETHOD GetUsePrivateBrowsing(bool*) override; 295 NS_IMETHOD SetUsePrivateBrowsing(bool) override; 296 NS_IMETHOD SetPrivateBrowsing(bool) override; 297 NS_IMETHOD GetUseRemoteTabs(bool*) override; 298 NS_IMETHOD SetRemoteTabs(bool) override; 299 NS_IMETHOD GetUseRemoteSubframes(bool*) override; 300 NS_IMETHOD SetRemoteSubframes(bool) override; 301 NS_IMETHOD GetScriptableOriginAttributes( 302 JSContext*, JS::MutableHandle<JS::Value>) override; 303 NS_IMETHOD_(void) 304 GetOriginAttributes(mozilla::OriginAttributes& aAttrs) override; 305 306 // Restores a cached presentation from history (mLSHE). 307 // This method swaps out the content viewer and simulates loads for 308 // subframes. It then simulates the completion of the toplevel load. 309 nsresult RestoreFromHistory(); 310 311 /** 312 * Parses the passed in header string and sets up a refreshURI if a "refresh" 313 * header is found. If docshell is busy loading a page currently, the request 314 * will be queued and executed when the current page finishes loading. 315 * 316 * @param aDocument document to which the refresh header applies. 317 * @param aHeader The meta refresh header string. 318 */ 319 void SetupRefreshURIFromHeader(mozilla::dom::Document* aDocument, 320 const nsAString& aHeader); 321 322 // Perform a URI load from a refresh timer. This is just like the 323 // ForceRefreshURI method on nsIRefreshURI, but makes sure to take 324 // the timer involved out of mRefreshURIList if it's there. 325 // aTimer must not be null. 326 nsresult ForceRefreshURIFromTimer(nsIURI* aURI, nsIPrincipal* aPrincipal, 327 uint32_t aDelay, nsITimer* aTimer); 328 329 // We need dummy OnLocationChange in some cases to update the UI without 330 // updating security info. 331 void FireDummyOnLocationChange() { 332 FireOnLocationChange(this, nullptr, mCurrentURI, 333 LOCATION_CHANGE_SAME_DOCUMENT); 334 } 335 336 nsresult HistoryEntryRemoved(int32_t aIndex); 337 338 // Notify Scroll observers when an async panning/zooming transform 339 // has started being applied 340 MOZ_CAN_RUN_SCRIPT_BOUNDARY 341 void NotifyAsyncPanZoomStarted(); 342 343 // Notify Scroll observers when an async panning/zooming transform 344 // is no longer applied 345 MOZ_CAN_RUN_SCRIPT_BOUNDARY 346 void NotifyAsyncPanZoomStopped(); 347 348 void SetInFrameSwap(bool aInSwap) { mInFrameSwap = aInSwap; } 349 bool InFrameSwap(); 350 351 bool GetForcedAutodetection() { return mForcedAutodetection; } 352 353 void ResetForcedAutodetection() { mForcedAutodetection = false; } 354 355 mozilla::HTMLEditor* GetHTMLEditorInternal(); 356 nsresult SetHTMLEditorInternal(mozilla::HTMLEditor* aHTMLEditor); 357 358 // Handle page navigation due to charset changes 359 nsresult CharsetChangeReloadDocument( 360 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource); 361 nsresult CharsetChangeStopDocumentLoad(); 362 363 nsDOMNavigationTiming* GetNavigationTiming() const; 364 365 nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs); 366 367 const mozilla::OriginAttributes& GetOriginAttributes() { 368 return mBrowsingContext->OriginAttributesRef(); 369 } 370 371 // Determine whether this docshell corresponds to the given history entry, 372 // via having a pointer to it in mOSHE or mLSHE. 373 bool HasHistoryEntry(nsISHEntry* aEntry) const { 374 return aEntry && (aEntry == mOSHE || aEntry == mLSHE); 375 } 376 377 // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry 378 void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry); 379 380 bool GetCreatedDynamically() const { 381 return mBrowsingContext && mBrowsingContext->CreatedDynamically(); 382 } 383 384 mozilla::gfx::Matrix5x4* GetColorMatrix() { return mColorMatrix.get(); } 385 386 static bool SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags); 387 388 // Tell the favicon service that aNewURI has the same favicon as aOldURI. 389 static void CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, 390 bool aInPrivateBrowsing); 391 392 static nsDocShell* Cast(nsIDocShell* aDocShell) { 393 return static_cast<nsDocShell*>(aDocShell); 394 } 395 396 static bool CanLoadInParentProcess(nsIURI* aURI); 397 398 // Returns true if the current load is a force reload (started by holding 399 // shift while triggering reload) 400 bool IsForceReloading(); 401 402 mozilla::dom::WindowProxyHolder GetWindowProxy() { 403 EnsureScriptEnvironment(); 404 return mozilla::dom::WindowProxyHolder(mBrowsingContext); 405 } 406 407 nsPIDOMWindowInner* GetActiveWindow(); 408 409 /** 410 * Loads the given URI. See comments on nsDocShellLoadState members for more 411 * information on information used. 412 * 413 * @param aCacheKey gets passed to DoURILoad call. 414 */ 415 MOZ_CAN_RUN_SCRIPT_BOUNDARY 416 nsresult InternalLoad( 417 nsDocShellLoadState* aLoadState, 418 mozilla::Maybe<uint32_t> aCacheKey = mozilla::Nothing()); 419 420 void MaybeRestoreWindowName(); 421 422 void StoreWindowNameToSHEntries(); 423 424 void SetWillChangeProcess() { mWillChangeProcess = true; } 425 bool WillChangeProcess() { return mWillChangeProcess; } 426 427 // Creates a real network channel (not a DocumentChannel) using the specified 428 // parameters. 429 // Used by nsDocShell when not using DocumentChannel, by DocumentLoadListener 430 // (parent-process DocumentChannel), and by DocumentChannelChild/ContentChild 431 // to transfer the resulting channel into the final process. 432 static nsresult CreateRealChannelForDocument( 433 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo, 434 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags, 435 const nsAString& aSrcdoc, nsIURI* aBaseURI); 436 437 // Creates a real (not DocumentChannel) channel, and configures it using the 438 // supplied nsDocShellLoadState. 439 // Configuration options here are ones that should be applied to only the 440 // real channel, especially ones that need to QI to channel subclasses. 441 static bool CreateAndConfigureRealChannelForLoadState( 442 mozilla::dom::BrowsingContext* aBrowsingContext, 443 nsDocShellLoadState* aLoadState, mozilla::net::LoadInfo* aLoadInfo, 444 nsIInterfaceRequestor* aCallbacks, nsDocShell* aDocShell, 445 const mozilla::OriginAttributes& aOriginAttributes, 446 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& rv, 447 nsIChannel** aChannel); 448 449 // This is used to deal with errors resulting from a failed page load. 450 // Errors are handled as follows: 451 // 1. Check to see if it's a file not found error or bad content 452 // encoding error. 453 // 2. Send the URI to a keyword server (if enabled) 454 // 3. If the error was DNS failure, then add www and .com to the URI 455 // (if appropriate). 456 // 4. If the www .com additions don't work, try those with an HTTPS scheme 457 // (if appropriate). 458 static already_AddRefed<nsIURI> AttemptURIFixup( 459 nsIChannel* aChannel, nsresult aStatus, 460 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType, 461 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing, 462 bool aNotifyKeywordSearchLoading = false, 463 nsIInputStream** aNewPostData = nullptr, 464 nsILoadInfo::SchemelessInputType* outSchemelessInput = nullptr); 465 466 static already_AddRefed<nsIURI> MaybeFixBadCertDomainErrorURI( 467 nsIChannel* aChannel, nsIURI* aUrl); 468 469 // Takes aStatus and filters out results that should not display 470 // an error page. 471 // If this returns a failed result, then we should display an error 472 // page with that result. 473 // aSkippedUnknownProtocolNavigation will be set to true if we chose 474 // to skip displaying an error page for an NS_ERROR_UNKNOWN_PROTOCOL 475 // navigation. 476 static nsresult FilterStatusForErrorPage( 477 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType, 478 bool aIsTopFrame, bool aUseErrorPages, 479 bool* aSkippedUnknownProtocolNavigation = nullptr); 480 481 // Notify consumers of a search being loaded through the observer service: 482 static void MaybeNotifyKeywordSearchLoading(const nsString& aProvider, 483 const nsString& aKeyword); 484 485 nsDocShell* GetInProcessChildAt(int32_t aIndex); 486 487 static bool ShouldAddURIVisit(nsIChannel* aChannel); 488 489 /** 490 * Helper function that finds the last URI and its transition flags for a 491 * channel. 492 * 493 * This method first checks the channel's property bag to see if previous 494 * info has been saved. If not, it gives back the referrer of the channel. 495 * 496 * @param aChannel 497 * The channel we are transitioning to 498 * @param aURI 499 * Output parameter with the previous URI, not addref'd 500 * @param aChannelRedirectFlags 501 * If a redirect, output parameter with the previous redirect flags 502 * from nsIChannelEventSink 503 */ 504 static void ExtractLastVisit(nsIChannel* aChannel, nsIURI** aURI, 505 uint32_t* aChannelRedirectFlags); 506 507 bool HasDocumentViewer() const { return !!mDocumentViewer; } 508 509 static uint32_t ComputeURILoaderFlags( 510 mozilla::dom::BrowsingContext* aBrowsingContext, uint32_t aLoadType, 511 bool aIsDocumentLoad = true); 512 513 mozilla::dom::SessionHistoryInfo* GetActiveSessionHistoryInfo() const; 514 515 void SetLoadingSessionHistoryInfo( 516 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, 517 bool aNeedToReportActiveAfterLoadingBecomesActive = false); 518 const mozilla::dom::LoadingSessionHistoryInfo* 519 GetLoadingSessionHistoryInfo() { 520 return mLoadingEntry.get(); 521 } 522 523 already_AddRefed<nsIInputStream> GetPostDataFromCurrentEntry() const; 524 mozilla::Maybe<uint32_t> GetCacheKeyFromCurrentEntry() const; 525 526 // Loading and/or active entries are only set when session history 527 // in the parent is on. 528 bool FillLoadStateFromCurrentEntry(nsDocShellLoadState& aLoadState); 529 530 static bool ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel); 531 532 bool IsOSHE(nsISHEntry* aEntry) const { return mOSHE == aEntry; } 533 534 mozilla::dom::ChildSHistory* GetSessionHistory() { 535 return mBrowsingContext->GetChildSessionHistory(); 536 } 537 538 // This returns true only when using session history in parent. 539 bool IsLoadingFromSessionHistory(); 540 541 NS_IMETHODIMP OnStartRequest(nsIRequest* aRequest) override; 542 NS_IMETHODIMP OnStopRequest(nsIRequest* aRequest, 543 nsresult aStatusCode) override; 544 545 private: // member functions 546 friend class nsAppShellService; 547 friend class nsDSURIContentListener; 548 friend class FramingChecker; 549 friend class OnLinkClickEvent; 550 friend class nsIDocShell; 551 friend class mozilla::dom::BrowsingContext; 552 friend class mozilla::net::DocumentLoadListener; 553 friend class nsGlobalWindowOuter; 554 555 nsDocShell(mozilla::dom::BrowsingContext* aBrowsingContext, 556 uint64_t aContentWindowID); 557 558 static inline uint32_t PRTimeToSeconds(PRTime aTimeUsec) { 559 return uint32_t(aTimeUsec / PR_USEC_PER_SEC); 560 } 561 562 virtual ~nsDocShell(); 563 564 // 565 // nsDocLoader 566 // 567 568 virtual void DestroyChildren() override; 569 570 // Overridden from nsDocLoader, this provides more information than the 571 // normal OnStateChange with flags STATE_REDIRECTING 572 virtual void OnRedirectStateChange(nsIChannel* aOldChannel, 573 nsIChannel* aNewChannel, 574 uint32_t aRedirectFlags, 575 uint32_t aStateFlags) override; 576 577 // Override the parent setter from nsDocLoader 578 virtual nsresult SetDocLoaderParent(nsDocLoader* aLoader) override; 579 580 // 581 // Content Viewer Management 582 // 583 584 // Return whether a viewer exists and assert that we aren't 585 // trying to get a viewer before it's eager creation during docshell 586 // initialization. 587 bool VerifyDocumentViewer(); 588 589 void DestroyDocumentViewer(); 590 591 nsresult CreateInitialDocumentViewer( 592 nsIOpenWindowInfo* aOpenWindowInfo = nullptr, 593 mozilla::dom::WindowGlobalChild* aWindowActor = nullptr); 594 595 // aPrincipal can be passed in if the caller wants. If null is 596 // passed in, the about:blank principal will end up being used. 597 // aPolicyContainer, if any, will be used for the new about:blank load. 598 nsresult CreateAboutBlankDocumentViewer( 599 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal, 600 nsIPolicyContainer* aPolicyContainer, nsIURI* aBaseURI, 601 bool aIsInitialDocument, 602 const mozilla::Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP = 603 mozilla::Nothing(), 604 bool aTryToSaveOldPresentation = true, bool aCheckPermitUnload = true, 605 mozilla::dom::WindowGlobalChild* aActor = nullptr); 606 607 nsresult CreateDocumentViewer(const nsACString& aContentType, 608 nsIRequest* aRequest, 609 nsIStreamListener** aContentHandler); 610 611 nsresult NewDocumentViewerObj(const nsACString& aContentType, 612 nsIRequest* aRequest, nsILoadGroup* aLoadGroup, 613 nsIStreamListener** aContentHandler, 614 nsIDocumentViewer** aViewer); 615 616 already_AddRefed<nsILoadURIDelegate> GetLoadURIDelegate(); 617 618 nsresult SetupNewViewer( 619 nsIDocumentViewer* aNewViewer, 620 mozilla::dom::WindowGlobalChild* aWindowActor = nullptr); 621 622 // 623 // Session History 624 // 625 626 // Either aChannel or aOwner must be null. If aChannel is 627 // present, the owner should be gotten from it. 628 // If aCloneChildren is true, then our current session history's 629 // children will be cloned onto the new entry. This should be 630 // used when we aren't actually changing the document while adding 631 // the new session history entry. 632 // aPolicyContainer is the policyContainer to be used for the load. That is 633 // *not* the policyContainer that will be applied to subresource loads within 634 // that document but the policyContainer for the document load itself. E.g. if 635 // that policyContainer's CSP includes upgrade-insecure-requests, then the new 636 // top-level load will be upgraded to HTTPS. 637 nsresult AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, 638 nsIPrincipal* aTriggeringPrincipal, 639 nsIPrincipal* aPrincipalToInherit, 640 nsIPrincipal* aPartitionedPrincipalToInherit, 641 nsIPolicyContainer* aPolicyContainer, 642 bool aCloneChildren, nsISHEntry** aNewEntry); 643 644 void UpdateActiveEntry( 645 bool aReplace, const mozilla::Maybe<nsPoint>& aPreviousScrollPos, 646 nsIURI* aURI, nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo, 647 nsIPrincipal* aTriggeringPrincipal, nsIPolicyContainer* aPolicyContainer, 648 const nsAString& aTitle, bool aScrollRestorationIsManual, 649 nsIStructuredCloneContainer* aData, bool aURIWasModified); 650 651 nsresult AddChildSHEntry(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry, 652 int32_t aChildOffset, uint32_t aLoadType, 653 bool aCloneChildren); 654 655 nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset, 656 bool aCloneChildren); 657 658 // Call this method to swap in a new history entry to m[OL]SHE, rather than 659 // setting it directly. This completes the navigation in all docshells 660 // in the case of a subframe navigation. 661 // Returns old mOSHE/mLSHE. 662 already_AddRefed<nsISHEntry> SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, 663 nsISHEntry* aEntry); 664 665 // This method calls SetHistoryEntry and updates mOSHE and mLSHE in BC to be 666 // the same as in docshell 667 void SetHistoryEntryAndUpdateBC(const mozilla::Maybe<nsISHEntry*>& aLSHE, 668 const mozilla::Maybe<nsISHEntry*>& aOSHE); 669 670 // If aNotifiedBeforeUnloadListeners is true, "beforeunload" event listeners 671 // were notified by the caller and given the chance to abort the navigation, 672 // and should not be notified again. 673 static nsresult ReloadDocument( 674 nsDocShell* aDocShell, mozilla::dom::Document* aDocument, 675 uint32_t aLoadType, mozilla::dom::BrowsingContext* aBrowsingContext, 676 nsIURI* aCurrentURI, nsIReferrerInfo* aReferrerInfo, 677 bool aNotifiedBeforeUnloadListeners = false); 678 679 public: 680 bool ShouldDoInitialAboutBlankSyncLoad(nsIURI* aURI, 681 nsDocShellLoadState* aLoadState, 682 nsIPrincipal* aPrincipalToInherit); 683 684 void UnsuppressPaintingIfNoNavigationAwayFromAboutBlank( 685 mozilla::PresShell* aPresShell); 686 687 bool HasStartedLoadingOtherThanInitialBlankURI(); 688 689 private: 690 // 691 // URI Load 692 // 693 694 // Actually open a channel and perform a URI load. Callers need to pass a 695 // non-null aLoadState->TriggeringPrincipal() which initiated the URI load. 696 // Please note that the TriggeringPrincipal will be used for performing 697 // security checks. If aLoadState->URI() is provided by the web, then please 698 // do not pass a SystemPrincipal as the triggeringPrincipal. If 699 // aLoadState()->PrincipalToInherit is null, then no inheritance of any sort 700 // will happen and the load will get a principal based on the URI being 701 // loaded. If the Srcdoc flag is set (INTERNAL_LOAD_FLAGS_IS_SRCDOC), the load 702 // will be considered as a srcdoc load, and the contents of Srcdoc will be 703 // loaded instead of the URI. aLoadState->OriginalURI() will be set as the 704 // originalURI on the channel that does the load. If OriginalURI is null, URI 705 // will be set as the originalURI. If LoadReplace is true, LOAD_REPLACE flag 706 // will be set on the nsIChannel. 707 // If `aCacheKey` is supplied, use it for the session history entry. 708 MOZ_CAN_RUN_SCRIPT nsresult DoURILoad(nsDocShellLoadState* aLoadState, 709 mozilla::Maybe<uint32_t> aCacheKey, 710 nsIRequest** aRequest); 711 712 // Implement require-trusted-types-for Pre-Navigation check on a javascript: 713 // URL. There is some disconnect between Trusted Types spec, CSP spec and 714 // implementations. We try to have something consistent with other browsers, 715 // following the intended goal of the Pre-Navigation check. 716 // https://w3c.github.io/webappsec-csp/#should-block-navigation-request 717 // https://w3c.github.io/trusted-types/dist/spec/#require-trusted-types-for-pre-navigation-check 718 // https://github.com/w3c/trusted-types/issues/548 719 // 720 // If trusted types are not required by a CSP policy, this returns immediately 721 // without side effect. Otherwise the method tries to modify aLoadState's URI 722 // to ensure its JavaScript code is a trusted script. 723 // @return An error if trusted types are required by an enforced CSP policy 724 // but the operation fails. NS_OK otherwise. 725 MOZ_CAN_RUN_SCRIPT nsresult PerformTrustedTypesPreNavigationCheck( 726 nsDocShellLoadState* aLoadState, nsGlobalWindowInner* aWindow) const; 727 728 nsresult CompleteInitialAboutBlankLoad(nsDocShellLoadState* aLoadState, 729 nsILoadInfo* aLoadInfo); 730 731 static nsresult AddHeadersToChannel(nsIInputStream* aHeadersData, 732 nsIChannel* aChannel); 733 734 nsresult OpenInitializedChannel(nsIChannel* aChannel, 735 nsIURILoader* aURILoader, 736 uint32_t aOpenFlags); 737 nsresult OpenRedirectedChannel(nsDocShellLoadState* aLoadState); 738 739 void UpdateMixedContentChannelForNewLoad(nsIChannel* aChannel); 740 741 MOZ_CAN_RUN_SCRIPT 742 nsresult ScrollToAnchor(bool aCurHasRef, bool aNewHasRef, 743 nsACString& aNewHash, uint32_t aLoadType); 744 745 // This returns the load type for a form submission (see 746 // https://html.spec.whatwg.org/#form-submission-algorithm). The load type 747 // should be set as soon as the target BC has been determined. 748 uint32_t GetLoadTypeForFormSubmission( 749 mozilla::dom::BrowsingContext* aTargetBC, 750 nsDocShellLoadState* aLoadState); 751 752 private: 753 // Returns true if it is the caller's responsibility to ensure 754 // FireOnLocationChange is called. 755 // In all other cases false is returned. 756 // Either aChannel or aTriggeringPrincipal must be null. If aChannel is 757 // present, the owner should be gotten from it. 758 // If OnNewURI calls AddToSessionHistory, it will pass its 759 // aCloneSHChildren argument as aCloneChildren. 760 // aPolicyContainer is the policyContainer to be used for the load. That is 761 // *not* the policyContainer that will be applied to subresource loads within 762 // that document but the policyContainer for the document load itself. E.g. if 763 // that policyContainer's CSP includes upgrade-insecure-requests, then the new 764 // top-level load will be upgraded to HTTPS. 765 bool OnNewURI(nsIURI* aURI, nsIChannel* aChannel, 766 nsIPrincipal* aTriggeringPrincipal, 767 nsIPrincipal* aPrincipalToInherit, 768 nsIPrincipal* aPartitionedPrincipalToInherit, 769 nsIPolicyContainer* aPolicyContainer, bool aAddToGlobalHistory, 770 bool aCloneSHChildren); 771 772 public: 773 // If wireframe collection is enabled, will attempt to gather the 774 // wireframe for the document. 775 mozilla::Maybe<mozilla::dom::Wireframe> GetWireframe(); 776 777 // If wireframe collection is enabled, will attempt to gather the 778 // wireframe for the document and stash it inside of the active history 779 // entry. Returns true if wireframes were collected. 780 bool CollectWireframe(); 781 782 // Helper method that is called when a new document (including any 783 // sub-documents - ie. frames) has been completely loaded. 784 MOZ_CAN_RUN_SCRIPT_BOUNDARY 785 nsresult EndPageLoad(nsIWebProgress* aProgress, nsIChannel* aChannel, 786 nsresult aResult); 787 788 // Builds an error page URI (e.g. about:neterror?etc) for the given aURI 789 // and displays it via the LoadErrorPage() overload below. 790 nsresult LoadErrorPage(nsIURI* aURI, const char16_t* aURL, 791 const char* aErrorPage, const char* aErrorType, 792 const char16_t* aDescription, const char* aCSSClass, 793 nsIChannel* aFailedChannel); 794 795 // This method directly loads aErrorURI as an error page. aFailedURI and 796 // aFailedChannel come from DisplayLoadError() or the LoadErrorPage() overload 797 // above. 798 nsresult LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, 799 nsIChannel* aFailedChannel); 800 801 bool DisplayLoadError(nsresult aError, nsIURI* aURI, const char16_t* aURL, 802 nsIChannel* aFailedChannel) { 803 bool didDisplayLoadError = false; 804 DisplayLoadError(aError, aURI, aURL, aFailedChannel, &didDisplayLoadError); 805 return didDisplayLoadError; 806 } 807 808 // Called when a document is recognised as content the device owner doesn't 809 // want to be displayed. Stops parsing, stops scripts, and displays an 810 // error page with DisplayLoadError. 811 void DisplayRestrictedContentError(); 812 813 // 814 // Uncategorized 815 // 816 817 // Get the principal that we'll set on the channel if we're inheriting. If 818 // aConsiderCurrentDocument is true, we try to use the current document if 819 // at all possible. If that fails, we fall back on the parent document. 820 // If that fails too, we force creation of a content viewer and use the 821 // resulting principal. If aConsiderCurrentDocument is false, we just look 822 // at the parent. 823 // If aConsiderPartitionedPrincipal is true, we consider the partitioned 824 // principal instead of the node principal. 825 nsIPrincipal* GetInheritedPrincipal( 826 bool aConsiderCurrentDocument, 827 bool aConsiderPartitionedPrincipal = false); 828 829 /** 830 * Helper function that caches a URI and a transition for saving later. 831 * 832 * @param aChannel 833 * Channel that will have these properties saved 834 * @param aURI 835 * The URI to save for later 836 * @param aChannelRedirectFlags 837 * The nsIChannelEventSink redirect flags to save for later 838 */ 839 static void SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI, 840 uint32_t aChannelRedirectFlags); 841 842 /** 843 * Helper function for adding a URI visit using IHistory. 844 * 845 * The IHistory API maintains chains of visits, tracking both HTTP referrers 846 * and redirects for a user session. VisitURI requires the current URI and 847 * the previous URI in the chain. 848 * 849 * Visits can be saved either during a redirect or when the request has 850 * reached its final destination. The previous URI in the visit may be 851 * from another redirect. 852 * 853 * @pre aURI is not null. 854 * 855 * @param aURI 856 * The URI that was just visited 857 * @param aPreviousURI 858 * The previous URI of this visit 859 * @param aChannelRedirectFlags 860 * For redirects, the redirect flags from nsIChannelEventSink 861 * (0 otherwise) 862 * @param aResponseStatus 863 * For HTTP channels, the response code (0 otherwise). 864 */ 865 void AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI, 866 uint32_t aChannelRedirectFlags, 867 uint32_t aResponseStatus = 0); 868 869 /** 870 * Internal helper funtion 871 */ 872 static void InternalAddURIVisit( 873 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags, 874 uint32_t aResponseStatus, mozilla::dom::BrowsingContext* aBrowsingContext, 875 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded); 876 877 static already_AddRefed<nsIURIFixupInfo> KeywordToURI( 878 const nsACString& aKeyword, bool aIsPrivateContext); 879 880 // Sets the current document's current state object to the given SHEntry's 881 // state object. The current state object is eventually given to the page 882 // in the PopState event. 883 void SetDocCurrentStateObj(nsISHEntry* aShEntry, 884 mozilla::dom::SessionHistoryInfo* aInfo); 885 886 // Returns true if would have called FireOnLocationChange, 887 // but did not because aFireOnLocationChange was false on entry. 888 // In this case it is the caller's responsibility to ensure 889 // FireOnLocationChange is called. 890 // In all other cases false is returned. 891 bool SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, 892 bool aFireOnLocationChange, bool aIsInitialAboutBlank, 893 uint32_t aLocationFlags); 894 895 // The following methods deal with saving and restoring content viewers 896 // in session history. 897 898 // mDocumentViewer points to the current content viewer associated with 899 // this docshell. When loading a new document, the content viewer is 900 // either destroyed or stored into a session history entry. To make sure 901 // that destruction happens in a controlled fashion, a given content viewer 902 // is always owned in exactly one of these ways: 903 // 1) The content viewer is active and owned by a docshell's 904 // mDocumentViewer. 905 // 2) The content viewer is still being displayed while we begin loading 906 // a new document. The content viewer is owned by the _new_ 907 // content viewer's mPreviousViewer, and has a pointer to the 908 // nsISHEntry where it will eventually be stored. The content viewer 909 // has been close()d by the docshell, which detaches the document from 910 // the window object. 911 // 3) The content viewer is cached in session history. The nsISHEntry 912 // has the only owning reference to the content viewer. The viewer 913 // has released its nsISHEntry pointer to prevent circular ownership. 914 // 915 // When restoring a content viewer from session history, open() is called 916 // to reattach the document to the window object. The content viewer is 917 // then placed into mDocumentViewer and removed from the history entry. 918 // (mDocumentViewer is put into session history as described above, if 919 // applicable). 920 921 // Determines whether we can safely cache the current mDocumentViewer in 922 // session history. This checks a number of factors such as cache policy, 923 // pending requests, and unload handlers. 924 // |aLoadType| should be the load type that will replace the current 925 // presentation. |aNewRequest| should be the request for the document to 926 // be loaded in place of the current document, or null if such a request 927 // has not been created yet. |aNewDocument| should be the document that will 928 // replace the current document. 929 bool CanSavePresentation(uint32_t aLoadType, nsIRequest* aNewRequest, 930 mozilla::dom::Document* aNewDocument, 931 bool aReportBFCacheComboTelemetry); 932 933 static void ReportBFCacheComboTelemetry(uint32_t aCombo); 934 935 // Captures the state of the supporting elements of the presentation 936 // (the "window" object, docshell tree, meta-refresh loads, and security 937 // state) and stores them on |mOSHE|. 938 nsresult CaptureState(); 939 940 // Begin the toplevel restore process for |aSHEntry|. 941 // This simulates a channel open, and defers the real work until 942 // RestoreFromHistory is called from a PLEvent. 943 nsresult RestorePresentation(nsISHEntry* aSHEntry, bool* aRestoring); 944 945 // Call BeginRestore(nullptr, false) for each child of this shell. 946 nsresult BeginRestoreChildren(); 947 948 // Method to get our current position and size without flushing 949 void DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, 950 int32_t* aHeight); 951 952 // Call this when a URI load is handed to us (via OnLinkClick or 953 // InternalLoad). This makes sure that we're not inside unload, or that if 954 // we are it's still OK to load this URI. 955 bool IsOKToLoadURI(nsIURI* aURI); 956 957 // helpers for executing commands 958 nsresult GetControllerForCommand(const char* aCommand, 959 nsIController** aResult); 960 961 // Possibly create a ClientSource object to represent an initial about:blank 962 // window that has not been allocated yet. Normally we try not to create 963 // this about:blank window until something calls GetDocument(). We still need 964 // the ClientSource to exist for this conceptual window, though. 965 // 966 // The ClientSource is created with the given principal if specified. If 967 // the principal is not provided we will attempt to inherit it when we 968 // are sure it will match what the real about:blank window principal 969 // would have been. There are some corner cases where we cannot easily 970 // determine the correct principal and will not create the ClientSource. 971 // In these cases the initial about:blank will appear to not exist until 972 // its real document and window are created. 973 void MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal = nullptr); 974 975 // Try to inherit the controller from same-origin parent. 976 void MaybeInheritController(mozilla::dom::ClientSource* aClientSource, 977 nsIPrincipal* aPrincipal); 978 979 // Determine if a service worker is allowed to control a window in this 980 // docshell with the given URL. If there are any reasons it should not, 981 // this will return false. If true is returned then the window *may* be 982 // controlled. The caller must still consult either the parent controller 983 // or the ServiceWorkerManager to determine if a service worker should 984 // actually control the window. 985 bool ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, 986 nsIURI* aURI); 987 988 // Return the ClientInfo for the initial about:blank window, if it exists 989 // or we have speculatively created a ClientSource in 990 // MaybeCreateInitialClientSource(). This can return a ClientInfo object 991 // even if GetExtantDoc() returns nullptr. 992 mozilla::Maybe<mozilla::dom::ClientInfo> GetInitialClientInfo() const; 993 994 /** 995 * Initializes mTiming if it isn't yet. 996 * After calling this, mTiming is non-null. This method returns true if the 997 * initialization of the Timing can be reset (basically this is true if a new 998 * Timing object is created). 999 * In case the loading is aborted, MaybeResetInitTiming() can be called 1000 * passing the return value of MaybeInitTiming(): if it's possible to reset 1001 * the Timing, this method will do it. 1002 */ 1003 [[nodiscard]] bool MaybeInitTiming(); 1004 void MaybeResetInitTiming(bool aReset); 1005 1006 // Convenience method for getting our parent docshell. Can return null 1007 already_AddRefed<nsDocShell> GetInProcessParentDocshell(); 1008 1009 // Internal implementation of nsIDocShell::FirePageHideNotification. 1010 // If aSkipCheckingDynEntries is true, it will not try to remove dynamic 1011 // subframe entries. This is to avoid redundant RemoveDynEntries calls in all 1012 // children docshells. 1013 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) 1014 MOZ_CAN_RUN_SCRIPT_BOUNDARY void FirePageHideNotificationInternal( 1015 bool aIsUnload, bool aSkipCheckingDynEntries); 1016 1017 void ThawFreezeNonRecursive(bool aThaw); 1018 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) 1019 MOZ_CAN_RUN_SCRIPT_BOUNDARY void FirePageHideShowNonRecursive(bool aShow); 1020 1021 nsresult Dispatch(already_AddRefed<nsIRunnable>&& aRunnable); 1022 1023 void ReattachEditorToWindow(nsISHEntry* aSHEntry); 1024 void ClearFrameHistory(nsISHEntry* aEntry); 1025 // Determine if this type of load should update history. 1026 static bool ShouldUpdateGlobalHistory(uint32_t aLoadType); 1027 void UpdateGlobalHistoryTitle(nsIURI* aURI); 1028 bool IsSubframe() { return mBrowsingContext->IsSubframe(); } 1029 bool CanSetOriginAttributes(); 1030 bool ShouldBlockLoadingForBackButton(); 1031 static bool ShouldDiscardLayoutState(nsIHttpChannel* aChannel); 1032 bool HasUnloadedParent(); 1033 bool JustStartedNetworkLoad(); 1034 bool NavigationBlockedByPrinting(bool aDisplayErrorDialog = true); 1035 bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true, 1036 bool aCheckIfUnloadFired = true); 1037 mozilla::ScrollContainerFrame* GetRootScrollContainerFrame(); 1038 nsIChannel* GetCurrentDocChannel(); 1039 nsresult EnsureScriptEnvironment(); 1040 nsresult EnsureEditorData(); 1041 nsresult EnsureTransferableHookData(); 1042 nsresult EnsureFind(); 1043 nsresult EnsureCommandHandler(); 1044 nsresult RefreshURIFromQueue(); 1045 void RefreshURIToQueue(); 1046 nsresult Embed(nsIDocumentViewer* aDocumentViewer, 1047 mozilla::dom::WindowGlobalChild* aWindowActor, 1048 bool aIsTransientAboutBlank, nsIRequest* aRequest, 1049 nsIURI* aPreviousURI); 1050 nsPresContext* GetEldestPresContext(); 1051 nsresult CheckLoadingPermissions(); 1052 1053 // Fire a traverse navigate event for a non-traversable navigable. 1054 MOZ_CAN_RUN_SCRIPT 1055 void MaybeFireTraverseHistory(nsDocShellLoadState* aLoadState); 1056 // Fire a traverse navigate event for a traversable navigable. Since this 1057 // participates in #checking-if-unloading-is-canceled we return false to 1058 // indicate that we should cancel the navigation. 1059 MOZ_CAN_RUN_SCRIPT 1060 nsIDocumentViewer::PermitUnloadResult MaybeFireTraversableTraverseHistory( 1061 const mozilla::dom::SessionHistoryInfo& aInfo, 1062 mozilla::Maybe<mozilla::dom::UserNavigationInvolvement> aUserInvolvement); 1063 1064 nsresult LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType, 1065 bool aUserActivation); 1066 nsresult LoadHistoryEntry( 1067 const mozilla::dom::LoadingSessionHistoryInfo& aEntry, uint32_t aLoadType, 1068 bool aUserActivation, bool aNotifiedBeforeUnloadListeners); 1069 MOZ_CAN_RUN_SCRIPT_BOUNDARY 1070 nsresult LoadHistoryEntry(nsDocShellLoadState* aLoadState, uint32_t aLoadType, 1071 bool aLoadingCurrentEntry); 1072 nsresult GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn); 1073 nsresult ConfirmRepost(bool* aRepost); 1074 nsresult GetPromptAndStringBundle(nsIPrompt** aPrompt, 1075 nsIStringBundle** aStringBundle); 1076 nsresult SetCurScrollPosEx(int32_t aCurHorizontalPos, 1077 int32_t aCurVerticalPos); 1078 nsPoint GetCurScrollPos(); 1079 1080 void RestoreScrollPositionFromTargetSessionHistoryInfo( 1081 mozilla::dom::SessionHistoryInfo* aTarget); 1082 1083 already_AddRefed<mozilla::dom::ChildSHistory> GetRootSessionHistory(); 1084 1085 bool CSSErrorReportingEnabled() const { return mCSSErrorReportingEnabled; } 1086 1087 // Handles retrieval of subframe session history for nsDocShell::LoadURI. If a 1088 // load is requested in a subframe of the current DocShell, the subframe 1089 // loadType may need to reflect the loadType of the parent document, or in 1090 // some cases (like reloads), the history load may need to be cancelled. See 1091 // function comments for in-depth logic descriptions. 1092 // Returns true if the method itself deals with the load. 1093 bool MaybeHandleSubframeHistory(nsDocShellLoadState* aLoadState, 1094 bool aContinueHandlingSubframeHistory); 1095 1096 // If we are passed a named target during InternalLoad, this method handles 1097 // moving the load to the browsing context the target name resolves to. 1098 nsresult PerformRetargeting(nsDocShellLoadState* aLoadState); 1099 1100 // Returns one of nsIContentPolicy::TYPE_DOCUMENT, 1101 // nsIContentPolicy::TYPE_INTERNAL_IFRAME, or 1102 // nsIContentPolicy::TYPE_INTERNAL_FRAME depending on who is responsible for 1103 // this docshell. 1104 nsContentPolicyType DetermineContentType(); 1105 1106 // If this is an iframe, and the embedder is OOP, then notifes the 1107 // embedder that loading has finished and we shouldn't be blocking 1108 // load of the embedder. Only called when we fail to load, as we wait 1109 // for the load event of our Document before notifying success. 1110 // 1111 // If aFireFrameErrorEvent is true, then fires an error event at the 1112 // embedder element, for both in-process and OOP embedders. 1113 void UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent = false); 1114 1115 // Check to see if we're loading a prior history entry or doing a fragment 1116 // navigation in the same document. 1117 // NOTE: In case we are doing a fragment navigation, and HTTPS-Only/ -First 1118 // mode is enabled and upgraded the underlying document, we update the URI of 1119 // aLoadState from HTTP to HTTPS (if neccessary). 1120 bool IsSameDocumentNavigation(nsDocShellLoadState* aLoadState, 1121 SameDocumentNavigationState& aState); 1122 1123 // ... If so, handle the scrolling or other action required instead of 1124 // continuing with new document navigation. 1125 MOZ_CAN_RUN_SCRIPT 1126 nsresult HandleSameDocumentNavigation(nsDocShellLoadState* aLoadState, 1127 SameDocumentNavigationState& aState, 1128 bool& aSameDocument); 1129 1130 uint32_t GetSameDocumentNavigationFlags(nsIURI* aNewURI); 1131 1132 // Called when the Private Browsing state of a nsDocShell changes. 1133 void NotifyPrivateBrowsingChanged(); 1134 1135 // Internal helpers for BrowsingContext to pass update values to nsIDocShell's 1136 // LoadGroup. 1137 void SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags); 1138 1139 void SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory); 1140 1141 void SetScrollRestorationIsManualOnHistoryEntry(nsISHEntry* aSHEntry, 1142 bool aIsManual); 1143 1144 void SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry, uint32_t aCacheKey); 1145 1146 // If the LoadState's URI is a javascript: URI, checks that the triggering 1147 // principal subsumes the principal of the current document, and returns 1148 // NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI if it does not. 1149 nsresult CheckDisallowedJavascriptLoad(nsDocShellLoadState* aLoadState); 1150 1151 nsresult LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating, 1152 bool aContinueHandlingSubframeHistory); 1153 1154 // Sets the active entry to the current loading entry. aPersist is used in the 1155 // case a new session history entry is added to the session history. 1156 // aExpired is true if the relevant nsIChannel has its cache token expired. 1157 // aCacheKey is the channel's cache key. 1158 // aPreviousURI should be the URI that was previously loaded into the 1159 // nsDocshell 1160 void MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey, 1161 nsIURI* aPreviousURI); 1162 1163 void ActivenessMaybeChanged(); 1164 1165 /** 1166 * Returns true if `noopener` will be force-enabled by any attempt to create 1167 * a popup window, even if rel="opener" is requested. 1168 */ 1169 bool NoopenerForceEnabled(); 1170 1171 bool ShouldOpenInBlankTarget(const nsAString& aOriginalTarget, 1172 nsIURI* aLinkURI, nsIContent* aContent, 1173 bool aIsUserTriggered); 1174 1175 void RecordSingleChannelId(bool aStartRequest, nsIRequest* aRequest); 1176 1177 void SetChannelToDisconnectOnPageHide(uint64_t aChannelId) { 1178 MOZ_ASSERT(mChannelToDisconnectOnPageHide == 0); 1179 mChannelToDisconnectOnPageHide = aChannelId; 1180 } 1181 void MaybeDisconnectChildListenersOnPageHide(); 1182 1183 /** 1184 * Helper for addState and document.open that does just the 1185 * history-manipulation guts. 1186 * 1187 * Arguments the spec defines: 1188 * 1189 * @param aDocument the document we're manipulating. This will get the new 1190 * URI. 1191 * @param aNewURI the new URI. 1192 * @param aData The serialized state data. May be null. 1193 * @param aHistoryHandling how to handle updating the history entries. 1194 * 1195 * Arguments we need internally because deriving them from the 1196 * others is a bit complicated: 1197 * 1198 * @param aCurrentURI the current URI we're working with. Might be null. 1199 * @param aEqualURIs whether the two URIs involved are equal. 1200 */ 1201 nsresult UpdateURLAndHistory( 1202 mozilla::dom::Document* aDocument, nsIURI* aNewURI, 1203 nsIStructuredCloneContainer* aData, 1204 mozilla::dom::NavigationHistoryBehavior aHistoryHandling, 1205 nsIURI* aCurrentURI, bool aEqualURIs); 1206 1207 bool IsSameDocumentAsActiveEntry( 1208 const mozilla::dom::SessionHistoryInfo& aSHInfo); 1209 1210 using nsIWebNavigation::Reload; 1211 1212 /** 1213 * Implementation of the spec algorithm #reload. 1214 * 1215 * Arguments the spec defines: 1216 * 1217 * @param aNavigationAPIState state for Navigation API. 1218 * @param aUserInvolvement if the user is involved in the reload. 1219 * 1220 * Arguments we need internally: 1221 * 1222 * @param aReloadFlags see nsIWebNavigation.reload. 1223 * @param aCx if the NavigateEvent is expected to fire aCx cannot be Nothing. 1224 */ 1225 MOZ_CAN_RUN_SCRIPT 1226 nsresult ReloadNavigable( 1227 mozilla::Maybe<mozilla::NotNull<JSContext*>> aCx, uint32_t aReloadFlags, 1228 nsIStructuredCloneContainer* aNavigationAPIState = nullptr, 1229 mozilla::dom::UserNavigationInvolvement aUserInvolvement = 1230 mozilla::dom::UserNavigationInvolvement::None, 1231 mozilla::dom::NavigationAPIMethodTracker* aNavigationAPIMethodTracker = 1232 nullptr); 1233 1234 private: 1235 MOZ_CAN_RUN_SCRIPT 1236 void InformNavigationAPIAboutAbortingNavigation(); 1237 1238 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) 1239 MOZ_CAN_RUN_SCRIPT_BOUNDARY 1240 void InformNavigationAPIAboutChildNavigableDestruction(); 1241 1242 enum class OngoingNavigation : uint8_t { NavigationID, Traversal }; 1243 enum class UnsetOngoingNavigation : bool { No, Yes }; 1244 // Implementation for `nsIWebNavigation::Stop`, extended to add a flag whether 1245 // to unset the ongoing navigation or not. 1246 MOZ_CAN_RUN_SCRIPT 1247 nsresult StopInternal(uint32_t aStopFlags, 1248 UnsetOngoingNavigation aUnsetOngoingNavigation); 1249 1250 MOZ_CAN_RUN_SCRIPT 1251 void SetOngoingNavigation( 1252 const mozilla::Maybe<OngoingNavigation>& aOngoingNavigation); 1253 1254 void SetCurrentURIInternal(nsIURI* aURI); 1255 1256 already_AddRefed<nsIWebProgressListener> BCWebProgressListener(); 1257 1258 // data members 1259 nsString mTitle; 1260 nsCString mOriginalUriString; 1261 nsTObserverArray<nsWeakPtr> mPrivacyObservers; 1262 nsTObserverArray<nsWeakPtr> mReflowObservers; 1263 nsTObserverArray<nsWeakPtr> mScrollObservers; 1264 mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource; 1265 nsCOMPtr<nsINetworkInterceptController> mInterceptController; 1266 RefPtr<nsDOMNavigationTiming> mTiming; 1267 RefPtr<nsDSURIContentListener> mContentListener; 1268 RefPtr<nsGlobalWindowOuter> mScriptGlobal; 1269 nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal; 1270 // The following 3 lists contain either nsITimer or nsRefreshTimer objects. 1271 // URIs to refresh are collected to mRefreshURIList. 1272 nsCOMPtr<nsIMutableArray> mRefreshURIList; 1273 // mSavedRefreshURIList is used to move the entries from mRefreshURIList to 1274 // mOSHE. 1275 nsCOMPtr<nsIMutableArray> mSavedRefreshURIList; 1276 // BFCache-in-parent implementation caches the entries in 1277 // mBFCachedRefreshURIList. 1278 nsCOMPtr<nsIMutableArray> mBFCachedRefreshURIList; 1279 uint64_t mContentWindowID; 1280 nsCOMPtr<nsIDocumentViewer> mDocumentViewer; 1281 nsCOMPtr<nsIWidget> mParentWidget; 1282 RefPtr<mozilla::dom::ChildSHistory> mSessionHistory; 1283 nsCOMPtr<nsIWebBrowserFind> mFind; 1284 RefPtr<nsCommandManager> mCommandManager; 1285 RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext; 1286 RefPtr<nsBrowserStatusFilter> mBCWebProgressStatusFilter; 1287 1288 // Weak reference to our BrowserChild actor. 1289 nsWeakPtr mBrowserChild; 1290 1291 // Dimensions of the docshell 1292 mozilla::LayoutDeviceIntRect mBounds; 1293 1294 /** 1295 * Content-Type Hint of the most-recently initiated load. Used for 1296 * session history entries. 1297 */ 1298 nsCString mContentTypeHint; 1299 1300 // mCurrentURI should be marked immutable on set if possible. 1301 // Change mCurrentURI only through SetCurrentURIInternal method. 1302 nsCOMPtr<nsIURI> mCurrentURI; 1303 nsCOMPtr<nsIReferrerInfo> mReferrerInfo; 1304 1305 #ifdef DEBUG 1306 // We're counting the number of |nsDocShells| to help find leaks 1307 static unsigned long gNumberOfDocShells; 1308 1309 nsCOMPtr<nsIURI> mLastOpenedURI; 1310 #endif 1311 1312 // Reference to the SHEntry for this docshell until the page is destroyed. 1313 // Somebody give me better name 1314 // Only used when SHIP is disabled. 1315 nsCOMPtr<nsISHEntry> mOSHE; 1316 1317 // Reference to the SHEntry for this docshell until the page is loaded 1318 // Somebody give me better name. 1319 // If mLSHE is non-null, non-pushState subframe loads don't create separate 1320 // root history entries. That is, frames loaded during the parent page 1321 // load don't generate history entries the way frame navigation after the 1322 // parent has loaded does. (This isn't the only purpose of mLSHE.) 1323 // Only used when SHIP is disabled. 1324 nsCOMPtr<nsISHEntry> mLSHE; 1325 1326 // The ongoing navigation should really be a UUID, "traverse" or null, but 1327 // until we actually start using the UUID we'll only store an enum value. 1328 // Nothing here is interpreted as null. 1329 // https://html.spec.whatwg.org/#ongoing-navigation 1330 mozilla::Maybe<OngoingNavigation> mOngoingNavigation; 1331 1332 // These are only set when fission.sessionHistoryInParent is set. 1333 mozilla::UniquePtr<mozilla::dom::SessionHistoryInfo> mActiveEntry; 1334 bool mActiveEntryIsLoadingFromSessionHistory = false; 1335 // mLoadingEntry is set when we're about to start loading. Whenever 1336 // setting mLoadingEntry, be sure to also set 1337 // mNeedToReportActiveAfterLoadingBecomesActive. 1338 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> mLoadingEntry; 1339 1340 // Holds a weak pointer to a RestorePresentationEvent object if any that 1341 // holds a weak pointer back to us. We use this pointer to possibly revoke 1342 // the event whenever necessary. 1343 nsRevocableEventPtr<RestorePresentationEvent> mRestorePresentationEvent; 1344 1345 // Editor data, if this document is designMode or contentEditable. 1346 mozilla::UniquePtr<nsDocShellEditorData> mEditorData; 1347 1348 // The URI we're currently loading. This is only relevant during the 1349 // firing of a pagehide/unload. The caller of FirePageHideNotification() 1350 // is responsible for setting it and unsetting it. It may be null if the 1351 // pagehide/unload is happening for some reason other than just loading a 1352 // new URI. 1353 nsCOMPtr<nsIURI> mLoadingURI; 1354 1355 // Set in LoadErrorPage from the method argument and used later 1356 // in CreateDocumentViewer. We have to delay an shistory entry creation 1357 // for which these objects are needed. 1358 nsCOMPtr<nsIURI> mFailedURI; 1359 nsCOMPtr<nsIChannel> mFailedChannel; 1360 1361 mozilla::UniquePtr<mozilla::gfx::Matrix5x4> mColorMatrix; 1362 1363 const mozilla::Encoding* mParentCharset; 1364 1365 // WEAK REFERENCES BELOW HERE. 1366 // Note these are intentionally not addrefd. Doing so will create a cycle. 1367 // For that reasons don't use nsCOMPtr. 1368 1369 nsIDocShellTreeOwner* mTreeOwner; // Weak Reference 1370 1371 RefPtr<mozilla::dom::EventTarget> mChromeEventHandler; 1372 1373 mozilla::ScrollbarPreference mScrollbarPref; // persistent across doc loads 1374 1375 eCharsetReloadState mCharsetReloadState; 1376 1377 int32_t mParentCharsetSource; 1378 mozilla::CSSIntSize mFrameMargins; 1379 1380 // This can either be a content docshell or a chrome docshell. 1381 const int32_t mItemType; 1382 1383 // Index into the nsISHEntry array, indicating the previous and current 1384 // entry at the time that this DocShell begins to load. Consequently 1385 // root docshell's indices can differ from child docshells'. 1386 int32_t mPreviousEntryIndex; 1387 int32_t mLoadedEntryIndex; 1388 1389 BusyFlags mBusyFlags; 1390 AppType mAppType; 1391 uint32_t mLoadType; 1392 uint32_t mFailedLoadType; 1393 1394 // See WindowGlobalParent::mSingleChannelId. 1395 mozilla::Maybe<uint64_t> mSingleChannelId; 1396 uint32_t mRequestForBlockingFromBFCacheCount = 0; 1397 1398 uint64_t mChannelToDisconnectOnPageHide; 1399 1400 uint32_t mPendingReloadCount = 0; 1401 1402 // The following two fields cannot be declared as bit fields 1403 // because of uses with AutoRestore. 1404 bool mCreatingDocument; // (should be) debugging only 1405 #ifdef DEBUG 1406 bool mInEnsureScriptEnv; 1407 uint64_t mDocShellID = 0; 1408 #endif 1409 1410 bool mInitialized : 1; 1411 bool mAllowSubframes : 1; 1412 bool mAllowMetaRedirects : 1; 1413 bool mAllowImages : 1; 1414 bool mAllowMedia : 1; 1415 bool mAllowDNSPrefetch : 1; 1416 bool mAllowWindowControl : 1; 1417 bool mCSSErrorReportingEnabled : 1; 1418 bool mAllowAuth : 1; 1419 bool mAllowKeywordFixup : 1; 1420 bool mDisableMetaRefreshWhenInactive : 1; 1421 bool mIsAppTab : 1; 1422 bool mWindowDraggingAllowed : 1; 1423 bool mInFrameSwap : 1; 1424 1425 // This boolean is set to true right before we fire pagehide and generally 1426 // unset when we embed a new content viewer. While it's true no navigation 1427 // is allowed in this docshell. 1428 bool mFiredUnloadEvent : 1; 1429 1430 // this flag is for bug #21358. a docshell may load many urls 1431 // which don't result in new documents being created (i.e. a new 1432 // content viewer) we want to make sure we don't call a on load 1433 // event more than once for a given content viewer. 1434 bool mEODForCurrentDocument : 1; 1435 bool mURIResultedInDocument : 1; 1436 1437 bool mIsBeingDestroyed : 1; 1438 1439 bool mIsExecutingOnLoadHandler : 1; 1440 1441 // Indicates to CreateDocumentViewer() that it is safe to cache the old 1442 // presentation of the page, and to SetupNewViewer() that the old viewer 1443 // should be passed a SHEntry to save itself into. 1444 // Only used with SHIP disabled. 1445 bool mSavingOldViewer : 1; 1446 1447 bool mInvisible : 1; 1448 1449 // There has been an OnStartRequest for a non-about:blank URI 1450 bool mHasLoadedNonBlankURI : 1; 1451 1452 // There has been a DoURILoad that wasn't the initial commit to about:blank 1453 bool mHasStartedLoadingOtherThanInitialBlankURI : 1; 1454 1455 // This flag means that mTiming has been initialized but nulled out. 1456 // We will check the innerWin's timing before creating a new one 1457 // in MaybeInitTiming() 1458 bool mBlankTiming : 1; 1459 1460 // This flag indicates when the title is valid for the current URI. 1461 bool mTitleValidForCurrentURI : 1; 1462 1463 // If mWillChangeProcess is set to true, then when the docshell is destroyed, 1464 // we prepare the browsing context to change process. 1465 bool mWillChangeProcess : 1; 1466 1467 // This flag indicates whether or not the DocShell is currently executing an 1468 // nsIWebNavigation navigation method. 1469 bool mIsNavigating : 1; 1470 1471 // Whether we have a pending encoding autodetection request from the 1472 // menu for all encodings. 1473 bool mForcedAutodetection : 1; 1474 1475 /* 1476 * Set to true if we're checking session history (in the parent process) for 1477 * a possible history load. Used only with iframes. 1478 */ 1479 bool mCheckingSessionHistory : 1; 1480 1481 // Whether mBrowsingContext->SetActiveSessionHistoryEntry() needs to be called 1482 // when the loading entry becomes the active entry. This is used for the 1483 // initial about:blank-replacing about:blank in order to make the history 1484 // length WPTs pass. 1485 bool mNeedToReportActiveAfterLoadingBecomesActive : 1; 1486 }; 1487 1488 inline nsISupports* ToSupports(nsDocShell* aDocShell) { 1489 return static_cast<nsIDocumentLoader*>(aDocShell); 1490 } 1491 1492 #endif /* nsDocShell_h__ */