LCOV - code coverage report
Current view: directory - layout/base - nsDocumentViewer.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1774 2 0.1 %
Date: 2012-06-02 Functions: 180 2 1.1 %

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

Generated by: LCOV version 1.7