Back to index

lightning-sunbird  0.9+nobinonly
nsDocumentViewer.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim: set ts=2 sw=2 et tw=80: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Dan Rosen <dr@netscape.com>
00025  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nscore.h"
00042 #include "nsCOMPtr.h"
00043 #include "nsCRT.h"
00044 #include "nsString.h"
00045 #include "nsReadableUtils.h"
00046 #include "nsISupports.h"
00047 #include "nsIContent.h"
00048 #include "nsIContentViewerContainer.h"
00049 #include "nsIDocumentViewer.h"
00050 #include "nsIDOMWindowInternal.h"
00051 #include "nsIDocumentViewerPrint.h"
00052 
00053 #include "nsIDocument.h"
00054 #include "nsPresContext.h"
00055 #include "nsIPresShell.h"
00056 #include "nsIEventStateManager.h"
00057 #include "nsStyleSet.h"
00058 #include "nsIStyleSheet.h"
00059 #include "nsICSSStyleSheet.h"
00060 #include "nsIFrame.h"
00061 
00062 #include "nsIScriptGlobalObject.h"
00063 #include "nsILinkHandler.h"
00064 #include "nsIDOMDocument.h"
00065 #include "nsISelectionListener.h"
00066 #include "nsISelectionPrivate.h"
00067 #include "nsIDOMHTMLDocument.h"
00068 #include "nsIDOMNSHTMLDocument.h"
00069 #include "nsIDOMHTMLCollection.h"
00070 #include "nsIDOMHTMLElement.h"
00071 #include "nsIDOMRange.h"
00072 #include "nsContentCID.h"
00073 #include "nsLayoutCID.h"
00074 #include "nsContentUtils.h"
00075 #include "nsLayoutStylesheetCache.h"
00076 
00077 #include "nsViewsCID.h"
00078 #include "nsWidgetsCID.h"
00079 #include "nsIDeviceContext.h"
00080 #include "nsIDeviceContextSpec.h"
00081 #include "nsIDeviceContextSpecFactory.h"
00082 #include "nsIViewManager.h"
00083 #include "nsIView.h"
00084 #include "nsView.h" // For nsView::GetViewFor
00085 
00086 #include "nsIPageSequenceFrame.h"
00087 #include "nsIURL.h"
00088 #include "nsNetUtil.h"
00089 #include "nsIChromeEventHandler.h"
00090 #include "nsIContentViewerEdit.h"
00091 #include "nsIContentViewerFile.h"
00092 #include "nsICSSLoader.h"
00093 #include "nsIMarkupDocumentViewer.h"
00094 #include "nsIInterfaceRequestor.h"
00095 #include "nsIInterfaceRequestorUtils.h"
00096 #include "nsIDocShellTreeItem.h"
00097 #include "nsIDocShellTreeNode.h"
00098 #include "nsIDocShellTreeOwner.h"
00099 #include "nsIDocShell.h"
00100 #include "nsIBaseWindow.h"
00101 #include "nsIFrameDebug.h"
00102 #include "nsILayoutHistoryState.h"
00103 #include "nsLayoutAtoms.h"
00104 #include "nsIParser.h"
00105 #include "nsGUIEvent.h"
00106 #include "nsHTMLReflowState.h"
00107 #include "nsIDOMHTMLAnchorElement.h"
00108 #include "nsIDOMHTMLAreaElement.h"
00109 #include "nsIDOMHTMLLinkElement.h"
00110 #include "nsIImageLoadingContent.h"
00111 #include "nsCopySupport.h"
00112 #include "nsIDOMHTMLFrameSetElement.h"
00113 #ifdef MOZ_XUL
00114 #include "nsIXULDocument.h"
00115 #endif
00116 #include "nsPrintfCString.h"
00117 
00118 #include "nsIClipboardHelper.h"
00119 
00120 #include "nsIEventQueueService.h"
00121 #include "nsIEventQueue.h"
00122 
00123 #include "nsPIDOMWindow.h"
00124 #include "nsIFocusController.h"
00125 #include "nsIMenuParent.h"
00126 
00127 #include "nsIScrollableView.h"
00128 #include "nsIHTMLDocument.h"
00129 #include "nsITimelineService.h"
00130 #include "nsGfxCIID.h"
00131 #include "nsStyleSheetService.h"
00132 
00133 // Printing
00134 #include "nsIWebBrowserPrint.h"
00135 
00136 #include "imgIContainer.h" // image animation mode constants
00137 
00138 #include "nsIPrompt.h"
00139 #include "nsIWindowWatcher.h"
00140 
00141 //--------------------------
00142 // Printing Include
00143 //---------------------------
00144 #ifdef NS_PRINTING
00145 
00146 #include "nsPrintEngine.h"
00147 
00148 // Print Options
00149 #include "nsIPrintSettings.h"
00150 #include "nsIPrintSettingsService.h"
00151 #include "nsIPrintOptions.h"
00152 #include "nsIServiceManager.h"
00153 #include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms
00154 #include "nsISimpleEnumerator.h"
00155 #include "nsXPCOM.h"
00156 #include "nsISupportsPrimitives.h"
00157 
00158 // PrintOptions is now implemented by PrintSettingsService
00159 static const char sPrintOptionsContractID[]         = "@mozilla.org/gfx/printsettings-service;1";
00160 
00161 // Printing Events
00162 #include "nsIEventQueue.h"
00163 #include "nsIEventQueueService.h"
00164 #include "nsPrintPreviewListener.h"
00165 
00166 #include "nsIDOMHTMLFrameElement.h"
00167 #include "nsIDOMHTMLIFrameElement.h"
00168 #include "nsIDOMHTMLObjectElement.h"
00169 #include "nsIPluginDocument.h"
00170 
00171 // Print Progress
00172 #include "nsIPrintProgress.h"
00173 #include "nsIPrintProgressParams.h"
00174 
00175 // Printing 
00176 #include "nsPrintEngine.h"
00177 #include "nsPagePrintTimer.h"
00178 
00179 #endif // NS_PRINTING
00180 
00181 // FrameSet
00182 #include "nsINodeInfo.h"
00183 #include "nsIDocument.h"
00184 #include "nsHTMLAtoms.h"
00185 
00186 //focus
00187 #include "nsIDOMEventReceiver.h"
00188 #include "nsIDOMFocusListener.h"
00189 #include "nsISelectionController.h"
00190 
00191 #include "nsBidiUtils.h"
00192 #include "nsISHEntry.h"
00193 #include "nsISHistory.h"
00194 #include "nsISHistoryInternal.h"
00195 #include "nsIWebNavigation.h"
00196 #include "nsWeakPtr.h"
00197 
00198 //paint forcing
00199 #include "prenv.h"
00200 #include <stdio.h>
00201 
00202 #ifdef NS_DEBUG
00203 
00204 #undef NOISY_VIEWER
00205 #else
00206 #undef NOISY_VIEWER
00207 #endif
00208 
00209 //-----------------------------------------------------
00210 // PR LOGGING
00211 #ifdef MOZ_LOGGING
00212 #define FORCE_PR_LOG /* Allow logging in the release build */
00213 #endif
00214 
00215 #include "prlog.h"
00216 
00217 #ifdef PR_LOGGING
00218 
00219 static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing");
00220 #define PR_PL(_p1)  PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
00221 
00222 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
00223 #else
00224 #define PRT_YESNO(_p)
00225 #define PR_PL(_p1)
00226 #endif
00227 //-----------------------------------------------------
00228 
00229 class DocumentViewerImpl;
00230 
00231 // a small delegate class used to avoid circular references
00232 
00233 #ifdef XP_MAC
00234 #pragma mark ** nsDocViewerSelectionListener **
00235 #endif
00236 
00237 class nsDocViewerSelectionListener : public nsISelectionListener
00238 {
00239 public:
00240 
00241   // nsISupports interface...
00242   NS_DECL_ISUPPORTS
00243 
00244   // nsISelectionListerner interface
00245   NS_DECL_NSISELECTIONLISTENER
00246 
00247                        nsDocViewerSelectionListener()
00248                        : mDocViewer(NULL)
00249                        , mGotSelectionState(PR_FALSE)
00250                        , mSelectionWasCollapsed(PR_FALSE)
00251                        {
00252                        }
00253 
00254   virtual              ~nsDocViewerSelectionListener() {}
00255 
00256   nsresult             Init(DocumentViewerImpl *aDocViewer);
00257 
00258 protected:
00259 
00260   DocumentViewerImpl*  mDocViewer;
00261   PRPackedBool         mGotSelectionState;
00262   PRPackedBool         mSelectionWasCollapsed;
00263 
00264 };
00265 
00266 
00269 class nsDocViewerFocusListener : public nsIDOMFocusListener
00270 {
00271 public:
00274   nsDocViewerFocusListener();
00277   virtual ~nsDocViewerFocusListener();
00278 
00279 
00280 /*interfaces for addref and release and queryinterface*/
00281   NS_DECL_ISUPPORTS
00282 
00283 /*BEGIN implementations of focus event handler interface*/
00284   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
00285   NS_IMETHOD Focus(nsIDOMEvent* aEvent);
00286   NS_IMETHOD Blur(nsIDOMEvent* aEvent);
00287 /*END implementations of focus event handler interface*/
00288   nsresult             Init(DocumentViewerImpl *aDocViewer);
00289 
00290 private:
00291     DocumentViewerImpl*  mDocViewer;
00292 };
00293 
00294 
00295 
00296 #ifdef XP_MAC
00297 #pragma mark ** DocumentViewerImpl **
00298 #endif
00299 
00300 //-------------------------------------------------------------
00301 class DocumentViewerImpl : public nsIDocumentViewer,
00302                            public nsIContentViewer_MOZILLA_1_8_BRANCH,
00303                            public nsIContentViewer_MOZILLA_1_8_BRANCH2,
00304                            public nsIContentViewerEdit,
00305                            public nsIContentViewerFile,
00306                            public nsIMarkupDocumentViewer,
00307                            public nsIWebBrowserPrint,
00308                            public nsIDocumentViewerPrint
00309 {
00310   friend class nsDocViewerSelectionListener;
00311   friend class nsPagePrintTimer;
00312   friend class nsPrintEngine;
00313 
00314 public:
00315   DocumentViewerImpl(nsPresContext* aPresContext);
00316 
00317   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
00318 
00319   // nsISupports interface...
00320   NS_DECL_ISUPPORTS
00321 
00322   // nsIContentViewer interface...
00323   NS_DECL_NSICONTENTVIEWER
00324   NS_DECL_NSICONTENTVIEWER_MOZILLA_1_8_BRANCH
00325   NS_DECL_NSICONTENTVIEWER_MOZILLA_1_8_BRANCH2
00326 
00327   // nsIDocumentViewer interface...
00328   NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet);
00329   NS_IMETHOD GetDocument(nsIDocument** aResult);
00330   NS_IMETHOD GetPresShell(nsIPresShell** aResult);
00331   NS_IMETHOD GetPresContext(nsPresContext** aResult);
00332   NS_IMETHOD CreateDocumentViewerUsing(nsPresContext* aPresContext,
00333                                        nsIDocumentViewer** aResult);
00334 
00335   // nsIContentViewerEdit
00336   NS_DECL_NSICONTENTVIEWEREDIT
00337 
00338   // nsIContentViewerFile
00339   NS_DECL_NSICONTENTVIEWERFILE
00340 
00341   // nsIMarkupDocumentViewer
00342   NS_DECL_NSIMARKUPDOCUMENTVIEWER
00343 
00344   // nsIWebBrowserPrint
00345   NS_DECL_NSIWEBBROWSERPRINT
00346 
00347   typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer,
00348                                 void* aClosure);
00349   void CallChildren(CallChildFunc aFunc, void* aClosure);
00350 
00351   // nsIDocumentViewerPrint Printing Methods
00352   NS_DECL_NSIDOCUMENTVIEWERPRINT
00353 
00354 protected:
00355   virtual ~DocumentViewerImpl();
00356 
00357 private:
00358   nsresult MakeWindow(nsIWidget* aParentWidget,
00359                       const nsRect& aBounds);
00360   nsresult InitInternal(nsIWidget* aParentWidget,
00361                         nsISupports *aState,
00362                         nsIDeviceContext* aDeviceContext,
00363                         const nsRect& aBounds,
00364                         PRBool aDoCreation,
00365                         PRBool aInPrintPreview);
00366   nsresult InitPresentationStuff(PRBool aDoInitialReflow);
00367 
00368   nsresult GetPopupNode(nsIDOMNode** aNode);
00369   nsresult GetPopupLinkNode(nsIDOMNode** aNode);
00370   nsresult GetPopupImageNode(nsIImageLoadingContent** aNode);
00371 
00372   void DumpContentToPPM(const char* aFileName);
00373 
00374   void PrepareToStartLoad(void);
00375 
00376   nsresult SyncParentSubDocMap();
00377 
00378 #ifdef NS_PRINTING
00379   // Called when the DocViewer is notified that the state
00380   // of Printing or PP has changed
00381   void SetIsPrintingInDocShellTree(nsIDocShellTreeNode* aParentNode, 
00382                                    PRBool               aIsPrintingOrPP, 
00383                                    PRBool               aStartAtTop);
00384 #endif // NS_PRINTING
00385 
00386 protected:
00387   // IMPORTANT: The ownership implicit in the following member
00388   // variables has been explicitly checked and set using nsCOMPtr
00389   // for owning pointers and raw COM interface pointers for weak
00390   // (ie, non owning) references. If you add any members to this
00391   // class, please make the ownership explicit (pinkerton, scc).
00392 
00393   nsWeakPtr mContainer; // it owns me!
00394   nsCOMPtr<nsIDeviceContext> mDeviceContext;   // ??? can't hurt, but...
00395 
00396   // the following six items are explicitly in this order
00397   // so they will be destroyed in the reverse order (pinkerton, scc)
00398   nsCOMPtr<nsIDocument>    mDocument;
00399   nsCOMPtr<nsIWidget>      mWindow;      // ??? should we really own it?
00400   nsCOMPtr<nsIViewManager> mViewManager;
00401   nsCOMPtr<nsPresContext> mPresContext;
00402   nsCOMPtr<nsIPresShell>   mPresShell;
00403 
00404   nsCOMPtr<nsIStyleSheet>  mUAStyleSheet;
00405 
00406   nsCOMPtr<nsISelectionListener> mSelectionListener;
00407   nsCOMPtr<nsIDOMFocusListener> mFocusListener;
00408 
00409   nsCOMPtr<nsIContentViewer> mPreviousViewer;
00410   nsCOMPtr<nsISHEntry> mSHEntry;
00411 
00412   nsIWidget* mParentWidget;          // purposely won't be ref counted
00413 
00414   PRInt16 mNumURLStarts;
00415   PRInt16 mDestroyRefCount;    // a second "refcount" for the document viewer's "destroy"
00416 
00417   unsigned      mEnableRendering : 1;
00418   unsigned      mStopped : 1;
00419   unsigned      mLoaded : 1;
00420   unsigned      mDeferredWindowClose : 1;
00421   // document management data
00422   //   these items are specific to markup documents (html and xml)
00423   //   may consider splitting these out into a subclass
00424   unsigned      mIsSticky : 1;
00425   unsigned      mInPermitUnload : 1;
00426 
00427 #ifdef NS_PRINTING
00428   unsigned      mClosingWhilePrinting : 1;
00429 
00430 #if NS_PRINT_PREVIEW
00431   // These data members support delayed printing when the document is loading
00432   unsigned                         mPrintIsPending : 1;
00433   unsigned                         mPrintDocIsFullyLoaded : 1;
00434   nsCOMPtr<nsIPrintSettings>       mCachedPrintSettings;
00435   nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
00436 #endif // NS_PRINT_PREVIEW
00437 
00438   nsPrintEngine*        mPrintEngine;
00439   nsCOMPtr<nsIDOMWindowInternal> mDialogParentWin;
00440 
00441 #ifdef NS_DEBUG
00442   FILE* mDebugFile;
00443 #endif // NS_DEBUG
00444 #endif // NS_PRINTING
00445 
00446   /* character set member data */
00447   PRInt32 mHintCharsetSource;
00448   nsCString mHintCharset;
00449   nsCString mDefaultCharacterSet;
00450   nsCString mForceCharacterSet;
00451   nsCString mPrevDocCharacterSet;
00452   
00453 
00454 };
00455 
00456 //------------------------------------------------------------------
00457 // DocumentViewerImpl
00458 //------------------------------------------------------------------
00459 // Class IDs
00460 static NS_DEFINE_CID(kViewManagerCID,       NS_VIEW_MANAGER_CID);
00461 static NS_DEFINE_CID(kWidgetCID,            NS_CHILD_CID);
00462 
00463 //------------------------------------------------------------------
00464 nsresult
00465 NS_NewDocumentViewer(nsIDocumentViewer** aResult)
00466 {
00467   *aResult = new DocumentViewerImpl(nsnull);
00468   if (!*aResult) {
00469     return NS_ERROR_OUT_OF_MEMORY;
00470   }
00471 
00472   NS_ADDREF(*aResult);
00473 
00474   return NS_OK;
00475 }
00476 
00477 void DocumentViewerImpl::PrepareToStartLoad()
00478 {
00479   mEnableRendering  = PR_TRUE;
00480   mStopped          = PR_FALSE;
00481   mLoaded           = PR_FALSE;
00482   mDeferredWindowClose = PR_FALSE;
00483 
00484 #ifdef NS_PRINTING
00485   mPrintIsPending        = PR_FALSE;
00486   mPrintDocIsFullyLoaded = PR_FALSE;
00487   mClosingWhilePrinting  = PR_FALSE;
00488 
00489   // Make sure we have destroyed it and cleared the data member
00490   if (mPrintEngine) {
00491     mPrintEngine->Destroy();
00492     NS_RELEASE(mPrintEngine);
00493   }
00494 
00495 #ifdef NS_PRINT_PREVIEW
00496   SetIsPrintPreview(PR_FALSE);
00497 #endif
00498 
00499 #ifdef NS_DEBUG
00500   mDebugFile = nsnull;
00501 #endif
00502 
00503 #endif // NS_PRINTING
00504 }
00505 
00506 // Note: operator new zeros our memory, so no need to init things to null.
00507 DocumentViewerImpl::DocumentViewerImpl(nsPresContext* aPresContext)
00508   : mPresContext(aPresContext),
00509     mIsSticky(PR_TRUE),
00510     mHintCharsetSource(kCharsetUninitialized)
00511 {
00512   PrepareToStartLoad();
00513 }
00514 
00515 NS_IMPL_ISUPPORTS9(DocumentViewerImpl,
00516                    nsIContentViewer,
00517                    nsIContentViewer_MOZILLA_1_8_BRANCH,
00518                    nsIContentViewer_MOZILLA_1_8_BRANCH2,
00519                    nsIDocumentViewer,
00520                    nsIMarkupDocumentViewer,
00521                    nsIContentViewerFile,
00522                    nsIContentViewerEdit,
00523                    nsIWebBrowserPrint,
00524                    nsIDocumentViewerPrint)
00525 
00526 DocumentViewerImpl::~DocumentViewerImpl()
00527 {
00528   if (mDocument) {
00529     Close(nsnull);
00530     mDocument->Destroy();
00531   }
00532 
00533   NS_ASSERTION(!mPresShell && !mPresContext,
00534                "User did not call nsIContentViewer::Destroy");
00535   if (mPresShell || mPresContext) {
00536     // Make sure we don't hand out a reference to the content viewer to
00537     // the SHEntry!
00538     mSHEntry = nsnull;
00539 
00540     Destroy();
00541   }
00542 
00543   // XXX(?) Revoke pending invalidate events
00544 }
00545 
00546 /*
00547  * This method is called by the Document Loader once a document has
00548  * been created for a particular data stream...  The content viewer
00549  * must cache this document for later use when Init(...) is called.
00550  *
00551  * This method is also called when an out of band document.write() happens.
00552  * In that case, the document passed in is the same as the previous document.
00553  */
00554 NS_IMETHODIMP
00555 DocumentViewerImpl::LoadStart(nsISupports *aDoc)
00556 {
00557 #ifdef NOISY_VIEWER
00558   printf("DocumentViewerImpl::LoadStart\n");
00559 #endif
00560 
00561   nsresult rv = NS_OK;
00562   if (!mDocument) {
00563     mDocument = do_QueryInterface(aDoc, &rv);
00564   }
00565   else if (mDocument == aDoc) {
00566     // Reset the document viewer's state back to what it was
00567     // when the document load started.
00568     PrepareToStartLoad();
00569   }
00570 
00571   return rv;
00572 }
00573 
00574 nsresult
00575 DocumentViewerImpl::SyncParentSubDocMap()
00576 {
00577   nsCOMPtr<nsIDocShellTreeItem> item(do_QueryReferent(mContainer));
00578   nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(item));
00579   nsCOMPtr<nsIContent> content;
00580 
00581   if (mDocument && pwin) {
00582     content = do_QueryInterface(pwin->GetFrameElementInternal());
00583   }
00584 
00585   if (content) {
00586     nsCOMPtr<nsIDocShellTreeItem> parent;
00587     item->GetParent(getter_AddRefs(parent));
00588 
00589     nsCOMPtr<nsIDOMWindow> parent_win(do_GetInterface(parent));
00590 
00591     if (parent_win) {
00592       nsCOMPtr<nsIDOMDocument> dom_doc;
00593       parent_win->GetDocument(getter_AddRefs(dom_doc));
00594 
00595       nsCOMPtr<nsIDocument> parent_doc(do_QueryInterface(dom_doc));
00596 
00597       if (parent_doc) {
00598         return parent_doc->SetSubDocumentFor(content, mDocument);
00599       }
00600     }
00601   }
00602 
00603   return NS_OK;
00604 }
00605 
00606 NS_IMETHODIMP
00607 DocumentViewerImpl::SetContainer(nsISupports* aContainer)
00608 {
00609   mContainer = do_GetWeakReference(aContainer);
00610   if (mPresContext) {
00611     mPresContext->SetContainer(aContainer);
00612   }
00613 
00614   // We're loading a new document into the window where this document
00615   // viewer lives, sync the parent document's frame element -> sub
00616   // document map
00617 
00618   return SyncParentSubDocMap();
00619 }
00620 
00621 NS_IMETHODIMP
00622 DocumentViewerImpl::GetContainer(nsISupports** aResult)
00623 {
00624    NS_ENSURE_ARG_POINTER(aResult);
00625 
00626    *aResult = nsnull;
00627    nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
00628    container.swap(*aResult);
00629    return NS_OK;
00630 }
00631 
00632 NS_IMETHODIMP
00633 DocumentViewerImpl::Init(nsIWidget* aParentWidget,
00634                          nsIDeviceContext* aDeviceContext,
00635                          const nsRect& aBounds)
00636 {
00637   return InitInternal(aParentWidget, nsnull, aDeviceContext, aBounds, PR_TRUE, PR_FALSE);
00638 }
00639 
00640 nsresult
00641 DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
00642 {
00643   // Create the style set...
00644   nsStyleSet *styleSet;
00645   nsresult rv = CreateStyleSet(mDocument, &styleSet);
00646   NS_ENSURE_SUCCESS(rv, rv);
00647 
00648   // Now make the shell for the document
00649   rv = mDocument->CreateShell(mPresContext, mViewManager, styleSet,
00650                               getter_AddRefs(mPresShell));
00651   if (NS_FAILED(rv)) {
00652     delete styleSet;
00653     return rv;
00654   }
00655 
00656   // We're done creating the style set
00657   styleSet->EndUpdate();
00658 
00659   if (aDoInitialReflow) {
00660     // Since InitialReflow() will create frames for *all* items
00661     // that are currently in the document tree, we need to flush
00662     // any pending notifications to prevent the content sink from
00663     // duplicating layout frames for content it has added to the tree
00664     // but hasn't notified the document about. (Bug 154018)
00665     //
00666     // Note that we are flushing before we add mPresShell as an observer
00667     // to avoid bogus notifications.
00668 
00669     mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
00670   }
00671 
00672   mPresShell->BeginObservingDocument();
00673 
00674   // Initialize our view manager
00675   nsRect bounds;
00676   mWindow->GetBounds(bounds);
00677 
00678   float p2t;
00679 
00680   p2t = mPresContext->PixelsToTwips();
00681 
00682   nscoord width = NSIntPixelsToTwips(bounds.width, p2t);
00683   nscoord height = NSIntPixelsToTwips(bounds.height, p2t);
00684 
00685   mViewManager->DisableRefresh();
00686   mViewManager->SetWindowDimensions(width, height);
00687 
00688   // Setup default view manager background color
00689 
00690   // This may be overridden by the docshell with the background color
00691   // for the last document loaded into the docshell
00692   mViewManager->SetDefaultBackgroundColor(mPresContext->DefaultBackgroundColor());
00693 
00694   if (aDoInitialReflow) {
00695     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
00696     if (htmlDoc) {
00697       nsCOMPtr<nsIDOMHTMLFrameSetElement> frameset =
00698         do_QueryInterface(mDocument->GetRootContent());
00699       htmlDoc->SetIsFrameset(frameset != nsnull);
00700     }
00701 
00702     // Initial reflow
00703     mPresShell->InitialReflow(width, height);
00704 
00705     // Now trigger a refresh
00706     if (mEnableRendering) {
00707       mViewManager->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
00708     }
00709   } else {
00710     // Store the visible area so it's available for other callers of
00711     // InitialReflow, like nsContentSink::StartLayout.
00712     mPresContext->SetVisibleArea(nsRect(0, 0, width, height));
00713   }
00714 
00715   // now register ourselves as a selection listener, so that we get
00716   // called when the selection changes in the window
00717   nsDocViewerSelectionListener *selectionListener =
00718     new nsDocViewerSelectionListener();
00719   NS_ENSURE_TRUE(selectionListener, NS_ERROR_OUT_OF_MEMORY);
00720 
00721   selectionListener->Init(this);
00722 
00723   // mSelectionListener is a owning reference
00724   mSelectionListener = selectionListener;
00725 
00726   nsCOMPtr<nsISelection> selection;
00727   rv = GetDocumentSelection(getter_AddRefs(selection));
00728   NS_ENSURE_SUCCESS(rv, rv);
00729 
00730   nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
00731   rv = selPrivate->AddSelectionListener(mSelectionListener);
00732   if (NS_FAILED(rv))
00733     return rv;
00734 
00735   // Save old listener so we can unregister it
00736   nsCOMPtr<nsIDOMFocusListener> mOldFocusListener = mFocusListener;
00737 
00738   // focus listener
00739   //
00740   // now register ourselves as a focus listener, so that we get called
00741   // when the focus changes in the window
00742   nsDocViewerFocusListener *focusListener;
00743   NS_NEWXPCOM(focusListener, nsDocViewerFocusListener);
00744   NS_ENSURE_TRUE(focusListener, NS_ERROR_OUT_OF_MEMORY);
00745 
00746   focusListener->Init(this);
00747 
00748   // mFocusListener is a strong reference
00749   mFocusListener = focusListener;
00750 
00751   // get the DOM event receiver
00752   nsCOMPtr<nsIDOMEventReceiver> erP(do_QueryInterface(mDocument));
00753   NS_WARN_IF_FALSE(erP, "No event receiver in document!");
00754 
00755   if (erP) {
00756     rv = erP->AddEventListenerByIID(mFocusListener,
00757                                     NS_GET_IID(nsIDOMFocusListener));
00758     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
00759     if (mOldFocusListener) {
00760       rv = erP->RemoveEventListenerByIID(mOldFocusListener,
00761                                       NS_GET_IID(nsIDOMFocusListener));
00762       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove focus listener");
00763     }
00764   }
00765 
00766   return NS_OK;
00767 }
00768 
00769 //-----------------------------------------------
00770 // This method can be used to initial the "presentation"
00771 // The aDoCreation indicates whether it should create
00772 // all the new objects or just initialize the existing ones
00773 nsresult
00774 DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
00775                                  nsISupports *aState,
00776                                  nsIDeviceContext* aDeviceContext,
00777                                  const nsRect& aBounds,
00778                                  PRBool aDoCreation,
00779                                  PRBool aInPrintPreview)
00780 {
00781   mParentWidget = aParentWidget; // not ref counted
00782 
00783   nsresult rv = NS_OK;
00784   NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER);
00785 
00786   mDeviceContext = aDeviceContext;
00787 
00788 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
00789   // Clear PrintPreview Alternate Device
00790   if (mDeviceContext) {
00791     mDeviceContext->SetAltDevice(nsnull);
00792     mDeviceContext->SetCanonicalPixelScale(1.0);
00793   }
00794 #endif
00795 
00796   PRBool makeCX = PR_FALSE;
00797   if (aDoCreation) {
00798     if (aParentWidget && !mPresContext) {
00799       // Create presentation context
00800       mPresContext = new nsPresContext(GetIsCreatingPrintPreview() ?
00801                                         nsPresContext::eContext_PrintPreview :
00802                                         nsPresContext::eContext_Galley);
00803       NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
00804 
00805       nsresult rv = mPresContext->Init(aDeviceContext); 
00806       if (NS_FAILED(rv)) {
00807         mPresContext = nsnull;
00808         return rv;
00809       }
00810 
00811 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
00812       makeCX = !GetIsPrintPreview(); // needs to be true except when we are already in PP
00813 #else
00814       makeCX = PR_TRUE;
00815 #endif
00816     }
00817 
00818     if (mPresContext) {
00819       // Create the ViewManager and Root View...
00820 
00821       // We must do this before we tell the script global object about
00822       // this new document since doing that will cause us to re-enter
00823       // into nsSubDocumentFrame code through reflows caused by
00824       // FlushPendingNotifications() calls down the road...
00825 
00826       rv = MakeWindow(aParentWidget, aBounds);
00827       NS_ENSURE_SUCCESS(rv, rv);
00828       Hide();
00829     }
00830   }
00831 
00832   nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryReferent(mContainer));
00833   if (requestor) {
00834     if (mPresContext) {
00835       nsCOMPtr<nsILinkHandler> linkHandler;
00836       requestor->GetInterface(NS_GET_IID(nsILinkHandler),
00837                               getter_AddRefs(linkHandler));
00838 
00839       mPresContext->SetContainer(requestor);
00840       mPresContext->SetLinkHandler(linkHandler);
00841     }
00842 
00843     if (!aInPrintPreview) {
00844       // Set script-context-owner in the document
00845 
00846       nsCOMPtr<nsIScriptGlobalObject> global;
00847       requestor->GetInterface(NS_GET_IID(nsIScriptGlobalObject),
00848                               getter_AddRefs(global));
00849 
00850       if (global) {
00851         nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(mDocument));
00852 
00853         if (domdoc) {
00854           global->SetNewDocument(domdoc, aState, PR_TRUE, PR_TRUE);
00855         }
00856       }
00857     }
00858   }
00859 
00860   if (aDoCreation && mPresContext) {
00861     // The ViewManager and Root View was created above (in
00862     // MakeWindow())...
00863 
00864     rv = InitPresentationStuff(!makeCX);
00865   }
00866 
00867   return rv;
00868 }
00869 
00870 void
00871 DocumentViewerImpl::DumpContentToPPM(const char* aFileName)
00872 {
00873   mDocument->FlushPendingNotifications(Flush_Display);
00874 
00875   nsIScrollableView* scrollableView;
00876   mViewManager->GetRootScrollableView(&scrollableView);
00877   nsIView* view;
00878   if (scrollableView) {
00879     scrollableView->GetScrolledView(view);
00880   } else {
00881     mViewManager->GetRootView(view);
00882   }
00883   nsRect r = view->GetBounds() - view->GetPosition();
00884   float p2t = mPresContext->PixelsToTwips();
00885   // Limit the bitmap size to 5000x5000
00886   nscoord twipLimit = NSIntPixelsToTwips(5000, p2t);
00887   if (r.height > twipLimit)
00888     r.height = twipLimit;
00889   if (r.width > twipLimit)
00890     r.width = twipLimit;
00891 
00892   const char* status;
00893 
00894   if (r.IsEmpty()) {
00895     status = "EMPTY";
00896   } else {
00897     nsCOMPtr<nsIRenderingContext> context;
00898     nsresult rv = mViewManager->RenderOffscreen(view, r,
00899                                                 PR_FALSE, PR_TRUE,
00900                                                 NS_RGB(255, 255, 255),
00901                                                 getter_AddRefs(context));
00902 
00903     if (NS_FAILED(rv)) {
00904       status = "FAILEDRENDER";
00905     } else {
00906       nsIDrawingSurface* surface;
00907       context->GetDrawingSurface(&surface);
00908       if (!surface) {
00909         status = "NOSURFACE";
00910       } else {
00911         float t2p = mPresContext->TwipsToPixels();
00912         PRUint32 width = NSTwipsToIntPixels(view->GetBounds().width, t2p);
00913         PRUint32 height = NSTwipsToIntPixels(view->GetBounds().height, t2p);
00914 
00915         PRUint8* data;
00916         PRInt32 rowLen, rowSpan;
00917         rv = surface->Lock(0, 0, width, height, (void**)&data, &rowSpan, &rowLen,
00918                            NS_LOCK_SURFACE_READ_ONLY);
00919         if (NS_FAILED(rv)) {
00920           status = "FAILEDLOCK";
00921         } else {
00922           PRUint32 bytesPerPix = rowLen/width;
00923           nsPixelFormat format;
00924           surface->GetPixelFormat(&format);
00925 
00926           PRUint8* buf = new PRUint8[3*width];
00927           if (buf) {
00928             FILE* f = fopen(aFileName, "wb");
00929             if (f) {
00930               fprintf(f, "P6\n%d\n%d\n255\n", width, height);
00931               for (PRUint32 i = 0; i < height; ++i) {
00932                 PRUint8* src = data + i*rowSpan;
00933                 PRUint8* dest = buf;
00934                 for (PRUint32 j = 0; j < width; ++j) {
00935                   /* v is the pixel value */
00936 #ifdef IS_BIG_ENDIAN
00937                   PRUint32 v = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
00938                   v >>= (32 - 8*bytesPerPix);
00939 #else
00940                   PRUint32 v = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
00941 #endif
00942                   dest[0] = ((v & format.mRedMask) >> format.mRedShift) << (8 - format.mRedCount);
00943                   dest[1] = ((v & format.mGreenMask) >> format.mGreenShift) << (8 - format.mGreenCount);
00944                   dest[2] = ((v & format.mBlueMask) >> format.mBlueShift) << (8 - format.mBlueCount);
00945                   src += bytesPerPix;
00946                   dest += 3;
00947                 }
00948                 fwrite(buf, 3, width, f);
00949               }
00950               fclose(f);
00951               status = "OK";
00952             }
00953             
00954             delete[] buf;
00955           }
00956           surface->Unlock();
00957         }
00958         context->DestroyDrawingSurface(surface);
00959       }
00960     }
00961   }
00962 
00963   nsIURI *uri = mDocument->GetDocumentURI();
00964   nsCAutoString spec;
00965   if (uri) {
00966     uri->GetAsciiSpec(spec);
00967   }
00968   printf("GECKO: PAINT FORCED AFTER ONLOAD: %s %s (%s)\n", spec.get(), aFileName, status);
00969   fflush(stdout);
00970 }
00971 
00972 //
00973 // LoadComplete(aStatus)
00974 //
00975 //   aStatus - The status returned from loading the document.
00976 //
00977 // This method is called by the container when the document has been
00978 // completely loaded.
00979 //
00980 NS_IMETHODIMP
00981 DocumentViewerImpl::LoadComplete(nsresult aStatus)
00982 {
00983   nsresult rv = NS_OK;
00984   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
00985 
00986   // First, get the script global object from the document...
00987   nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
00988 
00989   // Fail if no ScriptGlobalObject is available...
00990   NS_ENSURE_TRUE(global, NS_ERROR_NULL_POINTER);
00991 
00992   mLoaded = PR_TRUE;
00993 
00994   /* We need to protect ourself against auto-destruction in case the
00995      window is closed while processing the OnLoad event.  See bug
00996      http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
00997      explanation.
00998   */
00999   nsCOMPtr<nsIDocumentViewer> kungFuDeathGrip(this);
01000 
01001   // Now, fire either an OnLoad or OnError event to the document...
01002   PRBool restoring = PR_FALSE;
01003   if(NS_SUCCEEDED(aStatus)) {
01004     nsEventStatus status = nsEventStatus_eIgnore;
01005     nsEvent event(PR_TRUE, NS_PAGE_LOAD);
01006 
01007     // If the document presentation is being restored, we don't want to fire
01008     // onload to the document content since that would likely confuse scripts
01009     // on the page.
01010 
01011     nsIDocShell *docShell = global->GetDocShell();
01012     NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
01013 
01014     docShell->GetRestoringDocument(&restoring);
01015     if (!restoring) {
01016       rv = global->HandleDOMEvent(mPresContext, &event, nsnull,
01017                                   NS_EVENT_FLAG_INIT, &status);
01018 #ifdef MOZ_TIMELINE
01019       // if navigator.xul's load is complete, the main nav window is visible
01020       // mark that point.
01021 
01022       //printf("DEBUG: getting uri from document (%p)\n", mDocument.get());
01023 
01024       nsIURI *uri = mDocument ? mDocument->GetDocumentURI() : nsnull;
01025 
01026       if (uri) {
01027         //printf("DEBUG: getting spec for uri (%p)\n", uri.get());
01028         nsCAutoString spec;
01029         uri->GetSpec(spec);
01030         if (spec.EqualsLiteral("chrome://navigator/content/navigator.xul") ||
01031             spec.EqualsLiteral("chrome://browser/content/browser.xul")) {
01032           NS_TIMELINE_MARK("Navigator Window visible now");
01033         }
01034       }
01035 #endif /* MOZ_TIMELINE */
01036     }
01037   } else {
01038     // XXX: Should fire error event to the document...
01039   }
01040 
01041   // Notify the document that it has been shown (regardless of whether
01042   // it was just loaded). Note: mDocument may be null now if the above
01043   // firing of onload caused the document to unload.
01044   if (mDocument)
01045     mDocument->OnPageShow(restoring);
01046 
01047   // Now that the document has loaded, we can tell the presshell
01048   // to unsuppress painting.
01049   if (mPresShell && !mStopped) {
01050     nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
01051     mPresShell->UnsuppressPainting();
01052   }
01053 
01054   static PRBool forcePaint
01055     = PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD") != nsnull;
01056   static PRUint32 index = 0;
01057   if (forcePaint) {
01058     nsCAutoString name(PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD"));
01059     name.AppendLiteral("-");
01060     ++index;
01061     name.AppendInt(index);
01062     DumpContentToPPM(name.get());
01063   }
01064 
01065 #ifdef NS_PRINTING
01066   // Check to see if someone tried to print during the load
01067   if (mPrintIsPending) {
01068     mPrintIsPending        = PR_FALSE;
01069     mPrintDocIsFullyLoaded = PR_TRUE;
01070     Print(mCachedPrintSettings, mCachedPrintWebProgressListner);
01071     mCachedPrintSettings           = nsnull;
01072     mCachedPrintWebProgressListner = nsnull;
01073   }
01074 #endif
01075 
01076   return rv;
01077 }
01078 
01079 NS_IMETHODIMP
01080 DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
01081 {
01082   *aPermitUnload = PR_TRUE;
01083 
01084   if (!mDocument || mInPermitUnload) {
01085     return NS_OK;
01086   }
01087 
01088   // First, get the script global object from the document...
01089   nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
01090 
01091   if (!global) {
01092     // This is odd, but not fatal
01093     NS_WARNING("nsIScriptGlobalObject not set for document!");
01094     return NS_OK;
01095   }
01096 
01097   // Now, fire an BeforeUnload event to the document and see if it's ok
01098   // to unload...
01099   nsEventStatus status = nsEventStatus_eIgnore;
01100   nsBeforePageUnloadEvent event(PR_TRUE, NS_BEFORE_PAGE_UNLOAD);
01101   nsresult rv = NS_OK;
01102 
01103   // In evil cases we might be destroyed while handling the
01104   // onbeforeunload event, don't let that happen. (see also bug#331040)
01105   nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
01106 
01107   {
01108     // Never permit popups from the beforeunload handler, no matter
01109     // how we get here.
01110     nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
01111 
01112     mInPermitUnload = PR_TRUE;
01113     rv = global->HandleDOMEvent(mPresContext, &event, nsnull,
01114                                 NS_EVENT_FLAG_INIT, &status);
01115     mInPermitUnload = PR_FALSE;
01116   }
01117 
01118   nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
01119 
01120   if (NS_SUCCEEDED(rv) && (event.flags & NS_EVENT_FLAG_NO_DEFAULT ||
01121                            !event.text.IsEmpty())) {
01122     // Ask the user if it's ok to unload the current page
01123 
01124     nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShellNode);
01125 
01126     if (prompt) {
01127       nsXPIDLString preMsg, postMsg;
01128       rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
01129                                               "OnBeforeUnloadPreMessage",
01130                                               preMsg);
01131       rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
01132                                                "OnBeforeUnloadPostMessage",
01133                                                postMsg);
01134 
01135       // GetStringFromName can succeed, yet give NULL strings back.
01136       if (NS_FAILED(rv) || preMsg.IsEmpty() || postMsg.IsEmpty()) {
01137         NS_ERROR("Failed to get strings from dom.properties!");
01138         return NS_OK;
01139       }
01140 
01141       // Limit the length of the text the page can inject into this
01142       // dialogue to 1024 characters.
01143       PRInt32 len = PR_MIN(event.text.Length(), 1024);
01144 
01145       nsAutoString msg(preMsg + NS_LITERAL_STRING("\n\n") +
01146                        StringHead(event.text, len) +
01147                        NS_LITERAL_STRING("\n\n") + postMsg);
01148 
01149       // This doesn't pass a title, which makes the title be
01150       // "Confirm", is that ok, or do we want a localizable title for
01151       // this dialogue?
01152       if (NS_FAILED(prompt->Confirm(nsnull, msg.get(), aPermitUnload))) {
01153         *aPermitUnload = PR_TRUE;
01154       }
01155     }
01156   }
01157 
01158   if (docShellNode) {
01159     PRInt32 childCount;
01160     docShellNode->GetChildCount(&childCount);
01161 
01162     for (PRInt32 i = 0; i < childCount && *aPermitUnload; ++i) {
01163       nsCOMPtr<nsIDocShellTreeItem> item;
01164       docShellNode->GetChildAt(i, getter_AddRefs(item));
01165 
01166       nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item));
01167       nsCOMPtr<nsIContentViewer> cv;
01168 
01169       docShell->GetContentViewer(getter_AddRefs(cv));
01170 
01171       if (cv) {
01172         cv->PermitUnload(aPermitUnload);
01173       }
01174     }
01175   }
01176 
01177   return NS_OK;
01178 }
01179 
01180 NS_IMETHODIMP
01181 DocumentViewerImpl::PageHide(PRBool aIsUnload)
01182 {
01183   mEnableRendering = PR_FALSE;
01184 
01185   if (!mDocument) {
01186     return NS_ERROR_NULL_POINTER;
01187   }
01188 
01189   nsresult rv = NS_OK;
01190 
01191   mDocument->OnPageHide(!aIsUnload);
01192   if (aIsUnload) {
01193     // if Destroy() was called during OnPageHide(), mDocument is nsnull.
01194     NS_ENSURE_STATE(mDocument);
01195 
01196     // First, get the script global object from the document...
01197     nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
01198 
01199     if (!global) {
01200       // Fail if no ScriptGlobalObject is available...
01201       NS_ERROR("nsIScriptGlobalObject not set for document!");
01202       return NS_ERROR_NULL_POINTER;
01203     }
01204 
01205     // Now, fire an Unload event to the document...
01206     nsEventStatus status = nsEventStatus_eIgnore;
01207     nsEvent event(PR_TRUE, NS_PAGE_UNLOAD);
01208 
01209     // Never permit popups from the unload handler, no matter how we get
01210     // here.
01211     nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
01212 
01213     rv = global->HandleDOMEvent(mPresContext, &event, nsnull,
01214                                 NS_EVENT_FLAG_INIT, &status);
01215   }
01216 
01217   // look for open menupopups and close them after the unload event, in case
01218   // the unload event listeners open any new popups
01219   nsCOMPtr<nsIPresShell_MOZILLA_1_8_BRANCH> presShell18 = do_QueryInterface(mPresShell);
01220   if (presShell18)
01221     presShell18->HidePopups();
01222 
01223   return rv;
01224 }
01225 
01226 static void
01227 AttachContainerRecurse(nsIDocShell* aShell)
01228 {
01229   nsCOMPtr<nsIContentViewer> viewer;
01230   aShell->GetContentViewer(getter_AddRefs(viewer));
01231   nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(viewer);
01232   if (docViewer) {
01233     nsCOMPtr<nsIDocument> doc;
01234     docViewer->GetDocument(getter_AddRefs(doc));
01235     if (doc) {
01236       doc->SetContainer(aShell);
01237     }
01238     nsCOMPtr<nsPresContext> pc;
01239     docViewer->GetPresContext(getter_AddRefs(pc));
01240     if (pc) {
01241       pc->SetContainer(aShell);
01242       pc->SetLinkHandler(nsCOMPtr<nsILinkHandler>(do_QueryInterface(aShell)));
01243     }
01244     nsCOMPtr<nsIPresShell> presShell;
01245     docViewer->GetPresShell(getter_AddRefs(presShell));
01246     if (presShell) {
01247       presShell->SetForwardingContainer(nsnull);
01248     }
01249   }
01250 
01251   // Now recurse through the children
01252   nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(aShell);
01253   NS_ASSERTION(node, "docshells must implement nsIDocShellTreeNode");
01254 
01255   PRInt32 childCount;
01256   node->GetChildCount(&childCount);
01257   for (PRInt32 i = 0; i < childCount; ++i) {
01258     nsCOMPtr<nsIDocShellTreeItem> childItem;
01259     node->GetChildAt(i, getter_AddRefs(childItem));
01260     AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem)));
01261   }
01262 }
01263 
01264 NS_IMETHODIMP
01265 DocumentViewerImpl::Open(nsISupports *aState)
01266 {
01267   return NS_ERROR_NOT_IMPLEMENTED;
01268 }
01269 
01270 NS_IMETHODIMP
01271 DocumentViewerImpl::OpenWithEntry(nsISupports *aState, nsISHEntry *aSHEntry)
01272 {
01273   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
01274 
01275   // Our container might have gone away while we were closed.
01276   // If this is the case, we must fail to open so we don't crash.
01277   nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
01278   if (!container)
01279     return NS_ERROR_NOT_AVAILABLE;
01280 
01281   nsRect bounds;
01282   mWindow->GetBounds(bounds);
01283 
01284   nsresult rv = InitInternal(mParentWidget, aState, mDeviceContext, bounds,
01285                              PR_FALSE, PR_FALSE);
01286   NS_ENSURE_SUCCESS(rv, rv);
01287 
01288   if (mDocument)
01289     mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
01290 
01291   if (mPresShell)
01292     mPresShell->SetForwardingContainer(nsnull);
01293 
01294   // Rehook the child presentations.  The child shells are still in
01295   // session history, so get them from there.
01296 
01297   nsCOMPtr<nsIDocShellTreeItem> item;
01298   PRInt32 itemIndex = 0;
01299   while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++,
01300                                              getter_AddRefs(item))) && item) {
01301     AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item)));
01302   }
01303   
01304   SyncParentSubDocMap();
01305 
01306   // XXX re-enable image animations once that works correctly
01307 
01308   PrepareToStartLoad();
01309   return NS_OK;
01310 }
01311 
01312 NS_IMETHODIMP
01313 DocumentViewerImpl::Close(nsISHEntry *aSHEntry)
01314 {
01315   // All callers are supposed to call close to break circular
01316   // references.  If we do this stuff in the destructor, the
01317   // destructor might never be called (especially if we're being
01318   // used from JS.
01319 
01320   mSHEntry = aSHEntry;
01321 
01322   // Close is also needed to disable scripts during paint suppression,
01323   // since we transfer the existing global object to the new document
01324   // that is loaded.  In the future, the global object may become a proxy
01325   // for an object that can be switched in and out so that we don't need
01326   // to disable scripts during paint suppression.
01327 
01328   if (!mDocument)
01329     return NS_OK;
01330 
01331 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
01332   // Turn scripting back on
01333   // after PrintPreview had turned it off
01334   if (GetIsPrintPreview() && mPrintEngine) {
01335     mPrintEngine->TurnScriptingOn(PR_TRUE);
01336   }
01337 #endif
01338 
01339 #ifdef NS_PRINTING
01340   // A Close was called while we were printing
01341   // so don't clear the ScriptGlobalObject
01342   // or clear the mDocument below
01343   // Also, do an extra addref to keep the viewer from going away.
01344   if (mPrintEngine && !mClosingWhilePrinting) {
01345     mClosingWhilePrinting = PR_TRUE;
01346     NS_ADDREF_THIS();
01347   } else
01348 #endif
01349     {
01350       // out of band cleanup of webshell
01351       mDocument->SetScriptGlobalObject(nsnull);
01352 
01353       if (!mSHEntry)
01354         mDocument->Destroy();
01355     }
01356 
01357   if (mFocusListener) {
01358     // get the DOM event receiver
01359     nsCOMPtr<nsIDOMEventReceiver> erP(do_QueryInterface(mDocument));
01360     NS_WARN_IF_FALSE(erP, "No event receiver in document!");
01361 
01362     if (erP) {
01363       erP->RemoveEventListenerByIID(mFocusListener,
01364                                     NS_GET_IID(nsIDOMFocusListener));
01365     }
01366   }
01367 
01368   return NS_OK;
01369 }
01370 
01371 static void
01372 DetachContainerRecurse(nsIDocShell *aShell)
01373 {
01374   // Unhook this docshell's presentation
01375   nsCOMPtr<nsIContentViewer> viewer;
01376   aShell->GetContentViewer(getter_AddRefs(viewer));
01377   nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(viewer);
01378   if (docViewer) {
01379     nsCOMPtr<nsIDocument> doc;
01380     docViewer->GetDocument(getter_AddRefs(doc));
01381     if (doc) {
01382       doc->SetContainer(nsnull);
01383     }
01384     nsCOMPtr<nsPresContext> pc;
01385     docViewer->GetPresContext(getter_AddRefs(pc));
01386     if (pc) {
01387       pc->SetContainer(nsnull);
01388       pc->SetLinkHandler(nsnull);
01389     }
01390     nsCOMPtr<nsIPresShell> presShell;
01391     docViewer->GetPresShell(getter_AddRefs(presShell));
01392     if (presShell) {
01393       presShell->SetForwardingContainer(nsWeakPtr(do_GetWeakReference(aShell)));
01394     }
01395   }
01396 
01397   // Now recurse through the children
01398   nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(aShell);
01399   NS_ASSERTION(node, "docshells must implement nsIDocShellTreeNode");
01400 
01401   PRInt32 childCount;
01402   node->GetChildCount(&childCount);
01403   for (PRInt32 i = 0; i < childCount; ++i) {
01404     nsCOMPtr<nsIDocShellTreeItem> childItem;
01405     node->GetChildAt(i, getter_AddRefs(childItem));
01406     DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem)));
01407   }
01408 }
01409 
01410 NS_IMETHODIMP
01411 DocumentViewerImpl::Destroy()
01412 {
01413   NS_ASSERTION(mDocument, "No document in Destroy()!");
01414 
01415 #ifdef NS_PRINTING
01416   // Here is where we check to see if the docment was still being prepared 
01417   // for printing when it was asked to be destroy from someone externally
01418   // This usually happens if the document is unloaded while the user is in the Print Dialog
01419   //
01420   // So we flip the bool to remember that the document is going away
01421   // and we can clean up and abort later after returning from the Print Dialog
01422   if (mPrintEngine) {
01423     if (mPrintEngine->CheckBeforeDestroy()) {
01424       return NS_OK;
01425     }
01426   }
01427 #endif
01428 
01429   // Don't let the document get unloaded while we are printing.
01430   // this could happen if we hit the back button during printing.
01431   // We also keep the viewer from being cached in session history, since
01432   // we require all documents there to be sanitized.
01433   if (mDestroyRefCount != 0) {
01434     --mDestroyRefCount;
01435     return NS_OK;
01436   }
01437 
01438   // If we were told to put ourselves into session history instead of destroy
01439   // the presentation, do that now.
01440   if (mSHEntry) {
01441     if (mPresShell)
01442       mPresShell->Freeze();
01443 
01444     // Make sure the presentation isn't torn down by Hide().
01445     mSHEntry->SetSticky(mIsSticky);
01446     mIsSticky = PR_TRUE;
01447 
01448     PRBool savePresentation = PR_TRUE;
01449 
01450     // Remove our root view from the view hierarchy.
01451     if (mPresShell) {
01452       nsIViewManager *vm = mPresShell->GetViewManager();
01453       if (vm) {
01454         nsIView *rootView = nsnull;
01455         vm->GetRootView(rootView);
01456 
01457         if (rootView) {
01458           nsIView *rootViewParent = rootView->GetParent();
01459           if (rootViewParent) {
01460             nsIViewManager *parentVM = rootViewParent->GetViewManager();
01461             if (parentVM) {
01462               parentVM->RemoveChild(rootView);
01463             }
01464           }
01465         }
01466       }
01467     }
01468 
01469     Hide();
01470 
01471     // This is after Hide() so that the user doesn't see the inputs clear.
01472     if (mDocument) {
01473       nsresult rv = mDocument->Sanitize();
01474       if (NS_FAILED(rv)) {
01475         // If we failed to sanitize, don't save presentation.
01476         savePresentation = PR_FALSE;
01477       }
01478     }
01479 
01480 
01481     // Reverse ownership. Do this *after* calling sanitize so that sanitize
01482     // doesn't cause mutations that make the SHEntry drop the presentation
01483     if (savePresentation) {
01484       mSHEntry->SetContentViewer(this);
01485     }
01486     else {
01487       mSHEntry->SyncPresentationState();
01488     }
01489     nsCOMPtr<nsISHEntry> shEntry = mSHEntry; // we'll need this below
01490     mSHEntry = nsnull;
01491 
01492     // Break the link from the document/presentation to the docshell, so that
01493     // link traversals cannot affect the currently-loaded document.
01494     // When the presentation is restored, Open() and InitInternal() will reset
01495     // these pointers to their original values.
01496 
01497     if (mDocument)
01498       mDocument->SetContainer(nsnull);
01499     if (mPresContext) {
01500       mPresContext->SetLinkHandler(nsnull);
01501       mPresContext->SetContainer(nsnull);
01502     }
01503     if (mPresShell)
01504       mPresShell->SetForwardingContainer(mContainer);
01505 
01506     // Do the same for our children.  Note that we need to get the child
01507     // docshells from the SHEntry now; the docshell will have cleared them.
01508     nsCOMPtr<nsIDocShellTreeItem> item;
01509     PRInt32 itemIndex = 0;
01510     while (NS_SUCCEEDED(shEntry->ChildShellAt(itemIndex++,
01511                                               getter_AddRefs(item))) && item) {
01512       DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item)));
01513     }
01514 
01515     return NS_OK;
01516   }
01517 
01518   if (mDocument) {
01519     mDocument->Destroy();
01520     mDocument = nsnull;
01521   }
01522 
01523   // All callers are supposed to call destroy to break circular
01524   // references.  If we do this stuff in the destructor, the
01525   // destructor might never be called (especially if we're being
01526   // used from JS.
01527 
01528 #ifdef NS_PRINTING
01529   if (mPrintEngine) {
01530     mPrintEngine->Destroy();
01531     NS_RELEASE(mPrintEngine);
01532   }
01533 #endif
01534 
01535   // Avoid leaking the old viewer.
01536   if (mPreviousViewer) {
01537     mPreviousViewer->Destroy();
01538     mPreviousViewer = nsnull;
01539   }
01540 
01541   if (mDeviceContext) {
01542     mDeviceContext->FlushFontCache();
01543     mDeviceContext = nsnull;
01544   }
01545 
01546   if (mPresShell) {
01547     // Break circular reference (or something)
01548     mPresShell->EndObservingDocument();
01549 
01550     nsCOMPtr<nsISelection> selection;
01551     GetDocumentSelection(getter_AddRefs(selection));
01552 
01553     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
01554 
01555     if (selPrivate && mSelectionListener)
01556       selPrivate->RemoveSelectionListener(mSelectionListener);
01557 
01558     mPresShell->Destroy();
01559     mPresShell = nsnull;
01560   }
01561 
01562   if (mPresContext) {
01563     mPresContext->SetContainer(nsnull);
01564     mPresContext->SetLinkHandler(nsnull);
01565     mPresContext = nsnull;
01566   }
01567 
01568   mContainer = nsnull;
01569 
01570   return NS_OK;
01571 }
01572 
01573 NS_IMETHODIMP
01574 DocumentViewerImpl::Stop(void)
01575 {
01576   NS_ASSERTION(mDocument, "Stop called too early or too late");
01577   if (mDocument) {
01578     mDocument->StopDocumentLoad();
01579   }
01580 
01581   if (mEnableRendering && (mLoaded || mStopped) && mPresContext && !mSHEntry)
01582     mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
01583 
01584   mStopped = PR_TRUE;
01585 
01586   if (!mLoaded && mPresShell) {
01587     // Well, we might as well paint what we have so far.
01588     nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
01589     mPresShell->UnsuppressPainting();
01590   }
01591 
01592   return NS_OK;
01593 }
01594 
01595 NS_IMETHODIMP
01596 DocumentViewerImpl::GetDOMDocument(nsIDOMDocument **aResult)
01597 {
01598   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
01599   return CallQueryInterface(mDocument, aResult);
01600 }
01601 
01602 NS_IMETHODIMP
01603 DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
01604 {
01605   // Assumptions:
01606   //
01607   // 1) this document viewer has been initialized with a call to Init().
01608   // 2) the stylesheets associated with the document have been added
01609   // to the document.
01610 
01611   // XXX Right now, this method assumes that the layout of the current
01612   // document hasn't started yet.  More cleanup will probably be
01613   // necessary to make this method work for the case when layout *has*
01614   // occurred for the current document.
01615   // That work can happen when and if it is needed.
01616 
01617   nsresult rv;
01618   if (!aDocument)
01619     return NS_ERROR_NULL_POINTER;
01620 
01621   nsCOMPtr<nsIDocument> newDoc = do_QueryInterface(aDocument, &rv);
01622   if (NS_FAILED(rv)) return rv;
01623 
01624   // Set new container
01625   nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
01626   newDoc->SetContainer(container);
01627 
01628   if (mDocument != newDoc) {
01629     // Replace the old document with the new one. Do this only when
01630     // the new document really is a new document.
01631     mDocument = newDoc;
01632 
01633     // Set the script global object on the new document
01634     nsCOMPtr<nsIScriptGlobalObject> global = do_GetInterface(container);
01635     if (global) {
01636       global->SetNewDocument(aDocument, nsnull, PR_TRUE, PR_TRUE);
01637     }
01638 
01639     // Clear the list of old child docshells.
01640     nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
01641     if (node) {
01642       PRInt32 count;
01643       node->GetChildCount(&count);
01644       for (PRInt32 i = 0; i < count; ++i) {
01645         nsCOMPtr<nsIDocShellTreeItem> child;
01646         node->GetChildAt(0, getter_AddRefs(child));
01647         node->RemoveChild(child);
01648       }
01649     }
01650   }
01651 
01652   rv = SyncParentSubDocMap();
01653   NS_ENSURE_SUCCESS(rv, rv);
01654 
01655   // Replace the current pres shell with a new shell for the new document
01656 
01657   nsCOMPtr<nsILinkHandler> linkHandler;
01658   if (mPresShell) {
01659     if (mPresContext) {
01660       // Save the linkhandler (nsPresShell::Destroy removes it from
01661       // mPresContext).
01662       linkHandler = mPresContext->GetLinkHandler();
01663     }
01664 
01665     mPresShell->EndObservingDocument();
01666     mPresShell->Destroy();
01667 
01668     mPresShell = nsnull;
01669   }
01670 
01671   // And if we're already given a prescontext...
01672   if (mPresContext) {
01673     // If we had a linkHandler and it got removed, put it back.
01674     if (linkHandler) {
01675       mPresContext->SetLinkHandler(linkHandler);
01676     }
01677 
01678     // Create a new style set for the document
01679 
01680     nsStyleSet *styleSet;
01681     rv = CreateStyleSet(mDocument, &styleSet);
01682     NS_ENSURE_SUCCESS(rv, rv);
01683 
01684     rv = newDoc->CreateShell(mPresContext, mViewManager, styleSet,
01685                              getter_AddRefs(mPresShell));
01686     if (NS_FAILED(rv)) {
01687       delete styleSet;
01688       return rv;
01689     }
01690 
01691     // We're done creating the style set
01692     styleSet->EndUpdate();
01693 
01694     // The pres shell owns the style set now.
01695     mPresShell->BeginObservingDocument();
01696 
01697     // Register the focus listener on the new document
01698 
01699     nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mDocument, &rv);
01700     NS_WARN_IF_FALSE(erP, "No event receiver in document!");
01701 
01702     if (erP) {
01703       rv = erP->AddEventListenerByIID(mFocusListener,
01704                                       NS_GET_IID(nsIDOMFocusListener));
01705       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
01706     }
01707   }
01708 
01709   return rv;
01710 }
01711 
01712 NS_IMETHODIMP
01713 DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet)
01714 {
01715   NS_ASSERTION(aUAStyleSheet, "unexpected null pointer");
01716   nsCOMPtr<nsICSSStyleSheet> sheet(do_QueryInterface(aUAStyleSheet));
01717   if (sheet) {
01718     nsCOMPtr<nsICSSStyleSheet> newSheet;
01719     sheet->Clone(nsnull, nsnull, nsnull, nsnull, getter_AddRefs(newSheet));
01720     mUAStyleSheet = newSheet;
01721   }
01722   return NS_OK;
01723 }
01724 
01725 NS_IMETHODIMP
01726 DocumentViewerImpl::GetDocument(nsIDocument** aResult)
01727 {
01728   NS_IF_ADDREF(*aResult = mDocument);
01729 
01730   return NS_OK;
01731 }
01732 
01733 NS_IMETHODIMP
01734 DocumentViewerImpl::GetPresShell(nsIPresShell** aResult)
01735 {
01736   NS_IF_ADDREF(*aResult = mPresShell);
01737 
01738   return NS_OK;
01739 }
01740 
01741 NS_IMETHODIMP
01742 DocumentViewerImpl::GetPresContext(nsPresContext** aResult)
01743 {
01744   NS_IF_ADDREF(*aResult = mPresContext);
01745 
01746   return NS_OK;
01747 }
01748 
01749 NS_IMETHODIMP
01750 DocumentViewerImpl::GetBounds(nsRect& aResult)
01751 {
01752   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
01753   NS_PRECONDITION(mWindow, "null window");
01754   if (mWindow) {
01755     mWindow->GetBounds(aResult);
01756   }
01757   else {
01758     aResult.SetRect(0, 0, 0, 0);
01759   }
01760   return NS_OK;
01761 }
01762 
01763 NS_IMETHODIMP
01764 DocumentViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer)
01765 {
01766   *aViewer = mPreviousViewer;
01767   NS_IF_ADDREF(*aViewer);
01768   return NS_OK;
01769 }
01770 
01771 NS_IMETHODIMP
01772 DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer)
01773 {
01774   // NOTE:  |Show| sets |mPreviousViewer| to null without calling this
01775   // function.
01776 
01777   if (aViewer) {
01778     NS_ASSERTION(!mPreviousViewer,
01779                  "can't set previous viewer when there already is one");
01780 
01781     // In a multiple chaining situation (which occurs when running a thrashing
01782     // test like i-bench or jrgm's tests with no delay), we can build up a
01783     // whole chain of viewers.  In order to avoid this, we always set our previous
01784     // viewer to the MOST previous viewer in the chain, and then dump the intermediate
01785     // link from the chain.  This ensures that at most only 2 documents are alive
01786     // and undestroyed at any given time (the one that is showing and the one that
01787     // is loading with painting suppressed).
01788     // It's very important that if this ever gets changed the code
01789     // before the RestorePresentation call in nsDocShell::InternalLoad
01790     // be changed accordingly.
01791     nsCOMPtr<nsIContentViewer> prevViewer;
01792     aViewer->GetPreviousViewer(getter_AddRefs(prevViewer));
01793     if (prevViewer) {
01794       aViewer->SetPreviousViewer(nsnull);
01795       aViewer->Destroy();
01796       return SetPreviousViewer(prevViewer);
01797     }
01798   }
01799 
01800   mPreviousViewer = aViewer;
01801   return NS_OK;
01802 }
01803 
01804 NS_IMETHODIMP
01805 DocumentViewerImpl::SetBounds(const nsRect& aBounds)
01806 {
01807   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
01808 
01809   if (mWindow) {
01810     // Don't have the widget repaint. Layout will generate repaint requests
01811     // during reflow
01812     mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height,
01813                     PR_FALSE);
01814   }
01815 
01816   // If there's a previous viewer, it's the one that's actually showing,
01817   // so be sure to resize it as well so it paints over the right area.
01818   // This may slow down the performance of the new page load, but resize
01819   // during load is also probably a relatively unusual condition
01820   // relating to things being hidden while something is loaded.  It so
01821   // happens that Firefox does this a good bit with its infobar, and it
01822   // looks ugly if we don't do this.
01823   if (mPreviousViewer)
01824     mPreviousViewer->SetBounds(aBounds);
01825 
01826   return NS_OK;
01827 }
01828 
01829 NS_IMETHODIMP
01830 DocumentViewerImpl::Move(PRInt32 aX, PRInt32 aY)
01831 {
01832   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
01833   NS_PRECONDITION(mWindow, "null window");
01834   if (mWindow) {
01835     mWindow->Move(aX, aY);
01836   }
01837   return NS_OK;
01838 }
01839 
01840 NS_IMETHODIMP
01841 DocumentViewerImpl::Show(void)
01842 {
01843   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
01844 
01845   // We don't need the previous viewer anymore since we're not
01846   // displaying it.
01847   if (mPreviousViewer) {
01848     // This little dance *may* only be to keep
01849     // PresShell::EndObservingDocument happy, but I'm not sure.
01850     nsCOMPtr<nsIContentViewer> prevViewer(mPreviousViewer);
01851     mPreviousViewer = nsnull;
01852     prevViewer->Destroy();
01853 
01854     // Make sure we don't have too many cached ContentViewers
01855     nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryReferent(mContainer);
01856     if (treeItem) {
01857       // We need to find the root DocShell since only that object has an
01858       // SHistory and we need the SHistory to evict content viewers
01859       nsCOMPtr<nsIDocShellTreeItem> root;
01860       treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
01861       nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
01862       nsCOMPtr<nsISHistory> history;
01863       webNav->GetSessionHistory(getter_AddRefs(history));
01864       nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
01865       if (historyInt) {
01866         PRInt32 prevIndex,loadedIndex;
01867         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
01868         docShell->GetPreviousTransIndex(&prevIndex);
01869         docShell->GetLoadedTransIndex(&loadedIndex);
01870 #ifdef DEBUG_PAGE_CACHE
01871         printf("About to evict content viewers: prev=%d, loaded=%d\n",
01872                prevIndex, loadedIndex);
01873 #endif
01874         historyInt->EvictContentViewers(prevIndex, loadedIndex);
01875       }
01876     }
01877   }
01878 
01879   if (mWindow) {
01880     mWindow->Show(PR_TRUE);
01881   }
01882 
01883   if (mDocument && !mPresShell && !mWindow) {
01884     nsresult rv;
01885 
01886     nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
01887     NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);
01888 
01889     base_win->GetParentWidget(&mParentWidget);
01890     NS_ENSURE_TRUE(mParentWidget, NS_ERROR_UNEXPECTED);
01891 
01892     mDeviceContext = dont_AddRef(mParentWidget->GetDeviceContext());
01893 
01894 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
01895     // Clear PrintPreview Alternate Device
01896     if (mDeviceContext) {
01897       mDeviceContext->SetAltDevice(nsnull);
01898     }
01899 #endif
01900 
01901     // Create presentation context
01902     if (GetIsCreatingPrintPreview()) {
01903       NS_ERROR("Whoa, we should not get here!");
01904 
01905       return NS_ERROR_UNEXPECTED;
01906     }
01907 
01908     NS_ASSERTION(!mPresContext, "Shouldn't have a prescontext if we have no shell!");
01909     mPresContext = new nsPresContext(nsPresContext::eContext_Galley);
01910     NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
01911 
01912     rv = mPresContext->Init(mDeviceContext);
01913     if (NS_FAILED(rv)) {
01914       mPresContext = nsnull;
01915       return rv;
01916     }
01917 
01918     nsRect tbounds;
01919     mParentWidget->GetBounds(tbounds);
01920 
01921     rv = MakeWindow(mParentWidget, tbounds);
01922     if (NS_FAILED(rv))
01923       return rv;
01924 
01925     if (mPresContext && base_win) {
01926       nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win));
01927 
01928       if (linkHandler) {
01929         mPresContext->SetLinkHandler(linkHandler);
01930       }
01931 
01932       mPresContext->SetContainer(base_win);
01933     }
01934 
01935     if (mPresContext) {
01936       Hide();
01937 
01938       rv = InitPresentationStuff(PR_TRUE);
01939     }
01940 
01941     // If we get here the document load has already started and the
01942     // window is shown because some JS on the page caused it to be
01943     // shown...
01944 
01945     nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
01946     mPresShell->UnsuppressPainting();
01947   }
01948 
01949   return NS_OK;
01950 }
01951 
01952 NS_IMETHODIMP
01953 DocumentViewerImpl::Hide(void)
01954 {
01955   PRBool is_in_print_mode = PR_FALSE;
01956 
01957   GetDoingPrint(&is_in_print_mode);
01958 
01959   if (is_in_print_mode) {
01960     // If we, or one of our parents, is in print mode it means we're
01961     // right now returning from print and the layout frame that was
01962     // created for this document is being destroyed. In such a case we
01963     // ignore the Hide() call.
01964     // XXX The above statement is a lie. We do not check our parents.
01965     // in fact it always returns false for subdocuments.
01966     return NS_OK;
01967   }
01968 
01969   GetDoingPrintPreview(&is_in_print_mode);
01970 
01971   if (is_in_print_mode) {
01972     // If we, or one of our parents, is in print preview mode it means
01973     // we're right now returning from print preview and the layout
01974     // frame that was created for this document is being destroyed. In
01975     // such a case we ignore the Hide() call.
01976     // XXX The above statement is a lie. We do not check our parents.
01977     // in fact it always returns false for subdocuments.
01978     return NS_OK;
01979   }
01980 
01981   NS_PRECONDITION(mWindow, "null window");
01982   if (mWindow) {
01983     mWindow->Show(PR_FALSE);
01984   }
01985 
01986   if (!mPresShell || GetIsPrintPreview()) {
01987     return NS_OK;
01988   }
01989 
01990   NS_ASSERTION(mPresContext, "Can't have a presshell and no prescontext!");
01991 
01992   // Avoid leaking the old viewer.
01993   if (mPreviousViewer) {
01994     mPreviousViewer->Destroy();
01995     mPreviousViewer = nsnull;
01996   }
01997 
01998   if (mIsSticky) {
01999     // This window is sticky, that means that it might be shown again
02000     // and we don't want the presshell n' all that to be thrown away
02001     // just because the window is hidden.
02002 
02003     return NS_OK;
02004   }
02005 
02006   if (mDeviceContext) {
02007     mDeviceContext->FlushFontCache();
02008   }
02009 
02010   // Break circular reference (or something)
02011   mPresShell->EndObservingDocument();
02012   nsCOMPtr<nsISelection> selection;
02013 
02014   GetDocumentSelection(getter_AddRefs(selection));
02015 
02016   nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
02017 
02018   if (selPrivate && mSelectionListener) {
02019     selPrivate->RemoveSelectionListener(mSelectionListener);
02020   }
02021 
02022 #ifdef MOZ_XUL
02023   nsCOMPtr<nsIXULDocument> xul_doc(do_QueryInterface(mDocument));
02024 
02025   if (xul_doc) {
02026     xul_doc->OnHide();
02027   }
02028 #endif
02029 
02030   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
02031   if (docShell) {
02032     PRBool saveLayoutState = PR_FALSE;
02033     docShell->GetShouldSaveLayoutState(&saveLayoutState);
02034     if (saveLayoutState) {
02035       nsCOMPtr<nsILayoutHistoryState> layoutState;
02036       mPresShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
02037     }
02038   }
02039 
02040   nsCOMPtr<nsIPresShell> tempShell = mPresShell;
02041   nsCOMPtr<nsPresContext> tempContext = mPresContext;
02042 
02043   mPresShell     = nsnull;
02044   mPresContext   = nsnull;
02045 
02046   tempShell->Destroy();
02047 
02048   // Clear weak refs
02049   tempContext->SetContainer(nsnull);
02050   tempContext->SetLinkHandler(nsnull);                             
02051 
02052   mViewManager   = nsnull;
02053   mWindow        = nsnull;
02054   mDeviceContext = nsnull;
02055   mParentWidget  = nsnull;
02056 
02057   nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
02058 
02059   if (base_win) {
02060     base_win->SetParentWidget(nsnull);
02061   }
02062 
02063   return NS_OK;
02064 }
02065 NS_IMETHODIMP
02066 DocumentViewerImpl::SetEnableRendering(PRBool aOn)
02067 {
02068   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
02069   mEnableRendering = aOn;
02070   if (mViewManager) {
02071     if (aOn) {
02072       mViewManager->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
02073       nsIView* view;
02074       mViewManager->GetRootView(view);   // views are not refCounted
02075       if (view) {
02076         mViewManager->UpdateView(view, NS_VMREFRESH_IMMEDIATE);
02077       }
02078     }
02079     else {
02080       mViewManager->DisableRefresh();
02081     }
02082   }
02083   return NS_OK;
02084 }
02085 
02086 NS_IMETHODIMP
02087 DocumentViewerImpl::GetSticky(PRBool *aSticky)
02088 {
02089   *aSticky = mIsSticky;
02090 
02091   return NS_OK;
02092 }
02093 
02094 NS_IMETHODIMP
02095 DocumentViewerImpl::SetSticky(PRBool aSticky)
02096 {
02097   mIsSticky = aSticky;
02098 
02099   return NS_OK;
02100 }
02101 
02102 NS_IMETHODIMP
02103 DocumentViewerImpl::GetEnableRendering(PRBool* aResult)
02104 {
02105   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
02106   NS_PRECONDITION(nsnull != aResult, "null OUT ptr");
02107   if (aResult) {
02108     *aResult = mEnableRendering;
02109   }
02110   return NS_OK;
02111 }
02112 
02113 NS_IMETHODIMP
02114 DocumentViewerImpl::RequestWindowClose(PRBool* aCanClose)
02115 {
02116 #ifdef NS_PRINTING
02117   if (mPrintIsPending || (mPrintEngine && mPrintEngine->GetIsPrinting())) {
02118     *aCanClose = PR_FALSE;
02119     mDeferredWindowClose = PR_TRUE;
02120   } else
02121 #endif
02122     *aCanClose = PR_TRUE;
02123 
02124   return NS_OK;
02125 }
02126 
02127 NS_DEFINE_CID(kCSSLoaderCID, NS_CSS_LOADER_CID);
02128 
02129 PR_STATIC_CALLBACK(PRBool)
02130 AppendAgentSheet(nsIStyleSheet *aSheet, void *aData)
02131 {
02132   nsStyleSet *styleSet = NS_STATIC_CAST(nsStyleSet*, aData);
02133   styleSet->AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet);
02134   return PR_TRUE;
02135 }
02136 
02137 PR_STATIC_CALLBACK(PRBool)
02138 PrependUserSheet(nsIStyleSheet *aSheet, void *aData)
02139 {
02140   nsStyleSet *styleSet = NS_STATIC_CAST(nsStyleSet*, aData);
02141   styleSet->PrependStyleSheet(nsStyleSet::eUserSheet, aSheet);
02142   return PR_TRUE;
02143 }
02144 
02145 nsresult
02146 DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
02147                                    nsStyleSet** aStyleSet)
02148 {
02149   // this should eventually get expanded to allow for creating
02150   // different sets for different media
02151   if (!mUAStyleSheet) {
02152     NS_WARNING("unable to load UA style sheet");
02153   }
02154 
02155   nsStyleSet *styleSet = new nsStyleSet();
02156   if (!styleSet) {
02157     return NS_ERROR_OUT_OF_MEMORY;
02158   }
02159 
02160   styleSet->BeginUpdate();
02161   
02162   // The document will fill in the document sheets when we create the presshell
02163   
02164   // Handle the user sheets.
02165   nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
02166   PRInt32 shellType;
02167   docShell->GetItemType(&shellType);
02168   nsICSSStyleSheet* sheet = nsnull;
02169   if (shellType == nsIDocShellTreeItem::typeChrome) {
02170     sheet = nsLayoutStylesheetCache::UserChromeSheet();
02171   }
02172   else {
02173     sheet = nsLayoutStylesheetCache::UserContentSheet();
02174   }
02175 
02176   if (sheet)
02177     styleSet->AppendStyleSheet(nsStyleSet::eUserSheet, sheet);
02178 
02179   // Append chrome sheets (scrollbars + forms).
02180   PRBool shouldOverride = PR_FALSE;
02181   nsCOMPtr<nsIDocShell> ds(do_QueryInterface(docShell));
02182   nsCOMPtr<nsIChromeEventHandler> chromeHandler;
02183   nsCOMPtr<nsICSSLoader> cssLoader( do_GetService(kCSSLoaderCID) );
02184   nsCOMPtr<nsIURI> uri;
02185   nsCOMPtr<nsICSSStyleSheet> csssheet;
02186 
02187   ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
02188   if (chromeHandler) {
02189     nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
02190     nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
02191     if (elt && content) {
02192       nsCOMPtr<nsIURI> baseURI = content->GetBaseURI();
02193 
02194       nsAutoString sheets;
02195       elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
02196       if (!sheets.IsEmpty() && baseURI) {
02197         char *str = ToNewCString(sheets);
02198         char *newStr = str;
02199         char *token;
02200         while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) {
02201           NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nsnull,
02202                     baseURI);
02203           if (!uri) continue;
02204 
02205           cssLoader->LoadAgentSheet(uri, getter_AddRefs(csssheet));
02206           if (!sheet) continue;
02207 
02208           styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, csssheet);
02209           shouldOverride = PR_TRUE;
02210         }
02211         nsMemory::Free(str);
02212       }
02213     }
02214   }
02215 
02216   if (!shouldOverride) {
02217     sheet = nsLayoutStylesheetCache::ScrollbarsSheet();
02218     if (sheet) {
02219       styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
02220     }
02221   }
02222 
02223   sheet = nsLayoutStylesheetCache::FormsSheet();
02224   if (sheet) {
02225     styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
02226   }
02227 
02228   if (mUAStyleSheet) {
02229     styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, mUAStyleSheet);
02230   }
02231 
02232   nsCOMPtr<nsIStyleSheetService> dummy =
02233     do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);
02234 
02235   nsStyleSheetService *sheetService = nsStyleSheetService::gInstance;
02236   if (sheetService) {
02237     sheetService->AgentStyleSheets()->EnumerateForwards(AppendAgentSheet,
02238                                                         styleSet);
02239     sheetService->UserStyleSheets()->EnumerateBackwards(PrependUserSheet,
02240                                                         styleSet);
02241   }
02242 
02243   // Caller will handle calling EndUpdate, per contract.
02244   *aStyleSet = styleSet;
02245   return NS_OK;
02246 }
02247 
02248 NS_IMETHODIMP
02249 DocumentViewerImpl::ClearHistoryEntry()
02250 {
02251   mSHEntry = nsnull;
02252   return NS_OK;
02253 }
02254 
02255 //-------------------------------------------------------
02256 
02257 nsresult
02258 DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget,
02259                                const nsRect& aBounds)
02260 {
02261   nsresult rv;
02262 
02263   mViewManager = do_CreateInstance(kViewManagerCID, &rv);
02264   if (NS_FAILED(rv))
02265     return rv;
02266 
02267   nsIDeviceContext *dx = mPresContext->DeviceContext();
02268 
02269   nsRect tbounds = aBounds;
02270   float p2t;
02271   p2t = mPresContext->PixelsToTwips();
02272   tbounds *= p2t;
02273 
02274    // Initialize the view manager with an offset. This allows the viewmanager
02275    // to manage a coordinate space offset from (0,0)
02276   rv = mViewManager->Init(dx);
02277   if (NS_FAILED(rv))
02278     return rv;
02279 
02280   // Reset the bounds offset so the root view is set to 0,0. The
02281   // offset is specified in nsIViewManager::Init above.
02282   // Besides, layout will reset the root view to (0,0) during reflow,
02283   // so changing it to 0,0 eliminates placing the root view in the
02284   // wrong place initially.
02285   tbounds.x = 0;
02286   tbounds.y = 0;
02287 
02288   // Create a child window of the parent that is our "root view/window"
02289   // if aParentWidget has a view, we'll hook our view manager up to its view tree
02290   nsIView* containerView = nsView::GetViewFor(aParentWidget);
02291 
02292   if (containerView) {
02293     // see if the containerView has already been hooked into a foreign view manager hierarchy
02294     // if it has, then we have to hook into the hierarchy too otherwise bad things will happen.
02295     nsIViewManager* containerVM = containerView->GetViewManager();
02296     nsIView* pView = containerView;
02297     do {
02298       pView = pView->GetParent();
02299     } while (pView && pView->GetViewManager() == containerVM);
02300 
02301     if (!pView) {
02302       // OK, so the container is not already hooked up into a foreign view manager hierarchy.
02303       // That means we can choose not to hook ourselves up.
02304       //
02305       // If the parent container is a chrome shell then we won't hook into its view
02306       // tree. This will improve performance a little bit (especially given scrolling/painting perf bugs)
02307       // but is really just for peace of mind. This check can be removed if we want to support fancy
02308       // chrome effects like transparent controls floating over content, transparent Web browsers, and
02309       // things like that, and the perf bugs are fixed.
02310       nsCOMPtr<nsIDocShellTreeItem> container(do_QueryReferent(mContainer));
02311       nsCOMPtr<nsIDocShellTreeItem> parentContainer;
02312       PRInt32 itemType;
02313       if (nsnull == container
02314           || NS_FAILED(container->GetParent(getter_AddRefs(parentContainer)))
02315           || nsnull == parentContainer
02316           || NS_FAILED(parentContainer->GetItemType(&itemType))
02317           || itemType != nsIDocShellTreeItem::typeContent) {
02318         containerView = nsnull;
02319       }
02320     }
02321   }
02322 
02323   // Create a view
02324   nsIView* view = mViewManager->CreateView(tbounds, containerView);
02325   if (!view)
02326     return NS_ERROR_OUT_OF_MEMORY;
02327 
02328   // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
02329   // otherwise the view will find its own parent widget and "do the right thing" to
02330   // establish a parent/child widget relationship
02331   rv = view->CreateWidget(kWidgetCID, nsnull,
02332                           containerView != nsnull ? nsnull : aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
02333                           PR_TRUE, PR_FALSE);
02334   if (NS_FAILED(rv))
02335     return rv;
02336 
02337   // Setup hierarchical relationship in view manager
02338   mViewManager->SetRootView(view);
02339 
02340   mWindow = view->GetWidget();
02341 
02342   // This SetFocus is necessary so the Arrow Key and Page Key events
02343   // go to the scrolled view as soon as the Window is created instead of going to
02344   // the browser window (this enables keyboard scrolling of the document)
02345   // mWindow->SetFocus();
02346 
02347   return rv;
02348 }
02349 
02350 // Return the selection for the document. Note that text fields have their
02351 // own selection, which cannot be accessed with this method. Use
02352 // mPresShell->GetSelectionForCopy() instead.
02353 nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection,
02354                                                   nsIPresShell *aPresShell)
02355 {
02356   if (!aPresShell) {
02357     if (!mPresShell) {
02358       return NS_ERROR_NOT_INITIALIZED;
02359     }
02360     aPresShell = mPresShell;
02361   }
02362   if (!aSelection)
02363     return NS_ERROR_NULL_POINTER;
02364   if (!aPresShell)
02365     return NS_ERROR_NULL_POINTER;
02366 
02367   nsCOMPtr<nsISelectionController> selcon;
02368   selcon = do_QueryInterface(aPresShell);
02369   if (selcon)
02370     return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
02371                                 aSelection);
02372   return NS_ERROR_FAILURE;
02373 }
02374 
02375 NS_IMETHODIMP
02376 DocumentViewerImpl::CreateDocumentViewerUsing(nsPresContext* aPresContext,
02377                                               nsIDocumentViewer** aResult)
02378 {
02379   if (!mDocument) {
02380     // XXX better error
02381     return NS_ERROR_NULL_POINTER;
02382   }
02383   if (!aPresContext) {
02384     return NS_ERROR_NULL_POINTER;
02385   }
02386 
02387   // Create new viewer
02388   DocumentViewerImpl* viewer = new DocumentViewerImpl(aPresContext);
02389   if (!viewer) {
02390     return NS_ERROR_OUT_OF_MEMORY;
02391   }
02392   NS_ADDREF(viewer);
02393 
02394   // XXX make sure the ua style sheet is used (for now; need to be
02395   // able to specify an alternate)
02396   viewer->SetUAStyleSheet(mUAStyleSheet);
02397 
02398   // Bind the new viewer to the old document
02399   nsresult rv = viewer->LoadStart(mDocument);
02400 
02401   *aResult = viewer;
02402 
02403   return rv;
02404 }
02405 
02406 #ifdef XP_MAC
02407 #pragma mark -
02408 #endif
02409 
02410 /* ========================================================================================
02411  * nsIContentViewerEdit
02412  * ======================================================================================== */
02413 
02414 NS_IMETHODIMP DocumentViewerImpl::Search()
02415 {
02416   NS_ASSERTION(0, "NOT IMPLEMENTED");
02417   return NS_ERROR_NOT_IMPLEMENTED;
02418 }
02419 
02420 NS_IMETHODIMP DocumentViewerImpl::GetSearchable(PRBool *aSearchable)
02421 {
02422   NS_ASSERTION(0, "NOT IMPLEMENTED");
02423   return NS_ERROR_NOT_IMPLEMENTED;
02424 }
02425 
02426 NS_IMETHODIMP DocumentViewerImpl::ClearSelection()
02427 {
02428   nsresult rv;
02429   nsCOMPtr<nsISelection> selection;
02430 
02431   // use mPresShell->GetSelectionForCopy() ?
02432   rv = GetDocumentSelection(getter_AddRefs(selection));
02433   if (NS_FAILED(rv)) return rv;
02434 
02435   return selection->CollapseToStart();
02436 }
02437 
02438 NS_IMETHODIMP DocumentViewerImpl::SelectAll()
02439 {
02440   // XXX this is a temporary implementation copied from nsWebShell
02441   // for now. I think nsDocument and friends should have some helper
02442   // functions to make this easier.
02443   nsCOMPtr<nsISelection> selection;
02444   nsresult rv;
02445 
02446   // use mPresShell->GetSelectionForCopy() ?
02447   rv = GetDocumentSelection(getter_AddRefs(selection));
02448   if (NS_FAILED(rv)) return rv;
02449 
02450   nsCOMPtr<nsIDOMHTMLDocument> htmldoc = do_QueryInterface(mDocument);
02451   nsCOMPtr<nsIDOMNode> bodyNode;
02452 
02453   if (htmldoc)
02454   {
02455     nsCOMPtr<nsIDOMHTMLElement>bodyElement;
02456     rv = htmldoc->GetBody(getter_AddRefs(bodyElement));
02457     if (NS_FAILED(rv) || !bodyElement) return rv;
02458 
02459     bodyNode = do_QueryInterface(bodyElement);
02460   }
02461   else if (mDocument)
02462   {
02463     bodyNode = do_QueryInterface(mDocument->GetRootContent());
02464   }
02465   if (!bodyNode) return NS_ERROR_FAILURE;
02466 
02467   rv = selection->RemoveAllRanges();
02468   if (NS_FAILED(rv)) return rv;
02469 
02470   rv = selection->SelectAllChildren(bodyNode);
02471   return rv;
02472 }
02473 
02474 NS_IMETHODIMP DocumentViewerImpl::CopySelection()
02475 {
02476   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
02477   return mPresShell->DoCopy();
02478 }
02479 
02480 NS_IMETHODIMP DocumentViewerImpl::CopyLinkLocation()
02481 {
02482   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
02483   nsCOMPtr<nsIDOMNode> node;
02484   GetPopupLinkNode(getter_AddRefs(node));
02485   // make noise if we're not in a link
02486   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
02487 
02488   nsAutoString locationText;
02489   nsresult rv = mPresShell->GetLinkLocation(node, locationText);
02490   NS_ENSURE_SUCCESS(rv, rv);
02491 
02492   nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
02493   NS_ENSURE_SUCCESS(rv, rv);
02494 
02495   // copy the href onto the clipboard
02496   return clipboard->CopyString(locationText);
02497 }
02498 
02499 NS_IMETHODIMP DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags)
02500 {
02501   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
02502   nsCOMPtr<nsIImageLoadingContent> node;
02503   GetPopupImageNode(getter_AddRefs(node));
02504   // make noise if we're not in an image
02505   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
02506 
02507   return nsCopySupport::ImageCopy(node, aCopyFlags);
02508 }
02509 
02510 NS_IMETHODIMP DocumentViewerImpl::GetCopyable(PRBool *aCopyable)
02511 {
02512   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
02513 
02514   nsCOMPtr<nsISelection> selection;
02515   nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(selection));
02516   if (NS_FAILED(rv)) return rv;
02517 
02518   PRBool isCollapsed;
02519   selection->GetIsCollapsed(&isCollapsed);
02520 
02521   *aCopyable = !isCollapsed;
02522   return NS_OK;
02523 }
02524 
02525 NS_IMETHODIMP DocumentViewerImpl::CutSelection()
02526 {
02527   NS_ASSERTION(0, "NOT IMPLEMENTED");
02528   return NS_ERROR_NOT_IMPLEMENTED;
02529 }
02530 
02531 NS_IMETHODIMP DocumentViewerImpl::GetCutable(PRBool *aCutable)
02532 {
02533   *aCutable = PR_FALSE;  // mm, will this ever be called for an editable document?
02534   return NS_OK;
02535 }
02536 
02537 NS_IMETHODIMP DocumentViewerImpl::Paste()
02538 {
02539   NS_ASSERTION(0, "NOT IMPLEMENTED");
02540   return NS_ERROR_NOT_IMPLEMENTED;
02541 }
02542 
02543 NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable)
02544 {
02545   *aPasteable = PR_FALSE;
02546   return NS_OK;
02547 }
02548 
02549 /* AString getContents (in string mimeType, in boolean selectionOnly); */
02550 NS_IMETHODIMP DocumentViewerImpl::GetContents(const char *mimeType, PRBool selectionOnly, nsAString& aOutValue)
02551 {
02552   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
02553   return mPresShell->DoGetContents(nsDependentCString(mimeType), 0, selectionOnly, aOutValue);
02554 }
02555 
02556 /* readonly attribute boolean canGetContents; */
02557 NS_IMETHODIMP DocumentViewerImpl::GetCanGetContents(PRBool *aCanGetContents)
02558 {
02559   return GetCopyable(aCanGetContents);
02560 }
02561 
02562 #ifdef XP_MAC
02563 #pragma mark -
02564 #endif
02565 
02566 /* ========================================================================================
02567  * nsIContentViewerFile
02568  * ======================================================================================== */
02573 NS_IMETHODIMP
02574 DocumentViewerImpl::Print(PRBool            aSilent,
02575                           FILE *            aDebugFile,
02576                           nsIPrintSettings* aPrintSettings)
02577 {
02578 #ifdef NS_PRINTING
02579   nsCOMPtr<nsIPrintSettings> printSettings;
02580 
02581 #ifdef NS_DEBUG
02582   nsresult rv = NS_ERROR_FAILURE;
02583 
02584   mDebugFile = aDebugFile;
02585   // if they don't pass in a PrintSettings, then make one
02586   // it will have all the default values
02587   printSettings = aPrintSettings;
02588   nsCOMPtr<nsIPrintOptions> printOptions = do_GetService(sPrintOptionsContractID, &rv);
02589   if (NS_SUCCEEDED(rv)) {
02590     // if they don't pass in a PrintSettings, then make one
02591     if (printSettings == nsnull) {
02592       printOptions->CreatePrintSettings(getter_AddRefs(printSettings));
02593     }
02594     NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!");
02595   }
02596   if (printSettings) printSettings->SetPrintSilent(aSilent);
02597   if (printSettings) printSettings->SetShowPrintProgress(PR_FALSE);
02598 #endif
02599 
02600 
02601   return Print(printSettings, nsnull);
02602 #else
02603   return NS_ERROR_FAILURE;
02604 #endif
02605 }
02606 
02607 /* [noscript] void printWithParent (in nsIDOMWindowInternal aParentWin, in nsIPrintSettings aThePrintSettings, in nsIWebProgressListener aWPListener); */
02608 NS_IMETHODIMP 
02609 DocumentViewerImpl::PrintWithParent(nsIDOMWindowInternal *aParentWin, nsIPrintSettings *aThePrintSettings, nsIWebProgressListener *aWPListener)
02610 {
02611 #ifdef NS_PRINTING
02612   mDialogParentWin = aParentWin;
02613   return Print(aThePrintSettings, aWPListener);
02614 #else
02615   return NS_ERROR_FAILURE;
02616 #endif
02617 }
02618 
02619 // nsIContentViewerFile interface
02620 NS_IMETHODIMP
02621 DocumentViewerImpl::GetPrintable(PRBool *aPrintable)
02622 {
02623   NS_ENSURE_ARG_POINTER(aPrintable);
02624 
02625   *aPrintable = !GetIsPrinting();
02626 
02627   return NS_OK;
02628 }
02629 
02630 #ifdef XP_MAC
02631 #pragma mark -
02632 #endif
02633 
02634 //*****************************************************************************
02635 // nsIMarkupDocumentViewer
02636 //*****************************************************************************
02637 
02638 NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
02639 {
02640    NS_ENSURE_ARG(aNode);
02641    NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
02642    nsCOMPtr<nsIPresShell> presShell;
02643    NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE);
02644 
02645    // Get the nsIContent interface, because that's what we need to
02646    // get the primary frame
02647 
02648    nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
02649    NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
02650 
02651    // Get the primary frame
02652    nsIFrame* frame;  // Remember Frames aren't ref-counted.  They are in their
02653                      // own special little world.
02654 
02655    NS_ENSURE_SUCCESS(presShell->GetPrimaryFrameFor(content, &frame),
02656       NS_ERROR_FAILURE);
02657 
02658    // tell the pres shell to scroll to the frame
02659    NS_ENSURE_SUCCESS(presShell->ScrollFrameIntoView(frame,
02660                                                     NS_PRESSHELL_SCROLL_TOP,
02661                                                     NS_PRESSHELL_SCROLL_ANYWHERE),
02662                      NS_ERROR_FAILURE);
02663    return NS_OK;
02664 }
02665 
02666 void
02667 DocumentViewerImpl::CallChildren(CallChildFunc aFunc, void* aClosure)
02668 {
02669   nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
02670   if (docShellNode)
02671   {
02672     PRInt32 i;
02673     PRInt32 n;
02674     docShellNode->GetChildCount(&n);
02675     for (i=0; i < n; i++)
02676     {
02677       nsCOMPtr<nsIDocShellTreeItem> child;
02678       docShellNode->GetChildAt(i, getter_AddRefs(child));
02679       nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
02680       NS_ASSERTION(childAsShell, "null child in docshell");
02681       if (childAsShell)
02682       {
02683         nsCOMPtr<nsIContentViewer> childCV;
02684         childAsShell->GetContentViewer(getter_AddRefs(childCV));
02685         if (childCV)
02686         {
02687           nsCOMPtr<nsIMarkupDocumentViewer> markupCV = do_QueryInterface(childCV);
02688           if (markupCV) {
02689             (*aFunc)(markupCV, aClosure);
02690           }
02691         }
02692       }
02693     }
02694   }
02695 }
02696 
02697 struct TextZoomInfo
02698 {
02699   float mTextZoom;
02700 };
02701 
02702 static void
02703 SetChildTextZoom(nsIMarkupDocumentViewer* aChild, void* aClosure)
02704 {
02705   struct TextZoomInfo* textZoomInfo = (struct TextZoomInfo*) aClosure;
02706   aChild->SetTextZoom(textZoomInfo->mTextZoom);
02707 }
02708 
02709 NS_IMETHODIMP
02710 DocumentViewerImpl::SetTextZoom(float aTextZoom)
02711 {
02712   if (mViewManager) {
02713     mViewManager->BeginUpdateViewBatch();
02714   }
02715       
02716   // Set the text zoom on all children of mContainer (even if our zoom didn't
02717   // change, our children's zoom may be different, though it would be unusual).
02718   // Do this first, in case kids are auto-sizing and post reflow commands on
02719   // our presshell (which should be subsumed into our own style change reflow).
02720   struct TextZoomInfo textZoomInfo = { aTextZoom };
02721   CallChildren(SetChildTextZoom, &textZoomInfo);
02722 
02723   // Now change our own zoom
02724   if (mPresContext && aTextZoom != mPresContext->TextZoom()) {
02725       mPresContext->SetTextZoom(aTextZoom);
02726   }
02727 
02728   if (mViewManager) {
02729     mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
02730   }
02731   
02732   return NS_OK;
02733 }
02734 
02735 NS_IMETHODIMP
02736 DocumentViewerImpl::GetTextZoom(float* aTextZoom)
02737 {
02738   NS_ENSURE_ARG_POINTER(aTextZoom);
02739 
02740   if (mPresContext) {
02741     *aTextZoom = mPresContext->TextZoom();
02742     return NS_OK;
02743   }
02744 
02745   *aTextZoom = 1.0;
02746   return NS_OK;
02747 }
02748 
02749 static void
02750 SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer* aChild, void* aClosure)
02751 {
02752   PRBool styleDisabled  = *NS_STATIC_CAST(PRBool*, aClosure);
02753   aChild->SetAuthorStyleDisabled(styleDisabled);
02754 }
02755 
02756 
02757 NS_IMETHODIMP
02758 DocumentViewerImpl::SetAuthorStyleDisabled(PRBool aStyleDisabled)
02759 {
02760   if (mPresShell) {
02761     mPresShell->SetAuthorStyleDisabled(aStyleDisabled);
02762   }
02763   CallChildren(SetChildAuthorStyleDisabled, &aStyleDisabled);
02764   return NS_OK;
02765 }
02766 
02767 NS_IMETHODIMP
02768 DocumentViewerImpl::GetAuthorStyleDisabled(PRBool* aStyleDisabled)
02769 {
02770   if (mPresShell) {
02771     *aStyleDisabled = mPresShell->GetAuthorStyleDisabled();
02772   } else {
02773     *aStyleDisabled = PR_FALSE;
02774   }
02775   return NS_OK;
02776 }
02777 
02778 NS_IMETHODIMP
02779 DocumentViewerImpl::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
02780 {
02781   NS_ENSURE_STATE(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
02782 
02783   if (mDefaultCharacterSet.IsEmpty())
02784   {
02785     const nsAdoptingString& defCharset =
02786       nsContentUtils::GetLocalizedStringPref("intl.charset.default");
02787 
02788     if (!defCharset.IsEmpty())
02789       LossyCopyUTF16toASCII(defCharset, mDefaultCharacterSet);
02790     else
02791       mDefaultCharacterSet.AssignLiteral("ISO-8859-1");
02792   }
02793   aDefaultCharacterSet = mDefaultCharacterSet;
02794   return NS_OK;
02795 }
02796 
02797 static void
02798 SetChildDefaultCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
02799 {
02800   const nsACString* charset = NS_STATIC_CAST(nsACString*, aClosure);
02801   aChild->SetDefaultCharacterSet(*charset);
02802 }
02803 
02804 NS_IMETHODIMP
02805 DocumentViewerImpl::SetDefaultCharacterSet(const nsACString& aDefaultCharacterSet)
02806 {
02807   mDefaultCharacterSet = aDefaultCharacterSet;  // this does a copy of aDefaultCharacterSet
02808   // now set the default char set on all children of mContainer
02809   CallChildren(SetChildDefaultCharacterSet, (void*) &aDefaultCharacterSet);
02810   return NS_OK;
02811 }
02812 
02813 // XXX: SEMANTIC CHANGE!
02814 //      returns a copy of the string.  Caller is responsible for freeing result
02815 //      using Recycle(aForceCharacterSet)
02816 NS_IMETHODIMP DocumentViewerImpl::GetForceCharacterSet(nsACString& aForceCharacterSet)
02817 {
02818   aForceCharacterSet = mForceCharacterSet;
02819   return NS_OK;
02820 }
02821 
02822 static void
02823 SetChildForceCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
02824 {
02825   const nsACString* charset = NS_STATIC_CAST(nsACString*, aClosure);
02826   aChild->SetForceCharacterSet(*charset);
02827 }
02828 
02829 NS_IMETHODIMP
02830 DocumentViewerImpl::SetForceCharacterSet(const nsACString& aForceCharacterSet)
02831 {
02832   mForceCharacterSet = aForceCharacterSet;
02833   // now set the force char set on all children of mContainer
02834   CallChildren(SetChildForceCharacterSet, (void*) &aForceCharacterSet);
02835   return NS_OK;
02836 }
02837 
02838 // XXX: SEMANTIC CHANGE!
02839 //      returns a copy of the string.  Caller is responsible for freeing result
02840 //      using Recycle(aHintCharacterSet)
02841 NS_IMETHODIMP DocumentViewerImpl::GetHintCharacterSet(nsACString& aHintCharacterSet)
02842 {
02843 
02844   if(kCharsetUninitialized == mHintCharsetSource) {
02845     aHintCharacterSet.Truncate();
02846   } else {
02847     aHintCharacterSet = mHintCharset;
02848     // this can't possibly be right.  we can't set a value just because somebody got a related value!
02849     //mHintCharsetSource = kCharsetUninitialized;
02850   }
02851   return NS_OK;
02852 }
02853 
02854 NS_IMETHODIMP DocumentViewerImpl::GetHintCharacterSetSource(PRInt32 *aHintCharacterSetSource)
02855 {
02856   NS_ENSURE_ARG_POINTER(aHintCharacterSetSource);
02857 
02858   *aHintCharacterSetSource = mHintCharsetSource;
02859   return NS_OK;
02860 }
02861 
02862 
02863 NS_IMETHODIMP DocumentViewerImpl::GetPrevDocCharacterSet(nsACString& aPrevDocCharacterSet)
02864 {
02865   aPrevDocCharacterSet = mPrevDocCharacterSet;
02866 
02867   return NS_OK;
02868 }
02869 
02870 static void
02871 SetChildPrevDocCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
02872 {
02873   const nsACString* charset = NS_STATIC_CAST(nsACString*, aClosure);
02874   aChild->SetPrevDocCharacterSet(*charset);
02875 }
02876 
02877 
02878 NS_IMETHODIMP
02879 DocumentViewerImpl::SetPrevDocCharacterSet(const nsACString& aPrevDocCharacterSet)
02880 {
02881   mPrevDocCharacterSet = aPrevDocCharacterSet;  
02882   CallChildren(SetChildPrevDocCharacterSet, (void*) &aPrevDocCharacterSet);
02883   return NS_OK;
02884 }
02885 
02886 
02887 static void
02888 SetChildHintCharacterSetSource(nsIMarkupDocumentViewer* aChild, void* aClosure)
02889 {
02890   aChild->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure));
02891 }
02892 
02893 NS_IMETHODIMP
02894 DocumentViewerImpl::SetHintCharacterSetSource(PRInt32 aHintCharacterSetSource)
02895 {
02896   mHintCharsetSource = aHintCharacterSetSource;
02897   // now set the hint char set source on all children of mContainer
02898   CallChildren(SetChildHintCharacterSetSource,
02899                       (void*) aHintCharacterSetSource);
02900   return NS_OK;
02901 }
02902 
02903 static void
02904 SetChildHintCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
02905 {
02906   const nsACString* charset = NS_STATIC_CAST(nsACString*, aClosure);
02907   aChild->SetHintCharacterSet(*charset);
02908 }
02909 
02910 NS_IMETHODIMP
02911 DocumentViewerImpl::SetHintCharacterSet(const nsACString& aHintCharacterSet)
02912 {
02913   mHintCharset = aHintCharacterSet;
02914   // now set the hint char set on all children of mContainer
02915   CallChildren(SetChildHintCharacterSet, (void*) &aHintCharacterSet);
02916   return NS_OK;
02917 }
02918 
02919 static void
02920 SetChildBidiOptions(nsIMarkupDocumentViewer* aChild, void* aClosure)
02921 {
02922   aChild->SetBidiOptions(NS_PTR_TO_INT32(aClosure));
02923 }
02924 
02925 NS_IMETHODIMP DocumentViewerImpl::SetBidiTextDirection(PRUint8 aTextDirection)
02926 {
02927   PRUint32 bidiOptions;
02928 
02929   GetBidiOptions(&bidiOptions);
02930   SET_BIDI_OPTION_DIRECTION(bidiOptions, aTextDirection);
02931   SetBidiOptions(bidiOptions);
02932   return NS_OK;
02933 }
02934 
02935 NS_IMETHODIMP DocumentViewerImpl::GetBidiTextDirection(PRUint8* aTextDirection)
02936 {
02937   PRUint32 bidiOptions;
02938 
02939   if (aTextDirection) {
02940     GetBidiOptions(&bidiOptions);
02941     *aTextDirection = GET_BIDI_OPTION_DIRECTION(bidiOptions);
02942   }
02943   return NS_OK;
02944 }
02945 
02946 NS_IMETHODIMP DocumentViewerImpl::SetBidiTextType(PRUint8 aTextType)
02947 {
02948   PRUint32 bidiOptions;
02949 
02950   GetBidiOptions(&bidiOptions);
02951   SET_BIDI_OPTION_TEXTTYPE(bidiOptions, aTextType);
02952   SetBidiOptions(bidiOptions);
02953   return NS_OK;
02954 }
02955 
02956 NS_IMETHODIMP DocumentViewerImpl::GetBidiTextType(PRUint8* aTextType)
02957 {
02958   PRUint32 bidiOptions;
02959 
02960   if (aTextType) {
02961     GetBidiOptions(&bidiOptions);
02962     *aTextType = GET_BIDI_OPTION_TEXTTYPE(bidiOptions);
02963   }
02964   return NS_OK;
02965 }
02966 
02967 NS_IMETHODIMP DocumentViewerImpl::SetBidiControlsTextMode(PRUint8 aControlsTextMode)
02968 {
02969   PRUint32 bidiOptions;
02970 
02971   GetBidiOptions(&bidiOptions);
02972   SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions, aControlsTextMode);
02973   SetBidiOptions(bidiOptions);
02974   return NS_OK;
02975 }
02976 
02977 NS_IMETHODIMP DocumentViewerImpl::GetBidiControlsTextMode(PRUint8* aControlsTextMode)
02978 {
02979   PRUint32 bidiOptions;
02980 
02981   if (aControlsTextMode) {
02982     GetBidiOptions(&bidiOptions);
02983     *aControlsTextMode = GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions);
02984   }
02985   return NS_OK;
02986 }
02987 
02988 NS_IMETHODIMP DocumentViewerImpl::SetBidiNumeral(PRUint8 aNumeral)
02989 {
02990   PRUint32 bidiOptions;
02991 
02992   GetBidiOptions(&bidiOptions);
02993   SET_BIDI_OPTION_NUMERAL(bidiOptions, aNumeral);
02994   SetBidiOptions(bidiOptions);
02995   return NS_OK;
02996 }
02997 
02998 NS_IMETHODIMP DocumentViewerImpl::GetBidiNumeral(PRUint8* aNumeral)
02999 {
03000   PRUint32 bidiOptions;
03001 
03002   if (aNumeral) {
03003     GetBidiOptions(&bidiOptions);
03004     *aNumeral = GET_BIDI_OPTION_NUMERAL(bidiOptions);
03005   }
03006   return NS_OK;
03007 }
03008 
03009 NS_IMETHODIMP DocumentViewerImpl::SetBidiSupport(PRUint8 aSupport)
03010 {
03011   PRUint32 bidiOptions;
03012 
03013   GetBidiOptions(&bidiOptions);
03014   SET_BIDI_OPTION_SUPPORT(bidiOptions, aSupport);
03015   SetBidiOptions(bidiOptions);
03016   return NS_OK;
03017 }
03018 
03019 NS_IMETHODIMP DocumentViewerImpl::GetBidiSupport(PRUint8* aSupport)
03020 {
03021   PRUint32 bidiOptions;
03022 
03023   if (aSupport) {
03024     GetBidiOptions(&bidiOptions);
03025     *aSupport = GET_BIDI_OPTION_SUPPORT(bidiOptions);
03026   }
03027   return NS_OK;
03028 }
03029 
03030 NS_IMETHODIMP DocumentViewerImpl::SetBidiCharacterSet(PRUint8 aCharacterSet)
03031 {
03032   PRUint32 bidiOptions;
03033 
03034   GetBidiOptions(&bidiOptions);
03035   SET_BIDI_OPTION_CHARACTERSET(bidiOptions, aCharacterSet);
03036   SetBidiOptions(bidiOptions);
03037   return NS_OK;
03038 }
03039 
03040 NS_IMETHODIMP DocumentViewerImpl::GetBidiCharacterSet(PRUint8* aCharacterSet)
03041 {
03042   PRUint32 bidiOptions;
03043 
03044   if (aCharacterSet) {
03045     GetBidiOptions(&bidiOptions);
03046     *aCharacterSet = GET_BIDI_OPTION_CHARACTERSET(bidiOptions);
03047   }
03048   return NS_OK;
03049 }
03050 
03051 NS_IMETHODIMP DocumentViewerImpl::SetBidiOptions(PRUint32 aBidiOptions)
03052 {
03053   if (mPresContext) {
03054     mPresContext->SetBidi(aBidiOptions, PR_TRUE); // could cause reflow
03055   }
03056   // now set bidi on all children of mContainer
03057   CallChildren(SetChildBidiOptions, (void*) aBidiOptions);
03058   return NS_OK;
03059 }
03060 
03061 NS_IMETHODIMP DocumentViewerImpl::GetBidiOptions(PRUint32* aBidiOptions)
03062 {
03063   if (aBidiOptions) {
03064     if (mPresContext) {
03065       *aBidiOptions = mPresContext->GetBidi();
03066     }
03067     else
03068       *aBidiOptions = IBMBIDI_DEFAULT_BIDI_OPTIONS;
03069   }
03070   return NS_OK;
03071 }
03072 
03073 NS_IMETHODIMP DocumentViewerImpl::SizeToContent()
03074 {
03075    NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
03076 
03077    nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryReferent(mContainer));
03078    NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
03079 
03080    nsCOMPtr<nsIDocShellTreeItem> docShellParent;
03081    docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent));
03082 
03083    // It's only valid to access this from a top frame.  Doesn't work from
03084    // sub-frames.
03085    NS_ENSURE_TRUE(!docShellParent, NS_ERROR_FAILURE);
03086 
03087    nsCOMPtr<nsIPresShell> presShell;
03088    GetPresShell(getter_AddRefs(presShell));
03089    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
03090 
03091    // Flush out all content and style updates. We can't use a resize reflow
03092    // because it won't change some sizes that a style change reflow will.
03093    mDocument->FlushPendingNotifications(Flush_Layout);
03094                                         
03095    NS_ENSURE_SUCCESS(presShell->ResizeReflow(NS_UNCONSTRAINEDSIZE,
03096       NS_UNCONSTRAINEDSIZE), NS_ERROR_FAILURE);
03097 
03098    nsCOMPtr<nsPresContext> presContext;
03099    GetPresContext(getter_AddRefs(presContext));
03100    NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
03101 
03102    PRInt32 width, height;
03103    float   pixelScale;
03104 
03105    // so how big is it?
03106    nsRect shellArea = presContext->GetVisibleArea();
03107    if (shellArea.width == NS_UNCONSTRAINEDSIZE ||
03108        shellArea.height == NS_UNCONSTRAINEDSIZE) {
03109      // Protect against bogus returns here
03110      return NS_ERROR_FAILURE;
03111    }
03112    pixelScale = presContext->TwipsToPixels();
03113    width = PRInt32((float)shellArea.width*pixelScale);
03114    height = PRInt32((float)shellArea.height*pixelScale);
03115 
03116    nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
03117    docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
03118    NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
03119 
03120    /* presContext's size was calculated in twips and has already been
03121       rounded to the equivalent pixels (so the width/height calculation
03122       we just performed was probably exact, though it was based on
03123       values already rounded during ResizeReflow). In a surprising
03124       number of instances, this rounding makes a window which for want
03125       of one extra pixel's width ends up wrapping the longest line of
03126       text during actual window layout. This makes the window too short,
03127       generally clipping the OK/Cancel buttons. Here we add one pixel
03128       to the calculated width, to circumvent this problem. */
03129    NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShellAsItem, width+1, height),
03130       NS_ERROR_FAILURE);
03131 
03132    return NS_OK;
03133 }
03134 
03135 
03136 
03137 #ifdef XP_MAC
03138 #pragma mark -
03139 #endif
03140 
03141 NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener, nsISelectionListener)
03142 
03143 nsresult nsDocViewerSelectionListener::Init(DocumentViewerImpl *aDocViewer)
03144 {
03145   mDocViewer = aDocViewer;
03146   return NS_OK;
03147 }
03148 
03149 /*
03150  * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
03151  * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
03152  * of commands. The focus controller stores the popup node, these retrieve
03153  * them and munge appropriately. Note that we have to store the popup node
03154  * rather than retrieving it from EventStateManager::GetFocusedContent because
03155  * not all content (images included) can receive focus.
03156  */
03157 
03158 nsresult
03159 DocumentViewerImpl::GetPopupNode(nsIDOMNode** aNode)
03160 {
03161   NS_ENSURE_ARG_POINTER(aNode);
03162 
03163   nsresult rv;
03164 
03165   // get the document
03166   nsCOMPtr<nsIDocument> document;
03167   rv = GetDocument(getter_AddRefs(document));
03168   NS_ENSURE_SUCCESS(rv, rv);
03169   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
03170 
03171 
03172   // get the private dom window
03173   nsCOMPtr<nsPIDOMWindow> privateWin(do_QueryInterface(document->GetScriptGlobalObject(), &rv));
03174   NS_ENSURE_SUCCESS(rv, rv);
03175 
03176   // get the focus controller
03177   nsIFocusController *focusController = privateWin->GetRootFocusController();
03178   NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
03179 
03180   // get the popup node
03181   focusController->GetPopupNode(aNode); // addref happens here
03182 
03183   return rv;
03184 }
03185 
03186 // GetPopupLinkNode: return popup link node or fail
03187 nsresult
03188 DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode** aNode)
03189 {
03190   NS_ENSURE_ARG_POINTER(aNode);
03191 
03192   // you get null unless i say so
03193   *aNode = nsnull;
03194 
03195   // find popup node
03196   nsCOMPtr<nsIDOMNode> node;
03197   nsresult rv = GetPopupNode(getter_AddRefs(node));
03198   NS_ENSURE_SUCCESS(rv, rv);
03199 
03200   // find out if we have a link in our ancestry
03201   while (node) {
03202 
03203     // are we an anchor?
03204     nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(node));
03205     nsCOMPtr<nsIDOMHTMLAreaElement> area;
03206     nsCOMPtr<nsIDOMHTMLLinkElement> link;
03207     nsAutoString xlinkType;
03208     if (!anchor) {
03209       // area?
03210       area = do_QueryInterface(node);
03211       if (!area) {
03212         // link?
03213         link = do_QueryInterface(node);
03214         if (!link) {
03215           // XLink?
03216           nsCOMPtr<nsIDOMElement> element(do_QueryInterface(node));
03217           if (element) {
03218             element->GetAttributeNS(NS_LITERAL_STRING("http://www.w3.org/1999/xlink"),NS_LITERAL_STRING("type"),xlinkType);
03219           }
03220         }
03221       }
03222     }
03223     if (anchor || area || link || xlinkType.EqualsLiteral("simple")) {
03224       *aNode = node;
03225       NS_IF_ADDREF(*aNode); // addref
03226       return NS_OK;
03227     }
03228     else {
03229       // if not, get our parent and keep trying...
03230       nsCOMPtr<nsIDOMNode> parentNode;
03231       node->GetParentNode(getter_AddRefs(parentNode));
03232       node = parentNode;
03233     }
03234   }
03235 
03236   // if we have no node, fail
03237   return NS_ERROR_FAILURE;
03238 }
03239 
03240 // GetPopupLinkNode: return popup image node or fail
03241 nsresult
03242 DocumentViewerImpl::GetPopupImageNode(nsIImageLoadingContent** aNode)
03243 {
03244   NS_ENSURE_ARG_POINTER(aNode);
03245 
03246   // you get null unless i say so
03247   *aNode = nsnull;
03248 
03249   // find popup node
03250   nsCOMPtr<nsIDOMNode> node;
03251   nsresult rv = GetPopupNode(getter_AddRefs(node));
03252   NS_ENSURE_SUCCESS(rv, rv);
03253 
03254   if (node)
03255     CallQueryInterface(node, aNode);
03256 
03257   return NS_OK;
03258 }
03259 
03260 /*
03261  * XXX dr
03262  * ------
03263  * These two functions -- GetInLink and GetInImage -- are kind of annoying
03264  * in that they only get called from the controller (in
03265  * nsDOMWindowController::IsCommandEnabled). The actual construction of the
03266  * context menus in communicator (nsContextMenu.js) has its own, redundant
03267  * tests. No big deal, but good to keep in mind if we ever clean context
03268  * menus.
03269  */
03270 
03271 NS_IMETHODIMP DocumentViewerImpl::GetInLink(PRBool* aInLink)
03272 {
03273 #ifdef DEBUG_dr
03274   printf("dr :: DocumentViewerImpl::GetInLink\n");
03275 #endif
03276 
03277   NS_ENSURE_ARG_POINTER(aInLink);
03278 
03279   // we're not in a link unless i say so
03280   *aInLink = PR_FALSE;
03281 
03282   // get the popup link
03283   nsCOMPtr<nsIDOMNode> node;
03284   nsresult rv = GetPopupLinkNode(getter_AddRefs(node));
03285   if (NS_FAILED(rv)) return rv;
03286   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
03287 
03288   // if we made it here, we're in a link
03289   *aInLink = PR_TRUE;
03290   return NS_OK;
03291 }
03292 
03293 NS_IMETHODIMP DocumentViewerImpl::GetInImage(PRBool* aInImage)
03294 {
03295 #ifdef DEBUG_dr
03296   printf("dr :: DocumentViewerImpl::GetInImage\n");
03297 #endif
03298 
03299   NS_ENSURE_ARG_POINTER(aInImage);
03300 
03301   // we're not in an image unless i say so
03302   *aInImage = PR_FALSE;
03303 
03304   // get the popup image
03305   nsCOMPtr<nsIImageLoadingContent> node;
03306   nsresult rv = GetPopupImageNode(getter_AddRefs(node));
03307   if (NS_FAILED(rv)) return rv;
03308   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
03309 
03310   // if we made it here, we're in an image
03311   *aInImage = PR_TRUE;
03312   return NS_OK;
03313 }
03314 
03315 NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *, PRInt16)
03316 {
03317   NS_ASSERTION(mDocViewer, "Should have doc viewer!");
03318 
03319   // get the selection state
03320   nsCOMPtr<nsISelection> selection;
03321   nsresult rv = mDocViewer->GetDocumentSelection(getter_AddRefs(selection));
03322   if (NS_FAILED(rv)) return rv;
03323 
03324   PRBool selectionCollapsed;
03325   selection->GetIsCollapsed(&selectionCollapsed);
03326   // we only call UpdateCommands when the selection changes from collapsed
03327   // to non-collapsed or vice versa. We might need another update string
03328   // for simple selection changes, but that would be expenseive.
03329   if (!mGotSelectionState || mSelectionWasCollapsed != selectionCollapsed)
03330   {
03331     nsCOMPtr<nsIDocument> theDoc;
03332     mDocViewer->GetDocument(getter_AddRefs(theDoc));
03333     if (!theDoc) return NS_ERROR_FAILURE;
03334 
03335     nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(theDoc->GetScriptGlobalObject());
03336     if (!domWindow) return NS_ERROR_FAILURE;
03337 
03338     domWindow->UpdateCommands(NS_LITERAL_STRING("select"));
03339     mGotSelectionState = PR_TRUE;
03340     mSelectionWasCollapsed = selectionCollapsed;
03341   }
03342 
03343   return NS_OK;
03344 }
03345 
03346 //nsDocViewerFocusListener
03347 NS_IMPL_ISUPPORTS2(nsDocViewerFocusListener,
03348                    nsIDOMFocusListener,
03349                    nsIDOMEventListener)
03350 
03351 nsDocViewerFocusListener::nsDocViewerFocusListener()
03352 :mDocViewer(nsnull)
03353 {
03354 }
03355 
03356 nsDocViewerFocusListener::~nsDocViewerFocusListener(){}
03357 
03358 nsresult
03359 nsDocViewerFocusListener::HandleEvent(nsIDOMEvent* aEvent)
03360 {
03361   return NS_OK;
03362 }
03363 
03364 NS_IMETHODIMP
03365 nsDocViewerFocusListener::Focus(nsIDOMEvent* aEvent)
03366 {
03367   nsCOMPtr<nsIPresShell> shell;
03368   if(!mDocViewer)
03369     return NS_ERROR_FAILURE;
03370 
03371   nsresult result = mDocViewer->GetPresShell(getter_AddRefs(shell));
03372   if(NS_FAILED(result) || !shell)
03373     return result?result:NS_ERROR_FAILURE;
03374   nsCOMPtr<nsISelectionController> selCon;
03375   selCon = do_QueryInterface(shell);
03376   PRInt16 selectionStatus;
03377   selCon->GetDisplaySelection(&selectionStatus);
03378 
03379   // If selection was disabled, re-enable it.
03380   if(selectionStatus == nsISelectionController::SELECTION_DISABLED ||
03381      selectionStatus == nsISelectionController::SELECTION_HIDDEN)
03382   {
03383     selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
03384     selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
03385   }
03386   return result;
03387 }
03388 
03389 NS_IMETHODIMP
03390 nsDocViewerFocusListener::Blur(nsIDOMEvent* aEvent)
03391 {
03392   nsCOMPtr<nsIPresShell> shell;
03393   if(!mDocViewer)
03394     return NS_ERROR_FAILURE;
03395 
03396   nsresult result = mDocViewer->GetPresShell(getter_AddRefs(shell));
03397   if(NS_FAILED(result) || !shell)
03398     return result?result:NS_ERROR_FAILURE;
03399   nsCOMPtr<nsISelectionController> selCon;
03400   selCon = do_QueryInterface(shell);
03401   PRInt16 selectionStatus;
03402   selCon->GetDisplaySelection(&selectionStatus);
03403 
03404   // If selection was on, disable it.
03405   if(selectionStatus == nsISelectionController::SELECTION_ON ||
03406      selectionStatus == nsISelectionController::SELECTION_ATTENTION)
03407   {
03408     selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
03409     selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
03410   }
03411   return result;
03412 }
03413 
03414 
03415 nsresult
03416 nsDocViewerFocusListener::Init(DocumentViewerImpl *aDocViewer)
03417 {
03418   mDocViewer = aDocViewer;
03419   return NS_OK;
03420 }
03421 
03425 NS_IMETHODIMP
03426 DocumentViewerImpl::Print(nsIPrintSettings*       aPrintSettings,
03427                           nsIWebProgressListener* aWebProgressListener)
03428 {
03429 #ifdef NS_PRINTING
03430   INIT_RUNTIME_ERROR_CHECKING();
03431 
03432 #ifdef MOZ_XUL
03433   // Temporary code for Bug 136185 / Bug 240490
03434   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
03435   if (xulDoc) {
03436     nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL);
03437     return NS_ERROR_FAILURE;
03438   }
03439 #endif
03440 
03441   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
03442   NS_ASSERTION(docShell, "This has to be a docshell");
03443 
03444   // Check to see if this document is still busy
03445   // If it is busy and we aren't already "queued" up to print then
03446   // Indicate there is a print pending and cache the args for later
03447   PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
03448   if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
03449        (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && 
03450       !mPrintDocIsFullyLoaded) {
03451     if (!mPrintIsPending) {
03452       mCachedPrintSettings           = aPrintSettings;
03453       mCachedPrintWebProgressListner = aWebProgressListener;
03454       mPrintIsPending                = PR_TRUE;
03455     }
03456     PR_PL(("Printing Stopped - document is still busy!"));
03457     return NS_ERROR_GFX_PRINTER_DOC_IS_BUSY;
03458   }
03459 
03460   nsCOMPtr<nsIPresShell> presShell;
03461   docShell->GetPresShell(getter_AddRefs(presShell));
03462 
03463   if (!presShell) {
03464     // A frame that's not displayed can't be printed!
03465     PR_PL(("Printing Stopped - PreShell was NULL!"));
03466     return NS_OK;
03467   }
03468 
03469   nsresult rv = NS_ERROR_FAILURE;
03470 
03471   // if we are printing another URL, then exit
03472   // the reason we check here is because this method can be called while
03473   // another is still in here (the printing dialog is a good example).
03474   // the only time we can print more than one job at a time is the regression tests
03475   if (GetIsPrinting()) {
03476     // Let the user know we are not ready to print.
03477     rv = NS_ERROR_NOT_AVAILABLE;
03478     nsPrintEngine::ShowPrintErrorDialog(rv);
03479     return rv;
03480   }
03481 
03482   // If we are hosting a full-page plugin, tell it to print
03483   // first. It shows its own native print UI.
03484   nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument));
03485   if (pDoc)
03486     return pDoc->Print();
03487 
03488   if (!mPrintEngine) {
03489     mPrintEngine = new nsPrintEngine();
03490     NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
03491     NS_ADDREF(mPrintEngine);
03492 
03493 #ifdef NS_DEBUG
03494     mPrintEngine->Initialize(this, this, docShell, mDocument, 
03495                              mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile);
03496 #else
03497     mPrintEngine->Initialize(this, this, docShell, mDocument, 
03498                              mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull);
03499 #endif
03500   }
03501 
03502   rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener);
03503   if (NS_FAILED(rv)) {
03504     OnDonePrinting();
03505   }
03506   return rv;
03507 #else
03508   PR_PL(("NS_PRINTING not defined - printing not implemented in this build!"));
03509   return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED;
03510 #endif /* NS_PRINTING */
03511 }
03512 
03520 NS_IMETHODIMP
03521 DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, 
03522                                  nsIDOMWindow *aChildDOMWin, 
03523                                  nsIWebProgressListener* aWebProgressListener)
03524 {
03525 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
03526   nsresult rv = NS_OK;
03527 
03528   if (GetIsPrinting()) {
03529     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
03530     return NS_ERROR_FAILURE;
03531   }
03532 
03533 #ifdef MOZ_XUL
03534   // Temporary code for Bug 136185 / Bug 240490
03535   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
03536   if (xulDoc) {
03537     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
03538     nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE);
03539     return NS_ERROR_FAILURE;
03540   }
03541 #endif
03542 
03543   if (!mPrintEngine) {
03544     mPrintEngine = new nsPrintEngine();
03545     NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
03546     NS_ADDREF(mPrintEngine);
03547 
03548     mPrintEngine->Initialize(this, this,
03549                              nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)),
03550                              mDocument, mDeviceContext, mPresContext,
03551                              mWindow, mParentWidget,
03552 #ifdef NS_DEBUG
03553                              mDebugFile
03554 #else
03555                              nsnull
03556 #endif
03557                              );
03558   }
03559 
03560   rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener);
03561   if (NS_FAILED(rv)) {
03562     OnDonePrinting();
03563   }
03564   return rv;
03565 #else
03566   return NS_ERROR_FAILURE;
03567 #endif
03568 }
03569 
03570 //----------------------------------------------------------------------
03571 NS_IMETHODIMP
03572 DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum)
03573 {
03574 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
03575   if (GetIsPrinting()) return NS_ERROR_FAILURE;
03576 
03577   if (!mPrintEngine) return NS_ERROR_FAILURE;
03578 
03579   nsIScrollableView* scrollableView;
03580   mViewManager->GetRootScrollableView(&scrollableView);
03581   if (scrollableView == nsnull) return NS_OK;
03582 
03583   // Check to see if we can short circut scrolling to the top
03584   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME ||
03585       (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) {
03586     scrollableView->ScrollTo(0, 0, PR_TRUE);
03587     return NS_OK;
03588   }
03589 
03590   // Finds the SimplePageSequencer frame
03591   // in PP mPrtPreview->mPrintObject->mSeqFrame is null
03592   nsIFrame* seqFrame  = nsnull;
03593   PRInt32   pageCount = 0;
03594   if (NS_FAILED(mPrintEngine->GetSeqFrameAndCountPages(seqFrame, pageCount))) {
03595     return NS_ERROR_FAILURE;
03596   }
03597 
03598   // Figure where we are currently scrolled to
03599   nscoord x;
03600   nscoord y;
03601   scrollableView->GetScrollPosition(x, y);
03602 
03603   PRInt32    pageNum = 1;
03604   nsIFrame * fndPageFrame  = nsnull;
03605   nsIFrame * currentPage   = nsnull;
03606 
03607   // If it is "End" then just do a "goto" to the last page
03608   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) {
03609     aType    = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM;
03610     aPageNum = pageCount;
03611   }
03612 
03613   // Now, locate the current page we are on and
03614   // and the page of the page number
03615   nscoord gap = 0;
03616   nsIFrame* pageFrame = seqFrame->GetFirstChild(nsnull);
03617   while (pageFrame != nsnull) {
03618     nsRect pageRect = pageFrame->GetRect();
03619     if (pageNum == 1) {
03620       gap = pageRect.y;
03621     }
03622     if (pageRect.Contains(pageRect.x, y)) {
03623       currentPage = pageFrame;
03624     }
03625     if (pageNum == aPageNum) {
03626       fndPageFrame = pageFrame;
03627       break;
03628     }
03629     pageNum++;
03630     pageFrame = pageFrame->GetNextSibling();
03631   }
03632 
03633   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) {
03634     if (currentPage) {
03635       fndPageFrame = currentPage->GetPrevInFlow();
03636       if (!fndPageFrame) {
03637         return NS_OK;
03638       }
03639     } else {
03640       return NS_OK;
03641     }
03642   } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) {
03643     if (currentPage) {
03644       fndPageFrame = currentPage->GetNextInFlow();
03645       if (!fndPageFrame) {
03646         return NS_OK;
03647       }
03648     } else {
03649       return NS_OK;
03650     }
03651   } else { // If we get here we are doing "GoTo"
03652     if (aPageNum < 0 || aPageNum > pageCount) {
03653       return NS_OK;
03654     }
03655   }
03656 
03657   if (fndPageFrame && scrollableView) {
03658     // find offset from view
03659     nsPoint pnt;
03660     nsIView * view;
03661     fndPageFrame->GetOffsetFromView(pnt, &view);
03662 
03663     nscoord deadSpaceGap = 0;
03664     nsIPageSequenceFrame * sqf;
03665     if (NS_SUCCEEDED(CallQueryInterface(seqFrame, &sqf))) {
03666       sqf->GetDeadSpaceValue(&deadSpaceGap);
03667     }
03668 
03669     // scroll so that top of page (plus the gray area) is at the top of the scroll area
03670     scrollableView->ScrollTo(0, fndPageFrame->GetPosition().y-deadSpaceGap, PR_TRUE);
03671   }
03672   return NS_OK;
03673 #else
03674   return NS_ERROR_FAILURE;
03675 #endif // NS_PRINT_PREVIEW
03676 
03677 }
03678 
03679 /* readonly attribute nsIPrintSettings globalPrintSettings; */
03680 NS_IMETHODIMP
03681 DocumentViewerImpl::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings)
03682 {
03683 #ifdef NS_PRINTING
03684   NS_ENSURE_ARG_POINTER(aGlobalPrintSettings);
03685 
03686   nsPrintEngine printEngine;
03687   return printEngine.GetGlobalPrintSettings(aGlobalPrintSettings);
03688 #else
03689   return NS_ERROR_FAILURE;
03690 #endif
03691 }
03692 
03693 /* readonly attribute boolean doingPrint; */
03694 // XXX This always returns PR_FALSE for subdocuments
03695 NS_IMETHODIMP
03696 DocumentViewerImpl::GetDoingPrint(PRBool *aDoingPrint)
03697 {
03698 #ifdef NS_PRINTING
03699   NS_ENSURE_ARG_POINTER(aDoingPrint);
03700   
03701   *aDoingPrint = PR_FALSE;
03702   if (mPrintEngine) {
03703     // XXX shouldn't this be GetDoingPrint() ?
03704     return mPrintEngine->GetDoingPrintPreview(aDoingPrint);
03705   } 
03706   return NS_OK;
03707 #else
03708   return NS_ERROR_FAILURE;
03709 #endif
03710 }
03711 
03712 /* readonly attribute boolean doingPrintPreview; */
03713 // XXX This always returns PR_FALSE for subdocuments
03714 NS_IMETHODIMP
03715 DocumentViewerImpl::GetDoingPrintPreview(PRBool *aDoingPrintPreview)
03716 {
03717 #ifdef NS_PRINTING
03718   NS_ENSURE_ARG_POINTER(aDoingPrintPreview);
03719 
03720   *aDoingPrintPreview = PR_FALSE;
03721   if (mPrintEngine) {
03722     return mPrintEngine->GetDoingPrintPreview(aDoingPrintPreview);
03723   }
03724   return NS_OK;
03725 #else
03726   return NS_ERROR_FAILURE;
03727 #endif
03728 }
03729 
03730 /* readonly attribute nsIPrintSettings currentPrintSettings; */
03731 NS_IMETHODIMP
03732 DocumentViewerImpl::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings)
03733 {
03734 #ifdef NS_PRINTING
03735   NS_ENSURE_ARG_POINTER(aCurrentPrintSettings);
03736 
03737   *aCurrentPrintSettings = nsnull;
03738   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03739 
03740   return mPrintEngine->GetCurrentPrintSettings(aCurrentPrintSettings);
03741 #else
03742   return NS_ERROR_FAILURE;
03743 #endif
03744 }
03745 
03746 /* readonly attribute nsIDOMWindow currentChildDOMWindow; */
03747 NS_IMETHODIMP 
03748 DocumentViewerImpl::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWindow)
03749 {
03750   NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow);
03751   *aCurrentChildDOMWindow = nsnull;
03752   return NS_ERROR_NOT_IMPLEMENTED;
03753 }
03754 
03755 /* void cancel (); */
03756 NS_IMETHODIMP
03757 DocumentViewerImpl::Cancel()
03758 {
03759 #ifdef NS_PRINTING
03760   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03761   return mPrintEngine->Cancelled();
03762 #else
03763   return NS_ERROR_FAILURE;
03764 #endif
03765 }
03766 
03767 /* void exitPrintPreview (); */
03768 NS_IMETHODIMP
03769 DocumentViewerImpl::ExitPrintPreview()
03770 {
03771 #ifdef NS_PRINTING
03772   if (GetIsPrinting()) return NS_ERROR_FAILURE;
03773   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03774 
03775   if (GetIsPrintPreview()) {
03776     ReturnToGalleyPresentation();
03777   }
03778   return NS_OK;
03779 #else
03780   return NS_ERROR_FAILURE;
03781 #endif
03782 }
03783 
03784 //----------------------------------------------------------------------------------
03785 // Enumerate all the documents for their titles
03786 NS_IMETHODIMP
03787 DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount,
03788                                            PRUnichar*** aResult)
03789 {
03790 #ifdef NS_PRINTING
03791   NS_ENSURE_ARG(aCount);
03792   NS_ENSURE_ARG_POINTER(aResult);
03793   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03794 
03795   return mPrintEngine->EnumerateDocumentNames(aCount, aResult);
03796 #else
03797   return NS_ERROR_FAILURE;
03798 #endif
03799 }
03800 
03801 /* readonly attribute boolean isFramesetFrameSelected; */
03802 NS_IMETHODIMP 
03803 DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected)
03804 {
03805 #ifdef NS_PRINTING
03806   *aIsFramesetFrameSelected = PR_FALSE;
03807   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03808 
03809   return mPrintEngine->GetIsFramesetFrameSelected(aIsFramesetFrameSelected);
03810 #else
03811   return NS_ERROR_FAILURE;
03812 #endif
03813 }
03814 
03815 /* readonly attribute long printPreviewNumPages; */
03816 NS_IMETHODIMP
03817 DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages)
03818 {
03819 #ifdef NS_PRINTING
03820   NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
03821   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03822 
03823   return mPrintEngine->GetPrintPreviewNumPages(aPrintPreviewNumPages);
03824 #else
03825   return NS_ERROR_FAILURE;
03826 #endif
03827 }
03828 
03829 /* readonly attribute boolean isFramesetDocument; */
03830 NS_IMETHODIMP
03831 DocumentViewerImpl::GetIsFramesetDocument(PRBool *aIsFramesetDocument)
03832 {
03833 #ifdef NS_PRINTING
03834   *aIsFramesetDocument = PR_FALSE;
03835   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03836 
03837   return mPrintEngine->GetIsFramesetDocument(aIsFramesetDocument);
03838 #else
03839   return NS_ERROR_FAILURE;
03840 #endif
03841 }
03842 
03843 /* readonly attribute boolean isIFrameSelected; */
03844 NS_IMETHODIMP 
03845 DocumentViewerImpl::GetIsIFrameSelected(PRBool *aIsIFrameSelected)
03846 {
03847 #ifdef NS_PRINTING
03848   *aIsIFrameSelected = PR_FALSE;
03849   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03850 
03851   return mPrintEngine->GetIsIFrameSelected(aIsIFrameSelected);
03852 #else
03853   return NS_ERROR_FAILURE;
03854 #endif
03855 }
03856 
03857 /* readonly attribute boolean isRangeSelection; */
03858 NS_IMETHODIMP 
03859 DocumentViewerImpl::GetIsRangeSelection(PRBool *aIsRangeSelection)
03860 {
03861 #ifdef NS_PRINTING
03862   *aIsRangeSelection = PR_FALSE;
03863   NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE);
03864 
03865   return mPrintEngine->GetIsRangeSelection(aIsRangeSelection);
03866 #else
03867   return NS_ERROR_FAILURE;
03868 #endif
03869 }
03870 
03871 
03872 #ifdef NS_PRINTING
03873 //----------------------------------------------------------------------------------
03874 // Printing/Print Preview Helpers
03875 //----------------------------------------------------------------------------------
03876 
03877 //----------------------------------------------------------------------------------
03878 // Walks the document tree and tells each DocShell whether Printing/PP is happening
03879 void 
03880 DocumentViewerImpl::SetIsPrintingInDocShellTree(nsIDocShellTreeNode* aParentNode, 
03881                                                 PRBool               aIsPrintingOrPP, 
03882                                                 PRBool               aStartAtTop)
03883 {
03884   NS_ASSERTION(aParentNode, "Parent can't be NULL!");
03885 
03886   nsCOMPtr<nsIDocShellTreeItem> parentItem(do_QueryInterface(aParentNode));
03887 
03888   // find top of "same parent" tree
03889   if (aStartAtTop) {
03890     while (parentItem) {
03891       nsCOMPtr<nsIDocShellTreeItem> parent;
03892       parentItem->GetSameTypeParent(getter_AddRefs(parent));
03893       if (!parent) {
03894         break;
03895       }
03896       parentItem = do_QueryInterface(parent);
03897     }
03898   }
03899   NS_ASSERTION(parentItem, "parentItem can't be null");
03900 
03901   // Check to see if the DocShell's ContentViewer is printing/PP
03902   nsCOMPtr<nsIContentViewerContainer> viewerContainer(do_QueryInterface(parentItem));
03903   if (viewerContainer) {
03904     viewerContainer->SetIsPrinting(aIsPrintingOrPP);
03905   }
03906 
03907   // Traverse children to see if any of them are printing.
03908   PRInt32 n;
03909   aParentNode->GetChildCount(&n);
03910   for (PRInt32 i=0; i < n; i++) {
03911     nsCOMPtr<nsIDocShellTreeItem> child;
03912     aParentNode->GetChildAt(i, getter_AddRefs(child));
03913     nsCOMPtr<nsIDocShellTreeNode> childAsNode(do_QueryInterface(child));
03914     NS_ASSERTION(childAsNode, "child isn't nsIDocShellTreeNode");
03915     if (childAsNode) {
03916       SetIsPrintingInDocShellTree(childAsNode, aIsPrintingOrPP, PR_FALSE);
03917     }
03918   }
03919 
03920 }
03921 #endif // NS_PRINTING
03922 
03923 //------------------------------------------------------------
03924 // XXX this always returns PR_FALSE for subdocuments
03925 PRBool
03926 DocumentViewerImpl::GetIsPrinting()
03927 {
03928 #ifdef NS_PRINTING
03929   if (mPrintEngine) {
03930     return mPrintEngine->GetIsPrinting();
03931   }
03932 #endif
03933   return PR_FALSE; 
03934 }
03935 
03936 //------------------------------------------------------------
03937 // Notification from the PrintEngine of the current Printing status
03938 void
03939 DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting)
03940 {
03941 #ifdef NS_PRINTING
03942   // Set all the docShells in the docshell tree to be printing.
03943   // that way if anyone of them tries to "navigate" it can't
03944   if (mContainer) {
03945     nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
03946     NS_ASSERTION(docShellTreeNode, "mContainer has to be a nsIDocShellTreeNode");
03947     SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrinting, PR_TRUE);
03948   }
03949 #endif
03950 }
03951 
03952 //------------------------------------------------------------
03953 // The PrintEngine holds the current value
03954 // this called from inside the DocViewer.
03955 // XXX it always returns PR_FALSE for subdocuments
03956 PRBool
03957 DocumentViewerImpl::GetIsPrintPreview()
03958 {
03959 #ifdef NS_PRINTING
03960   if (mPrintEngine) {
03961     return mPrintEngine->GetIsPrintPreview();
03962   }
03963 #endif
03964   return PR_FALSE; 
03965 }
03966 
03967 //------------------------------------------------------------
03968 // Notification from the PrintEngine of the current PP status
03969 void
03970 DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview)
03971 {
03972 #ifdef NS_PRINTING
03973   // Set all the docShells in the docshell tree to be printing.
03974   // that way if anyone of them tries to "navigate" it can't
03975   if (mContainer) {
03976     nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
03977     NS_ASSERTION(docShellTreeNode, "mContainer has to be a nsIDocShellTreeNode");
03978     SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, PR_TRUE);
03979   }
03980 #endif
03981 }
03982 
03983 //------------------------------------------------------------
03984 // The PrintEngine holds the current value
03985 // this called from inside the DocViewer
03986 PRBool
03987 DocumentViewerImpl::GetIsCreatingPrintPreview()
03988 {
03989 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
03990   if (mPrintEngine) {
03991     return mPrintEngine->GetIsCreatingPrintPreview();
03992   }
03993 #endif
03994   return PR_FALSE; 
03995 }
03996 
03997 //----------------------------------------------------------------------------------
03998 // nsIDocumentViewerPrint IFace
03999 //----------------------------------------------------------------------------------
04000 
04001 //------------------------------------------------------------
04002 void
04003 DocumentViewerImpl::IncrementDestroyRefCount()
04004 {
04005   ++mDestroyRefCount;
04006 }
04007 
04008 //------------------------------------------------------------
04009 void
04010 DocumentViewerImpl::ReturnToGalleyPresentation()
04011 {
04012 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
04013   if (!GetIsPrintPreview()) {
04014     NS_ASSERTION(0, "Wow, we should never get here!");
04015     return;
04016   }
04017 
04018   // Get the current size of what is being viewed
04019   nsRect bounds;
04020   mWindow->GetBounds(bounds);
04021 
04022   // In case we have focus focus the parent DocShell
04023   // which in this case should always be chrome
04024   nsCOMPtr<nsIDocShellTreeItem>  dstParentItem;
04025   nsCOMPtr<nsIDocShellTreeItem>  dstItem(do_QueryReferent(mContainer));
04026   if (dstItem) {
04027     dstItem->GetParent(getter_AddRefs(dstParentItem));
04028     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(dstParentItem));
04029     if (docShell) {
04030       docShell->SetHasFocus(PR_TRUE);
04031     }
04032   }
04033 
04034   // Start to kill off the old Presentation
04035   // by cleaning up the PresShell
04036   if (mPresShell) {
04037     // Break circular reference (or something)
04038     mPresShell->EndObservingDocument();
04039     nsCOMPtr<nsISelection> selection;
04040     nsresult rv = GetDocumentSelection(getter_AddRefs(selection));
04041     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
04042     if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener)
04043       selPrivate->RemoveSelectionListener(mSelectionListener);
04044     mPresShell->Destroy();
04045   }
04046 
04047   // clear weak references before we go away
04048   if (mPresContext) {
04049     mPresContext->SetContainer(nsnull);
04050     mPresContext->SetLinkHandler(nsnull);
04051   }
04052 
04053   //------------------------------------------------
04054   // NOTE:
04055   // Here is why the code below is a little confusing:
04056   //   1) Scripting needs to be turned back on before 
04057   //      the print engine is destroyed
04058   //   2) The PrintEngine must be destroyed BEFORE 
04059   //      calling InitInternal when caching documents (framesets)
04060   //      BUT the PrintEngine must be destroyed AFTER 
04061   //      calling InitInternal when NOT caching documents (no framesets)
04062   //------------------------------------------------
04063 
04064   // wasCached will be used below to indicate whether the 
04065   // InitInternal should create all new objects or just
04066   // initialize the existing ones
04067   PRBool wasCached = PR_FALSE;
04068 
04069   if (mPrintEngine && mPrintEngine->HasCachedPres()) {
04070 
04071     mPrintEngine->GetCachedPresentation(mPresShell, mPresContext, mViewManager, mWindow);
04072 
04073     // Tell the "real" presshell to start observing the document
04074     // again.
04075     mPresShell->BeginObservingDocument();
04076 
04077     mWindow->Show(PR_TRUE);
04078 
04079     wasCached = PR_TRUE;
04080   } else {
04081     // Destroy the old Presentation
04082     mPresShell    = nsnull;
04083     mPresContext  = nsnull;
04084     mViewManager  = nsnull;
04085     mWindow       = nsnull;
04086   }
04087 
04088   if (mPrintEngine) {
04089     // Very important! Turn On scripting
04090     mPrintEngine->TurnScriptingOn(PR_TRUE);
04091 
04092     if (wasCached) {
04093       mPrintEngine->Destroy();
04094       NS_RELEASE(mPrintEngine);
04095     }
04096   }
04097 
04098   InitInternal(mParentWidget, nsnull, mDeviceContext, bounds, !wasCached, PR_TRUE);
04099 
04100   if (mPrintEngine && !wasCached) {
04101     mPrintEngine->Destroy();
04102     NS_RELEASE(mPrintEngine);
04103   }
04104 
04105   // this needs to be set here not earlier,
04106   // because it is needing when re-constructing the Galley Mode)
04107   SetIsPrintPreview(PR_FALSE);
04108 
04109   mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
04110 
04111   Show();
04112 
04113 #endif // NS_PRINTING && NS_PRINT_PREVIEW
04114 }
04115 
04116 //------------------------------------------------------------
04117 // Reset ESM focus for all descendent doc shells.
04118 static void
04119 ResetFocusState(nsIDocShell* aDocShell)
04120 {
04121   nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
04122   aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
04123                                    nsIDocShell::ENUMERATE_FORWARDS,
04124                                    getter_AddRefs(docShellEnumerator));
04125   
04126   nsCOMPtr<nsIDocShell> currentDocShell;
04127   nsCOMPtr<nsISupports> currentContainer;
04128   PRBool hasMoreDocShells;
04129   while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells))
04130          && hasMoreDocShells) {
04131     docShellEnumerator->GetNext(getter_AddRefs(currentContainer));
04132     currentDocShell = do_QueryInterface(currentContainer);
04133     if (!currentDocShell) {
04134       break;
04135     }
04136     nsCOMPtr<nsPresContext> presContext;
04137     currentDocShell->GetPresContext(getter_AddRefs(presContext));
04138     nsIEventStateManager* esm =
04139       presContext ? presContext->EventStateManager() : nsnull;
04140     if (esm) {
04141        esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
04142        esm->SetFocusedContent(nsnull);
04143     }
04144   }
04145 }
04146 
04147 //------------------------------------------------------------
04148 void
04149 DocumentViewerImpl::InstallNewPresentation()
04150 {
04151 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
04152   // Get the current size of what is being viewed
04153   nsRect bounds;
04154   mWindow->GetBounds(bounds);
04155 
04156   // In case we have focus focus the parent DocShell
04157   // which in this case should always be chrome
04158   nsCOMPtr<nsIDocShellTreeItem>  dstParentItem;
04159   nsCOMPtr<nsIDocShellTreeItem>  dstItem(do_QueryReferent(mContainer));
04160   if (dstItem) {
04161     dstItem->GetParent(getter_AddRefs(dstParentItem));
04162     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(dstParentItem));
04163     if (docShell) {
04164       docShell->SetHasFocus(PR_TRUE);
04165       ::ResetFocusState(docShell);
04166     }
04167   }
04168 
04169   // turn off selection painting
04170   nsCOMPtr<nsISelectionController> selectionController =
04171     do_QueryInterface(mPresShell);
04172   if (selectionController) {
04173     selectionController->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
04174   }
04175 
04176   // Start to kill off the old Presentation
04177   // by cleaning up the PresShell
04178   if (mPresShell) {
04179     // Break circular reference (or something)
04180     mPresShell->EndObservingDocument();
04181     nsCOMPtr<nsISelection> selection;
04182     nsresult rv = GetDocumentSelection(getter_AddRefs(selection));
04183     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
04184     if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener)
04185       selPrivate->RemoveSelectionListener(mSelectionListener);
04186 
04187     // We need to destroy the PreShell if there is an existing PP
04188     // or we are not caching the original Presentation
04189     if (!mPrintEngine->IsCachingPres() || mPrintEngine->IsOldPrintPreviewPres()) {
04190       mPresShell->Destroy();
04191     }
04192   }
04193 
04194   // clear weak references before we go away
04195   if (mPresContext) {
04196     mPresContext->SetContainer(nsnull);
04197     mPresContext->SetLinkHandler(nsnull);
04198   }
04199 
04200   // See if we are suppose to be caching the old Presentation
04201   // and then check to see if we already have.
04202   if (mPrintEngine->IsCachingPres() && !mPrintEngine->HasCachedPres()) {
04203     // Cach old presentation
04204     mPrintEngine->CachePresentation(mPresShell, mPresContext, mViewManager, mWindow);
04205     mWindow->Show(PR_FALSE);
04206   } else {
04207     // Destroy the old Presentation
04208     mPresShell    = nsnull;
04209     mPresContext  = nsnull;
04210     mViewManager  = nsnull;
04211     mWindow       = nsnull;
04212   }
04213 
04214   mPrintEngine->InstallPrintPreviewListener();
04215 
04216   mPrintEngine->GetNewPresentation(mPresShell, mPresContext, mViewManager, mWindow);
04217 
04218   mPresShell->BeginObservingDocument();
04219 
04220   // Make sure we have focus in a context that has a container, bug 244128.
04221   nsIEventStateManager* esm = mPresContext->EventStateManager();
04222   if (esm) {
04223     esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
04224     esm->SetFocusedContent(nsnull);
04225   }
04226 
04227   nscoord width  = bounds.width;
04228   nscoord height = bounds.height;
04229   float p2t;
04230   p2t = mPresContext->PixelsToTwips();
04231   width = NSIntPixelsToTwips(width, p2t);
04232   height = NSIntPixelsToTwips(height, p2t);
04233   mViewManager->DisableRefresh();
04234   mViewManager->SetWindowDimensions(width, height);
04235 
04236   mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_FALSE);
04237   mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_PAINT, PR_TRUE);
04238 
04239   mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
04240 
04241   Show();
04242 
04243   mPrintEngine->ShowDocList(PR_TRUE);
04244 #endif // NS_PRINTING && NS_PRINT_PREVIEW
04245 }
04246 
04247 //------------------------------------------------------------
04248 // This called ONLY when printing has completed and the DV
04249 // is being notified that it should get rid of the PrintEngine.
04250 //
04251 // BUT, if we are in Print Preview then we want to ignore the 
04252 // notification (we do not get rid of the PrintEngine)
04253 // 
04254 // One small caveat: 
04255 //   This IS called from two places in this module for cleaning
04256 //   up when an error occurred during the start up printing 
04257 //   and print preview
04258 //
04259 void
04260 DocumentViewerImpl::OnDonePrinting() 
04261 {
04262 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
04263   if (mPrintEngine) {
04264     if (GetIsPrintPreview()) {
04265       mPrintEngine->DestroyPrintingData();
04266     } else {
04267       mPrintEngine->Destroy();
04268       NS_RELEASE(mPrintEngine);
04269     }
04270 
04271     // We are done printing, now cleanup 
04272     if (mDeferredWindowClose) {
04273       mDeferredWindowClose = PR_FALSE;
04274       nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
04275       nsCOMPtr<nsIDOMWindowInternal> win = do_GetInterface(container);
04276       if (win)
04277         win->Close();
04278     } else if (mClosingWhilePrinting) {
04279       if (mDocument) {
04280         mDocument->SetScriptGlobalObject(nsnull);
04281         mDocument->Destroy();
04282         mDocument = nsnull;
04283       }
04284       mClosingWhilePrinting = PR_FALSE;
04285       NS_RELEASE_THIS();
04286     }
04287   }
04288 #endif // NS_PRINTING && NS_PRINT_PREVIEW
04289 }
04290 
04291 NS_IMETHODIMP
04292 DocumentViewerImpl::GetHistoryEntry(nsISHEntry **aHistoryEntry)
04293 {
04294   NS_IF_ADDREF(*aHistoryEntry = mSHEntry);
04295   return NS_OK;
04296 }