LCOV - code coverage report
Current view: top level - layout/base - nsDocumentViewer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 864 2039 42.4 %
Date: 2017-07-14 16:53:18 Functions: 95 186 51.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 sw=2 et 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             : /* container for a document and its presentation */
       8             : 
       9             : #include "gfxContext.h"
      10             : #include "mozilla/ServoRestyleManager.h"
      11             : #include "mozilla/ServoStyleSet.h"
      12             : #include "nsAutoPtr.h"
      13             : #include "nscore.h"
      14             : #include "nsCOMPtr.h"
      15             : #include "nsCRT.h"
      16             : #include "nsString.h"
      17             : #include "nsReadableUtils.h"
      18             : #include "nsIContent.h"
      19             : #include "nsIContentViewerContainer.h"
      20             : #include "nsIContentViewer.h"
      21             : #include "nsIDocumentViewerPrint.h"
      22             : #include "mozilla/dom/BeforeUnloadEvent.h"
      23             : #include "nsIDocument.h"
      24             : #include "nsPresContext.h"
      25             : #include "nsIPresShell.h"
      26             : #include "mozilla/StyleSetHandle.h"
      27             : #include "mozilla/StyleSetHandleInlines.h"
      28             : #include "nsIFrame.h"
      29             : #include "nsIWritablePropertyBag2.h"
      30             : #include "nsSubDocumentFrame.h"
      31             : 
      32             : #include "nsILinkHandler.h"
      33             : #include "nsIDOMDocument.h"
      34             : #include "nsISelectionListener.h"
      35             : #include "mozilla/dom/Selection.h"
      36             : #include "nsIDOMHTMLDocument.h"
      37             : #include "nsIDOMHTMLElement.h"
      38             : #include "nsContentUtils.h"
      39             : #include "nsLayoutStylesheetCache.h"
      40             : #ifdef ACCESSIBILITY
      41             : #include "mozilla/a11y/DocAccessible.h"
      42             : #endif
      43             : #include "mozilla/BasicEvents.h"
      44             : #include "mozilla/Encoding.h"
      45             : #include "mozilla/Preferences.h"
      46             : #include "mozilla/WeakPtr.h"
      47             : #include "mozilla/StyleSheet.h"
      48             : #include "mozilla/StyleSheetInlines.h"
      49             : 
      50             : #include "nsViewManager.h"
      51             : #include "nsView.h"
      52             : 
      53             : #include "nsIPageSequenceFrame.h"
      54             : #include "nsNetUtil.h"
      55             : #include "nsIContentViewerEdit.h"
      56             : #include "nsIContentViewerFile.h"
      57             : #include "mozilla/StyleSheetInlines.h"
      58             : #include "mozilla/css/Loader.h"
      59             : #include "nsIInterfaceRequestor.h"
      60             : #include "nsIInterfaceRequestorUtils.h"
      61             : #include "nsDocShell.h"
      62             : #include "nsIBaseWindow.h"
      63             : #include "nsILayoutHistoryState.h"
      64             : #include "nsCharsetSource.h"
      65             : #include "mozilla/ReflowInput.h"
      66             : #include "nsIImageLoadingContent.h"
      67             : #include "nsCopySupport.h"
      68             : #include "nsIDOMHTMLFrameSetElement.h"
      69             : #include "nsIDOMHTMLImageElement.h"
      70             : #ifdef MOZ_XUL
      71             : #include "nsIXULDocument.h"
      72             : #include "nsXULPopupManager.h"
      73             : #endif
      74             : 
      75             : #include "nsIClipboardHelper.h"
      76             : 
      77             : #include "nsPIDOMWindow.h"
      78             : #include "nsGlobalWindow.h"
      79             : #include "nsDOMNavigationTiming.h"
      80             : #include "nsPIWindowRoot.h"
      81             : #include "nsJSEnvironment.h"
      82             : #include "nsFocusManager.h"
      83             : 
      84             : #include "nsIScrollableFrame.h"
      85             : #include "nsStyleSheetService.h"
      86             : #include "nsILoadContext.h"
      87             : 
      88             : #include "nsIPrompt.h"
      89             : #include "imgIContainer.h" // image animation mode constants
      90             : 
      91             : #include "nsSandboxFlags.h"
      92             : 
      93             : #include "mozilla/DocLoadingTimelineMarker.h"
      94             : 
      95             : //--------------------------
      96             : // Printing Include
      97             : //---------------------------
      98             : #ifdef NS_PRINTING
      99             : 
     100             : #include "nsIWebBrowserPrint.h"
     101             : 
     102             : #include "nsPrintEngine.h"
     103             : 
     104             : // Print Options
     105             : #include "nsIPrintSettings.h"
     106             : #include "nsIPrintSettingsService.h"
     107             : #include "nsISimpleEnumerator.h"
     108             : 
     109             : #include "nsIPluginDocument.h"
     110             : 
     111             : #endif // NS_PRINTING
     112             : 
     113             : //focus
     114             : #include "nsIDOMEventTarget.h"
     115             : #include "nsIDOMEventListener.h"
     116             : #include "nsISelectionController.h"
     117             : 
     118             : #include "mozilla/EventDispatcher.h"
     119             : #include "nsISHEntry.h"
     120             : #include "nsISHistory.h"
     121             : #include "nsISHistoryInternal.h"
     122             : #include "nsIWebNavigation.h"
     123             : #include "mozilla/dom/XMLHttpRequestMainThread.h"
     124             : 
     125             : //paint forcing
     126             : #include <stdio.h>
     127             : 
     128             : #include "mozilla/dom/Element.h"
     129             : #include "mozilla/Telemetry.h"
     130             : 
     131             : using namespace mozilla;
     132             : using namespace mozilla::dom;
     133             : 
     134             : #define BEFOREUNLOAD_DISABLED_PREFNAME "dom.disable_beforeunload"
     135             : #define BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME "dom.require_user_interaction_for_beforeunload"
     136             : 
     137             : //-----------------------------------------------------
     138             : // LOGGING
     139             : #include "LayoutLogging.h"
     140             : #include "mozilla/Logging.h"
     141             : 
     142             : #ifdef NS_PRINTING
     143             : static mozilla::LazyLogModule gPrintingLog("printing");
     144             : 
     145             : #define PR_PL(_p1)  MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1);
     146             : #endif // NS_PRINTING
     147             : 
     148             : #define PRT_YESNO(_p) ((_p)?"YES":"NO")
     149             : //-----------------------------------------------------
     150             : 
     151             : class nsDocumentViewer;
     152             : namespace mozilla {
     153             : class AutoPrintEventDispatcher;
     154             : }
     155             : 
     156             : // a small delegate class used to avoid circular references
     157             : 
     158             : class nsDocViewerSelectionListener : public nsISelectionListener
     159             : {
     160             : public:
     161             : 
     162             :   // nsISupports interface...
     163             :   NS_DECL_ISUPPORTS
     164             : 
     165             :   // nsISelectionListerner interface
     166             :   NS_DECL_NSISELECTIONLISTENER
     167             : 
     168          28 :                        nsDocViewerSelectionListener()
     169          28 :                        : mDocViewer(nullptr)
     170          28 :                        , mSelectionWasCollapsed(true)
     171             :                        {
     172          28 :                        }
     173             : 
     174             :   nsresult             Init(nsDocumentViewer *aDocViewer);
     175             : 
     176           3 :   void                 Disconnect() { mDocViewer = nullptr; }
     177             : 
     178             : protected:
     179             : 
     180           9 :   virtual              ~nsDocViewerSelectionListener() {}
     181             : 
     182             :   nsDocumentViewer*    mDocViewer;
     183             :   bool                 mSelectionWasCollapsed;
     184             : 
     185             : };
     186             : 
     187             : 
     188             : /** editor Implementation of the FocusListener interface
     189             :  */
     190             : class nsDocViewerFocusListener : public nsIDOMEventListener
     191             : {
     192             : public:
     193             :   /** default constructor
     194             :    */
     195             :   nsDocViewerFocusListener();
     196             : 
     197             :   NS_DECL_ISUPPORTS
     198             :   NS_DECL_NSIDOMEVENTLISTENER
     199             : 
     200             :   nsresult             Init(nsDocumentViewer *aDocViewer);
     201             : 
     202           7 :   void                 Disconnect() { mDocViewer = nullptr; }
     203             : 
     204             : protected:
     205             :   /** default destructor
     206             :    */
     207             :   virtual ~nsDocViewerFocusListener();
     208             : 
     209             : private:
     210             :     nsDocumentViewer*  mDocViewer;
     211             : };
     212             : 
     213             : 
     214             : //-------------------------------------------------------------
     215             : class nsDocumentViewer final : public nsIContentViewer,
     216             :                                public nsIContentViewerEdit,
     217             :                                public nsIContentViewerFile,
     218             :                                public nsIDocumentViewerPrint
     219             : 
     220             : #ifdef NS_PRINTING
     221             :                              , public nsIWebBrowserPrint
     222             : #endif
     223             : 
     224             : {
     225             :   friend class nsDocViewerSelectionListener;
     226             :   friend class nsPagePrintTimer;
     227             :   friend class nsPrintEngine;
     228             : 
     229             : public:
     230             :   nsDocumentViewer();
     231             : 
     232             :   // nsISupports interface...
     233             :   NS_DECL_ISUPPORTS
     234             : 
     235             :   // nsIContentViewer interface...
     236             :   NS_DECL_NSICONTENTVIEWER
     237             : 
     238             :   // nsIContentViewerEdit
     239             :   NS_DECL_NSICONTENTVIEWEREDIT
     240             : 
     241             :   // nsIContentViewerFile
     242             :   NS_DECL_NSICONTENTVIEWERFILE
     243             : 
     244             : #ifdef NS_PRINTING
     245             :   // nsIWebBrowserPrint
     246             :   NS_DECL_NSIWEBBROWSERPRINT
     247             : #endif
     248             : 
     249             :   typedef void (*CallChildFunc)(nsIContentViewer* aViewer, void* aClosure);
     250             :   void CallChildren(CallChildFunc aFunc, void* aClosure);
     251             : 
     252             :   // nsIDocumentViewerPrint Printing Methods
     253             :   NS_DECL_NSIDOCUMENTVIEWERPRINT
     254             : 
     255             : protected:
     256             :   virtual ~nsDocumentViewer();
     257             : 
     258             : private:
     259             :   /**
     260             :    * Creates a view manager, root view, and widget for the root view, setting
     261             :    * mViewManager and mWindow.
     262             :    * @param aSize the initial size in appunits
     263             :    * @param aContainerView the container view to hook our root view up
     264             :    * to as a child, or null if this will be the root view manager
     265             :    */
     266             :   nsresult MakeWindow(const nsSize& aSize, nsView* aContainerView);
     267             : 
     268             :   /**
     269             :    * Create our device context
     270             :    */
     271             :   nsresult CreateDeviceContext(nsView* aContainerView);
     272             : 
     273             :   /**
     274             :    * If aDoCreation is true, this creates the device context, creates a
     275             :    * prescontext if necessary, and calls MakeWindow.
     276             :    *
     277             :    * If aForceSetNewDocument is false, then SetNewDocument won't be
     278             :    * called if the window's current document is already mDocument.
     279             :    */
     280             :   nsresult InitInternal(nsIWidget* aParentWidget,
     281             :                         nsISupports *aState,
     282             :                         const nsIntRect& aBounds,
     283             :                         bool aDoCreation,
     284             :                         bool aNeedMakeCX = true,
     285             :                         bool aForceSetNewDocument = true);
     286             :   /**
     287             :    * @param aDoInitialReflow set to true if you want to kick off the initial
     288             :    * reflow
     289             :    */
     290             :   nsresult InitPresentationStuff(bool aDoInitialReflow);
     291             : 
     292             :   nsresult GetPopupNode(nsIDOMNode** aNode);
     293             :   nsresult GetPopupLinkNode(nsIDOMNode** aNode);
     294             :   nsresult GetPopupImageNode(nsIImageLoadingContent** aNode);
     295             : 
     296             :   nsresult GetContentSizeInternal(int32_t* aWidth, int32_t* aHeight,
     297             :                                   nscoord aMaxWidth, nscoord aMaxHeight);
     298             : 
     299             :   void PrepareToStartLoad(void);
     300             : 
     301             :   nsresult SyncParentSubDocMap();
     302             : 
     303             :   mozilla::dom::Selection* GetDocumentSelection();
     304             : 
     305             :   void DestroyPresShell();
     306             :   void DestroyPresContext();
     307             : 
     308             : #ifdef NS_PRINTING
     309             :   // Called when the DocViewer is notified that the state
     310             :   // of Printing or PP has changed
     311             :   void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
     312             :                                    bool                 aIsPrintingOrPP,
     313             :                                    bool                 aStartAtTop);
     314             : #endif // NS_PRINTING
     315             : 
     316             :   // Whether we should attach to the top level widget. This is true if we
     317             :   // are sharing/recycling a single base widget and not creating multiple
     318             :   // child widgets.
     319             :   bool ShouldAttachToTopLevel();
     320             : 
     321             : protected:
     322             :   // These return the current shell/prescontext etc.
     323             :   nsIPresShell* GetPresShell();
     324             :   nsPresContext* GetPresContext();
     325             :   nsViewManager* GetViewManager();
     326             : 
     327             :   void DetachFromTopLevelWidget();
     328             : 
     329             :   void SetPrintRelated();
     330             : 
     331             :   // IMPORTANT: The ownership implicit in the following member
     332             :   // variables has been explicitly checked and set using nsCOMPtr
     333             :   // for owning pointers and raw COM interface pointers for weak
     334             :   // (ie, non owning) references. If you add any members to this
     335             :   // class, please make the ownership explicit (pinkerton, scc).
     336             : 
     337             :   WeakPtr<nsDocShell> mContainer; // it owns me!
     338             :   nsWeakPtr mTopContainerWhilePrinting;
     339             :   RefPtr<nsDeviceContext> mDeviceContext;  // We create and own this baby
     340             : 
     341             :   // the following six items are explicitly in this order
     342             :   // so they will be destroyed in the reverse order (pinkerton, scc)
     343             :   nsCOMPtr<nsIDocument>    mDocument;
     344             :   nsCOMPtr<nsIWidget>      mWindow;      // may be null
     345             :   RefPtr<nsViewManager> mViewManager;
     346             :   RefPtr<nsPresContext>  mPresContext;
     347             :   nsCOMPtr<nsIPresShell>   mPresShell;
     348             : 
     349             :   RefPtr<nsDocViewerSelectionListener> mSelectionListener;
     350             :   RefPtr<nsDocViewerFocusListener> mFocusListener;
     351             : 
     352             :   nsCOMPtr<nsIContentViewer> mPreviousViewer;
     353             :   nsCOMPtr<nsISHEntry> mSHEntry;
     354             : 
     355             :   nsIWidget* mParentWidget; // purposely won't be ref counted.  May be null
     356             :   bool mAttachedToParent; // view is attached to the parent widget
     357             : 
     358             :   nsIntRect mBounds;
     359             : 
     360             :   // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
     361             :   // presshell only.
     362             :   float mTextZoom;      // Text zoom, defaults to 1.0
     363             :   float mPageZoom;
     364             :   float mOverrideDPPX;  // DPPX overrided, defaults to 0.0
     365             :   int mMinFontSize;
     366             : 
     367             :   int16_t mNumURLStarts;
     368             :   int16_t mDestroyRefCount;    // a second "refcount" for the document viewer's "destroy"
     369             : 
     370             :   unsigned      mStopped : 1;
     371             :   unsigned      mLoaded : 1;
     372             :   unsigned      mDeferredWindowClose : 1;
     373             :   // document management data
     374             :   //   these items are specific to markup documents (html and xml)
     375             :   //   may consider splitting these out into a subclass
     376             :   unsigned      mIsSticky : 1;
     377             :   unsigned      mInPermitUnload : 1;
     378             :   unsigned      mInPermitUnloadPrompt: 1;
     379             : 
     380             : #ifdef NS_PRINTING
     381             :   unsigned      mClosingWhilePrinting : 1;
     382             : 
     383             : #if NS_PRINT_PREVIEW
     384             :   unsigned                         mPrintPreviewZoomed : 1;
     385             : 
     386             :   // These data members support delayed printing when the document is loading
     387             :   unsigned                         mPrintIsPending : 1;
     388             :   unsigned                         mPrintDocIsFullyLoaded : 1;
     389             :   nsCOMPtr<nsIPrintSettings>       mCachedPrintSettings;
     390             :   nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
     391             : 
     392             :   RefPtr<nsPrintEngine>          mPrintEngine;
     393             :   float                            mOriginalPrintPreviewScale;
     394             :   float                            mPrintPreviewZoom;
     395             :   nsAutoPtr<AutoPrintEventDispatcher> mAutoBeforeAndAfterPrint;
     396             : #endif // NS_PRINT_PREVIEW
     397             : 
     398             : #ifdef DEBUG
     399             :   FILE* mDebugFile;
     400             : #endif // DEBUG
     401             : #endif // NS_PRINTING
     402             : 
     403             :   /* character set member data */
     404             :   int32_t mHintCharsetSource;
     405             :   const Encoding* mHintCharset;
     406             :   const Encoding* mForceCharacterSet;
     407             : 
     408             :   bool mIsPageMode;
     409             :   bool mInitializedForPrintPreview;
     410             :   bool mHidden;
     411             :   bool mPrintRelated; // Only use for asserts.
     412             :   bool mPresShellDestroyed; // Only use for asserts.
     413             :   bool mDestroyWasFull; // Only use for asserts.
     414             : };
     415             : 
     416             : namespace mozilla {
     417             : 
     418             : /**
     419             :  * A RAII class for automatic dispatch of the 'beforeprint' and 'afterprint'
     420             :  * events ('beforeprint' on construction, 'afterprint' on destruction).
     421             :  *
     422             :  * https://developer.mozilla.org/en-US/docs/Web/Events/beforeprint
     423             :  * https://developer.mozilla.org/en-US/docs/Web/Events/afterprint
     424             :  */
     425             : class AutoPrintEventDispatcher
     426             : {
     427             : public:
     428           0 :   explicit AutoPrintEventDispatcher(nsIDocument* aTop) : mTop(aTop)
     429             :   {
     430           0 :     DispatchEventToWindowTree(NS_LITERAL_STRING("beforeprint"));
     431           0 :   }
     432           0 :   ~AutoPrintEventDispatcher()
     433           0 :   {
     434           0 :     DispatchEventToWindowTree(NS_LITERAL_STRING("afterprint"));
     435           0 :   }
     436             : 
     437             : private:
     438           0 :   void DispatchEventToWindowTree(const nsAString& aEvent)
     439             :   {
     440           0 :     nsCOMArray<nsIDocument> targets;
     441           0 :     CollectDocuments(mTop, &targets);
     442           0 :     for (int32_t i = 0; i < targets.Count(); ++i) {
     443           0 :       nsIDocument* d = targets[i];
     444           0 :       nsContentUtils::DispatchTrustedEvent(d, d->GetWindow(),
     445           0 :                                            aEvent, false, false, nullptr);
     446             :     }
     447           0 :   }
     448             : 
     449           0 :   static bool CollectDocuments(nsIDocument* aDocument, void* aData)
     450             :   {
     451           0 :     if (aDocument) {
     452           0 :       static_cast<nsCOMArray<nsIDocument>*>(aData)->AppendObject(aDocument);
     453           0 :       aDocument->EnumerateSubDocuments(CollectDocuments, aData);
     454             :     }
     455           0 :     return true;
     456             :   }
     457             : 
     458             :   nsCOMPtr<nsIDocument> mTop;
     459             : };
     460             : 
     461             : }
     462             : 
     463          15 : class nsDocumentShownDispatcher : public Runnable
     464             : {
     465             : public:
     466           5 :   explicit nsDocumentShownDispatcher(nsCOMPtr<nsIDocument> aDocument)
     467           5 :     : Runnable("nsDocumentShownDispatcher"), mDocument(aDocument) {}
     468             : 
     469             :   NS_IMETHOD Run() override;
     470             : 
     471             : private:
     472             :   nsCOMPtr<nsIDocument> mDocument;
     473             : };
     474             : 
     475             : 
     476             : //------------------------------------------------------------------
     477             : // nsDocumentViewer
     478             : //------------------------------------------------------------------
     479             : 
     480             : //------------------------------------------------------------------
     481             : already_AddRefed<nsIContentViewer>
     482          29 : NS_NewContentViewer()
     483             : {
     484          58 :   RefPtr<nsDocumentViewer> viewer = new nsDocumentViewer();
     485          58 :   return viewer.forget();
     486             : }
     487             : 
     488          50 : void nsDocumentViewer::PrepareToStartLoad()
     489             : {
     490          50 :   mStopped          = false;
     491          50 :   mLoaded           = false;
     492          50 :   mAttachedToParent = false;
     493          50 :   mDeferredWindowClose = false;
     494             : 
     495             : #ifdef NS_PRINTING
     496          50 :   mPrintIsPending        = false;
     497          50 :   mPrintDocIsFullyLoaded = false;
     498          50 :   mClosingWhilePrinting  = false;
     499             : 
     500             :   // Make sure we have destroyed it and cleared the data member
     501          50 :   if (mPrintEngine) {
     502           0 :     mPrintEngine->Destroy();
     503           0 :     mPrintEngine = nullptr;
     504             : #ifdef NS_PRINT_PREVIEW
     505           0 :     SetIsPrintPreview(false);
     506             : #endif
     507             :   }
     508             : 
     509             : #ifdef DEBUG
     510          50 :   mDebugFile = nullptr;
     511             : #endif
     512             : 
     513             : #endif // NS_PRINTING
     514          50 : }
     515             : 
     516          29 : nsDocumentViewer::nsDocumentViewer()
     517             :   : mParentWidget(nullptr),
     518             :     mAttachedToParent(false),
     519             :     mTextZoom(1.0),
     520             :     mPageZoom(1.0),
     521             :     mOverrideDPPX(0.0),
     522             :     mMinFontSize(0),
     523             :     mNumURLStarts(0),
     524             :     mDestroyRefCount(0),
     525             :     mStopped(false),
     526             :     mLoaded(false),
     527             :     mDeferredWindowClose(false),
     528             :     mIsSticky(true),
     529             :     mInPermitUnload(false),
     530             :     mInPermitUnloadPrompt(false),
     531             : #ifdef NS_PRINTING
     532             :     mClosingWhilePrinting(false),
     533             : #if NS_PRINT_PREVIEW
     534             :     mPrintPreviewZoomed(false),
     535             :     mPrintIsPending(false),
     536             :     mPrintDocIsFullyLoaded(false),
     537             :     mOriginalPrintPreviewScale(0.0),
     538             :     mPrintPreviewZoom(1.0),
     539             : #endif // NS_PRINT_PREVIEW
     540             : #ifdef DEBUG
     541             :     mDebugFile(nullptr),
     542             : #endif // DEBUG
     543             : #endif // NS_PRINTING
     544             :     mHintCharsetSource(kCharsetUninitialized),
     545             :     mHintCharset(nullptr),
     546             :     mForceCharacterSet(nullptr),
     547             :     mIsPageMode(false),
     548             :     mInitializedForPrintPreview(false),
     549             :     mHidden(false),
     550             :     mPrintRelated(false),
     551             :     mPresShellDestroyed(true),
     552          29 :     mDestroyWasFull(false)
     553             : {
     554          29 :   PrepareToStartLoad();
     555          29 : }
     556             : 
     557             : void
     558           0 : nsDocumentViewer::SetPrintRelated()
     559             : {
     560           0 :   if (!mPrintRelated) {
     561           0 :     if (mViewManager) {
     562           0 :       mViewManager->SetPrintRelated();
     563             :     }
     564             :   }
     565           0 :   mPrintRelated = true;
     566           0 : }
     567             : 
     568         323 : NS_IMPL_ADDREF(nsDocumentViewer)
     569         292 : NS_IMPL_RELEASE(nsDocumentViewer)
     570             : 
     571         217 : NS_INTERFACE_MAP_BEGIN(nsDocumentViewer)
     572         217 :     NS_INTERFACE_MAP_ENTRY(nsIContentViewer)
     573          72 :     NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile)
     574          72 :     NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit)
     575          42 :     NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint)
     576          42 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentViewer)
     577             : #ifdef NS_PRINTING
     578          32 :     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint)
     579             : #endif
     580          32 : NS_INTERFACE_MAP_END
     581             : 
     582           9 : nsDocumentViewer::~nsDocumentViewer()
     583             : {
     584           3 :   if (mDocument) {
     585           0 :     Close(nullptr);
     586           0 :     mDocument->Destroy();
     587             :   }
     588             : 
     589             :   nsIFrame* vmRootFrame =
     590           3 :     mViewManager && mViewManager->GetRootView()
     591           3 :       ? mViewManager->GetRootView()->GetFrame()
     592           3 :       : nullptr;
     593           3 :   nsIFrame* psRootFrame = mPresShell ? mPresShell->GetRootFrame() : nullptr;
     594           3 :   MOZ_RELEASE_ASSERT(vmRootFrame == psRootFrame);
     595             : 
     596           3 :   NS_ASSERTION(!mPresShell && !mPresContext,
     597             :                "User did not call nsIContentViewer::Destroy");
     598           3 :   if (mPresShell || mPresContext) {
     599             :     // Make sure we don't hand out a reference to the content viewer to
     600             :     // the SHEntry!
     601           0 :     mSHEntry = nullptr;
     602           0 :     mDestroyWasFull = false;
     603           0 :     Destroy();
     604           0 :     MOZ_RELEASE_ASSERT(mDestroyWasFull);
     605             :   }
     606             : 
     607           3 :   MOZ_RELEASE_ASSERT(mPresShellDestroyed);
     608             : 
     609           3 :   MOZ_RELEASE_ASSERT(!mPresShell || !mPresShell->GetRootFrame());
     610           3 :   MOZ_RELEASE_ASSERT(!mViewManager || !mViewManager->GetRootView() ||
     611             :     (!mViewManager->GetRootView()->GetFrame() &&
     612             :      !mViewManager->GetRootView()->GetFirstChild()));
     613             : 
     614           3 :   if (mSelectionListener) {
     615           3 :     mSelectionListener->Disconnect();
     616             :   }
     617             : 
     618           3 :   if (mFocusListener) {
     619           3 :     mFocusListener->Disconnect();
     620             :   }
     621             : 
     622             :   // XXX(?) Revoke pending invalidate events
     623           9 : }
     624             : 
     625             : /*
     626             :  * This method is called by the Document Loader once a document has
     627             :  * been created for a particular data stream...  The content viewer
     628             :  * must cache this document for later use when Init(...) is called.
     629             :  *
     630             :  * This method is also called when an out of band document.write() happens.
     631             :  * In that case, the document passed in is the same as the previous document.
     632             :  */
     633             : /* virtual */ void
     634          29 : nsDocumentViewer::LoadStart(nsIDocument* aDocument)
     635             : {
     636          29 :   MOZ_ASSERT(aDocument);
     637             : 
     638          29 :   if (!mDocument) {
     639          29 :     mDocument = aDocument;
     640             :   }
     641          29 : }
     642             : 
     643             : nsresult
     644          29 : nsDocumentViewer::SyncParentSubDocMap()
     645             : {
     646          58 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
     647          29 :   if (!docShell) {
     648          21 :     return NS_OK;
     649             :   }
     650             : 
     651          16 :   nsCOMPtr<nsPIDOMWindowOuter> pwin(docShell->GetWindow());
     652           8 :   if (!mDocument || !pwin) {
     653           0 :     return NS_OK;
     654             :   }
     655             : 
     656          16 :   nsCOMPtr<Element> element = pwin->GetFrameElementInternal();
     657           8 :   if (!element) {
     658           6 :     return NS_OK;
     659             :   }
     660             : 
     661           4 :   nsCOMPtr<nsIDocShellTreeItem> parent;
     662           2 :   docShell->GetParent(getter_AddRefs(parent));
     663             : 
     664           4 :   nsCOMPtr<nsPIDOMWindowOuter> parent_win = parent ? parent->GetWindow() : nullptr;
     665           2 :   if (!parent_win) {
     666           0 :     return NS_OK;
     667             :   }
     668             : 
     669           4 :   nsCOMPtr<nsIDocument> parent_doc = parent_win->GetDoc();
     670           2 :   if (!parent_doc) {
     671           0 :     return NS_OK;
     672             :   }
     673             : 
     674           4 :   if (mDocument &&
     675           4 :       parent_doc->GetSubDocumentFor(element) != mDocument &&
     676           2 :       parent_doc->EventHandlingSuppressed()) {
     677           0 :     mDocument->SuppressEventHandling(parent_doc->EventHandlingSuppressed());
     678             :   }
     679           2 :   return parent_doc->SetSubDocumentFor(element, mDocument);
     680             : }
     681             : 
     682             : NS_IMETHODIMP
     683           8 : nsDocumentViewer::SetContainer(nsIDocShell* aContainer)
     684             : {
     685           8 :   mContainer = static_cast<nsDocShell*>(aContainer);
     686           8 :   if (mPresContext) {
     687           0 :     mPresContext->SetContainer(mContainer);
     688             :   }
     689             : 
     690             :   // We're loading a new document into the window where this document
     691             :   // viewer lives, sync the parent document's frame element -> sub
     692             :   // document map
     693             : 
     694           8 :   return SyncParentSubDocMap();
     695             : }
     696             : 
     697             : NS_IMETHODIMP
     698           0 : nsDocumentViewer::GetContainer(nsIDocShell** aResult)
     699             : {
     700           0 :    NS_ENSURE_ARG_POINTER(aResult);
     701             : 
     702           0 :    nsCOMPtr<nsIDocShell> container(mContainer);
     703           0 :    container.swap(*aResult);
     704           0 :    return NS_OK;
     705             : }
     706             : 
     707             : NS_IMETHODIMP
     708          29 : nsDocumentViewer::Init(nsIWidget* aParentWidget,
     709             :                          const nsIntRect& aBounds)
     710             : {
     711          29 :   return InitInternal(aParentWidget, nullptr, aBounds, true);
     712             : }
     713             : 
     714             : nsresult
     715          28 : nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow)
     716             : {
     717             :   // We assert this because initializing the pres shell could otherwise cause
     718             :   // re-entrancy into nsDocumentViewer methods, which might cause a different
     719             :   // pres shell to be created.  Callers of InitPresentationStuff should ensure
     720             :   // the call is appropriately bounded by an nsAutoScriptBlocker to decide
     721             :   // when it is safe for these re-entrant calls to be made.
     722          28 :   MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
     723             :              "InitPresentationStuff must only be called when scripts are "
     724             :              "blocked");
     725             : 
     726          28 :   if (GetIsPrintPreview())
     727           0 :     return NS_OK;
     728             : 
     729          28 :   NS_ASSERTION(!mPresShell,
     730             :                "Someone should have destroyed the presshell!");
     731             : 
     732             :   // Create the style set...
     733          28 :   StyleSetHandle styleSet = CreateStyleSet(mDocument);
     734             : 
     735             :   // Now make the shell for the document
     736          28 :   mPresShell = mDocument->CreateShell(mPresContext, mViewManager, styleSet);
     737          28 :   if (!mPresShell) {
     738           0 :     styleSet->Delete();
     739           0 :     return NS_ERROR_FAILURE;
     740             :   }
     741          28 :   mPresShellDestroyed = false;
     742             : 
     743             :   // We're done creating the style set
     744          28 :   styleSet->EndUpdate();
     745             : 
     746          28 :   if (aDoInitialReflow) {
     747             :     // Since Initialize() will create frames for *all* items
     748             :     // that are currently in the document tree, we need to flush
     749             :     // any pending notifications to prevent the content sink from
     750             :     // duplicating layout frames for content it has added to the tree
     751             :     // but hasn't notified the document about. (Bug 154018)
     752             :     //
     753             :     // Note that we are flushing before we add mPresShell as an observer
     754             :     // to avoid bogus notifications.
     755             : 
     756           0 :     mDocument->FlushPendingNotifications(FlushType::ContentAndNotify);
     757             :   }
     758             : 
     759          28 :   mPresShell->BeginObservingDocument();
     760             : 
     761             :   // Initialize our view manager
     762          28 :   int32_t p2a = mPresContext->AppUnitsPerDevPixel();
     763          28 :   MOZ_ASSERT(p2a ==
     764             :              mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
     765          28 :   nscoord width = p2a * mBounds.width;
     766          28 :   nscoord height = p2a * mBounds.height;
     767             : 
     768          28 :   mViewManager->SetWindowDimensions(width, height);
     769          28 :   mPresContext->SetTextZoom(mTextZoom);
     770          28 :   mPresContext->SetFullZoom(mPageZoom);
     771          28 :   mPresContext->SetOverrideDPPX(mOverrideDPPX);
     772          28 :   mPresContext->SetBaseMinFontSize(mMinFontSize);
     773             : 
     774          28 :   p2a = mPresContext->AppUnitsPerDevPixel();  // zoom may have changed it
     775          28 :   width = p2a * mBounds.width;
     776          28 :   height = p2a * mBounds.height;
     777          28 :   if (aDoInitialReflow) {
     778           0 :     nsCOMPtr<nsIPresShell> shell = mPresShell;
     779             :     // Initial reflow
     780           0 :     shell->Initialize(width, height);
     781             :   } else {
     782             :     // Store the visible area so it's available for other callers of
     783             :     // Initialize, like nsContentSink::StartLayout.
     784          28 :     mPresContext->SetVisibleArea(nsRect(0, 0, width, height));
     785             :   }
     786             : 
     787             :   // now register ourselves as a selection listener, so that we get
     788             :   // called when the selection changes in the window
     789          28 :   if (!mSelectionListener) {
     790             :     nsDocViewerSelectionListener *selectionListener =
     791          28 :       new nsDocViewerSelectionListener();
     792             : 
     793          28 :     selectionListener->Init(this);
     794             : 
     795             :     // mSelectionListener is a owning reference
     796          28 :     mSelectionListener = selectionListener;
     797             :   }
     798             : 
     799          56 :   RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
     800          28 :   if (!selection) {
     801           0 :     return NS_ERROR_FAILURE;
     802             :   }
     803             : 
     804          28 :   nsresult rv = selection->AddSelectionListener(mSelectionListener);
     805          28 :   if (NS_FAILED(rv))
     806           0 :     return rv;
     807             : 
     808             :   // Save old listener so we can unregister it
     809          56 :   RefPtr<nsDocViewerFocusListener> oldFocusListener = mFocusListener;
     810          28 :   if (oldFocusListener) {
     811           0 :     oldFocusListener->Disconnect();
     812             :   }
     813             : 
     814             :   // focus listener
     815             :   //
     816             :   // now register ourselves as a focus listener, so that we get called
     817             :   // when the focus changes in the window
     818          28 :   nsDocViewerFocusListener *focusListener = new nsDocViewerFocusListener();
     819             : 
     820          28 :   focusListener->Init(this);
     821             : 
     822             :   // mFocusListener is a strong reference
     823          28 :   mFocusListener = focusListener;
     824             : 
     825          28 :   if (mDocument) {
     826          84 :     mDocument->AddEventListener(NS_LITERAL_STRING("focus"),
     827             :                                 mFocusListener,
     828          84 :                                 false, false);
     829          84 :     mDocument->AddEventListener(NS_LITERAL_STRING("blur"),
     830             :                                 mFocusListener,
     831          84 :                                 false, false);
     832             : 
     833          28 :     if (oldFocusListener) {
     834           0 :       mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"),
     835           0 :                                      oldFocusListener, false);
     836           0 :       mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"),
     837           0 :                                      oldFocusListener, false);
     838             :     }
     839             :   }
     840             : 
     841          28 :   if (aDoInitialReflow && mDocument) {
     842           0 :     mDocument->ScrollToRef();
     843             :   }
     844             : 
     845          28 :   return NS_OK;
     846             : }
     847             : 
     848             : static nsPresContext*
     849          28 : CreatePresContext(nsIDocument* aDocument,
     850             :                   nsPresContext::nsPresContextType aType,
     851             :                   nsView* aContainerView)
     852             : {
     853          28 :   if (aContainerView)
     854           1 :     return new nsPresContext(aDocument, aType);
     855          27 :   return new nsRootPresContext(aDocument, aType);
     856             : }
     857             : 
     858             : //-----------------------------------------------
     859             : // This method can be used to initial the "presentation"
     860             : // The aDoCreation indicates whether it should create
     861             : // all the new objects or just initialize the existing ones
     862             : nsresult
     863          50 : nsDocumentViewer::InitInternal(nsIWidget* aParentWidget,
     864             :                                  nsISupports *aState,
     865             :                                  const nsIntRect& aBounds,
     866             :                                  bool aDoCreation,
     867             :                                  bool aNeedMakeCX /*= true*/,
     868             :                                  bool aForceSetNewDocument /* = true*/)
     869             : {
     870          50 :   if (mIsPageMode) {
     871             :     // XXXbz should the InitInternal in SetPageMode just pass false
     872             :     // here itself?
     873           0 :     aForceSetNewDocument = false;
     874             :   }
     875             : 
     876             :   // We don't want any scripts to run here. That can cause flushing,
     877             :   // which can cause reentry into initialization of this document viewer,
     878             :   // which would be disastrous.
     879         100 :   nsAutoScriptBlocker blockScripts;
     880             : 
     881          50 :   mParentWidget = aParentWidget; // not ref counted
     882          50 :   mBounds = aBounds;
     883             : 
     884          50 :   nsresult rv = NS_OK;
     885          50 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER);
     886             : 
     887          50 :   nsView* containerView = FindContainerView();
     888             : 
     889          50 :   bool makeCX = false;
     890          50 :   if (aDoCreation) {
     891          29 :     nsresult rv = CreateDeviceContext(containerView);
     892          29 :     NS_ENSURE_SUCCESS(rv, rv);
     893             : 
     894             :     // XXXbz this is a nasty hack to do with the fact that we create
     895             :     // presentations both in Init() and in Show()...  Ideally we would only do
     896             :     // it in one place (Show()) and require that callers call init(), open(),
     897             :     // show() in that order or something.
     898          57 :     if (!mPresContext &&
     899          24 :         (aParentWidget || containerView || mDocument->IsBeingUsedAsImage() ||
     900           1 :          (mDocument->GetDisplayDocument() &&
     901           0 :           mDocument->GetDisplayDocument()->GetShell()))) {
     902             :       // Create presentation context
     903          28 :       if (mIsPageMode) {
     904             :         //Presentation context already created in SetPageMode which is calling this method
     905             :       } else {
     906             :         mPresContext = CreatePresContext(mDocument,
     907          28 :             nsPresContext::eContext_Galley, containerView);
     908             :       }
     909          28 :       NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
     910             : 
     911          28 :       nsresult rv = mPresContext->Init(mDeviceContext);
     912          28 :       if (NS_FAILED(rv)) {
     913           0 :         mPresContext = nullptr;
     914           0 :         return rv;
     915             :       }
     916             : 
     917             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
     918          28 :       makeCX = !GetIsPrintPreview() && aNeedMakeCX; // needs to be true except when we are already in PP or we are enabling/disabling paginated mode.
     919             : #else
     920             :       makeCX = true;
     921             : #endif
     922             :     }
     923             : 
     924          29 :     if (mPresContext) {
     925             :       // Create the ViewManager and Root View...
     926             : 
     927             :       // We must do this before we tell the script global object about
     928             :       // this new document since doing that will cause us to re-enter
     929             :       // into nsSubDocumentFrame code through reflows caused by
     930             :       // FlushPendingNotifications() calls down the road...
     931             : 
     932          56 :       rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(aBounds.width),
     933          28 :                              mPresContext->DevPixelsToAppUnits(aBounds.height)),
     934          28 :                       containerView);
     935          28 :       NS_ENSURE_SUCCESS(rv, rv);
     936          28 :       Hide();
     937             : 
     938             : #ifdef NS_PRINT_PREVIEW
     939          28 :       if (mIsPageMode) {
     940             :         // I'm leaving this in a broken state for the moment; we should
     941             :         // be measuring/scaling with the print device context, not the
     942             :         // screen device context, but this is good enough to allow
     943             :         // printing reftests to work.
     944           0 :         double pageWidth = 0, pageHeight = 0;
     945           0 :         mPresContext->GetPrintSettings()->GetEffectivePageSize(&pageWidth,
     946           0 :                                                                &pageHeight);
     947           0 :         mPresContext->SetPageSize(
     948           0 :           nsSize(mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageWidth)),
     949           0 :                  mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageHeight))));
     950           0 :         mPresContext->SetIsRootPaginatedDocument(true);
     951           0 :         mPresContext->SetPageScale(1.0f);
     952             :       }
     953             : #endif
     954             :     } else {
     955             :       // Avoid leaking the old viewer.
     956           1 :       if (mPreviousViewer) {
     957           0 :         mPreviousViewer->Destroy();
     958           0 :         mPreviousViewer = nullptr;
     959             :       }
     960             :     }
     961             :   }
     962             : 
     963         100 :   nsCOMPtr<nsIInterfaceRequestor> requestor(mContainer);
     964          50 :   if (requestor) {
     965           8 :     if (mPresContext) {
     966          14 :       nsCOMPtr<nsILinkHandler> linkHandler;
     967          14 :       requestor->GetInterface(NS_GET_IID(nsILinkHandler),
     968          14 :                               getter_AddRefs(linkHandler));
     969             : 
     970           7 :       mPresContext->SetContainer(mContainer);
     971           7 :       mPresContext->SetLinkHandler(linkHandler);
     972             :     }
     973             : 
     974             :     // Set script-context-owner in the document
     975             : 
     976          16 :     nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(requestor);
     977             : 
     978           8 :     if (window) {
     979          16 :       nsCOMPtr<nsIDocument> curDoc = window->GetExtantDoc();
     980           8 :       if (aForceSetNewDocument || curDoc != mDocument) {
     981           8 :         rv = window->SetNewDocument(mDocument, aState, false);
     982           8 :         if (NS_FAILED(rv)) {
     983           0 :           Destroy();
     984           0 :           return rv;
     985             :         }
     986           8 :         nsJSContext::LoadStart();
     987             :       }
     988             :     }
     989             :   }
     990             : 
     991          50 :   if (aDoCreation && mPresContext) {
     992             :     // The ViewManager and Root View was created above (in
     993             :     // MakeWindow())...
     994             : 
     995          28 :     rv = InitPresentationStuff(!makeCX);
     996             :   }
     997             : 
     998          50 :   return rv;
     999             : }
    1000             : 
    1001          29 : void nsDocumentViewer::SetNavigationTiming(nsDOMNavigationTiming* timing)
    1002             : {
    1003          29 :   NS_ASSERTION(mDocument, "Must have a document to set navigation timing.");
    1004          29 :   if (mDocument) {
    1005          29 :     mDocument->SetNavigationTiming(timing);
    1006             :   }
    1007          29 : }
    1008             : 
    1009             : //
    1010             : // LoadComplete(aStatus)
    1011             : //
    1012             : //   aStatus - The status returned from loading the document.
    1013             : //
    1014             : // This method is called by the container when the document has been
    1015             : // completely loaded.
    1016             : //
    1017             : NS_IMETHODIMP
    1018           6 : nsDocumentViewer::LoadComplete(nsresult aStatus)
    1019             : {
    1020             :   /* We need to protect ourself against auto-destruction in case the
    1021             :      window is closed while processing the OnLoad event.  See bug
    1022             :      http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
    1023             :      explanation.
    1024             :   */
    1025          12 :   RefPtr<nsDocumentViewer> kungFuDeathGrip(this);
    1026             : 
    1027             :   // Flush out layout so it's up-to-date by the time onload is called.
    1028             :   // Note that this could destroy the window, so do this before
    1029             :   // checking for our mDocument and its window.
    1030           6 :   if (mPresShell && !mStopped) {
    1031             :     // Hold strong ref because this could conceivably run script
    1032           8 :     nsCOMPtr<nsIPresShell> shell = mPresShell;
    1033           4 :     shell->FlushPendingNotifications(FlushType::Layout);
    1034             :   }
    1035             : 
    1036           6 :   nsresult rv = NS_OK;
    1037           6 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    1038             : 
    1039             :   // First, get the window from the document...
    1040          12 :   nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
    1041             : 
    1042           6 :   mLoaded = true;
    1043             : 
    1044             :   // Now, fire either an OnLoad or OnError event to the document...
    1045           6 :   bool restoring = false;
    1046             :   // XXXbz imagelib kills off the document load for a full-page image with
    1047             :   // NS_ERROR_PARSED_DATA_CACHED if it's in the cache.  So we want to treat
    1048             :   // that one as a success code; otherwise whether we fire onload for the image
    1049             :   // will depend on whether it's cached!
    1050          16 :   if(window &&
    1051          15 :      (NS_SUCCEEDED(aStatus) || aStatus == NS_ERROR_PARSED_DATA_CACHED)) {
    1052           4 :     nsEventStatus status = nsEventStatus_eIgnore;
    1053           8 :     WidgetEvent event(true, eLoad);
    1054           4 :     event.mFlags.mBubbles = false;
    1055           4 :     event.mFlags.mCancelable = false;
    1056             :      // XXX Dispatching to |window|, but using |document| as the target.
    1057           4 :     event.mTarget = mDocument;
    1058             : 
    1059             :     // If the document presentation is being restored, we don't want to fire
    1060             :     // onload to the document content since that would likely confuse scripts
    1061             :     // on the page.
    1062             : 
    1063           4 :     nsIDocShell *docShell = window->GetDocShell();
    1064           4 :     NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
    1065             : 
    1066           4 :     docShell->GetRestoringDocument(&restoring);
    1067           4 :     if (!restoring) {
    1068           4 :       NS_ASSERTION(mDocument->IsXULDocument() || // readyState for XUL is bogus
    1069             :                    mDocument->GetReadyStateEnum() ==
    1070             :                      nsIDocument::READYSTATE_INTERACTIVE ||
    1071             :                    // test_stricttransportsecurity.html has old-style
    1072             :                    // docshell-generated about:blank docs reach this code!
    1073             :                    (mDocument->GetReadyStateEnum() ==
    1074             :                       nsIDocument::READYSTATE_UNINITIALIZED &&
    1075             :                     NS_IsAboutBlank(mDocument->GetDocumentURI())),
    1076             :                    "Bad readystate");
    1077           8 :       nsCOMPtr<nsIDocument> d = mDocument;
    1078           4 :       mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
    1079             : 
    1080           8 :       RefPtr<nsDOMNavigationTiming> timing(d->GetNavigationTiming());
    1081           4 :       if (timing) {
    1082           4 :         timing->NotifyLoadEventStart();
    1083             :       }
    1084             : 
    1085             :       // Dispatch observer notification to notify observers document load is complete.
    1086           8 :       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1087           4 :       if (os) {
    1088           4 :         nsIPrincipal *principal = d->NodePrincipal();
    1089           8 :         os->NotifyObservers(d,
    1090           4 :                             nsContentUtils::IsSystemPrincipal(principal) ?
    1091             :                             "chrome-document-loaded" :
    1092             :                             "content-document-loaded",
    1093           8 :                             nullptr);
    1094             :       }
    1095             : 
    1096             :       // Notify any devtools about the load.
    1097           8 :       RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
    1098             : 
    1099           4 :       if (timelines && timelines->HasConsumer(docShell)) {
    1100           0 :         timelines->AddMarkerForDocShell(docShell,
    1101           0 :           MakeUnique<DocLoadingTimelineMarker>("document::Load"));
    1102             :       }
    1103             : 
    1104           4 :       EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status);
    1105           4 :       if (timing) {
    1106           4 :         timing->NotifyLoadEventEnd();
    1107             :       }
    1108             :     }
    1109             :   } else {
    1110             :     // XXX: Should fire error event to the document...
    1111             :   }
    1112             : 
    1113             :   // Notify the document that it has been shown (regardless of whether
    1114             :   // it was just loaded). Note: mDocument may be null now if the above
    1115             :   // firing of onload caused the document to unload.
    1116           6 :   if (mDocument) {
    1117             :     // Re-get window, since it might have changed during above firing of onload
    1118           6 :     window = mDocument->GetWindow();
    1119           6 :     if (window) {
    1120           6 :       nsIDocShell *docShell = window->GetDocShell();
    1121             :       bool isInUnload;
    1122          12 :       if (docShell && NS_SUCCEEDED(docShell->GetIsInUnload(&isInUnload)) &&
    1123           6 :           !isInUnload) {
    1124           5 :         mDocument->OnPageShow(restoring, nullptr);
    1125             :       }
    1126             :     }
    1127             :   }
    1128             : 
    1129           6 :   if (!mStopped) {
    1130           5 :     if (mDocument) {
    1131           5 :       mDocument->ScrollToRef();
    1132             :     }
    1133             : 
    1134             :     // Now that the document has loaded, we can tell the presshell
    1135             :     // to unsuppress painting.
    1136           5 :     if (mPresShell) {
    1137           8 :       nsCOMPtr<nsIPresShell> shell(mPresShell);
    1138           4 :       shell->UnsuppressPainting();
    1139             :       // mPresShell could have been removed now, see bug 378682/421432
    1140           4 :       if (mPresShell) {
    1141           4 :         mPresShell->LoadComplete();
    1142             :       }
    1143             :     }
    1144             :   }
    1145             : 
    1146             :   // Release the JS bytecode cache from its wait on the load event, and
    1147             :   // potentially dispatch the encoding of the bytecode.
    1148           6 :   if (mDocument && mDocument->ScriptLoader()) {
    1149           6 :     mDocument->ScriptLoader()->LoadEventFired();
    1150             :   }
    1151             : 
    1152           6 :   nsJSContext::LoadEnd();
    1153             : 
    1154             :   // It's probably a good idea to GC soon since we have finished loading.
    1155          12 :   nsJSContext::PokeGC(JS::gcreason::LOAD_END,
    1156          18 :                       mDocument ? mDocument->GetWrapperPreserveColor() : nullptr);
    1157             : 
    1158             : #ifdef NS_PRINTING
    1159             :   // Check to see if someone tried to print during the load
    1160           6 :   if (mPrintIsPending) {
    1161           0 :     mPrintIsPending        = false;
    1162           0 :     mPrintDocIsFullyLoaded = true;
    1163           0 :     Print(mCachedPrintSettings, mCachedPrintWebProgressListner);
    1164           0 :     mCachedPrintSettings           = nullptr;
    1165           0 :     mCachedPrintWebProgressListner = nullptr;
    1166             :   }
    1167             : #endif
    1168             : 
    1169           6 :   return rv;
    1170             : }
    1171             : 
    1172             : NS_IMETHODIMP
    1173           0 : nsDocumentViewer::GetLoadCompleted(bool *aOutLoadCompleted)
    1174             : {
    1175           0 :   *aOutLoadCompleted = mLoaded;
    1176           0 :   return NS_OK;
    1177             : }
    1178             : 
    1179             : NS_IMETHODIMP
    1180           0 : nsDocumentViewer::GetIsStopped(bool* aOutIsStopped)
    1181             : {
    1182           0 :   *aOutIsStopped = mStopped;
    1183           0 :   return NS_OK;
    1184             : }
    1185             : 
    1186             : NS_IMETHODIMP
    1187           5 : nsDocumentViewer::PermitUnload(bool *aPermitUnload)
    1188             : {
    1189           5 :   bool shouldPrompt = true;
    1190           5 :   return PermitUnloadInternal(&shouldPrompt, aPermitUnload);
    1191             : }
    1192             : 
    1193             : 
    1194             : nsresult
    1195           5 : nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
    1196             :                                        bool *aPermitUnload)
    1197             : {
    1198          10 :   AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
    1199             : 
    1200           5 :   nsresult rv = NS_OK;
    1201           5 :   *aPermitUnload = true;
    1202             : 
    1203          10 :   if (!mDocument
    1204           5 :    || mInPermitUnload
    1205          10 :    || mInPermitUnloadPrompt) {
    1206           0 :     return NS_OK;
    1207             :   }
    1208             : 
    1209             :   static bool sIsBeforeUnloadDisabled;
    1210             :   static bool sBeforeUnloadRequiresInteraction;
    1211             :   static bool sBeforeUnloadPrefsCached = false;
    1212             : 
    1213           5 :   if (!sBeforeUnloadPrefsCached) {
    1214           2 :     sBeforeUnloadPrefsCached = true;
    1215             :     Preferences::AddBoolVarCache(&sIsBeforeUnloadDisabled,
    1216           2 :                                  BEFOREUNLOAD_DISABLED_PREFNAME);
    1217             :     Preferences::AddBoolVarCache(&sBeforeUnloadRequiresInteraction,
    1218           2 :                                  BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME);
    1219             :   }
    1220             : 
    1221             :   // First, get the script global object from the document...
    1222           5 :   nsPIDOMWindowOuter* window = mDocument->GetWindow();
    1223             : 
    1224           5 :   if (!window) {
    1225             :     // This is odd, but not fatal
    1226           0 :     NS_WARNING("window not set for document!");
    1227           0 :     return NS_OK;
    1228             :   }
    1229             : 
    1230           5 :   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "This is unsafe");
    1231             : 
    1232             :   // Now, fire an BeforeUnload event to the document and see if it's ok
    1233             :   // to unload...
    1234           5 :   nsIPresShell* shell = mDocument->GetShell();
    1235           5 :   nsPresContext* presContext = nullptr;
    1236           5 :   if (shell) {
    1237           5 :     presContext = shell->GetPresContext();
    1238             :   }
    1239             :   RefPtr<BeforeUnloadEvent> event =
    1240          15 :     new BeforeUnloadEvent(mDocument, presContext, nullptr);
    1241           5 :   event->InitEvent(NS_LITERAL_STRING("beforeunload"), false, true);
    1242             : 
    1243             :   // Dispatching to |window|, but using |document| as the target.
    1244           5 :   event->SetTarget(mDocument);
    1245           5 :   event->SetTrusted(true);
    1246             : 
    1247             :   // In evil cases we might be destroyed while handling the
    1248             :   // onbeforeunload event, don't let that happen. (see also bug#331040)
    1249          10 :   RefPtr<nsDocumentViewer> kungFuDeathGrip(this);
    1250             : 
    1251           5 :   bool dialogsAreEnabled = false;
    1252             :   {
    1253             :     // Never permit popups from the beforeunload handler, no matter
    1254             :     // how we get here.
    1255          10 :     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    1256             : 
    1257             :     // Never permit dialogs from the beforeunload handler
    1258           5 :     nsGlobalWindow* globalWindow = nsGlobalWindow::Cast(window);
    1259           5 :     dialogsAreEnabled = globalWindow->AreDialogsEnabled();
    1260          10 :     nsGlobalWindow::TemporarilyDisableDialogs disableDialogs(globalWindow);
    1261             : 
    1262          10 :     nsIDocument::PageUnloadingEventTimeStamp timestamp(mDocument);
    1263             : 
    1264           5 :     mInPermitUnload = true;
    1265           5 :     EventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext,
    1266           5 :                                       nullptr);
    1267           5 :     mInPermitUnload = false;
    1268             :   }
    1269             : 
    1270          10 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    1271          10 :   nsAutoString text;
    1272           5 :   event->GetReturnValue(text);
    1273             : 
    1274             :   // NB: we nullcheck mDocument because it might now be dead as a result of
    1275             :   // the event being dispatched.
    1276          20 :   if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled &&
    1277          15 :       mDocument && !(mDocument->GetSandboxFlags() & SANDBOXED_MODALS) &&
    1278          15 :       (!sBeforeUnloadRequiresInteraction || mDocument->UserHasInteracted()) &&
    1279           0 :       (event->WidgetEventPtr()->DefaultPrevented() || !text.IsEmpty())) {
    1280             :     // Ask the user if it's ok to unload the current page
    1281             : 
    1282           0 :     nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell);
    1283             : 
    1284           0 :     if (prompt) {
    1285           0 :       nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
    1286           0 :       if (promptBag) {
    1287             :         bool isTabModalPromptAllowed;
    1288           0 :         GetIsTabModalPromptAllowed(&isTabModalPromptAllowed);
    1289           0 :         promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"),
    1290           0 :                                      isTabModalPromptAllowed);
    1291             :       }
    1292             : 
    1293           0 :       nsXPIDLString title, message, stayLabel, leaveLabel;
    1294             :       rv  = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1295             :                                                "OnBeforeUnloadTitle",
    1296           0 :                                                title);
    1297             :       nsresult tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1298             :                                                "OnBeforeUnloadMessage",
    1299           0 :                                                message);
    1300           0 :       if (NS_FAILED(tmp)) {
    1301           0 :         rv = tmp;
    1302             :       }
    1303             :       tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1304             :                                                "OnBeforeUnloadLeaveButton",
    1305           0 :                                                leaveLabel);
    1306           0 :       if (NS_FAILED(tmp)) {
    1307           0 :         rv = tmp;
    1308             :       }
    1309             :       tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1310             :                                                "OnBeforeUnloadStayButton",
    1311           0 :                                                stayLabel);
    1312           0 :       if (NS_FAILED(tmp)) {
    1313           0 :         rv = tmp;
    1314             :       }
    1315             : 
    1316           0 :       if (NS_FAILED(rv) || !title || !message || !stayLabel || !leaveLabel) {
    1317           0 :         NS_ERROR("Failed to get strings from dom.properties!");
    1318           0 :         return NS_OK;
    1319             :       }
    1320             : 
    1321             :       // Although the exact value is ignored, we must not pass invalid
    1322             :       // bool values through XPConnect.
    1323           0 :       bool dummy = false;
    1324           0 :       int32_t buttonPressed = 0;
    1325             :       uint32_t buttonFlags = (nsIPrompt::BUTTON_POS_0_DEFAULT |
    1326             :                              (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) |
    1327           0 :                              (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_1));
    1328             : 
    1329           0 :       nsAutoSyncOperation sync(mDocument);
    1330           0 :       mInPermitUnloadPrompt = true;
    1331           0 :       mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_COUNT, 1);
    1332           0 :       rv = prompt->ConfirmEx(title, message, buttonFlags,
    1333             :                              leaveLabel, stayLabel, nullptr, nullptr,
    1334           0 :                              &dummy, &buttonPressed);
    1335           0 :       mInPermitUnloadPrompt = false;
    1336             : 
    1337             :       // If the prompt aborted, we tell our consumer that it is not allowed
    1338             :       // to unload the page. One reason that prompts abort is that the user
    1339             :       // performed some action that caused the page to unload while our prompt
    1340             :       // was active. In those cases we don't want our consumer to also unload
    1341             :       // the page.
    1342             :       //
    1343             :       // XXX: Are there other cases where prompts can abort? Is it ok to
    1344             :       //      prevent unloading the page in those cases?
    1345           0 :       if (NS_FAILED(rv)) {
    1346           0 :         mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION, 2);
    1347           0 :         *aPermitUnload = false;
    1348           0 :         return NS_OK;
    1349             :       }
    1350             : 
    1351             :       // Button 0 == leave, button 1 == stay
    1352           0 :       *aPermitUnload = (buttonPressed == 0);
    1353           0 :       mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION,
    1354           0 :         (*aPermitUnload ? 1 : 0));
    1355             :       // If the user decided to go ahead, make sure not to prompt the user again
    1356             :       // by toggling the internal prompting bool to false:
    1357           0 :       if (*aPermitUnload) {
    1358           0 :         *aShouldPrompt = false;
    1359             :       }
    1360             :     }
    1361             :   }
    1362             : 
    1363           5 :   if (docShell) {
    1364             :     int32_t childCount;
    1365           5 :     docShell->GetChildCount(&childCount);
    1366             : 
    1367           5 :     for (int32_t i = 0; i < childCount && *aPermitUnload; ++i) {
    1368           0 :       nsCOMPtr<nsIDocShellTreeItem> item;
    1369           0 :       docShell->GetChildAt(i, getter_AddRefs(item));
    1370             : 
    1371           0 :       nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item));
    1372             : 
    1373           0 :       if (docShell) {
    1374           0 :         nsCOMPtr<nsIContentViewer> cv;
    1375           0 :         docShell->GetContentViewer(getter_AddRefs(cv));
    1376             : 
    1377           0 :         if (cv) {
    1378           0 :           cv->PermitUnloadInternal(aShouldPrompt, aPermitUnload);
    1379             :         }
    1380             :       }
    1381             :     }
    1382             :   }
    1383             : 
    1384           5 :   return NS_OK;
    1385             : }
    1386             : 
    1387             : NS_IMETHODIMP
    1388          10 : nsDocumentViewer::GetBeforeUnloadFiring(bool* aInEvent)
    1389             : {
    1390          10 :   *aInEvent = mInPermitUnload;
    1391          10 :   return NS_OK;
    1392             : }
    1393             : 
    1394             : NS_IMETHODIMP
    1395           0 : nsDocumentViewer::GetInPermitUnload(bool* aInEvent)
    1396             : {
    1397           0 :   *aInEvent = mInPermitUnloadPrompt;
    1398           0 :   return NS_OK;
    1399             : }
    1400             : 
    1401             : NS_IMETHODIMP
    1402           4 : nsDocumentViewer::PageHide(bool aIsUnload)
    1403             : {
    1404           8 :   AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
    1405             : 
    1406           4 :   mHidden = true;
    1407             : 
    1408           4 :   if (!mDocument) {
    1409           0 :     return NS_ERROR_NULL_POINTER;
    1410             :   }
    1411             : 
    1412           4 :   if (aIsUnload) {
    1413             :     // Poke the GC. The window might be collectable garbage now.
    1414           4 :     nsJSContext::PokeGC(JS::gcreason::PAGE_HIDE,
    1415           4 :                         mDocument->GetWrapperPreserveColor(),
    1416           4 :                         NS_GC_DELAY * 2);
    1417             :   }
    1418             : 
    1419           4 :   mDocument->OnPageHide(!aIsUnload, nullptr);
    1420             : 
    1421             :   // inform the window so that the focus state is reset.
    1422           4 :   NS_ENSURE_STATE(mDocument);
    1423           4 :   nsPIDOMWindowOuter* window = mDocument->GetWindow();
    1424           4 :   if (window)
    1425           4 :     window->PageHidden();
    1426             : 
    1427           4 :   if (aIsUnload) {
    1428             :     // if Destroy() was called during OnPageHide(), mDocument is nullptr.
    1429           4 :     NS_ENSURE_STATE(mDocument);
    1430             : 
    1431             :     // First, get the window from the document...
    1432           4 :     nsPIDOMWindowOuter* window = mDocument->GetWindow();
    1433             : 
    1434           4 :     if (!window) {
    1435             :       // Fail if no window is available...
    1436           0 :       NS_WARNING("window not set for document!");
    1437           0 :       return NS_ERROR_NULL_POINTER;
    1438             :     }
    1439             : 
    1440             :     // Now, fire an Unload event to the document...
    1441           4 :     nsEventStatus status = nsEventStatus_eIgnore;
    1442           8 :     WidgetEvent event(true, eUnload);
    1443           4 :     event.mFlags.mBubbles = false;
    1444             :     // XXX Dispatching to |window|, but using |document| as the target.
    1445           4 :     event.mTarget = mDocument;
    1446             : 
    1447             :     // Never permit popups from the unload handler, no matter how we get
    1448             :     // here.
    1449           8 :     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    1450             : 
    1451           8 :     nsIDocument::PageUnloadingEventTimeStamp timestamp(mDocument);
    1452             : 
    1453           4 :     EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status);
    1454             :   }
    1455             : 
    1456             : #ifdef MOZ_XUL
    1457             :   // look for open menupopups and close them after the unload event, in case
    1458             :   // the unload event listeners open any new popups
    1459           4 :   nsContentUtils::HidePopupsInDocument(mDocument);
    1460             : #endif
    1461             : 
    1462           4 :   return NS_OK;
    1463             : }
    1464             : 
    1465             : static void
    1466           0 : AttachContainerRecurse(nsIDocShell* aShell)
    1467             : {
    1468           0 :   nsCOMPtr<nsIContentViewer> viewer;
    1469           0 :   aShell->GetContentViewer(getter_AddRefs(viewer));
    1470           0 :   if (viewer) {
    1471           0 :     viewer->SetIsHidden(false);
    1472           0 :     nsIDocument* doc = viewer->GetDocument();
    1473           0 :     if (doc) {
    1474           0 :       doc->SetContainer(static_cast<nsDocShell*>(aShell));
    1475             :     }
    1476           0 :     RefPtr<nsPresContext> pc;
    1477           0 :     viewer->GetPresContext(getter_AddRefs(pc));
    1478           0 :     if (pc) {
    1479           0 :       pc->SetContainer(static_cast<nsDocShell*>(aShell));
    1480           0 :       nsCOMPtr<nsILinkHandler> handler = do_QueryInterface(aShell);
    1481           0 :       pc->SetLinkHandler(handler);
    1482             :     }
    1483           0 :     nsCOMPtr<nsIPresShell> presShell;
    1484           0 :     viewer->GetPresShell(getter_AddRefs(presShell));
    1485           0 :     if (presShell) {
    1486           0 :       presShell->SetForwardingContainer(WeakPtr<nsDocShell>());
    1487             :     }
    1488             :   }
    1489             : 
    1490             :   // Now recurse through the children
    1491             :   int32_t childCount;
    1492           0 :   aShell->GetChildCount(&childCount);
    1493           0 :   for (int32_t i = 0; i < childCount; ++i) {
    1494           0 :     nsCOMPtr<nsIDocShellTreeItem> childItem;
    1495           0 :     aShell->GetChildAt(i, getter_AddRefs(childItem));
    1496           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryInterface(childItem);
    1497           0 :     AttachContainerRecurse(shell);
    1498             :   }
    1499           0 : }
    1500             : 
    1501             : NS_IMETHODIMP
    1502          21 : nsDocumentViewer::Open(nsISupports *aState, nsISHEntry *aSHEntry)
    1503             : {
    1504          21 :   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
    1505             : 
    1506          21 :   if (mDocument)
    1507          21 :     mDocument->SetContainer(mContainer);
    1508             : 
    1509          21 :   nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
    1510          21 :   NS_ENSURE_SUCCESS(rv, rv);
    1511             : 
    1512          21 :   mHidden = false;
    1513             : 
    1514          21 :   if (mPresShell)
    1515          21 :     mPresShell->SetForwardingContainer(WeakPtr<nsDocShell>());
    1516             : 
    1517             :   // Rehook the child presentations.  The child shells are still in
    1518             :   // session history, so get them from there.
    1519             : 
    1520          21 :   if (aSHEntry) {
    1521           0 :     nsCOMPtr<nsIDocShellTreeItem> item;
    1522           0 :     int32_t itemIndex = 0;
    1523           0 :     while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++,
    1524           0 :                                                getter_AddRefs(item))) && item) {
    1525           0 :       nsCOMPtr<nsIDocShell> shell = do_QueryInterface(item);
    1526           0 :       AttachContainerRecurse(shell);
    1527             :     }
    1528             :   }
    1529             : 
    1530          21 :   SyncParentSubDocMap();
    1531             : 
    1532          21 :   if (mFocusListener && mDocument) {
    1533          63 :     mDocument->AddEventListener(NS_LITERAL_STRING("focus"), mFocusListener,
    1534          63 :                                 false, false);
    1535          63 :     mDocument->AddEventListener(NS_LITERAL_STRING("blur"), mFocusListener,
    1536          63 :                                 false, false);
    1537             :   }
    1538             : 
    1539             :   // XXX re-enable image animations once that works correctly
    1540             : 
    1541          21 :   PrepareToStartLoad();
    1542             : 
    1543             :   // When loading a page from the bfcache with puppet widgets, we do the
    1544             :   // widget attachment here (it is otherwise done in MakeWindow, which is
    1545             :   // called for non-bfcache pages in the history, but not bfcache pages).
    1546             :   // Attachment is necessary, since we get detached when another page
    1547             :   // is browsed to. That is, if we are one page A, then when we go to
    1548             :   // page B, we detach. So page A's view has no widget. If we then go
    1549             :   // back to it, and it is in the bfcache, we will use that view, which
    1550             :   // doesn't have a widget. The attach call here will properly attach us.
    1551          21 :   if (nsIWidget::UsePuppetWidgets() && mPresContext &&
    1552           0 :       ShouldAttachToTopLevel()) {
    1553             :     // If the old view is already attached to our parent, detach
    1554           0 :     DetachFromTopLevelWidget();
    1555             : 
    1556           0 :     nsViewManager *vm = GetViewManager();
    1557           0 :     MOZ_ASSERT(vm, "no view manager");
    1558           0 :     nsView* v = vm->GetRootView();
    1559           0 :     MOZ_ASSERT(v, "no root view");
    1560           0 :     MOZ_ASSERT(mParentWidget, "no mParentWidget to set");
    1561           0 :     v->AttachToTopLevelWidget(mParentWidget);
    1562             : 
    1563           0 :     mAttachedToParent = true;
    1564             :   }
    1565             : 
    1566          21 :   return NS_OK;
    1567             : }
    1568             : 
    1569             : NS_IMETHODIMP
    1570           4 : nsDocumentViewer::Close(nsISHEntry *aSHEntry)
    1571             : {
    1572             :   // All callers are supposed to call close to break circular
    1573             :   // references.  If we do this stuff in the destructor, the
    1574             :   // destructor might never be called (especially if we're being
    1575             :   // used from JS.
    1576             : 
    1577           4 :   mSHEntry = aSHEntry;
    1578             : 
    1579             :   // Close is also needed to disable scripts during paint suppression,
    1580             :   // since we transfer the existing global object to the new document
    1581             :   // that is loaded.  In the future, the global object may become a proxy
    1582             :   // for an object that can be switched in and out so that we don't need
    1583             :   // to disable scripts during paint suppression.
    1584             : 
    1585           4 :   if (!mDocument)
    1586           0 :     return NS_OK;
    1587             : 
    1588             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
    1589             :   // Turn scripting back on
    1590             :   // after PrintPreview had turned it off
    1591           4 :   if (GetIsPrintPreview() && mPrintEngine) {
    1592           0 :     mPrintEngine->TurnScriptingOn(true);
    1593             :   }
    1594             : #endif
    1595             : 
    1596             : #ifdef NS_PRINTING
    1597             :   // A Close was called while we were printing
    1598             :   // so don't clear the ScriptGlobalObject
    1599             :   // or clear the mDocument below
    1600           4 :   if (mPrintEngine && !mClosingWhilePrinting) {
    1601           0 :     mClosingWhilePrinting = true;
    1602             :   } else
    1603             : #endif
    1604             :     {
    1605             :       // out of band cleanup of docshell
    1606           4 :       mDocument->SetScriptGlobalObject(nullptr);
    1607             : 
    1608           4 :       if (!mSHEntry && mDocument)
    1609           4 :         mDocument->RemovedFromDocShell();
    1610             :     }
    1611             : 
    1612           4 :   if (mFocusListener) {
    1613           4 :     mFocusListener->Disconnect();
    1614           4 :     if (mDocument) {
    1615          16 :       mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), mFocusListener,
    1616          12 :                                      false);
    1617          16 :       mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), mFocusListener,
    1618          12 :                                      false);
    1619             :     }
    1620             :   }
    1621             : 
    1622           4 :   return NS_OK;
    1623             : }
    1624             : 
    1625             : static void
    1626           0 : DetachContainerRecurse(nsIDocShell *aShell)
    1627             : {
    1628             :   // Unhook this docshell's presentation
    1629           0 :   nsCOMPtr<nsIContentViewer> viewer;
    1630           0 :   aShell->GetContentViewer(getter_AddRefs(viewer));
    1631           0 :   if (viewer) {
    1632           0 :     nsIDocument* doc = viewer->GetDocument();
    1633           0 :     if (doc) {
    1634           0 :       doc->SetContainer(nullptr);
    1635             :     }
    1636           0 :     RefPtr<nsPresContext> pc;
    1637           0 :     viewer->GetPresContext(getter_AddRefs(pc));
    1638           0 :     if (pc) {
    1639           0 :       pc->Detach();
    1640             :     }
    1641           0 :     nsCOMPtr<nsIPresShell> presShell;
    1642           0 :     viewer->GetPresShell(getter_AddRefs(presShell));
    1643           0 :     if (presShell) {
    1644           0 :       auto weakShell = static_cast<nsDocShell*>(aShell);
    1645           0 :       presShell->SetForwardingContainer(weakShell);
    1646             :     }
    1647             :   }
    1648             : 
    1649             :   // Now recurse through the children
    1650             :   int32_t childCount;
    1651           0 :   aShell->GetChildCount(&childCount);
    1652           0 :   for (int32_t i = 0; i < childCount; ++i) {
    1653           0 :     nsCOMPtr<nsIDocShellTreeItem> childItem;
    1654           0 :     aShell->GetChildAt(i, getter_AddRefs(childItem));
    1655           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryInterface(childItem);
    1656           0 :     DetachContainerRecurse(shell);
    1657             :   }
    1658           0 : }
    1659             : 
    1660             : NS_IMETHODIMP
    1661           4 : nsDocumentViewer::Destroy()
    1662             : {
    1663           4 :   NS_ASSERTION(mDocument, "No document in Destroy()!");
    1664             : 
    1665             : #ifdef NS_PRINTING
    1666             :   // Here is where we check to see if the document was still being prepared
    1667             :   // for printing when it was asked to be destroy from someone externally
    1668             :   // This usually happens if the document is unloaded while the user is in the
    1669             :   // Print Dialog
    1670             :   //
    1671             :   // So we flip the bool to remember that the document is going away
    1672             :   // and we can clean up and abort later after returning from the Print Dialog
    1673           4 :   if (mPrintEngine) {
    1674           0 :     if (mPrintEngine->CheckBeforeDestroy()) {
    1675           0 :       return NS_OK;
    1676             :     }
    1677             :   }
    1678             :   // Dispatch the 'afterprint' event now, if pending:
    1679           4 :   mAutoBeforeAndAfterPrint = nullptr;
    1680             : #endif
    1681             : 
    1682             :   // Don't let the document get unloaded while we are printing.
    1683             :   // this could happen if we hit the back button during printing.
    1684             :   // We also keep the viewer from being cached in session history, since
    1685             :   // we require all documents there to be sanitized.
    1686           4 :   if (mDestroyRefCount != 0) {
    1687           0 :     --mDestroyRefCount;
    1688           0 :     return NS_OK;
    1689             :   }
    1690             : 
    1691             :   // If we were told to put ourselves into session history instead of destroy
    1692             :   // the presentation, do that now.
    1693           4 :   if (mSHEntry) {
    1694           0 :     if (mPresShell)
    1695           0 :       mPresShell->Freeze();
    1696             : 
    1697             :     // Make sure the presentation isn't torn down by Hide().
    1698           0 :     mSHEntry->SetSticky(mIsSticky);
    1699           0 :     mIsSticky = true;
    1700             : 
    1701           0 :     bool savePresentation = mDocument ? mDocument->IsBFCachingAllowed() : true;
    1702             : 
    1703             :     // Remove our root view from the view hierarchy.
    1704           0 :     if (mPresShell) {
    1705           0 :       nsViewManager *vm = mPresShell->GetViewManager();
    1706           0 :       if (vm) {
    1707           0 :         nsView *rootView = vm->GetRootView();
    1708             : 
    1709           0 :         if (rootView) {
    1710           0 :           nsView *rootViewParent = rootView->GetParent();
    1711           0 :           if (rootViewParent) {
    1712           0 :             nsViewManager *parentVM = rootViewParent->GetViewManager();
    1713           0 :             if (parentVM) {
    1714           0 :               parentVM->RemoveChild(rootView);
    1715             :             }
    1716             :           }
    1717             :         }
    1718             :       }
    1719             :     }
    1720             : 
    1721           0 :     Hide();
    1722             : 
    1723             :     // This is after Hide() so that the user doesn't see the inputs clear.
    1724           0 :     if (mDocument) {
    1725           0 :       mDocument->Sanitize();
    1726             :     }
    1727             : 
    1728             :     // Reverse ownership. Do this *after* calling sanitize so that sanitize
    1729             :     // doesn't cause mutations that make the SHEntry drop the presentation
    1730             : 
    1731             :     // Grab a reference to mSHEntry before calling into things like
    1732             :     // SyncPresentationState that might mess with our members.
    1733           0 :     nsCOMPtr<nsISHEntry> shEntry = mSHEntry; // we'll need this below
    1734           0 :     mSHEntry = nullptr;
    1735             : 
    1736           0 :     if (savePresentation) {
    1737           0 :       shEntry->SetContentViewer(this);
    1738             :     }
    1739             : 
    1740             :     // Always sync the presentation state.  That way even if someone screws up
    1741             :     // and shEntry has no window state at this point we'll be ok; we just won't
    1742             :     // cache ourselves.
    1743           0 :     shEntry->SyncPresentationState();
    1744             : 
    1745             :     // Shut down accessibility for the document before we start to tear it down.
    1746             : #ifdef ACCESSIBILITY
    1747           0 :     if (mPresShell) {
    1748           0 :       a11y::DocAccessible* docAcc = mPresShell->GetDocAccessible();
    1749           0 :       if (docAcc) {
    1750           0 :         docAcc->Shutdown();
    1751             :       }
    1752             :     }
    1753             : #endif
    1754             : 
    1755             :     // Break the link from the document/presentation to the docshell, so that
    1756             :     // link traversals cannot affect the currently-loaded document.
    1757             :     // When the presentation is restored, Open() and InitInternal() will reset
    1758             :     // these pointers to their original values.
    1759             : 
    1760           0 :     if (mDocument) {
    1761           0 :       mDocument->SetContainer(nullptr);
    1762             :     }
    1763           0 :     if (mPresContext) {
    1764           0 :       mPresContext->Detach();
    1765             :     }
    1766           0 :     if (mPresShell) {
    1767           0 :       mPresShell->SetForwardingContainer(mContainer);
    1768             :     }
    1769             : 
    1770             :     // Do the same for our children.  Note that we need to get the child
    1771             :     // docshells from the SHEntry now; the docshell will have cleared them.
    1772           0 :     nsCOMPtr<nsIDocShellTreeItem> item;
    1773           0 :     int32_t itemIndex = 0;
    1774           0 :     while (NS_SUCCEEDED(shEntry->ChildShellAt(itemIndex++,
    1775           0 :                                               getter_AddRefs(item))) && item) {
    1776           0 :       nsCOMPtr<nsIDocShell> shell = do_QueryInterface(item);
    1777           0 :       DetachContainerRecurse(shell);
    1778             :     }
    1779             : 
    1780           0 :     return NS_OK;
    1781             :   }
    1782             : 
    1783             :   // The document was not put in the bfcache
    1784             : 
    1785             :   // Protect against pres shell destruction running scripts and re-entrantly
    1786             :   // creating a new presentation.
    1787           8 :   nsAutoScriptBlocker scriptBlocker;
    1788             : 
    1789           4 :   if (mPresShell) {
    1790           3 :     DestroyPresShell();
    1791             :   }
    1792           4 :   if (mDocument) {
    1793           4 :     mDocument->Destroy();
    1794           4 :     mDocument = nullptr;
    1795             :   }
    1796             : 
    1797             :   // All callers are supposed to call destroy to break circular
    1798             :   // references.  If we do this stuff in the destructor, the
    1799             :   // destructor might never be called (especially if we're being
    1800             :   // used from JS.
    1801             : 
    1802             : #ifdef NS_PRINTING
    1803           4 :   if (mPrintEngine) {
    1804           0 :     RefPtr<nsPrintEngine> printEngine = mozilla::Move(mPrintEngine);
    1805             : #ifdef NS_PRINT_PREVIEW
    1806             :     bool doingPrintPreview;
    1807           0 :     printEngine->GetDoingPrintPreview(&doingPrintPreview);
    1808           0 :     if (doingPrintPreview) {
    1809           0 :       printEngine->FinishPrintPreview();
    1810             :     }
    1811             : #endif
    1812           0 :     printEngine->Destroy();
    1813           0 :     MOZ_ASSERT(!mPrintEngine,
    1814             :                "mPrintEngine shouldn't be recreated while destroying it");
    1815             :   }
    1816             : #endif
    1817             : 
    1818             :   // Avoid leaking the old viewer.
    1819           4 :   if (mPreviousViewer) {
    1820           0 :     mPreviousViewer->Destroy();
    1821           0 :     mPreviousViewer = nullptr;
    1822             :   }
    1823             : 
    1824           4 :   mDeviceContext = nullptr;
    1825             : 
    1826           4 :   if (mPresContext) {
    1827           3 :     DestroyPresContext();
    1828             :   }
    1829             : 
    1830           4 :   mWindow = nullptr;
    1831           4 :   mViewManager = nullptr;
    1832           4 :   mContainer = WeakPtr<nsDocShell>();
    1833             : 
    1834           4 :   mDestroyWasFull = true;
    1835             : 
    1836           4 :   return NS_OK;
    1837             : }
    1838             : 
    1839             : NS_IMETHODIMP
    1840           4 : nsDocumentViewer::Stop(void)
    1841             : {
    1842           4 :   NS_ASSERTION(mDocument, "Stop called too early or too late");
    1843           4 :   if (mDocument) {
    1844           4 :     mDocument->StopDocumentLoad();
    1845             :   }
    1846             : 
    1847           4 :   if (!mHidden && (mLoaded || mStopped) && mPresContext && !mSHEntry)
    1848           0 :     mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
    1849             : 
    1850           4 :   mStopped = true;
    1851             : 
    1852           4 :   if (!mLoaded && mPresShell) {
    1853             :     // Well, we might as well paint what we have so far.
    1854           4 :     nsCOMPtr<nsIPresShell> shell(mPresShell); // bug 378682
    1855           2 :     shell->UnsuppressPainting();
    1856             :   }
    1857             : 
    1858           4 :   return NS_OK;
    1859             : }
    1860             : 
    1861             : NS_IMETHODIMP
    1862         403 : nsDocumentViewer::GetDOMDocument(nsIDOMDocument **aResult)
    1863             : {
    1864         403 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    1865         403 :   return CallQueryInterface(mDocument, aResult);
    1866             : }
    1867             : 
    1868             : NS_IMETHODIMP_(nsIDocument *)
    1869        2573 : nsDocumentViewer::GetDocument()
    1870             : {
    1871        2573 :   return mDocument;
    1872             : }
    1873             : 
    1874             : NS_IMETHODIMP
    1875           0 : nsDocumentViewer::SetDOMDocument(nsIDOMDocument *aDocument)
    1876             : {
    1877             :   // Assumptions:
    1878             :   //
    1879             :   // 1) this document viewer has been initialized with a call to Init().
    1880             :   // 2) the stylesheets associated with the document have been added
    1881             :   // to the document.
    1882             : 
    1883             :   // XXX Right now, this method assumes that the layout of the current
    1884             :   // document hasn't started yet.  More cleanup will probably be
    1885             :   // necessary to make this method work for the case when layout *has*
    1886             :   // occurred for the current document.
    1887             :   // That work can happen when and if it is needed.
    1888             : 
    1889           0 :   if (!aDocument)
    1890           0 :     return NS_ERROR_NULL_POINTER;
    1891             : 
    1892           0 :   nsCOMPtr<nsIDocument> newDoc = do_QueryInterface(aDocument);
    1893           0 :   NS_ENSURE_TRUE(newDoc, NS_ERROR_UNEXPECTED);
    1894             : 
    1895           0 :   return SetDocumentInternal(newDoc, false);
    1896             : }
    1897             : 
    1898             : NS_IMETHODIMP
    1899           0 : nsDocumentViewer::SetDocumentInternal(nsIDocument* aDocument,
    1900             :                                         bool aForceReuseInnerWindow)
    1901             : {
    1902           0 :   MOZ_ASSERT(aDocument);
    1903             : 
    1904             :   // Set new container
    1905           0 :   aDocument->SetContainer(mContainer);
    1906             : 
    1907           0 :   if (mDocument != aDocument) {
    1908           0 :     if (aForceReuseInnerWindow) {
    1909             :       // Transfer the navigation timing information to the new document, since
    1910             :       // we're keeping the same inner and hence should really have the same
    1911             :       // timing information.
    1912           0 :       aDocument->SetNavigationTiming(mDocument->GetNavigationTiming());
    1913             :     }
    1914             : 
    1915           0 :     if (mDocument->IsStaticDocument()) {
    1916           0 :       mDocument->Destroy();
    1917             :     }
    1918             : 
    1919             :     // Clear the list of old child docshells. Child docshells for the new
    1920             :     // document will be constructed as frames are created.
    1921           0 :     if (!aDocument->IsStaticDocument()) {
    1922           0 :       nsCOMPtr<nsIDocShell> node(mContainer);
    1923           0 :       if (node) {
    1924             :         int32_t count;
    1925           0 :         node->GetChildCount(&count);
    1926           0 :         for (int32_t i = 0; i < count; ++i) {
    1927           0 :           nsCOMPtr<nsIDocShellTreeItem> child;
    1928           0 :           node->GetChildAt(0, getter_AddRefs(child));
    1929           0 :           node->RemoveChild(child);
    1930             :         }
    1931             :       }
    1932             :     }
    1933             : 
    1934             :     // Replace the old document with the new one. Do this only when
    1935             :     // the new document really is a new document.
    1936           0 :     mDocument = aDocument;
    1937             : 
    1938             :     // Set the script global object on the new document
    1939             :     nsCOMPtr<nsPIDOMWindowOuter> window =
    1940           0 :       mContainer ? mContainer->GetWindow() : nullptr;
    1941           0 :     if (window) {
    1942           0 :       nsresult rv = window->SetNewDocument(aDocument, nullptr,
    1943           0 :                                            aForceReuseInnerWindow);
    1944           0 :       if (NS_FAILED(rv)) {
    1945           0 :         Destroy();
    1946           0 :         return rv;
    1947             :       }
    1948             :     }
    1949             :   }
    1950             : 
    1951           0 :   nsresult rv = SyncParentSubDocMap();
    1952           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1953             : 
    1954             :   // Replace the current pres shell with a new shell for the new document
    1955             : 
    1956             :   // Protect against pres shell destruction running scripts and re-entrantly
    1957             :   // creating a new presentation.
    1958           0 :   nsAutoScriptBlocker scriptBlocker;
    1959             : 
    1960           0 :   if (mPresShell) {
    1961           0 :     DestroyPresShell();
    1962             :   }
    1963             : 
    1964           0 :   if (mPresContext) {
    1965           0 :     DestroyPresContext();
    1966             : 
    1967           0 :     mWindow = nullptr;
    1968           0 :     rv = InitInternal(mParentWidget, nullptr, mBounds, true, true, false);
    1969             :   }
    1970             : 
    1971           0 :   return rv;
    1972             : }
    1973             : 
    1974             : nsIPresShell*
    1975          89 : nsDocumentViewer::GetPresShell()
    1976             : {
    1977          89 :   return mPresShell;
    1978             : }
    1979             : 
    1980             : nsPresContext*
    1981          89 : nsDocumentViewer::GetPresContext()
    1982             : {
    1983          89 :   return mPresContext;
    1984             : }
    1985             : 
    1986             : nsViewManager*
    1987           0 : nsDocumentViewer::GetViewManager()
    1988             : {
    1989           0 :   return mViewManager;
    1990             : }
    1991             : 
    1992             : NS_IMETHODIMP
    1993          89 : nsDocumentViewer::GetPresShell(nsIPresShell** aResult)
    1994             : {
    1995          89 :   nsIPresShell* shell = GetPresShell();
    1996          89 :   NS_IF_ADDREF(*aResult = shell);
    1997          89 :   return NS_OK;
    1998             : }
    1999             : 
    2000             : NS_IMETHODIMP
    2001          50 : nsDocumentViewer::GetPresContext(nsPresContext** aResult)
    2002             : {
    2003          50 :   nsPresContext* pc = GetPresContext();
    2004          50 :   NS_IF_ADDREF(*aResult = pc);
    2005          50 :   return NS_OK;
    2006             : }
    2007             : 
    2008             : NS_IMETHODIMP
    2009          19 : nsDocumentViewer::GetBounds(nsIntRect& aResult)
    2010             : {
    2011          19 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    2012          19 :   aResult = mBounds;
    2013          19 :   return NS_OK;
    2014             : }
    2015             : 
    2016             : NS_IMETHODIMP
    2017           8 : nsDocumentViewer::GetPreviousViewer(nsIContentViewer** aViewer)
    2018             : {
    2019           8 :   *aViewer = mPreviousViewer;
    2020           8 :   NS_IF_ADDREF(*aViewer);
    2021           8 :   return NS_OK;
    2022             : }
    2023             : 
    2024             : NS_IMETHODIMP
    2025           3 : nsDocumentViewer::SetPreviousViewer(nsIContentViewer* aViewer)
    2026             : {
    2027             :   // NOTE:  |Show| sets |mPreviousViewer| to null without calling this
    2028             :   // function.
    2029             : 
    2030           3 :   if (aViewer) {
    2031           3 :     NS_ASSERTION(!mPreviousViewer,
    2032             :                  "can't set previous viewer when there already is one");
    2033             : 
    2034             :     // In a multiple chaining situation (which occurs when running a thrashing
    2035             :     // test like i-bench or jrgm's tests with no delay), we can build up a
    2036             :     // whole chain of viewers.  In order to avoid this, we always set our previous
    2037             :     // viewer to the MOST previous viewer in the chain, and then dump the intermediate
    2038             :     // link from the chain.  This ensures that at most only 2 documents are alive
    2039             :     // and undestroyed at any given time (the one that is showing and the one that
    2040             :     // is loading with painting suppressed).
    2041             :     // It's very important that if this ever gets changed the code
    2042             :     // before the RestorePresentation call in nsDocShell::InternalLoad
    2043             :     // be changed accordingly.
    2044           6 :     nsCOMPtr<nsIContentViewer> prevViewer;
    2045           3 :     aViewer->GetPreviousViewer(getter_AddRefs(prevViewer));
    2046           3 :     if (prevViewer) {
    2047           0 :       aViewer->SetPreviousViewer(nullptr);
    2048           0 :       aViewer->Destroy();
    2049           0 :       return SetPreviousViewer(prevViewer);
    2050             :     }
    2051             :   }
    2052             : 
    2053           3 :   mPreviousViewer = aViewer;
    2054           3 :   return NS_OK;
    2055             : }
    2056             : 
    2057             : NS_IMETHODIMP
    2058          24 : nsDocumentViewer::SetBoundsWithFlags(const nsIntRect& aBounds, uint32_t aFlags)
    2059             : {
    2060          24 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    2061             : 
    2062          24 :   mBounds = aBounds;
    2063             : 
    2064          24 :   if (mWindow && !mAttachedToParent) {
    2065             :     // Resize the widget, but don't trigger repaint. Layout will generate
    2066             :     // repaint requests during reflow.
    2067           0 :     mWindow->Resize(aBounds.x, aBounds.y,
    2068           0 :                     aBounds.width, aBounds.height,
    2069           0 :                     false);
    2070          24 :   } else if (mPresContext && mViewManager) {
    2071             :     // Ensure presContext's deviceContext is up to date, as we sometimes get
    2072             :     // here before a resolution-change notification has been fully handled
    2073             :     // during display configuration changes, especially when there are lots
    2074             :     // of windows/widgets competing to handle the notifications.
    2075             :     // (See bug 1154125.)
    2076          24 :     if (mPresContext->DeviceContext()->CheckDPIChange()) {
    2077           1 :       mPresContext->UIResolutionChanged();
    2078             :     }
    2079          24 :     int32_t p2a = mPresContext->AppUnitsPerDevPixel();
    2080          24 :     mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(mBounds.width, p2a),
    2081             :                                       NSIntPixelsToAppUnits(mBounds.height, p2a),
    2082          48 :                                       !!(aFlags & nsIContentViewer::eDelayResize));
    2083             :   }
    2084             : 
    2085             :   // If there's a previous viewer, it's the one that's actually showing,
    2086             :   // so be sure to resize it as well so it paints over the right area.
    2087             :   // This may slow down the performance of the new page load, but resize
    2088             :   // during load is also probably a relatively unusual condition
    2089             :   // relating to things being hidden while something is loaded.  It so
    2090             :   // happens that Firefox does this a good bit with its infobar, and it
    2091             :   // looks ugly if we don't do this.
    2092          24 :   if (mPreviousViewer) {
    2093           0 :     nsCOMPtr<nsIContentViewer> previousViewer = mPreviousViewer;
    2094           0 :     previousViewer->SetBounds(aBounds);
    2095             :   }
    2096             : 
    2097          24 :   return NS_OK;
    2098             : }
    2099             : 
    2100             : NS_IMETHODIMP
    2101          18 : nsDocumentViewer::SetBounds(const nsIntRect& aBounds)
    2102             : {
    2103          18 :   return SetBoundsWithFlags(aBounds, 0);
    2104             : }
    2105             : 
    2106             : NS_IMETHODIMP
    2107           0 : nsDocumentViewer::Move(int32_t aX, int32_t aY)
    2108             : {
    2109           0 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    2110           0 :   mBounds.MoveTo(aX, aY);
    2111           0 :   if (mWindow) {
    2112           0 :     mWindow->Move(aX, aY);
    2113             :   }
    2114           0 :   return NS_OK;
    2115             : }
    2116             : 
    2117             : NS_IMETHODIMP
    2118           5 : nsDocumentViewer::Show(void)
    2119             : {
    2120           5 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    2121             : 
    2122             :   // We don't need the previous viewer anymore since we're not
    2123             :   // displaying it.
    2124           5 :   if (mPreviousViewer) {
    2125             :     // This little dance *may* only be to keep
    2126             :     // PresShell::EndObservingDocument happy, but I'm not sure.
    2127           6 :     nsCOMPtr<nsIContentViewer> prevViewer(mPreviousViewer);
    2128           3 :     mPreviousViewer = nullptr;
    2129           3 :     prevViewer->Destroy();
    2130             : 
    2131             :     // Make sure we don't have too many cached ContentViewers
    2132           6 :     nsCOMPtr<nsIDocShellTreeItem> treeItem(mContainer);
    2133           3 :     if (treeItem) {
    2134             :       // We need to find the root DocShell since only that object has an
    2135             :       // SHistory and we need the SHistory to evict content viewers
    2136           6 :       nsCOMPtr<nsIDocShellTreeItem> root;
    2137           3 :       treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
    2138           6 :       nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
    2139           6 :       nsCOMPtr<nsISHistory> history;
    2140           3 :       webNav->GetSessionHistory(getter_AddRefs(history));
    2141           6 :       nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
    2142           3 :       if (historyInt) {
    2143             :         int32_t prevIndex,loadedIndex;
    2144           2 :         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
    2145           1 :         docShell->GetPreviousTransIndex(&prevIndex);
    2146           1 :         docShell->GetLoadedTransIndex(&loadedIndex);
    2147             : #ifdef DEBUG_PAGE_CACHE
    2148             :         printf("About to evict content viewers: prev=%d, loaded=%d\n",
    2149             :                prevIndex, loadedIndex);
    2150             : #endif
    2151           1 :         historyInt->EvictOutOfRangeContentViewers(loadedIndex);
    2152             :       }
    2153             :     }
    2154             :   }
    2155             : 
    2156           5 :   if (mWindow) {
    2157             :     // When attached to a top level xul window, we do not need to call
    2158             :     // Show on the widget. Underlying window management code handles
    2159             :     // this when the window is initialized.
    2160           5 :     if (!mAttachedToParent) {
    2161           0 :       mWindow->Show(true);
    2162             :     }
    2163             :   }
    2164             : 
    2165             :   // Hold on to the document so we can use it after the script blocker below
    2166             :   // has been released (which might re-entrantly call into other
    2167             :   // nsDocumentViewer methods).
    2168          10 :   nsCOMPtr<nsIDocument> document = mDocument;
    2169             : 
    2170           5 :   if (mDocument && !mPresShell) {
    2171             :     // The InitPresentationStuff call below requires a script blocker, because
    2172             :     // its PresShell::Initialize call can cause scripts to run and therefore
    2173             :     // re-entrant calls to nsDocumentViewer methods to be made.
    2174           0 :     nsAutoScriptBlocker scriptBlocker;
    2175             : 
    2176           0 :     NS_ASSERTION(!mWindow, "Window already created but no presshell?");
    2177             : 
    2178           0 :     nsCOMPtr<nsIBaseWindow> base_win(mContainer);
    2179           0 :     if (base_win) {
    2180           0 :       base_win->GetParentWidget(&mParentWidget);
    2181           0 :       if (mParentWidget) {
    2182           0 :         mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
    2183             :       }
    2184             :     }
    2185             : 
    2186           0 :     nsView* containerView = FindContainerView();
    2187             : 
    2188           0 :     nsresult rv = CreateDeviceContext(containerView);
    2189           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2190             : 
    2191             :     // Create presentation context
    2192           0 :     NS_ASSERTION(!mPresContext, "Shouldn't have a prescontext if we have no shell!");
    2193             :     mPresContext = CreatePresContext(mDocument,
    2194           0 :         nsPresContext::eContext_Galley, containerView);
    2195           0 :     NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
    2196             : 
    2197           0 :     rv = mPresContext->Init(mDeviceContext);
    2198           0 :     if (NS_FAILED(rv)) {
    2199           0 :       mPresContext = nullptr;
    2200           0 :       return rv;
    2201             :     }
    2202             : 
    2203           0 :     rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width),
    2204             :                            mPresContext->DevPixelsToAppUnits(mBounds.height)),
    2205           0 :                            containerView);
    2206           0 :     if (NS_FAILED(rv))
    2207           0 :       return rv;
    2208             : 
    2209           0 :     if (mPresContext && base_win) {
    2210           0 :       nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win));
    2211             : 
    2212           0 :       if (linkHandler) {
    2213           0 :         mPresContext->SetLinkHandler(linkHandler);
    2214             :       }
    2215             : 
    2216           0 :       mPresContext->SetContainer(mContainer);
    2217             :     }
    2218             : 
    2219           0 :     if (mPresContext) {
    2220           0 :       Hide();
    2221             : 
    2222           0 :       rv = InitPresentationStuff(mDocument->MayStartLayout());
    2223             :     }
    2224             : 
    2225             :     // If we get here the document load has already started and the
    2226             :     // window is shown because some JS on the page caused it to be
    2227             :     // shown...
    2228             : 
    2229           0 :     if (mPresShell) {
    2230           0 :       nsCOMPtr<nsIPresShell> shell(mPresShell); // bug 378682
    2231           0 :       shell->UnsuppressPainting();
    2232             :     }
    2233             :   }
    2234             : 
    2235             :   // Notify observers that a new page has been shown. This will get run
    2236             :   // from the event loop after we actually draw the page.
    2237             :   RefPtr<nsDocumentShownDispatcher> event =
    2238          15 :     new nsDocumentShownDispatcher(document);
    2239          15 :   document->Dispatch("nsDocumentShownDispatcher",
    2240             :                       TaskCategory::Other,
    2241          15 :                       event.forget());
    2242             : 
    2243           5 :   return NS_OK;
    2244             : }
    2245             : 
    2246             : NS_IMETHODIMP
    2247          29 : nsDocumentViewer::Hide(void)
    2248             : {
    2249          29 :   if (!mAttachedToParent && mWindow) {
    2250           0 :     mWindow->Show(false);
    2251             :   }
    2252             : 
    2253          29 :   if (!mPresShell)
    2254          28 :     return NS_OK;
    2255             : 
    2256           1 :   NS_ASSERTION(mPresContext, "Can't have a presshell and no prescontext!");
    2257             : 
    2258             :   // Avoid leaking the old viewer.
    2259           1 :   if (mPreviousViewer) {
    2260           0 :     mPreviousViewer->Destroy();
    2261           0 :     mPreviousViewer = nullptr;
    2262             :   }
    2263             : 
    2264           1 :   if (mIsSticky) {
    2265             :     // This window is sticky, that means that it might be shown again
    2266             :     // and we don't want the presshell n' all that to be thrown away
    2267             :     // just because the window is hidden.
    2268             : 
    2269           0 :     return NS_OK;
    2270             :   }
    2271             : 
    2272           2 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    2273           1 :   if (docShell) {
    2274             : #ifdef DEBUG
    2275           2 :     nsCOMPtr<nsIContentViewer> currentViewer;
    2276           1 :     docShell->GetContentViewer(getter_AddRefs(currentViewer));
    2277           1 :     MOZ_ASSERT(currentViewer == this);
    2278             : #endif
    2279           2 :     nsCOMPtr<nsILayoutHistoryState> layoutState;
    2280           1 :     mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
    2281             :   }
    2282             : 
    2283             :   // Do not run ScriptRunners queued by DestroyPresShell() in the intermediate
    2284             :   // state before we're done destroying PresShell, PresContext, ViewManager, etc.
    2285           2 :   nsAutoScriptBlocker scriptBlocker;
    2286             : 
    2287           1 :   DestroyPresShell();
    2288             : 
    2289           1 :   DestroyPresContext();
    2290             : 
    2291           1 :   mViewManager   = nullptr;
    2292           1 :   mWindow        = nullptr;
    2293           1 :   mDeviceContext = nullptr;
    2294           1 :   mParentWidget  = nullptr;
    2295             : 
    2296           2 :   nsCOMPtr<nsIBaseWindow> base_win(mContainer);
    2297             : 
    2298           1 :   if (base_win && !mAttachedToParent) {
    2299           1 :     base_win->SetParentWidget(nullptr);
    2300             :   }
    2301             : 
    2302           1 :   return NS_OK;
    2303             : }
    2304             : 
    2305             : NS_IMETHODIMP
    2306           0 : nsDocumentViewer::GetSticky(bool *aSticky)
    2307             : {
    2308           0 :   *aSticky = mIsSticky;
    2309             : 
    2310           0 :   return NS_OK;
    2311             : }
    2312             : 
    2313             : NS_IMETHODIMP
    2314           1 : nsDocumentViewer::SetSticky(bool aSticky)
    2315             : {
    2316           1 :   mIsSticky = aSticky;
    2317             : 
    2318           1 :   return NS_OK;
    2319             : }
    2320             : 
    2321             : NS_IMETHODIMP
    2322           0 : nsDocumentViewer::RequestWindowClose(bool* aCanClose)
    2323             : {
    2324             : #ifdef NS_PRINTING
    2325           0 :   if (mPrintIsPending || (mPrintEngine && mPrintEngine->GetIsPrinting())) {
    2326           0 :     *aCanClose = false;
    2327           0 :     mDeferredWindowClose = true;
    2328             :   } else
    2329             : #endif
    2330           0 :     *aCanClose = true;
    2331             : 
    2332           0 :   return NS_OK;
    2333             : }
    2334             : 
    2335             : StyleSetHandle
    2336          28 : nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument)
    2337             : {
    2338             :   // Make sure this does the same thing as PresShell::AddSheet wrt ordering.
    2339             : 
    2340             :   // this should eventually get expanded to allow for creating
    2341             :   // different sets for different media
    2342             : 
    2343          28 :   StyleBackendType backendType = aDocument->GetStyleBackendType();
    2344             : 
    2345          28 :   StyleSetHandle styleSet;
    2346          28 :   if (backendType == StyleBackendType::Gecko) {
    2347          28 :     styleSet = new nsStyleSet();
    2348             :   } else {
    2349           0 :     styleSet = new ServoStyleSet();
    2350             :   }
    2351             : 
    2352          28 :   styleSet->BeginUpdate();
    2353             : 
    2354             :   // The document will fill in the document sheets when we create the presshell
    2355             : 
    2356          28 :   if (aDocument->IsBeingUsedAsImage()) {
    2357          21 :     MOZ_ASSERT(aDocument->IsSVGDocument(),
    2358             :                "Do we want to skip most sheets for this new image type?");
    2359             : 
    2360             :     // SVG-as-an-image must be kept as light and small as possible. We
    2361             :     // deliberately skip loading everything and leave svg.css (and html.css and
    2362             :     // xul.css) to be loaded on-demand.
    2363             :     // XXXjwatt Nothing else is loaded on-demand, but I don't think that
    2364             :     // should matter for SVG-as-an-image. If it does, I want to know why!
    2365             : 
    2366             :     // Caller will handle calling EndUpdate, per contract.
    2367          21 :     return styleSet;
    2368             :   }
    2369             : 
    2370           7 :   auto cache = nsLayoutStylesheetCache::For(backendType);
    2371             : 
    2372             :   // Handle the user sheets.
    2373           7 :   StyleSheet* sheet = nullptr;
    2374           7 :   if (nsContentUtils::IsInChromeDocshell(aDocument)) {
    2375           4 :     sheet = cache->UserChromeSheet();
    2376             :   } else {
    2377           3 :     sheet = cache->UserContentSheet();
    2378             :   }
    2379             : 
    2380           7 :   if (sheet)
    2381           0 :     styleSet->AppendStyleSheet(SheetType::User, sheet);
    2382             : 
    2383             :   // Append chrome sheets (scrollbars + forms).
    2384           7 :   bool shouldOverride = false;
    2385             :   // We don't want a docshell here for external resource docs, so just
    2386             :   // look at mContainer.
    2387          14 :   nsCOMPtr<nsIDocShell> ds(mContainer);
    2388          14 :   nsCOMPtr<nsIDOMEventTarget> chromeHandler;
    2389          14 :   nsCOMPtr<nsIURI> uri;
    2390          14 :   RefPtr<StyleSheet> chromeSheet;
    2391             : 
    2392           7 :   if (ds) {
    2393           7 :     ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
    2394             :   }
    2395           7 :   if (chromeHandler) {
    2396           6 :     nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
    2397           6 :     nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
    2398           3 :     if (elt && content) {
    2399           2 :       nsCOMPtr<nsIURI> baseURI = content->GetBaseURI();
    2400             : 
    2401           2 :       nsAutoString sheets;
    2402           1 :       elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
    2403           1 :       if (!sheets.IsEmpty() && baseURI) {
    2404             :         RefPtr<css::Loader> cssLoader =
    2405           0 :           new css::Loader(backendType, aDocument->GetDocGroup());
    2406             : 
    2407           0 :         char *str = ToNewCString(sheets);
    2408           0 :         char *newStr = str;
    2409             :         char *token;
    2410           0 :         while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) {
    2411           0 :           NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nullptr,
    2412           0 :                     baseURI);
    2413           0 :           if (!uri) continue;
    2414             : 
    2415           0 :           cssLoader->LoadSheetSync(uri, &chromeSheet);
    2416           0 :           if (!chromeSheet) continue;
    2417             : 
    2418           0 :           styleSet->PrependStyleSheet(SheetType::Agent, chromeSheet);
    2419           0 :           shouldOverride = true;
    2420             :         }
    2421           0 :         free(str);
    2422             :       }
    2423             :     }
    2424             :   }
    2425             : 
    2426           7 :   if (!shouldOverride) {
    2427           7 :     sheet = cache->ScrollbarsSheet();
    2428           7 :     if (sheet) {
    2429           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2430             :     }
    2431             :   }
    2432             : 
    2433           7 :   if (!aDocument->IsSVGDocument()) {
    2434             :     // !!! IMPORTANT - KEEP THIS BLOCK IN SYNC WITH
    2435             :     // !!! SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded.
    2436             : 
    2437             :     // SVGForeignObjectElement::BindToTree calls SVGDocument::
    2438             :     // EnsureNonSVGUserAgentStyleSheetsLoaded to loads these UA sheet
    2439             :     // on-demand. (Excluding the quirks sheet, which should never be loaded for
    2440             :     // an SVG document, and excluding xul.css which will be loaded on demand by
    2441             :     // nsXULElement::BindToTree.)
    2442             : 
    2443           7 :     sheet = cache->NumberControlSheet();
    2444           7 :     if (sheet) {
    2445           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2446             :     }
    2447             : 
    2448           7 :     sheet = cache->FormsSheet();
    2449           7 :     if (sheet) {
    2450           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2451             :     }
    2452             : 
    2453           7 :     if (aDocument->LoadsFullXULStyleSheetUpFront()) {
    2454             :       // nsXULElement::BindToTree loads xul.css on-demand if we don't load it
    2455             :       // up-front here.
    2456           3 :       sheet = cache->XULSheet();
    2457           3 :       if (sheet) {
    2458           3 :         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2459             :       }
    2460             :     }
    2461             : 
    2462           7 :     sheet = cache->MinimalXULSheet();
    2463           7 :     if (sheet) {
    2464             :       // Load the minimal XUL rules for scrollbars and a few other XUL things
    2465             :       // that non-XUL (typically HTML) documents commonly use.
    2466           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2467             :     }
    2468             : 
    2469           7 :     sheet = cache->CounterStylesSheet();
    2470           7 :     if (sheet) {
    2471           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2472             :     }
    2473             : 
    2474           7 :     if (nsLayoutUtils::ShouldUseNoScriptSheet(aDocument)) {
    2475           7 :       sheet = cache->NoScriptSheet();
    2476           7 :       if (sheet) {
    2477           7 :         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2478             :       }
    2479             :     }
    2480             : 
    2481           7 :     if (nsLayoutUtils::ShouldUseNoFramesSheet(aDocument)) {
    2482           0 :       sheet = cache->NoFramesSheet();
    2483           0 :       if (sheet) {
    2484           0 :         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2485             :       }
    2486             :     }
    2487             : 
    2488             :     // We don't add quirk.css here; nsPresContext::CompatibilityModeChanged will
    2489             :     // append it if needed.
    2490             : 
    2491           7 :     sheet = cache->HTMLSheet();
    2492           7 :     if (sheet) {
    2493           7 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2494             :     }
    2495             : 
    2496           7 :     styleSet->PrependStyleSheet(SheetType::Agent,
    2497           7 :                                 cache->UASheet());
    2498             :   } else {
    2499             :     // SVG documents may have scrollbars and need the scrollbar styling.
    2500           0 :     sheet = cache->MinimalXULSheet();
    2501           0 :     if (sheet) {
    2502           0 :       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
    2503             :     }
    2504             :   }
    2505             : 
    2506           7 :   nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
    2507           7 :   if (sheetService) {
    2508          14 :     for (StyleSheet* sheet : *sheetService->AgentStyleSheets(backendType)) {
    2509           7 :       styleSet->AppendStyleSheet(SheetType::Agent, sheet);
    2510             :     }
    2511           7 :     for (StyleSheet* sheet :
    2512           7 :            Reversed(*sheetService->UserStyleSheets(backendType))) {
    2513           0 :       styleSet->PrependStyleSheet(SheetType::User, sheet);
    2514             :     }
    2515             :   }
    2516             : 
    2517             :   // Caller will handle calling EndUpdate, per contract.
    2518           7 :   return styleSet;
    2519             : }
    2520             : 
    2521             : NS_IMETHODIMP
    2522           0 : nsDocumentViewer::ClearHistoryEntry()
    2523             : {
    2524           0 :   if (mDocument) {
    2525           0 :     nsJSContext::PokeGC(JS::gcreason::PAGE_HIDE,
    2526           0 :                         mDocument->GetWrapperPreserveColor(),
    2527           0 :                         NS_GC_DELAY * 2);
    2528             :   }
    2529             : 
    2530           0 :   mSHEntry = nullptr;
    2531           0 :   return NS_OK;
    2532             : }
    2533             : 
    2534             : //-------------------------------------------------------
    2535             : 
    2536             : nsresult
    2537          28 : nsDocumentViewer::MakeWindow(const nsSize& aSize, nsView* aContainerView)
    2538             : {
    2539          28 :   if (GetIsPrintPreview())
    2540           0 :     return NS_OK;
    2541             : 
    2542          28 :   bool shouldAttach = ShouldAttachToTopLevel();
    2543             : 
    2544          28 :   if (shouldAttach) {
    2545             :     // If the old view is already attached to our parent, detach
    2546           6 :     DetachFromTopLevelWidget();
    2547             :   }
    2548             : 
    2549          28 :   mViewManager = new nsViewManager();
    2550             : 
    2551          28 :   nsDeviceContext *dx = mPresContext->DeviceContext();
    2552             : 
    2553          28 :   nsresult rv = mViewManager->Init(dx);
    2554          28 :   if (NS_FAILED(rv))
    2555           0 :     return rv;
    2556             : 
    2557          28 :   if (mPrintRelated) {
    2558           0 :     mViewManager->SetPrintRelated();
    2559             :   }
    2560             : 
    2561             :   // The root view is always at 0,0.
    2562          56 :   nsRect tbounds(nsPoint(0, 0), aSize);
    2563             :   // Create a view
    2564          28 :   nsView* view = mViewManager->CreateView(tbounds, aContainerView);
    2565          28 :   if (!view)
    2566           0 :     return NS_ERROR_OUT_OF_MEMORY;
    2567             : 
    2568             :   // Create a widget if we were given a parent widget or don't have a
    2569             :   // container view that we can hook up to without a widget.
    2570             :   // Don't create widgets for ResourceDocs (external resources & svg images),
    2571             :   // because when they're displayed, they're painted into *another* document's
    2572             :   // widget.
    2573          41 :   if (!mDocument->IsResourceDoc() &&
    2574           8 :       (mParentWidget || !aContainerView)) {
    2575             :     // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
    2576             :     // otherwise the view will find its own parent widget and "do the right thing" to
    2577             :     // establish a parent/child widget relationship
    2578           6 :     nsWidgetInitData initData;
    2579             :     nsWidgetInitData* initDataPtr;
    2580           6 :     if (!mParentWidget) {
    2581           0 :       initDataPtr = &initData;
    2582           0 :       initData.mWindowType = eWindowType_invisible;
    2583             :     } else {
    2584           6 :       initDataPtr = nullptr;
    2585             :     }
    2586             : 
    2587           6 :     if (shouldAttach) {
    2588             :       // Reuse the top level parent widget.
    2589           6 :       rv = view->AttachToTopLevelWidget(mParentWidget);
    2590           6 :       mAttachedToParent = true;
    2591             :     }
    2592           0 :     else if (!aContainerView && mParentWidget) {
    2593           0 :       rv = view->CreateWidgetForParent(mParentWidget, initDataPtr,
    2594           0 :                                        true, false);
    2595             :     }
    2596             :     else {
    2597           0 :       rv = view->CreateWidget(initDataPtr, true, false);
    2598             :     }
    2599           6 :     if (NS_FAILED(rv))
    2600           0 :       return rv;
    2601             :   }
    2602             : 
    2603             :   // Setup hierarchical relationship in view manager
    2604          28 :   mViewManager->SetRootView(view);
    2605             : 
    2606          28 :   mWindow = view->GetWidget();
    2607             : 
    2608             :   // This SetFocus is necessary so the Arrow Key and Page Key events
    2609             :   // go to the scrolled view as soon as the Window is created instead of going to
    2610             :   // the browser window (this enables keyboard scrolling of the document)
    2611             :   // mWindow->SetFocus();
    2612             : 
    2613          28 :   return rv;
    2614             : }
    2615             : 
    2616             : void
    2617           6 : nsDocumentViewer::DetachFromTopLevelWidget()
    2618             : {
    2619           6 :   if (mViewManager) {
    2620           0 :     nsView* oldView = mViewManager->GetRootView();
    2621           0 :     if (oldView && oldView->IsAttachedToTopLevel()) {
    2622           0 :       oldView->DetachFromTopLevelWidget();
    2623             :     }
    2624             :   }
    2625           6 :   mAttachedToParent = false;
    2626           6 : }
    2627             : 
    2628             : nsView*
    2629          50 : nsDocumentViewer::FindContainerView()
    2630             : {
    2631          50 :   if (!mContainer) {
    2632          42 :     return nullptr;
    2633             :   }
    2634             : 
    2635          16 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    2636          16 :   nsCOMPtr<nsPIDOMWindowOuter> pwin(docShell->GetWindow());
    2637           8 :   if (!pwin) {
    2638           0 :     return nullptr;
    2639             :   }
    2640             : 
    2641          16 :   nsCOMPtr<Element> containerElement = pwin->GetFrameElementInternal();
    2642           8 :   if (!containerElement) {
    2643           6 :     return nullptr;
    2644             :   }
    2645             : 
    2646           2 :   nsIFrame* subdocFrame = nsLayoutUtils::GetRealPrimaryFrameFor(containerElement);
    2647           2 :   if (!subdocFrame) {
    2648             :     // XXX Silenced by default in bug 1175289
    2649           1 :     LAYOUT_WARNING("Subdocument container has no frame");
    2650           1 :     return nullptr;
    2651             :   }
    2652             : 
    2653             :   // subdocFrame might not be a subdocument frame; the frame
    2654             :   // constructor can treat a <frame> as an inline in some XBL
    2655             :   // cases. Treat that as display:none, the document is not
    2656             :   // displayed.
    2657           1 :   if (!subdocFrame->IsSubDocumentFrame()) {
    2658           0 :     NS_WARNING_ASSERTION(subdocFrame->Type() == LayoutFrameType::None,
    2659             :                          "Subdocument container has non-subdocument frame");
    2660           0 :     return nullptr;
    2661             :   }
    2662             : 
    2663           1 :   NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views");
    2664           1 :   return static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView();
    2665             : }
    2666             : 
    2667             : nsresult
    2668          29 : nsDocumentViewer::CreateDeviceContext(nsView* aContainerView)
    2669             : {
    2670          29 :   NS_PRECONDITION(!mPresShell && !mWindow,
    2671             :                   "This will screw up our existing presentation");
    2672          29 :   NS_PRECONDITION(mDocument, "Gotta have a document here");
    2673             : 
    2674          29 :   nsIDocument* doc = mDocument->GetDisplayDocument();
    2675          29 :   if (doc) {
    2676           0 :     NS_ASSERTION(!aContainerView, "External resource document embedded somewhere?");
    2677             :     // We want to use our display document's device context if possible
    2678           0 :     nsIPresShell* shell = doc->GetShell();
    2679           0 :     if (shell) {
    2680           0 :       nsPresContext* ctx = shell->GetPresContext();
    2681           0 :       if (ctx) {
    2682           0 :         mDeviceContext = ctx->DeviceContext();
    2683           0 :         return NS_OK;
    2684             :       }
    2685             :     }
    2686             :   }
    2687             : 
    2688             :   // Create a device context even if we already have one, since our widget
    2689             :   // might have changed.
    2690          29 :   nsIWidget* widget = nullptr;
    2691          29 :   if (aContainerView) {
    2692           1 :     widget = aContainerView->GetNearestWidget(nullptr);
    2693             :   }
    2694          29 :   if (!widget) {
    2695          28 :     widget = mParentWidget;
    2696             :   }
    2697          29 :   if (widget) {
    2698           7 :     widget = widget->GetTopLevelWidget();
    2699             :   }
    2700             : 
    2701          29 :   mDeviceContext = new nsDeviceContext();
    2702          29 :   mDeviceContext->Init(widget);
    2703          29 :   return NS_OK;
    2704             : }
    2705             : 
    2706             : // Return the selection for the document. Note that text fields have their
    2707             : // own selection, which cannot be accessed with this method.
    2708             : mozilla::dom::Selection*
    2709          38 : nsDocumentViewer::GetDocumentSelection()
    2710             : {
    2711          38 :   if (!mPresShell) {
    2712           0 :     return nullptr;
    2713             :   }
    2714             : 
    2715          38 :   return mPresShell->GetCurrentSelection(SelectionType::eNormal);
    2716             : }
    2717             : 
    2718             : /* ========================================================================================
    2719             :  * nsIContentViewerEdit
    2720             :  * ======================================================================================== */
    2721             : 
    2722           0 : NS_IMETHODIMP nsDocumentViewer::ClearSelection()
    2723             : {
    2724             :   // use nsCopySupport::GetSelectionForCopy() ?
    2725           0 :   RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
    2726           0 :   if (!selection) {
    2727           0 :     return NS_ERROR_FAILURE;
    2728             :   }
    2729             : 
    2730           0 :   return selection->CollapseToStart();
    2731             : }
    2732             : 
    2733           0 : NS_IMETHODIMP nsDocumentViewer::SelectAll()
    2734             : {
    2735             :   // XXX this is a temporary implementation copied from nsWebShell
    2736             :   // for now. I think nsDocument and friends should have some helper
    2737             :   // functions to make this easier.
    2738             : 
    2739             :   // use nsCopySupport::GetSelectionForCopy() ?
    2740           0 :   RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
    2741           0 :   if (!selection) {
    2742           0 :     return NS_ERROR_FAILURE;
    2743             :   }
    2744             : 
    2745           0 :   nsCOMPtr<nsIDOMHTMLDocument> htmldoc = do_QueryInterface(mDocument);
    2746           0 :   nsCOMPtr<nsIDOMNode> bodyNode;
    2747             : 
    2748             :   nsresult rv;
    2749           0 :   if (htmldoc)
    2750             :   {
    2751           0 :     nsCOMPtr<nsIDOMHTMLElement>bodyElement;
    2752           0 :     rv = htmldoc->GetBody(getter_AddRefs(bodyElement));
    2753           0 :     if (NS_FAILED(rv) || !bodyElement) return rv;
    2754             : 
    2755           0 :     bodyNode = do_QueryInterface(bodyElement);
    2756             :   }
    2757           0 :   else if (mDocument)
    2758             :   {
    2759           0 :     bodyNode = do_QueryInterface(mDocument->GetRootElement());
    2760             :   }
    2761           0 :   if (!bodyNode) return NS_ERROR_FAILURE;
    2762             : 
    2763           0 :   rv = selection->RemoveAllRanges();
    2764           0 :   if (NS_FAILED(rv)) return rv;
    2765             : 
    2766           0 :   mozilla::dom::Selection::AutoUserInitiated userSelection(selection);
    2767           0 :   rv = selection->SelectAllChildren(bodyNode);
    2768           0 :   return rv;
    2769             : }
    2770             : 
    2771           0 : NS_IMETHODIMP nsDocumentViewer::CopySelection()
    2772             : {
    2773           0 :   nsCopySupport::FireClipboardEvent(eCopy, nsIClipboard::kGlobalClipboard,
    2774           0 :                                     mPresShell, nullptr);
    2775           0 :   return NS_OK;
    2776             : }
    2777             : 
    2778           0 : NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation()
    2779             : {
    2780           0 :   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
    2781           0 :   nsCOMPtr<nsIDOMNode> node;
    2782           0 :   GetPopupLinkNode(getter_AddRefs(node));
    2783             :   // make noise if we're not in a link
    2784           0 :   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
    2785             : 
    2786           0 :   nsCOMPtr<dom::Element> elm(do_QueryInterface(node));
    2787           0 :   NS_ENSURE_TRUE(elm, NS_ERROR_FAILURE);
    2788             : 
    2789           0 :   nsAutoString locationText;
    2790           0 :   nsContentUtils::GetLinkLocation(elm, locationText);
    2791           0 :   if (locationText.IsEmpty())
    2792           0 :     return NS_ERROR_FAILURE;
    2793             : 
    2794           0 :   nsresult rv = NS_OK;
    2795           0 :   nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
    2796           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2797             : 
    2798             :   // copy the href onto the clipboard
    2799           0 :   return clipboard->CopyString(locationText);
    2800             : }
    2801             : 
    2802           0 : NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags)
    2803             : {
    2804           0 :   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
    2805           0 :   nsCOMPtr<nsIImageLoadingContent> node;
    2806           0 :   GetPopupImageNode(getter_AddRefs(node));
    2807             :   // make noise if we're not in an image
    2808           0 :   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
    2809             : 
    2810           0 :   nsCOMPtr<nsILoadContext> loadContext(mContainer);
    2811           0 :   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
    2812             : }
    2813             : 
    2814             : 
    2815           0 : NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool *aCopyable)
    2816             : {
    2817           0 :   NS_ENSURE_ARG_POINTER(aCopyable);
    2818           0 :   *aCopyable = nsCopySupport::CanCopy(mDocument);
    2819           0 :   return NS_OK;
    2820             : }
    2821             : 
    2822           0 : NS_IMETHODIMP nsDocumentViewer::GetContents(const char *mimeType, bool selectionOnly, nsAString& aOutValue)
    2823             : {
    2824           0 :   aOutValue.Truncate();
    2825             : 
    2826           0 :   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
    2827           0 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
    2828             : 
    2829             :   // Now we have the selection.  Make sure it's nonzero:
    2830           0 :   nsCOMPtr<nsISelection> sel;
    2831           0 :   if (selectionOnly) {
    2832           0 :     nsCopySupport::GetSelectionForCopy(mDocument, getter_AddRefs(sel));
    2833           0 :     NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE);
    2834             : 
    2835             :     bool isCollapsed;
    2836           0 :     sel->GetIsCollapsed(&isCollapsed);
    2837           0 :     if (isCollapsed)
    2838           0 :       return NS_OK;
    2839             :   }
    2840             : 
    2841             :   // call the copy code
    2842           0 :   return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
    2843           0 :                                     mDocument, aOutValue);
    2844             : }
    2845             : 
    2846           2 : NS_IMETHODIMP nsDocumentViewer::GetCanGetContents(bool *aCanGetContents)
    2847             : {
    2848           2 :   NS_ENSURE_ARG_POINTER(aCanGetContents);
    2849           2 :   *aCanGetContents = false;
    2850           2 :   NS_ENSURE_STATE(mDocument);
    2851           2 :   *aCanGetContents = nsCopySupport::CanCopy(mDocument);
    2852           2 :   return NS_OK;
    2853             : }
    2854             : 
    2855           0 : NS_IMETHODIMP nsDocumentViewer::SetCommandNode(nsIDOMNode* aNode)
    2856             : {
    2857           0 :   nsIDocument* document = GetDocument();
    2858           0 :   NS_ENSURE_STATE(document);
    2859             : 
    2860           0 :   nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
    2861           0 :   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
    2862             : 
    2863           0 :   nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
    2864           0 :   NS_ENSURE_STATE(root);
    2865             : 
    2866           0 :   root->SetPopupNode(aNode);
    2867           0 :   return NS_OK;
    2868             : }
    2869             : 
    2870             : /* ========================================================================================
    2871             :  * nsIContentViewerFile
    2872             :  * ======================================================================================== */
    2873             : /** ---------------------------------------------------
    2874             :  *  See documentation above in the nsIContentViewerfile class definition
    2875             :  *      @update 01/24/00 dwc
    2876             :  */
    2877             : NS_IMETHODIMP
    2878           0 : nsDocumentViewer::Print(bool              aSilent,
    2879             :                           FILE *            aDebugFile,
    2880             :                           nsIPrintSettings* aPrintSettings)
    2881             : {
    2882             : #ifdef NS_PRINTING
    2883           0 :   SetPrintRelated();
    2884             : 
    2885           0 :   nsCOMPtr<nsIPrintSettings> printSettings;
    2886             : 
    2887             : #ifdef DEBUG
    2888           0 :   nsresult rv = NS_ERROR_FAILURE;
    2889             : 
    2890           0 :   mDebugFile = aDebugFile;
    2891             :   // if they don't pass in a PrintSettings, then make one
    2892             :   // it will have all the default values
    2893           0 :   printSettings = aPrintSettings;
    2894             :   nsCOMPtr<nsIPrintSettingsService> printSettingsSvc
    2895           0 :     = do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
    2896           0 :   if (NS_SUCCEEDED(rv)) {
    2897             :     // if they don't pass in a PrintSettings, then make one
    2898           0 :     if (printSettings == nullptr) {
    2899           0 :       printSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
    2900             :     }
    2901           0 :     NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!");
    2902             :   }
    2903           0 :   if (printSettings) printSettings->SetPrintSilent(aSilent);
    2904           0 :   if (printSettings) printSettings->SetShowPrintProgress(false);
    2905             : #endif
    2906             : 
    2907             : 
    2908           0 :   return Print(printSettings, nullptr);
    2909             : #else
    2910             :   return NS_ERROR_FAILURE;
    2911             : #endif
    2912             : }
    2913             : 
    2914             : // nsIContentViewerFile interface
    2915             : NS_IMETHODIMP
    2916           0 : nsDocumentViewer::GetPrintable(bool *aPrintable)
    2917             : {
    2918           0 :   NS_ENSURE_ARG_POINTER(aPrintable);
    2919             : 
    2920           0 :   *aPrintable = !GetIsPrinting();
    2921             : 
    2922           0 :   return NS_OK;
    2923             : }
    2924             : 
    2925           0 : NS_IMETHODIMP nsDocumentViewer::ScrollToNode(nsIDOMNode* aNode)
    2926             : {
    2927           0 :   NS_ENSURE_ARG(aNode);
    2928           0 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    2929           0 :   nsCOMPtr<nsIPresShell> presShell;
    2930           0 :   NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE);
    2931             : 
    2932             :   // Get the nsIContent interface, because that's what we need to
    2933             :   // get the primary frame
    2934             : 
    2935           0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    2936           0 :   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
    2937             : 
    2938             :   // Tell the PresShell to scroll to the primary frame of the content.
    2939           0 :   NS_ENSURE_SUCCESS(
    2940             :     presShell->ScrollContentIntoView(content,
    2941             :                                      nsIPresShell::ScrollAxis(
    2942             :                                        nsIPresShell::SCROLL_TOP,
    2943             :                                        nsIPresShell::SCROLL_ALWAYS),
    2944             :                                      nsIPresShell::ScrollAxis(),
    2945             :                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
    2946             :     NS_ERROR_FAILURE);
    2947           0 :   return NS_OK;
    2948             : }
    2949             : 
    2950             : void
    2951          36 : nsDocumentViewer::CallChildren(CallChildFunc aFunc, void* aClosure)
    2952             : {
    2953          72 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    2954          36 :   if (docShell)
    2955             :   {
    2956             :     int32_t i;
    2957             :     int32_t n;
    2958          36 :     docShell->GetChildCount(&n);
    2959          36 :     for (i=0; i < n; i++)
    2960             :     {
    2961           0 :       nsCOMPtr<nsIDocShellTreeItem> child;
    2962           0 :       docShell->GetChildAt(i, getter_AddRefs(child));
    2963           0 :       nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
    2964           0 :       NS_ASSERTION(childAsShell, "null child in docshell");
    2965           0 :       if (childAsShell)
    2966             :       {
    2967           0 :         nsCOMPtr<nsIContentViewer> childCV;
    2968           0 :         childAsShell->GetContentViewer(getter_AddRefs(childCV));
    2969           0 :         if (childCV)
    2970             :         {
    2971           0 :           (*aFunc)(childCV, aClosure);
    2972             :         }
    2973             :       }
    2974             :     }
    2975             :   }
    2976          36 : }
    2977             : 
    2978             : static void
    2979           0 : ChangeChildPaintingEnabled(nsIContentViewer* aChild, void* aClosure)
    2980             : {
    2981           0 :   bool* enablePainting = (bool*) aClosure;
    2982           0 :   if (*enablePainting) {
    2983           0 :     aChild->ResumePainting();
    2984             :   } else {
    2985           0 :     aChild->PausePainting();
    2986             :   }
    2987           0 : }
    2988             : 
    2989             : struct ZoomInfo
    2990             : {
    2991             :   float mZoom;
    2992             : };
    2993             : 
    2994             : static void
    2995           0 : SetChildTextZoom(nsIContentViewer* aChild, void* aClosure)
    2996             : {
    2997           0 :   struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
    2998           0 :   aChild->SetTextZoom(ZoomInfo->mZoom);
    2999           0 : }
    3000             : 
    3001             : static void
    3002           0 : SetChildMinFontSize(nsIContentViewer* aChild, void* aClosure)
    3003             : {
    3004           0 :   aChild->SetMinFontSize(NS_PTR_TO_INT32(aClosure));
    3005           0 : }
    3006             : 
    3007             : static void
    3008           0 : SetChildFullZoom(nsIContentViewer* aChild, void* aClosure)
    3009             : {
    3010           0 :   struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
    3011           0 :   aChild->SetFullZoom(ZoomInfo->mZoom);
    3012           0 : }
    3013             : 
    3014             : static void
    3015           0 : SetChildOverrideDPPX(nsIContentViewer* aChild, void* aClosure)
    3016             : {
    3017           0 :   struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
    3018           0 :   aChild->SetOverrideDPPX(ZoomInfo->mZoom);
    3019           0 : }
    3020             : 
    3021             : static bool
    3022           0 : SetExtResourceTextZoom(nsIDocument* aDocument, void* aClosure)
    3023             : {
    3024             :   // Would it be better to enumerate external resource viewers instead?
    3025           0 :   nsIPresShell* shell = aDocument->GetShell();
    3026           0 :   if (shell) {
    3027           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3028           0 :     if (ctxt) {
    3029           0 :       struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
    3030           0 :       ctxt->SetTextZoom(ZoomInfo->mZoom);
    3031             :     }
    3032             :   }
    3033             : 
    3034           0 :   return true;
    3035             : }
    3036             : 
    3037             : static bool
    3038           0 : SetExtResourceMinFontSize(nsIDocument* aDocument, void* aClosure)
    3039             : {
    3040           0 :   nsIPresShell* shell = aDocument->GetShell();
    3041           0 :   if (shell) {
    3042           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3043           0 :     if (ctxt) {
    3044           0 :       ctxt->SetBaseMinFontSize(NS_PTR_TO_INT32(aClosure));
    3045             :     }
    3046             :   }
    3047             : 
    3048           0 :   return true;
    3049             : }
    3050             : 
    3051             : static bool
    3052           0 : SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure)
    3053             : {
    3054             :   // Would it be better to enumerate external resource viewers instead?
    3055           0 :   nsIPresShell* shell = aDocument->GetShell();
    3056           0 :   if (shell) {
    3057           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3058           0 :     if (ctxt) {
    3059           0 :       struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
    3060           0 :       ctxt->SetFullZoom(ZoomInfo->mZoom);
    3061             :     }
    3062             :   }
    3063             : 
    3064           0 :   return true;
    3065             : }
    3066             : 
    3067             : static bool
    3068           0 : SetExtResourceOverrideDPPX(nsIDocument* aDocument, void* aClosure)
    3069             : {
    3070           0 :   nsIPresShell* shell = aDocument->GetShell();
    3071           0 :   if (shell) {
    3072           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3073           0 :     if (ctxt) {
    3074           0 :       struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
    3075           0 :       ctxt->SetOverrideDPPX(ZoomInfo->mZoom);
    3076             :     }
    3077             :   }
    3078             : 
    3079           0 :   return true;
    3080             : }
    3081             : 
    3082             : NS_IMETHODIMP
    3083           6 : nsDocumentViewer::SetTextZoom(float aTextZoom)
    3084             : {
    3085             :   // If we don't have a document, then we need to bail.
    3086           6 :   if (!mDocument) {
    3087           0 :     return NS_ERROR_FAILURE;
    3088             :   }
    3089             : 
    3090           6 :   if (GetIsPrintPreview()) {
    3091           0 :     return NS_OK;
    3092             :   }
    3093             : 
    3094           6 :   mTextZoom = aTextZoom;
    3095             : 
    3096             :   // Set the text zoom on all children of mContainer (even if our zoom didn't
    3097             :   // change, our children's zoom may be different, though it would be unusual).
    3098             :   // Do this first, in case kids are auto-sizing and post reflow commands on
    3099             :   // our presshell (which should be subsumed into our own style change reflow).
    3100           6 :   struct ZoomInfo ZoomInfo = { aTextZoom };
    3101           6 :   CallChildren(SetChildTextZoom, &ZoomInfo);
    3102             : 
    3103             :   // Now change our own zoom
    3104           6 :   nsPresContext* pc = GetPresContext();
    3105           6 :   if (pc && aTextZoom != mPresContext->TextZoom()) {
    3106           0 :       pc->SetTextZoom(aTextZoom);
    3107             :   }
    3108             : 
    3109             :   // And do the external resources
    3110           6 :   mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo);
    3111             : 
    3112           6 :   nsContentUtils::DispatchChromeEvent(mDocument, static_cast<nsIDocument*>(mDocument),
    3113          12 :                                       NS_LITERAL_STRING("TextZoomChange"),
    3114          12 :                                       true, true);
    3115             : 
    3116           6 :   return NS_OK;
    3117             : }
    3118             : 
    3119             : NS_IMETHODIMP
    3120           7 : nsDocumentViewer::GetTextZoom(float* aTextZoom)
    3121             : {
    3122           7 :   NS_ENSURE_ARG_POINTER(aTextZoom);
    3123           7 :   nsPresContext* pc = GetPresContext();
    3124           7 :   *aTextZoom = pc ? pc->TextZoom() : 1.0f;
    3125           7 :   return NS_OK;
    3126             : }
    3127             : 
    3128             : NS_IMETHODIMP
    3129           0 : nsDocumentViewer::GetEffectiveTextZoom(float* aEffectiveTextZoom)
    3130             : {
    3131           0 :   NS_ENSURE_ARG_POINTER(aEffectiveTextZoom);
    3132           0 :   nsPresContext* pc = GetPresContext();
    3133           0 :   *aEffectiveTextZoom = pc ? pc->EffectiveTextZoom() : 1.0f;
    3134           0 :   return NS_OK;
    3135             : }
    3136             : 
    3137             : NS_IMETHODIMP
    3138           4 : nsDocumentViewer::SetMinFontSize(int32_t aMinFontSize)
    3139             : {
    3140             :   // If we don't have a document, then we need to bail.
    3141           4 :   if (!mDocument) {
    3142           0 :     return NS_ERROR_FAILURE;
    3143             :   }
    3144             : 
    3145           4 :   if (GetIsPrintPreview()) {
    3146           0 :     return NS_OK;
    3147             :   }
    3148             : 
    3149           4 :   mMinFontSize = aMinFontSize;
    3150             : 
    3151             :   // Set the min font on all children of mContainer (even if our min font didn't
    3152             :   // change, our children's min font may be different, though it would be unusual).
    3153             :   // Do this first, in case kids are auto-sizing and post reflow commands on
    3154             :   // our presshell (which should be subsumed into our own style change reflow).
    3155           4 :   CallChildren(SetChildMinFontSize, NS_INT32_TO_PTR(aMinFontSize));
    3156             : 
    3157             :   // Now change our own min font
    3158           4 :   nsPresContext* pc = GetPresContext();
    3159           4 :   if (pc && aMinFontSize != mPresContext->MinFontSize(nullptr)) {
    3160           0 :     pc->SetBaseMinFontSize(aMinFontSize);
    3161             :   }
    3162             : 
    3163             :   // And do the external resources
    3164           8 :   mDocument->EnumerateExternalResources(SetExtResourceMinFontSize,
    3165           8 :                                         NS_INT32_TO_PTR(aMinFontSize));
    3166             : 
    3167           4 :   return NS_OK;
    3168             : }
    3169             : 
    3170             : NS_IMETHODIMP
    3171           4 : nsDocumentViewer::GetMinFontSize(int32_t* aMinFontSize)
    3172             : {
    3173           4 :   NS_ENSURE_ARG_POINTER(aMinFontSize);
    3174           4 :   nsPresContext* pc = GetPresContext();
    3175           4 :   *aMinFontSize = pc ? pc->BaseMinFontSize() : 0;
    3176           4 :   return NS_OK;
    3177             : }
    3178             : 
    3179             : NS_IMETHODIMP
    3180           6 : nsDocumentViewer::SetFullZoom(float aFullZoom)
    3181             : {
    3182             : #ifdef NS_PRINT_PREVIEW
    3183           6 :   if (GetIsPrintPreview()) {
    3184           0 :     nsPresContext* pc = GetPresContext();
    3185           0 :     NS_ENSURE_TRUE(pc, NS_OK);
    3186           0 :     nsCOMPtr<nsIPresShell> shell = pc->GetPresShell();
    3187           0 :     NS_ENSURE_TRUE(shell, NS_OK);
    3188             : 
    3189           0 :     if (!mPrintPreviewZoomed) {
    3190           0 :       mOriginalPrintPreviewScale = pc->GetPrintPreviewScale();
    3191           0 :       mPrintPreviewZoomed = true;
    3192             :     }
    3193             : 
    3194           0 :     mPrintPreviewZoom = aFullZoom;
    3195           0 :     pc->SetPrintPreviewScale(aFullZoom * mOriginalPrintPreviewScale);
    3196           0 :     nsIPageSequenceFrame* pf = shell->GetPageSequenceFrame();
    3197           0 :     if (pf) {
    3198           0 :       nsIFrame* f = do_QueryFrame(pf);
    3199           0 :       shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
    3200             :     }
    3201             : 
    3202           0 :     nsIFrame* rootFrame = shell->GetRootFrame();
    3203           0 :     if (rootFrame) {
    3204           0 :       rootFrame->InvalidateFrame();
    3205             :     }
    3206           0 :     return NS_OK;
    3207             :   }
    3208             : #endif
    3209             : 
    3210             :   // If we don't have a document, then we need to bail.
    3211           6 :   if (!mDocument) {
    3212           0 :     return NS_ERROR_FAILURE;
    3213             :   }
    3214             : 
    3215           6 :   bool fullZoomChange = (mPageZoom != aFullZoom);
    3216           6 :   mPageZoom = aFullZoom;
    3217             : 
    3218           6 :   struct ZoomInfo ZoomInfo = { aFullZoom };
    3219           6 :   CallChildren(SetChildFullZoom, &ZoomInfo);
    3220             : 
    3221           6 :   nsPresContext* pc = GetPresContext();
    3222           6 :   if (pc) {
    3223           5 :     pc->SetFullZoom(aFullZoom);
    3224             :   }
    3225             : 
    3226             :   // And do the external resources
    3227           6 :   mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo);
    3228             : 
    3229             :   // Dispatch FullZoomChange event only if fullzoom value really was been changed
    3230           6 :   if (fullZoomChange) {
    3231           0 :     nsContentUtils::DispatchChromeEvent(mDocument, static_cast<nsIDocument*>(mDocument),
    3232           0 :                                         NS_LITERAL_STRING("FullZoomChange"),
    3233           0 :                                         true, true);
    3234             :   }
    3235             : 
    3236           6 :   return NS_OK;
    3237             : }
    3238             : 
    3239             : NS_IMETHODIMP
    3240           4 : nsDocumentViewer::GetFullZoom(float* aFullZoom)
    3241             : {
    3242           4 :   NS_ENSURE_ARG_POINTER(aFullZoom);
    3243             : #ifdef NS_PRINT_PREVIEW
    3244           4 :   if (GetIsPrintPreview()) {
    3245           0 :     *aFullZoom = mPrintPreviewZoom;
    3246           0 :     return NS_OK;
    3247             :   }
    3248             : #endif
    3249             :   // Check the prescontext first because it might have a temporary
    3250             :   // setting for print-preview
    3251           4 :   nsPresContext* pc = GetPresContext();
    3252           4 :   *aFullZoom = pc ? pc->GetFullZoom() : mPageZoom;
    3253           4 :   return NS_OK;
    3254             : }
    3255             : 
    3256             : NS_IMETHODIMP
    3257           4 : nsDocumentViewer::SetOverrideDPPX(float aDPPX)
    3258             : {
    3259             :   // If we don't have a document, then we need to bail.
    3260           4 :   if (!mDocument) {
    3261           0 :     return NS_ERROR_FAILURE;
    3262             :   }
    3263             : 
    3264           4 :   mOverrideDPPX = aDPPX;
    3265             : 
    3266           4 :   struct ZoomInfo ZoomInfo = { aDPPX };
    3267           4 :   CallChildren(SetChildOverrideDPPX, &ZoomInfo);
    3268             : 
    3269           4 :   nsPresContext* pc = GetPresContext();
    3270           4 :   if (pc) {
    3271           3 :     pc->SetOverrideDPPX(aDPPX);
    3272             :   }
    3273             : 
    3274             :   // And do the external resources
    3275           4 :   mDocument->EnumerateExternalResources(SetExtResourceOverrideDPPX, &ZoomInfo);
    3276             : 
    3277           4 :   return NS_OK;
    3278             : }
    3279             : 
    3280             : NS_IMETHODIMP
    3281           4 : nsDocumentViewer::GetOverrideDPPX(float* aDPPX)
    3282             : {
    3283           4 :   NS_ENSURE_ARG_POINTER(aDPPX);
    3284             : 
    3285           4 :   nsPresContext* pc = GetPresContext();
    3286           4 :   *aDPPX = pc ? pc->GetOverrideDPPX() : mOverrideDPPX;
    3287           4 :   return NS_OK;
    3288             : }
    3289             : 
    3290             : static void
    3291           0 : SetChildAuthorStyleDisabled(nsIContentViewer* aChild, void* aClosure)
    3292             : {
    3293           0 :   bool styleDisabled  = *static_cast<bool*>(aClosure);
    3294           0 :   aChild->SetAuthorStyleDisabled(styleDisabled);
    3295           0 : }
    3296             : 
    3297             : 
    3298             : NS_IMETHODIMP
    3299           4 : nsDocumentViewer::SetAuthorStyleDisabled(bool aStyleDisabled)
    3300             : {
    3301           4 :   if (mPresShell) {
    3302           3 :     mPresShell->SetAuthorStyleDisabled(aStyleDisabled);
    3303             :   }
    3304           4 :   CallChildren(SetChildAuthorStyleDisabled, &aStyleDisabled);
    3305           4 :   return NS_OK;
    3306             : }
    3307             : 
    3308             : NS_IMETHODIMP
    3309           7 : nsDocumentViewer::GetAuthorStyleDisabled(bool* aStyleDisabled)
    3310             : {
    3311           7 :   if (mPresShell) {
    3312           7 :     *aStyleDisabled = mPresShell->GetAuthorStyleDisabled();
    3313             :   } else {
    3314           0 :     *aStyleDisabled = false;
    3315             :   }
    3316           7 :   return NS_OK;
    3317             : }
    3318             : 
    3319             : static bool
    3320           0 : ExtResourceEmulateMedium(nsIDocument* aDocument, void* aClosure)
    3321             : {
    3322           0 :   nsIPresShell* shell = aDocument->GetShell();
    3323           0 :   if (shell) {
    3324           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3325           0 :     if (ctxt) {
    3326           0 :       const nsAString* mediaType = static_cast<nsAString*>(aClosure);
    3327           0 :       ctxt->EmulateMedium(*mediaType);
    3328             :     }
    3329             :   }
    3330             : 
    3331           0 :   return true;
    3332             : }
    3333             : 
    3334             : static void
    3335           0 : ChildEmulateMedium(nsIContentViewer* aChild, void* aClosure)
    3336             : {
    3337           0 :   const nsAString* mediaType = static_cast<nsAString*>(aClosure);
    3338           0 :   aChild->EmulateMedium(*mediaType);
    3339           0 : }
    3340             : 
    3341             : NS_IMETHODIMP
    3342           0 : nsDocumentViewer::EmulateMedium(const nsAString& aMediaType)
    3343             : {
    3344           0 :   if (mPresContext) {
    3345           0 :     mPresContext->EmulateMedium(aMediaType);
    3346             :   }
    3347           0 :   CallChildren(ChildEmulateMedium, const_cast<nsAString*>(&aMediaType));
    3348             : 
    3349           0 :   if (mDocument) {
    3350           0 :     mDocument->EnumerateExternalResources(ExtResourceEmulateMedium,
    3351           0 :                                           const_cast<nsAString*>(&aMediaType));
    3352             :   }
    3353             : 
    3354           0 :   return NS_OK;
    3355             : }
    3356             : 
    3357             : static bool
    3358           0 : ExtResourceStopEmulatingMedium(nsIDocument* aDocument, void* aClosure)
    3359             : {
    3360           0 :   nsIPresShell* shell = aDocument->GetShell();
    3361           0 :   if (shell) {
    3362           0 :     nsPresContext* ctxt = shell->GetPresContext();
    3363           0 :     if (ctxt) {
    3364           0 :       ctxt->StopEmulatingMedium();
    3365             :     }
    3366             :   }
    3367             : 
    3368           0 :   return true;
    3369             : }
    3370             : 
    3371             : static void
    3372           0 : ChildStopEmulatingMedium(nsIContentViewer* aChild, void* aClosure)
    3373             : {
    3374           0 :   aChild->StopEmulatingMedium();
    3375           0 : }
    3376             : 
    3377             : NS_IMETHODIMP
    3378           0 : nsDocumentViewer::StopEmulatingMedium()
    3379             : {
    3380           0 :   if (mPresContext) {
    3381           0 :     mPresContext->StopEmulatingMedium();
    3382             :   }
    3383           0 :   CallChildren(ChildStopEmulatingMedium, nullptr);
    3384             : 
    3385           0 :   if (mDocument) {
    3386           0 :     mDocument->EnumerateExternalResources(ExtResourceStopEmulatingMedium,
    3387           0 :                                           nullptr);
    3388             :   }
    3389             : 
    3390           0 :   return NS_OK;
    3391             : }
    3392             : 
    3393           0 : NS_IMETHODIMP nsDocumentViewer::GetForceCharacterSet(nsACString& aForceCharacterSet)
    3394             : {
    3395           0 :   auto encoding = nsDocumentViewer::GetForceCharset();
    3396           0 :   if (encoding) {
    3397           0 :     encoding->Name(aForceCharacterSet);
    3398             :   } else {
    3399           0 :     aForceCharacterSet.Truncate();
    3400             :   }
    3401           0 :   return NS_OK;
    3402             : }
    3403             : 
    3404             : /* [noscript,notxpcom] Encoding getForceCharset (); */
    3405             : NS_IMETHODIMP_(const Encoding *)
    3406           5 : nsDocumentViewer::GetForceCharset()
    3407             : {
    3408           5 :   return mForceCharacterSet;
    3409             : }
    3410             : 
    3411             : static void
    3412           0 : SetChildForceCharacterSet(nsIContentViewer* aChild, void* aClosure)
    3413             : {
    3414           0 :   auto encoding = static_cast<const Encoding*>(aClosure);
    3415           0 :   aChild->SetForceCharset(encoding);
    3416           0 : }
    3417             : 
    3418             : NS_IMETHODIMP
    3419           0 : nsDocumentViewer::SetForceCharacterSet(const nsACString& aForceCharacterSet)
    3420             : {
    3421             :   // This method is scriptable, so add-ons could pass in something other
    3422             :   // than a canonical name. However, in case where the input is a canonical
    3423             :   // name, "replacement" doesn't survive label resolution. Additionally, the
    3424             :   // empty string means no hint.
    3425           0 :   const Encoding* encoding = nullptr;
    3426           0 :   if (!aForceCharacterSet.IsEmpty()) {
    3427           0 :     if (aForceCharacterSet.EqualsLiteral("replacement")) {
    3428           0 :       encoding = REPLACEMENT_ENCODING;
    3429           0 :     } else if (!(encoding = Encoding::ForLabel(aForceCharacterSet))) {
    3430             :       // Reject unknown labels
    3431           0 :       return NS_ERROR_INVALID_ARG;
    3432             :     }
    3433             :   }
    3434           0 :   nsDocumentViewer::SetForceCharset(encoding);
    3435           0 :   return NS_OK;
    3436             : }
    3437             : 
    3438             : /* [noscript,notxpcom] void setForceCharset (in Encoding aEncoding); */
    3439             : NS_IMETHODIMP_(void)
    3440           4 : nsDocumentViewer::SetForceCharset(const Encoding *aEncoding)
    3441             : {
    3442           4 :   mForceCharacterSet = aEncoding;
    3443             :   // now set the force char set on all children of mContainer
    3444           4 :   CallChildren(SetChildForceCharacterSet, (void*) aEncoding);
    3445           4 : }
    3446             : 
    3447           0 : NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(nsACString& aHintCharacterSet)
    3448             : {
    3449           0 :   auto encoding = nsDocumentViewer::GetHintCharset();
    3450           0 :   if (encoding) {
    3451           0 :     encoding->Name(aHintCharacterSet);
    3452             :   } else {
    3453           0 :     aHintCharacterSet.Truncate();
    3454             :   }
    3455           0 :   return NS_OK;
    3456             : }
    3457             : 
    3458             : /* [noscript,notxpcom] Encoding getHintCharset (); */
    3459             : NS_IMETHODIMP_(const Encoding *)
    3460           4 : nsDocumentViewer::GetHintCharset()
    3461             : {
    3462           4 :   if(kCharsetUninitialized == mHintCharsetSource) {
    3463           4 :     return nullptr;
    3464             :   }
    3465             :   // this can't possibly be right.  we can't set a value just because somebody got a related value!
    3466             :   //mHintCharsetSource = kCharsetUninitialized;
    3467           0 :   return mHintCharset;
    3468             : }
    3469             : 
    3470           7 : NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSetSource(int32_t *aHintCharacterSetSource)
    3471             : {
    3472           7 :   NS_ENSURE_ARG_POINTER(aHintCharacterSetSource);
    3473             : 
    3474           7 :   *aHintCharacterSetSource = mHintCharsetSource;
    3475           7 :   return NS_OK;
    3476             : }
    3477             : 
    3478             : static void
    3479           0 : SetChildHintCharacterSetSource(nsIContentViewer* aChild, void* aClosure)
    3480             : {
    3481           0 :   aChild->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure));
    3482           0 : }
    3483             : 
    3484             : NS_IMETHODIMP
    3485           4 : nsDocumentViewer::SetHintCharacterSetSource(int32_t aHintCharacterSetSource)
    3486             : {
    3487           4 :   mHintCharsetSource = aHintCharacterSetSource;
    3488             :   // now set the hint char set source on all children of mContainer
    3489           4 :   CallChildren(SetChildHintCharacterSetSource,
    3490           8 :                       NS_INT32_TO_PTR(aHintCharacterSetSource));
    3491           4 :   return NS_OK;
    3492             : }
    3493             : 
    3494             : static void
    3495           0 : SetChildHintCharacterSet(nsIContentViewer* aChild, void* aClosure)
    3496             : {
    3497           0 :   auto encoding = static_cast<const Encoding*>(aClosure);
    3498           0 :   aChild->SetHintCharset(encoding);
    3499           0 : }
    3500             : 
    3501             : NS_IMETHODIMP
    3502           0 : nsDocumentViewer::SetHintCharacterSet(const nsACString& aHintCharacterSet)
    3503             : {
    3504             :   // This method is scriptable, so add-ons could pass in something other
    3505             :   // than a canonical name. However, in case where the input is a canonical
    3506             :   // name, "replacement" doesn't survive label resolution. Additionally, the
    3507             :   // empty string means no hint.
    3508           0 :   const Encoding* encoding = nullptr;
    3509           0 :   if (!aHintCharacterSet.IsEmpty()) {
    3510           0 :     if (aHintCharacterSet.EqualsLiteral("replacement")) {
    3511           0 :       encoding = REPLACEMENT_ENCODING;
    3512           0 :     } else if (!(encoding = Encoding::ForLabel(aHintCharacterSet))) {
    3513             :       // Reject unknown labels
    3514           0 :       return NS_ERROR_INVALID_ARG;
    3515             :     }
    3516             :   }
    3517           0 :   nsDocumentViewer::SetHintCharset(encoding);
    3518           0 :   return NS_OK;
    3519             : }
    3520             : 
    3521             : /* [noscript,notxpcom] void setHintCharset (in Encoding aEncoding); */
    3522             : NS_IMETHODIMP_(void)
    3523           4 : nsDocumentViewer::SetHintCharset(const Encoding *aEncoding)
    3524             : {
    3525           4 :   mHintCharset = aEncoding;
    3526             :   // now set the hint char set on all children of mContainer
    3527           4 :   CallChildren(SetChildHintCharacterSet, (void*) aEncoding);
    3528           4 : }
    3529             : 
    3530             : static void
    3531           0 : AppendChildSubtree(nsIContentViewer* aChild, void* aClosure)
    3532             : {
    3533             :   nsTArray<nsCOMPtr<nsIContentViewer> >& array =
    3534           0 :     *static_cast<nsTArray<nsCOMPtr<nsIContentViewer> >*>(aClosure);
    3535           0 :   aChild->AppendSubtree(array);
    3536           0 : }
    3537             : 
    3538           0 : NS_IMETHODIMP nsDocumentViewer::AppendSubtree(nsTArray<nsCOMPtr<nsIContentViewer> >& aArray)
    3539             : {
    3540           0 :   aArray.AppendElement(this);
    3541           0 :   CallChildren(AppendChildSubtree, &aArray);
    3542           0 :   return NS_OK;
    3543             : }
    3544             : 
    3545             : NS_IMETHODIMP
    3546           0 : nsDocumentViewer::PausePainting()
    3547             : {
    3548           0 :   bool enablePaint = false;
    3549           0 :   CallChildren(ChangeChildPaintingEnabled, &enablePaint);
    3550             : 
    3551           0 :   nsIPresShell* presShell = GetPresShell();
    3552           0 :   if (presShell) {
    3553           0 :     presShell->PausePainting();
    3554             :   }
    3555             : 
    3556           0 :   return NS_OK;
    3557             : }
    3558             : 
    3559             : NS_IMETHODIMP
    3560           0 : nsDocumentViewer::ResumePainting()
    3561             : {
    3562           0 :   bool enablePaint = true;
    3563           0 :   CallChildren(ChangeChildPaintingEnabled, &enablePaint);
    3564             : 
    3565           0 :   nsIPresShell* presShell = GetPresShell();
    3566           0 :   if (presShell) {
    3567           0 :     presShell->ResumePainting();
    3568             :   }
    3569             : 
    3570           0 :   return NS_OK;
    3571             : }
    3572             : 
    3573             : nsresult
    3574           0 : nsDocumentViewer::GetContentSizeInternal(int32_t* aWidth, int32_t* aHeight,
    3575             :                                          nscoord aMaxWidth, nscoord aMaxHeight)
    3576             : {
    3577           0 :   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
    3578             : 
    3579           0 :   nsCOMPtr<nsIPresShell> presShell;
    3580           0 :   GetPresShell(getter_AddRefs(presShell));
    3581           0 :   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    3582             : 
    3583             :   // Flush out all content and style updates. We can't use a resize reflow
    3584             :   // because it won't change some sizes that a style change reflow will.
    3585           0 :   mDocument->FlushPendingNotifications(FlushType::Layout);
    3586             : 
    3587           0 :   nsIFrame *root = presShell->GetRootFrame();
    3588           0 :   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
    3589             : 
    3590             :   nscoord prefWidth;
    3591             :   {
    3592           0 :     RefPtr<gfxContext> rcx(presShell->CreateReferenceRenderingContext());
    3593           0 :     prefWidth = root->GetPrefISize(rcx);
    3594             :   }
    3595           0 :   if (prefWidth > aMaxWidth) {
    3596           0 :     prefWidth = aMaxWidth;
    3597             :   }
    3598             : 
    3599           0 :   nsresult rv = presShell->ResizeReflow(prefWidth, NS_UNCONSTRAINEDSIZE);
    3600           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3601             : 
    3602           0 :   RefPtr<nsPresContext> presContext;
    3603           0 :   GetPresContext(getter_AddRefs(presContext));
    3604           0 :   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
    3605             : 
    3606             :   // so how big is it?
    3607           0 :   nsRect shellArea = presContext->GetVisibleArea();
    3608           0 :   if (shellArea.height > aMaxHeight) {
    3609             :     // Reflow to max height if we would up too tall.
    3610           0 :     rv = presShell->ResizeReflow(prefWidth, aMaxHeight);
    3611           0 :     NS_ENSURE_SUCCESS(rv, rv);
    3612             : 
    3613           0 :     shellArea = presContext->GetVisibleArea();
    3614             :   }
    3615             : 
    3616             :   // Protect against bogus returns here
    3617           0 :   NS_ENSURE_TRUE(shellArea.width != NS_UNCONSTRAINEDSIZE &&
    3618             :                  shellArea.height != NS_UNCONSTRAINEDSIZE,
    3619             :                  NS_ERROR_FAILURE);
    3620             : 
    3621           0 :   *aWidth = presContext->AppUnitsToDevPixels(shellArea.width);
    3622           0 :   *aHeight = presContext->AppUnitsToDevPixels(shellArea.height);
    3623             : 
    3624           0 :   return NS_OK;
    3625             : }
    3626             : 
    3627             : NS_IMETHODIMP
    3628           0 : nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight)
    3629             : {
    3630             :   // Skip doing this on docshell-less documents for now
    3631           0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(mContainer);
    3632           0 :   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_NOT_AVAILABLE);
    3633             : 
    3634           0 :   nsCOMPtr<nsIDocShellTreeItem> docShellParent;
    3635           0 :   docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent));
    3636             : 
    3637             :   // It's only valid to access this from a top frame.  Doesn't work from
    3638             :   // sub-frames.
    3639           0 :   NS_ENSURE_TRUE(!docShellParent, NS_ERROR_FAILURE);
    3640             : 
    3641           0 :   return GetContentSizeInternal(aWidth, aHeight, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
    3642             : }
    3643             : 
    3644             : NS_IMETHODIMP
    3645           0 : nsDocumentViewer::GetContentSizeConstrained(int32_t aMaxWidth, int32_t aMaxHeight,
    3646             :                                             int32_t* aWidth, int32_t* aHeight)
    3647             : {
    3648           0 :   RefPtr<nsPresContext> presContext;
    3649           0 :   GetPresContext(getter_AddRefs(presContext));
    3650           0 :   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
    3651             : 
    3652           0 :   nscoord maxWidth = NS_UNCONSTRAINEDSIZE;
    3653           0 :   nscoord maxHeight = NS_UNCONSTRAINEDSIZE;
    3654           0 :   if (aMaxWidth > 0) {
    3655           0 :     maxWidth = presContext->DevPixelsToAppUnits(aMaxWidth);
    3656             :   }
    3657           0 :   if (aMaxHeight > 0) {
    3658           0 :     maxHeight = presContext->DevPixelsToAppUnits(aMaxHeight);
    3659             :   }
    3660             : 
    3661           0 :   return GetContentSizeInternal(aWidth, aHeight, maxWidth, maxHeight);
    3662             : }
    3663             : 
    3664             : 
    3665         159 : NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, nsISelectionListener)
    3666             : 
    3667          28 : nsresult nsDocViewerSelectionListener::Init(nsDocumentViewer *aDocViewer)
    3668             : {
    3669          28 :   mDocViewer = aDocViewer;
    3670          28 :   return NS_OK;
    3671             : }
    3672             : 
    3673             : /*
    3674             :  * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
    3675             :  * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
    3676             :  * of commands. The focus controller stores the popup node, these retrieve
    3677             :  * them and munge appropriately. Note that we have to store the popup node
    3678             :  * rather than retrieving it from EventStateManager::GetFocusedContent because
    3679             :  * not all content (images included) can receive focus.
    3680             :  */
    3681             : 
    3682             : nsresult
    3683           8 : nsDocumentViewer::GetPopupNode(nsIDOMNode** aNode)
    3684             : {
    3685           8 :   NS_ENSURE_ARG_POINTER(aNode);
    3686             : 
    3687           8 :   *aNode = nullptr;
    3688             : 
    3689             :   // get the document
    3690           8 :   nsIDocument* document = GetDocument();
    3691           8 :   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
    3692             : 
    3693             :   // get the private dom window
    3694          16 :   nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
    3695           8 :   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
    3696           8 :   if (window) {
    3697          16 :     nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
    3698           8 :     NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
    3699             : 
    3700             :     // get the popup node
    3701          16 :     nsCOMPtr<nsIDOMNode> node = root->GetPopupNode();
    3702             : #ifdef MOZ_XUL
    3703           8 :     if (!node) {
    3704           8 :       nsPIDOMWindowOuter* rootWindow = root->GetWindow();
    3705           8 :       if (rootWindow) {
    3706          16 :         nsCOMPtr<nsIDocument> rootDoc = rootWindow->GetExtantDoc();
    3707           8 :         if (rootDoc) {
    3708           8 :           nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    3709           8 :           if (pm) {
    3710           8 :             node = pm->GetLastTriggerPopupNode(rootDoc);
    3711             :           }
    3712             :         }
    3713             :       }
    3714             :     }
    3715             : #endif
    3716           8 :     node.swap(*aNode);
    3717             :   }
    3718             : 
    3719           8 :   return NS_OK;
    3720             : }
    3721             : 
    3722             : // GetPopupLinkNode: return popup link node or fail
    3723             : nsresult
    3724           2 : nsDocumentViewer::GetPopupLinkNode(nsIDOMNode** aNode)
    3725             : {
    3726           2 :   NS_ENSURE_ARG_POINTER(aNode);
    3727             : 
    3728             :   // you get null unless i say so
    3729           2 :   *aNode = nullptr;
    3730             : 
    3731             :   // find popup node
    3732           4 :   nsCOMPtr<nsIDOMNode> node;
    3733           2 :   nsresult rv = GetPopupNode(getter_AddRefs(node));
    3734           2 :   NS_ENSURE_SUCCESS(rv, rv);
    3735             : 
    3736             :   // find out if we have a link in our ancestry
    3737           2 :   while (node) {
    3738             : 
    3739           0 :     nsCOMPtr<nsIContent> content(do_QueryInterface(node));
    3740           0 :     if (content) {
    3741           0 :       nsCOMPtr<nsIURI> hrefURI = content->GetHrefURI();
    3742           0 :       if (hrefURI) {
    3743           0 :         *aNode = node;
    3744           0 :         NS_IF_ADDREF(*aNode); // addref
    3745           0 :         return NS_OK;
    3746             :       }
    3747             :     }
    3748             : 
    3749             :     // get our parent and keep trying...
    3750           0 :     nsCOMPtr<nsIDOMNode> parentNode;
    3751           0 :     node->GetParentNode(getter_AddRefs(parentNode));
    3752           0 :     node = parentNode;
    3753             :   }
    3754             : 
    3755             :   // if we have no node, fail
    3756           2 :   return NS_ERROR_FAILURE;
    3757             : }
    3758             : 
    3759             : // GetPopupLinkNode: return popup image node or fail
    3760             : nsresult
    3761           6 : nsDocumentViewer::GetPopupImageNode(nsIImageLoadingContent** aNode)
    3762             : {
    3763           6 :   NS_ENSURE_ARG_POINTER(aNode);
    3764             : 
    3765             :   // you get null unless i say so
    3766           6 :   *aNode = nullptr;
    3767             : 
    3768             :   // find popup node
    3769          12 :   nsCOMPtr<nsIDOMNode> node;
    3770           6 :   nsresult rv = GetPopupNode(getter_AddRefs(node));
    3771           6 :   NS_ENSURE_SUCCESS(rv, rv);
    3772             : 
    3773           6 :   if (node)
    3774           0 :     CallQueryInterface(node, aNode);
    3775             : 
    3776           6 :   return NS_OK;
    3777             : }
    3778             : 
    3779             : /*
    3780             :  * XXX dr
    3781             :  * ------
    3782             :  * These two functions -- GetInLink and GetInImage -- are kind of annoying
    3783             :  * in that they only get called from the controller (in
    3784             :  * nsDOMWindowController::IsCommandEnabled). The actual construction of the
    3785             :  * context menus in communicator (nsContextMenu.js) has its own, redundant
    3786             :  * tests. No big deal, but good to keep in mind if we ever clean context
    3787             :  * menus.
    3788             :  */
    3789             : 
    3790           2 : NS_IMETHODIMP nsDocumentViewer::GetInLink(bool* aInLink)
    3791             : {
    3792             : #ifdef DEBUG_dr
    3793             :   printf("dr :: nsDocumentViewer::GetInLink\n");
    3794             : #endif
    3795             : 
    3796           2 :   NS_ENSURE_ARG_POINTER(aInLink);
    3797             : 
    3798             :   // we're not in a link unless i say so
    3799           2 :   *aInLink = false;
    3800             : 
    3801             :   // get the popup link
    3802           4 :   nsCOMPtr<nsIDOMNode> node;
    3803           2 :   nsresult rv = GetPopupLinkNode(getter_AddRefs(node));
    3804           2 :   if (NS_FAILED(rv)) return rv;
    3805           0 :   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
    3806             : 
    3807             :   // if we made it here, we're in a link
    3808           0 :   *aInLink = true;
    3809           0 :   return NS_OK;
    3810             : }
    3811             : 
    3812           6 : NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage)
    3813             : {
    3814             : #ifdef DEBUG_dr
    3815             :   printf("dr :: nsDocumentViewer::GetInImage\n");
    3816             : #endif
    3817             : 
    3818           6 :   NS_ENSURE_ARG_POINTER(aInImage);
    3819             : 
    3820             :   // we're not in an image unless i say so
    3821           6 :   *aInImage = false;
    3822             : 
    3823             :   // get the popup image
    3824          12 :   nsCOMPtr<nsIImageLoadingContent> node;
    3825           6 :   nsresult rv = GetPopupImageNode(getter_AddRefs(node));
    3826           6 :   if (NS_FAILED(rv)) return rv;
    3827           6 :   if (!node) {
    3828           6 :     return NS_ERROR_FAILURE;
    3829             :   }
    3830             : 
    3831             :   // Make sure there is a URI assigned. This allows <input type="image"> to
    3832             :   // be an image but rejects other <input> types. This matches what
    3833             :   // nsContextMenu.js does.
    3834           0 :   nsCOMPtr<nsIURI> uri;
    3835           0 :   node->GetCurrentURI(getter_AddRefs(uri));
    3836           0 :   if (uri) {
    3837             :     // if we made it here, we're in an image
    3838           0 :     *aInImage = true;
    3839             :   }
    3840             : 
    3841           0 :   return NS_OK;
    3842             : }
    3843             : 
    3844           6 : NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *, int16_t aReason)
    3845             : {
    3846           6 :   if (!mDocViewer) {
    3847           0 :     return NS_OK;
    3848             :   }
    3849             : 
    3850             :   // get the selection state
    3851          12 :   RefPtr<mozilla::dom::Selection> selection = mDocViewer->GetDocumentSelection();
    3852           6 :   if (!selection) {
    3853           0 :     return NS_ERROR_FAILURE;
    3854             :   }
    3855             : 
    3856           6 :   nsIDocument* theDoc = mDocViewer->GetDocument();
    3857           6 :   if (!theDoc) return NS_ERROR_FAILURE;
    3858             : 
    3859          12 :   nsCOMPtr<nsPIDOMWindowOuter> domWindow = theDoc->GetWindow();
    3860           6 :   if (!domWindow) return NS_ERROR_FAILURE;
    3861             : 
    3862             :   bool selectionCollapsed;
    3863           0 :   selection->GetIsCollapsed(&selectionCollapsed);
    3864             :   // We only call UpdateCommands when the selection changes from collapsed to
    3865             :   // non-collapsed or vice versa, however we skip the initializing collapse. We
    3866             :   // might need another update string for simple selection changes, but that
    3867             :   // would be expenseive.
    3868           0 :   if (mSelectionWasCollapsed != selectionCollapsed)
    3869             :   {
    3870           0 :     domWindow->UpdateCommands(NS_LITERAL_STRING("select"), selection, aReason);
    3871           0 :     mSelectionWasCollapsed = selectionCollapsed;
    3872             :   }
    3873             : 
    3874           0 :   return NS_OK;
    3875             : }
    3876             : 
    3877             : //nsDocViewerFocusListener
    3878         257 : NS_IMPL_ISUPPORTS(nsDocViewerFocusListener,
    3879             :                   nsIDOMEventListener)
    3880             : 
    3881          28 : nsDocViewerFocusListener::nsDocViewerFocusListener()
    3882          28 : :mDocViewer(nullptr)
    3883             : {
    3884          28 : }
    3885             : 
    3886           9 : nsDocViewerFocusListener::~nsDocViewerFocusListener(){}
    3887             : 
    3888             : nsresult
    3889           3 : nsDocViewerFocusListener::HandleEvent(nsIDOMEvent* aEvent)
    3890             : {
    3891           3 :   NS_ENSURE_STATE(mDocViewer);
    3892             : 
    3893           6 :   nsCOMPtr<nsIPresShell> shell;
    3894           3 :   mDocViewer->GetPresShell(getter_AddRefs(shell));
    3895           3 :   NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
    3896             : 
    3897           6 :   nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(shell);
    3898             :   int16_t selectionStatus;
    3899           3 :   selCon->GetDisplaySelection(&selectionStatus);
    3900             : 
    3901           6 :   nsAutoString eventType;
    3902           3 :   aEvent->GetType(eventType);
    3903           3 :   if (eventType.EqualsLiteral("focus")) {
    3904             :     // If selection was disabled, re-enable it.
    3905           3 :     if(selectionStatus == nsISelectionController::SELECTION_DISABLED ||
    3906           0 :        selectionStatus == nsISelectionController::SELECTION_HIDDEN) {
    3907           3 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
    3908           3 :       selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
    3909             :     }
    3910             :   } else {
    3911           0 :     MOZ_ASSERT(eventType.EqualsLiteral("blur"), "Unexpected event type");
    3912             :     // If selection was on, disable it.
    3913           0 :     if(selectionStatus == nsISelectionController::SELECTION_ON ||
    3914           0 :        selectionStatus == nsISelectionController::SELECTION_ATTENTION) {
    3915           0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
    3916           0 :       selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
    3917             :     }
    3918             :   }
    3919             : 
    3920           3 :   return NS_OK;
    3921             : }
    3922             : 
    3923             : nsresult
    3924          28 : nsDocViewerFocusListener::Init(nsDocumentViewer *aDocViewer)
    3925             : {
    3926          28 :   mDocViewer = aDocViewer;
    3927          28 :   return NS_OK;
    3928             : }
    3929             : 
    3930             : /** ---------------------------------------------------
    3931             :  *  From nsIWebBrowserPrint
    3932             :  */
    3933             : 
    3934             : #ifdef NS_PRINTING
    3935             : 
    3936             : NS_IMETHODIMP
    3937           0 : nsDocumentViewer::Print(nsIPrintSettings*       aPrintSettings,
    3938             :                           nsIWebProgressListener* aWebProgressListener)
    3939             : {
    3940           0 :   SetPrintRelated();
    3941             : 
    3942             :   // Printing XUL documents is not supported.
    3943           0 :   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
    3944           0 :   if (xulDoc) {
    3945           0 :     return NS_ERROR_FAILURE;
    3946             :   }
    3947             : 
    3948           0 :   if (!mContainer) {
    3949           0 :     PR_PL(("Container was destroyed yet we are still trying to use it!"));
    3950           0 :     return NS_ERROR_FAILURE;
    3951             :   }
    3952             : 
    3953           0 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    3954           0 :   NS_ENSURE_STATE(docShell);
    3955             : 
    3956             :   // Check to see if this document is still busy
    3957             :   // If it is busy and we aren't already "queued" up to print then
    3958             :   // Indicate there is a print pending and cache the args for later
    3959           0 :   uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
    3960           0 :   if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
    3961           0 :        (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) &&
    3962           0 :       !mPrintDocIsFullyLoaded) {
    3963           0 :     if (!mPrintIsPending) {
    3964           0 :       mCachedPrintSettings           = aPrintSettings;
    3965           0 :       mCachedPrintWebProgressListner = aWebProgressListener;
    3966           0 :       mPrintIsPending                = true;
    3967             :     }
    3968           0 :     PR_PL(("Printing Stopped - document is still busy!"));
    3969           0 :     return NS_ERROR_GFX_PRINTER_DOC_IS_BUSY;
    3970             :   }
    3971             : 
    3972           0 :   if (!mDocument || !mDeviceContext) {
    3973           0 :     PR_PL(("Can't Print without a document and a device context"));
    3974           0 :     return NS_ERROR_FAILURE;
    3975             :   }
    3976             : 
    3977             :   nsresult rv;
    3978             : 
    3979             :   // if we are printing another URL, then exit
    3980             :   // the reason we check here is because this method can be called while
    3981             :   // another is still in here (the printing dialog is a good example).
    3982             :   // the only time we can print more than one job at a time is the regression tests
    3983           0 :   if (GetIsPrinting()) {
    3984             :     // Let the user know we are not ready to print.
    3985           0 :     rv = NS_ERROR_NOT_AVAILABLE;
    3986             : 
    3987           0 :     if (mPrintEngine) {
    3988           0 :       mPrintEngine->FirePrintingErrorEvent(rv);
    3989             :     }
    3990             : 
    3991           0 :     return rv;
    3992             :   }
    3993             : 
    3994             :   // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
    3995           0 :   MOZ_ASSERT(!mAutoBeforeAndAfterPrint,
    3996             :              "We don't want to dispatch nested beforeprint/afterprint");
    3997             :   nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
    3998           0 :     new AutoPrintEventDispatcher(mDocument));
    3999           0 :   NS_ENSURE_STATE(!GetIsPrinting());
    4000             :   // If we are hosting a full-page plugin, tell it to print
    4001             :   // first. It shows its own native print UI.
    4002           0 :   nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument));
    4003           0 :   if (pDoc)
    4004           0 :     return pDoc->Print();
    4005             : 
    4006           0 :   if (!mPrintEngine) {
    4007           0 :     NS_ENSURE_STATE(mDeviceContext);
    4008           0 :     mPrintEngine = new nsPrintEngine();
    4009             : 
    4010           0 :     rv = mPrintEngine->Initialize(this, mContainer, mDocument,
    4011           0 :                                   float(mDeviceContext->AppUnitsPerCSSInch()) /
    4012           0 :                                   float(mDeviceContext->AppUnitsPerDevPixel()) /
    4013           0 :                                   mPageZoom,
    4014             : #ifdef DEBUG
    4015             :                                   mDebugFile
    4016             : #else
    4017             :                                   nullptr
    4018             : #endif
    4019           0 :                                   );
    4020           0 :     if (NS_FAILED(rv)) {
    4021           0 :       mPrintEngine->Destroy();
    4022           0 :       mPrintEngine = nullptr;
    4023           0 :       return rv;
    4024             :     }
    4025             :   }
    4026           0 :   if (mPrintEngine->HasPrintCallbackCanvas()) {
    4027             :     // Postpone the 'afterprint' event until after the mozPrintCallback
    4028             :     // callbacks have been called:
    4029           0 :     mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
    4030             :   }
    4031           0 :   dom::Element* root = mDocument->GetRootElement();
    4032           0 :   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
    4033           0 :     mPrintEngine->SetDisallowSelectionPrint(true);
    4034             :   }
    4035           0 :   rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener);
    4036           0 :   if (NS_FAILED(rv)) {
    4037           0 :     OnDonePrinting();
    4038             :   }
    4039           0 :   return rv;
    4040             : }
    4041             : 
    4042             : NS_IMETHODIMP
    4043           0 : nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
    4044             :                                mozIDOMWindowProxy* aChildDOMWin,
    4045             :                                nsIWebProgressListener* aWebProgressListener)
    4046             : {
    4047           0 :   SetPrintRelated();
    4048             : 
    4049             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
    4050           0 :   NS_WARNING_ASSERTION(
    4051             :     IsInitializedForPrintPreview(),
    4052             :     "Using docshell.printPreview is the preferred way for print previewing!");
    4053             : 
    4054           0 :   NS_ENSURE_ARG_POINTER(aChildDOMWin);
    4055           0 :   nsresult rv = NS_OK;
    4056             : 
    4057           0 :   if (GetIsPrinting()) {
    4058           0 :     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
    4059           0 :     return NS_ERROR_FAILURE;
    4060             :   }
    4061             : 
    4062             :   // Printing XUL documents is not supported.
    4063           0 :   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
    4064           0 :   if (xulDoc) {
    4065           0 :     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
    4066           0 :     return NS_ERROR_FAILURE;
    4067             :   }
    4068             : 
    4069           0 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    4070           0 :   if (!docShell || !mDeviceContext) {
    4071           0 :     PR_PL(("Can't Print Preview without device context and docshell"));
    4072           0 :     return NS_ERROR_FAILURE;
    4073             :   }
    4074             : 
    4075           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aChildDOMWin);
    4076           0 :   MOZ_ASSERT(window);
    4077           0 :   nsCOMPtr<nsIDocument> doc = window->GetDoc();
    4078           0 :   NS_ENSURE_STATE(doc);
    4079             : 
    4080             :   // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
    4081             :   // XXX Currently[1] when the user switches between portrait and landscape
    4082             :   // mode in print preview, we re-enter this function before
    4083             :   // mAutoBeforeAndAfterPrint (if set) is cleared to dispatch the 'afterprint'
    4084             :   // event.  To avoid sending multiple 'beforeprint'/'afterprint' events we
    4085             :   // must avoid creating a new AutoPrintEventDispatcher object here if we
    4086             :   // already have one saved in mAutoBeforeAndAfterPrint.
    4087             :   // [1] Until PDF.js is removed (though, maybe after that as well).
    4088           0 :   nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint;
    4089           0 :   if (!mAutoBeforeAndAfterPrint) {
    4090           0 :     autoBeforeAndAfterPrint = new AutoPrintEventDispatcher(doc);
    4091             :   }
    4092           0 :   NS_ENSURE_STATE(!GetIsPrinting());
    4093             :   // beforeprint event may have caused ContentViewer to be shutdown.
    4094           0 :   NS_ENSURE_STATE(mContainer);
    4095           0 :   NS_ENSURE_STATE(mDeviceContext);
    4096           0 :   if (!mPrintEngine) {
    4097           0 :     mPrintEngine = new nsPrintEngine();
    4098             : 
    4099           0 :     rv = mPrintEngine->Initialize(this, mContainer, doc,
    4100           0 :                                   float(mDeviceContext->AppUnitsPerCSSInch()) /
    4101           0 :                                   float(mDeviceContext->AppUnitsPerDevPixel()) /
    4102           0 :                                   mPageZoom,
    4103             : #ifdef DEBUG
    4104             :                                   mDebugFile
    4105             : #else
    4106             :                                   nullptr
    4107             : #endif
    4108           0 :                                   );
    4109           0 :     if (NS_FAILED(rv)) {
    4110           0 :       mPrintEngine->Destroy();
    4111           0 :       mPrintEngine = nullptr;
    4112           0 :       return rv;
    4113             :     }
    4114             :   }
    4115           0 :   if (autoBeforeAndAfterPrint &&
    4116           0 :       mPrintEngine->HasPrintCallbackCanvas()) {
    4117             :     // Postpone the 'afterprint' event until after the mozPrintCallback
    4118             :     // callbacks have been called:
    4119           0 :     mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
    4120             :   }
    4121           0 :   dom::Element* root = doc->GetRootElement();
    4122           0 :   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
    4123           0 :     PR_PL(("PrintPreview: found mozdisallowselectionprint"));
    4124           0 :     mPrintEngine->SetDisallowSelectionPrint(true);
    4125             :   }
    4126           0 :   rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener);
    4127           0 :   mPrintPreviewZoomed = false;
    4128           0 :   if (NS_FAILED(rv)) {
    4129           0 :     OnDonePrinting();
    4130             :   }
    4131           0 :   return rv;
    4132             : #else
    4133             :   return NS_ERROR_FAILURE;
    4134             : #endif
    4135             : }
    4136             : 
    4137             : //----------------------------------------------------------------------
    4138             : NS_IMETHODIMP
    4139           0 : nsDocumentViewer::PrintPreviewNavigate(int16_t aType, int32_t aPageNum)
    4140             : {
    4141           0 :   SetPrintRelated();
    4142             : 
    4143           0 :   if (!GetIsPrintPreview() ||
    4144           0 :       mPrintEngine->GetIsCreatingPrintPreview())
    4145           0 :     return NS_ERROR_FAILURE;
    4146             : 
    4147             :   nsIScrollableFrame* sf =
    4148           0 :     mPrintEngine->GetPrintPreviewPresShell()->GetRootScrollFrameAsScrollable();
    4149           0 :   if (!sf)
    4150           0 :     return NS_OK;
    4151             : 
    4152             :   // Check to see if we can short circut scrolling to the top
    4153           0 :   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME ||
    4154           0 :       (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) {
    4155           0 :     sf->ScrollTo(nsPoint(0, 0), nsIScrollableFrame::INSTANT);
    4156           0 :     return NS_OK;
    4157             :   }
    4158             : 
    4159             :   // Finds the SimplePageSequencer frame
    4160             :   // in PP mPrtPreview->mPrintObject->mSeqFrame is null
    4161           0 :   nsIFrame* seqFrame  = nullptr;
    4162           0 :   int32_t   pageCount = 0;
    4163           0 :   if (NS_FAILED(mPrintEngine->GetSeqFrameAndCountPages(seqFrame, pageCount))) {
    4164           0 :     return NS_ERROR_FAILURE;
    4165             :   }
    4166             : 
    4167             :   // Figure where we are currently scrolled to
    4168           0 :   nsPoint pt = sf->GetScrollPosition();
    4169             : 
    4170           0 :   int32_t    pageNum = 1;
    4171           0 :   nsIFrame * fndPageFrame  = nullptr;
    4172           0 :   nsIFrame * currentPage   = nullptr;
    4173             : 
    4174             :   // If it is "End" then just do a "goto" to the last page
    4175           0 :   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) {
    4176           0 :     aType    = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM;
    4177           0 :     aPageNum = pageCount;
    4178             :   }
    4179             : 
    4180             :   // Now, locate the current page we are on and
    4181             :   // and the page of the page number
    4182           0 :   for (nsIFrame* pageFrame : seqFrame->PrincipalChildList()) {
    4183           0 :     nsRect pageRect = pageFrame->GetRect();
    4184           0 :     if (pageRect.Contains(pageRect.x, pt.y)) {
    4185           0 :       currentPage = pageFrame;
    4186             :     }
    4187           0 :     if (pageNum == aPageNum) {
    4188           0 :       fndPageFrame = pageFrame;
    4189           0 :       break;
    4190             :     }
    4191           0 :     pageNum++;
    4192             :   }
    4193             : 
    4194           0 :   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) {
    4195           0 :     if (currentPage) {
    4196           0 :       fndPageFrame = currentPage->GetPrevInFlow();
    4197           0 :       if (!fndPageFrame) {
    4198           0 :         return NS_OK;
    4199             :       }
    4200             :     } else {
    4201           0 :       return NS_OK;
    4202             :     }
    4203           0 :   } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) {
    4204           0 :     if (currentPage) {
    4205           0 :       fndPageFrame = currentPage->GetNextInFlow();
    4206           0 :       if (!fndPageFrame) {
    4207           0 :         return NS_OK;
    4208             :       }
    4209             :     } else {
    4210           0 :       return NS_OK;
    4211             :     }
    4212             :   } else { // If we get here we are doing "GoTo"
    4213           0 :     if (aPageNum < 0 || aPageNum > pageCount) {
    4214           0 :       return NS_OK;
    4215             :     }
    4216             :   }
    4217             : 
    4218           0 :   if (fndPageFrame) {
    4219             :     nscoord newYPosn =
    4220           0 :       nscoord(mPrintEngine->GetPrintPreviewScale() * fndPageFrame->GetPosition().y);
    4221           0 :     sf->ScrollTo(nsPoint(pt.x, newYPosn), nsIScrollableFrame::INSTANT);
    4222             :   }
    4223           0 :   return NS_OK;
    4224             : 
    4225             : }
    4226             : 
    4227             : NS_IMETHODIMP
    4228           0 : nsDocumentViewer::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings)
    4229             : {
    4230           0 :   return nsPrintEngine::GetGlobalPrintSettings(aGlobalPrintSettings);
    4231             : }
    4232             : 
    4233             : // XXX This always returns false for subdocuments
    4234             : NS_IMETHODIMP
    4235           0 : nsDocumentViewer::GetDoingPrint(bool *aDoingPrint)
    4236             : {
    4237           0 :   NS_ENSURE_ARG_POINTER(aDoingPrint);
    4238             : 
    4239           0 :   *aDoingPrint = false;
    4240           0 :   if (mPrintEngine) {
    4241             :     // XXX shouldn't this be GetDoingPrint() ?
    4242           0 :     return mPrintEngine->GetDoingPrintPreview(aDoingPrint);
    4243             :   }
    4244           0 :   return NS_OK;
    4245             : }
    4246             : 
    4247             : // XXX This always returns false for subdocuments
    4248             : NS_IMETHODIMP
    4249           0 : nsDocumentViewer::GetDoingPrintPreview(bool *aDoingPrintPreview)
    4250             : {
    4251           0 :   NS_ENSURE_ARG_POINTER(aDoingPrintPreview);
    4252             : 
    4253           0 :   *aDoingPrintPreview = false;
    4254           0 :   if (mPrintEngine) {
    4255           0 :     return mPrintEngine->GetDoingPrintPreview(aDoingPrintPreview);
    4256             :   }
    4257           0 :   return NS_OK;
    4258             : }
    4259             : 
    4260             : NS_IMETHODIMP
    4261           0 : nsDocumentViewer::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings)
    4262             : {
    4263           0 :   NS_ENSURE_ARG_POINTER(aCurrentPrintSettings);
    4264             : 
    4265           0 :   *aCurrentPrintSettings = nullptr;
    4266           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4267             : 
    4268           0 :   return mPrintEngine->GetCurrentPrintSettings(aCurrentPrintSettings);
    4269             : }
    4270             : 
    4271             : 
    4272             : NS_IMETHODIMP
    4273           0 : nsDocumentViewer::GetCurrentChildDOMWindow(mozIDOMWindowProxy** aCurrentChildDOMWindow)
    4274             : {
    4275           0 :   NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow);
    4276           0 :   *aCurrentChildDOMWindow = nullptr;
    4277           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4278             : }
    4279             : 
    4280             : NS_IMETHODIMP
    4281           0 : nsDocumentViewer::Cancel()
    4282             : {
    4283           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4284           0 :   return mPrintEngine->Cancelled();
    4285             : }
    4286             : 
    4287             : NS_IMETHODIMP
    4288           0 : nsDocumentViewer::ExitPrintPreview()
    4289             : {
    4290           0 :   if (GetIsPrinting())
    4291           0 :     return NS_ERROR_FAILURE;
    4292           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4293             : 
    4294           0 :   if (GetIsPrintPreview()) {
    4295           0 :     ReturnToGalleyPresentation();
    4296             :   }
    4297           0 :   return NS_OK;
    4298             : }
    4299             : 
    4300             : //----------------------------------------------------------------------------------
    4301             : // Enumerate all the documents for their titles
    4302             : NS_IMETHODIMP
    4303           0 : nsDocumentViewer::EnumerateDocumentNames(uint32_t* aCount,
    4304             :                                            char16_t*** aResult)
    4305             : {
    4306             : #ifdef NS_PRINTING
    4307           0 :   NS_ENSURE_ARG(aCount);
    4308           0 :   NS_ENSURE_ARG_POINTER(aResult);
    4309           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4310             : 
    4311           0 :   return mPrintEngine->EnumerateDocumentNames(aCount, aResult);
    4312             : #else
    4313             :   return NS_ERROR_FAILURE;
    4314             : #endif
    4315             : }
    4316             : 
    4317             : NS_IMETHODIMP
    4318           0 : nsDocumentViewer::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected)
    4319             : {
    4320             : #ifdef NS_PRINTING
    4321           0 :   *aIsFramesetFrameSelected = false;
    4322           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4323             : 
    4324           0 :   return mPrintEngine->GetIsFramesetFrameSelected(aIsFramesetFrameSelected);
    4325             : #else
    4326             :   return NS_ERROR_FAILURE;
    4327             : #endif
    4328             : }
    4329             : 
    4330             : NS_IMETHODIMP
    4331           0 : nsDocumentViewer::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
    4332             : {
    4333             : #ifdef NS_PRINTING
    4334           0 :   NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
    4335           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4336             : 
    4337           0 :   return mPrintEngine->GetPrintPreviewNumPages(aPrintPreviewNumPages);
    4338             : #else
    4339             :   return NS_ERROR_FAILURE;
    4340             : #endif
    4341             : }
    4342             : 
    4343             : NS_IMETHODIMP
    4344           0 : nsDocumentViewer::GetIsFramesetDocument(bool *aIsFramesetDocument)
    4345             : {
    4346             : #ifdef NS_PRINTING
    4347           0 :   *aIsFramesetDocument = false;
    4348           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4349             : 
    4350           0 :   return mPrintEngine->GetIsFramesetDocument(aIsFramesetDocument);
    4351             : #else
    4352             :   return NS_ERROR_FAILURE;
    4353             : #endif
    4354             : }
    4355             : 
    4356             : NS_IMETHODIMP
    4357           0 : nsDocumentViewer::GetIsIFrameSelected(bool *aIsIFrameSelected)
    4358             : {
    4359             : #ifdef NS_PRINTING
    4360           0 :   *aIsIFrameSelected = false;
    4361           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4362             : 
    4363           0 :   return mPrintEngine->GetIsIFrameSelected(aIsIFrameSelected);
    4364             : #else
    4365             :   return NS_ERROR_FAILURE;
    4366             : #endif
    4367             : }
    4368             : 
    4369             : NS_IMETHODIMP
    4370           0 : nsDocumentViewer::GetIsRangeSelection(bool *aIsRangeSelection)
    4371             : {
    4372             : #ifdef NS_PRINTING
    4373           0 :   *aIsRangeSelection = false;
    4374           0 :   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
    4375             : 
    4376           0 :   return mPrintEngine->GetIsRangeSelection(aIsRangeSelection);
    4377             : #else
    4378             :   return NS_ERROR_FAILURE;
    4379             : #endif
    4380             : }
    4381             : 
    4382             : //----------------------------------------------------------------------------------
    4383             : // Printing/Print Preview Helpers
    4384             : //----------------------------------------------------------------------------------
    4385             : 
    4386             : //----------------------------------------------------------------------------------
    4387             : // Walks the document tree and tells each DocShell whether Printing/PP is happening
    4388             : void
    4389           0 : nsDocumentViewer::SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
    4390             :                                                 bool                 aIsPrintingOrPP,
    4391             :                                                 bool                 aStartAtTop)
    4392             : {
    4393           0 :   nsCOMPtr<nsIDocShellTreeItem> parentItem(do_QueryInterface(aParentNode));
    4394             : 
    4395             :   // find top of "same parent" tree
    4396           0 :   if (aStartAtTop) {
    4397           0 :     if (aIsPrintingOrPP) {
    4398           0 :       while (parentItem) {
    4399           0 :         nsCOMPtr<nsIDocShellTreeItem> parent;
    4400           0 :         parentItem->GetSameTypeParent(getter_AddRefs(parent));
    4401           0 :         if (!parent) {
    4402           0 :           break;
    4403             :         }
    4404           0 :         parentItem = do_QueryInterface(parent);
    4405             :       }
    4406           0 :       mTopContainerWhilePrinting = do_GetWeakReference(parentItem);
    4407             :     } else {
    4408           0 :       parentItem = do_QueryReferent(mTopContainerWhilePrinting);
    4409             :     }
    4410             :   }
    4411             : 
    4412             :   // Check to see if the DocShell's ContentViewer is printing/PP
    4413           0 :   nsCOMPtr<nsIContentViewerContainer> viewerContainer(do_QueryInterface(parentItem));
    4414           0 :   if (viewerContainer) {
    4415           0 :     viewerContainer->SetIsPrinting(aIsPrintingOrPP);
    4416             :   }
    4417             : 
    4418           0 :   if (!aParentNode) {
    4419           0 :     return;
    4420             :   }
    4421             : 
    4422             :   // Traverse children to see if any of them are printing.
    4423             :   int32_t n;
    4424           0 :   aParentNode->GetChildCount(&n);
    4425           0 :   for (int32_t i=0; i < n; i++) {
    4426           0 :     nsCOMPtr<nsIDocShellTreeItem> child;
    4427           0 :     aParentNode->GetChildAt(i, getter_AddRefs(child));
    4428           0 :     NS_ASSERTION(child, "child isn't nsIDocShell");
    4429           0 :     if (child) {
    4430           0 :       SetIsPrintingInDocShellTree(child, aIsPrintingOrPP, false);
    4431             :     }
    4432             :   }
    4433             : 
    4434             : }
    4435             : #endif // NS_PRINTING
    4436             : 
    4437             : bool
    4438          28 : nsDocumentViewer::ShouldAttachToTopLevel()
    4439             : {
    4440          28 :   if (!mParentWidget)
    4441          22 :     return false;
    4442             : 
    4443          12 :   nsCOMPtr<nsIDocShellTreeItem> containerItem(mContainer);
    4444           6 :   if (!containerItem)
    4445           0 :     return false;
    4446             : 
    4447             :   // We always attach when using puppet widgets
    4448           6 :   if (nsIWidget::UsePuppetWidgets())
    4449           2 :     return true;
    4450             : 
    4451             : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
    4452             :   // On windows, in the parent process we also attach, but just to
    4453             :   // chrome items
    4454           4 :   nsWindowType winType = mParentWidget->WindowType();
    4455           6 :   if ((winType == eWindowType_toplevel ||
    4456           2 :        winType == eWindowType_dialog ||
    4457           8 :        winType == eWindowType_invisible) &&
    4458           4 :       containerItem->ItemType() == nsIDocShellTreeItem::typeChrome) {
    4459           4 :     return true;
    4460             :   }
    4461             : #endif
    4462             : 
    4463           0 :   return false;
    4464             : }
    4465             : 
    4466             : //------------------------------------------------------------
    4467             : // XXX this always returns false for subdocuments
    4468             : bool
    4469           0 : nsDocumentViewer::GetIsPrinting()
    4470             : {
    4471             : #ifdef NS_PRINTING
    4472           0 :   if (mPrintEngine) {
    4473           0 :     return mPrintEngine->GetIsPrinting();
    4474             :   }
    4475             : #endif
    4476           0 :   return false;
    4477             : }
    4478             : 
    4479             : //------------------------------------------------------------
    4480             : // Notification from the PrintEngine of the current Printing status
    4481             : void
    4482           0 : nsDocumentViewer::SetIsPrinting(bool aIsPrinting)
    4483             : {
    4484             : #ifdef NS_PRINTING
    4485           0 :   if (aIsPrinting) {
    4486           0 :     SetPrintRelated();
    4487             :   }
    4488             :   // Set all the docShells in the docshell tree to be printing.
    4489             :   // that way if anyone of them tries to "navigate" it can't
    4490           0 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    4491           0 :   if (docShell || !aIsPrinting) {
    4492           0 :     SetIsPrintingInDocShellTree(docShell, aIsPrinting, true);
    4493             :   } else {
    4494           0 :     NS_WARNING("Did you close a window before printing?");
    4495             :   }
    4496             : 
    4497           0 :   if (!aIsPrinting) {
    4498             :     // Dispatch the 'afterprint' event now, if pending:
    4499           0 :     mAutoBeforeAndAfterPrint = nullptr;
    4500             :   }
    4501             : #endif
    4502           0 : }
    4503             : 
    4504             : //------------------------------------------------------------
    4505             : // The PrintEngine holds the current value
    4506             : // this called from inside the DocViewer.
    4507             : // XXX it always returns false for subdocuments
    4508             : bool
    4509         108 : nsDocumentViewer::GetIsPrintPreview()
    4510             : {
    4511             : #ifdef NS_PRINTING
    4512         108 :   if (mPrintEngine) {
    4513           0 :     return mPrintEngine->GetIsPrintPreview();
    4514             :   }
    4515             : #endif
    4516         108 :   return false;
    4517             : }
    4518             : 
    4519             : //------------------------------------------------------------
    4520             : // Notification from the PrintEngine of the current PP status
    4521             : void
    4522           0 : nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview)
    4523             : {
    4524             : #ifdef NS_PRINTING
    4525           0 :   if (aIsPrintPreview) {
    4526           0 :     SetPrintRelated();
    4527             :   }
    4528             :   // Set all the docShells in the docshell tree to be printing.
    4529             :   // that way if anyone of them tries to "navigate" it can't
    4530           0 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    4531           0 :   if (docShell || !aIsPrintPreview) {
    4532           0 :     SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
    4533             :   }
    4534           0 :   if (!aIsPrintPreview) {
    4535             :     // Dispatch the 'afterprint' event now, if pending:
    4536           0 :     mAutoBeforeAndAfterPrint = nullptr;
    4537             :   }
    4538             : #endif
    4539             : 
    4540             :   // Protect against pres shell destruction running scripts.
    4541           0 :   nsAutoScriptBlocker scriptBlocker;
    4542             : 
    4543           0 :   if (!aIsPrintPreview) {
    4544           0 :     if (mPresShell) {
    4545           0 :       DestroyPresShell();
    4546             :     }
    4547           0 :     mWindow = nullptr;
    4548           0 :     mViewManager = nullptr;
    4549           0 :     mPresContext = nullptr;
    4550           0 :     mPresShell = nullptr;
    4551             :   }
    4552           0 : }
    4553             : 
    4554             : //----------------------------------------------------------------------------------
    4555             : // nsIDocumentViewerPrint IFace
    4556             : //----------------------------------------------------------------------------------
    4557             : 
    4558             : //------------------------------------------------------------
    4559             : void
    4560           0 : nsDocumentViewer::IncrementDestroyRefCount()
    4561             : {
    4562           0 :   SetPrintRelated();
    4563           0 :   ++mDestroyRefCount;
    4564           0 : }
    4565             : 
    4566             : //------------------------------------------------------------
    4567             : 
    4568             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
    4569             : //------------------------------------------------------------
    4570             : // Reset ESM focus for all descendent doc shells.
    4571             : static void
    4572           0 : ResetFocusState(nsIDocShell* aDocShell)
    4573             : {
    4574           0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    4575           0 :   if (!fm)
    4576           0 :     return;
    4577             : 
    4578           0 :   nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
    4579           0 :   aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
    4580             :                                    nsIDocShell::ENUMERATE_FORWARDS,
    4581           0 :                                    getter_AddRefs(docShellEnumerator));
    4582             : 
    4583           0 :   nsCOMPtr<nsISupports> currentContainer;
    4584             :   bool hasMoreDocShells;
    4585           0 :   while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells))
    4586           0 :          && hasMoreDocShells) {
    4587           0 :     docShellEnumerator->GetNext(getter_AddRefs(currentContainer));
    4588           0 :     nsCOMPtr<nsPIDOMWindowOuter> win = do_GetInterface(currentContainer);
    4589           0 :     if (win)
    4590           0 :       fm->ClearFocus(win);
    4591             :   }
    4592             : }
    4593             : #endif // NS_PRINTING && NS_PRINT_PREVIEW
    4594             : 
    4595             : void
    4596           0 : nsDocumentViewer::ReturnToGalleyPresentation()
    4597             : {
    4598             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
    4599           0 :   SetPrintRelated();
    4600             : 
    4601           0 :   if (!GetIsPrintPreview()) {
    4602           0 :     NS_ERROR("Wow, we should never get here!");
    4603           0 :     return;
    4604             :   }
    4605             : 
    4606           0 :   SetIsPrintPreview(false);
    4607             : 
    4608           0 :   mPrintEngine->TurnScriptingOn(true);
    4609           0 :   mPrintEngine->Destroy();
    4610           0 :   mPrintEngine = nullptr;
    4611             : 
    4612           0 :   nsCOMPtr<nsIDocShell> docShell(mContainer);
    4613           0 :   ResetFocusState(docShell);
    4614             : 
    4615           0 :   SetTextZoom(mTextZoom);
    4616           0 :   SetFullZoom(mPageZoom);
    4617           0 :   SetOverrideDPPX(mOverrideDPPX);
    4618           0 :   SetMinFontSize(mMinFontSize);
    4619           0 :   Show();
    4620             : 
    4621             : #endif // NS_PRINTING && NS_PRINT_PREVIEW
    4622             : }
    4623             : 
    4624             : //------------------------------------------------------------
    4625             : // This called ONLY when printing has completed and the DV
    4626             : // is being notified that it should get rid of the PrintEngine.
    4627             : //
    4628             : // BUT, if we are in Print Preview then we want to ignore the
    4629             : // notification (we do not get rid of the PrintEngine)
    4630             : //
    4631             : // One small caveat:
    4632             : //   This IS called from two places in this module for cleaning
    4633             : //   up when an error occurred during the start up printing
    4634             : //   and print preview
    4635             : //
    4636             : void
    4637           0 : nsDocumentViewer::OnDonePrinting()
    4638             : {
    4639             : #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
    4640           0 :   SetPrintRelated();
    4641           0 :   if (mPrintEngine) {
    4642           0 :     RefPtr<nsPrintEngine> pe = mPrintEngine;
    4643           0 :     if (GetIsPrintPreview()) {
    4644           0 :       pe->DestroyPrintingData();
    4645             :     } else {
    4646           0 :       mPrintEngine = nullptr;
    4647           0 :       pe->Destroy();
    4648             :     }
    4649             : 
    4650             :     // We are done printing, now cleanup
    4651           0 :     if (mDeferredWindowClose) {
    4652           0 :       mDeferredWindowClose = false;
    4653           0 :       if (mContainer) {
    4654           0 :         if (nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(mContainer->GetWindow())) {
    4655           0 :           win->Close();
    4656             :         }
    4657             :       }
    4658           0 :     } else if (mClosingWhilePrinting) {
    4659           0 :       if (mDocument) {
    4660           0 :         mDocument->Destroy();
    4661           0 :         mDocument = nullptr;
    4662             :       }
    4663           0 :       mClosingWhilePrinting = false;
    4664             :     }
    4665             :   }
    4666             : #endif // NS_PRINTING && NS_PRINT_PREVIEW
    4667           0 : }
    4668             : 
    4669           0 : NS_IMETHODIMP nsDocumentViewer::SetPageMode(bool aPageMode, nsIPrintSettings* aPrintSettings)
    4670             : {
    4671           0 :   if (aPageMode) {
    4672           0 :     SetPrintRelated();
    4673             :   }
    4674             : 
    4675             :   // XXX Page mode is only partially working; it's currently used for
    4676             :   // reftests that require a paginated context
    4677           0 :   mIsPageMode = aPageMode;
    4678             : 
    4679             :   // The DestroyPresShell call requires a script blocker, since the
    4680             :   // PresShell::Destroy call it does can cause scripts to run, which could
    4681             :   // re-entrantly call methods on the nsDocumentViewer.
    4682           0 :   nsAutoScriptBlocker scriptBlocker;
    4683             : 
    4684           0 :   if (mPresShell) {
    4685           0 :     DestroyPresShell();
    4686             :   }
    4687             : 
    4688           0 :   if (mPresContext) {
    4689           0 :     DestroyPresContext();
    4690             :   }
    4691             : 
    4692           0 :   mViewManager  = nullptr;
    4693           0 :   mWindow       = nullptr;
    4694             : 
    4695           0 :   NS_ENSURE_STATE(mDocument);
    4696           0 :   if (aPageMode)
    4697             :   {
    4698             :     mPresContext = CreatePresContext(mDocument,
    4699           0 :         nsPresContext::eContext_PageLayout, FindContainerView());
    4700           0 :     NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
    4701           0 :     mPresContext->SetPaginatedScrolling(true);
    4702           0 :     mPresContext->SetPrintSettings(aPrintSettings);
    4703           0 :     nsresult rv = mPresContext->Init(mDeviceContext);
    4704           0 :     NS_ENSURE_SUCCESS(rv, rv);
    4705             :   }
    4706           0 :   NS_ENSURE_SUCCESS(InitInternal(mParentWidget, nullptr, mBounds, true, false),
    4707             :                     NS_ERROR_FAILURE);
    4708             : 
    4709           0 :   Show();
    4710           0 :   return NS_OK;
    4711             : }
    4712             : 
    4713             : NS_IMETHODIMP
    4714           0 : nsDocumentViewer::GetHistoryEntry(nsISHEntry **aHistoryEntry)
    4715             : {
    4716           0 :   NS_IF_ADDREF(*aHistoryEntry = mSHEntry);
    4717           0 :   return NS_OK;
    4718             : }
    4719             : 
    4720             : NS_IMETHODIMP
    4721           0 : nsDocumentViewer::GetIsTabModalPromptAllowed(bool *aAllowed)
    4722             : {
    4723           0 :   *aAllowed = !mHidden;
    4724           0 :   return NS_OK;
    4725             : }
    4726             : 
    4727             : NS_IMETHODIMP
    4728           5 : nsDocumentViewer::GetIsHidden(bool *aHidden)
    4729             : {
    4730           5 :   *aHidden = mHidden;
    4731           5 :   return NS_OK;
    4732             : }
    4733             : 
    4734             : NS_IMETHODIMP
    4735           0 : nsDocumentViewer::SetIsHidden(bool aHidden)
    4736             : {
    4737           0 :   mHidden = aHidden;
    4738           0 :   return NS_OK;
    4739             : }
    4740             : 
    4741             : void
    4742           4 : nsDocumentViewer::DestroyPresShell()
    4743             : {
    4744             :   // We assert this because destroying the pres shell could otherwise cause
    4745             :   // re-entrancy into nsDocumentViewer methods, and all callers of
    4746             :   // DestroyPresShell need to do other cleanup work afterwards before it
    4747             :   // is safe for those re-entrant method calls to be made.
    4748           4 :   MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
    4749             :              "DestroyPresShell must only be called when scripts are blocked");
    4750             : 
    4751             :   nsIFrame* vmRootFrame =
    4752           8 :     mViewManager && mViewManager->GetRootView()
    4753           8 :       ? mViewManager->GetRootView()->GetFrame()
    4754           4 :       : nullptr;
    4755           4 :   nsIFrame* psRootFrame = mPresShell ? mPresShell->GetRootFrame() : nullptr;
    4756           4 :   MOZ_RELEASE_ASSERT(vmRootFrame == psRootFrame);
    4757             : 
    4758             :   // Break circular reference (or something)
    4759           4 :   mPresShell->EndObservingDocument();
    4760             : 
    4761           8 :   RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
    4762           4 :   if (selection && mSelectionListener)
    4763           4 :     selection->RemoveSelectionListener(mSelectionListener);
    4764             : 
    4765           4 :   bool hadRootFrame = !!mPresShell->GetRootFrame();
    4766           4 :   mPresShell->Destroy();
    4767           4 :   mPresShellDestroyed = true;
    4768           4 :   MOZ_RELEASE_ASSERT(!mPresShell->GetRootFrame());
    4769             :   // destroying the frame tree via presshell destroy should have done this
    4770           4 :   if (hadRootFrame) {
    4771           0 :     MOZ_RELEASE_ASSERT(!mViewManager || !mViewManager->GetRootView());
    4772             :   }
    4773           4 :   MOZ_RELEASE_ASSERT(!mViewManager || !mViewManager->GetRootView() ||
    4774             :     (!mViewManager->GetRootView()->GetFrame() &&
    4775             :      !mViewManager->GetRootView()->GetFirstChild()));
    4776             : 
    4777           4 :   mPresShell = nullptr;
    4778           4 : }
    4779             : 
    4780             : void
    4781           4 : nsDocumentViewer::DestroyPresContext()
    4782             : {
    4783           4 :   mPresContext->Detach();
    4784           4 :   mPresContext = nullptr;
    4785           4 : }
    4786             : 
    4787             : bool
    4788           0 : nsDocumentViewer::IsInitializedForPrintPreview()
    4789             : {
    4790           0 :   return mInitializedForPrintPreview;
    4791             : }
    4792             : 
    4793             : void
    4794           0 : nsDocumentViewer::InitializeForPrintPreview()
    4795             : {
    4796           0 :   SetPrintRelated();
    4797           0 :   mInitializedForPrintPreview = true;
    4798           0 : }
    4799             : 
    4800             : void
    4801           0 : nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager,
    4802             :                                               nsPresContext* aPresContext,
    4803             :                                               nsIPresShell* aPresShell)
    4804             : {
    4805             :   // Protect against pres shell destruction running scripts and re-entrantly
    4806             :   // creating a new presentation.
    4807           0 :   nsAutoScriptBlocker scriptBlocker;
    4808             : 
    4809           0 :   if (mPresShell) {
    4810           0 :     DestroyPresShell();
    4811             :   }
    4812             : 
    4813           0 :   mWindow = nullptr;
    4814           0 :   mViewManager = aViewManager;
    4815           0 :   mPresContext = aPresContext;
    4816           0 :   mPresShell = aPresShell;
    4817             : 
    4818           0 :   if (ShouldAttachToTopLevel()) {
    4819           0 :     DetachFromTopLevelWidget();
    4820           0 :     nsView* rootView = mViewManager->GetRootView();
    4821           0 :     rootView->AttachToTopLevelWidget(mParentWidget);
    4822           0 :     mAttachedToParent = true;
    4823             :   }
    4824           0 : }
    4825             : 
    4826             : // Fires the "document-shown" event so that interested parties are aware of it.
    4827             : NS_IMETHODIMP
    4828           5 : nsDocumentShownDispatcher::Run()
    4829             : {
    4830             :   nsCOMPtr<nsIObserverService> observerService =
    4831          10 :     mozilla::services::GetObserverService();
    4832           5 :   if (observerService) {
    4833           5 :     observerService->NotifyObservers(mDocument, "document-shown", nullptr);
    4834             :   }
    4835          10 :   return NS_OK;
    4836             : }

Generated by: LCOV version 1.13