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"
121 #include "nsIMenuParent.h"
123 #include "nsIScrollableView.h"
124 #include "nsIHTMLDocument.h"
125 #include "nsITimelineService.h"
126 #include "nsGfxCIID.h"
127 #include "nsStyleSheetService.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
SetUAStyleSheet(nsIStyleSheet
* aUAStyleSheet
);
325 NS_IMETHOD
GetDocument(nsIDocument
** aResult
);
326 NS_IMETHOD
GetPresShell(nsIPresShell
** aResult
);
327 NS_IMETHOD
GetPresContext(nsPresContext
** aResult
);
329 // nsIContentViewerEdit
330 NS_DECL_NSICONTENTVIEWEREDIT
332 // nsIContentViewerFile
333 NS_DECL_NSICONTENTVIEWERFILE
335 // nsIMarkupDocumentViewer
336 NS_DECL_NSIMARKUPDOCUMENTVIEWER
339 // nsIWebBrowserPrint
340 NS_DECL_NSIWEBBROWSERPRINT
343 typedef void (*CallChildFunc
)(nsIMarkupDocumentViewer
* aViewer
,
345 void CallChildren(CallChildFunc aFunc
, void* aClosure
);
347 // nsIDocumentViewerPrint Printing Methods
348 NS_DECL_NSIDOCUMENTVIEWERPRINT
351 virtual ~DocumentViewerImpl();
355 * Creates a view manager, root view, and widget for the root view, setting
356 * mViewManager and mWindow.
357 * @param aSize the initial size in appunits
359 nsresult
MakeWindow(const nsSize
& aSize
);
362 * Create our device context
364 nsresult
CreateDeviceContext(nsIWidget
* aWidget
);
367 * Make sure to set up mDeviceContext as needed before calling this
369 nsresult
InitInternal(nsIWidget
* aParentWidget
,
371 const nsRect
& aBounds
,
373 PRBool aInPrintPreview
,
374 PRBool aNeedMakeCX
= PR_TRUE
);
376 * @param aDoInitialReflow set to true if you want to kick off the initial
378 * @param aReenableRefresh set to true if you want this to reenable refresh
379 * before returning; otherwise this will return with refresh disabled
380 * in the view manager
382 nsresult
InitPresentationStuff(PRBool aDoInitialReflow
, PRBool aReenableRefresh
);
384 nsresult
GetPopupNode(nsIDOMNode
** aNode
);
385 nsresult
GetPopupLinkNode(nsIDOMNode
** aNode
);
386 nsresult
GetPopupImageNode(nsIImageLoadingContent
** aNode
);
388 void PrepareToStartLoad(void);
390 nsresult
SyncParentSubDocMap();
392 nsresult
GetDocumentSelection(nsISelection
**aSelection
);
394 nsresult
GetClipboardEventTarget(nsIDOMNode
**aEventTarget
);
395 nsresult
FireClipboardEvent(PRUint32 msg
, PRBool
* aPreventDefault
);
398 // Called when the DocViewer is notified that the state
399 // of Printing or PP has changed
400 void SetIsPrintingInDocShellTree(nsIDocShellTreeNode
* aParentNode
,
401 PRBool aIsPrintingOrPP
,
403 #endif // NS_PRINTING
406 // These return the current shell/prescontext etc.
407 nsIPresShell
* GetPresShell();
408 nsPresContext
* GetPresContext();
409 nsIViewManager
* GetViewManager();
411 // IMPORTANT: The ownership implicit in the following member
412 // variables has been explicitly checked and set using nsCOMPtr
413 // for owning pointers and raw COM interface pointers for weak
414 // (ie, non owning) references. If you add any members to this
415 // class, please make the ownership explicit (pinkerton, scc).
417 nsWeakPtr mContainer
; // it owns me!
418 nsCOMPtr
<nsIDeviceContext
> mDeviceContext
; // We create and own this baby
420 // the following six items are explicitly in this order
421 // so they will be destroyed in the reverse order (pinkerton, scc)
422 nsCOMPtr
<nsIDocument
> mDocument
;
423 nsCOMPtr
<nsIWidget
> mWindow
; // ??? should we really own it?
424 nsCOMPtr
<nsIViewManager
> mViewManager
;
425 nsCOMPtr
<nsPresContext
> mPresContext
;
426 nsCOMPtr
<nsIPresShell
> mPresShell
;
428 nsCOMPtr
<nsIStyleSheet
> mUAStyleSheet
;
430 nsCOMPtr
<nsISelectionListener
> mSelectionListener
;
431 nsCOMPtr
<nsIDOMFocusListener
> mFocusListener
;
433 nsCOMPtr
<nsIContentViewer
> mPreviousViewer
;
434 nsCOMPtr
<nsISHEntry
> mSHEntry
;
436 nsIWidget
* mParentWidget
; // purposely won't be ref counted
438 // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
440 float mTextZoom
; // Text zoom, defaults to 1.0
443 PRInt16 mNumURLStarts
;
444 PRInt16 mDestroyRefCount
; // a second "refcount" for the document viewer's "destroy"
446 unsigned mEnableRendering
: 1;
447 unsigned mStopped
: 1;
448 unsigned mLoaded
: 1;
449 unsigned mDeferredWindowClose
: 1;
450 // document management data
451 // these items are specific to markup documents (html and xml)
452 // may consider splitting these out into a subclass
453 unsigned mIsSticky
: 1;
454 unsigned mInPermitUnload
: 1;
457 unsigned mClosingWhilePrinting
: 1;
460 // These data members support delayed printing when the document is loading
461 unsigned mPrintIsPending
: 1;
462 unsigned mPrintDocIsFullyLoaded
: 1;
463 nsCOMPtr
<nsIPrintSettings
> mCachedPrintSettings
;
464 nsCOMPtr
<nsIWebProgressListener
> mCachedPrintWebProgressListner
;
466 nsCOMPtr
<nsPrintEngine
> mPrintEngine
;
467 #endif // NS_PRINT_PREVIEW
472 #endif // NS_PRINTING
474 /* character set member data */
475 PRInt32 mHintCharsetSource
;
476 nsCString mHintCharset
;
477 nsCString mDefaultCharacterSet
;
478 nsCString mForceCharacterSet
;
479 nsCString mPrevDocCharacterSet
;
481 PRPackedBool mIsPageMode
;
485 //------------------------------------------------------------------
486 // DocumentViewerImpl
487 //------------------------------------------------------------------
489 static NS_DEFINE_CID(kViewManagerCID
, NS_VIEW_MANAGER_CID
);
490 static NS_DEFINE_CID(kWidgetCID
, NS_CHILD_CID
);
491 static NS_DEFINE_CID(kDeviceContextCID
, NS_DEVICE_CONTEXT_CID
);
493 //------------------------------------------------------------------
495 NS_NewDocumentViewer(nsIDocumentViewer
** aResult
)
497 *aResult
= new DocumentViewerImpl();
499 return NS_ERROR_OUT_OF_MEMORY
;
507 void DocumentViewerImpl::PrepareToStartLoad()
509 mEnableRendering
= PR_TRUE
;
512 mDeferredWindowClose
= PR_FALSE
;
515 mPrintIsPending
= PR_FALSE
;
516 mPrintDocIsFullyLoaded
= PR_FALSE
;
517 mClosingWhilePrinting
= PR_FALSE
;
519 // Make sure we have destroyed it and cleared the data member
521 mPrintEngine
->Destroy();
522 mPrintEngine
= nsnull
;
525 #ifdef NS_PRINT_PREVIEW
526 SetIsPrintPreview(PR_FALSE
);
533 #endif // NS_PRINTING
536 // Note: operator new zeros our memory, so no need to init things to null.
537 DocumentViewerImpl::DocumentViewerImpl()
538 : mTextZoom(1.0), mPageZoom(1.0),
540 mHintCharsetSource(kCharsetUninitialized
)
542 PrepareToStartLoad();
545 NS_IMPL_ADDREF(DocumentViewerImpl
)
546 NS_IMPL_RELEASE(DocumentViewerImpl
)
548 NS_INTERFACE_MAP_BEGIN(DocumentViewerImpl
)
549 NS_INTERFACE_MAP_ENTRY(nsIContentViewer
)
550 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewer
)
551 NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer
)
552 NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile
)
553 NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit
)
554 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint
)
555 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIContentViewer
)
557 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint
)
561 DocumentViewerImpl::~DocumentViewerImpl()
565 mDocument
->Destroy();
568 NS_ASSERTION(!mPresShell
&& !mPresContext
,
569 "User did not call nsIContentViewer::Destroy");
570 if (mPresShell
|| mPresContext
) {
571 // Make sure we don't hand out a reference to the content viewer to
578 // XXX(?) Revoke pending invalidate events
582 * This method is called by the Document Loader once a document has
583 * been created for a particular data stream... The content viewer
584 * must cache this document for later use when Init(...) is called.
586 * This method is also called when an out of band document.write() happens.
587 * In that case, the document passed in is the same as the previous document.
590 DocumentViewerImpl::LoadStart(nsISupports
*aDoc
)
593 printf("DocumentViewerImpl::LoadStart\n");
598 mDocument
= do_QueryInterface(aDoc
, &rv
);
600 else if (mDocument
== aDoc
) {
601 // Reset the document viewer's state back to what it was
602 // when the document load started.
603 PrepareToStartLoad();
610 DocumentViewerImpl::SyncParentSubDocMap()
612 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryReferent(mContainer
));
613 nsCOMPtr
<nsPIDOMWindow
> pwin(do_GetInterface(item
));
614 nsCOMPtr
<nsIContent
> content
;
616 if (mDocument
&& pwin
) {
617 content
= do_QueryInterface(pwin
->GetFrameElementInternal());
621 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
622 item
->GetParent(getter_AddRefs(parent
));
624 nsCOMPtr
<nsIDOMWindow
> parent_win(do_GetInterface(parent
));
627 nsCOMPtr
<nsIDOMDocument
> dom_doc
;
628 parent_win
->GetDocument(getter_AddRefs(dom_doc
));
630 nsCOMPtr
<nsIDocument
> parent_doc(do_QueryInterface(dom_doc
));
633 return parent_doc
->SetSubDocumentFor(content
, mDocument
);
642 DocumentViewerImpl::SetContainer(nsISupports
* aContainer
)
644 mContainer
= do_GetWeakReference(aContainer
);
646 mPresContext
->SetContainer(aContainer
);
649 // We're loading a new document into the window where this document
650 // viewer lives, sync the parent document's frame element -> sub
653 return SyncParentSubDocMap();
657 DocumentViewerImpl::GetContainer(nsISupports
** aResult
)
659 NS_ENSURE_ARG_POINTER(aResult
);
662 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
663 container
.swap(*aResult
);
668 DocumentViewerImpl::Init(nsIWidget
* aParentWidget
,
669 const nsRect
& aBounds
)
671 nsresult rv
= CreateDeviceContext(aParentWidget
);
672 NS_ENSURE_SUCCESS(rv
, rv
);
674 return InitInternal(aParentWidget
, nsnull
, aBounds
, PR_TRUE
, PR_FALSE
);
678 DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow
, PRBool aReenableRefresh
)
680 // Create the style set...
681 nsStyleSet
*styleSet
;
682 nsresult rv
= CreateStyleSet(mDocument
, &styleSet
);
683 NS_ENSURE_SUCCESS(rv
, rv
);
685 // Now make the shell for the document
686 rv
= mDocument
->CreateShell(mPresContext
, mViewManager
, styleSet
,
687 getter_AddRefs(mPresShell
));
693 // We're done creating the style set
694 styleSet
->EndUpdate();
696 if (aDoInitialReflow
) {
697 // Since InitialReflow() will create frames for *all* items
698 // that are currently in the document tree, we need to flush
699 // any pending notifications to prevent the content sink from
700 // duplicating layout frames for content it has added to the tree
701 // but hasn't notified the document about. (Bug 154018)
703 // Note that we are flushing before we add mPresShell as an observer
704 // to avoid bogus notifications.
706 mDocument
->FlushPendingNotifications(Flush_ContentAndNotify
);
709 mPresShell
->BeginObservingDocument();
711 // Initialize our view manager
713 mWindow
->GetBounds(bounds
);
715 nscoord width
= mPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds
.width
;
716 nscoord height
= mPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds
.height
;
718 mViewManager
->DisableRefresh();
719 mViewManager
->SetWindowDimensions(width
, height
);
720 mPresContext
->SetTextZoom(mTextZoom
);
721 mPresContext
->SetFullZoom(mPageZoom
);
723 // Setup default view manager background color
725 // This may be overridden by the docshell with the background color
726 // for the last document loaded into the docshell
727 mViewManager
->SetDefaultBackgroundColor(mPresContext
->DefaultBackgroundColor());
729 if (aDoInitialReflow
) {
730 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(mDocument
);
732 nsCOMPtr
<nsIDOMHTMLFrameSetElement
> frameset
=
733 do_QueryInterface(mDocument
->GetRootContent());
734 htmlDoc
->SetIsFrameset(frameset
!= nsnull
);
737 nsCOMPtr
<nsIPresShell
> shellGrip
= mPresShell
;
739 mPresShell
->InitialReflow(width
, height
);
741 // Store the visible area so it's available for other callers of
742 // InitialReflow, like nsContentSink::StartLayout.
743 mPresContext
->SetVisibleArea(nsRect(0, 0, width
, height
));
746 // Now trigger a refresh
747 if (aReenableRefresh
&& mEnableRendering
&& mViewManager
) {
748 mViewManager
->EnableRefresh(NS_VMREFRESH_IMMEDIATE
);
751 // now register ourselves as a selection listener, so that we get
752 // called when the selection changes in the window
753 nsDocViewerSelectionListener
*selectionListener
=
754 new nsDocViewerSelectionListener();
755 NS_ENSURE_TRUE(selectionListener
, NS_ERROR_OUT_OF_MEMORY
);
757 selectionListener
->Init(this);
759 // mSelectionListener is a owning reference
760 mSelectionListener
= selectionListener
;
762 nsCOMPtr
<nsISelection
> selection
;
763 rv
= GetDocumentSelection(getter_AddRefs(selection
));
764 NS_ENSURE_SUCCESS(rv
, rv
);
766 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
767 rv
= selPrivate
->AddSelectionListener(mSelectionListener
);
771 // Save old listener so we can unregister it
772 nsCOMPtr
<nsIDOMFocusListener
> oldFocusListener
= mFocusListener
;
776 // now register ourselves as a focus listener, so that we get called
777 // when the focus changes in the window
778 nsDocViewerFocusListener
*focusListener
;
779 NS_NEWXPCOM(focusListener
, nsDocViewerFocusListener
);
780 NS_ENSURE_TRUE(focusListener
, NS_ERROR_OUT_OF_MEMORY
);
782 focusListener
->Init(this);
784 // mFocusListener is a strong reference
785 mFocusListener
= focusListener
;
788 rv
= mDocument
->AddEventListenerByIID(mFocusListener
,
789 NS_GET_IID(nsIDOMFocusListener
));
790 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to register focus listener");
791 if (oldFocusListener
) {
792 rv
= mDocument
->RemoveEventListenerByIID(oldFocusListener
,
793 NS_GET_IID(nsIDOMFocusListener
));
794 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to remove focus listener");
801 //-----------------------------------------------
802 // This method can be used to initial the "presentation"
803 // The aDoCreation indicates whether it should create
804 // all the new objects or just initialize the existing ones
806 DocumentViewerImpl::InitInternal(nsIWidget
* aParentWidget
,
808 const nsRect
& aBounds
,
810 PRBool aInPrintPreview
,
811 PRBool aNeedMakeCX
/*= PR_TRUE*/)
813 mParentWidget
= aParentWidget
; // not ref counted
816 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NULL_POINTER
);
818 PRBool makeCX
= PR_FALSE
;
820 if (aParentWidget
&& !mPresContext
) {
821 // Create presentation context
823 //Presentation context already created in SetPageMode which is calling this method
827 new nsPresContext(mDocument
, nsPresContext::eContext_Galley
);
828 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
830 nsresult rv
= mPresContext
->Init(mDeviceContext
);
832 mPresContext
= nsnull
;
836 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
837 makeCX
= !GetIsPrintPreview() && aNeedMakeCX
; // needs to be true except when we are already in PP or we are enabling/disabling paginated mode.
844 // Create the ViewManager and Root View...
846 // We must do this before we tell the script global object about
847 // this new document since doing that will cause us to re-enter
848 // into nsSubDocumentFrame code through reflows caused by
849 // FlushPendingNotifications() calls down the road...
851 rv
= MakeWindow(nsSize(mPresContext
->DevPixelsToAppUnits(aBounds
.width
),
852 mPresContext
->DevPixelsToAppUnits(aBounds
.height
)));
853 NS_ENSURE_SUCCESS(rv
, rv
);
856 #ifdef NS_PRINT_PREVIEW
858 // I'm leaving this in a broken state for the moment; we should
859 // be measuring/scaling with the print device context, not the
860 // screen device context, but this is good enough to allow
861 // printing reftests to work.
863 nsCOMPtr
<nsIDeviceContextSpec
> devspec
=
864 do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv
);
865 NS_ENSURE_SUCCESS(rv
, rv
);
866 // mWindow has been initialized by preceding call to MakeWindow
867 rv
= devspec
->Init(mWindow
, mPresContext
->GetPrintSettings(), PR_FALSE
);
868 NS_ENSURE_SUCCESS(rv
, rv
);
869 nsCOMPtr
<nsIDeviceContext
> devctx
=
870 do_CreateInstance("@mozilla.org/gfx/devicecontext;1", &rv
);
871 NS_ENSURE_SUCCESS(rv
, rv
);
872 rv
= devctx
->InitForPrinting(devspec
);
873 NS_ENSURE_SUCCESS(rv
, rv
);
874 // XXX I'm breaking this code; I'm not sure I really want to mess with
875 // the document viewer at the moment to get the right device context
876 // (this won't break anyone, since page layout mode was never really
879 double pageWidth
= 0, pageHeight
= 0;
880 mPresContext
->GetPrintSettings()->GetEffectivePageSize(&pageWidth
,
882 mPresContext
->SetPageSize(
883 nsSize(mPresContext
->TwipsToAppUnits(NSToIntFloor(pageWidth
)),
884 mPresContext
->TwipsToAppUnits(NSToIntFloor(pageHeight
))));
885 mPresContext
->SetIsRootPaginatedDocument(PR_TRUE
);
886 mPresContext
->SetPageScale(1.0f
);
892 nsCOMPtr
<nsIInterfaceRequestor
> requestor(do_QueryReferent(mContainer
));
895 nsCOMPtr
<nsILinkHandler
> linkHandler
;
896 requestor
->GetInterface(NS_GET_IID(nsILinkHandler
),
897 getter_AddRefs(linkHandler
));
899 mPresContext
->SetContainer(requestor
);
900 mPresContext
->SetLinkHandler(linkHandler
);
903 if (!aInPrintPreview
) {
904 // Set script-context-owner in the document
906 nsCOMPtr
<nsPIDOMWindow
> window
;
907 requestor
->GetInterface(NS_GET_IID(nsPIDOMWindow
),
908 getter_AddRefs(window
));
911 window
->SetNewDocument(mDocument
, aState
, PR_TRUE
);
913 nsJSContext::LoadStart();
918 if (aDoCreation
&& mPresContext
) {
919 // The ViewManager and Root View was created above (in
922 rv
= InitPresentationStuff(!makeCX
, !makeCX
);
929 // LoadComplete(aStatus)
931 // aStatus - The status returned from loading the document.
933 // This method is called by the container when the document has been
934 // completely loaded.
937 DocumentViewerImpl::LoadComplete(nsresult aStatus
)
939 /* We need to protect ourself against auto-destruction in case the
940 window is closed while processing the OnLoad event. See bug
941 http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
944 nsCOMPtr
<nsIDocumentViewer
> kungFuDeathGrip(this);
946 // Flush out layout so it's up-to-date by the time onload is called.
947 // Note that this could destroy the window, so do this before
948 // checking for our mDocument and its window.
949 if (mPresShell
&& !mStopped
) {
950 // Hold strong ref because this could conceivably run script
951 nsCOMPtr
<nsIPresShell
> shell
= mPresShell
;
952 shell
->FlushPendingNotifications(Flush_Layout
);
956 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
958 // First, get the window from the document...
959 nsPIDOMWindow
*window
= mDocument
->GetWindow();
961 // Fail if no window is available...
962 NS_ENSURE_TRUE(window
, NS_ERROR_NULL_POINTER
);
966 // Now, fire either an OnLoad or OnError event to the document...
967 PRBool restoring
= PR_FALSE
;
968 if(NS_SUCCEEDED(aStatus
)) {
969 nsEventStatus status
= nsEventStatus_eIgnore
;
970 nsEvent
event(PR_TRUE
, NS_LOAD
);
971 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
972 // XXX Dispatching to |window|, but using |document| as the target.
973 event
.target
= mDocument
;
975 // If the document presentation is being restored, we don't want to fire
976 // onload to the document content since that would likely confuse scripts
979 nsIDocShell
*docShell
= window
->GetDocShell();
980 NS_ENSURE_TRUE(docShell
, NS_ERROR_UNEXPECTED
);
982 docShell
->GetRestoringDocument(&restoring
);
984 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
,
987 // if navigator.xul's load is complete, the main nav window is visible
990 //printf("DEBUG: getting uri from document (%p)\n", mDocument.get());
992 nsIURI
*uri
= mDocument
? mDocument
->GetDocumentURI() : nsnull
;
995 //printf("DEBUG: getting spec for uri (%p)\n", uri.get());
998 if (spec
.EqualsLiteral("chrome://navigator/content/navigator.xul") ||
999 spec
.EqualsLiteral("chrome://browser/content/browser.xul")) {
1000 NS_TIMELINE_MARK("Navigator Window visible now");
1003 #endif /* MOZ_TIMELINE */
1006 // XXX: Should fire error event to the document...
1009 // Notify the document that it has been shown (regardless of whether
1010 // it was just loaded). Note: mDocument may be null now if the above
1011 // firing of onload caused the document to unload.
1013 mDocument
->OnPageShow(restoring
);
1015 // Now that the document has loaded, we can tell the presshell
1016 // to unsuppress painting.
1017 if (mPresShell
&& !mStopped
) {
1018 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
);
1019 mPresShell
->UnsuppressPainting();
1020 // mPresShell could have been removed now, see bug 378682/421432
1022 mPresShell
->ScrollToAnchor();
1026 nsJSContext::LoadEnd();
1029 // Check to see if someone tried to print during the load
1030 if (mPrintIsPending
) {
1031 mPrintIsPending
= PR_FALSE
;
1032 mPrintDocIsFullyLoaded
= PR_TRUE
;
1033 Print(mCachedPrintSettings
, mCachedPrintWebProgressListner
);
1034 mCachedPrintSettings
= nsnull
;
1035 mCachedPrintWebProgressListner
= nsnull
;
1043 DocumentViewerImpl::PermitUnload(PRBool
*aPermitUnload
)
1045 *aPermitUnload
= PR_TRUE
;
1047 if (!mDocument
|| mInPermitUnload
) {
1051 // First, get the script global object from the document...
1052 nsPIDOMWindow
*window
= mDocument
->GetWindow();
1055 // This is odd, but not fatal
1056 NS_WARNING("window not set for document!");
1060 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "This is unsafe");
1062 // Now, fire an BeforeUnload event to the document and see if it's ok
1064 nsEventStatus status
= nsEventStatus_eIgnore
;
1065 nsBeforePageUnloadEvent
event(PR_TRUE
, NS_BEFORE_PAGE_UNLOAD
);
1066 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
1067 // XXX Dispatching to |window|, but using |document| as the target.
1068 event
.target
= mDocument
;
1069 nsresult rv
= NS_OK
;
1071 // In evil cases we might be destroyed while handling the
1072 // onbeforeunload event, don't let that happen. (see also bug#331040)
1073 nsRefPtr
<DocumentViewerImpl
> kungFuDeathGrip(this);
1076 // Never permit popups from the beforeunload handler, no matter
1078 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
1080 mInPermitUnload
= PR_TRUE
;
1081 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
, &status
);
1082 mInPermitUnload
= PR_FALSE
;
1085 nsCOMPtr
<nsIDocShellTreeNode
> docShellNode(do_QueryReferent(mContainer
));
1087 if (NS_SUCCEEDED(rv
) && (event
.flags
& NS_EVENT_FLAG_NO_DEFAULT
||
1088 !event
.text
.IsEmpty())) {
1089 // Ask the user if it's ok to unload the current page
1091 nsCOMPtr
<nsIPrompt
> prompt
= do_GetInterface(docShellNode
);
1094 nsXPIDLString preMsg
, postMsg
;
1095 rv
= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES
,
1096 "OnBeforeUnloadPreMessage",
1098 rv
|= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES
,
1099 "OnBeforeUnloadPostMessage",
1102 // GetStringFromName can succeed, yet give NULL strings back.
1103 if (NS_FAILED(rv
) || preMsg
.IsEmpty() || postMsg
.IsEmpty()) {
1104 NS_ERROR("Failed to get strings from dom.properties!");
1108 // Limit the length of the text the page can inject into this
1109 // dialogue to 1024 characters.
1110 PRInt32 len
= PR_MIN(event
.text
.Length(), 1024);
1114 msg
= preMsg
+ NS_LITERAL_STRING("\n\n") + postMsg
;
1116 msg
= preMsg
+ NS_LITERAL_STRING("\n\n") +
1117 StringHead(event
.text
, len
) +
1118 NS_LITERAL_STRING("\n\n") + postMsg
;
1121 // This doesn't pass a title, which makes the title be
1122 // "Confirm", is that ok, or do we want a localizable title for
1124 if (NS_FAILED(prompt
->Confirm(nsnull
, msg
.get(), aPermitUnload
))) {
1125 *aPermitUnload
= PR_TRUE
;
1132 docShellNode
->GetChildCount(&childCount
);
1134 for (PRInt32 i
= 0; i
< childCount
&& *aPermitUnload
; ++i
) {
1135 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1136 docShellNode
->GetChildAt(i
, getter_AddRefs(item
));
1138 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(item
));
1141 nsCOMPtr
<nsIContentViewer
> cv
;
1142 docShell
->GetContentViewer(getter_AddRefs(cv
));
1145 cv
->PermitUnload(aPermitUnload
);
1155 DocumentViewerImpl::PageHide(PRBool aIsUnload
)
1157 mEnableRendering
= PR_FALSE
;
1160 return NS_ERROR_NULL_POINTER
;
1163 mDocument
->OnPageHide(!aIsUnload
);
1165 // if Destroy() was called during OnPageHide(), mDocument is nsnull.
1166 NS_ENSURE_STATE(mDocument
);
1168 // First, get the window from the document...
1169 nsPIDOMWindow
*window
= mDocument
->GetWindow();
1172 // Fail if no window is available...
1173 NS_ERROR("window not set for document!");
1174 return NS_ERROR_NULL_POINTER
;
1177 // Now, fire an Unload event to the document...
1178 nsEventStatus status
= nsEventStatus_eIgnore
;
1179 nsEvent
event(PR_TRUE
, NS_PAGE_UNLOAD
);
1180 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
1181 // XXX Dispatching to |window|, but using |document| as the target.
1182 event
.target
= mDocument
;
1184 // Never permit popups from the unload handler, no matter how we get
1186 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
1188 nsEventDispatcher::Dispatch(window
, mPresContext
, &event
, nsnull
, &status
);
1192 // look for open menupopups and close them after the unload event, in case
1193 // the unload event listeners open any new popups
1195 nsContentUtils::HidePopupsInDocument(mDocument
);
1202 AttachContainerRecurse(nsIDocShell
* aShell
)
1204 nsCOMPtr
<nsIContentViewer
> viewer
;
1205 aShell
->GetContentViewer(getter_AddRefs(viewer
));
1206 nsCOMPtr
<nsIDocumentViewer
> docViewer
= do_QueryInterface(viewer
);
1208 nsCOMPtr
<nsIDocument
> doc
;
1209 docViewer
->GetDocument(getter_AddRefs(doc
));
1211 doc
->SetContainer(aShell
);
1213 nsCOMPtr
<nsPresContext
> pc
;
1214 docViewer
->GetPresContext(getter_AddRefs(pc
));
1216 pc
->SetContainer(aShell
);
1217 pc
->SetLinkHandler(nsCOMPtr
<nsILinkHandler
>(do_QueryInterface(aShell
)));
1219 nsCOMPtr
<nsIPresShell
> presShell
;
1220 docViewer
->GetPresShell(getter_AddRefs(presShell
));
1222 presShell
->SetForwardingContainer(nsnull
);
1226 // Now recurse through the children
1227 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(aShell
);
1228 NS_ASSERTION(node
, "docshells must implement nsIDocShellTreeNode");
1231 node
->GetChildCount(&childCount
);
1232 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
1233 nsCOMPtr
<nsIDocShellTreeItem
> childItem
;
1234 node
->GetChildAt(i
, getter_AddRefs(childItem
));
1235 AttachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(childItem
)));
1240 DocumentViewerImpl::Open(nsISupports
*aState
, nsISHEntry
*aSHEntry
)
1242 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
1244 // Our container might have gone away while we were closed.
1245 // If this is the case, we must fail to open so we don't crash.
1246 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
1248 return NS_ERROR_NOT_AVAILABLE
;
1251 mWindow
->GetBounds(bounds
);
1253 nsresult rv
= InitInternal(mParentWidget
, aState
, bounds
, PR_FALSE
, PR_FALSE
);
1254 NS_ENSURE_SUCCESS(rv
, rv
);
1257 mDocument
->SetContainer(nsCOMPtr
<nsISupports
>(do_QueryReferent(mContainer
)));
1260 mPresShell
->SetForwardingContainer(nsnull
);
1262 // Rehook the child presentations. The child shells are still in
1263 // session history, so get them from there.
1265 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1266 PRInt32 itemIndex
= 0;
1267 while (NS_SUCCEEDED(aSHEntry
->ChildShellAt(itemIndex
++,
1268 getter_AddRefs(item
))) && item
) {
1269 AttachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(item
)));
1272 SyncParentSubDocMap();
1274 if (mFocusListener
&& mDocument
) {
1275 mDocument
->AddEventListenerByIID(mFocusListener
,
1276 NS_GET_IID(nsIDOMFocusListener
));
1279 // XXX re-enable image animations once that works correctly
1281 PrepareToStartLoad();
1286 DocumentViewerImpl::Close(nsISHEntry
*aSHEntry
)
1288 // All callers are supposed to call close to break circular
1289 // references. If we do this stuff in the destructor, the
1290 // destructor might never be called (especially if we're being
1293 mSHEntry
= aSHEntry
;
1295 // Close is also needed to disable scripts during paint suppression,
1296 // since we transfer the existing global object to the new document
1297 // that is loaded. In the future, the global object may become a proxy
1298 // for an object that can be switched in and out so that we don't need
1299 // to disable scripts during paint suppression.
1304 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
1305 // Turn scripting back on
1306 // after PrintPreview had turned it off
1307 if (GetIsPrintPreview() && mPrintEngine
) {
1308 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
1313 // A Close was called while we were printing
1314 // so don't clear the ScriptGlobalObject
1315 // or clear the mDocument below
1316 // Also, do an extra addref to keep the viewer from going away.
1317 if (mPrintEngine
&& !mClosingWhilePrinting
) {
1318 mClosingWhilePrinting
= PR_TRUE
;
1323 // out of band cleanup of webshell
1324 mDocument
->SetScriptGlobalObject(nsnull
);
1327 mDocument
->RemovedFromDocShell();
1330 if (mFocusListener
&& mDocument
) {
1331 mDocument
->RemoveEventListenerByIID(mFocusListener
,
1332 NS_GET_IID(nsIDOMFocusListener
));
1339 DetachContainerRecurse(nsIDocShell
*aShell
)
1341 // Unhook this docshell's presentation
1342 nsCOMPtr
<nsIContentViewer
> viewer
;
1343 aShell
->GetContentViewer(getter_AddRefs(viewer
));
1344 nsCOMPtr
<nsIDocumentViewer
> docViewer
= do_QueryInterface(viewer
);
1346 nsCOMPtr
<nsIDocument
> doc
;
1347 docViewer
->GetDocument(getter_AddRefs(doc
));
1349 doc
->SetContainer(nsnull
);
1351 nsCOMPtr
<nsPresContext
> pc
;
1352 docViewer
->GetPresContext(getter_AddRefs(pc
));
1354 pc
->SetContainer(nsnull
);
1355 pc
->SetLinkHandler(nsnull
);
1357 nsCOMPtr
<nsIPresShell
> presShell
;
1358 docViewer
->GetPresShell(getter_AddRefs(presShell
));
1360 presShell
->SetForwardingContainer(nsWeakPtr(do_GetWeakReference(aShell
)));
1364 // Now recurse through the children
1365 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(aShell
);
1366 NS_ASSERTION(node
, "docshells must implement nsIDocShellTreeNode");
1369 node
->GetChildCount(&childCount
);
1370 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
1371 nsCOMPtr
<nsIDocShellTreeItem
> childItem
;
1372 node
->GetChildAt(i
, getter_AddRefs(childItem
));
1373 DetachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(childItem
)));
1378 DocumentViewerImpl::Destroy()
1380 NS_ASSERTION(mDocument
, "No document in Destroy()!");
1383 // Here is where we check to see if the docment was still being prepared
1384 // for printing when it was asked to be destroy from someone externally
1385 // This usually happens if the document is unloaded while the user is in the Print Dialog
1387 // So we flip the bool to remember that the document is going away
1388 // and we can clean up and abort later after returning from the Print Dialog
1390 if (mPrintEngine
->CheckBeforeDestroy()) {
1396 // Don't let the document get unloaded while we are printing.
1397 // this could happen if we hit the back button during printing.
1398 // We also keep the viewer from being cached in session history, since
1399 // we require all documents there to be sanitized.
1400 if (mDestroyRefCount
!= 0) {
1405 // If we were told to put ourselves into session history instead of destroy
1406 // the presentation, do that now.
1409 mPresShell
->Freeze();
1411 // Make sure the presentation isn't torn down by Hide().
1412 mSHEntry
->SetSticky(mIsSticky
);
1413 mIsSticky
= PR_TRUE
;
1415 PRBool savePresentation
= PR_TRUE
;
1417 // Remove our root view from the view hierarchy.
1419 nsIViewManager
*vm
= mPresShell
->GetViewManager();
1421 nsIView
*rootView
= nsnull
;
1422 vm
->GetRootView(rootView
);
1425 nsIView
*rootViewParent
= rootView
->GetParent();
1426 if (rootViewParent
) {
1427 nsIViewManager
*parentVM
= rootViewParent
->GetViewManager();
1429 parentVM
->RemoveChild(rootView
);
1438 // This is after Hide() so that the user doesn't see the inputs clear.
1440 nsresult rv
= mDocument
->Sanitize();
1441 if (NS_FAILED(rv
)) {
1442 // If we failed to sanitize, don't save presentation.
1443 savePresentation
= PR_FALSE
;
1448 // Reverse ownership. Do this *after* calling sanitize so that sanitize
1449 // doesn't cause mutations that make the SHEntry drop the presentation
1450 if (savePresentation
) {
1451 mSHEntry
->SetContentViewer(this);
1454 mSHEntry
->SyncPresentationState();
1456 nsCOMPtr
<nsISHEntry
> shEntry
= mSHEntry
; // we'll need this below
1459 // Break the link from the document/presentation to the docshell, so that
1460 // link traversals cannot affect the currently-loaded document.
1461 // When the presentation is restored, Open() and InitInternal() will reset
1462 // these pointers to their original values.
1465 mDocument
->SetContainer(nsnull
);
1467 mPresContext
->SetLinkHandler(nsnull
);
1468 mPresContext
->SetContainer(nsnull
);
1471 mPresShell
->SetForwardingContainer(mContainer
);
1473 // Do the same for our children. Note that we need to get the child
1474 // docshells from the SHEntry now; the docshell will have cleared them.
1475 nsCOMPtr
<nsIDocShellTreeItem
> item
;
1476 PRInt32 itemIndex
= 0;
1477 while (NS_SUCCEEDED(shEntry
->ChildShellAt(itemIndex
++,
1478 getter_AddRefs(item
))) && item
) {
1479 DetachContainerRecurse(nsCOMPtr
<nsIDocShell
>(do_QueryInterface(item
)));
1486 mDocument
->Destroy();
1490 // All callers are supposed to call destroy to break circular
1491 // references. If we do this stuff in the destructor, the
1492 // destructor might never be called (especially if we're being
1497 #ifdef NS_PRINT_PREVIEW
1498 PRBool doingPrintPreview
;
1499 mPrintEngine
->GetDoingPrintPreview(&doingPrintPreview
);
1500 if (doingPrintPreview
) {
1501 mPrintEngine
->FinishPrintPreview();
1505 mPrintEngine
->Destroy();
1506 mPrintEngine
= nsnull
;
1510 // Avoid leaking the old viewer.
1511 if (mPreviousViewer
) {
1512 mPreviousViewer
->Destroy();
1513 mPreviousViewer
= nsnull
;
1516 mDeviceContext
= nsnull
;
1519 // Break circular reference (or something)
1520 mPresShell
->EndObservingDocument();
1522 nsCOMPtr
<nsISelection
> selection
;
1523 GetDocumentSelection(getter_AddRefs(selection
));
1525 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
1527 if (selPrivate
&& mSelectionListener
)
1528 selPrivate
->RemoveSelectionListener(mSelectionListener
);
1530 mPresShell
->Destroy();
1531 mPresShell
= nsnull
;
1535 mPresContext
->SetContainer(nsnull
);
1536 mPresContext
->SetLinkHandler(nsnull
);
1537 mPresContext
= nsnull
;
1540 mContainer
= nsnull
;
1546 DocumentViewerImpl::Stop(void)
1548 NS_ASSERTION(mDocument
, "Stop called too early or too late");
1550 mDocument
->StopDocumentLoad();
1553 if (mEnableRendering
&& (mLoaded
|| mStopped
) && mPresContext
&& !mSHEntry
)
1554 mPresContext
->SetImageAnimationMode(imgIContainer::kDontAnimMode
);
1558 if (!mLoaded
&& mPresShell
) {
1559 // Well, we might as well paint what we have so far.
1560 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
); // bug 378682
1561 mPresShell
->UnsuppressPainting();
1568 DocumentViewerImpl::GetDOMDocument(nsIDOMDocument
**aResult
)
1570 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1571 return CallQueryInterface(mDocument
, aResult
);
1575 DocumentViewerImpl::SetDOMDocument(nsIDOMDocument
*aDocument
)
1579 // 1) this document viewer has been initialized with a call to Init().
1580 // 2) the stylesheets associated with the document have been added
1583 // XXX Right now, this method assumes that the layout of the current
1584 // document hasn't started yet. More cleanup will probably be
1585 // necessary to make this method work for the case when layout *has*
1586 // occurred for the current document.
1587 // That work can happen when and if it is needed.
1591 return NS_ERROR_NULL_POINTER
;
1593 nsCOMPtr
<nsIDocument
> newDoc
= do_QueryInterface(aDocument
, &rv
);
1594 if (NS_FAILED(rv
)) return rv
;
1596 // Set new container
1597 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
1598 newDoc
->SetContainer(container
);
1600 if (mDocument
!= newDoc
) {
1601 // Replace the old document with the new one. Do this only when
1602 // the new document really is a new document.
1605 // Set the script global object on the new document
1606 nsCOMPtr
<nsPIDOMWindow
> window
= do_GetInterface(container
);
1608 window
->SetNewDocument(newDoc
, nsnull
, PR_TRUE
);
1611 // Clear the list of old child docshells. CChild docshells for the new
1612 // document will be constructed as frames are created.
1613 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(container
);
1616 node
->GetChildCount(&count
);
1617 for (PRInt32 i
= 0; i
< count
; ++i
) {
1618 nsCOMPtr
<nsIDocShellTreeItem
> child
;
1619 node
->GetChildAt(0, getter_AddRefs(child
));
1620 node
->RemoveChild(child
);
1625 rv
= SyncParentSubDocMap();
1626 NS_ENSURE_SUCCESS(rv
, rv
);
1628 // Replace the current pres shell with a new shell for the new document
1630 nsCOMPtr
<nsILinkHandler
> linkHandler
;
1632 nsSize
currentSize(0, 0);
1635 mViewManager
->GetWindowDimensions(¤tSize
.width
, ¤tSize
.height
);
1639 // Save the linkhandler (nsPresShell::Destroy removes it from
1641 linkHandler
= mPresContext
->GetLinkHandler();
1644 mPresShell
->EndObservingDocument();
1645 mPresShell
->Destroy();
1647 mPresShell
= nsnull
;
1649 // This destroys the root view because it was associated with the root frame,
1650 // which has been torn down. Recreate the viewmanager and root view.
1651 MakeWindow(currentSize
);
1654 // And if we're already given a prescontext...
1656 // If we had a linkHandler and it got removed, put it back.
1658 mPresContext
->SetLinkHandler(linkHandler
);
1661 rv
= InitPresentationStuff(PR_FALSE
, PR_TRUE
);
1668 DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet
* aUAStyleSheet
)
1670 NS_ASSERTION(aUAStyleSheet
, "unexpected null pointer");
1671 nsCOMPtr
<nsICSSStyleSheet
> sheet(do_QueryInterface(aUAStyleSheet
));
1673 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
1674 sheet
->Clone(nsnull
, nsnull
, nsnull
, nsnull
, getter_AddRefs(newSheet
));
1675 mUAStyleSheet
= newSheet
;
1681 DocumentViewerImpl::GetDocument(nsIDocument
** aResult
)
1683 NS_IF_ADDREF(*aResult
= mDocument
);
1689 DocumentViewerImpl::GetPresShell()
1691 if (!GetIsPrintPreview()) {
1694 NS_ENSURE_TRUE(mDocument
, nsnull
);
1695 nsCOMPtr
<nsIPresShell
> shell
;
1696 nsCOMPtr
<nsIPresShell
> currentShell
;
1697 nsPresShellIterator
iter(mDocument
);
1698 while ((shell
= iter
.GetNextShell())) {
1699 currentShell
.swap(shell
);
1701 return currentShell
.get();
1705 DocumentViewerImpl::GetPresContext()
1707 if (!GetIsPrintPreview()) {
1708 return mPresContext
;
1710 nsIPresShell
* shell
= GetPresShell();
1711 return shell
? shell
->GetPresContext() : nsnull
;
1715 DocumentViewerImpl::GetViewManager()
1717 if (!GetIsPrintPreview()) {
1718 return mViewManager
;
1720 nsIPresShell
* shell
= GetPresShell();
1721 return shell
? shell
->GetViewManager() : nsnull
;
1725 DocumentViewerImpl::GetPresShell(nsIPresShell
** aResult
)
1727 nsIPresShell
* shell
= GetPresShell();
1728 NS_IF_ADDREF(*aResult
= shell
);
1733 DocumentViewerImpl::GetPresContext(nsPresContext
** aResult
)
1735 nsPresContext
* pc
= GetPresContext();
1736 NS_IF_ADDREF(*aResult
= pc
);
1741 DocumentViewerImpl::GetBounds(nsRect
& aResult
)
1743 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1744 NS_PRECONDITION(mWindow
, "null window");
1746 mWindow
->GetBounds(aResult
);
1749 aResult
.SetRect(0, 0, 0, 0);
1755 DocumentViewerImpl::GetPreviousViewer(nsIContentViewer
** aViewer
)
1757 *aViewer
= mPreviousViewer
;
1758 NS_IF_ADDREF(*aViewer
);
1763 DocumentViewerImpl::SetPreviousViewer(nsIContentViewer
* aViewer
)
1765 // NOTE: |Show| sets |mPreviousViewer| to null without calling this
1769 NS_ASSERTION(!mPreviousViewer
,
1770 "can't set previous viewer when there already is one");
1772 // In a multiple chaining situation (which occurs when running a thrashing
1773 // test like i-bench or jrgm's tests with no delay), we can build up a
1774 // whole chain of viewers. In order to avoid this, we always set our previous
1775 // viewer to the MOST previous viewer in the chain, and then dump the intermediate
1776 // link from the chain. This ensures that at most only 2 documents are alive
1777 // and undestroyed at any given time (the one that is showing and the one that
1778 // is loading with painting suppressed).
1779 // It's very important that if this ever gets changed the code
1780 // before the RestorePresentation call in nsDocShell::InternalLoad
1781 // be changed accordingly.
1782 nsCOMPtr
<nsIContentViewer
> prevViewer
;
1783 aViewer
->GetPreviousViewer(getter_AddRefs(prevViewer
));
1785 aViewer
->SetPreviousViewer(nsnull
);
1787 return SetPreviousViewer(prevViewer
);
1791 mPreviousViewer
= aViewer
;
1796 DocumentViewerImpl::SetBounds(const nsRect
& aBounds
)
1798 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1801 // Don't have the widget repaint. Layout will generate repaint requests
1803 mWindow
->Resize(aBounds
.x
, aBounds
.y
, aBounds
.width
, aBounds
.height
,
1807 // If there's a previous viewer, it's the one that's actually showing,
1808 // so be sure to resize it as well so it paints over the right area.
1809 // This may slow down the performance of the new page load, but resize
1810 // during load is also probably a relatively unusual condition
1811 // relating to things being hidden while something is loaded. It so
1812 // happens that Firefox does this a good bit with its infobar, and it
1813 // looks ugly if we don't do this.
1814 if (mPreviousViewer
)
1815 mPreviousViewer
->SetBounds(aBounds
);
1817 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
1818 if (GetIsPrintPreview() && !mPrintEngine
->GetIsCreatingPrintPreview()) {
1819 mPrintEngine
->GetPrintPreviewWindow()->Resize(aBounds
.x
, aBounds
.y
,
1820 aBounds
.width
, aBounds
.height
,
1828 DocumentViewerImpl::Move(PRInt32 aX
, PRInt32 aY
)
1830 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1831 NS_PRECONDITION(mWindow
, "null window");
1833 mWindow
->Move(aX
, aY
);
1839 DocumentViewerImpl::Show(void)
1841 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
1843 // We don't need the previous viewer anymore since we're not
1845 if (mPreviousViewer
) {
1846 // This little dance *may* only be to keep
1847 // PresShell::EndObservingDocument happy, but I'm not sure.
1848 nsCOMPtr
<nsIContentViewer
> prevViewer(mPreviousViewer
);
1849 mPreviousViewer
= nsnull
;
1850 prevViewer
->Destroy();
1852 // Make sure we don't have too many cached ContentViewers
1853 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryReferent(mContainer
);
1855 // We need to find the root DocShell since only that object has an
1856 // SHistory and we need the SHistory to evict content viewers
1857 nsCOMPtr
<nsIDocShellTreeItem
> root
;
1858 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
1859 nsCOMPtr
<nsIWebNavigation
> webNav
= do_QueryInterface(root
);
1860 nsCOMPtr
<nsISHistory
> history
;
1861 webNav
->GetSessionHistory(getter_AddRefs(history
));
1862 nsCOMPtr
<nsISHistoryInternal
> historyInt
= do_QueryInterface(history
);
1864 PRInt32 prevIndex
,loadedIndex
;
1865 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(treeItem
);
1866 docShell
->GetPreviousTransIndex(&prevIndex
);
1867 docShell
->GetLoadedTransIndex(&loadedIndex
);
1868 #ifdef DEBUG_PAGE_CACHE
1869 printf("About to evict content viewers: prev=%d, loaded=%d\n",
1870 prevIndex
, loadedIndex
);
1872 historyInt
->EvictContentViewers(prevIndex
, loadedIndex
);
1878 mWindow
->Show(PR_TRUE
);
1881 if (mDocument
&& !mPresShell
&& !mWindow
) {
1882 nsCOMPtr
<nsIBaseWindow
> base_win(do_QueryReferent(mContainer
));
1883 NS_ENSURE_TRUE(base_win
, NS_ERROR_UNEXPECTED
);
1885 base_win
->GetParentWidget(&mParentWidget
);
1886 NS_ENSURE_TRUE(mParentWidget
, NS_ERROR_UNEXPECTED
);
1887 mParentWidget
->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
1889 nsresult rv
= CreateDeviceContext(mParentWidget
);
1890 NS_ENSURE_SUCCESS(rv
, rv
);
1892 // Create presentation context
1893 NS_ASSERTION(!mPresContext
, "Shouldn't have a prescontext if we have no shell!");
1894 mPresContext
= new nsPresContext(mDocument
, nsPresContext::eContext_Galley
);
1895 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
1897 rv
= mPresContext
->Init(mDeviceContext
);
1898 if (NS_FAILED(rv
)) {
1899 mPresContext
= nsnull
;
1904 mParentWidget
->GetBounds(tbounds
);
1906 rv
= MakeWindow(nsSize(mPresContext
->DevPixelsToAppUnits(tbounds
.width
),
1907 mPresContext
->DevPixelsToAppUnits(tbounds
.height
)));
1911 if (mPresContext
&& base_win
) {
1912 nsCOMPtr
<nsILinkHandler
> linkHandler(do_GetInterface(base_win
));
1915 mPresContext
->SetLinkHandler(linkHandler
);
1918 mPresContext
->SetContainer(base_win
);
1924 rv
= InitPresentationStuff(mDocument
->MayStartLayout(),
1925 mDocument
->MayStartLayout());
1928 // If we get here the document load has already started and the
1929 // window is shown because some JS on the page caused it to be
1932 nsCOMPtr
<nsIPresShell
> shellDeathGrip(mPresShell
); // bug 378682
1933 mPresShell
->UnsuppressPainting();
1940 DocumentViewerImpl::Hide(void)
1942 NS_PRECONDITION(mWindow
, "null window");
1944 mWindow
->Show(PR_FALSE
);
1950 NS_ASSERTION(mPresContext
, "Can't have a presshell and no prescontext!");
1952 // Avoid leaking the old viewer.
1953 if (mPreviousViewer
) {
1954 mPreviousViewer
->Destroy();
1955 mPreviousViewer
= nsnull
;
1959 // This window is sticky, that means that it might be shown again
1960 // and we don't want the presshell n' all that to be thrown away
1961 // just because the window is hidden.
1966 // Break circular reference (or something)
1967 mPresShell
->EndObservingDocument();
1968 nsCOMPtr
<nsISelection
> selection
;
1970 GetDocumentSelection(getter_AddRefs(selection
));
1972 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
1974 if (selPrivate
&& mSelectionListener
) {
1975 selPrivate
->RemoveSelectionListener(mSelectionListener
);
1978 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
1980 PRBool saveLayoutState
= PR_FALSE
;
1981 docShell
->GetShouldSaveLayoutState(&saveLayoutState
);
1982 if (saveLayoutState
) {
1983 nsCOMPtr
<nsILayoutHistoryState
> layoutState
;
1984 mPresShell
->CaptureHistoryState(getter_AddRefs(layoutState
), PR_TRUE
);
1988 mPresShell
->Destroy();
1990 mPresContext
->SetContainer(nsnull
);
1991 mPresContext
->SetLinkHandler(nsnull
);
1993 mPresShell
= nsnull
;
1994 mPresContext
= nsnull
;
1995 mViewManager
= nsnull
;
1997 mDeviceContext
= nsnull
;
1998 mParentWidget
= nsnull
;
2000 nsCOMPtr
<nsIBaseWindow
> base_win(do_QueryReferent(mContainer
));
2003 base_win
->SetParentWidget(nsnull
);
2009 DocumentViewerImpl::SetEnableRendering(PRBool aOn
)
2011 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
2012 mEnableRendering
= aOn
;
2015 mViewManager
->EnableRefresh(NS_VMREFRESH_IMMEDIATE
);
2017 mViewManager
->GetRootView(view
); // views are not refCounted
2019 mViewManager
->UpdateView(view
, NS_VMREFRESH_IMMEDIATE
);
2023 mViewManager
->DisableRefresh();
2030 DocumentViewerImpl::GetSticky(PRBool
*aSticky
)
2032 *aSticky
= mIsSticky
;
2038 DocumentViewerImpl::SetSticky(PRBool aSticky
)
2040 mIsSticky
= aSticky
;
2046 DocumentViewerImpl::GetEnableRendering(PRBool
* aResult
)
2048 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
2049 NS_PRECONDITION(nsnull
!= aResult
, "null OUT ptr");
2051 *aResult
= mEnableRendering
;
2057 DocumentViewerImpl::RequestWindowClose(PRBool
* aCanClose
)
2060 if (mPrintIsPending
|| (mPrintEngine
&& mPrintEngine
->GetIsPrinting())) {
2061 *aCanClose
= PR_FALSE
;
2062 mDeferredWindowClose
= PR_TRUE
;
2065 *aCanClose
= PR_TRUE
;
2070 PR_STATIC_CALLBACK(PRBool
)
2071 AppendAgentSheet(nsIStyleSheet
*aSheet
, void *aData
)
2073 nsStyleSet
*styleSet
= static_cast<nsStyleSet
*>(aData
);
2074 styleSet
->AppendStyleSheet(nsStyleSet::eAgentSheet
, aSheet
);
2078 PR_STATIC_CALLBACK(PRBool
)
2079 PrependUserSheet(nsIStyleSheet
*aSheet
, void *aData
)
2081 nsStyleSet
*styleSet
= static_cast<nsStyleSet
*>(aData
);
2082 styleSet
->PrependStyleSheet(nsStyleSet::eUserSheet
, aSheet
);
2087 DocumentViewerImpl::CreateStyleSet(nsIDocument
* aDocument
,
2088 nsStyleSet
** aStyleSet
)
2090 // Make sure this does the same thing as PresShell::AddSheet wrt ordering.
2092 // this should eventually get expanded to allow for creating
2093 // different sets for different media
2094 if (!mUAStyleSheet
) {
2095 NS_WARNING("unable to load UA style sheet");
2098 nsStyleSet
*styleSet
= new nsStyleSet();
2100 return NS_ERROR_OUT_OF_MEMORY
;
2103 styleSet
->BeginUpdate();
2105 // The document will fill in the document sheets when we create the presshell
2107 // Handle the user sheets.
2108 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryReferent(mContainer
));
2110 docShell
->GetItemType(&shellType
);
2111 nsICSSStyleSheet
* sheet
= nsnull
;
2112 if (shellType
== nsIDocShellTreeItem::typeChrome
) {
2113 sheet
= nsLayoutStylesheetCache::UserChromeSheet();
2116 sheet
= nsLayoutStylesheetCache::UserContentSheet();
2120 styleSet
->AppendStyleSheet(nsStyleSet::eUserSheet
, sheet
);
2122 // Append chrome sheets (scrollbars + forms).
2123 PRBool shouldOverride
= PR_FALSE
;
2124 nsCOMPtr
<nsIDocShell
> ds(do_QueryInterface(docShell
));
2125 nsCOMPtr
<nsIDOMEventTarget
> chromeHandler
;
2126 nsCOMPtr
<nsIURI
> uri
;
2127 nsCOMPtr
<nsICSSStyleSheet
> csssheet
;
2129 ds
->GetChromeEventHandler(getter_AddRefs(chromeHandler
));
2130 if (chromeHandler
) {
2131 nsCOMPtr
<nsIDOMElement
> elt(do_QueryInterface(chromeHandler
));
2132 nsCOMPtr
<nsIContent
> content(do_QueryInterface(elt
));
2133 if (elt
&& content
) {
2134 nsCOMPtr
<nsIURI
> baseURI
= content
->GetBaseURI();
2136 nsAutoString sheets
;
2137 elt
->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets
);
2138 if (!sheets
.IsEmpty() && baseURI
) {
2139 nsCOMPtr
<nsICSSLoader
> cssLoader
;
2140 NS_NewCSSLoader(getter_AddRefs(cssLoader
));
2142 char *str
= ToNewCString(sheets
);
2145 while ( (token
= nsCRT::strtok(newStr
, ", ", &newStr
)) ) {
2146 NS_NewURI(getter_AddRefs(uri
), nsDependentCString(token
), nsnull
,
2150 cssLoader
->LoadSheetSync(uri
, getter_AddRefs(csssheet
));
2151 if (!sheet
) continue;
2153 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, csssheet
);
2154 shouldOverride
= PR_TRUE
;
2156 nsMemory::Free(str
);
2161 if (!shouldOverride
) {
2162 sheet
= nsLayoutStylesheetCache::ScrollbarsSheet();
2164 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, sheet
);
2168 sheet
= nsLayoutStylesheetCache::FormsSheet();
2170 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, sheet
);
2173 if (mUAStyleSheet
) {
2174 styleSet
->PrependStyleSheet(nsStyleSet::eAgentSheet
, mUAStyleSheet
);
2177 nsCOMPtr
<nsIStyleSheetService
> dummy
=
2178 do_GetService(NS_STYLESHEETSERVICE_CONTRACTID
);
2180 nsStyleSheetService
*sheetService
= nsStyleSheetService::gInstance
;
2182 sheetService
->AgentStyleSheets()->EnumerateForwards(AppendAgentSheet
,
2184 sheetService
->UserStyleSheets()->EnumerateBackwards(PrependUserSheet
,
2188 // Caller will handle calling EndUpdate, per contract.
2189 *aStyleSet
= styleSet
;
2194 DocumentViewerImpl::ClearHistoryEntry()
2200 //-------------------------------------------------------
2203 DocumentViewerImpl::MakeWindow(const nsSize
& aSize
)
2207 mViewManager
= do_CreateInstance(kViewManagerCID
, &rv
);
2211 nsIDeviceContext
*dx
= mPresContext
->DeviceContext();
2213 rv
= mViewManager
->Init(dx
);
2217 // Create a child window of the parent that is our "root view/window"
2218 // if aParentWidget has a view, we'll hook our view manager up to its view tree
2219 nsIView
* containerView
= nsIView::GetViewFor(mParentWidget
);
2221 if (containerView
) {
2222 // see if the containerView has already been hooked into a foreign view manager hierarchy
2223 // if it has, then we have to hook into the hierarchy too otherwise bad things will happen.
2224 nsIViewManager
* containerVM
= containerView
->GetViewManager();
2225 nsIView
* pView
= containerView
;
2227 pView
= pView
->GetParent();
2228 } while (pView
&& pView
->GetViewManager() == containerVM
);
2231 // OK, so the container is not already hooked up into a foreign view manager hierarchy.
2232 // That means we can choose not to hook ourselves up.
2234 // If the parent container is a chrome shell and we are a content shell
2235 // then we won't hook into its view
2236 // tree. This will improve performance a little bit (especially given scrolling/painting perf bugs)
2237 // but is really just for peace of mind. This check can be removed if we want to support fancy
2238 // chrome effects like transparent controls floating over content, transparent Web browsers, and
2239 // things like that, and the perf bugs are fixed.
2240 nsCOMPtr
<nsIDocShellTreeItem
> container(do_QueryReferent(mContainer
));
2241 nsCOMPtr
<nsIDocShellTreeItem
> sameTypeParent
;
2243 container
->GetSameTypeParent(getter_AddRefs(sameTypeParent
));
2245 if (!sameTypeParent
) {
2246 containerView
= nsnull
;
2251 // The root view is always at 0,0.
2252 nsRect
tbounds(nsPoint(0, 0), aSize
);
2254 nsIView
* view
= mViewManager
->CreateView(tbounds
, containerView
);
2256 return NS_ERROR_OUT_OF_MEMORY
;
2258 // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
2259 // otherwise the view will find its own parent widget and "do the right thing" to
2260 // establish a parent/child widget relationship
2261 rv
= view
->CreateWidget(kWidgetCID
, nsnull
,
2262 containerView
!= nsnull
? nsnull
: mParentWidget
->GetNativeData(NS_NATIVE_WIDGET
),
2267 // Setup hierarchical relationship in view manager
2268 mViewManager
->SetRootView(view
);
2270 mWindow
= view
->GetWidget();
2272 // This SetFocus is necessary so the Arrow Key and Page Key events
2273 // go to the scrolled view as soon as the Window is created instead of going to
2274 // the browser window (this enables keyboard scrolling of the document)
2275 // mWindow->SetFocus();
2281 DocumentViewerImpl::CreateDeviceContext(nsIWidget
* aWidget
)
2283 NS_PRECONDITION(!mDeviceContext
, "How come we're calling this?");
2285 mDeviceContext
= do_CreateInstance(kDeviceContextCID
);
2286 NS_ENSURE_TRUE(mDeviceContext
, NS_ERROR_FAILURE
);
2287 mDeviceContext
->Init(aWidget
->GetNativeData(NS_NATIVE_WIDGET
));
2292 // Return the selection for the document. Note that text fields have their
2293 // own selection, which cannot be accessed with this method. Use
2294 // mPresShell->GetSelectionForCopy() instead.
2295 nsresult
DocumentViewerImpl::GetDocumentSelection(nsISelection
**aSelection
)
2297 NS_ENSURE_ARG_POINTER(aSelection
);
2299 return NS_ERROR_NOT_INITIALIZED
;
2302 nsCOMPtr
<nsISelectionController
> selcon
;
2303 selcon
= do_QueryInterface(mPresShell
);
2305 return selcon
->GetSelection(nsISelectionController::SELECTION_NORMAL
,
2307 return NS_ERROR_FAILURE
;
2310 /* ========================================================================================
2311 * nsIContentViewerEdit
2312 * ======================================================================================== */
2314 NS_IMETHODIMP
DocumentViewerImpl::Search()
2316 // Nothing to do here.
2320 NS_IMETHODIMP
DocumentViewerImpl::GetSearchable(PRBool
*aSearchable
)
2322 // Nothing to do here.
2323 *aSearchable
= PR_FALSE
;
2327 NS_IMETHODIMP
DocumentViewerImpl::ClearSelection()
2330 nsCOMPtr
<nsISelection
> selection
;
2332 // use mPresShell->GetSelectionForCopy() ?
2333 rv
= GetDocumentSelection(getter_AddRefs(selection
));
2334 if (NS_FAILED(rv
)) return rv
;
2336 return selection
->CollapseToStart();
2339 NS_IMETHODIMP
DocumentViewerImpl::SelectAll()
2341 // XXX this is a temporary implementation copied from nsWebShell
2342 // for now. I think nsDocument and friends should have some helper
2343 // functions to make this easier.
2344 nsCOMPtr
<nsISelection
> selection
;
2347 // use mPresShell->GetSelectionForCopy() ?
2348 rv
= GetDocumentSelection(getter_AddRefs(selection
));
2349 if (NS_FAILED(rv
)) return rv
;
2351 nsCOMPtr
<nsIDOMHTMLDocument
> htmldoc
= do_QueryInterface(mDocument
);
2352 nsCOMPtr
<nsIDOMNode
> bodyNode
;
2356 nsCOMPtr
<nsIDOMHTMLElement
>bodyElement
;
2357 rv
= htmldoc
->GetBody(getter_AddRefs(bodyElement
));
2358 if (NS_FAILED(rv
) || !bodyElement
) return rv
;
2360 bodyNode
= do_QueryInterface(bodyElement
);
2364 bodyNode
= do_QueryInterface(mDocument
->GetRootContent());
2366 if (!bodyNode
) return NS_ERROR_FAILURE
;
2368 rv
= selection
->RemoveAllRanges();
2369 if (NS_FAILED(rv
)) return rv
;
2371 rv
= selection
->SelectAllChildren(bodyNode
);
2375 NS_IMETHODIMP
DocumentViewerImpl::CopySelection()
2377 PRBool preventDefault
;
2378 nsresult rv
= FireClipboardEvent(NS_COPY
, &preventDefault
);
2379 if (NS_FAILED(rv
) || preventDefault
)
2382 return mPresShell
->DoCopy();
2385 NS_IMETHODIMP
DocumentViewerImpl::CopyLinkLocation()
2387 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2388 nsCOMPtr
<nsIDOMNode
> node
;
2389 GetPopupLinkNode(getter_AddRefs(node
));
2390 // make noise if we're not in a link
2391 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
2393 nsAutoString locationText
;
2394 nsresult rv
= mPresShell
->GetLinkLocation(node
, locationText
);
2395 NS_ENSURE_SUCCESS(rv
, rv
);
2397 nsCOMPtr
<nsIClipboardHelper
> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv
));
2398 NS_ENSURE_SUCCESS(rv
, rv
);
2400 // copy the href onto the clipboard
2401 return clipboard
->CopyString(locationText
);
2404 NS_IMETHODIMP
DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags
)
2406 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2407 nsCOMPtr
<nsIImageLoadingContent
> node
;
2408 GetPopupImageNode(getter_AddRefs(node
));
2409 // make noise if we're not in an image
2410 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
2412 return nsCopySupport::ImageCopy(node
, aCopyFlags
);
2415 nsresult
DocumentViewerImpl::GetClipboardEventTarget(nsIDOMNode
** aEventTarget
)
2417 NS_ENSURE_ARG_POINTER(aEventTarget
);
2418 *aEventTarget
= nsnull
;
2421 return NS_ERROR_NOT_INITIALIZED
;
2423 nsCOMPtr
<nsISelection
> sel
;
2424 nsresult rv
= mPresShell
->GetSelectionForCopy(getter_AddRefs(sel
));
2428 return NS_ERROR_FAILURE
;
2430 return nsCopySupport::GetClipboardEventTarget(sel
, aEventTarget
);
2433 nsresult
DocumentViewerImpl::FireClipboardEvent(PRUint32 msg
,
2434 PRBool
* aPreventDefault
)
2436 *aPreventDefault
= PR_FALSE
;
2438 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_NOT_INITIALIZED
);
2439 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2441 // It seems to be unsafe to fire an event handler during reflow (bug 393696)
2442 PRBool isReflowing
= PR_TRUE
;
2443 nsresult rv
= mPresShell
->IsReflowLocked(&isReflowing
);
2444 if (NS_FAILED(rv
) || isReflowing
)
2447 nsCOMPtr
<nsIDOMNode
> eventTarget
;
2448 rv
= GetClipboardEventTarget(getter_AddRefs(eventTarget
));
2450 // On failure to get event target, just forget about it and don't fire.
2453 nsEventStatus status
= nsEventStatus_eIgnore
;
2454 nsEvent
evt(PR_TRUE
, msg
);
2455 nsEventDispatcher::Dispatch(eventTarget
, mPresContext
, &evt
, nsnull
,
2457 // if event handler return'd false (PreventDefault)
2458 if (status
== nsEventStatus_eConsumeNoDefault
)
2459 *aPreventDefault
= PR_TRUE
;
2461 // Ensure that the calling function can use mPresShell -- if the event
2462 // handler closed this window, mPresShell will be gone.
2463 NS_ENSURE_STATE(mPresShell
);
2468 NS_IMETHODIMP
DocumentViewerImpl::GetCopyable(PRBool
*aCopyable
)
2470 NS_ENSURE_ARG_POINTER(aCopyable
);
2471 *aCopyable
= PR_FALSE
;
2473 NS_ENSURE_STATE(mPresShell
);
2474 nsCOMPtr
<nsISelection
> selection
;
2475 nsresult rv
= mPresShell
->GetSelectionForCopy(getter_AddRefs(selection
));
2480 selection
->GetIsCollapsed(&isCollapsed
);
2482 *aCopyable
= !isCollapsed
;
2486 NS_IMETHODIMP
DocumentViewerImpl::CutSelection()
2488 // preventDefault's value is ignored because cut from the document has no
2489 // default behaviour.
2490 PRBool preventDefault
;
2491 return FireClipboardEvent(NS_CUT
, &preventDefault
);
2494 NS_IMETHODIMP
DocumentViewerImpl::GetCutable(PRBool
*aCutable
)
2496 NS_ENSURE_ARG_POINTER(aCutable
);
2497 *aCutable
= PR_FALSE
;
2501 NS_IMETHODIMP
DocumentViewerImpl::Paste()
2503 // preventDefault's value is ignored because paste into the document has no
2504 // default behaviour.
2505 PRBool preventDefault
;
2506 return FireClipboardEvent(NS_PASTE
, &preventDefault
);
2509 NS_IMETHODIMP
DocumentViewerImpl::GetPasteable(PRBool
*aPasteable
)
2511 NS_ENSURE_ARG_POINTER(aPasteable
);
2512 *aPasteable
= PR_FALSE
;
2516 /* AString getContents (in string mimeType, in boolean selectionOnly); */
2517 NS_IMETHODIMP
DocumentViewerImpl::GetContents(const char *mimeType
, PRBool selectionOnly
, nsAString
& aOutValue
)
2519 NS_ENSURE_TRUE(mPresShell
, NS_ERROR_NOT_INITIALIZED
);
2520 return mPresShell
->DoGetContents(nsDependentCString(mimeType
), 0, selectionOnly
, aOutValue
);
2523 /* readonly attribute boolean canGetContents; */
2524 NS_IMETHODIMP
DocumentViewerImpl::GetCanGetContents(PRBool
*aCanGetContents
)
2526 return GetCopyable(aCanGetContents
);
2533 /* ========================================================================================
2534 * nsIContentViewerFile
2535 * ======================================================================================== */
2536 /** ---------------------------------------------------
2537 * See documentation above in the nsIContentViewerfile class definition
2538 * @update 01/24/00 dwc
2541 DocumentViewerImpl::Print(PRBool aSilent
,
2543 nsIPrintSettings
* aPrintSettings
)
2546 nsCOMPtr
<nsIPrintSettings
> printSettings
;
2549 nsresult rv
= NS_ERROR_FAILURE
;
2551 mDebugFile
= aDebugFile
;
2552 // if they don't pass in a PrintSettings, then make one
2553 // it will have all the default values
2554 printSettings
= aPrintSettings
;
2555 nsCOMPtr
<nsIPrintOptions
> printOptions
= do_GetService(sPrintOptionsContractID
, &rv
);
2556 if (NS_SUCCEEDED(rv
)) {
2557 // if they don't pass in a PrintSettings, then make one
2558 if (printSettings
== nsnull
) {
2559 printOptions
->CreatePrintSettings(getter_AddRefs(printSettings
));
2561 NS_ASSERTION(printSettings
, "You can't PrintPreview without a PrintSettings!");
2563 if (printSettings
) printSettings
->SetPrintSilent(aSilent
);
2564 if (printSettings
) printSettings
->SetShowPrintProgress(PR_FALSE
);
2568 return Print(printSettings
, nsnull
);
2570 return NS_ERROR_FAILURE
;
2574 /* [noscript] void printWithParent (in nsIDOMWindowInternal aParentWin, in nsIPrintSettings aThePrintSettings, in nsIWebProgressListener aWPListener); */
2576 DocumentViewerImpl::PrintWithParent(nsIDOMWindowInternal
*aParentWin
, nsIPrintSettings
*aThePrintSettings
, nsIWebProgressListener
*aWPListener
)
2579 return Print(aThePrintSettings
, aWPListener
);
2581 return NS_ERROR_FAILURE
;
2585 // nsIContentViewerFile interface
2587 DocumentViewerImpl::GetPrintable(PRBool
*aPrintable
)
2589 NS_ENSURE_ARG_POINTER(aPrintable
);
2591 *aPrintable
= !GetIsPrinting();
2596 //*****************************************************************************
2597 // nsIMarkupDocumentViewer
2598 //*****************************************************************************
2600 NS_IMETHODIMP
DocumentViewerImpl::ScrollToNode(nsIDOMNode
* aNode
)
2602 NS_ENSURE_ARG(aNode
);
2603 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
2604 nsCOMPtr
<nsIPresShell
> presShell
;
2605 NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell
)), NS_ERROR_FAILURE
);
2607 // Get the nsIContent interface, because that's what we need to
2608 // get the primary frame
2610 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aNode
));
2611 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
2613 // Tell the PresShell to scroll to the primary frame of the content.
2614 NS_ENSURE_SUCCESS(presShell
->ScrollContentIntoView(content
,
2615 NS_PRESSHELL_SCROLL_TOP
,
2616 NS_PRESSHELL_SCROLL_ANYWHERE
),
2622 DocumentViewerImpl::CallChildren(CallChildFunc aFunc
, void* aClosure
)
2624 nsCOMPtr
<nsIDocShellTreeNode
> docShellNode(do_QueryReferent(mContainer
));
2629 docShellNode
->GetChildCount(&n
);
2630 for (i
=0; i
< n
; i
++)
2632 nsCOMPtr
<nsIDocShellTreeItem
> child
;
2633 docShellNode
->GetChildAt(i
, getter_AddRefs(child
));
2634 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
2635 NS_ASSERTION(childAsShell
, "null child in docshell");
2638 nsCOMPtr
<nsIContentViewer
> childCV
;
2639 childAsShell
->GetContentViewer(getter_AddRefs(childCV
));
2642 nsCOMPtr
<nsIMarkupDocumentViewer
> markupCV
= do_QueryInterface(childCV
);
2644 (*aFunc
)(markupCV
, aClosure
);
2658 SetChildTextZoom(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2660 struct ZoomInfo
* ZoomInfo
= (struct ZoomInfo
*) aClosure
;
2661 aChild
->SetTextZoom(ZoomInfo
->mZoom
);
2665 SetChildFullZoom(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2667 struct ZoomInfo
* ZoomInfo
= (struct ZoomInfo
*) aClosure
;
2668 aChild
->SetFullZoom(ZoomInfo
->mZoom
);
2672 DocumentViewerImpl::SetTextZoom(float aTextZoom
)
2674 if (!GetIsPrintPreview()) {
2675 mTextZoom
= aTextZoom
;
2678 nsIViewManager::UpdateViewBatch
batch(GetViewManager());
2680 // Set the text zoom on all children of mContainer (even if our zoom didn't
2681 // change, our children's zoom may be different, though it would be unusual).
2682 // Do this first, in case kids are auto-sizing and post reflow commands on
2683 // our presshell (which should be subsumed into our own style change reflow).
2684 struct ZoomInfo ZoomInfo
= { aTextZoom
};
2685 CallChildren(SetChildTextZoom
, &ZoomInfo
);
2687 // Now change our own zoom
2688 nsPresContext
* pc
= GetPresContext();
2689 if (pc
&& aTextZoom
!= mPresContext
->TextZoom()) {
2690 pc
->SetTextZoom(aTextZoom
);
2693 batch
.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC
);
2699 DocumentViewerImpl::GetTextZoom(float* aTextZoom
)
2701 NS_ENSURE_ARG_POINTER(aTextZoom
);
2702 nsPresContext
* pc
= GetPresContext();
2703 *aTextZoom
= pc
? pc
->TextZoom() : 1.0f
;
2708 DocumentViewerImpl::SetFullZoom(float aFullZoom
)
2710 if (!GetIsPrintPreview()) {
2711 mPageZoom
= aFullZoom
;
2714 nsIViewManager::UpdateViewBatch
batch(GetViewManager());
2716 struct ZoomInfo ZoomInfo
= { aFullZoom
};
2717 CallChildren(SetChildFullZoom
, &ZoomInfo
);
2719 nsPresContext
* pc
= GetPresContext();
2721 pc
->SetFullZoom(aFullZoom
);
2724 batch
.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC
);
2730 DocumentViewerImpl::GetFullZoom(float* aFullZoom
)
2732 NS_ENSURE_ARG_POINTER(aFullZoom
);
2733 // Check the prescontext first because it might have a temporary
2734 // setting for print-preview
2735 nsPresContext
* pc
= GetPresContext();
2736 *aFullZoom
= pc
? pc
->GetFullZoom() : mPageZoom
;
2741 SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2743 PRBool styleDisabled
= *static_cast<PRBool
*>(aClosure
);
2744 aChild
->SetAuthorStyleDisabled(styleDisabled
);
2749 DocumentViewerImpl::SetAuthorStyleDisabled(PRBool aStyleDisabled
)
2752 mPresShell
->SetAuthorStyleDisabled(aStyleDisabled
);
2754 CallChildren(SetChildAuthorStyleDisabled
, &aStyleDisabled
);
2759 DocumentViewerImpl::GetAuthorStyleDisabled(PRBool
* aStyleDisabled
)
2762 *aStyleDisabled
= mPresShell
->GetAuthorStyleDisabled();
2764 *aStyleDisabled
= PR_FALSE
;
2770 DocumentViewerImpl::GetDefaultCharacterSet(nsACString
& aDefaultCharacterSet
)
2772 NS_ENSURE_STATE(nsCOMPtr
<nsISupports
>(do_QueryReferent(mContainer
)));
2774 if (mDefaultCharacterSet
.IsEmpty())
2776 const nsAdoptingString
& defCharset
=
2777 nsContentUtils::GetLocalizedStringPref("intl.charset.default");
2779 if (!defCharset
.IsEmpty())
2780 LossyCopyUTF16toASCII(defCharset
, mDefaultCharacterSet
);
2782 mDefaultCharacterSet
.AssignLiteral("ISO-8859-1");
2784 aDefaultCharacterSet
= mDefaultCharacterSet
;
2789 SetChildDefaultCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2791 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2792 aChild
->SetDefaultCharacterSet(*charset
);
2796 DocumentViewerImpl::SetDefaultCharacterSet(const nsACString
& aDefaultCharacterSet
)
2798 mDefaultCharacterSet
= aDefaultCharacterSet
; // this does a copy of aDefaultCharacterSet
2799 // now set the default char set on all children of mContainer
2800 CallChildren(SetChildDefaultCharacterSet
, (void*) &aDefaultCharacterSet
);
2804 // XXX: SEMANTIC CHANGE!
2805 // returns a copy of the string. Caller is responsible for freeing result
2806 // using Recycle(aForceCharacterSet)
2807 NS_IMETHODIMP
DocumentViewerImpl::GetForceCharacterSet(nsACString
& aForceCharacterSet
)
2809 aForceCharacterSet
= mForceCharacterSet
;
2814 SetChildForceCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2816 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2817 aChild
->SetForceCharacterSet(*charset
);
2821 DocumentViewerImpl::SetForceCharacterSet(const nsACString
& aForceCharacterSet
)
2823 mForceCharacterSet
= aForceCharacterSet
;
2824 // now set the force char set on all children of mContainer
2825 CallChildren(SetChildForceCharacterSet
, (void*) &aForceCharacterSet
);
2829 // XXX: SEMANTIC CHANGE!
2830 // returns a copy of the string. Caller is responsible for freeing result
2831 // using Recycle(aHintCharacterSet)
2832 NS_IMETHODIMP
DocumentViewerImpl::GetHintCharacterSet(nsACString
& aHintCharacterSet
)
2835 if(kCharsetUninitialized
== mHintCharsetSource
) {
2836 aHintCharacterSet
.Truncate();
2838 aHintCharacterSet
= mHintCharset
;
2839 // this can't possibly be right. we can't set a value just because somebody got a related value!
2840 //mHintCharsetSource = kCharsetUninitialized;
2845 NS_IMETHODIMP
DocumentViewerImpl::GetHintCharacterSetSource(PRInt32
*aHintCharacterSetSource
)
2847 NS_ENSURE_ARG_POINTER(aHintCharacterSetSource
);
2849 *aHintCharacterSetSource
= mHintCharsetSource
;
2854 NS_IMETHODIMP
DocumentViewerImpl::GetPrevDocCharacterSet(nsACString
& aPrevDocCharacterSet
)
2856 aPrevDocCharacterSet
= mPrevDocCharacterSet
;
2862 SetChildPrevDocCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2864 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2865 aChild
->SetPrevDocCharacterSet(*charset
);
2870 DocumentViewerImpl::SetPrevDocCharacterSet(const nsACString
& aPrevDocCharacterSet
)
2872 mPrevDocCharacterSet
= aPrevDocCharacterSet
;
2873 CallChildren(SetChildPrevDocCharacterSet
, (void*) &aPrevDocCharacterSet
);
2879 SetChildHintCharacterSetSource(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2881 aChild
->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure
));
2885 DocumentViewerImpl::SetHintCharacterSetSource(PRInt32 aHintCharacterSetSource
)
2887 mHintCharsetSource
= aHintCharacterSetSource
;
2888 // now set the hint char set source on all children of mContainer
2889 CallChildren(SetChildHintCharacterSetSource
,
2890 (void*) aHintCharacterSetSource
);
2895 SetChildHintCharacterSet(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2897 const nsACString
* charset
= static_cast<nsACString
*>(aClosure
);
2898 aChild
->SetHintCharacterSet(*charset
);
2902 DocumentViewerImpl::SetHintCharacterSet(const nsACString
& aHintCharacterSet
)
2904 mHintCharset
= aHintCharacterSet
;
2905 // now set the hint char set on all children of mContainer
2906 CallChildren(SetChildHintCharacterSet
, (void*) &aHintCharacterSet
);
2911 SetChildBidiOptions(nsIMarkupDocumentViewer
* aChild
, void* aClosure
)
2913 aChild
->SetBidiOptions(NS_PTR_TO_INT32(aClosure
));
2916 NS_IMETHODIMP
DocumentViewerImpl::SetBidiTextDirection(PRUint8 aTextDirection
)
2918 PRUint32 bidiOptions
;
2920 GetBidiOptions(&bidiOptions
);
2921 SET_BIDI_OPTION_DIRECTION(bidiOptions
, aTextDirection
);
2922 SetBidiOptions(bidiOptions
);
2926 NS_IMETHODIMP
DocumentViewerImpl::GetBidiTextDirection(PRUint8
* aTextDirection
)
2928 PRUint32 bidiOptions
;
2930 if (aTextDirection
) {
2931 GetBidiOptions(&bidiOptions
);
2932 *aTextDirection
= GET_BIDI_OPTION_DIRECTION(bidiOptions
);
2937 NS_IMETHODIMP
DocumentViewerImpl::SetBidiTextType(PRUint8 aTextType
)
2939 PRUint32 bidiOptions
;
2941 GetBidiOptions(&bidiOptions
);
2942 SET_BIDI_OPTION_TEXTTYPE(bidiOptions
, aTextType
);
2943 SetBidiOptions(bidiOptions
);
2947 NS_IMETHODIMP
DocumentViewerImpl::GetBidiTextType(PRUint8
* aTextType
)
2949 PRUint32 bidiOptions
;
2952 GetBidiOptions(&bidiOptions
);
2953 *aTextType
= GET_BIDI_OPTION_TEXTTYPE(bidiOptions
);
2958 NS_IMETHODIMP
DocumentViewerImpl::SetBidiControlsTextMode(PRUint8 aControlsTextMode
)
2960 PRUint32 bidiOptions
;
2962 GetBidiOptions(&bidiOptions
);
2963 SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
, aControlsTextMode
);
2964 SetBidiOptions(bidiOptions
);
2968 NS_IMETHODIMP
DocumentViewerImpl::GetBidiControlsTextMode(PRUint8
* aControlsTextMode
)
2970 PRUint32 bidiOptions
;
2972 if (aControlsTextMode
) {
2973 GetBidiOptions(&bidiOptions
);
2974 *aControlsTextMode
= GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
);
2979 NS_IMETHODIMP
DocumentViewerImpl::SetBidiNumeral(PRUint8 aNumeral
)
2981 PRUint32 bidiOptions
;
2983 GetBidiOptions(&bidiOptions
);
2984 SET_BIDI_OPTION_NUMERAL(bidiOptions
, aNumeral
);
2985 SetBidiOptions(bidiOptions
);
2989 NS_IMETHODIMP
DocumentViewerImpl::GetBidiNumeral(PRUint8
* aNumeral
)
2991 PRUint32 bidiOptions
;
2994 GetBidiOptions(&bidiOptions
);
2995 *aNumeral
= GET_BIDI_OPTION_NUMERAL(bidiOptions
);
3000 NS_IMETHODIMP
DocumentViewerImpl::SetBidiSupport(PRUint8 aSupport
)
3002 PRUint32 bidiOptions
;
3004 GetBidiOptions(&bidiOptions
);
3005 SET_BIDI_OPTION_SUPPORT(bidiOptions
, aSupport
);
3006 SetBidiOptions(bidiOptions
);
3010 NS_IMETHODIMP
DocumentViewerImpl::GetBidiSupport(PRUint8
* aSupport
)
3012 PRUint32 bidiOptions
;
3015 GetBidiOptions(&bidiOptions
);
3016 *aSupport
= GET_BIDI_OPTION_SUPPORT(bidiOptions
);
3021 NS_IMETHODIMP
DocumentViewerImpl::SetBidiCharacterSet(PRUint8 aCharacterSet
)
3023 PRUint32 bidiOptions
;
3025 GetBidiOptions(&bidiOptions
);
3026 SET_BIDI_OPTION_CHARACTERSET(bidiOptions
, aCharacterSet
);
3027 SetBidiOptions(bidiOptions
);
3031 NS_IMETHODIMP
DocumentViewerImpl::GetBidiCharacterSet(PRUint8
* aCharacterSet
)
3033 PRUint32 bidiOptions
;
3035 if (aCharacterSet
) {
3036 GetBidiOptions(&bidiOptions
);
3037 *aCharacterSet
= GET_BIDI_OPTION_CHARACTERSET(bidiOptions
);
3042 NS_IMETHODIMP
DocumentViewerImpl::SetBidiOptions(PRUint32 aBidiOptions
)
3045 mPresContext
->SetBidi(aBidiOptions
, PR_TRUE
); // could cause reflow
3047 // now set bidi on all children of mContainer
3048 CallChildren(SetChildBidiOptions
, (void*) aBidiOptions
);
3052 NS_IMETHODIMP
DocumentViewerImpl::GetBidiOptions(PRUint32
* aBidiOptions
)
3056 *aBidiOptions
= mPresContext
->GetBidi();
3059 *aBidiOptions
= IBMBIDI_DEFAULT_BIDI_OPTIONS
;
3064 NS_IMETHODIMP
DocumentViewerImpl::SizeToContent()
3066 NS_ENSURE_TRUE(mDocument
, NS_ERROR_NOT_AVAILABLE
);
3068 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryReferent(mContainer
));
3069 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
3071 nsCOMPtr
<nsIDocShellTreeItem
> docShellParent
;
3072 docShellAsItem
->GetSameTypeParent(getter_AddRefs(docShellParent
));
3074 // It's only valid to access this from a top frame. Doesn't work from
3076 NS_ENSURE_TRUE(!docShellParent
, NS_ERROR_FAILURE
);
3078 nsCOMPtr
<nsIPresShell
> presShell
;
3079 GetPresShell(getter_AddRefs(presShell
));
3080 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
3082 // Flush out all content and style updates. We can't use a resize reflow
3083 // because it won't change some sizes that a style change reflow will.
3084 mDocument
->FlushPendingNotifications(Flush_Layout
);
3086 nsIFrame
*root
= presShell
->GetRootFrame();
3087 NS_ENSURE_TRUE(root
, NS_ERROR_FAILURE
);
3091 nsCOMPtr
<nsIRenderingContext
> rcx
;
3092 presShell
->CreateRenderingContext(root
, getter_AddRefs(rcx
));
3093 NS_ENSURE_TRUE(rcx
, NS_ERROR_FAILURE
);
3094 prefWidth
= root
->GetPrefWidth(rcx
);
3097 nsresult rv
= presShell
->ResizeReflow(prefWidth
, NS_UNCONSTRAINEDSIZE
);
3098 NS_ENSURE_SUCCESS(rv
, rv
);
3100 nsCOMPtr
<nsPresContext
> presContext
;
3101 GetPresContext(getter_AddRefs(presContext
));
3102 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
3104 PRInt32 width
, height
;
3106 // so how big is it?
3107 nsRect shellArea
= presContext
->GetVisibleArea();
3108 // Protect against bogus returns here
3109 NS_ENSURE_TRUE(shellArea
.width
!= NS_UNCONSTRAINEDSIZE
&&
3110 shellArea
.height
!= NS_UNCONSTRAINEDSIZE
,
3112 width
= presContext
->AppUnitsToDevPixels(shellArea
.width
);
3113 height
= presContext
->AppUnitsToDevPixels(shellArea
.height
);
3115 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3116 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3117 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3119 /* presContext's size was calculated in app units and has already been
3120 rounded to the equivalent pixels (so the width/height calculation
3121 we just performed was probably exact, though it was based on
3122 values already rounded during ResizeReflow). In a surprising
3123 number of instances, this rounding makes a window which for want
3124 of one extra pixel's width ends up wrapping the longest line of
3125 text during actual window layout. This makes the window too short,
3126 generally clipping the OK/Cancel buttons. Here we add one pixel
3127 to the calculated width, to circumvent this problem. */
3128 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
+1, height
),
3135 NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener
, nsISelectionListener
)
3137 nsresult
nsDocViewerSelectionListener::Init(DocumentViewerImpl
*aDocViewer
)
3139 mDocViewer
= aDocViewer
;
3144 * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
3145 * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
3146 * of commands. The focus controller stores the popup node, these retrieve
3147 * them and munge appropriately. Note that we have to store the popup node
3148 * rather than retrieving it from EventStateManager::GetFocusedContent because
3149 * not all content (images included) can receive focus.
3153 DocumentViewerImpl::GetPopupNode(nsIDOMNode
** aNode
)
3155 NS_ENSURE_ARG_POINTER(aNode
);
3160 nsCOMPtr
<nsIDocument
> document
;
3161 rv
= GetDocument(getter_AddRefs(document
));
3162 NS_ENSURE_SUCCESS(rv
, rv
);
3163 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
3166 // get the private dom window
3167 nsPIDOMWindow
*privateWin
= document
->GetWindow();
3168 NS_ENSURE_TRUE(privateWin
, NS_ERROR_NOT_AVAILABLE
);
3170 // get the focus controller
3171 nsIFocusController
*focusController
= privateWin
->GetRootFocusController();
3172 NS_ENSURE_TRUE(focusController
, NS_ERROR_FAILURE
);
3174 // get the popup node
3175 focusController
->GetPopupNode(aNode
); // addref happens here
3180 // GetPopupLinkNode: return popup link node or fail
3182 DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode
** aNode
)
3184 NS_ENSURE_ARG_POINTER(aNode
);
3186 // you get null unless i say so
3190 nsCOMPtr
<nsIDOMNode
> node
;
3191 nsresult rv
= GetPopupNode(getter_AddRefs(node
));
3192 NS_ENSURE_SUCCESS(rv
, rv
);
3194 // find out if we have a link in our ancestry
3197 // are we an anchor?
3198 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor(do_QueryInterface(node
));
3199 nsCOMPtr
<nsIDOMHTMLAreaElement
> area
;
3200 nsCOMPtr
<nsIDOMHTMLLinkElement
> link
;
3201 nsAutoString xlinkType
;
3204 area
= do_QueryInterface(node
);
3207 link
= do_QueryInterface(node
);
3210 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(node
));
3212 element
->GetAttributeNS(NS_LITERAL_STRING("http://www.w3.org/1999/xlink"),NS_LITERAL_STRING("type"),xlinkType
);
3217 if (anchor
|| area
|| link
|| xlinkType
.EqualsLiteral("simple")) {
3219 NS_IF_ADDREF(*aNode
); // addref
3223 // if not, get our parent and keep trying...
3224 nsCOMPtr
<nsIDOMNode
> parentNode
;
3225 node
->GetParentNode(getter_AddRefs(parentNode
));
3230 // if we have no node, fail
3231 return NS_ERROR_FAILURE
;
3234 // GetPopupLinkNode: return popup image node or fail
3236 DocumentViewerImpl::GetPopupImageNode(nsIImageLoadingContent
** aNode
)
3238 NS_ENSURE_ARG_POINTER(aNode
);
3240 // you get null unless i say so
3244 nsCOMPtr
<nsIDOMNode
> node
;
3245 nsresult rv
= GetPopupNode(getter_AddRefs(node
));
3246 NS_ENSURE_SUCCESS(rv
, rv
);
3249 CallQueryInterface(node
, aNode
);
3257 * These two functions -- GetInLink and GetInImage -- are kind of annoying
3258 * in that they only get called from the controller (in
3259 * nsDOMWindowController::IsCommandEnabled). The actual construction of the
3260 * context menus in communicator (nsContextMenu.js) has its own, redundant
3261 * tests. No big deal, but good to keep in mind if we ever clean context
3265 NS_IMETHODIMP
DocumentViewerImpl::GetInLink(PRBool
* aInLink
)
3268 printf("dr :: DocumentViewerImpl::GetInLink\n");
3271 NS_ENSURE_ARG_POINTER(aInLink
);
3273 // we're not in a link unless i say so
3274 *aInLink
= PR_FALSE
;
3276 // get the popup link
3277 nsCOMPtr
<nsIDOMNode
> node
;
3278 nsresult rv
= GetPopupLinkNode(getter_AddRefs(node
));
3279 if (NS_FAILED(rv
)) return rv
;
3280 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
3282 // if we made it here, we're in a link
3287 NS_IMETHODIMP
DocumentViewerImpl::GetInImage(PRBool
* aInImage
)
3290 printf("dr :: DocumentViewerImpl::GetInImage\n");
3293 NS_ENSURE_ARG_POINTER(aInImage
);
3295 // we're not in an image unless i say so
3296 *aInImage
= PR_FALSE
;
3298 // get the popup image
3299 nsCOMPtr
<nsIImageLoadingContent
> node
;
3300 nsresult rv
= GetPopupImageNode(getter_AddRefs(node
));
3301 if (NS_FAILED(rv
)) return rv
;
3302 NS_ENSURE_TRUE(node
, NS_ERROR_FAILURE
);
3304 // if we made it here, we're in an image
3305 *aInImage
= PR_TRUE
;
3309 NS_IMETHODIMP
nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument
*, nsISelection
*, PRInt16
)
3311 NS_ASSERTION(mDocViewer
, "Should have doc viewer!");
3313 // get the selection state
3314 nsCOMPtr
<nsISelection
> selection
;
3315 nsresult rv
= mDocViewer
->GetDocumentSelection(getter_AddRefs(selection
));
3316 if (NS_FAILED(rv
)) return rv
;
3318 PRBool selectionCollapsed
;
3319 selection
->GetIsCollapsed(&selectionCollapsed
);
3320 // we only call UpdateCommands when the selection changes from collapsed
3321 // to non-collapsed or vice versa. We might need another update string
3322 // for simple selection changes, but that would be expenseive.
3323 if (!mGotSelectionState
|| mSelectionWasCollapsed
!= selectionCollapsed
)
3325 nsCOMPtr
<nsIDocument
> theDoc
;
3326 mDocViewer
->GetDocument(getter_AddRefs(theDoc
));
3327 if (!theDoc
) return NS_ERROR_FAILURE
;
3329 nsPIDOMWindow
*domWindow
= theDoc
->GetWindow();
3330 if (!domWindow
) return NS_ERROR_FAILURE
;
3332 domWindow
->UpdateCommands(NS_LITERAL_STRING("select"));
3333 mGotSelectionState
= PR_TRUE
;
3334 mSelectionWasCollapsed
= selectionCollapsed
;
3340 //nsDocViewerFocusListener
3341 NS_IMPL_ISUPPORTS2(nsDocViewerFocusListener
,
3342 nsIDOMFocusListener
,
3343 nsIDOMEventListener
)
3345 nsDocViewerFocusListener::nsDocViewerFocusListener()
3350 nsDocViewerFocusListener::~nsDocViewerFocusListener(){}
3353 nsDocViewerFocusListener::HandleEvent(nsIDOMEvent
* aEvent
)
3359 nsDocViewerFocusListener::Focus(nsIDOMEvent
* aEvent
)
3361 nsCOMPtr
<nsIPresShell
> shell
;
3363 return NS_ERROR_FAILURE
;
3365 nsresult result
= mDocViewer
->GetPresShell(getter_AddRefs(shell
));
3366 if(NS_FAILED(result
) || !shell
)
3367 return result
?result
:NS_ERROR_FAILURE
;
3368 nsCOMPtr
<nsISelectionController
> selCon
;
3369 selCon
= do_QueryInterface(shell
);
3370 PRInt16 selectionStatus
;
3371 selCon
->GetDisplaySelection(&selectionStatus
);
3373 // If selection was disabled, re-enable it.
3374 if(selectionStatus
== nsISelectionController::SELECTION_DISABLED
||
3375 selectionStatus
== nsISelectionController::SELECTION_HIDDEN
)
3377 selCon
->SetDisplaySelection(nsISelectionController::SELECTION_ON
);
3378 selCon
->RepaintSelection(nsISelectionController::SELECTION_NORMAL
);
3384 nsDocViewerFocusListener::Blur(nsIDOMEvent
* aEvent
)
3386 nsCOMPtr
<nsIPresShell
> shell
;
3388 return NS_ERROR_FAILURE
;
3390 nsresult result
= mDocViewer
->GetPresShell(getter_AddRefs(shell
));
3391 if(NS_FAILED(result
) || !shell
)
3392 return result
?result
:NS_ERROR_FAILURE
;
3393 nsCOMPtr
<nsISelectionController
> selCon
;
3394 selCon
= do_QueryInterface(shell
);
3395 PRInt16 selectionStatus
;
3396 selCon
->GetDisplaySelection(&selectionStatus
);
3398 // If selection was on, disable it.
3399 if(selectionStatus
== nsISelectionController::SELECTION_ON
||
3400 selectionStatus
== nsISelectionController::SELECTION_ATTENTION
)
3402 selCon
->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED
);
3403 selCon
->RepaintSelection(nsISelectionController::SELECTION_NORMAL
);
3410 nsDocViewerFocusListener::Init(DocumentViewerImpl
*aDocViewer
)
3412 mDocViewer
= aDocViewer
;
3416 /** ---------------------------------------------------
3417 * From nsIWebBrowserPrint
3423 DocumentViewerImpl::Print(nsIPrintSettings
* aPrintSettings
,
3424 nsIWebProgressListener
* aWebProgressListener
)
3428 // Temporary code for Bug 136185 / Bug 240490
3429 nsCOMPtr
<nsIXULDocument
> xulDoc(do_QueryInterface(mDocument
));
3431 nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL
);
3432 return NS_ERROR_FAILURE
;
3437 PR_PL(("Container was destroyed yet we are still trying to use it!"));
3438 return NS_ERROR_FAILURE
;
3441 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
3442 NS_ASSERTION(docShell
, "This has to be a docshell");
3444 // Check to see if this document is still busy
3445 // If it is busy and we aren't already "queued" up to print then
3446 // Indicate there is a print pending and cache the args for later
3447 PRUint32 busyFlags
= nsIDocShell::BUSY_FLAGS_NONE
;
3448 if ((NS_FAILED(docShell
->GetBusyFlags(&busyFlags
)) ||
3449 (busyFlags
!= nsIDocShell::BUSY_FLAGS_NONE
&& busyFlags
& nsIDocShell::BUSY_FLAGS_PAGE_LOADING
)) &&
3450 !mPrintDocIsFullyLoaded
) {
3451 if (!mPrintIsPending
) {
3452 mCachedPrintSettings
= aPrintSettings
;
3453 mCachedPrintWebProgressListner
= aWebProgressListener
;
3454 mPrintIsPending
= PR_TRUE
;
3456 PR_PL(("Printing Stopped - document is still busy!"));
3457 return NS_ERROR_GFX_PRINTER_DOC_IS_BUSY
;
3460 nsCOMPtr
<nsIPresShell
> presShell
;
3461 docShell
->GetPresShell(getter_AddRefs(presShell
));
3462 if (!presShell
|| !mDocument
|| !mDeviceContext
|| !mParentWidget
) {
3463 PR_PL(("Can't Print without pres shell, document etc"));
3464 return NS_ERROR_FAILURE
;
3469 // if we are printing another URL, then exit
3470 // the reason we check here is because this method can be called while
3471 // another is still in here (the printing dialog is a good example).
3472 // the only time we can print more than one job at a time is the regression tests
3473 if (GetIsPrinting()) {
3474 // Let the user know we are not ready to print.
3475 rv
= NS_ERROR_NOT_AVAILABLE
;
3476 nsPrintEngine::ShowPrintErrorDialog(rv
);
3480 // If we are hosting a full-page plugin, tell it to print
3481 // first. It shows its own native print UI.
3482 nsCOMPtr
<nsIPluginDocument
> pDoc(do_QueryInterface(mDocument
));
3484 return pDoc
->Print();
3486 if (!mPrintEngine
) {
3487 mPrintEngine
= new nsPrintEngine();
3488 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_OUT_OF_MEMORY
);
3490 rv
= mPrintEngine
->Initialize(this, docShell
, mDocument
,
3491 mDeviceContext
, mParentWidget
,
3498 if (NS_FAILED(rv
)) {
3499 mPrintEngine
->Destroy();
3500 mPrintEngine
= nsnull
;
3505 rv
= mPrintEngine
->Print(aPrintSettings
, aWebProgressListener
);
3506 if (NS_FAILED(rv
)) {
3513 DocumentViewerImpl::PrintPreview(nsIPrintSettings
* aPrintSettings
,
3514 nsIDOMWindow
*aChildDOMWin
,
3515 nsIWebProgressListener
* aWebProgressListener
)
3517 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
3518 nsresult rv
= NS_OK
;
3520 if (GetIsPrinting()) {
3521 nsPrintEngine::CloseProgressDialog(aWebProgressListener
);
3522 return NS_ERROR_FAILURE
;
3526 // Temporary code for Bug 136185 / Bug 240490
3527 nsCOMPtr
<nsIXULDocument
> xulDoc(do_QueryInterface(mDocument
));
3529 nsPrintEngine::CloseProgressDialog(aWebProgressListener
);
3530 nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL
, PR_FALSE
);
3531 return NS_ERROR_FAILURE
;
3536 PR_PL(("Container was destroyed yet we are still trying to use it!"));
3537 return NS_ERROR_FAILURE
;
3540 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
3541 NS_ASSERTION(docShell
, "This has to be a docshell");
3542 nsCOMPtr
<nsIPresShell
> presShell
;
3543 docShell
->GetPresShell(getter_AddRefs(presShell
));
3544 if (!presShell
|| !mDocument
|| !mDeviceContext
|| !mParentWidget
) {
3545 PR_PL(("Can't Print Preview without pres shell, document etc"));
3546 return NS_ERROR_FAILURE
;
3549 if (!mPrintEngine
) {
3550 mPrintEngine
= new nsPrintEngine();
3551 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_OUT_OF_MEMORY
);
3553 rv
= mPrintEngine
->Initialize(this, docShell
, mDocument
,
3554 mDeviceContext
, mParentWidget
,
3561 if (NS_FAILED(rv
)) {
3562 mPrintEngine
->Destroy();
3563 mPrintEngine
= nsnull
;
3568 rv
= mPrintEngine
->PrintPreview(aPrintSettings
, aChildDOMWin
, aWebProgressListener
);
3569 if (NS_FAILED(rv
)) {
3574 return NS_ERROR_FAILURE
;
3578 //----------------------------------------------------------------------
3580 DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType
, PRInt32 aPageNum
)
3582 if (!GetIsPrintPreview() ||
3583 mPrintEngine
->GetIsCreatingPrintPreview())
3584 return NS_ERROR_FAILURE
;
3586 nsIScrollableView
* scrollableView
= nsnull
;
3587 mPrintEngine
->GetPrintPreviewViewManager()->GetRootScrollableView(&scrollableView
);
3588 if (scrollableView
== nsnull
)
3591 // Check to see if we can short circut scrolling to the top
3592 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_HOME
||
3593 (aType
== nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM
&& aPageNum
== 1)) {
3594 scrollableView
->ScrollTo(0, 0, PR_TRUE
);
3598 // Finds the SimplePageSequencer frame
3599 // in PP mPrtPreview->mPrintObject->mSeqFrame is null
3600 nsIFrame
* seqFrame
= nsnull
;
3601 PRInt32 pageCount
= 0;
3602 if (NS_FAILED(mPrintEngine
->GetSeqFrameAndCountPages(seqFrame
, pageCount
))) {
3603 return NS_ERROR_FAILURE
;
3606 // Figure where we are currently scrolled to
3609 scrollableView
->GetScrollPosition(x
, y
);
3611 PRInt32 pageNum
= 1;
3612 nsIFrame
* fndPageFrame
= nsnull
;
3613 nsIFrame
* currentPage
= nsnull
;
3615 // If it is "End" then just do a "goto" to the last page
3616 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_END
) {
3617 aType
= nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM
;
3618 aPageNum
= pageCount
;
3621 // Now, locate the current page we are on and
3622 // and the page of the page number
3624 nsIFrame
* pageFrame
= seqFrame
->GetFirstChild(nsnull
);
3625 while (pageFrame
!= nsnull
) {
3626 nsRect pageRect
= pageFrame
->GetRect();
3630 if (pageRect
.Contains(pageRect
.x
, y
)) {
3631 currentPage
= pageFrame
;
3633 if (pageNum
== aPageNum
) {
3634 fndPageFrame
= pageFrame
;
3638 pageFrame
= pageFrame
->GetNextSibling();
3641 if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE
) {
3643 fndPageFrame
= currentPage
->GetPrevInFlow();
3644 if (!fndPageFrame
) {
3650 } else if (aType
== nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE
) {
3652 fndPageFrame
= currentPage
->GetNextInFlow();
3653 if (!fndPageFrame
) {
3659 } else { // If we get here we are doing "GoTo"
3660 if (aPageNum
< 0 || aPageNum
> pageCount
) {
3665 if (fndPageFrame
&& scrollableView
) {
3666 nscoord deadSpaceGapTwips
= 0;
3667 nsIPageSequenceFrame
* sqf
;
3668 if (NS_SUCCEEDED(CallQueryInterface(seqFrame
, &sqf
))) {
3669 sqf
->GetDeadSpaceValue(&deadSpaceGapTwips
);
3672 // To compute deadSpaceGap, use the same presContext as was used
3673 // to layout the seqFrame. (That presContext may have different
3674 // TwipsToAppUnits conversion from this->mPresContext)
3675 nscoord deadSpaceGap
=
3676 seqFrame
->PresContext()->TwipsToAppUnits(deadSpaceGapTwips
);
3679 nscoord(mPrintEngine
->GetPrintPreviewScale() *
3680 float(fndPageFrame
->GetPosition().y
- deadSpaceGap
));
3681 scrollableView
->ScrollTo(0, newYPosn
, PR_TRUE
);
3687 /* readonly attribute nsIPrintSettings globalPrintSettings; */
3689 DocumentViewerImpl::GetGlobalPrintSettings(nsIPrintSettings
* *aGlobalPrintSettings
)
3691 return nsPrintEngine::GetGlobalPrintSettings(aGlobalPrintSettings
);
3694 /* readonly attribute boolean doingPrint; */
3695 // XXX This always returns PR_FALSE for subdocuments
3697 DocumentViewerImpl::GetDoingPrint(PRBool
*aDoingPrint
)
3699 NS_ENSURE_ARG_POINTER(aDoingPrint
);
3701 *aDoingPrint
= PR_FALSE
;
3703 // XXX shouldn't this be GetDoingPrint() ?
3704 return mPrintEngine
->GetDoingPrintPreview(aDoingPrint
);
3709 /* readonly attribute boolean doingPrintPreview; */
3710 // XXX This always returns PR_FALSE for subdocuments
3712 DocumentViewerImpl::GetDoingPrintPreview(PRBool
*aDoingPrintPreview
)
3714 NS_ENSURE_ARG_POINTER(aDoingPrintPreview
);
3716 *aDoingPrintPreview
= PR_FALSE
;
3718 return mPrintEngine
->GetDoingPrintPreview(aDoingPrintPreview
);
3723 /* readonly attribute nsIPrintSettings currentPrintSettings; */
3725 DocumentViewerImpl::GetCurrentPrintSettings(nsIPrintSettings
* *aCurrentPrintSettings
)
3727 NS_ENSURE_ARG_POINTER(aCurrentPrintSettings
);
3729 *aCurrentPrintSettings
= nsnull
;
3730 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3732 return mPrintEngine
->GetCurrentPrintSettings(aCurrentPrintSettings
);
3736 /* readonly attribute nsIDOMWindow currentChildDOMWindow; */
3738 DocumentViewerImpl::GetCurrentChildDOMWindow(nsIDOMWindow
* *aCurrentChildDOMWindow
)
3740 NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow
);
3741 *aCurrentChildDOMWindow
= nsnull
;
3742 return NS_ERROR_NOT_IMPLEMENTED
;
3745 /* void cancel (); */
3747 DocumentViewerImpl::Cancel()
3749 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3750 return mPrintEngine
->Cancelled();
3753 /* void exitPrintPreview (); */
3755 DocumentViewerImpl::ExitPrintPreview()
3757 if (GetIsPrinting()) return NS_ERROR_FAILURE
;
3758 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3760 if (GetIsPrintPreview()) {
3761 ReturnToGalleyPresentation();
3766 //----------------------------------------------------------------------------------
3767 // Enumerate all the documents for their titles
3769 DocumentViewerImpl::EnumerateDocumentNames(PRUint32
* aCount
,
3770 PRUnichar
*** aResult
)
3773 NS_ENSURE_ARG(aCount
);
3774 NS_ENSURE_ARG_POINTER(aResult
);
3775 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3777 return mPrintEngine
->EnumerateDocumentNames(aCount
, aResult
);
3779 return NS_ERROR_FAILURE
;
3783 /* readonly attribute boolean isFramesetFrameSelected; */
3785 DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool
*aIsFramesetFrameSelected
)
3788 *aIsFramesetFrameSelected
= PR_FALSE
;
3789 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3791 return mPrintEngine
->GetIsFramesetFrameSelected(aIsFramesetFrameSelected
);
3793 return NS_ERROR_FAILURE
;
3797 /* readonly attribute long printPreviewNumPages; */
3799 DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32
*aPrintPreviewNumPages
)
3802 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages
);
3803 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3805 return mPrintEngine
->GetPrintPreviewNumPages(aPrintPreviewNumPages
);
3807 return NS_ERROR_FAILURE
;
3811 /* readonly attribute boolean isFramesetDocument; */
3813 DocumentViewerImpl::GetIsFramesetDocument(PRBool
*aIsFramesetDocument
)
3816 *aIsFramesetDocument
= PR_FALSE
;
3817 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3819 return mPrintEngine
->GetIsFramesetDocument(aIsFramesetDocument
);
3821 return NS_ERROR_FAILURE
;
3825 /* readonly attribute boolean isIFrameSelected; */
3827 DocumentViewerImpl::GetIsIFrameSelected(PRBool
*aIsIFrameSelected
)
3830 *aIsIFrameSelected
= PR_FALSE
;
3831 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3833 return mPrintEngine
->GetIsIFrameSelected(aIsIFrameSelected
);
3835 return NS_ERROR_FAILURE
;
3839 /* readonly attribute boolean isRangeSelection; */
3841 DocumentViewerImpl::GetIsRangeSelection(PRBool
*aIsRangeSelection
)
3844 *aIsRangeSelection
= PR_FALSE
;
3845 NS_ENSURE_TRUE(mPrintEngine
, NS_ERROR_FAILURE
);
3847 return mPrintEngine
->GetIsRangeSelection(aIsRangeSelection
);
3849 return NS_ERROR_FAILURE
;
3853 //----------------------------------------------------------------------------------
3854 // Printing/Print Preview Helpers
3855 //----------------------------------------------------------------------------------
3857 //----------------------------------------------------------------------------------
3858 // Walks the document tree and tells each DocShell whether Printing/PP is happening
3860 DocumentViewerImpl::SetIsPrintingInDocShellTree(nsIDocShellTreeNode
* aParentNode
,
3861 PRBool aIsPrintingOrPP
,
3864 NS_ASSERTION(aParentNode
, "Parent can't be NULL!");
3866 nsCOMPtr
<nsIDocShellTreeItem
> parentItem(do_QueryInterface(aParentNode
));
3868 // find top of "same parent" tree
3870 while (parentItem
) {
3871 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
3872 parentItem
->GetSameTypeParent(getter_AddRefs(parent
));
3876 parentItem
= do_QueryInterface(parent
);
3879 NS_ASSERTION(parentItem
, "parentItem can't be null");
3881 // Check to see if the DocShell's ContentViewer is printing/PP
3882 nsCOMPtr
<nsIContentViewerContainer
> viewerContainer(do_QueryInterface(parentItem
));
3883 if (viewerContainer
) {
3884 viewerContainer
->SetIsPrinting(aIsPrintingOrPP
);
3887 // Traverse children to see if any of them are printing.
3889 aParentNode
->GetChildCount(&n
);
3890 for (PRInt32 i
=0; i
< n
; i
++) {
3891 nsCOMPtr
<nsIDocShellTreeItem
> child
;
3892 aParentNode
->GetChildAt(i
, getter_AddRefs(child
));
3893 nsCOMPtr
<nsIDocShellTreeNode
> childAsNode(do_QueryInterface(child
));
3894 NS_ASSERTION(childAsNode
, "child isn't nsIDocShellTreeNode");
3896 SetIsPrintingInDocShellTree(childAsNode
, aIsPrintingOrPP
, PR_FALSE
);
3901 #endif // NS_PRINTING
3903 //------------------------------------------------------------
3904 // XXX this always returns PR_FALSE for subdocuments
3906 DocumentViewerImpl::GetIsPrinting()
3910 return mPrintEngine
->GetIsPrinting();
3916 //------------------------------------------------------------
3917 // Notification from the PrintEngine of the current Printing status
3919 DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting
)
3922 // Set all the docShells in the docshell tree to be printing.
3923 // that way if anyone of them tries to "navigate" it can't
3925 nsCOMPtr
<nsIDocShellTreeNode
> docShellTreeNode(do_QueryReferent(mContainer
));
3926 NS_ASSERTION(docShellTreeNode
, "mContainer has to be a nsIDocShellTreeNode");
3927 SetIsPrintingInDocShellTree(docShellTreeNode
, aIsPrinting
, PR_TRUE
);
3932 //------------------------------------------------------------
3933 // The PrintEngine holds the current value
3934 // this called from inside the DocViewer.
3935 // XXX it always returns PR_FALSE for subdocuments
3937 DocumentViewerImpl::GetIsPrintPreview()
3941 return mPrintEngine
->GetIsPrintPreview();
3947 //------------------------------------------------------------
3948 // Notification from the PrintEngine of the current PP status
3950 DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview
)
3953 // Set all the docShells in the docshell tree to be printing.
3954 // that way if anyone of them tries to "navigate" it can't
3956 nsCOMPtr
<nsIDocShellTreeNode
> docShellTreeNode(do_QueryReferent(mContainer
));
3957 NS_ASSERTION(docShellTreeNode
, "mContainer has to be a nsIDocShellTreeNode");
3958 SetIsPrintingInDocShellTree(docShellTreeNode
, aIsPrintPreview
, PR_TRUE
);
3963 //----------------------------------------------------------------------------------
3964 // nsIDocumentViewerPrint IFace
3965 //----------------------------------------------------------------------------------
3967 //------------------------------------------------------------
3969 DocumentViewerImpl::IncrementDestroyRefCount()
3974 //------------------------------------------------------------
3976 static void ResetFocusState(nsIDocShell
* aDocShell
);
3979 DocumentViewerImpl::ReturnToGalleyPresentation()
3981 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
3982 if (!GetIsPrintPreview()) {
3983 NS_ERROR("Wow, we should never get here!");
3987 SetIsPrintPreview(PR_FALSE
);
3989 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
3990 mPrintEngine
->Destroy();
3991 mPrintEngine
= nsnull
;
3993 mViewManager
->EnableRefresh(NS_VMREFRESH_DEFERRED
);
3995 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
3996 ResetFocusState(docShell
);
3999 mPresContext
->RestoreImageAnimationMode();
4001 SetTextZoom(mTextZoom
);
4002 SetFullZoom(mPageZoom
);
4005 #endif // NS_PRINTING && NS_PRINT_PREVIEW
4008 //------------------------------------------------------------
4009 // Reset ESM focus for all descendent doc shells.
4011 ResetFocusState(nsIDocShell
* aDocShell
)
4013 nsCOMPtr
<nsISimpleEnumerator
> docShellEnumerator
;
4014 aDocShell
->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent
,
4015 nsIDocShell::ENUMERATE_FORWARDS
,
4016 getter_AddRefs(docShellEnumerator
));
4018 nsCOMPtr
<nsIDocShell
> currentDocShell
;
4019 nsCOMPtr
<nsISupports
> currentContainer
;
4020 PRBool hasMoreDocShells
;
4021 while (NS_SUCCEEDED(docShellEnumerator
->HasMoreElements(&hasMoreDocShells
))
4022 && hasMoreDocShells
) {
4023 docShellEnumerator
->GetNext(getter_AddRefs(currentContainer
));
4024 currentDocShell
= do_QueryInterface(currentContainer
);
4025 if (!currentDocShell
) {
4028 nsCOMPtr
<nsPresContext
> presContext
;
4029 currentDocShell
->GetPresContext(getter_AddRefs(presContext
));
4030 nsIEventStateManager
* esm
=
4031 presContext
? presContext
->EventStateManager() : nsnull
;
4033 esm
->SetContentState(nsnull
, NS_EVENT_STATE_FOCUS
);
4034 esm
->SetFocusedContent(nsnull
);
4039 //------------------------------------------------------------
4040 // This called ONLY when printing has completed and the DV
4041 // is being notified that it should get rid of the PrintEngine.
4043 // BUT, if we are in Print Preview then we want to ignore the
4044 // notification (we do not get rid of the PrintEngine)
4046 // One small caveat:
4047 // This IS called from two places in this module for cleaning
4048 // up when an error occurred during the start up printing
4049 // and print preview
4052 DocumentViewerImpl::OnDonePrinting()
4054 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
4056 if (GetIsPrintPreview()) {
4057 mPrintEngine
->DestroyPrintingData();
4059 mPrintEngine
->Destroy();
4060 mPrintEngine
= nsnull
;
4063 // We are done printing, now cleanup
4064 if (mDeferredWindowClose
) {
4065 mDeferredWindowClose
= PR_FALSE
;
4066 nsCOMPtr
<nsISupports
> container
= do_QueryReferent(mContainer
);
4067 nsCOMPtr
<nsIDOMWindowInternal
> win
= do_GetInterface(container
);
4070 } else if (mClosingWhilePrinting
) {
4072 mDocument
->SetScriptGlobalObject(nsnull
);
4073 mDocument
->Destroy();
4076 mClosingWhilePrinting
= PR_FALSE
;
4080 mPresContext
->RestoreImageAnimationMode();
4082 #endif // NS_PRINTING && NS_PRINT_PREVIEW
4085 NS_IMETHODIMP
DocumentViewerImpl::SetPageMode(PRBool aPageMode
, nsIPrintSettings
* aPrintSettings
)
4087 // XXX Page mode is only partially working; it's currently used for
4088 // reftests that require a paginated context
4089 mIsPageMode
= aPageMode
;
4090 // Get the current size of what is being viewed
4092 mWindow
->GetBounds(bounds
);
4095 // Break circular reference (or something)
4096 mPresShell
->EndObservingDocument();
4097 nsCOMPtr
<nsISelection
> selection
;
4098 nsresult rv
= GetDocumentSelection(getter_AddRefs(selection
));
4099 nsCOMPtr
<nsISelectionPrivate
> selPrivate(do_QueryInterface(selection
));
4100 if (NS_SUCCEEDED(rv
) && selPrivate
&& mSelectionListener
)
4101 selPrivate
->RemoveSelectionListener(mSelectionListener
);
4102 mPresShell
->Destroy();
4106 mPresContext
->SetContainer(nsnull
);
4107 mPresContext
->SetLinkHandler(nsnull
);
4110 mPresShell
= nsnull
;
4111 mPresContext
= nsnull
;
4112 mViewManager
= nsnull
;
4115 NS_ENSURE_STATE(mDocument
);
4119 new nsPresContext(mDocument
, nsPresContext::eContext_PageLayout
);
4120 NS_ENSURE_TRUE(mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
4121 mPresContext
->SetPaginatedScrolling(PR_TRUE
);
4122 mPresContext
->SetPrintSettings(aPrintSettings
);
4123 nsresult rv
= mPresContext
->Init(mDeviceContext
);
4124 NS_ENSURE_SUCCESS(rv
, rv
);
4126 InitInternal(mParentWidget
, nsnull
, bounds
, PR_TRUE
, PR_FALSE
, PR_FALSE
);
4127 mViewManager
->EnableRefresh(NS_VMREFRESH_NO_SYNC
);
4134 DocumentViewerImpl::GetHistoryEntry(nsISHEntry
**aHistoryEntry
)
4136 NS_IF_ADDREF(*aHistoryEntry
= mSHEntry
);