1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=80: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Dan Rosen <dr@netscape.com>
25 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
26 * Mats Palmgren <mats.palmgren@bredband.net>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 /* container for a document and its presentation */
48 #include "nsReadableUtils.h"
49 #include "nsISupports.h"
50 #include "nsIContent.h"
51 #include "nsIContentViewerContainer.h"
52 #include "nsIDocumentViewer.h"
53 #include "nsIDocumentViewerPrint.h"
55 #include "nsIDocument.h"
56 #include "nsPresContext.h"
57 #include "nsIPresShell.h"
58 #include "nsIEventStateManager.h"
59 #include "nsStyleSet.h"
60 #include "nsIStyleSheet.h"
61 #include "nsICSSStyleSheet.h"
64 #include "nsILinkHandler.h"
65 #include "nsIDOMDocument.h"
66 #include "nsISelectionListener.h"
67 #include "nsISelectionPrivate.h"
68 #include "nsIDOMHTMLDocument.h"
69 #include "nsIDOMNSHTMLDocument.h"
70 #include "nsIDOMHTMLCollection.h"
71 #include "nsIDOMHTMLElement.h"
72 #include "nsIDOMRange.h"
73 #include "nsContentCID.h"
74 #include "nsLayoutCID.h"
75 #include "nsContentUtils.h"
76 #include "nsLayoutStylesheetCache.h"
78 #include "nsViewsCID.h"
79 #include "nsWidgetsCID.h"
80 #include "nsIDeviceContext.h"
81 #include "nsIDeviceContextSpec.h"
82 #include "nsIViewManager.h"
85 #include "nsIPageSequenceFrame.h"
87 #include "nsNetUtil.h"
88 #include "nsIContentViewerEdit.h"
89 #include "nsIContentViewerFile.h"
90 #include "nsICSSLoader.h"
91 #include "nsIMarkupDocumentViewer.h"
92 #include "nsIInterfaceRequestor.h"
93 #include "nsIInterfaceRequestorUtils.h"
94 #include "nsIDocShellTreeItem.h"
95 #include "nsIDocShellTreeNode.h"
96 #include "nsIDocShellTreeOwner.h"
97 #include "nsIDocShell.h"
98 #include "nsIBaseWindow.h"
99 #include "nsIFrameDebug.h"
100 #include "nsILayoutHistoryState.h"
101 #include "nsIParser.h"
102 #include "nsGUIEvent.h"
103 #include "nsHTMLReflowState.h"
104 #include "nsIDOMHTMLAnchorElement.h"
105 #include "nsIDOMHTMLAreaElement.h"
106 #include "nsIDOMHTMLLinkElement.h"
107 #include "nsIImageLoadingContent.h"
108 #include "nsCopySupport.h"
109 #include "nsIDOMHTMLFrameSetElement.h"
111 #include "nsIXULDocument.h"
112 #include "nsXULPopupManager.h"
114 #include "nsPrintfCString.h"
116 #include "nsIClipboardHelper.h"
118 #include "nsPIDOMWindow.h"
119 #include "nsJSEnvironment.h"
120 #include "nsIFocusController.h"
122 #include "nsIScrollableView.h"
123 #include "nsIHTMLDocument.h"
124 #include "nsITimelineService.h"
125 #include "nsGfxCIID.h"
126 #include "nsStyleSheetService.h"
127 #include "ImageErrors.h"
129 #include "nsIPrompt.h"
130 #include "imgIContainer.h" // image animation mode constants
132 //--------------------------
134 //---------------------------
137 #include "nsIWebBrowserPrint.h"
139 #include "nsPrintEngine.h"
142 #include "nsIPrintSettings.h"
143 #include "nsIPrintSettingsService.h"
144 #include "nsIPrintOptions.h"
145 #include "nsIServiceManager.h"
146 #include "nsISimpleEnumerator.h"
148 #include "nsISupportsPrimitives.h"
150 // PrintOptions is now implemented by PrintSettingsService
151 static const char sPrintOptionsContractID
[] = "@mozilla.org/gfx/printsettings-service;1";
154 #include "nsPrintPreviewListener.h"
156 #include "nsIDOMHTMLFrameElement.h"
157 #include "nsIDOMHTMLIFrameElement.h"
158 #include "nsIDOMHTMLObjectElement.h"
159 #include "nsIPluginDocument.h"
162 #include "nsIPrintProgress.h"
163 #include "nsIPrintProgressParams.h"
165 // Print error dialog
166 #include "nsIWindowWatcher.h"
169 #include "nsPrintEngine.h"
170 #include "nsPagePrintTimer.h"
172 #endif // NS_PRINTING
175 #include "nsIDocument.h"
178 #include "nsIDOMEventTarget.h"
179 #include "nsIDOMFocusListener.h"
180 #include "nsISelectionController.h"
182 #include "nsBidiUtils.h"
183 #include "nsISHEntry.h"
184 #include "nsISHistory.h"
185 #include "nsISHistoryInternal.h"
186 #include "nsIWebNavigation.h"
187 #include "nsWeakPtr.h"
188 #include "nsEventDispatcher.h"
189 #include "nsPresShellIterator.h"
195 //switch to page layout
196 #include "nsGfxCIID.h"
205 //-----------------------------------------------------
208 #define FORCE_PR_LOG /* Allow logging in the release build */
215 static PRLogModuleInfo
* kPrintingLogMod
= PR_NewLogModule("printing");
216 #define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
218 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
220 #define PRT_YESNO(_p)
223 //-----------------------------------------------------
225 class DocumentViewerImpl
;
227 // a small delegate class used to avoid circular references
230 #pragma mark ** nsDocViewerSelectionListener **
233 class nsDocViewerSelectionListener
: public nsISelectionListener
237 // nsISupports interface...
240 // nsISelectionListerner interface
241 NS_DECL_NSISELECTIONLISTENER
243 nsDocViewerSelectionListener()
245 , mGotSelectionState(PR_FALSE
)
246 , mSelectionWasCollapsed(PR_FALSE
)
250 virtual ~nsDocViewerSelectionListener() {}
252 nsresult
Init(DocumentViewerImpl
*aDocViewer
);
256 DocumentViewerImpl
* mDocViewer
;
257 PRPackedBool mGotSelectionState
;
258 PRPackedBool mSelectionWasCollapsed
;
263 /** editor Implementation of the FocusListener interface
265 class nsDocViewerFocusListener
: public nsIDOMFocusListener
268 /** default constructor
270 nsDocViewerFocusListener();
271 /** default destructor
273 virtual ~nsDocViewerFocusListener();
276 /*interfaces for addref and release and queryinterface*/
279 /*BEGIN implementations of focus event handler interface*/
280 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
);
281 NS_IMETHOD
Focus(nsIDOMEvent
* aEvent
);
282 NS_IMETHOD
Blur(nsIDOMEvent
* aEvent
);
283 /*END implementations of focus event handler interface*/
284 nsresult
Init(DocumentViewerImpl
*aDocViewer
);
287 DocumentViewerImpl
* mDocViewer
;
293 #pragma mark ** DocumentViewerImpl **
296 //-------------------------------------------------------------
297 class DocumentViewerImpl
: public nsIDocumentViewer
,
298 public nsIContentViewerEdit
,
299 public nsIContentViewerFile
,
300 public nsIMarkupDocumentViewer
,
301 public nsIDocumentViewerPrint
304 , public nsIWebBrowserPrint
308 friend class nsDocViewerSelectionListener
;
309 friend class nsPagePrintTimer
;
310 friend class nsPrintEngine
;
313 DocumentViewerImpl();
315 NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
317 // nsISupports interface...
320 // nsIContentViewer interface...
321 NS_DECL_NSICONTENTVIEWER
323 // nsIDocumentViewer interface...
324 NS_IMETHOD
GetDocument(nsIDocument
** aResult
);
325 NS_IMETHOD
GetPresShell(nsIPresShell
** aResult
);
326 NS_IMETHOD
GetPresContext(nsPresContext
** aResult
);
328 // nsIContentViewerEdit
329 NS_DECL_NSICONTENTVIEWEREDIT
331 // nsIContentViewerFile
332 NS_DECL_NSICONTENTVIEWERFILE
334 // nsIMarkupDocumentViewer
335 NS_DECL_NSIMARKUPDOCUMENTVIEWER
338 // nsIWebBrowserPrint
339 NS_DECL_NSIWEBBROWSERPRINT
342 typedef void (*CallChildFunc
)(nsIMarkupDocumentViewer
* aViewer
,
344 void CallChildren(CallChildFunc aFunc
, void* aClosure
);
346 // nsIDocumentViewerPrint Printing Methods
347 NS_DECL_NSIDOCUMENTVIEWERPRINT
350 virtual ~DocumentViewerImpl();
354 * Creates a view manager, root view, and widget for the root view, setting
355 * mViewManager and mWindow.
356 * @param aSize the initial size in appunits
358 nsresult
MakeWindow(const nsSize
& aSize
);
361 * Create our device context
363 nsresult
CreateDeviceContext(nsIWidget
* aWidget
);
366 * Make sure to set up mDeviceContext as needed before calling this
368 nsresult
InitInternal(nsIWidget
* aParentWidget
,
370 const nsRect
& aBounds
,
372 PRBool aInPrintPreview
,
373 PRBool aNeedMakeCX
= PR_TRUE
);
375 * @param aDoInitialReflow set to true if you want to kick off the initial
377 * @param aReenableRefresh set to true if you want this to reenable refresh
378 * before returning; otherwise this will return with refresh disabled
379 * in the view manager
381 nsresult
InitPresentationStuff(PRBool aDoInitialReflow
, PRBool aReenableRefresh
);
383 nsresult
GetPopupNode(nsIDOMNode
** aNode
);
384 nsresult
GetPopupLinkNode(nsIDOMNode
** aNode
);
385 nsresult
GetPopupImageNode(nsIImageLoadingContent
** aNode
);
387 void PrepareToStartLoad(void);
389 nsresult
SyncParentSubDocMap();
391 nsresult
GetDocumentSelection(nsISelection
**aSelection
);
393 nsresult
GetClipboardEventTarget(nsIDOMNode
**aEventTarget
);
394 nsresult
FireClipboardEvent(PRUint32 msg
, PRBool
* aPreventDefault
);
397 // Called when the DocViewer is notified that the state
398 // of Printing or PP has changed
399 void SetIsPrintingInDocShellTree(nsIDocShellTreeNode
* aParentNode
,
400 PRBool aIsPrintingOrPP
,
402 #endif // NS_PRINTING
405 // These return the current shell/prescontext etc.
406 nsIPresShell
* GetPresShell();
407 nsPresContext
* GetPresContext();
408 nsIViewManager
* GetViewManager();
410 // IMPORTANT: The ownership implicit in the following member
411 // variables has been explicitly checked and set using nsCOMPtr
412 // for owning pointers and raw COM interface pointers for weak
413 // (ie, non owning) references. If you add any members to this
414 // class, please make the ownership explicit (pinkerton, scc).
416 nsWeakPtr mContainer
; // it owns me!
417 nsCOMPtr
<nsIDeviceContext
> mDeviceContext
; // We create and own this baby
419 // the following six items are explicitly in this order
420 // so they will be destroyed in the reverse order (pinkerton, scc)
421 nsCOMPtr
<nsIDocument
> mDocument
;
422 nsCOMPtr
<nsIWidget
> mWindow
; // ??? should we really own it?
423 nsCOMPtr
<nsIViewManager
> mViewManager
;
424 nsCOMPtr
<nsPresContext
> mPresContext
;
425 nsCOMPtr
<nsIPresShell
> mPresShell
;
427 nsCOMPtr
<nsISelectionListener
> mSelectionListener
;
428 nsCOMPtr
<nsIDOMFocusListener
> mFocusListener
;
430 nsCOMPtr
<nsIContentViewer
> mPreviousViewer
;
431 nsCOMPtr
<nsISHEntry
> mSHEntry
;
433 nsIWidget
* mParentWidget
; // purposely won't be ref counted. May be null
435 // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
437 float mTextZoom
; // Text zoom, defaults to 1.0
440 PRInt16 mNumURLStarts
;
441 PRInt16 mDestroyRefCount
; // a second "refcount" for the document viewer's "destroy"
443 unsigned mEnableRendering
: 1;
444 unsigned mStopped
: 1;
445 unsigned mLoaded
: 1;
446 unsigned mDeferredWindowClose
: 1;
447 // document management data
448 // these items are specific to markup documents (html and xml)
449 // may consider splitting these out into a subclass
450 unsigned mIsSticky
: 1;
451 unsigned mInPermitUnload
: 1;
454 unsigned mClosingWhilePrinting
: 1;
457 // These data members support delayed printing when the document is loading
458 unsigned mPrintIsPending
: 1;
459 unsigned mPrintDocIsFullyLoaded
: 1;
460 nsCOMPtr
<nsIPrintSettings
> mCachedPrintSettings
;
461 nsCOMPtr
<nsIWebProgressListener
> mCachedPrintWebProgressListner
;
463 nsCOMPtr
<nsPrintEngine
> mPrintEngine
;
464 #endif // NS_PRINT_PREVIEW
469 #endif // NS_PRINTING
471 /* character set member data */
472 PRInt32 mHintCharsetSource
;
473 nsCString mHintCharset
;
474 nsCString mDefaultCharacterSet
;
475 nsCString mForceCharacterSet
;
476 nsCString mPrevDocCharacterSet
;
478 PRPackedBool mIsPageMode
;
482 //------------------------------------------------------------------
483 // DocumentViewerImpl
484 //------------------------------------------------------------------
486 static NS_DEFINE_CID(kViewManagerCID
, NS_VIEW_MANAGER_CID
);
487 static NS_DEFINE_CID(kWidgetCID
, NS_CHILD_CID
);
488 static NS_DEFINE_CID(kDeviceContextCID
, NS_DEVICE_CONTEXT_CID
);
490 //------------------------------------------------------------------
492 NS_NewDocumentViewer(nsIDocumentViewer
** aResult
)
494 *aResult
= new DocumentViewerImpl();
496 return NS_ERROR_OUT_OF_MEMORY
;
504 void DocumentViewerImpl::PrepareToStartLoad()
506 mEnableRendering
= PR_TRUE
;
509 mDeferredWindowClose
= PR_FALSE
;
512 mPrintIsPending
= PR_FALSE
;
513 mPrintDocIsFullyLoaded
= PR_FALSE
;
514 mClosingWhilePrinting
= PR_FALSE
;
516 // Make sure we have destroyed it and cleared the data member
518 mPrintEngine
->Destroy();
519 mPrintEngine
= nsnull
;
522 #ifdef NS_PRINT_PREVIEW
523 SetIsPrintPreview(PR_FALSE
);
530 #endif // NS_PRINTING
533 // Note: operator new zeros our memory, so no need to init things to null.
534 DocumentViewerImpl::DocumentViewerImpl()
535 : mTextZoom(1.0), mPageZoom(1.0),
537 mHintCharsetSource(kCharsetUninitialized
)
539 PrepareToStartLoad();
542 NS_IMPL_ADDREF(DocumentViewerImpl
)
543 NS_IMPL_RELEASE(DocumentViewerImpl
)
545 NS_INTERFACE_MAP_BEGIN(DocumentViewerImpl
)
546 NS_INTERFACE_MAP_ENTRY(nsIContentViewer
)
547 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewer
)
548 NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer
)
549 NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile
)
550 NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit
)
551 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint
)
552 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIContentViewer
)
554 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint
)
558 DocumentViewerImpl::~DocumentViewerImpl()
562 mDocument
->Destroy();
565 NS_ASSERTION(!mPresShell
&& !mPresContext
,
566 "User did not call nsIContentViewer::Destroy");
567 if (mPresShell
|| mPresContext
) {
568 // Make sure we don't hand out a reference to the content viewer to
575 // XXX(?) Revoke pending invalidate events
579 * This method is called by the Document Loader once a document has
580 * been created for a particular data stream... The content viewer
581 * must cache this document for later use when Init(...) is called.
583 * This method is also called when an out of band document.write() happens.
584 * In that case, the document passed in is the same as the previous document.
587 DocumentViewerImpl::LoadStart(nsISupports
*aDoc
)
590 printf("DocumentViewerImpl::LoadStart\n");
595 mDocument
= do_QueryInterface(aDoc
, &rv
);
597 else if (mDocument
== aDoc
) {
598 // Reset the document viewer's state back to what it was
599 // when the document load started.
600 PrepareToStartLoad();
607 DocumentViewerImpl::SyncParentSubDocMap()
609 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryReferent(mContainer
));
610 nsCOMPtr
<nsPIDOMWindow
> pwin(do_GetInterface(item
));
611 nsCOMPtr
<nsIContent
> content
;
613 if (mDocument
&& pwin
) {
614 content
= do_QueryInterface(pwin
->GetFrameElementInternal());
618 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
619 item
->GetParent(getter_AddRefs(parent
));
621 nsCOMPtr
<nsIDOMWindow
> parent_win(do_GetInterface(parent
));
624 nsCOMPtr
<nsIDOMDocument
> dom_doc
;
625 parent_win
->GetDocument(getter_AddRefs(dom_doc
));
627 nsCOMPtr
<nsIDocument
> parent_doc(do_QueryInterface(dom_doc
));
630 return parent_doc
->SetSubDocumentFor(content
, mDocument
);
639 DocumentViewerImpl::SetContainer(nsISupports
* aContainer
)
641 mContainer
= do_GetWeakReference(aContainer
);
643 mPresContext
->SetContainer(aContainer
);
646 // We're loading a new document into the window where this document
647 // viewer lives, sync the parent document's frame element -> sub
650 return SyncParentSubDocMap();
654 DocumentViewerImpl::GetContainer(nsISupports
** aResult
)
656 NS_ENSURE_ARG_POINTER(aResult
);
659 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
660 container
.swap(*aResult
);
665 DocumentViewerImpl::Init(nsIWidget
* aParentWidget
,
666 const nsRect
& aBounds
)
668 nsresult rv
= CreateDeviceContext(aParentWidget
);
669 NS_ENSURE_SUCCESS(rv
, rv
);
671 return InitInternal(aParentWidget
, nsnull
, aBounds
, PR_TRUE
, PR_FALSE
);
675 DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow
, PRBool aReenableRefresh
)
677 // Create the style set...
678 nsStyleSet
*styleSet
;
679 nsresult rv
= CreateStyleSet(mDocument
, &styleSet
);
680 NS_ENSURE_SUCCESS(rv
, rv
);
682 // Now make the shell for the document
683 rv
= mDocument
->CreateShell(mPresContext
, mViewManager
, styleSet
,
684 getter_AddRefs(mPresShell
));
690 // We're done creating the style set
691 styleSet
->EndUpdate();
693 if (aDoInitialReflow
) {
694 // Since InitialReflow() will create frames for *all* items
695 // that are currently in the document tree, we need to flush
696 // any pending notifications to prevent the content sink from
697 // duplicating layout frames for content it has added to the tree
698 // but hasn't notified the document about. (Bug 154018)
700 // Note that we are flushing before we add mPresShell as an observer
701 // to avoid bogus notifications.
703 mDocument
->FlushPendingNotifications(Flush_ContentAndNotify
);
706 mPresShell
->BeginObservingDocument();
708 // Initialize our view manager
710 mWindow
->GetBounds(bounds
);
712 nscoord width
= mPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds
.width
;
713 nscoord height
= mPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds
.height
;
715 mViewManager
->DisableRefresh();
716 mViewManager
->SetWindowDimensions(width
, height
);
717 mPresContext
->SetTextZoom(mTextZoom
);
718 mPresContext
->SetFullZoom(mPageZoom
);
720 // Setup default view manager background color
722 // This may be overridden by the docshell with the background color
723 // for the last document loaded into the docshell
724 mViewManager
->SetDefaultBackgroundColor(mPresContext
->DefaultBackgroundColor());
726 if (aDoInitialReflow
) {
727 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(mDocument
);
729 nsCOMPtr
<nsIDOMHTMLFrameSetElement
> frameset
=
730 do_QueryInterface(mDocument
->GetRootContent());
731 htmlDoc
->SetIsFrameset(frameset
!= nsnull
);
734 nsCOMPtr
<nsIPresShell
> shellGrip
= mPresShell
;
736 mPresShell
->InitialReflow(width
, height
);
738 // Store the visible area so it's available for other callers of
739 // InitialReflow, like nsContentSink::StartLayout.
740 mPresContext
->SetVisibleArea(nsRect(0, 0, width
, height
));
743 // Now trigger a refresh
744 if (aReenableRefresh
&& mEnableRendering
&& mViewManager
) {
745 mViewManager
->EnableRefresh(NS_VMREFRESH_IMMEDIATE
);
748 // now register ourselves as a selection listener, so that we get
749 // called when the selection changes in the window
750 nsDocViewerSelectionListener
*selectionListener
=
751 new nsDocViewerSelectionListener();
752 NS_ENSURE_TRUE(selectionListener
, NS_ERROR_OUT_OF_MEMORY
);
754 selectionListener
->Init(this);
756 // mSelectionListener is a owning reference
757 mSelectionListener
= selectionListener
;
759 nsCOMPtr
<nsISelection
> selection
;
760 rv
= GetDocumentSelection(getter_AddRefs(selection
));
761 NS_ENSURE_SUCCESS(rv
, rv
);
763 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
764 rv
= selPrivate
->AddSelectionListener(mSelectionListener
);
768 // Save old listener so we can unregister it
769 nsCOMPtr
<nsIDOMFocusListener
> oldFocusListener
= mFocusListener
;
773 // now register ourselves as a focus listener, so that we get called
774 // when the focus changes in the window
775 nsDocViewerFocusListener
*focusListener
;
776 NS_NEWXPCOM(focusListener
, nsDocViewerFocusListener
);
777 NS_ENSURE_TRUE(focusListener
, NS_ERROR_OUT_OF_MEMORY
);
779 focusListener
->Init(this);
781 // mFocusListener is a strong reference
782 mFocusListener
= focusListener
;
785 rv
= mDocument
->AddEventListenerByIID(mFocusListener
,
786 NS_GET_IID(nsIDOMFocusListener
));
787 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to register focus listener");
788 if (oldFocusListener
) {
789 rv
= mDocument
->RemoveEventListenerByIID(oldFocusListener
,
790 NS_GET_IID(nsIDOMFocusListener
));
791 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to remove focus listener");
798 //-----------------------------------------------
799 // This method can be used to initial the "presentation"
800 // The aDoCreation indicates whether it should create
801 // all the new objects or just initialize the existing ones
803 DocumentViewerImpl::InitInternal(nsIWidget
* aParentWidget
,
805 const nsRect
& aBounds
,
807 PRBool aInPrintPreview
,
808 PRBool aNeedMakeCX
/*= PR_TRUE*/)
810 mParentWidget
= aParentWidget
; // not ref counted
813 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NULL_POINTER
);
815 PRBool makeCX
= PR_FALSE
;
817 // XXXbz this is a nasty hack to do with the fact that we create
818 // presentations both in Init() and in Show()... Ideally we would only do
819 // it in one place (Show()) and require that callers call init(), open(),
820 // show() in that order or something.
821 if ((aParentWidget
|| mDocument
->GetDisplayDocument()) && !mPresContext
) {
822 // Create presentation context
824 //Presentation context already created in SetPageMode which is calling this method
828 new nsPresContext(mDocument
, nsPresContext::eContext_Galley
);
829 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
831 nsresult rv
= mPresContext
->Init(mDeviceContext
);
833 mPresContext
= nsnull
;
837 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
838 makeCX
= !GetIsPrintPreview() && aNeedMakeCX
; // needs to be true except when we are already in PP or we are enabling/disabling paginated mode.
845 // Create the ViewManager and Root View...
847 // We must do this before we tell the script global object about
848 // this new document since doing that will cause us to re-enter
849 // into nsSubDocumentFrame code through reflows caused by
850 // FlushPendingNotifications() calls down the road...
852 rv
= MakeWindow(nsSize(mPresContext
->DevPixelsToAppUnits(aBounds
.width
),
853 mPresContext
->DevPixelsToAppUnits(aBounds
.height
)));
854 NS_ENSURE_SUCCESS(rv
, rv
);
857 #ifdef NS_PRINT_PREVIEW
859 // I'm leaving this in a broken state for the moment; we should
860 // be measuring/scaling with the print device context, not the
861 // screen device context, but this is good enough to allow
862 // printing reftests to work.
864 nsCOMPtr
<nsIDeviceContextSpec
> devspec
=
865 do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv
);
866 NS_ENSURE_SUCCESS(rv
, rv
);
867 // mWindow has been initialized by preceding call to MakeWindow
868 rv
= devspec
->Init(mWindow
, mPresContext
->GetPrintSettings(), PR_FALSE
);
869 NS_ENSURE_SUCCESS(rv
, rv
);
870 nsCOMPtr
<nsIDeviceContext
> devctx
=
871 do_CreateInstance("@mozilla.org/gfx/devicecontext;1", &rv
);
872 NS_ENSURE_SUCCESS(rv
, rv
);
873 rv
= devctx
->InitForPrinting(devspec
);
874 NS_ENSURE_SUCCESS(rv
, rv
);
875 // XXX I'm breaking this code; I'm not sure I really want to mess with
876 // the document viewer at the moment to get the right device context
877 // (this won't break anyone, since page layout mode was never really
880 double pageWidth
= 0, pageHeight
= 0;
881 mPresContext
->GetPrintSettings()->GetEffectivePageSize(&pageWidth
,
883 mPresContext
->SetPageSize(
884 nsSize(mPresContext
->TwipsToAppUnits(NSToIntFloor(pageWidth
)),
885 mPresContext
->TwipsToAppUnits(NSToIntFloor(pageHeight
))));
886 mPresContext
->SetIsRootPaginatedDocument(PR_TRUE
);
887 mPresContext
->SetPageScale(1.0f
);
893 nsCOMPtr
<nsIInterfaceRequestor
> requestor(do_QueryReferent(mContainer
));
896 nsCOMPtr
<nsILinkHandler
> linkHandler
;
897 requestor
->GetInterface(NS_GET_IID(nsILinkHandler
),
898 getter_AddRefs(linkHandler
));
900 mPresContext
->SetContainer(requestor
);
901 mPresContext
->SetLinkHandler(linkHandler
);
904 if (!aInPrintPreview
) {
905 // Set script-context-owner in the document
907 nsCOMPtr
<nsPIDOMWindow
> window
;
908 requestor
->GetInterface(NS_GET_IID(nsPIDOMWindow
),
909 getter_AddRefs(window
));
912 window
->SetNewDocument(mDocument
, aState
, PR_TRUE
);
914 nsJSContext::LoadStart();
919 if (aDoCreation
&& mPresContext
) {
920 // The ViewManager and Root View was created above (in
923 rv
= InitPresentationStuff(!makeCX
, !makeCX
);
930 // LoadComplete(aStatus)
932 // aStatus - The status returned from loading the document.
934 // This method is called by the container when the document has been
935 // completely loaded.
938 DocumentViewerImpl::LoadComplete(nsresult aStatus
)
940 /* We need to protect ourself against auto-destruction in case the
941 window is closed while processing the OnLoad event. See bug
942 http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
945 nsCOMPtr
<nsIDocumentViewer
> kungFuDeathGrip(this);
947 // Flush out layout so it's up-to-date by the time onload is called.
948 // Note that this could destroy the window, so do this before
949 // checking for our mDocument and its window.
950 if (mPresShell
&& !mStopped
) {
951 // Hold strong ref because this could conceivably run script
952 nsCOMPtr
<nsIPresShell
> shell
= mPresShell
;
953 shell
->FlushPendingNotifications(Flush_Layout
);
957 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
959 // First, get the window from the document...
960 nsPIDOMWindow
*window
= mDocument
->GetWindow();
964 // Now, fire either an OnLoad or OnError event to the document...
965 PRBool restoring
= PR_FALSE
;
966 // XXXbz imagelib kills off the document load for a full-page image with
967 // NS_IMAGELIB_ERROR_LOAD_ABORTED if it's in the cache. So we want to treat
968 // that one as a success code; otherwise whether we fire onload for the image
969 // will depend on whether it's cached!
971 (NS_SUCCEEDED(aStatus
) || aStatus
== NS_IMAGELIB_ERROR_LOAD_ABORTED
)) {
972 nsEventStatus status
= nsEventStatus_eIgnore
;
973 nsEvent
event(PR_TRUE
, NS_LOAD
);
974 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
975 // XXX Dispatching to |window|, but using |document| as the target.
976 event
.target
= mDocument
;
978 // If the document presentation is being restored, we don't want to fire
979 // onload to the document content since that would likely confuse scripts
982 nsIDocShell
*docShell
= window
->GetDocShell();
983 NS_ENSURE_TRUE(docShell
, NS_ERROR_UNEXPECTED
);
985 docShell
->GetRestoringDocument(&restoring
);
987 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
,
990 // if navigator.xul's load is complete, the main nav window is visible
993 //printf("DEBUG: getting uri from document (%p)\n", mDocument.get());
995 nsIURI
*uri
= mDocument
? mDocument
->GetDocumentURI() : nsnull
;
998 //printf("DEBUG: getting spec for uri (%p)\n", uri.get());
1001 if (spec
.EqualsLiteral("chrome://navigator/content/navigator.xul") ||
1002 spec
.EqualsLiteral("chrome://browser/content/browser.xul")) {
1003 NS_TIMELINE_MARK("Navigator Window visible now");
1006 #endif /* MOZ_TIMELINE */
1009 // XXX: Should fire error event to the document...
1012 // Notify the document that it has been shown (regardless of whether
1013 // it was just loaded). Note: mDocument may be null now if the above
1014 // firing of onload caused the document to unload.
1016 mDocument
->OnPageShow(restoring
);
1018 // Now that the document has loaded, we can tell the presshell
1019 // to unsuppress painting.
1020 if (mPresShell
&& !mStopped
) {
1021 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
);
1022 mPresShell
->UnsuppressPainting();
1023 // mPresShell could have been removed now, see bug 378682/421432
1025 mPresShell
->ScrollToAnchor();
1029 nsJSContext::LoadEnd();
1032 // Check to see if someone tried to print during the load
1033 if (mPrintIsPending
) {
1034 mPrintIsPending
= PR_FALSE
;
1035 mPrintDocIsFullyLoaded
= PR_TRUE
;
1036 Print(mCachedPrintSettings
, mCachedPrintWebProgressListner
);
1037 mCachedPrintSettings
= nsnull
;
1038 mCachedPrintWebProgressListner
= nsnull
;
1046 DocumentViewerImpl::PermitUnload(PRBool
*aPermitUnload
)
1048 *aPermitUnload
= PR_TRUE
;
1050 if (!mDocument
|| mInPermitUnload
) {
1054 // First, get the script global object from the document...
1055 nsPIDOMWindow
*window
= mDocument
->GetWindow();
1058 // This is odd, but not fatal
1059 NS_WARNING("window not set for document!");
1063 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "This is unsafe");
1065 // Now, fire an BeforeUnload event to the document and see if it's ok
1067 nsEventStatus status
= nsEventStatus_eIgnore
;
1068 nsBeforePageUnloadEvent
event(PR_TRUE
, NS_BEFORE_PAGE_UNLOAD
);
1069 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
1070 // XXX Dispatching to |window|, but using |document| as the target.
1071 event
.target
= mDocument
;
1072 nsresult rv
= NS_OK
;
1074 // In evil cases we might be destroyed while handling the
1075 // onbeforeunload event, don't let that happen. (see also bug#331040)
1076 nsRefPtr
<DocumentViewerImpl
> kungFuDeathGrip(this);
1079 // Never permit popups from the beforeunload handler, no matter
1081 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
1083 mInPermitUnload
= PR_TRUE
;
1084 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
, &status
);
1085 mInPermitUnload
= PR_FALSE
;
1088 nsCOMPtr
<nsIDocShellTreeNode
> docShellNode(do_QueryReferent(mContainer
));
1090 if (NS_SUCCEEDED(rv
) && (event
.flags
& NS_EVENT_FLAG_NO_DEFAULT
||
1091 !event
.text
.IsEmpty())) {
1092 // Ask the user if it's ok to unload the current page
1094 nsCOMPtr
<nsIPrompt
> prompt
= do_GetInterface(docShellNode
);
1097 nsXPIDLString preMsg
, postMsg
;
1098 rv
= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES
,
1099 "OnBeforeUnloadPreMessage",
1101 rv
|= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES
,
1102 "OnBeforeUnloadPostMessage",
1105 // GetStringFromName can succeed, yet give NULL strings back.
1106 if (NS_FAILED(rv
) || preMsg
.IsEmpty() || postMsg
.IsEmpty()) {
1107 NS_ERROR("Failed to get strings from dom.properties!");
1111 // Limit the length of the text the page can inject into this
1112 // dialogue to 1024 characters.
1113 PRInt32 len
= PR_MIN(event
.text
.Length(), 1024);
1117 msg
= preMsg
+ NS_LITERAL_STRING("\n\n") + postMsg
;
1119 msg
= preMsg
+ NS_LITERAL_STRING("\n\n") +
1120 StringHead(event
.text
, len
) +
1121 NS_LITERAL_STRING("\n\n") + postMsg
;
1124 // This doesn't pass a title, which makes the title be
1125 // "Confirm", is that ok, or do we want a localizable title for
1127 if (NS_FAILED(prompt
->Confirm(nsnull
, msg
.get(), aPermitUnload
))) {
1128 *aPermitUnload
= PR_TRUE
;
1135 docShellNode
->GetChildCount(&childCount
);
1137 for (PRInt32 i
= 0; i
< childCount
&& *aPermitUnload
; ++i
) {
1138 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1139 docShellNode
->GetChildAt(i
, getter_AddRefs(item
));
1141 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(item
));
1144 nsCOMPtr
<nsIContentViewer
> cv
;
1145 docShell
->GetContentViewer(getter_AddRefs(cv
));
1148 cv
->PermitUnload(aPermitUnload
);
1158 DocumentViewerImpl::PageHide(PRBool aIsUnload
)
1160 mEnableRendering
= PR_FALSE
;
1163 return NS_ERROR_NULL_POINTER
;
1166 mDocument
->OnPageHide(!aIsUnload
);
1168 // if Destroy() was called during OnPageHide(), mDocument is nsnull.
1169 NS_ENSURE_STATE(mDocument
);
1171 // First, get the window from the document...
1172 nsPIDOMWindow
*window
= mDocument
->GetWindow();
1175 // Fail if no window is available...
1176 NS_ERROR("window not set for document!");
1177 return NS_ERROR_NULL_POINTER
;
1180 // Now, fire an Unload event to the document...
1181 nsEventStatus status
= nsEventStatus_eIgnore
;
1182 nsEvent
event(PR_TRUE
, NS_PAGE_UNLOAD
);
1183 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
1184 // XXX Dispatching to |window|, but using |document| as the target.
1185 event
.target
= mDocument
;
1187 // Never permit popups from the unload handler, no matter how we get
1189 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
1191 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
, &status
);
1195 // look for open menupopups and close them after the unload event, in case
1196 // the unload event listeners open any new popups
1198 nsContentUtils::HidePopupsInDocument(mDocument
);
1205 AttachContainerRecurse(nsIDocShell
* aShell
)
1207 nsCOMPtr
<nsIContentViewer
> viewer
;
1208 aShell
->GetContentViewer(getter_AddRefs(viewer
));
1209 nsCOMPtr
<nsIDocumentViewer
> docViewer
= do_QueryInterface(viewer
);
1211 nsCOMPtr
<nsIDocument
> doc
;
1212 docViewer
->GetDocument(getter_AddRefs(doc
));
1214 doc
->SetContainer(aShell
);
1216 nsCOMPtr
<nsPresContext
> pc
;
1217 docViewer
->GetPresContext(getter_AddRefs(pc
));
1219 pc
->SetContainer(aShell
);
1220 pc
->SetLinkHandler(nsCOMPtr
<nsILinkHandler
>(do_QueryInterface(aShell
)));
1222 nsCOMPtr
<nsIPresShell
> presShell
;
1223 docViewer
->GetPresShell(getter_AddRefs(presShell
));
1225 presShell
->SetForwardingContainer(nsnull
);
1229 // Now recurse through the children
1230 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(aShell
);
1231 NS_ASSERTION(node
, "docshells must implement nsIDocShellTreeNode");
1234 node
->GetChildCount(&childCount
);
1235 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
1236 nsCOMPtr
<nsIDocShellTreeItem
> childItem
;
1237 node
->GetChildAt(i
, getter_AddRefs(childItem
));
1238 AttachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(childItem
)));
1243 DocumentViewerImpl::Open(nsISupports
*aState
, nsISHEntry
*aSHEntry
)
1245 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
1248 mWindow
->GetBounds(bounds
);
1251 mDocument
->SetContainer(nsCOMPtr
<nsISupports
>(do_QueryReferent(mContainer
)));
1253 nsresult rv
= InitInternal(mParentWidget
, aState
, bounds
, PR_FALSE
, PR_FALSE
);
1254 NS_ENSURE_SUCCESS(rv
, rv
);
1257 mPresShell
->SetForwardingContainer(nsnull
);
1259 // Rehook the child presentations. The child shells are still in
1260 // session history, so get them from there.
1263 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1264 PRInt32 itemIndex
= 0;
1265 while (NS_SUCCEEDED(aSHEntry
->ChildShellAt(itemIndex
++,
1266 getter_AddRefs(item
))) && item
) {
1267 AttachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(item
)));
1271 SyncParentSubDocMap();
1273 if (mFocusListener
&& mDocument
) {
1274 mDocument
->AddEventListenerByIID(mFocusListener
,
1275 NS_GET_IID(nsIDOMFocusListener
));
1278 // XXX re-enable image animations once that works correctly
1280 PrepareToStartLoad();
1285 DocumentViewerImpl::Close(nsISHEntry
*aSHEntry
)
1287 // All callers are supposed to call close to break circular
1288 // references. If we do this stuff in the destructor, the
1289 // destructor might never be called (especially if we're being
1292 mSHEntry
= aSHEntry
;
1294 // Close is also needed to disable scripts during paint suppression,
1295 // since we transfer the existing global object to the new document
1296 // that is loaded. In the future, the global object may become a proxy
1297 // for an object that can be switched in and out so that we don't need
1298 // to disable scripts during paint suppression.
1303 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
1304 // Turn scripting back on
1305 // after PrintPreview had turned it off
1306 if (GetIsPrintPreview() && mPrintEngine
) {
1307 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
1312 // A Close was called while we were printing
1313 // so don't clear the ScriptGlobalObject
1314 // or clear the mDocument below
1315 if (mPrintEngine
&& !mClosingWhilePrinting
) {
1316 mClosingWhilePrinting
= PR_TRUE
;
1320 // out of band cleanup of webshell
1321 mDocument
->SetScriptGlobalObject(nsnull
);
1323 if (!mSHEntry
&& mDocument
)
1324 mDocument
->RemovedFromDocShell();
1327 if (mFocusListener
&& mDocument
) {
1328 mDocument
->RemoveEventListenerByIID(mFocusListener
,
1329 NS_GET_IID(nsIDOMFocusListener
));
1336 DetachContainerRecurse(nsIDocShell
*aShell
)
1338 // Unhook this docshell's presentation
1339 nsCOMPtr
<nsIContentViewer
> viewer
;
1340 aShell
->GetContentViewer(getter_AddRefs(viewer
));
1341 nsCOMPtr
<nsIDocumentViewer
> docViewer
= do_QueryInterface(viewer
);
1343 nsCOMPtr
<nsIDocument
> doc
;
1344 docViewer
->GetDocument(getter_AddRefs(doc
));
1346 doc
->SetContainer(nsnull
);
1348 nsCOMPtr
<nsPresContext
> pc
;
1349 docViewer
->GetPresContext(getter_AddRefs(pc
));
1351 pc
->SetContainer(nsnull
);
1352 pc
->SetLinkHandler(nsnull
);
1354 nsCOMPtr
<nsIPresShell
> presShell
;
1355 docViewer
->GetPresShell(getter_AddRefs(presShell
));
1357 presShell
->SetForwardingContainer(nsWeakPtr(do_GetWeakReference(aShell
)));
1361 // Now recurse through the children
1362 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(aShell
);
1363 NS_ASSERTION(node
, "docshells must implement nsIDocShellTreeNode");
1366 node
->GetChildCount(&childCount
);
1367 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
1368 nsCOMPtr
<nsIDocShellTreeItem
> childItem
;
1369 node
->GetChildAt(i
, getter_AddRefs(childItem
));
1370 DetachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(childItem
)));
1375 DocumentViewerImpl::Destroy()
1377 NS_ASSERTION(mDocument
, "No document in Destroy()!");
1380 // Here is where we check to see if the docment was still being prepared
1381 // for printing when it was asked to be destroy from someone externally
1382 // This usually happens if the document is unloaded while the user is in the Print Dialog
1384 // So we flip the bool to remember that the document is going away
1385 // and we can clean up and abort later after returning from the Print Dialog
1387 if (mPrintEngine
->CheckBeforeDestroy()) {
1393 // Don't let the document get unloaded while we are printing.
1394 // this could happen if we hit the back button during printing.
1395 // We also keep the viewer from being cached in session history, since
1396 // we require all documents there to be sanitized.
1397 if (mDestroyRefCount
!= 0) {
1402 // If we were told to put ourselves into session history instead of destroy
1403 // the presentation, do that now.
1406 mPresShell
->Freeze();
1408 // Make sure the presentation isn't torn down by Hide().
1409 mSHEntry
->SetSticky(mIsSticky
);
1410 mIsSticky
= PR_TRUE
;
1412 PRBool savePresentation
= PR_TRUE
;
1414 // Remove our root view from the view hierarchy.
1416 nsIViewManager
*vm
= mPresShell
->GetViewManager();
1418 nsIView
*rootView
= nsnull
;
1419 vm
->GetRootView(rootView
);
1422 nsIView
*rootViewParent
= rootView
->GetParent();
1423 if (rootViewParent
) {
1424 nsIViewManager
*parentVM
= rootViewParent
->GetViewManager();
1426 parentVM
->RemoveChild(rootView
);
1435 // This is after Hide() so that the user doesn't see the inputs clear.
1437 nsresult rv
= mDocument
->Sanitize();
1438 if (NS_FAILED(rv
)) {
1439 // If we failed to sanitize, don't save presentation.
1440 savePresentation
= PR_FALSE
;
1445 // Reverse ownership. Do this *after* calling sanitize so that sanitize
1446 // doesn't cause mutations that make the SHEntry drop the presentation
1447 if (savePresentation
) {
1448 mSHEntry
->SetContentViewer(this);
1451 mSHEntry
->SyncPresentationState();
1453 nsCOMPtr
<nsISHEntry
> shEntry
= mSHEntry
; // we'll need this below
1456 // Break the link from the document/presentation to the docshell, so that
1457 // link traversals cannot affect the currently-loaded document.
1458 // When the presentation is restored, Open() and InitInternal() will reset
1459 // these pointers to their original values.
1462 mDocument
->SetContainer(nsnull
);
1464 mPresContext
->SetLinkHandler(nsnull
);
1465 mPresContext
->SetContainer(nsnull
);
1468 mPresShell
->SetForwardingContainer(mContainer
);
1470 // Do the same for our children. Note that we need to get the child
1471 // docshells from the SHEntry now; the docshell will have cleared them.
1472 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1473 PRInt32 itemIndex
= 0;
1474 while (NS_SUCCEEDED(shEntry
->ChildShellAt(itemIndex
++,
1475 getter_AddRefs(item
))) && item
) {
1476 DetachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(item
)));
1483 mDocument
->Destroy();
1487 // All callers are supposed to call destroy to break circular
1488 // references. If we do this stuff in the destructor, the
1489 // destructor might never be called (especially if we're being
1494 #ifdef NS_PRINT_PREVIEW
1495 PRBool doingPrintPreview
;
1496 mPrintEngine
->GetDoingPrintPreview(&doingPrintPreview
);
1497 if (doingPrintPreview
) {
1498 mPrintEngine
->FinishPrintPreview();
1502 mPrintEngine
->Destroy();
1503 mPrintEngine
= nsnull
;
1507 // Avoid leaking the old viewer.
1508 if (mPreviousViewer
) {
1509 mPreviousViewer
->Destroy();
1510 mPreviousViewer
= nsnull
;
1513 mDeviceContext
= nsnull
;
1516 // Break circular reference (or something)
1517 mPresShell
->EndObservingDocument();
1519 nsCOMPtr
<nsISelection
> selection
;
1520 GetDocumentSelection(getter_AddRefs(selection
));
1522 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
1524 if (selPrivate
&& mSelectionListener
)
1525 selPrivate
->RemoveSelectionListener(mSelectionListener
);
1527 mPresShell
->Destroy();
1528 mPresShell
= nsnull
;
1532 mPresContext
->SetContainer(nsnull
);
1533 mPresContext
->SetLinkHandler(nsnull
);
1534 mPresContext
= nsnull
;
1537 mContainer
= nsnull
;
1543 DocumentViewerImpl::Stop(void)
1545 NS_ASSERTION(mDocument
, "Stop called too early or too late");
1547 mDocument
->StopDocumentLoad();
1550 if (mEnableRendering
&& (mLoaded
|| mStopped
) && mPresContext
&& !mSHEntry
)
1551 mPresContext
->SetImageAnimationMode(imgIContainer::kDontAnimMode
);
1555 if (!mLoaded
&& mPresShell
) {
1556 // Well, we might as well paint what we have so far.
1557 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
); // bug 378682
1558 mPresShell
->UnsuppressPainting();
1565 DocumentViewerImpl::GetDOMDocument(nsIDOMDocument
**aResult
)
1567 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1568 return CallQueryInterface(mDocument
, aResult
);
1572 DocumentViewerImpl::SetDOMDocument(nsIDOMDocument
*aDocument
)
1576 // 1) this document viewer has been initialized with a call to Init().
1577 // 2) the stylesheets associated with the document have been added
1580 // XXX Right now, this method assumes that the layout of the current
1581 // document hasn't started yet. More cleanup will probably be
1582 // necessary to make this method work for the case when layout *has*
1583 // occurred for the current document.
1584 // That work can happen when and if it is needed.
1588 return NS_ERROR_NULL_POINTER
;
1590 nsCOMPtr
<nsIDocument
> newDoc
= do_QueryInterface(aDocument
, &rv
);
1591 if (NS_FAILED(rv
)) return rv
;
1593 // Set new container
1594 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
1595 newDoc
->SetContainer(container
);
1597 if (mDocument
!= newDoc
) {
1598 // Replace the old document with the new one. Do this only when
1599 // the new document really is a new document.
1602 // Set the script global object on the new document
1603 nsCOMPtr
<nsPIDOMWindow
> window
= do_GetInterface(container
);
1605 window
->SetNewDocument(newDoc
, nsnull
, PR_TRUE
);
1608 // Clear the list of old child docshells. CChild docshells for the new
1609 // document will be constructed as frames are created.
1610 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(container
);
1613 node
->GetChildCount(&count
);
1614 for (PRInt32 i
= 0; i
< count
; ++i
) {
1615 nsCOMPtr
<nsIDocShellTreeItem
> child
;
1616 node
->GetChildAt(0, getter_AddRefs(child
));
1617 node
->RemoveChild(child
);
1622 rv
= SyncParentSubDocMap();
1623 NS_ENSURE_SUCCESS(rv
, rv
);
1625 // Replace the current pres shell with a new shell for the new document
1627 nsCOMPtr
<nsILinkHandler
> linkHandler
;
1629 nsSize
currentSize(0, 0);
1632 mViewManager
->GetWindowDimensions(¤tSize
.width
, ¤tSize
.height
);
1636 // Save the linkhandler (nsPresShell::Destroy removes it from
1638 linkHandler
= mPresContext
->GetLinkHandler();
1641 mPresShell
->EndObservingDocument();
1642 mPresShell
->Destroy();
1644 mPresShell
= nsnull
;
1646 // This destroys the root view because it was associated with the root frame,
1647 // which has been torn down. Recreate the viewmanager and root view.
1648 MakeWindow(currentSize
);
1651 // And if we're already given a prescontext...
1653 // If we had a linkHandler and it got removed, put it back.
1655 mPresContext
->SetLinkHandler(linkHandler
);
1658 rv
= InitPresentationStuff(PR_FALSE
, PR_TRUE
);
1665 DocumentViewerImpl::GetDocument(nsIDocument
** aResult
)
1667 NS_IF_ADDREF(*aResult
= mDocument
);
1673 DocumentViewerImpl::GetPresShell()
1675 if (!GetIsPrintPreview()) {
1678 NS_ENSURE_TRUE(mDocument
, nsnull
);
1679 nsCOMPtr
<nsIPresShell
> shell
;
1680 nsCOMPtr
<nsIPresShell
> currentShell
;
1681 nsPresShellIterator
iter(mDocument
);
1682 while ((shell
= iter
.GetNextShell())) {
1683 currentShell
.swap(shell
);
1685 return currentShell
.get();
1689 DocumentViewerImpl::GetPresContext()
1691 if (!GetIsPrintPreview()) {
1692 return mPresContext
;
1694 nsIPresShell
* shell
= GetPresShell();
1695 return shell
? shell
->GetPresContext() : nsnull
;
1699 DocumentViewerImpl::GetViewManager()
1701 if (!GetIsPrintPreview()) {
1702 return mViewManager
;
1704 nsIPresShell
* shell
= GetPresShell();
1705 return shell
? shell
->GetViewManager() : nsnull
;
1709 DocumentViewerImpl::GetPresShell(nsIPresShell
** aResult
)
1711 nsIPresShell
* shell
= GetPresShell();
1712 NS_IF_ADDREF(*aResult
= shell
);
1717 DocumentViewerImpl::GetPresContext(nsPresContext
** aResult
)
1719 nsPresContext
* pc
= GetPresContext();
1720 NS_IF_ADDREF(*aResult
= pc
);
1725 DocumentViewerImpl::GetBounds(nsRect
& aResult
)
1727 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1728 NS_PRECONDITION(mWindow
, "null window");
1730 mWindow
->GetBounds(aResult
);
1733 aResult
.SetRect(0, 0, 0, 0);
1739 DocumentViewerImpl::GetPreviousViewer(nsIContentViewer
** aViewer
)
1741 *aViewer
= mPreviousViewer
;
1742 NS_IF_ADDREF(*aViewer
);
1747 DocumentViewerImpl::SetPreviousViewer(nsIContentViewer
* aViewer
)
1749 // NOTE: |Show| sets |mPreviousViewer| to null without calling this
1753 NS_ASSERTION(!mPreviousViewer
,
1754 "can't set previous viewer when there already is one");
1756 // In a multiple chaining situation (which occurs when running a thrashing
1757 // test like i-bench or jrgm's tests with no delay), we can build up a
1758 // whole chain of viewers. In order to avoid this, we always set our previous
1759 // viewer to the MOST previous viewer in the chain, and then dump the intermediate
1760 // link from the chain. This ensures that at most only 2 documents are alive
1761 // and undestroyed at any given time (the one that is showing and the one that
1762 // is loading with painting suppressed).
1763 // It's very important that if this ever gets changed the code
1764 // before the RestorePresentation call in nsDocShell::InternalLoad
1765 // be changed accordingly.
1766 nsCOMPtr
<nsIContentViewer
> prevViewer
;
1767 aViewer
->GetPreviousViewer(getter_AddRefs(prevViewer
));
1769 aViewer
->SetPreviousViewer(nsnull
);
1771 return SetPreviousViewer(prevViewer
);
1775 mPreviousViewer
= aViewer
;
1780 DocumentViewerImpl::SetBounds(const nsRect
& aBounds
)
1782 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1785 // Don't have the widget repaint. Layout will generate repaint requests
1787 mWindow
->Resize(aBounds
.x
, aBounds
.y
, aBounds
.width
, aBounds
.height
,
1791 // If there's a previous viewer, it's the one that's actually showing,
1792 // so be sure to resize it as well so it paints over the right area.
1793 // This may slow down the performance of the new page load, but resize
1794 // during load is also probably a relatively unusual condition
1795 // relating to things being hidden while something is loaded. It so
1796 // happens that Firefox does this a good bit with its infobar, and it
1797 // looks ugly if we don't do this.
1798 if (mPreviousViewer
)
1799 mPreviousViewer
->SetBounds(aBounds
);
1801 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
1802 if (GetIsPrintPreview() && !mPrintEngine
->GetIsCreatingPrintPreview()) {
1803 mPrintEngine
->GetPrintPreviewWindow()->Resize(aBounds
.x
, aBounds
.y
,
1804 aBounds
.width
, aBounds
.height
,
1812 DocumentViewerImpl::Move(PRInt32 aX
, PRInt32 aY
)
1814 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1815 NS_PRECONDITION(mWindow
, "null window");
1817 mWindow
->Move(aX
, aY
);
1823 DocumentViewerImpl::Show(void)
1825 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1827 // We don't need the previous viewer anymore since we're not
1829 if (mPreviousViewer
) {
1830 // This little dance *may* only be to keep
1831 // PresShell::EndObservingDocument happy, but I'm not sure.
1832 nsCOMPtr
<nsIContentViewer
> prevViewer(mPreviousViewer
);
1833 mPreviousViewer
= nsnull
;
1834 prevViewer
->Destroy();
1836 // Make sure we don't have too many cached ContentViewers
1837 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryReferent(mContainer
);
1839 // We need to find the root DocShell since only that object has an
1840 // SHistory and we need the SHistory to evict content viewers
1841 nsCOMPtr
<nsIDocShellTreeItem
> root
;
1842 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
1843 nsCOMPtr
<nsIWebNavigation
> webNav
= do_QueryInterface(root
);
1844 nsCOMPtr
<nsISHistory
> history
;
1845 webNav
->GetSessionHistory(getter_AddRefs(history
));
1846 nsCOMPtr
<nsISHistoryInternal
> historyInt
= do_QueryInterface(history
);
1848 PRInt32 prevIndex
,loadedIndex
;
1849 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(treeItem
);
1850 docShell
->GetPreviousTransIndex(&prevIndex
);
1851 docShell
->GetLoadedTransIndex(&loadedIndex
);
1852 #ifdef DEBUG_PAGE_CACHE
1853 printf("About to evict content viewers: prev=%d, loaded=%d\n",
1854 prevIndex
, loadedIndex
);
1856 historyInt
->EvictContentViewers(prevIndex
, loadedIndex
);
1862 mWindow
->Show(PR_TRUE
);
1865 if (mDocument
&& !mPresShell
&& !mWindow
) {
1866 nsCOMPtr
<nsIBaseWindow
> base_win(do_QueryReferent(mContainer
));
1868 base_win
->GetParentWidget(&mParentWidget
);
1869 NS_ENSURE_TRUE(mParentWidget
, NS_ERROR_UNEXPECTED
);
1870 mParentWidget
->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
1873 nsresult rv
= CreateDeviceContext(mParentWidget
);
1874 NS_ENSURE_SUCCESS(rv
, rv
);
1876 // Create presentation context
1877 NS_ASSERTION(!mPresContext
, "Shouldn't have a prescontext if we have no shell!");
1878 mPresContext
= new nsPresContext(mDocument
, nsPresContext::eContext_Galley
);
1879 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
1881 rv
= mPresContext
->Init(mDeviceContext
);
1882 if (NS_FAILED(rv
)) {
1883 mPresContext
= nsnull
;
1888 if (mParentWidget
) {
1889 mParentWidget
->GetBounds(tbounds
);
1891 // No good default size; just size to 0 by 0 for lack of anything better.
1892 tbounds
= nsRect(0, 0, 0, 0);
1895 rv
= MakeWindow(nsSize(mPresContext
->DevPixelsToAppUnits(tbounds
.width
),
1896 mPresContext
->DevPixelsToAppUnits(tbounds
.height
)));
1900 if (mPresContext
&& base_win
) {
1901 nsCOMPtr
<nsILinkHandler
> linkHandler(do_GetInterface(base_win
));
1904 mPresContext
->SetLinkHandler(linkHandler
);
1907 mPresContext
->SetContainer(base_win
);
1913 rv
= InitPresentationStuff(mDocument
->MayStartLayout(),
1914 mDocument
->MayStartLayout());
1917 // If we get here the document load has already started and the
1918 // window is shown because some JS on the page caused it to be
1921 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
); // bug 378682
1922 mPresShell
->UnsuppressPainting();
1929 DocumentViewerImpl::Hide(void)
1931 NS_PRECONDITION(mWindow
, "null window");
1933 mWindow
->Show(PR_FALSE
);
1939 NS_ASSERTION(mPresContext
, "Can't have a presshell and no prescontext!");
1941 // Avoid leaking the old viewer.
1942 if (mPreviousViewer
) {
1943 mPreviousViewer
->Destroy();
1944 mPreviousViewer
= nsnull
;
1948 // This window is sticky, that means that it might be shown again
1949 // and we don't want the presshell n' all that to be thrown away
1950 // just because the window is hidden.
1955 // Break circular reference (or something)
1956 mPresShell
->EndObservingDocument();
1957 nsCOMPtr
<nsISelection
> selection
;
1959 GetDocumentSelection(getter_AddRefs(selection
));
1961 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
1963 if (selPrivate
&& mSelectionListener
) {
1964 selPrivate
->RemoveSelectionListener(mSelectionListener
);
1967 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
1969 nsCOMPtr
<nsILayoutHistoryState
> layoutState
;
1970 mPresShell
->CaptureHistoryState(getter_AddRefs(layoutState
), PR_TRUE
);
1973 mPresShell
->Destroy();
1975 mPresContext
->SetContainer(nsnull
);
1976 mPresContext
->SetLinkHandler(nsnull
);
1978 mPresShell
= nsnull
;
1979 mPresContext
= nsnull
;
1980 mViewManager
= nsnull
;
1982 mDeviceContext
= nsnull
;
1983 mParentWidget
= nsnull
;
1985 nsCOMPtr
<nsIBaseWindow
> base_win(do_QueryReferent(mContainer
));
1988 base_win
->SetParentWidget(nsnull
);
1994 DocumentViewerImpl::SetEnableRendering(PRBool aOn
)
1996 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1997 mEnableRendering
= aOn
;
2000 mViewManager
->EnableRefresh(NS_VMREFRESH_IMMEDIATE
);
2002 mViewManager
->GetRootView(view
); // views are not refCounted
2004 mViewManager
->UpdateView(view
, NS_VMREFRESH_IMMEDIATE
);
2008 mViewManager
->DisableRefresh();
2015 DocumentViewerImpl::GetSticky(PRBool
*aSticky
)
2017 *aSticky
= mIsSticky
;
2023 DocumentViewerImpl::SetSticky(PRBool aSticky
)
2025 mIsSticky
= aSticky
;
2031 DocumentViewerImpl::GetEnableRendering(PRBool
* aResult
)
2033 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
2034 NS_PRECONDITION(nsnull
!= aResult
, "null OUT ptr");
2036 *aResult
= mEnableRendering
;
2042 DocumentViewerImpl::RequestWindowClose(PRBool
* aCanClose
)
2045 if (mPrintIsPending
|| (mPrintEngine
&& mPrintEngine
->GetIsPrinting())) {
2046 *aCanClose
= PR_FALSE
;
2047 mDeferredWindowClose
= PR_TRUE
;
2050 *aCanClose
= PR_TRUE
;
2056 AppendAgentSheet(nsIStyleSheet
*aSheet
, void *aData
)
2058 nsStyleSet
*styleSet
= static_cast<nsStyleSet
*>(aData
);
2059 styleSet
->AppendStyleSheet(nsStyleSet::eAgentSheet
, aSheet
);
2064 PrependUserSheet(nsIStyleSheet
*aSheet
, void *aData
)
2066 nsStyleSet
*styleSet
= static_cast<nsStyleSet
*>(aData
);
2067 styleSet
->PrependStyleSheet(nsStyleSet::eUserSheet
, aSheet
);
2072 DocumentViewerImpl::CreateStyleSet(nsIDocument
* aDocument
,
2073 nsStyleSet
** aStyleSet
)
2075 // Make sure this does the same thing as PresShell::AddSheet wrt ordering.
2077 // this should eventually get expanded to allow for creating
2078 // different sets for different media
2079 nsStyleSet
*styleSet
= new nsStyleSet();
2081 return NS_ERROR_OUT_OF_MEMORY
;
2084 styleSet
->BeginUpdate();
2086 // The document will fill in the document sheets when we create the presshell
2088 // Handle the user sheets.
2090 nsCOMPtr
<nsISupports
> debugDocContainer
= aDocument
->GetContainer();
2091 nsCOMPtr
<nsIDocShellTreeItem
> debugDocShell(do_QueryReferent(mContainer
));
2092 NS_ASSERTION(SameCOMIdentity(debugDocContainer
, debugDocShell
),
2093 "Unexpected containers");
2095 nsICSSStyleSheet
* sheet
= nsnull
;
2096 if (nsContentUtils::IsInChromeDocshell(aDocument
)) {
2097 sheet
= nsLayoutStylesheetCache::UserChromeSheet();
2100 sheet
= nsLayoutStylesheetCache::UserContentSheet();
2104 styleSet
->AppendStyleSheet(nsStyleSet::eUserSheet
, sheet
);
2106 // Append chrome sheets (scrollbars + forms).
2107 PRBool shouldOverride
= PR_FALSE
;
2108 // We don't want a docshell here for external resource docs, so just
2109 // look at mContainer.
2110 nsCOMPtr
<nsIDocShell
> ds(do_QueryReferent(mContainer
));
2111 nsCOMPtr
<nsIDOMEventTarget
> chromeHandler
;
2112 nsCOMPtr
<nsIURI
> uri
;
2113 nsCOMPtr
<nsICSSStyleSheet
> csssheet
;
2116 ds
->GetChromeEventHandler(getter_AddRefs(chromeHandler
));
2118 if (chromeHandler
) {
2119 nsCOMPtr
<nsIDOMElement
> elt(do_QueryInterface(chromeHandler
));
2120 nsCOMPtr
<nsIContent
> content(do_QueryInterface(elt
));
2121 if (elt
&& content
) {
2122 nsCOMPtr
<nsIURI
> baseURI
= content
->GetBaseURI();
2124 nsAutoString sheets
;
2125 elt
->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets
);
2126 if (!sheets
.IsEmpty() && baseURI
) {
2127 nsCOMPtr
<nsICSSLoader
> cssLoader
;
2128 NS_NewCSSLoader(getter_AddRefs(cssLoader
));
2130 char *str
= ToNewCString(sheets
);
2133 while ( (token
= nsCRT::strtok(newStr
, ", ", &newStr
)) ) {
2134 NS_NewURI(getter_AddRefs(uri
), nsDependentCString(token
), nsnull
,
2138 cssLoader
->LoadSheetSync(uri
, getter_AddRefs(csssheet
));
2139 if (!sheet
) continue;
2141 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, csssheet
);
2142 shouldOverride
= PR_TRUE
;
2144 nsMemory::Free(str
);
2149 if (!shouldOverride
) {
2150 sheet
= nsLayoutStylesheetCache::ScrollbarsSheet();
2152 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, sheet
);
2156 sheet
= nsLayoutStylesheetCache::FormsSheet();
2158 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, sheet
);
2161 // Make sure to clone the quirk sheet so that it can be usefully
2162 // enabled/disabled as needed.
2163 nsCOMPtr
<nsICSSStyleSheet
> quirkClone
;
2164 if (!nsLayoutStylesheetCache::UASheet() ||
2165 !nsLayoutStylesheetCache::QuirkSheet() ||
2166 NS_FAILED(nsLayoutStylesheetCache::QuirkSheet()->
2167 Clone(nsnull
, nsnull
, nsnull
, nsnull
,
2168 getter_AddRefs(quirkClone
))) ||
2171 return NS_ERROR_OUT_OF_MEMORY
;
2173 // quirk.css needs to come after the regular UA sheet (or more precisely,
2174 // after the html.css and so forth that the UA sheet imports).
2175 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, quirkClone
);
2176 styleSet
->SetQuirkStyleSheet(quirkClone
);
2177 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
,
2178 nsLayoutStylesheetCache::UASheet());
2180 nsCOMPtr
<nsIStyleSheetService
> dummy
=
2181 do_GetService(NS_STYLESHEETSERVICE_CONTRACTID
);
2183 nsStyleSheetService
*sheetService
= nsStyleSheetService::gInstance
;
2185 sheetService
->AgentStyleSheets()->EnumerateForwards(AppendAgentSheet
,
2187 sheetService
->UserStyleSheets()->EnumerateBackwards(PrependUserSheet
,
2191 // Caller will handle calling EndUpdate, per contract.
2192 *aStyleSet
= styleSet
;
2197 DocumentViewerImpl::ClearHistoryEntry()
2203 //-------------------------------------------------------
2206 DocumentViewerImpl::MakeWindow(const nsSize
& aSize
)
2210 mViewManager
= do_CreateInstance(kViewManagerCID
, &rv
);
2214 nsIDeviceContext
*dx
= mPresContext
->DeviceContext();
2216 rv
= mViewManager
->Init(dx
);
2220 // Create a child window of the parent that is our "root view/window"
2221 // if aParentWidget has a view, we'll hook our view manager up to its view tree
2222 nsIView
* containerView
=
2223 mParentWidget
? nsIView::GetViewFor(mParentWidget
) : nsnull
;
2225 if (containerView
) {
2226 // see if the containerView has already been hooked into a foreign view manager hierarchy
2227 // if it has, then we have to hook into the hierarchy too otherwise bad things will happen.
2228 nsIViewManager
* containerVM
= containerView
->GetViewManager();
2229 nsIView
* pView
= containerView
;
2231 pView
= pView
->GetParent();
2232 } while (pView
&& pView
->GetViewManager() == containerVM
);
2235 // OK, so the container is not already hooked up into a foreign view manager hierarchy.
2236 // That means we can choose not to hook ourselves up.
2238 // If the parent container is a chrome shell and we are a content shell
2239 // then we won't hook into its view
2240 // tree. This will improve performance a little bit (especially given scrolling/painting perf bugs)
2241 // but is really just for peace of mind. This check can be removed if we want to support fancy
2242 // chrome effects like transparent controls floating over content, transparent Web browsers, and
2243 // things like that, and the perf bugs are fixed.
2244 nsCOMPtr
<nsIDocShellTreeItem
> container(do_QueryReferent(mContainer
));
2245 nsCOMPtr
<nsIDocShellTreeItem
> sameTypeParent
;
2247 container
->GetSameTypeParent(getter_AddRefs(sameTypeParent
));
2249 if (!sameTypeParent
) {
2250 containerView
= nsnull
;
2255 // The root view is always at 0,0.
2256 nsRect
tbounds(nsPoint(0, 0), aSize
);
2258 nsIView
* view
= mViewManager
->CreateView(tbounds
, containerView
);
2260 return NS_ERROR_OUT_OF_MEMORY
;
2262 // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
2263 // otherwise the view will find its own parent widget and "do the right thing" to
2264 // establish a parent/child widget relationship
2265 nsWidgetInitData initData
;
2266 nsWidgetInitData
* initDataPtr
;
2267 if (!mParentWidget
) {
2268 initDataPtr
= &initData
;
2269 initData
.mWindowType
= eWindowType_invisible
;
2271 initData
.mContentType
=
2272 nsContentUtils::IsInChromeDocshell(mDocument
) ?
2273 eContentTypeUI
: eContentTypeContent
;
2275 initDataPtr
= nsnull
;
2277 rv
= view
->CreateWidget(kWidgetCID
, initDataPtr
,
2278 (containerView
!= nsnull
|| !mParentWidget
) ?
2279 nsnull
: mParentWidget
->GetNativeData(NS_NATIVE_WIDGET
),
2284 // Setup hierarchical relationship in view manager
2285 mViewManager
->SetRootView(view
);
2287 mWindow
= view
->GetWidget();
2289 // This SetFocus is necessary so the Arrow Key and Page Key events
2290 // go to the scrolled view as soon as the Window is created instead of going to
2291 // the browser window (this enables keyboard scrolling of the document)
2292 // mWindow->SetFocus();
2298 DocumentViewerImpl::CreateDeviceContext(nsIWidget
* aWidget
)
2300 NS_PRECONDITION(!mPresShell
&& !mPresContext
&& !mWindow
,
2301 "This will screw up our existing presentation");
2302 NS_PRECONDITION(mDocument
, "Gotta have a document here");
2304 nsIDocument
* doc
= mDocument
->GetDisplayDocument();
2306 NS_ASSERTION(!aWidget
, "Shouldn't have a widget here");
2308 // We want to use our display document's device context if possible
2309 nsIPresShell
* shell
= doc
->GetPrimaryShell();
2311 nsPresContext
* ctx
= shell
->GetPresContext();
2313 mDeviceContext
= ctx
->DeviceContext();
2319 // Create a device context even if we already have one, since our widget
2320 // might have changed.
2321 mDeviceContext
= do_CreateInstance(kDeviceContextCID
);
2322 NS_ENSURE_TRUE(mDeviceContext
, NS_ERROR_FAILURE
);
2323 mDeviceContext
->Init(aWidget
?
2324 aWidget
->GetNativeData(NS_NATIVE_WIDGET
) : nsnull
);
2328 // Return the selection for the document. Note that text fields have their
2329 // own selection, which cannot be accessed with this method. Use
2330 // mPresShell->GetSelectionForCopy() instead.
2331 nsresult
DocumentViewerImpl::GetDocumentSelection(nsISelection
**aSelection
)
2333 NS_ENSURE_ARG_POINTER(aSelection
);
2335 return NS_ERROR_NOT_INITIALIZED
;
2338 nsCOMPtr
<nsISelectionController
> selcon
;
2339 selcon
= do_QueryInterface(mPresShell
);
2341 return selcon
->GetSelection(nsISelectionController::SELECTION_NORMAL
,
2343 return NS_ERROR_FAILURE
;
2346 /* ========================================================================================
2347 * nsIContentViewerEdit
2348 * ======================================================================================== */
2350 NS_IMETHODIMP
DocumentViewerImpl::Search()
2352 // Nothing to do here.
2356 NS_IMETHODIMP
DocumentViewerImpl::GetSearchable(PRBool
*aSearchable
)
2358 // Nothing to do here.
2359 *aSearchable
= PR_FALSE
;
2363 NS_IMETHODIMP
DocumentViewerImpl::ClearSelection()
2366 nsCOMPtr
<nsISelection
> selection
;
2368 // use mPresShell->GetSelectionForCopy() ?
2369 rv
= GetDocumentSelection(getter_AddRefs(selection
));
2370 if (NS_FAILED(rv
)) return rv
;
2372 return selection
->CollapseToStart();
2375 NS_IMETHODIMP
DocumentViewerImpl::SelectAll()
2377 // XXX this is a temporary implementation copied from nsWebShell
2378 // for now. I think nsDocument and friends should have some helper
2379 // functions to make this easier.
2380 nsCOMPtr
<nsISelection
> selection
;
2383 // use mPresShell->GetSelectionForCopy() ?
2384 rv
= GetDocumentSelection(getter_AddRefs(selection
));
2385 if (NS_FAILED(rv
)) return rv
;
2387 nsCOMPtr
<nsIDOMHTMLDocument
> htmldoc
= do_QueryInterface(mDocument
);
2388 nsCOMPtr
<nsIDOMNode
> bodyNode
;
2392 nsCOMPtr
<nsIDOMHTMLElement
>bodyElement
;
2393 rv
= htmldoc
->GetBody(getter_AddRefs(bodyElement
));
2394 if (NS_FAILED(rv
) || !bodyElement
) return rv
;
2396 bodyNode
= do_QueryInterface(bodyElement
);
2400 bodyNode
= do_QueryInterface(mDocument
->GetRootContent());
2402 if (!bodyNode
) return NS_ERROR_FAILURE
;
2404 rv
= selection
->RemoveAllRanges();
2405 if (NS_FAILED(rv
)) return rv
;
2407 rv
= selection
->SelectAllChildren(bodyNode
);
2411 NS_IMETHODIMP
DocumentViewerImpl::CopySelection()
2413 PRBool preventDefault
;
2414 nsresult rv
= FireClipboardEvent(NS_COPY
, &preventDefault
);
2415 if (NS_FAILED(rv
) || preventDefault
)
2418 return mPresShell
->DoCopy();
2421 NS_IMETHODIMP
DocumentViewerImpl::CopyLinkLocation()
2423 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2424 nsCOMPtr
<nsIDOMNode
> node
;
2425 GetPopupLinkNode(getter_AddRefs(node
));
2426 // make noise if we're not in a link
2427 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
2429 nsAutoString locationText
;
2430 nsresult rv
= mPresShell
->GetLinkLocation(node
, locationText
);
2431 NS_ENSURE_SUCCESS(rv
, rv
);
2433 nsCOMPtr
<nsIClipboardHelper
> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv
));
2434 NS_ENSURE_SUCCESS(rv
, rv
);
2436 // copy the href onto the clipboard
2437 return clipboard
->CopyString(locationText
);
2440 NS_IMETHODIMP
DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags
)
2442 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2443 nsCOMPtr
<nsIImageLoadingContent
> node
;
2444 GetPopupImageNode(getter_AddRefs(node
));
2445 // make noise if we're not in an image
2446 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
2448 return nsCopySupport::ImageCopy(node
, aCopyFlags
);
2451 nsresult
DocumentViewerImpl::GetClipboardEventTarget(nsIDOMNode
** aEventTarget
)
2453 NS_ENSURE_ARG_POINTER(aEventTarget
);
2454 *aEventTarget
= nsnull
;
2457 return NS_ERROR_NOT_INITIALIZED
;
2459 nsCOMPtr
<nsISelection
> sel
;
2460 nsresult rv
= mPresShell
->GetSelectionForCopy(getter_AddRefs(sel
));
2464 return NS_ERROR_FAILURE
;
2466 return nsCopySupport::GetClipboardEventTarget(sel
, aEventTarget
);
2469 nsresult
DocumentViewerImpl::FireClipboardEvent(PRUint32 msg
,
2470 PRBool
* aPreventDefault
)
2472 *aPreventDefault
= PR_FALSE
;
2474 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_NOT_INITIALIZED
);
2475 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2477 // It seems to be unsafe to fire an event handler during reflow (bug 393696)
2478 PRBool isReflowing
= PR_TRUE
;
2479 nsresult rv
= mPresShell
->IsReflowLocked(&isReflowing
);
2480 if (NS_FAILED(rv
) || isReflowing
)
2483 nsCOMPtr
<nsIDOMNode
> eventTarget
;
2484 rv
= GetClipboardEventTarget(getter_AddRefs(eventTarget
));
2486 // On failure to get event target, just forget about it and don't fire.
2489 nsEventStatus status
= nsEventStatus_eIgnore
;
2490 nsEvent
evt(PR_TRUE
, msg
);
2491 nsEventDispatcher::Dispatch(eventTarget
, mPresContext
, &evt
, nsnull
,
2493 // if event handler return'd false (PreventDefault)
2494 if (status
== nsEventStatus_eConsumeNoDefault
)
2495 *aPreventDefault
= PR_TRUE
;
2497 // Ensure that the calling function can use mPresShell -- if the event
2498 // handler closed this window, mPresShell will be gone.
2499 NS_ENSURE_STATE(mPresShell
);
2504 NS_IMETHODIMP
DocumentViewerImpl::GetCopyable(PRBool
*aCopyable
)
2506 NS_ENSURE_ARG_POINTER(aCopyable
);
2507 *aCopyable
= PR_FALSE
;
2509 NS_ENSURE_STATE(mPresShell
);
2510 nsCOMPtr
<nsISelection
> selection
;
2511 nsresult rv
= mPresShell
->GetSelectionForCopy(getter_AddRefs(selection
));
2516 selection
->GetIsCollapsed(&isCollapsed
);
2518 *aCopyable
= !isCollapsed
;
2522 NS_IMETHODIMP
DocumentViewerImpl::CutSelection()
2524 // preventDefault's value is ignored because cut from the document has no
2525 // default behaviour.
2526 PRBool preventDefault
;
2527 return FireClipboardEvent(NS_CUT
, &preventDefault
);
2530 NS_IMETHODIMP
DocumentViewerImpl::GetCutable(PRBool
*aCutable
)
2532 NS_ENSURE_ARG_POINTER(aCutable
);
2533 *aCutable
= PR_FALSE
;
2537 NS_IMETHODIMP
DocumentViewerImpl::Paste()
2539 // preventDefault's value is ignored because paste into the document has no
2540 // default behaviour.
2541 PRBool preventDefault
;
2542 return FireClipboardEvent(NS_PASTE
, &preventDefault
);
2545 NS_IMETHODIMP
DocumentViewerImpl::GetPasteable(PRBool
*aPasteable
)
2547 NS_ENSURE_ARG_POINTER(aPasteable
);
2548 *aPasteable
= PR_FALSE
;
2552 /* AString getContents (in string mimeType, in boolean selectionOnly); */
2553 NS_IMETHODIMP
DocumentViewerImpl::GetContents(const char *mimeType
, PRBool selectionOnly
, nsAString
& aOutValue
)
2555 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2556 return mPresShell
->DoGetContents(nsDependentCString(mimeType
), 0, selectionOnly
, aOutValue
);
2559 /* readonly attribute boolean canGetContents; */
2560 NS_IMETHODIMP
DocumentViewerImpl::GetCanGetContents(PRBool
*aCanGetContents
)
2562 return GetCopyable(aCanGetContents
);
2569 /* ========================================================================================
2570 * nsIContentViewerFile
2571 * ======================================================================================== */
2572 /** ---------------------------------------------------
2573 * See documentation above in the nsIContentViewerfile class definition
2574 * @update 01/24/00 dwc
2577 DocumentViewerImpl::Print(PRBool aSilent
,
2579 nsIPrintSettings
* aPrintSettings
)
2582 nsCOMPtr
<nsIPrintSettings
> printSettings
;
2585 nsresult rv
= NS_ERROR_FAILURE
;
2587 mDebugFile
= aDebugFile
;
2588 // if they don't pass in a PrintSettings, then make one
2589 // it will have all the default values
2590 printSettings
= aPrintSettings
;
2591 nsCOMPtr
<nsIPrintOptions
> printOptions
= do_GetService(sPrintOptionsContractID
, &rv
);
2592 if (NS_SUCCEEDED(rv
)) {
2593 // if they don't pass in a PrintSettings, then make one
2594 if (printSettings
== nsnull
) {
2595 printOptions
->CreatePrintSettings(getter_AddRefs(printSettings
));
2597 NS_ASSERTION(printSettings
, "You can't PrintPreview without a PrintSettings!");
2599 if (printSettings
) printSettings
->SetPrintSilent(aSilent
);
2600 if (printSettings
) printSettings
->SetShowPrintProgress(PR_FALSE
);
2604 return Print(printSettings
, nsnull
);
2606 return NS_ERROR_FAILURE
;
2610 /* [noscript] void printWithParent (in nsIDOMWindowInternal aParentWin, in nsIPrintSettings aThePrintSettings, in nsIWebProgressListener aWPListener); */
2612 DocumentViewerImpl::PrintWithParent(nsIDOMWindowInternal
*aParentWin
, nsIPrintSettings
*aThePrintSettings
, nsIWebProgressListener
*aWPListener
)
2615 return Print(aThePrintSettings
, aWPListener
);
2617 return NS_ERROR_FAILURE
;
2621 // nsIContentViewerFile interface
2623 DocumentViewerImpl::GetPrintable(PRBool
*aPrintable
)
2625 NS_ENSURE_ARG_POINTER(aPrintable
);
2627 *aPrintable
= !GetIsPrinting();
2632 //*****************************************************************************
2633 // nsIMarkupDocumentViewer
2634 //*****************************************************************************
2636 NS_IMETHODIMP
DocumentViewerImpl::ScrollToNode(nsIDOMNode
* aNode
)
2638 NS_ENSURE_ARG(aNode
);
2639 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
2640 nsCOMPtr
<nsIPresShell
> presShell
;
2641 NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell
)), NS_ERROR_FAILURE
);
2643 // Get the nsIContent interface, because that's what we need to
2644 // get the primary frame
2646 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aNode
));
2647 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
2649 // Tell the PresShell to scroll to the primary frame of the content.
2650 NS_ENSURE_SUCCESS(presShell
->ScrollContentIntoView(content
,
2651 NS_PRESSHELL_SCROLL_TOP
,
2652 NS_PRESSHELL_SCROLL_ANYWHERE
),
2658 DocumentViewerImpl::CallChildren(CallChildFunc aFunc
, void* aClosure
)
2660 nsCOMPtr
<nsIDocShellTreeNode
> docShellNode(do_QueryReferent(mContainer
));
2665 docShellNode
->GetChildCount(&n
);
2666 for (i
=0; i
< n
; i
++)
2668 nsCOMPtr
<nsIDocShellTreeItem
> child
;
2669 docShellNode
->GetChildAt(i
, getter_AddRefs(child
));
2670 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
2671 NS_ASSERTION(childAsShell
, "null child in docshell");
2674 nsCOMPtr
<nsIContentViewer
> childCV
;
2675 childAsShell
->GetContentViewer(getter_AddRefs(childCV
));
2678 nsCOMPtr
<nsIMarkupDocumentViewer
> markupCV
= do_QueryInterface(childCV
);
2680 (*aFunc
)(markupCV
, aClosure
);
2694 SetChildTextZoom(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2696 struct ZoomInfo
* ZoomInfo
= (struct ZoomInfo
*) aClosure
;
2697 aChild
->SetTextZoom(ZoomInfo
->mZoom
);
2701 SetChildFullZoom(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2703 struct ZoomInfo
* ZoomInfo
= (struct ZoomInfo
*) aClosure
;
2704 aChild
->SetFullZoom(ZoomInfo
->mZoom
);
2708 SetExtResourceTextZoom(nsIDocument
* aDocument
, void* aClosure
)
2710 // Would it be better to enumerate external resource viewers instead?
2711 nsIPresShell
* shell
= aDocument
->GetPrimaryShell();
2713 nsPresContext
* ctxt
= shell
->GetPresContext();
2715 struct ZoomInfo
* ZoomInfo
= static_cast<struct ZoomInfo
*>(aClosure
);
2716 ctxt
->SetTextZoom(ZoomInfo
->mZoom
);
2724 SetExtResourceFullZoom(nsIDocument
* aDocument
, void* aClosure
)
2726 // Would it be better to enumerate external resource viewers instead?
2727 nsIPresShell
* shell
= aDocument
->GetPrimaryShell();
2729 nsPresContext
* ctxt
= shell
->GetPresContext();
2731 struct ZoomInfo
* ZoomInfo
= static_cast<struct ZoomInfo
*>(aClosure
);
2732 ctxt
->SetFullZoom(ZoomInfo
->mZoom
);
2740 DocumentViewerImpl::SetTextZoom(float aTextZoom
)
2742 if (!GetIsPrintPreview()) {
2743 mTextZoom
= aTextZoom
;
2746 nsIViewManager::UpdateViewBatch
batch(GetViewManager());
2748 // Set the text zoom on all children of mContainer (even if our zoom didn't
2749 // change, our children's zoom may be different, though it would be unusual).
2750 // Do this first, in case kids are auto-sizing and post reflow commands on
2751 // our presshell (which should be subsumed into our own style change reflow).
2752 struct ZoomInfo ZoomInfo
= { aTextZoom
};
2753 CallChildren(SetChildTextZoom
, &ZoomInfo
);
2755 // Now change our own zoom
2756 nsPresContext
* pc
= GetPresContext();
2757 if (pc
&& aTextZoom
!= mPresContext
->TextZoom()) {
2758 pc
->SetTextZoom(aTextZoom
);
2761 // And do the external resources
2762 mDocument
->EnumerateExternalResources(SetExtResourceTextZoom
, &ZoomInfo
);
2764 batch
.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC
);
2770 DocumentViewerImpl::GetTextZoom(float* aTextZoom
)
2772 NS_ENSURE_ARG_POINTER(aTextZoom
);
2773 nsPresContext
* pc
= GetPresContext();
2774 *aTextZoom
= pc
? pc
->TextZoom() : 1.0f
;
2779 DocumentViewerImpl::SetFullZoom(float aFullZoom
)
2781 if (!GetIsPrintPreview()) {
2782 mPageZoom
= aFullZoom
;
2785 nsIViewManager::UpdateViewBatch
batch(GetViewManager());
2787 struct ZoomInfo ZoomInfo
= { aFullZoom
};
2788 CallChildren(SetChildFullZoom
, &ZoomInfo
);
2790 nsPresContext
* pc
= GetPresContext();
2792 pc
->SetFullZoom(aFullZoom
);
2795 // And do the external resources
2796 mDocument
->EnumerateExternalResources(SetExtResourceFullZoom
, &ZoomInfo
);
2798 batch
.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC
);
2804 DocumentViewerImpl::GetFullZoom(float* aFullZoom
)
2806 NS_ENSURE_ARG_POINTER(aFullZoom
);
2807 // Check the prescontext first because it might have a temporary
2808 // setting for print-preview
2809 nsPresContext
* pc
= GetPresContext();
2810 *aFullZoom
= pc
? pc
->GetFullZoom() : mPageZoom
;
2815 SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2817 PRBool styleDisabled
= *static_cast<PRBool
*>(aClosure
);
2818 aChild
->SetAuthorStyleDisabled(styleDisabled
);
2823 DocumentViewerImpl::SetAuthorStyleDisabled(PRBool aStyleDisabled
)
2826 mPresShell
->SetAuthorStyleDisabled(aStyleDisabled
);
2828 CallChildren(SetChildAuthorStyleDisabled
, &aStyleDisabled
);
2833 DocumentViewerImpl::GetAuthorStyleDisabled(PRBool
* aStyleDisabled
)
2836 *aStyleDisabled
= mPresShell
->GetAuthorStyleDisabled();
2838 *aStyleDisabled
= PR_FALSE
;
2844 DocumentViewerImpl::GetDefaultCharacterSet(nsACString
& aDefaultCharacterSet
)
2846 if (mDefaultCharacterSet
.IsEmpty())
2848 const nsAdoptingString
& defCharset
=
2849 nsContentUtils::GetLocalizedStringPref("intl.charset.default");
2851 if (!defCharset
.IsEmpty())
2852 LossyCopyUTF16toASCII(defCharset
, mDefaultCharacterSet
);
2854 mDefaultCharacterSet
.AssignLiteral("ISO-8859-1");
2856 aDefaultCharacterSet
= mDefaultCharacterSet
;
2861 SetChildDefaultCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2863 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2864 aChild
->SetDefaultCharacterSet(*charset
);
2868 DocumentViewerImpl::SetDefaultCharacterSet(const nsACString
& aDefaultCharacterSet
)
2870 mDefaultCharacterSet
= aDefaultCharacterSet
; // this does a copy of aDefaultCharacterSet
2871 // now set the default char set on all children of mContainer
2872 CallChildren(SetChildDefaultCharacterSet
, (void*) &aDefaultCharacterSet
);
2876 // XXX: SEMANTIC CHANGE!
2877 // returns a copy of the string. Caller is responsible for freeing result
2878 // using Recycle(aForceCharacterSet)
2879 NS_IMETHODIMP
DocumentViewerImpl::GetForceCharacterSet(nsACString
& aForceCharacterSet
)
2881 aForceCharacterSet
= mForceCharacterSet
;
2886 SetChildForceCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2888 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2889 aChild
->SetForceCharacterSet(*charset
);
2893 DocumentViewerImpl::SetForceCharacterSet(const nsACString
& aForceCharacterSet
)
2895 mForceCharacterSet
= aForceCharacterSet
;
2896 // now set the force char set on all children of mContainer
2897 CallChildren(SetChildForceCharacterSet
, (void*) &aForceCharacterSet
);
2901 // XXX: SEMANTIC CHANGE!
2902 // returns a copy of the string. Caller is responsible for freeing result
2903 // using Recycle(aHintCharacterSet)
2904 NS_IMETHODIMP
DocumentViewerImpl::GetHintCharacterSet(nsACString
& aHintCharacterSet
)
2907 if(kCharsetUninitialized
== mHintCharsetSource
) {
2908 aHintCharacterSet
.Truncate();
2910 aHintCharacterSet
= mHintCharset
;
2911 // this can't possibly be right. we can't set a value just because somebody got a related value!
2912 //mHintCharsetSource = kCharsetUninitialized;
2917 NS_IMETHODIMP
DocumentViewerImpl::GetHintCharacterSetSource(PRInt32
*aHintCharacterSetSource
)
2919 NS_ENSURE_ARG_POINTER(aHintCharacterSetSource
);
2921 *aHintCharacterSetSource
= mHintCharsetSource
;
2926 NS_IMETHODIMP
DocumentViewerImpl::GetPrevDocCharacterSet(nsACString
& aPrevDocCharacterSet
)
2928 aPrevDocCharacterSet
= mPrevDocCharacterSet
;
2934 SetChildPrevDocCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2936 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2937 aChild
->SetPrevDocCharacterSet(*charset
);
2942 DocumentViewerImpl::SetPrevDocCharacterSet(const nsACString
& aPrevDocCharacterSet
)
2944 mPrevDocCharacterSet
= aPrevDocCharacterSet
;
2945 CallChildren(SetChildPrevDocCharacterSet
, (void*) &aPrevDocCharacterSet
);
2951 SetChildHintCharacterSetSource(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2953 aChild
->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure
));
2957 DocumentViewerImpl::SetHintCharacterSetSource(PRInt32 aHintCharacterSetSource
)
2959 mHintCharsetSource
= aHintCharacterSetSource
;
2960 // now set the hint char set source on all children of mContainer
2961 CallChildren(SetChildHintCharacterSetSource
,
2962 (void*) aHintCharacterSetSource
);
2967 SetChildHintCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2969 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2970 aChild
->SetHintCharacterSet(*charset
);
2974 DocumentViewerImpl::SetHintCharacterSet(const nsACString
& aHintCharacterSet
)
2976 mHintCharset
= aHintCharacterSet
;
2977 // now set the hint char set on all children of mContainer
2978 CallChildren(SetChildHintCharacterSet
, (void*) &aHintCharacterSet
);
2983 SetChildBidiOptions(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2985 aChild
->SetBidiOptions(NS_PTR_TO_INT32(aClosure
));
2988 NS_IMETHODIMP
DocumentViewerImpl::SetBidiTextDirection(PRUint8 aTextDirection
)
2990 PRUint32 bidiOptions
;
2992 GetBidiOptions(&bidiOptions
);
2993 SET_BIDI_OPTION_DIRECTION(bidiOptions
, aTextDirection
);
2994 SetBidiOptions(bidiOptions
);
2998 NS_IMETHODIMP
DocumentViewerImpl::GetBidiTextDirection(PRUint8
* aTextDirection
)
3000 PRUint32 bidiOptions
;
3002 if (aTextDirection
) {
3003 GetBidiOptions(&bidiOptions
);
3004 *aTextDirection
= GET_BIDI_OPTION_DIRECTION(bidiOptions
);
3009 NS_IMETHODIMP
DocumentViewerImpl::SetBidiTextType(PRUint8 aTextType
)
3011 PRUint32 bidiOptions
;
3013 GetBidiOptions(&bidiOptions
);
3014 SET_BIDI_OPTION_TEXTTYPE(bidiOptions
, aTextType
);
3015 SetBidiOptions(bidiOptions
);
3019 NS_IMETHODIMP
DocumentViewerImpl::GetBidiTextType(PRUint8
* aTextType
)
3021 PRUint32 bidiOptions
;
3024 GetBidiOptions(&bidiOptions
);
3025 *aTextType
= GET_BIDI_OPTION_TEXTTYPE(bidiOptions
);
3030 NS_IMETHODIMP
DocumentViewerImpl::SetBidiControlsTextMode(PRUint8 aControlsTextMode
)
3032 PRUint32 bidiOptions
;
3034 GetBidiOptions(&bidiOptions
);
3035 SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
, aControlsTextMode
);
3036 SetBidiOptions(bidiOptions
);
3040 NS_IMETHODIMP
DocumentViewerImpl::GetBidiControlsTextMode(PRUint8
* aControlsTextMode
)
3042 PRUint32 bidiOptions
;
3044 if (aControlsTextMode
) {
3045 GetBidiOptions(&bidiOptions
);
3046 *aControlsTextMode
= GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
);
3051 NS_IMETHODIMP
DocumentViewerImpl::SetBidiNumeral(PRUint8 aNumeral
)
3053 PRUint32 bidiOptions
;
3055 GetBidiOptions(&bidiOptions
);
3056 SET_BIDI_OPTION_NUMERAL(bidiOptions
, aNumeral
);
3057 SetBidiOptions(bidiOptions
);
3061 NS_IMETHODIMP
DocumentViewerImpl::GetBidiNumeral(PRUint8
* aNumeral
)
3063 PRUint32 bidiOptions
;
3066 GetBidiOptions(&bidiOptions
);
3067 *aNumeral
= GET_BIDI_OPTION_NUMERAL(bidiOptions
);
3072 NS_IMETHODIMP
DocumentViewerImpl::SetBidiSupport(PRUint8 aSupport
)
3074 PRUint32 bidiOptions
;
3076 GetBidiOptions(&bidiOptions
);
3077 SET_BIDI_OPTION_SUPPORT(bidiOptions
, aSupport
);
3078 SetBidiOptions(bidiOptions
);
3082 NS_IMETHODIMP
DocumentViewerImpl::GetBidiSupport(PRUint8
* aSupport
)
3084 PRUint32 bidiOptions
;
3087 GetBidiOptions(&bidiOptions
);
3088 *aSupport
= GET_BIDI_OPTION_SUPPORT(bidiOptions
);
3093 NS_IMETHODIMP
DocumentViewerImpl::SetBidiCharacterSet(PRUint8 aCharacterSet
)
3095 PRUint32 bidiOptions
;
3097 GetBidiOptions(&bidiOptions
);
3098 SET_BIDI_OPTION_CHARACTERSET(bidiOptions
, aCharacterSet
);
3099 SetBidiOptions(bidiOptions
);
3103 NS_IMETHODIMP
DocumentViewerImpl::GetBidiCharacterSet(PRUint8
* aCharacterSet
)
3105 PRUint32 bidiOptions
;
3107 if (aCharacterSet
) {
3108 GetBidiOptions(&bidiOptions
);
3109 *aCharacterSet
= GET_BIDI_OPTION_CHARACTERSET(bidiOptions
);
3114 NS_IMETHODIMP
DocumentViewerImpl::SetBidiOptions(PRUint32 aBidiOptions
)
3117 mPresContext
->SetBidi(aBidiOptions
, PR_TRUE
); // could cause reflow
3119 // now set bidi on all children of mContainer
3120 CallChildren(SetChildBidiOptions
, (void*) aBidiOptions
);
3124 NS_IMETHODIMP
DocumentViewerImpl::GetBidiOptions(PRUint32
* aBidiOptions
)
3128 *aBidiOptions
= mPresContext
->GetBidi();
3131 *aBidiOptions
= IBMBIDI_DEFAULT_BIDI_OPTIONS
;
3136 NS_IMETHODIMP
DocumentViewerImpl::SizeToContent()
3138 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
3140 // Skip doing this on docshell-less documents for now
3141 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryReferent(mContainer
));
3142 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_NOT_AVAILABLE
);
3144 nsCOMPtr
<nsIDocShellTreeItem
> docShellParent
;
3145 docShellAsItem
->GetSameTypeParent(getter_AddRefs(docShellParent
));
3147 // It's only valid to access this from a top frame. Doesn't work from
3149 NS_ENSURE_TRUE(!docShellParent
, NS_ERROR_FAILURE
);
3151 nsCOMPtr
<nsIPresShell
> presShell
;
3152 GetPresShell(getter_AddRefs(presShell
));
3153 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
3155 // Flush out all content and style updates. We can't use a resize reflow
3156 // because it won't change some sizes that a style change reflow will.
3157 mDocument
->FlushPendingNotifications(Flush_Layout
);
3159 nsIFrame
*root
= presShell
->GetRootFrame();
3160 NS_ENSURE_TRUE(root
, NS_ERROR_FAILURE
);
3164 nsCOMPtr
<nsIRenderingContext
> rcx
;
3165 presShell
->CreateRenderingContext(root
, getter_AddRefs(rcx
));
3166 NS_ENSURE_TRUE(rcx
, NS_ERROR_FAILURE
);
3167 prefWidth
= root
->GetPrefWidth(rcx
);
3170 nsresult rv
= presShell
->ResizeReflow(prefWidth
, NS_UNCONSTRAINEDSIZE
);
3171 NS_ENSURE_SUCCESS(rv
, rv
);
3173 nsCOMPtr
<nsPresContext
> presContext
;
3174 GetPresContext(getter_AddRefs(presContext
));
3175 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
3177 PRInt32 width
, height
;
3179 // so how big is it?
3180 nsRect shellArea
= presContext
->GetVisibleArea();
3181 // Protect against bogus returns here
3182 NS_ENSURE_TRUE(shellArea
.width
!= NS_UNCONSTRAINEDSIZE
&&
3183 shellArea
.height
!= NS_UNCONSTRAINEDSIZE
,
3185 width
= presContext
->AppUnitsToDevPixels(shellArea
.width
);
3186 height
= presContext
->AppUnitsToDevPixels(shellArea
.height
);
3188 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3189 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3190 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3192 /* presContext's size was calculated in app units and has already been
3193 rounded to the equivalent pixels (so the width/height calculation
3194 we just performed was probably exact, though it was based on
3195 values already rounded during ResizeReflow). In a surprising
3196 number of instances, this rounding makes a window which for want
3197 of one extra pixel's width ends up wrapping the longest line of
3198 text during actual window layout. This makes the window too short,
3199 generally clipping the OK/Cancel buttons. Here we add one pixel
3200 to the calculated width, to circumvent this problem. */
3201 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
+1, height
),
3208 NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener
, nsISelectionListener
)
3210 nsresult
nsDocViewerSelectionListener::Init(DocumentViewerImpl
*aDocViewer
)
3212 mDocViewer
= aDocViewer
;
3217 * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
3218 * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
3219 * of commands. The focus controller stores the popup node, these retrieve
3220 * them and munge appropriately. Note that we have to store the popup node
3221 * rather than retrieving it from EventStateManager::GetFocusedContent because
3222 * not all content (images included) can receive focus.
3226 DocumentViewerImpl::GetPopupNode(nsIDOMNode
** aNode
)
3228 NS_ENSURE_ARG_POINTER(aNode
);
3233 nsCOMPtr
<nsIDocument
> document
;
3234 rv
= GetDocument(getter_AddRefs(document
));
3235 NS_ENSURE_SUCCESS(rv
, rv
);
3236 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
3239 // get the private dom window
3240 nsPIDOMWindow
*privateWin
= document
->GetWindow();
3241 NS_ENSURE_TRUE(privateWin
, NS_ERROR_NOT_AVAILABLE
);
3243 // get the focus controller
3244 nsIFocusController
*focusController
= privateWin
->GetRootFocusController();
3245 NS_ENSURE_TRUE(focusController
, NS_ERROR_FAILURE
);
3247 // get the popup node
3248 focusController
->GetPopupNode(aNode
); // addref happens here
3253 // GetPopupLinkNode: return popup link node or fail
3255 DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode
** aNode
)
3257 NS_ENSURE_ARG_POINTER(aNode
);
3259 // you get null unless i say so
3263 nsCOMPtr
<nsIDOMNode
> node
;
3264 nsresult rv
= GetPopupNode(getter_AddRefs(node
));
3265 NS_ENSURE_SUCCESS(rv
, rv
);
3267 // find out if we have a link in our ancestry
3270 // are we an anchor?
3271 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor(do_QueryInterface(node
));
3272 nsCOMPtr
<nsIDOMHTMLAreaElement
> area
;
3273 nsCOMPtr
<nsIDOMHTMLLinkElement
> link
;
3274 nsAutoString xlinkType
;
3277 area
= do_QueryInterface(node
);
3280 link
= do_QueryInterface(node
);
3283 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(node
));
3285 element
->GetAttributeNS(NS_LITERAL_STRING("http://www.w3.org/1999/xlink"),NS_LITERAL_STRING("type"),xlinkType
);
3290 if (anchor
|| area
|| link
|| xlinkType
.EqualsLiteral("simple")) {
3292 NS_IF_ADDREF(*aNode
); // addref
3296 // if not, get our parent and keep trying...
3297 nsCOMPtr
<nsIDOMNode
> parentNode
;
3298 node
->GetParentNode(getter_AddRefs(parentNode
));
3303 // if we have no node, fail
3304 return NS_ERROR_FAILURE
;
3307 // GetPopupLinkNode: return popup image node or fail
3309 DocumentViewerImpl::GetPopupImageNode(nsIImageLoadingContent
** aNode
)
3311 NS_ENSURE_ARG_POINTER(aNode
);
3313 // you get null unless i say so
3317 nsCOMPtr
<nsIDOMNode
> node
;
3318 nsresult rv
= GetPopupNode(getter_AddRefs(node
));
3319 NS_ENSURE_SUCCESS(rv
, rv
);
3322 CallQueryInterface(node
, aNode
);
3330 * These two functions -- GetInLink and GetInImage -- are kind of annoying
3331 * in that they only get called from the controller (in
3332 * nsDOMWindowController::IsCommandEnabled). The actual construction of the
3333 * context menus in communicator (nsContextMenu.js) has its own, redundant
3334 * tests. No big deal, but good to keep in mind if we ever clean context
3338 NS_IMETHODIMP
DocumentViewerImpl::GetInLink(PRBool
* aInLink
)
3341 printf("dr :: DocumentViewerImpl::GetInLink\n");
3344 NS_ENSURE_ARG_POINTER(aInLink
);
3346 // we're not in a link unless i say so
3347 *aInLink
= PR_FALSE
;
3349 // get the popup link
3350 nsCOMPtr
<nsIDOMNode
> node
;
3351 nsresult rv
= GetPopupLinkNode(getter_AddRefs(node
));
3352 if (NS_FAILED(rv
)) return rv
;
3353 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
3355 // if we made it here, we're in a link
3360 NS_IMETHODIMP
DocumentViewerImpl::GetInImage(PRBool
* aInImage
)
3363 printf("dr :: DocumentViewerImpl::GetInImage\n");
3366 NS_ENSURE_ARG_POINTER(aInImage
);
3368 // we're not in an image unless i say so
3369 *aInImage
= PR_FALSE
;
3371 // get the popup image
3372 nsCOMPtr
<nsIImageLoadingContent
> node
;
3373 nsresult rv
= GetPopupImageNode(getter_AddRefs(node
));
3374 if (NS_FAILED(rv
)) return rv
;
3375 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
3377 // if we made it here, we're in an image
3378 *aInImage
= PR_TRUE
;
3382 NS_IMETHODIMP
nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument
*, nsISelection
*, PRInt16
)
3384 NS_ASSERTION(mDocViewer
, "Should have doc viewer!");
3386 // get the selection state
3387 nsCOMPtr
<nsISelection
> selection
;
3388 nsresult rv
= mDocViewer
->GetDocumentSelection(getter_AddRefs(selection
));
3389 if (NS_FAILED(rv
)) return rv
;
3391 PRBool selectionCollapsed
;
3392 selection
->GetIsCollapsed(&selectionCollapsed
);
3393 // we only call UpdateCommands when the selection changes from collapsed
3394 // to non-collapsed or vice versa. We might need another update string
3395 // for simple selection changes, but that would be expenseive.
3396 if (!mGotSelectionState
|| mSelectionWasCollapsed
!= selectionCollapsed
)
3398 nsCOMPtr
<nsIDocument
> theDoc
;
3399 mDocViewer
->GetDocument(getter_AddRefs(theDoc
));
3400 if (!theDoc
) return NS_ERROR_FAILURE
;
3402 nsPIDOMWindow
*domWindow
= theDoc
->GetWindow();
3403 if (!domWindow
) return NS_ERROR_FAILURE
;
3405 domWindow
->UpdateCommands(NS_LITERAL_STRING("select"));
3406 mGotSelectionState
= PR_TRUE
;
3407 mSelectionWasCollapsed
= selectionCollapsed
;
3413 //nsDocViewerFocusListener
3414 NS_IMPL_ISUPPORTS2(nsDocViewerFocusListener
,
3415 nsIDOMFocusListener
,
3416 nsIDOMEventListener
)
3418 nsDocViewerFocusListener::nsDocViewerFocusListener()
3423 nsDocViewerFocusListener::~nsDocViewerFocusListener(){}
3426 nsDocViewerFocusListener::HandleEvent(nsIDOMEvent
* aEvent
)
3432 nsDocViewerFocusListener::Focus(nsIDOMEvent
* aEvent
)
3434 nsCOMPtr
<nsIPresShell
> shell
;
3436 return NS_ERROR_FAILURE
;
3438 nsresult result
= mDocViewer
->GetPresShell(getter_AddRefs(shell
));
3439 if(NS_FAILED(result
) || !shell
)
3440 return result
?result
:NS_ERROR_FAILURE
;
3441 nsCOMPtr
<nsISelectionController
> selCon
;
3442 selCon
= do_QueryInterface(shell
);
3443 PRInt16 selectionStatus
;
3444 selCon
->GetDisplaySelection(&selectionStatus
);
3446 // If selection was disabled, re-enable it.
3447 if(selectionStatus
== nsISelectionController::SELECTION_DISABLED
||
3448 selectionStatus
== nsISelectionController::SELECTION_HIDDEN
)
3450 selCon
->SetDisplaySelection(nsISelectionController::SELECTION_ON
);
3451 selCon
->RepaintSelection(nsISelectionController::SELECTION_NORMAL
);
3457 nsDocViewerFocusListener::Blur(nsIDOMEvent
* aEvent
)
3459 nsCOMPtr
<nsIPresShell
> shell
;
3461 return NS_ERROR_FAILURE
;
3463 nsresult result
= mDocViewer
->GetPresShell(getter_AddRefs(shell
));
3464 if(NS_FAILED(result
) || !shell
)
3465 return result
?result
:NS_ERROR_FAILURE
;
3466 nsCOMPtr
<nsISelectionController
> selCon
;
3467 selCon
= do_QueryInterface(shell
);
3468 PRInt16 selectionStatus
;
3469 selCon
->GetDisplaySelection(&selectionStatus
);
3471 // If selection was on, disable it.
3472 if(selectionStatus
== nsISelectionController::SELECTION_ON
||
3473 selectionStatus
== nsISelectionController::SELECTION_ATTENTION
)
3475 selCon
->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED
);
3476 selCon
->RepaintSelection(nsISelectionController::SELECTION_NORMAL
);
3483 nsDocViewerFocusListener::Init(DocumentViewerImpl
*aDocViewer
)
3485 mDocViewer
= aDocViewer
;
3489 /** ---------------------------------------------------
3490 * From nsIWebBrowserPrint
3496 DocumentViewerImpl::Print(nsIPrintSettings
* aPrintSettings
,
3497 nsIWebProgressListener
* aWebProgressListener
)
3501 // Temporary code for Bug 136185 / Bug 240490
3502 nsCOMPtr
<nsIXULDocument
> xulDoc(do_QueryInterface(mDocument
));
3504 nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL
);
3505 return NS_ERROR_FAILURE
;
3510 PR_PL(("Container was destroyed yet we are still trying to use it!"));
3511 return NS_ERROR_FAILURE
;
3514 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
3515 NS_ASSERTION(docShell
, "This has to be a docshell");
3517 // Check to see if this document is still busy
3518 // If it is busy and we aren't already "queued" up to print then
3519 // Indicate there is a print pending and cache the args for later
3520 PRUint32 busyFlags
= nsIDocShell::BUSY_FLAGS_NONE
;
3521 if ((NS_FAILED(docShell
->GetBusyFlags(&busyFlags
)) ||
3522 (busyFlags
!= nsIDocShell::BUSY_FLAGS_NONE
&& busyFlags
& nsIDocShell::BUSY_FLAGS_PAGE_LOADING
)) &&
3523 !mPrintDocIsFullyLoaded
) {
3524 if (!mPrintIsPending
) {
3525 mCachedPrintSettings
= aPrintSettings
;
3526 mCachedPrintWebProgressListner
= aWebProgressListener
;
3527 mPrintIsPending
= PR_TRUE
;
3529 PR_PL(("Printing Stopped - document is still busy!"));
3530 return NS_ERROR_GFX_PRINTER_DOC_IS_BUSY
;
3533 nsCOMPtr
<nsIPresShell
> presShell
;
3534 docShell
->GetPresShell(getter_AddRefs(presShell
));
3535 if (!presShell
|| !mDocument
|| !mDeviceContext
|| !mParentWidget
) {
3536 PR_PL(("Can't Print without pres shell, document etc"));
3537 return NS_ERROR_FAILURE
;
3542 // if we are printing another URL, then exit
3543 // the reason we check here is because this method can be called while
3544 // another is still in here (the printing dialog is a good example).
3545 // the only time we can print more than one job at a time is the regression tests
3546 if (GetIsPrinting()) {
3547 // Let the user know we are not ready to print.
3548 rv
= NS_ERROR_NOT_AVAILABLE
;
3549 nsPrintEngine::ShowPrintErrorDialog(rv
);
3553 // If we are hosting a full-page plugin, tell it to print
3554 // first. It shows its own native print UI.
3555 nsCOMPtr
<nsIPluginDocument
> pDoc(do_QueryInterface(mDocument
));
3557 return pDoc
->Print();
3559 if (!mPrintEngine
) {
3560 mPrintEngine
= new nsPrintEngine();
3561 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_OUT_OF_MEMORY
);
3563 rv
= mPrintEngine
->Initialize(this, docShell
, mDocument
,
3564 mDeviceContext
, mParentWidget
,
3571 if (NS_FAILED(rv
)) {
3572 mPrintEngine
->Destroy();
3573 mPrintEngine
= nsnull
;
3578 rv
= mPrintEngine
->Print(aPrintSettings
, aWebProgressListener
);
3579 if (NS_FAILED(rv
)) {
3586 DocumentViewerImpl::PrintPreview(nsIPrintSettings
* aPrintSettings
,
3587 nsIDOMWindow
*aChildDOMWin
,
3588 nsIWebProgressListener
* aWebProgressListener
)
3590 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
3591 nsresult rv
= NS_OK
;
3593 if (GetIsPrinting()) {
3594 nsPrintEngine::CloseProgressDialog(aWebProgressListener
);
3595 return NS_ERROR_FAILURE
;
3599 // Temporary code for Bug 136185 / Bug 240490
3600 nsCOMPtr
<nsIXULDocument
> xulDoc(do_QueryInterface(mDocument
));
3602 nsPrintEngine::CloseProgressDialog(aWebProgressListener
);
3603 nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL
, PR_FALSE
);
3604 return NS_ERROR_FAILURE
;
3609 PR_PL(("Container was destroyed yet we are still trying to use it!"));
3610 return NS_ERROR_FAILURE
;
3613 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
3614 NS_ASSERTION(docShell
, "This has to be a docshell");
3615 nsCOMPtr
<nsIPresShell
> presShell
;
3616 docShell
->GetPresShell(getter_AddRefs(presShell
));
3617 if (!presShell
|| !mDocument
|| !mDeviceContext
|| !mParentWidget
) {
3618 PR_PL(("Can't Print Preview without pres shell, document etc"));
3619 return NS_ERROR_FAILURE
;
3622 if (!mPrintEngine
) {
3623 mPrintEngine
= new nsPrintEngine();
3624 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_OUT_OF_MEMORY
);
3626 rv
= mPrintEngine
->Initialize(this, docShell
, mDocument
,
3627 mDeviceContext
, mParentWidget
,
3634 if (NS_FAILED(rv
)) {
3635 mPrintEngine
->Destroy();
3636 mPrintEngine
= nsnull
;
3641 rv
= mPrintEngine
->PrintPreview(aPrintSettings
, aChildDOMWin
, aWebProgressListener
);
3642 if (NS_FAILED(rv
)) {
3647 return NS_ERROR_FAILURE
;
3651 //----------------------------------------------------------------------
3653 DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType
, PRInt32 aPageNum
)
3655 if (!GetIsPrintPreview() ||
3656 mPrintEngine
->GetIsCreatingPrintPreview())
3657 return NS_ERROR_FAILURE
;
3659 nsIScrollableView
* scrollableView
= nsnull
;
3660 mPrintEngine
->GetPrintPreviewViewManager()->GetRootScrollableView(&scrollableView
);
3661 if (scrollableView
== nsnull
)
3664 // Check to see if we can short circut scrolling to the top
3665 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_HOME
||
3666 (aType
== nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM
&& aPageNum
== 1)) {
3667 scrollableView
->ScrollTo(0, 0, 0);
3671 // Finds the SimplePageSequencer frame
3672 // in PP mPrtPreview->mPrintObject->mSeqFrame is null
3673 nsIFrame
* seqFrame
= nsnull
;
3674 PRInt32 pageCount
= 0;
3675 if (NS_FAILED(mPrintEngine
->GetSeqFrameAndCountPages(seqFrame
, pageCount
))) {
3676 return NS_ERROR_FAILURE
;
3679 // Figure where we are currently scrolled to
3682 scrollableView
->GetScrollPosition(x
, y
);
3684 PRInt32 pageNum
= 1;
3685 nsIFrame
* fndPageFrame
= nsnull
;
3686 nsIFrame
* currentPage
= nsnull
;
3688 // If it is "End" then just do a "goto" to the last page
3689 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_END
) {
3690 aType
= nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM
;
3691 aPageNum
= pageCount
;
3694 // Now, locate the current page we are on and
3695 // and the page of the page number
3697 nsIFrame
* pageFrame
= seqFrame
->GetFirstChild(nsnull
);
3698 while (pageFrame
!= nsnull
) {
3699 nsRect pageRect
= pageFrame
->GetRect();
3703 if (pageRect
.Contains(pageRect
.x
, y
)) {
3704 currentPage
= pageFrame
;
3706 if (pageNum
== aPageNum
) {
3707 fndPageFrame
= pageFrame
;
3711 pageFrame
= pageFrame
->GetNextSibling();
3714 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE
) {
3716 fndPageFrame
= currentPage
->GetPrevInFlow();
3717 if (!fndPageFrame
) {
3723 } else if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE
) {
3725 fndPageFrame
= currentPage
->GetNextInFlow();
3726 if (!fndPageFrame
) {
3732 } else { // If we get here we are doing "GoTo"
3733 if (aPageNum
< 0 || aPageNum
> pageCount
) {
3738 if (fndPageFrame
&& scrollableView
) {
3739 nscoord deadSpaceGapTwips
= 0;
3740 nsIPageSequenceFrame
* sqf
;
3741 if (NS_SUCCEEDED(CallQueryInterface(seqFrame
, &sqf
))) {
3742 sqf
->GetDeadSpaceValue(&deadSpaceGapTwips
);
3745 // To compute deadSpaceGap, use the same presContext as was used
3746 // to layout the seqFrame. (That presContext may have different
3747 // TwipsToAppUnits conversion from this->mPresContext)
3748 nscoord deadSpaceGap
=
3749 seqFrame
->PresContext()->TwipsToAppUnits(deadSpaceGapTwips
);
3752 nscoord(mPrintEngine
->GetPrintPreviewScale() *
3753 float(fndPageFrame
->GetPosition().y
- deadSpaceGap
));
3754 scrollableView
->ScrollTo(0, newYPosn
, 0);
3760 /* readonly attribute nsIPrintSettings globalPrintSettings; */
3762 DocumentViewerImpl::GetGlobalPrintSettings(nsIPrintSettings
* *aGlobalPrintSettings
)
3764 return nsPrintEngine::GetGlobalPrintSettings(aGlobalPrintSettings
);
3767 /* readonly attribute boolean doingPrint; */
3768 // XXX This always returns PR_FALSE for subdocuments
3770 DocumentViewerImpl::GetDoingPrint(PRBool
*aDoingPrint
)
3772 NS_ENSURE_ARG_POINTER(aDoingPrint
);
3774 *aDoingPrint
= PR_FALSE
;
3776 // XXX shouldn't this be GetDoingPrint() ?
3777 return mPrintEngine
->GetDoingPrintPreview(aDoingPrint
);
3782 /* readonly attribute boolean doingPrintPreview; */
3783 // XXX This always returns PR_FALSE for subdocuments
3785 DocumentViewerImpl::GetDoingPrintPreview(PRBool
*aDoingPrintPreview
)
3787 NS_ENSURE_ARG_POINTER(aDoingPrintPreview
);
3789 *aDoingPrintPreview
= PR_FALSE
;
3791 return mPrintEngine
->GetDoingPrintPreview(aDoingPrintPreview
);
3796 /* readonly attribute nsIPrintSettings currentPrintSettings; */
3798 DocumentViewerImpl::GetCurrentPrintSettings(nsIPrintSettings
* *aCurrentPrintSettings
)
3800 NS_ENSURE_ARG_POINTER(aCurrentPrintSettings
);
3802 *aCurrentPrintSettings
= nsnull
;
3803 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3805 return mPrintEngine
->GetCurrentPrintSettings(aCurrentPrintSettings
);
3809 /* readonly attribute nsIDOMWindow currentChildDOMWindow; */
3811 DocumentViewerImpl::GetCurrentChildDOMWindow(nsIDOMWindow
* *aCurrentChildDOMWindow
)
3813 NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow
);
3814 *aCurrentChildDOMWindow
= nsnull
;
3815 return NS_ERROR_NOT_IMPLEMENTED
;
3818 /* void cancel (); */
3820 DocumentViewerImpl::Cancel()
3822 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3823 return mPrintEngine
->Cancelled();
3826 /* void exitPrintPreview (); */
3828 DocumentViewerImpl::ExitPrintPreview()
3830 if (GetIsPrinting()) return NS_ERROR_FAILURE
;
3831 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3833 if (GetIsPrintPreview()) {
3834 ReturnToGalleyPresentation();
3839 //----------------------------------------------------------------------------------
3840 // Enumerate all the documents for their titles
3842 DocumentViewerImpl::EnumerateDocumentNames(PRUint32
* aCount
,
3843 PRUnichar
*** aResult
)
3846 NS_ENSURE_ARG(aCount
);
3847 NS_ENSURE_ARG_POINTER(aResult
);
3848 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3850 return mPrintEngine
->EnumerateDocumentNames(aCount
, aResult
);
3852 return NS_ERROR_FAILURE
;
3856 /* readonly attribute boolean isFramesetFrameSelected; */
3858 DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool
*aIsFramesetFrameSelected
)
3861 *aIsFramesetFrameSelected
= PR_FALSE
;
3862 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3864 return mPrintEngine
->GetIsFramesetFrameSelected(aIsFramesetFrameSelected
);
3866 return NS_ERROR_FAILURE
;
3870 /* readonly attribute long printPreviewNumPages; */
3872 DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32
*aPrintPreviewNumPages
)
3875 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages
);
3876 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3878 return mPrintEngine
->GetPrintPreviewNumPages(aPrintPreviewNumPages
);
3880 return NS_ERROR_FAILURE
;
3884 /* readonly attribute boolean isFramesetDocument; */
3886 DocumentViewerImpl::GetIsFramesetDocument(PRBool
*aIsFramesetDocument
)
3889 *aIsFramesetDocument
= PR_FALSE
;
3890 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3892 return mPrintEngine
->GetIsFramesetDocument(aIsFramesetDocument
);
3894 return NS_ERROR_FAILURE
;
3898 /* readonly attribute boolean isIFrameSelected; */
3900 DocumentViewerImpl::GetIsIFrameSelected(PRBool
*aIsIFrameSelected
)
3903 *aIsIFrameSelected
= PR_FALSE
;
3904 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3906 return mPrintEngine
->GetIsIFrameSelected(aIsIFrameSelected
);
3908 return NS_ERROR_FAILURE
;
3912 /* readonly attribute boolean isRangeSelection; */
3914 DocumentViewerImpl::GetIsRangeSelection(PRBool
*aIsRangeSelection
)
3917 *aIsRangeSelection
= PR_FALSE
;
3918 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3920 return mPrintEngine
->GetIsRangeSelection(aIsRangeSelection
);
3922 return NS_ERROR_FAILURE
;
3926 //----------------------------------------------------------------------------------
3927 // Printing/Print Preview Helpers
3928 //----------------------------------------------------------------------------------
3930 //----------------------------------------------------------------------------------
3931 // Walks the document tree and tells each DocShell whether Printing/PP is happening
3933 DocumentViewerImpl::SetIsPrintingInDocShellTree(nsIDocShellTreeNode
* aParentNode
,
3934 PRBool aIsPrintingOrPP
,
3937 NS_ASSERTION(aParentNode
, "Parent can't be NULL!");
3939 nsCOMPtr
<nsIDocShellTreeItem
> parentItem(do_QueryInterface(aParentNode
));
3941 // find top of "same parent" tree
3943 while (parentItem
) {
3944 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
3945 parentItem
->GetSameTypeParent(getter_AddRefs(parent
));
3949 parentItem
= do_QueryInterface(parent
);
3952 NS_ASSERTION(parentItem
, "parentItem can't be null");
3954 // Check to see if the DocShell's ContentViewer is printing/PP
3955 nsCOMPtr
<nsIContentViewerContainer
> viewerContainer(do_QueryInterface(parentItem
));
3956 if (viewerContainer
) {
3957 viewerContainer
->SetIsPrinting(aIsPrintingOrPP
);
3960 // Traverse children to see if any of them are printing.
3962 aParentNode
->GetChildCount(&n
);
3963 for (PRInt32 i
=0; i
< n
; i
++) {
3964 nsCOMPtr
<nsIDocShellTreeItem
> child
;
3965 aParentNode
->GetChildAt(i
, getter_AddRefs(child
));
3966 nsCOMPtr
<nsIDocShellTreeNode
> childAsNode(do_QueryInterface(child
));
3967 NS_ASSERTION(childAsNode
, "child isn't nsIDocShellTreeNode");
3969 SetIsPrintingInDocShellTree(childAsNode
, aIsPrintingOrPP
, PR_FALSE
);
3974 #endif // NS_PRINTING
3976 //------------------------------------------------------------
3977 // XXX this always returns PR_FALSE for subdocuments
3979 DocumentViewerImpl::GetIsPrinting()
3983 return mPrintEngine
->GetIsPrinting();
3989 //------------------------------------------------------------
3990 // Notification from the PrintEngine of the current Printing status
3992 DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting
)
3995 // Set all the docShells in the docshell tree to be printing.
3996 // that way if anyone of them tries to "navigate" it can't
3998 nsCOMPtr
<nsIDocShellTreeNode
> docShellTreeNode(do_QueryReferent(mContainer
));
3999 NS_ASSERTION(docShellTreeNode
, "mContainer has to be a nsIDocShellTreeNode");
4000 SetIsPrintingInDocShellTree(docShellTreeNode
, aIsPrinting
, PR_TRUE
);
4005 //------------------------------------------------------------
4006 // The PrintEngine holds the current value
4007 // this called from inside the DocViewer.
4008 // XXX it always returns PR_FALSE for subdocuments
4010 DocumentViewerImpl::GetIsPrintPreview()
4014 return mPrintEngine
->GetIsPrintPreview();
4020 //------------------------------------------------------------
4021 // Notification from the PrintEngine of the current PP status
4023 DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview
)
4026 // Set all the docShells in the docshell tree to be printing.
4027 // that way if anyone of them tries to "navigate" it can't
4029 nsCOMPtr
<nsIDocShellTreeNode
> docShellTreeNode(do_QueryReferent(mContainer
));
4030 NS_ASSERTION(docShellTreeNode
, "mContainer has to be a nsIDocShellTreeNode");
4031 SetIsPrintingInDocShellTree(docShellTreeNode
, aIsPrintPreview
, PR_TRUE
);
4036 //----------------------------------------------------------------------------------
4037 // nsIDocumentViewerPrint IFace
4038 //----------------------------------------------------------------------------------
4040 //------------------------------------------------------------
4042 DocumentViewerImpl::IncrementDestroyRefCount()
4047 //------------------------------------------------------------
4049 static void ResetFocusState(nsIDocShell
* aDocShell
);
4052 DocumentViewerImpl::ReturnToGalleyPresentation()
4054 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
4055 if (!GetIsPrintPreview()) {
4056 NS_ERROR("Wow, we should never get here!");
4060 SetIsPrintPreview(PR_FALSE
);
4062 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
4063 mPrintEngine
->Destroy();
4064 mPrintEngine
= nsnull
;
4066 mViewManager
->EnableRefresh(NS_VMREFRESH_DEFERRED
);
4068 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
4069 ResetFocusState(docShell
);
4072 mPresContext
->RestoreImageAnimationMode();
4074 SetTextZoom(mTextZoom
);
4075 SetFullZoom(mPageZoom
);
4078 #endif // NS_PRINTING && NS_PRINT_PREVIEW
4081 //------------------------------------------------------------
4082 // Reset ESM focus for all descendent doc shells.
4084 ResetFocusState(nsIDocShell
* aDocShell
)
4086 nsCOMPtr
<nsISimpleEnumerator
> docShellEnumerator
;
4087 aDocShell
->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent
,
4088 nsIDocShell::ENUMERATE_FORWARDS
,
4089 getter_AddRefs(docShellEnumerator
));
4091 nsCOMPtr
<nsIDocShell
> currentDocShell
;
4092 nsCOMPtr
<nsISupports
> currentContainer
;
4093 PRBool hasMoreDocShells
;
4094 while (NS_SUCCEEDED(docShellEnumerator
->HasMoreElements(&hasMoreDocShells
))
4095 && hasMoreDocShells
) {
4096 docShellEnumerator
->GetNext(getter_AddRefs(currentContainer
));
4097 currentDocShell
= do_QueryInterface(currentContainer
);
4098 if (!currentDocShell
) {
4101 nsCOMPtr
<nsPresContext
> presContext
;
4102 currentDocShell
->GetPresContext(getter_AddRefs(presContext
));
4103 nsIEventStateManager
* esm
=
4104 presContext
? presContext
->EventStateManager() : nsnull
;
4106 esm
->SetContentState(nsnull
, NS_EVENT_STATE_FOCUS
);
4107 esm
->SetFocusedContent(nsnull
);
4112 //------------------------------------------------------------
4113 // This called ONLY when printing has completed and the DV
4114 // is being notified that it should get rid of the PrintEngine.
4116 // BUT, if we are in Print Preview then we want to ignore the
4117 // notification (we do not get rid of the PrintEngine)
4119 // One small caveat:
4120 // This IS called from two places in this module for cleaning
4121 // up when an error occurred during the start up printing
4122 // and print preview
4125 DocumentViewerImpl::OnDonePrinting()
4127 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
4129 if (GetIsPrintPreview()) {
4130 mPrintEngine
->DestroyPrintingData();
4132 mPrintEngine
->Destroy();
4133 mPrintEngine
= nsnull
;
4136 // We are done printing, now cleanup
4137 if (mDeferredWindowClose
) {
4138 mDeferredWindowClose
= PR_FALSE
;
4139 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
4140 nsCOMPtr
<nsIDOMWindowInternal
> win
= do_GetInterface(container
);
4143 } else if (mClosingWhilePrinting
) {
4145 mDocument
->SetScriptGlobalObject(nsnull
);
4146 mDocument
->Destroy();
4149 mClosingWhilePrinting
= PR_FALSE
;
4152 mPresContext
->RestoreImageAnimationMode();
4154 #endif // NS_PRINTING && NS_PRINT_PREVIEW
4157 NS_IMETHODIMP
DocumentViewerImpl::SetPageMode(PRBool aPageMode
, nsIPrintSettings
* aPrintSettings
)
4159 // XXX Page mode is only partially working; it's currently used for
4160 // reftests that require a paginated context
4161 mIsPageMode
= aPageMode
;
4162 // Get the current size of what is being viewed
4164 mWindow
->GetBounds(bounds
);
4167 // Break circular reference (or something)
4168 mPresShell
->EndObservingDocument();
4169 nsCOMPtr
<nsISelection
> selection
;
4170 nsresult rv
= GetDocumentSelection(getter_AddRefs(selection
));
4171 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
4172 if (NS_SUCCEEDED(rv
) && selPrivate
&& mSelectionListener
)
4173 selPrivate
->RemoveSelectionListener(mSelectionListener
);
4174 mPresShell
->Destroy();
4178 mPresContext
->SetContainer(nsnull
);
4179 mPresContext
->SetLinkHandler(nsnull
);
4182 mPresShell
= nsnull
;
4183 mPresContext
= nsnull
;
4184 mViewManager
= nsnull
;
4187 NS_ENSURE_STATE(mDocument
);
4191 new nsPresContext(mDocument
, nsPresContext::eContext_PageLayout
);
4192 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
4193 mPresContext
->SetPaginatedScrolling(PR_TRUE
);
4194 mPresContext
->SetPrintSettings(aPrintSettings
);
4195 nsresult rv
= mPresContext
->Init(mDeviceContext
);
4196 NS_ENSURE_SUCCESS(rv
, rv
);
4198 InitInternal(mParentWidget
, nsnull
, bounds
, PR_TRUE
, PR_FALSE
, PR_FALSE
);
4199 mViewManager
->EnableRefresh(NS_VMREFRESH_NO_SYNC
);
4206 DocumentViewerImpl::GetHistoryEntry(nsISHEntry
**aHistoryEntry
)
4208 NS_IF_ADDREF(*aHistoryEntry
= mSHEntry
);