1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/nsDocumentViewer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4412 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* container for a document and its presentation */ 1.11 + 1.12 +#include "nscore.h" 1.13 +#include "nsCOMPtr.h" 1.14 +#include "nsCRT.h" 1.15 +#include "nsString.h" 1.16 +#include "nsReadableUtils.h" 1.17 +#include "nsIContent.h" 1.18 +#include "nsIContentViewerContainer.h" 1.19 +#include "nsIContentViewer.h" 1.20 +#include "nsIDocumentViewerPrint.h" 1.21 +#include "nsIDOMBeforeUnloadEvent.h" 1.22 +#include "nsIDocument.h" 1.23 +#include "nsIDOMWindowUtils.h" 1.24 +#include "nsPresContext.h" 1.25 +#include "nsIPresShell.h" 1.26 +#include "nsStyleSet.h" 1.27 +#include "nsCSSStyleSheet.h" 1.28 +#include "nsIFrame.h" 1.29 +#include "nsIWritablePropertyBag2.h" 1.30 +#include "nsSubDocumentFrame.h" 1.31 + 1.32 +#include "nsILinkHandler.h" 1.33 +#include "nsIDOMDocument.h" 1.34 +#include "nsISelectionListener.h" 1.35 +#include "nsISelectionPrivate.h" 1.36 +#include "nsIDOMHTMLDocument.h" 1.37 +#include "nsIDOMHTMLElement.h" 1.38 +#include "nsContentUtils.h" 1.39 +#include "nsLayoutStylesheetCache.h" 1.40 +#ifdef ACCESSIBILITY 1.41 +#include "mozilla/a11y/DocAccessible.h" 1.42 +#endif 1.43 +#include "mozilla/BasicEvents.h" 1.44 +#include "mozilla/Preferences.h" 1.45 +#include "mozilla/dom/EncodingUtils.h" 1.46 +#include "mozilla/WeakPtr.h" 1.47 + 1.48 +#include "nsViewManager.h" 1.49 +#include "nsView.h" 1.50 + 1.51 +#include "nsIPageSequenceFrame.h" 1.52 +#include "nsNetUtil.h" 1.53 +#include "nsIContentViewerEdit.h" 1.54 +#include "nsIContentViewerFile.h" 1.55 +#include "mozilla/css/Loader.h" 1.56 +#include "nsIMarkupDocumentViewer.h" 1.57 +#include "nsIInterfaceRequestor.h" 1.58 +#include "nsIInterfaceRequestorUtils.h" 1.59 +#include "nsDocShell.h" 1.60 +#include "nsIBaseWindow.h" 1.61 +#include "nsILayoutHistoryState.h" 1.62 +#include "nsCharsetSource.h" 1.63 +#include "nsHTMLReflowState.h" 1.64 +#include "nsIImageLoadingContent.h" 1.65 +#include "nsCopySupport.h" 1.66 +#include "nsIDOMHTMLFrameSetElement.h" 1.67 +#ifdef MOZ_XUL 1.68 +#include "nsIXULDocument.h" 1.69 +#include "nsXULPopupManager.h" 1.70 +#endif 1.71 + 1.72 +#include "nsIClipboardHelper.h" 1.73 + 1.74 +#include "nsPIDOMWindow.h" 1.75 +#include "nsDOMNavigationTiming.h" 1.76 +#include "nsPIWindowRoot.h" 1.77 +#include "nsJSEnvironment.h" 1.78 +#include "nsFocusManager.h" 1.79 + 1.80 +#include "nsIScrollableFrame.h" 1.81 +#include "nsStyleSheetService.h" 1.82 +#include "nsRenderingContext.h" 1.83 +#include "nsILoadContext.h" 1.84 + 1.85 +#include "nsIPrompt.h" 1.86 +#include "imgIContainer.h" // image animation mode constants 1.87 + 1.88 +//-------------------------- 1.89 +// Printing Include 1.90 +//--------------------------- 1.91 +#ifdef NS_PRINTING 1.92 + 1.93 +#include "nsIWebBrowserPrint.h" 1.94 + 1.95 +#include "nsPrintEngine.h" 1.96 + 1.97 +// Print Options 1.98 +#include "nsIPrintSettings.h" 1.99 +#include "nsIPrintOptions.h" 1.100 +#include "nsISimpleEnumerator.h" 1.101 + 1.102 +#ifdef DEBUG 1.103 +// PrintOptions is now implemented by PrintSettingsService 1.104 +static const char sPrintOptionsContractID[] = 1.105 + "@mozilla.org/gfx/printsettings-service;1"; 1.106 +#endif // DEBUG 1.107 + 1.108 +#include "nsIPluginDocument.h" 1.109 + 1.110 +#endif // NS_PRINTING 1.111 + 1.112 +//focus 1.113 +#include "nsIDOMEventTarget.h" 1.114 +#include "nsIDOMEventListener.h" 1.115 +#include "nsISelectionController.h" 1.116 + 1.117 +#include "mozilla/EventDispatcher.h" 1.118 +#include "nsISHEntry.h" 1.119 +#include "nsISHistory.h" 1.120 +#include "nsISHistoryInternal.h" 1.121 +#include "nsIWebNavigation.h" 1.122 +#include "nsXMLHttpRequest.h" 1.123 + 1.124 +//paint forcing 1.125 +#include <stdio.h> 1.126 + 1.127 +#include "mozilla/dom/Element.h" 1.128 + 1.129 +using namespace mozilla; 1.130 +using namespace mozilla::dom; 1.131 + 1.132 +#define BEFOREUNLOAD_DISABLED_PREFNAME "dom.disable_beforeunload" 1.133 + 1.134 +//----------------------------------------------------- 1.135 +// PR LOGGING 1.136 +#ifdef MOZ_LOGGING 1.137 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.138 +#endif 1.139 + 1.140 +#include "prlog.h" 1.141 + 1.142 +#ifdef PR_LOGGING 1.143 + 1.144 +#ifdef NS_PRINTING 1.145 +static PRLogModuleInfo * 1.146 +GetPrintingLog() 1.147 +{ 1.148 + static PRLogModuleInfo *sLog; 1.149 + if (!sLog) 1.150 + sLog = PR_NewLogModule("printing"); 1.151 + return sLog; 1.152 +} 1.153 +#define PR_PL(_p1) PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1); 1.154 +#endif // NS_PRINTING 1.155 + 1.156 +#define PRT_YESNO(_p) ((_p)?"YES":"NO") 1.157 +#else 1.158 +#define PRT_YESNO(_p) 1.159 +#define PR_PL(_p1) 1.160 +#endif 1.161 +//----------------------------------------------------- 1.162 + 1.163 +class nsDocumentViewer; 1.164 +class nsPrintEventDispatcher; 1.165 + 1.166 +// a small delegate class used to avoid circular references 1.167 + 1.168 +class nsDocViewerSelectionListener : public nsISelectionListener 1.169 +{ 1.170 +public: 1.171 + 1.172 + // nsISupports interface... 1.173 + NS_DECL_ISUPPORTS 1.174 + 1.175 + // nsISelectionListerner interface 1.176 + NS_DECL_NSISELECTIONLISTENER 1.177 + 1.178 + nsDocViewerSelectionListener() 1.179 + : mDocViewer(nullptr) 1.180 + , mGotSelectionState(false) 1.181 + , mSelectionWasCollapsed(false) 1.182 + { 1.183 + } 1.184 + 1.185 + virtual ~nsDocViewerSelectionListener() {} 1.186 + 1.187 + nsresult Init(nsDocumentViewer *aDocViewer); 1.188 + 1.189 +protected: 1.190 + 1.191 + nsDocumentViewer* mDocViewer; 1.192 + bool mGotSelectionState; 1.193 + bool mSelectionWasCollapsed; 1.194 + 1.195 +}; 1.196 + 1.197 + 1.198 +/** editor Implementation of the FocusListener interface 1.199 + */ 1.200 +class nsDocViewerFocusListener : public nsIDOMEventListener 1.201 +{ 1.202 +public: 1.203 + /** default constructor 1.204 + */ 1.205 + nsDocViewerFocusListener(); 1.206 + /** default destructor 1.207 + */ 1.208 + virtual ~nsDocViewerFocusListener(); 1.209 + 1.210 + NS_DECL_ISUPPORTS 1.211 + NS_DECL_NSIDOMEVENTLISTENER 1.212 + 1.213 + nsresult Init(nsDocumentViewer *aDocViewer); 1.214 + 1.215 +private: 1.216 + nsDocumentViewer* mDocViewer; 1.217 +}; 1.218 + 1.219 + 1.220 +//------------------------------------------------------------- 1.221 +class nsDocumentViewer : public nsIContentViewer, 1.222 + public nsIContentViewerEdit, 1.223 + public nsIContentViewerFile, 1.224 + public nsIMarkupDocumentViewer, 1.225 + public nsIDocumentViewerPrint 1.226 + 1.227 +#ifdef NS_PRINTING 1.228 + , public nsIWebBrowserPrint 1.229 +#endif 1.230 + 1.231 +{ 1.232 + friend class nsDocViewerSelectionListener; 1.233 + friend class nsPagePrintTimer; 1.234 + friend class nsPrintEngine; 1.235 + 1.236 +public: 1.237 + nsDocumentViewer(); 1.238 + 1.239 + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW 1.240 + 1.241 + // nsISupports interface... 1.242 + NS_DECL_ISUPPORTS 1.243 + 1.244 + // nsIContentViewer interface... 1.245 + NS_DECL_NSICONTENTVIEWER 1.246 + 1.247 + // nsIContentViewerEdit 1.248 + NS_DECL_NSICONTENTVIEWEREDIT 1.249 + 1.250 + // nsIContentViewerFile 1.251 + NS_DECL_NSICONTENTVIEWERFILE 1.252 + 1.253 + // nsIMarkupDocumentViewer 1.254 + NS_DECL_NSIMARKUPDOCUMENTVIEWER 1.255 + 1.256 +#ifdef NS_PRINTING 1.257 + // nsIWebBrowserPrint 1.258 + NS_DECL_NSIWEBBROWSERPRINT 1.259 +#endif 1.260 + 1.261 + typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer, 1.262 + void* aClosure); 1.263 + void CallChildren(CallChildFunc aFunc, void* aClosure); 1.264 + 1.265 + // nsIDocumentViewerPrint Printing Methods 1.266 + NS_DECL_NSIDOCUMENTVIEWERPRINT 1.267 + 1.268 + 1.269 + static void DispatchBeforePrint(nsIDocument* aTop) 1.270 + { 1.271 + DispatchEventToWindowTree(aTop, NS_LITERAL_STRING("beforeprint")); 1.272 + } 1.273 + static void DispatchAfterPrint(nsIDocument* aTop) 1.274 + { 1.275 + DispatchEventToWindowTree(aTop, NS_LITERAL_STRING("afterprint")); 1.276 + } 1.277 + static void DispatchEventToWindowTree(nsIDocument* aTop, 1.278 + const nsAString& aEvent); 1.279 + 1.280 +protected: 1.281 + virtual ~nsDocumentViewer(); 1.282 + 1.283 +private: 1.284 + /** 1.285 + * Creates a view manager, root view, and widget for the root view, setting 1.286 + * mViewManager and mWindow. 1.287 + * @param aSize the initial size in appunits 1.288 + * @param aContainerView the container view to hook our root view up 1.289 + * to as a child, or null if this will be the root view manager 1.290 + */ 1.291 + nsresult MakeWindow(const nsSize& aSize, nsView* aContainerView); 1.292 + 1.293 + /** 1.294 + * Create our device context 1.295 + */ 1.296 + nsresult CreateDeviceContext(nsView* aContainerView); 1.297 + 1.298 + /** 1.299 + * If aDoCreation is true, this creates the device context, creates a 1.300 + * prescontext if necessary, and calls MakeWindow. 1.301 + * 1.302 + * If aForceSetNewDocument is false, then SetNewDocument won't be 1.303 + * called if the window's current document is already mDocument. 1.304 + */ 1.305 + nsresult InitInternal(nsIWidget* aParentWidget, 1.306 + nsISupports *aState, 1.307 + const nsIntRect& aBounds, 1.308 + bool aDoCreation, 1.309 + bool aNeedMakeCX = true, 1.310 + bool aForceSetNewDocument = true); 1.311 + /** 1.312 + * @param aDoInitialReflow set to true if you want to kick off the initial 1.313 + * reflow 1.314 + */ 1.315 + nsresult InitPresentationStuff(bool aDoInitialReflow); 1.316 + 1.317 + nsresult GetPopupNode(nsIDOMNode** aNode); 1.318 + nsresult GetPopupLinkNode(nsIDOMNode** aNode); 1.319 + nsresult GetPopupImageNode(nsIImageLoadingContent** aNode); 1.320 + 1.321 + void PrepareToStartLoad(void); 1.322 + 1.323 + nsresult SyncParentSubDocMap(); 1.324 + 1.325 + nsresult GetDocumentSelection(nsISelection **aSelection); 1.326 + 1.327 + void DestroyPresShell(); 1.328 + void DestroyPresContext(); 1.329 + 1.330 +#ifdef NS_PRINTING 1.331 + // Called when the DocViewer is notified that the state 1.332 + // of Printing or PP has changed 1.333 + void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode, 1.334 + bool aIsPrintingOrPP, 1.335 + bool aStartAtTop); 1.336 +#endif // NS_PRINTING 1.337 + 1.338 + // Whether we should attach to the top level widget. This is true if we 1.339 + // are sharing/recycling a single base widget and not creating multiple 1.340 + // child widgets. 1.341 + bool ShouldAttachToTopLevel(); 1.342 + 1.343 +protected: 1.344 + // These return the current shell/prescontext etc. 1.345 + nsIPresShell* GetPresShell(); 1.346 + nsPresContext* GetPresContext(); 1.347 + nsViewManager* GetViewManager(); 1.348 + 1.349 + void DetachFromTopLevelWidget(); 1.350 + 1.351 + // IMPORTANT: The ownership implicit in the following member 1.352 + // variables has been explicitly checked and set using nsCOMPtr 1.353 + // for owning pointers and raw COM interface pointers for weak 1.354 + // (ie, non owning) references. If you add any members to this 1.355 + // class, please make the ownership explicit (pinkerton, scc). 1.356 + 1.357 + WeakPtr<nsDocShell> mContainer; // it owns me! 1.358 + nsWeakPtr mTopContainerWhilePrinting; 1.359 + nsRefPtr<nsDeviceContext> mDeviceContext; // We create and own this baby 1.360 + 1.361 + // the following six items are explicitly in this order 1.362 + // so they will be destroyed in the reverse order (pinkerton, scc) 1.363 + nsCOMPtr<nsIDocument> mDocument; 1.364 + nsCOMPtr<nsIWidget> mWindow; // may be null 1.365 + nsRefPtr<nsViewManager> mViewManager; 1.366 + nsRefPtr<nsPresContext> mPresContext; 1.367 + nsCOMPtr<nsIPresShell> mPresShell; 1.368 + 1.369 + nsCOMPtr<nsISelectionListener> mSelectionListener; 1.370 + nsRefPtr<nsDocViewerFocusListener> mFocusListener; 1.371 + 1.372 + nsCOMPtr<nsIContentViewer> mPreviousViewer; 1.373 + nsCOMPtr<nsISHEntry> mSHEntry; 1.374 + 1.375 + nsIWidget* mParentWidget; // purposely won't be ref counted. May be null 1.376 + bool mAttachedToParent; // view is attached to the parent widget 1.377 + 1.378 + nsIntRect mBounds; 1.379 + 1.380 + // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley) 1.381 + // presshell only. 1.382 + float mTextZoom; // Text zoom, defaults to 1.0 1.383 + float mPageZoom; 1.384 + int mMinFontSize; 1.385 + 1.386 + int16_t mNumURLStarts; 1.387 + int16_t mDestroyRefCount; // a second "refcount" for the document viewer's "destroy" 1.388 + 1.389 + unsigned mStopped : 1; 1.390 + unsigned mLoaded : 1; 1.391 + unsigned mDeferredWindowClose : 1; 1.392 + // document management data 1.393 + // these items are specific to markup documents (html and xml) 1.394 + // may consider splitting these out into a subclass 1.395 + unsigned mIsSticky : 1; 1.396 + unsigned mInPermitUnload : 1; 1.397 + unsigned mInPermitUnloadPrompt: 1; 1.398 + 1.399 +#ifdef NS_PRINTING 1.400 + unsigned mClosingWhilePrinting : 1; 1.401 + 1.402 +#if NS_PRINT_PREVIEW 1.403 + unsigned mPrintPreviewZoomed : 1; 1.404 + 1.405 + // These data members support delayed printing when the document is loading 1.406 + unsigned mPrintIsPending : 1; 1.407 + unsigned mPrintDocIsFullyLoaded : 1; 1.408 + nsCOMPtr<nsIPrintSettings> mCachedPrintSettings; 1.409 + nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner; 1.410 + 1.411 + nsRefPtr<nsPrintEngine> mPrintEngine; 1.412 + float mOriginalPrintPreviewScale; 1.413 + float mPrintPreviewZoom; 1.414 + nsAutoPtr<nsPrintEventDispatcher> mBeforeAndAfterPrint; 1.415 +#endif // NS_PRINT_PREVIEW 1.416 + 1.417 +#ifdef DEBUG 1.418 + FILE* mDebugFile; 1.419 +#endif // DEBUG 1.420 +#endif // NS_PRINTING 1.421 + 1.422 + /* character set member data */ 1.423 + int32_t mHintCharsetSource; 1.424 + nsCString mHintCharset; 1.425 + nsCString mForceCharacterSet; 1.426 + 1.427 + bool mIsPageMode; 1.428 + bool mCallerIsClosingWindow; 1.429 + bool mInitializedForPrintPreview; 1.430 + bool mHidden; 1.431 +}; 1.432 + 1.433 +class nsPrintEventDispatcher 1.434 +{ 1.435 +public: 1.436 + nsPrintEventDispatcher(nsIDocument* aTop) : mTop(aTop) 1.437 + { 1.438 + nsDocumentViewer::DispatchBeforePrint(mTop); 1.439 + } 1.440 + ~nsPrintEventDispatcher() 1.441 + { 1.442 + nsDocumentViewer::DispatchAfterPrint(mTop); 1.443 + } 1.444 + 1.445 + nsCOMPtr<nsIDocument> mTop; 1.446 +}; 1.447 + 1.448 +class nsDocumentShownDispatcher : public nsRunnable 1.449 +{ 1.450 +public: 1.451 + nsDocumentShownDispatcher(nsCOMPtr<nsIDocument> aDocument) 1.452 + : mDocument(aDocument) {} 1.453 + 1.454 + NS_IMETHOD Run() MOZ_OVERRIDE; 1.455 + 1.456 +private: 1.457 + nsCOMPtr<nsIDocument> mDocument; 1.458 +}; 1.459 + 1.460 + 1.461 +//------------------------------------------------------------------ 1.462 +// nsDocumentViewer 1.463 +//------------------------------------------------------------------ 1.464 + 1.465 +//------------------------------------------------------------------ 1.466 +already_AddRefed<nsIContentViewer> 1.467 +NS_NewContentViewer() 1.468 +{ 1.469 + nsRefPtr<nsDocumentViewer> viewer = new nsDocumentViewer(); 1.470 + return viewer.forget(); 1.471 +} 1.472 + 1.473 +void nsDocumentViewer::PrepareToStartLoad() 1.474 +{ 1.475 + mStopped = false; 1.476 + mLoaded = false; 1.477 + mAttachedToParent = false; 1.478 + mDeferredWindowClose = false; 1.479 + mCallerIsClosingWindow = false; 1.480 + 1.481 +#ifdef NS_PRINTING 1.482 + mPrintIsPending = false; 1.483 + mPrintDocIsFullyLoaded = false; 1.484 + mClosingWhilePrinting = false; 1.485 + 1.486 + // Make sure we have destroyed it and cleared the data member 1.487 + if (mPrintEngine) { 1.488 + mPrintEngine->Destroy(); 1.489 + mPrintEngine = nullptr; 1.490 +#ifdef NS_PRINT_PREVIEW 1.491 + SetIsPrintPreview(false); 1.492 +#endif 1.493 + } 1.494 + 1.495 +#ifdef DEBUG 1.496 + mDebugFile = nullptr; 1.497 +#endif 1.498 + 1.499 +#endif // NS_PRINTING 1.500 +} 1.501 + 1.502 +// Note: operator new zeros our memory, so no need to init things to null. 1.503 +nsDocumentViewer::nsDocumentViewer() 1.504 + : mTextZoom(1.0), mPageZoom(1.0), mMinFontSize(0), 1.505 + mIsSticky(true), 1.506 +#ifdef NS_PRINT_PREVIEW 1.507 + mPrintPreviewZoom(1.0), 1.508 +#endif 1.509 + mHintCharsetSource(kCharsetUninitialized), 1.510 + mInitializedForPrintPreview(false), 1.511 + mHidden(false) 1.512 +{ 1.513 + PrepareToStartLoad(); 1.514 +} 1.515 + 1.516 +NS_IMPL_ADDREF(nsDocumentViewer) 1.517 +NS_IMPL_RELEASE(nsDocumentViewer) 1.518 + 1.519 +NS_INTERFACE_MAP_BEGIN(nsDocumentViewer) 1.520 + NS_INTERFACE_MAP_ENTRY(nsIContentViewer) 1.521 + NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer) 1.522 + NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile) 1.523 + NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit) 1.524 + NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint) 1.525 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentViewer) 1.526 +#ifdef NS_PRINTING 1.527 + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint) 1.528 +#endif 1.529 +NS_INTERFACE_MAP_END 1.530 + 1.531 +nsDocumentViewer::~nsDocumentViewer() 1.532 +{ 1.533 + if (mDocument) { 1.534 + Close(nullptr); 1.535 + mDocument->Destroy(); 1.536 + } 1.537 + 1.538 + NS_ASSERTION(!mPresShell && !mPresContext, 1.539 + "User did not call nsIContentViewer::Destroy"); 1.540 + if (mPresShell || mPresContext) { 1.541 + // Make sure we don't hand out a reference to the content viewer to 1.542 + // the SHEntry! 1.543 + mSHEntry = nullptr; 1.544 + 1.545 + Destroy(); 1.546 + } 1.547 + 1.548 + // XXX(?) Revoke pending invalidate events 1.549 +} 1.550 + 1.551 +/* 1.552 + * This method is called by the Document Loader once a document has 1.553 + * been created for a particular data stream... The content viewer 1.554 + * must cache this document for later use when Init(...) is called. 1.555 + * 1.556 + * This method is also called when an out of band document.write() happens. 1.557 + * In that case, the document passed in is the same as the previous document. 1.558 + */ 1.559 +/* virtual */ void 1.560 +nsDocumentViewer::LoadStart(nsIDocument* aDocument) 1.561 +{ 1.562 + MOZ_ASSERT(aDocument); 1.563 + 1.564 + if (!mDocument) { 1.565 + mDocument = aDocument; 1.566 + } 1.567 +} 1.568 + 1.569 +nsresult 1.570 +nsDocumentViewer::SyncParentSubDocMap() 1.571 +{ 1.572 + nsCOMPtr<nsIDocShellTreeItem> item(mContainer); 1.573 + nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(item)); 1.574 + nsCOMPtr<nsIContent> content; 1.575 + 1.576 + if (mDocument && pwin) { 1.577 + content = do_QueryInterface(pwin->GetFrameElementInternal()); 1.578 + } 1.579 + 1.580 + if (content) { 1.581 + nsCOMPtr<nsIDocShellTreeItem> parent; 1.582 + item->GetParent(getter_AddRefs(parent)); 1.583 + 1.584 + nsCOMPtr<nsIDOMWindow> parent_win(do_GetInterface(parent)); 1.585 + 1.586 + if (parent_win) { 1.587 + nsCOMPtr<nsIDOMDocument> dom_doc; 1.588 + parent_win->GetDocument(getter_AddRefs(dom_doc)); 1.589 + 1.590 + nsCOMPtr<nsIDocument> parent_doc(do_QueryInterface(dom_doc)); 1.591 + 1.592 + if (parent_doc) { 1.593 + if (mDocument && 1.594 + parent_doc->GetSubDocumentFor(content) != mDocument) { 1.595 + mDocument->SuppressEventHandling(nsIDocument::eEvents, 1.596 + parent_doc->EventHandlingSuppressed()); 1.597 + } 1.598 + return parent_doc->SetSubDocumentFor(content->AsElement(), mDocument); 1.599 + } 1.600 + } 1.601 + } 1.602 + 1.603 + return NS_OK; 1.604 +} 1.605 + 1.606 +NS_IMETHODIMP 1.607 +nsDocumentViewer::SetContainer(nsIDocShell* aContainer) 1.608 +{ 1.609 + mContainer = static_cast<nsDocShell*>(aContainer)->asWeakPtr(); 1.610 + if (mPresContext) { 1.611 + mPresContext->SetContainer(mContainer); 1.612 + } 1.613 + 1.614 + // We're loading a new document into the window where this document 1.615 + // viewer lives, sync the parent document's frame element -> sub 1.616 + // document map 1.617 + 1.618 + return SyncParentSubDocMap(); 1.619 +} 1.620 + 1.621 +NS_IMETHODIMP 1.622 +nsDocumentViewer::GetContainer(nsIDocShell** aResult) 1.623 +{ 1.624 + NS_ENSURE_ARG_POINTER(aResult); 1.625 + 1.626 + nsCOMPtr<nsIDocShell> container(mContainer); 1.627 + container.swap(*aResult); 1.628 + return NS_OK; 1.629 +} 1.630 + 1.631 +NS_IMETHODIMP 1.632 +nsDocumentViewer::Init(nsIWidget* aParentWidget, 1.633 + const nsIntRect& aBounds) 1.634 +{ 1.635 + return InitInternal(aParentWidget, nullptr, aBounds, true); 1.636 +} 1.637 + 1.638 +nsresult 1.639 +nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) 1.640 +{ 1.641 + if (GetIsPrintPreview()) 1.642 + return NS_OK; 1.643 + 1.644 + NS_ASSERTION(!mPresShell, 1.645 + "Someone should have destroyed the presshell!"); 1.646 + 1.647 + // Create the style set... 1.648 + nsStyleSet *styleSet; 1.649 + nsresult rv = CreateStyleSet(mDocument, &styleSet); 1.650 + NS_ENSURE_SUCCESS(rv, rv); 1.651 + 1.652 + // Now make the shell for the document 1.653 + mPresShell = mDocument->CreateShell(mPresContext, mViewManager, styleSet); 1.654 + if (!mPresShell) { 1.655 + delete styleSet; 1.656 + return NS_ERROR_FAILURE; 1.657 + } 1.658 + 1.659 + // We're done creating the style set 1.660 + styleSet->EndUpdate(); 1.661 + 1.662 + if (aDoInitialReflow) { 1.663 + // Since Initialize() will create frames for *all* items 1.664 + // that are currently in the document tree, we need to flush 1.665 + // any pending notifications to prevent the content sink from 1.666 + // duplicating layout frames for content it has added to the tree 1.667 + // but hasn't notified the document about. (Bug 154018) 1.668 + // 1.669 + // Note that we are flushing before we add mPresShell as an observer 1.670 + // to avoid bogus notifications. 1.671 + 1.672 + mDocument->FlushPendingNotifications(Flush_ContentAndNotify); 1.673 + } 1.674 + 1.675 + mPresShell->BeginObservingDocument(); 1.676 + 1.677 + // Initialize our view manager 1.678 + int32_t p2a = mPresContext->AppUnitsPerDevPixel(); 1.679 + MOZ_ASSERT(p2a == mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel()); 1.680 + nscoord width = p2a * mBounds.width; 1.681 + nscoord height = p2a * mBounds.height; 1.682 + 1.683 + mViewManager->SetWindowDimensions(width, height); 1.684 + mPresContext->SetTextZoom(mTextZoom); 1.685 + mPresContext->SetFullZoom(mPageZoom); 1.686 + mPresContext->SetBaseMinFontSize(mMinFontSize); 1.687 + 1.688 + p2a = mPresContext->AppUnitsPerDevPixel(); // zoom may have changed it 1.689 + width = p2a * mBounds.width; 1.690 + height = p2a * mBounds.height; 1.691 + if (aDoInitialReflow) { 1.692 + nsCOMPtr<nsIPresShell> shellGrip = mPresShell; 1.693 + // Initial reflow 1.694 + mPresShell->Initialize(width, height); 1.695 + } else { 1.696 + // Store the visible area so it's available for other callers of 1.697 + // Initialize, like nsContentSink::StartLayout. 1.698 + mPresContext->SetVisibleArea(nsRect(0, 0, width, height)); 1.699 + } 1.700 + 1.701 + // now register ourselves as a selection listener, so that we get 1.702 + // called when the selection changes in the window 1.703 + if (!mSelectionListener) { 1.704 + nsDocViewerSelectionListener *selectionListener = 1.705 + new nsDocViewerSelectionListener(); 1.706 + 1.707 + selectionListener->Init(this); 1.708 + 1.709 + // mSelectionListener is a owning reference 1.710 + mSelectionListener = selectionListener; 1.711 + } 1.712 + 1.713 + nsCOMPtr<nsISelection> selection; 1.714 + rv = GetDocumentSelection(getter_AddRefs(selection)); 1.715 + NS_ENSURE_SUCCESS(rv, rv); 1.716 + 1.717 + nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection)); 1.718 + rv = selPrivate->AddSelectionListener(mSelectionListener); 1.719 + if (NS_FAILED(rv)) 1.720 + return rv; 1.721 + 1.722 + // Save old listener so we can unregister it 1.723 + nsRefPtr<nsDocViewerFocusListener> oldFocusListener = mFocusListener; 1.724 + 1.725 + // focus listener 1.726 + // 1.727 + // now register ourselves as a focus listener, so that we get called 1.728 + // when the focus changes in the window 1.729 + nsDocViewerFocusListener *focusListener = new nsDocViewerFocusListener(); 1.730 + 1.731 + focusListener->Init(this); 1.732 + 1.733 + // mFocusListener is a strong reference 1.734 + mFocusListener = focusListener; 1.735 + 1.736 + if (mDocument) { 1.737 + mDocument->AddEventListener(NS_LITERAL_STRING("focus"), 1.738 + mFocusListener, 1.739 + false, false); 1.740 + mDocument->AddEventListener(NS_LITERAL_STRING("blur"), 1.741 + mFocusListener, 1.742 + false, false); 1.743 + 1.744 + if (oldFocusListener) { 1.745 + mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), 1.746 + oldFocusListener, false); 1.747 + mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), 1.748 + oldFocusListener, false); 1.749 + } 1.750 + } 1.751 + 1.752 + if (aDoInitialReflow && mDocument) { 1.753 + mDocument->ScrollToRef(); 1.754 + } 1.755 + 1.756 + return NS_OK; 1.757 +} 1.758 + 1.759 +static nsPresContext* 1.760 +CreatePresContext(nsIDocument* aDocument, 1.761 + nsPresContext::nsPresContextType aType, 1.762 + nsView* aContainerView) 1.763 +{ 1.764 + if (aContainerView) 1.765 + return new nsPresContext(aDocument, aType); 1.766 + return new nsRootPresContext(aDocument, aType); 1.767 +} 1.768 + 1.769 +//----------------------------------------------- 1.770 +// This method can be used to initial the "presentation" 1.771 +// The aDoCreation indicates whether it should create 1.772 +// all the new objects or just initialize the existing ones 1.773 +nsresult 1.774 +nsDocumentViewer::InitInternal(nsIWidget* aParentWidget, 1.775 + nsISupports *aState, 1.776 + const nsIntRect& aBounds, 1.777 + bool aDoCreation, 1.778 + bool aNeedMakeCX /*= true*/, 1.779 + bool aForceSetNewDocument /* = true*/) 1.780 +{ 1.781 + if (mIsPageMode) { 1.782 + // XXXbz should the InitInternal in SetPageMode just pass false 1.783 + // here itself? 1.784 + aForceSetNewDocument = false; 1.785 + } 1.786 + 1.787 + // We don't want any scripts to run here. That can cause flushing, 1.788 + // which can cause reentry into initialization of this document viewer, 1.789 + // which would be disastrous. 1.790 + nsAutoScriptBlocker blockScripts; 1.791 + 1.792 + mParentWidget = aParentWidget; // not ref counted 1.793 + mBounds = aBounds; 1.794 + 1.795 + nsresult rv = NS_OK; 1.796 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER); 1.797 + 1.798 + nsView* containerView = FindContainerView(); 1.799 + 1.800 + bool makeCX = false; 1.801 + if (aDoCreation) { 1.802 + nsresult rv = CreateDeviceContext(containerView); 1.803 + NS_ENSURE_SUCCESS(rv, rv); 1.804 + 1.805 + // XXXbz this is a nasty hack to do with the fact that we create 1.806 + // presentations both in Init() and in Show()... Ideally we would only do 1.807 + // it in one place (Show()) and require that callers call init(), open(), 1.808 + // show() in that order or something. 1.809 + if (!mPresContext && 1.810 + (aParentWidget || containerView || mDocument->IsBeingUsedAsImage() || 1.811 + (mDocument->GetDisplayDocument() && 1.812 + mDocument->GetDisplayDocument()->GetShell()))) { 1.813 + // Create presentation context 1.814 + if (mIsPageMode) { 1.815 + //Presentation context already created in SetPageMode which is calling this method 1.816 + } else { 1.817 + mPresContext = CreatePresContext(mDocument, 1.818 + nsPresContext::eContext_Galley, containerView); 1.819 + } 1.820 + NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY); 1.821 + 1.822 + nsresult rv = mPresContext->Init(mDeviceContext); 1.823 + if (NS_FAILED(rv)) { 1.824 + mPresContext = nullptr; 1.825 + return rv; 1.826 + } 1.827 + 1.828 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.829 + makeCX = !GetIsPrintPreview() && aNeedMakeCX; // needs to be true except when we are already in PP or we are enabling/disabling paginated mode. 1.830 +#else 1.831 + makeCX = true; 1.832 +#endif 1.833 + } 1.834 + 1.835 + if (mPresContext) { 1.836 + // Create the ViewManager and Root View... 1.837 + 1.838 + // We must do this before we tell the script global object about 1.839 + // this new document since doing that will cause us to re-enter 1.840 + // into nsSubDocumentFrame code through reflows caused by 1.841 + // FlushPendingNotifications() calls down the road... 1.842 + 1.843 + rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(aBounds.width), 1.844 + mPresContext->DevPixelsToAppUnits(aBounds.height)), 1.845 + containerView); 1.846 + NS_ENSURE_SUCCESS(rv, rv); 1.847 + Hide(); 1.848 + 1.849 +#ifdef NS_PRINT_PREVIEW 1.850 + if (mIsPageMode) { 1.851 + // I'm leaving this in a broken state for the moment; we should 1.852 + // be measuring/scaling with the print device context, not the 1.853 + // screen device context, but this is good enough to allow 1.854 + // printing reftests to work. 1.855 + double pageWidth = 0, pageHeight = 0; 1.856 + mPresContext->GetPrintSettings()->GetEffectivePageSize(&pageWidth, 1.857 + &pageHeight); 1.858 + mPresContext->SetPageSize( 1.859 + nsSize(mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageWidth)), 1.860 + mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageHeight)))); 1.861 + mPresContext->SetIsRootPaginatedDocument(true); 1.862 + mPresContext->SetPageScale(1.0f); 1.863 + } 1.864 +#endif 1.865 + } else { 1.866 + // Avoid leaking the old viewer. 1.867 + if (mPreviousViewer) { 1.868 + mPreviousViewer->Destroy(); 1.869 + mPreviousViewer = nullptr; 1.870 + } 1.871 + } 1.872 + } 1.873 + 1.874 + nsCOMPtr<nsIInterfaceRequestor> requestor(mContainer); 1.875 + if (requestor) { 1.876 + if (mPresContext) { 1.877 + nsCOMPtr<nsILinkHandler> linkHandler; 1.878 + requestor->GetInterface(NS_GET_IID(nsILinkHandler), 1.879 + getter_AddRefs(linkHandler)); 1.880 + 1.881 + mPresContext->SetContainer(mContainer); 1.882 + mPresContext->SetLinkHandler(linkHandler); 1.883 + } 1.884 + 1.885 + // Set script-context-owner in the document 1.886 + 1.887 + nsCOMPtr<nsPIDOMWindow> window; 1.888 + requestor->GetInterface(NS_GET_IID(nsPIDOMWindow), 1.889 + getter_AddRefs(window)); 1.890 + 1.891 + if (window) { 1.892 + nsCOMPtr<nsIDocument> curDoc = window->GetExtantDoc(); 1.893 + if (aForceSetNewDocument || curDoc != mDocument) { 1.894 + window->SetNewDocument(mDocument, aState, false); 1.895 + nsJSContext::LoadStart(); 1.896 + } 1.897 + } 1.898 + } 1.899 + 1.900 + if (aDoCreation && mPresContext) { 1.901 + // The ViewManager and Root View was created above (in 1.902 + // MakeWindow())... 1.903 + 1.904 + rv = InitPresentationStuff(!makeCX); 1.905 + } 1.906 + 1.907 + return rv; 1.908 +} 1.909 + 1.910 +void nsDocumentViewer::SetNavigationTiming(nsDOMNavigationTiming* timing) 1.911 +{ 1.912 + NS_ASSERTION(mDocument, "Must have a document to set navigation timing."); 1.913 + if (mDocument) { 1.914 + mDocument->SetNavigationTiming(timing); 1.915 + } 1.916 +} 1.917 + 1.918 +// 1.919 +// LoadComplete(aStatus) 1.920 +// 1.921 +// aStatus - The status returned from loading the document. 1.922 +// 1.923 +// This method is called by the container when the document has been 1.924 +// completely loaded. 1.925 +// 1.926 +NS_IMETHODIMP 1.927 +nsDocumentViewer::LoadComplete(nsresult aStatus) 1.928 +{ 1.929 + /* We need to protect ourself against auto-destruction in case the 1.930 + window is closed while processing the OnLoad event. See bug 1.931 + http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more 1.932 + explanation. 1.933 + */ 1.934 + nsRefPtr<nsDocumentViewer> kungFuDeathGrip(this); 1.935 + 1.936 + // Flush out layout so it's up-to-date by the time onload is called. 1.937 + // Note that this could destroy the window, so do this before 1.938 + // checking for our mDocument and its window. 1.939 + if (mPresShell && !mStopped) { 1.940 + // Hold strong ref because this could conceivably run script 1.941 + nsCOMPtr<nsIPresShell> shell = mPresShell; 1.942 + shell->FlushPendingNotifications(Flush_Layout); 1.943 + } 1.944 + 1.945 + nsresult rv = NS_OK; 1.946 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.947 + 1.948 + // First, get the window from the document... 1.949 + nsCOMPtr<nsPIDOMWindow> window = mDocument->GetWindow(); 1.950 + 1.951 + mLoaded = true; 1.952 + 1.953 + // Now, fire either an OnLoad or OnError event to the document... 1.954 + bool restoring = false; 1.955 + // XXXbz imagelib kills off the document load for a full-page image with 1.956 + // NS_ERROR_PARSED_DATA_CACHED if it's in the cache. So we want to treat 1.957 + // that one as a success code; otherwise whether we fire onload for the image 1.958 + // will depend on whether it's cached! 1.959 + if(window && 1.960 + (NS_SUCCEEDED(aStatus) || aStatus == NS_ERROR_PARSED_DATA_CACHED)) { 1.961 + nsEventStatus status = nsEventStatus_eIgnore; 1.962 + WidgetEvent event(true, NS_LOAD); 1.963 + event.mFlags.mBubbles = false; 1.964 + // XXX Dispatching to |window|, but using |document| as the target. 1.965 + event.target = mDocument; 1.966 + 1.967 + // If the document presentation is being restored, we don't want to fire 1.968 + // onload to the document content since that would likely confuse scripts 1.969 + // on the page. 1.970 + 1.971 + nsIDocShell *docShell = window->GetDocShell(); 1.972 + NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED); 1.973 + 1.974 + docShell->GetRestoringDocument(&restoring); 1.975 + if (!restoring) { 1.976 + NS_ASSERTION(mDocument->IsXUL() || // readyState for XUL is bogus 1.977 + mDocument->GetReadyStateEnum() == 1.978 + nsIDocument::READYSTATE_INTERACTIVE || 1.979 + // test_stricttransportsecurity.html has old-style 1.980 + // docshell-generated about:blank docs reach this code! 1.981 + (mDocument->GetReadyStateEnum() == 1.982 + nsIDocument::READYSTATE_UNINITIALIZED && 1.983 + NS_IsAboutBlank(mDocument->GetDocumentURI())), 1.984 + "Bad readystate"); 1.985 + nsCOMPtr<nsIDocument> d = mDocument; 1.986 + mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); 1.987 + 1.988 + nsRefPtr<nsDOMNavigationTiming> timing(d->GetNavigationTiming()); 1.989 + if (timing) { 1.990 + timing->NotifyLoadEventStart(); 1.991 + } 1.992 + 1.993 + // Dispatch observer notification to notify observers document load is complete. 1.994 + nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); 1.995 + nsIPrincipal *principal = d->NodePrincipal(); 1.996 + os->NotifyObservers(d, 1.997 + nsContentUtils::IsSystemPrincipal(principal) ? 1.998 + "chrome-document-loaded" : 1.999 + "content-document-loaded", 1.1000 + nullptr); 1.1001 + 1.1002 + EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status); 1.1003 + if (timing) { 1.1004 + timing->NotifyLoadEventEnd(); 1.1005 + } 1.1006 + } 1.1007 + } else { 1.1008 + // XXX: Should fire error event to the document... 1.1009 + } 1.1010 + 1.1011 + // Notify the document that it has been shown (regardless of whether 1.1012 + // it was just loaded). Note: mDocument may be null now if the above 1.1013 + // firing of onload caused the document to unload. 1.1014 + if (mDocument) { 1.1015 + // Re-get window, since it might have changed during above firing of onload 1.1016 + window = mDocument->GetWindow(); 1.1017 + if (window) { 1.1018 + nsIDocShell *docShell = window->GetDocShell(); 1.1019 + bool isInUnload; 1.1020 + if (docShell && NS_SUCCEEDED(docShell->GetIsInUnload(&isInUnload)) && 1.1021 + !isInUnload) { 1.1022 + mDocument->OnPageShow(restoring, nullptr); 1.1023 + } 1.1024 + } 1.1025 + } 1.1026 + 1.1027 + if (!mStopped) { 1.1028 + if (mDocument) { 1.1029 + mDocument->ScrollToRef(); 1.1030 + } 1.1031 + 1.1032 + // Now that the document has loaded, we can tell the presshell 1.1033 + // to unsuppress painting. 1.1034 + if (mPresShell) { 1.1035 + nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); 1.1036 + mPresShell->UnsuppressPainting(); 1.1037 + // mPresShell could have been removed now, see bug 378682/421432 1.1038 + if (mPresShell) { 1.1039 + mPresShell->LoadComplete(); 1.1040 + } 1.1041 + } 1.1042 + } 1.1043 + 1.1044 + nsJSContext::LoadEnd(); 1.1045 + 1.1046 +#ifdef NS_PRINTING 1.1047 + // Check to see if someone tried to print during the load 1.1048 + if (mPrintIsPending) { 1.1049 + mPrintIsPending = false; 1.1050 + mPrintDocIsFullyLoaded = true; 1.1051 + Print(mCachedPrintSettings, mCachedPrintWebProgressListner); 1.1052 + mCachedPrintSettings = nullptr; 1.1053 + mCachedPrintWebProgressListner = nullptr; 1.1054 + } 1.1055 +#endif 1.1056 + 1.1057 + return rv; 1.1058 +} 1.1059 + 1.1060 +NS_IMETHODIMP 1.1061 +nsDocumentViewer::PermitUnload(bool aCallerClosesWindow, 1.1062 + bool *aPermitUnload) 1.1063 +{ 1.1064 + bool shouldPrompt = true; 1.1065 + return PermitUnloadInternal(aCallerClosesWindow, &shouldPrompt, 1.1066 + aPermitUnload); 1.1067 +} 1.1068 + 1.1069 + 1.1070 +nsresult 1.1071 +nsDocumentViewer::PermitUnloadInternal(bool aCallerClosesWindow, 1.1072 + bool *aShouldPrompt, 1.1073 + bool *aPermitUnload) 1.1074 +{ 1.1075 + AutoDontWarnAboutSyncXHR disableSyncXHRWarning; 1.1076 + 1.1077 + *aPermitUnload = true; 1.1078 + 1.1079 + if (!mDocument 1.1080 + || mInPermitUnload 1.1081 + || mCallerIsClosingWindow 1.1082 + || mInPermitUnloadPrompt) { 1.1083 + return NS_OK; 1.1084 + } 1.1085 + 1.1086 + static bool sIsBeforeUnloadDisabled; 1.1087 + static bool sBeforeUnloadPrefCached = false; 1.1088 + 1.1089 + if (!sBeforeUnloadPrefCached ) { 1.1090 + sBeforeUnloadPrefCached = true; 1.1091 + Preferences::AddBoolVarCache(&sIsBeforeUnloadDisabled, 1.1092 + BEFOREUNLOAD_DISABLED_PREFNAME); 1.1093 + } 1.1094 + 1.1095 + // If the user has turned off onbeforeunload warnings, no need to check. 1.1096 + if (sIsBeforeUnloadDisabled) { 1.1097 + return NS_OK; 1.1098 + } 1.1099 + 1.1100 + // First, get the script global object from the document... 1.1101 + nsPIDOMWindow *window = mDocument->GetWindow(); 1.1102 + 1.1103 + if (!window) { 1.1104 + // This is odd, but not fatal 1.1105 + NS_WARNING("window not set for document!"); 1.1106 + return NS_OK; 1.1107 + } 1.1108 + 1.1109 + NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "This is unsafe"); 1.1110 + 1.1111 + // Now, fire an BeforeUnload event to the document and see if it's ok 1.1112 + // to unload... 1.1113 + nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument); 1.1114 + nsCOMPtr<nsIDOMEvent> event; 1.1115 + domDoc->CreateEvent(NS_LITERAL_STRING("beforeunloadevent"), 1.1116 + getter_AddRefs(event)); 1.1117 + nsCOMPtr<nsIDOMBeforeUnloadEvent> beforeUnload = do_QueryInterface(event); 1.1118 + NS_ENSURE_STATE(beforeUnload); 1.1119 + nsresult rv = event->InitEvent(NS_LITERAL_STRING("beforeunload"), 1.1120 + false, true); 1.1121 + NS_ENSURE_SUCCESS(rv, rv); 1.1122 + 1.1123 + // Dispatching to |window|, but using |document| as the target. 1.1124 + event->SetTarget(mDocument); 1.1125 + event->SetTrusted(true); 1.1126 + 1.1127 + // In evil cases we might be destroyed while handling the 1.1128 + // onbeforeunload event, don't let that happen. (see also bug#331040) 1.1129 + nsRefPtr<nsDocumentViewer> kungFuDeathGrip(this); 1.1130 + 1.1131 + { 1.1132 + // Never permit popups from the beforeunload handler, no matter 1.1133 + // how we get here. 1.1134 + nsAutoPopupStatePusher popupStatePusher(openAbused, true); 1.1135 + 1.1136 + // Never permit dialogs from the beforeunload handler 1.1137 + nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window); 1.1138 + bool dialogsWereEnabled = false; 1.1139 + utils->AreDialogsEnabled(&dialogsWereEnabled); 1.1140 + utils->DisableDialogs(); 1.1141 + 1.1142 + mInPermitUnload = true; 1.1143 + EventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext, 1.1144 + nullptr); 1.1145 + mInPermitUnload = false; 1.1146 + if (dialogsWereEnabled) { 1.1147 + utils->EnableDialogs(); 1.1148 + } 1.1149 + } 1.1150 + 1.1151 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.1152 + nsAutoString text; 1.1153 + beforeUnload->GetReturnValue(text); 1.1154 + if (*aShouldPrompt && (event->GetInternalNSEvent()->mFlags.mDefaultPrevented || 1.1155 + !text.IsEmpty())) { 1.1156 + // Ask the user if it's ok to unload the current page 1.1157 + 1.1158 + nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell); 1.1159 + 1.1160 + if (prompt) { 1.1161 + nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt); 1.1162 + if (promptBag) { 1.1163 + bool isTabModalPromptAllowed; 1.1164 + GetIsTabModalPromptAllowed(&isTabModalPromptAllowed); 1.1165 + promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), 1.1166 + isTabModalPromptAllowed); 1.1167 + } 1.1168 + 1.1169 + nsXPIDLString title, message, stayLabel, leaveLabel; 1.1170 + rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, 1.1171 + "OnBeforeUnloadTitle", 1.1172 + title); 1.1173 + nsresult tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, 1.1174 + "OnBeforeUnloadMessage", 1.1175 + message); 1.1176 + if (NS_FAILED(tmp)) { 1.1177 + rv = tmp; 1.1178 + } 1.1179 + tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, 1.1180 + "OnBeforeUnloadLeaveButton", 1.1181 + leaveLabel); 1.1182 + if (NS_FAILED(tmp)) { 1.1183 + rv = tmp; 1.1184 + } 1.1185 + tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, 1.1186 + "OnBeforeUnloadStayButton", 1.1187 + stayLabel); 1.1188 + if (NS_FAILED(tmp)) { 1.1189 + rv = tmp; 1.1190 + } 1.1191 + 1.1192 + if (NS_FAILED(rv) || !title || !message || !stayLabel || !leaveLabel) { 1.1193 + NS_ERROR("Failed to get strings from dom.properties!"); 1.1194 + return NS_OK; 1.1195 + } 1.1196 + 1.1197 + // Although the exact value is ignored, we must not pass invalid 1.1198 + // bool values through XPConnect. 1.1199 + bool dummy = false; 1.1200 + int32_t buttonPressed = 0; 1.1201 + uint32_t buttonFlags = (nsIPrompt::BUTTON_POS_0_DEFAULT | 1.1202 + (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) | 1.1203 + (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_1)); 1.1204 + 1.1205 + nsAutoSyncOperation sync(mDocument); 1.1206 + mInPermitUnloadPrompt = true; 1.1207 + rv = prompt->ConfirmEx(title, message, buttonFlags, 1.1208 + leaveLabel, stayLabel, nullptr, nullptr, 1.1209 + &dummy, &buttonPressed); 1.1210 + mInPermitUnloadPrompt = false; 1.1211 + 1.1212 + // If the prompt aborted, we tell our consumer that it is not allowed 1.1213 + // to unload the page. One reason that prompts abort is that the user 1.1214 + // performed some action that caused the page to unload while our prompt 1.1215 + // was active. In those cases we don't want our consumer to also unload 1.1216 + // the page. 1.1217 + // 1.1218 + // XXX: Are there other cases where prompts can abort? Is it ok to 1.1219 + // prevent unloading the page in those cases? 1.1220 + if (NS_FAILED(rv)) { 1.1221 + *aPermitUnload = false; 1.1222 + return NS_OK; 1.1223 + } 1.1224 + 1.1225 + // Button 0 == leave, button 1 == stay 1.1226 + *aPermitUnload = (buttonPressed == 0); 1.1227 + // If the user decided to go ahead, make sure not to prompt the user again 1.1228 + // by toggling the internal prompting bool to false: 1.1229 + if (*aPermitUnload) { 1.1230 + *aShouldPrompt = false; 1.1231 + } 1.1232 + } 1.1233 + } 1.1234 + 1.1235 + if (docShell) { 1.1236 + int32_t childCount; 1.1237 + docShell->GetChildCount(&childCount); 1.1238 + 1.1239 + for (int32_t i = 0; i < childCount && *aPermitUnload; ++i) { 1.1240 + nsCOMPtr<nsIDocShellTreeItem> item; 1.1241 + docShell->GetChildAt(i, getter_AddRefs(item)); 1.1242 + 1.1243 + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item)); 1.1244 + 1.1245 + if (docShell) { 1.1246 + nsCOMPtr<nsIContentViewer> cv; 1.1247 + docShell->GetContentViewer(getter_AddRefs(cv)); 1.1248 + 1.1249 + if (cv) { 1.1250 + cv->PermitUnloadInternal(aCallerClosesWindow, aShouldPrompt, 1.1251 + aPermitUnload); 1.1252 + } 1.1253 + } 1.1254 + } 1.1255 + } 1.1256 + 1.1257 + if (aCallerClosesWindow && *aPermitUnload) 1.1258 + mCallerIsClosingWindow = true; 1.1259 + 1.1260 + return NS_OK; 1.1261 +} 1.1262 + 1.1263 +NS_IMETHODIMP 1.1264 +nsDocumentViewer::GetBeforeUnloadFiring(bool* aInEvent) 1.1265 +{ 1.1266 + *aInEvent = mInPermitUnload; 1.1267 + return NS_OK; 1.1268 +} 1.1269 + 1.1270 +NS_IMETHODIMP 1.1271 +nsDocumentViewer::GetInPermitUnload(bool* aInEvent) 1.1272 +{ 1.1273 + *aInEvent = mInPermitUnloadPrompt; 1.1274 + return NS_OK; 1.1275 +} 1.1276 + 1.1277 +NS_IMETHODIMP 1.1278 +nsDocumentViewer::ResetCloseWindow() 1.1279 +{ 1.1280 + mCallerIsClosingWindow = false; 1.1281 + 1.1282 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.1283 + if (docShell) { 1.1284 + int32_t childCount; 1.1285 + docShell->GetChildCount(&childCount); 1.1286 + 1.1287 + for (int32_t i = 0; i < childCount; ++i) { 1.1288 + nsCOMPtr<nsIDocShellTreeItem> item; 1.1289 + docShell->GetChildAt(i, getter_AddRefs(item)); 1.1290 + 1.1291 + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item)); 1.1292 + 1.1293 + if (docShell) { 1.1294 + nsCOMPtr<nsIContentViewer> cv; 1.1295 + docShell->GetContentViewer(getter_AddRefs(cv)); 1.1296 + 1.1297 + if (cv) { 1.1298 + cv->ResetCloseWindow(); 1.1299 + } 1.1300 + } 1.1301 + } 1.1302 + } 1.1303 + return NS_OK; 1.1304 +} 1.1305 + 1.1306 +NS_IMETHODIMP 1.1307 +nsDocumentViewer::PageHide(bool aIsUnload) 1.1308 +{ 1.1309 + AutoDontWarnAboutSyncXHR disableSyncXHRWarning; 1.1310 + 1.1311 + mHidden = true; 1.1312 + 1.1313 + if (!mDocument) { 1.1314 + return NS_ERROR_NULL_POINTER; 1.1315 + } 1.1316 + 1.1317 + mDocument->OnPageHide(!aIsUnload, nullptr); 1.1318 + 1.1319 + // inform the window so that the focus state is reset. 1.1320 + NS_ENSURE_STATE(mDocument); 1.1321 + nsPIDOMWindow *window = mDocument->GetWindow(); 1.1322 + if (window) 1.1323 + window->PageHidden(); 1.1324 + 1.1325 + if (aIsUnload) { 1.1326 + // Poke the GC. The window might be collectable garbage now. 1.1327 + nsJSContext::PokeGC(JS::gcreason::PAGE_HIDE, NS_GC_DELAY * 2); 1.1328 + 1.1329 + // if Destroy() was called during OnPageHide(), mDocument is nullptr. 1.1330 + NS_ENSURE_STATE(mDocument); 1.1331 + 1.1332 + // First, get the window from the document... 1.1333 + nsPIDOMWindow *window = mDocument->GetWindow(); 1.1334 + 1.1335 + if (!window) { 1.1336 + // Fail if no window is available... 1.1337 + NS_WARNING("window not set for document!"); 1.1338 + return NS_ERROR_NULL_POINTER; 1.1339 + } 1.1340 + 1.1341 + // Now, fire an Unload event to the document... 1.1342 + nsEventStatus status = nsEventStatus_eIgnore; 1.1343 + WidgetEvent event(true, NS_PAGE_UNLOAD); 1.1344 + event.mFlags.mBubbles = false; 1.1345 + // XXX Dispatching to |window|, but using |document| as the target. 1.1346 + event.target = mDocument; 1.1347 + 1.1348 + // Never permit popups from the unload handler, no matter how we get 1.1349 + // here. 1.1350 + nsAutoPopupStatePusher popupStatePusher(openAbused, true); 1.1351 + 1.1352 + EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status); 1.1353 + } 1.1354 + 1.1355 +#ifdef MOZ_XUL 1.1356 + // look for open menupopups and close them after the unload event, in case 1.1357 + // the unload event listeners open any new popups 1.1358 + nsContentUtils::HidePopupsInDocument(mDocument); 1.1359 +#endif 1.1360 + 1.1361 + return NS_OK; 1.1362 +} 1.1363 + 1.1364 +static void 1.1365 +AttachContainerRecurse(nsIDocShell* aShell) 1.1366 +{ 1.1367 + nsCOMPtr<nsIContentViewer> viewer; 1.1368 + aShell->GetContentViewer(getter_AddRefs(viewer)); 1.1369 + if (viewer) { 1.1370 + nsIDocument* doc = viewer->GetDocument(); 1.1371 + if (doc) { 1.1372 + doc->SetContainer(static_cast<nsDocShell*>(aShell)); 1.1373 + } 1.1374 + nsRefPtr<nsPresContext> pc; 1.1375 + viewer->GetPresContext(getter_AddRefs(pc)); 1.1376 + if (pc) { 1.1377 + pc->SetContainer(static_cast<nsDocShell*>(aShell)); 1.1378 + pc->SetLinkHandler(nsCOMPtr<nsILinkHandler>(do_QueryInterface(aShell))); 1.1379 + } 1.1380 + nsCOMPtr<nsIPresShell> presShell; 1.1381 + viewer->GetPresShell(getter_AddRefs(presShell)); 1.1382 + if (presShell) { 1.1383 + presShell->SetForwardingContainer(WeakPtr<nsDocShell>()); 1.1384 + } 1.1385 + } 1.1386 + 1.1387 + // Now recurse through the children 1.1388 + int32_t childCount; 1.1389 + aShell->GetChildCount(&childCount); 1.1390 + for (int32_t i = 0; i < childCount; ++i) { 1.1391 + nsCOMPtr<nsIDocShellTreeItem> childItem; 1.1392 + aShell->GetChildAt(i, getter_AddRefs(childItem)); 1.1393 + AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem))); 1.1394 + } 1.1395 +} 1.1396 + 1.1397 +NS_IMETHODIMP 1.1398 +nsDocumentViewer::Open(nsISupports *aState, nsISHEntry *aSHEntry) 1.1399 +{ 1.1400 + NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED); 1.1401 + 1.1402 + if (mDocument) 1.1403 + mDocument->SetContainer(mContainer); 1.1404 + 1.1405 + nsresult rv = InitInternal(mParentWidget, aState, mBounds, false); 1.1406 + NS_ENSURE_SUCCESS(rv, rv); 1.1407 + 1.1408 + mHidden = false; 1.1409 + 1.1410 + if (mPresShell) 1.1411 + mPresShell->SetForwardingContainer(WeakPtr<nsDocShell>()); 1.1412 + 1.1413 + // Rehook the child presentations. The child shells are still in 1.1414 + // session history, so get them from there. 1.1415 + 1.1416 + if (aSHEntry) { 1.1417 + nsCOMPtr<nsIDocShellTreeItem> item; 1.1418 + int32_t itemIndex = 0; 1.1419 + while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++, 1.1420 + getter_AddRefs(item))) && item) { 1.1421 + AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item))); 1.1422 + } 1.1423 + } 1.1424 + 1.1425 + SyncParentSubDocMap(); 1.1426 + 1.1427 + if (mFocusListener && mDocument) { 1.1428 + mDocument->AddEventListener(NS_LITERAL_STRING("focus"), mFocusListener, 1.1429 + false, false); 1.1430 + mDocument->AddEventListener(NS_LITERAL_STRING("blur"), mFocusListener, 1.1431 + false, false); 1.1432 + } 1.1433 + 1.1434 + // XXX re-enable image animations once that works correctly 1.1435 + 1.1436 + PrepareToStartLoad(); 1.1437 + 1.1438 + // When loading a page from the bfcache with puppet widgets, we do the 1.1439 + // widget attachment here (it is otherwise done in MakeWindow, which is 1.1440 + // called for non-bfcache pages in the history, but not bfcache pages). 1.1441 + // Attachment is necessary, since we get detached when another page 1.1442 + // is browsed to. That is, if we are one page A, then when we go to 1.1443 + // page B, we detach. So page A's view has no widget. If we then go 1.1444 + // back to it, and it is in the bfcache, we will use that view, which 1.1445 + // doesn't have a widget. The attach call here will properly attach us. 1.1446 + if (nsIWidget::UsePuppetWidgets() && mPresContext && 1.1447 + ShouldAttachToTopLevel()) { 1.1448 + // If the old view is already attached to our parent, detach 1.1449 + DetachFromTopLevelWidget(); 1.1450 + 1.1451 + nsViewManager *vm = GetViewManager(); 1.1452 + NS_ABORT_IF_FALSE(vm, "no view manager"); 1.1453 + nsView* v = vm->GetRootView(); 1.1454 + NS_ABORT_IF_FALSE(v, "no root view"); 1.1455 + NS_ABORT_IF_FALSE(mParentWidget, "no mParentWidget to set"); 1.1456 + v->AttachToTopLevelWidget(mParentWidget); 1.1457 + 1.1458 + mAttachedToParent = true; 1.1459 + } 1.1460 + 1.1461 + return NS_OK; 1.1462 +} 1.1463 + 1.1464 +NS_IMETHODIMP 1.1465 +nsDocumentViewer::Close(nsISHEntry *aSHEntry) 1.1466 +{ 1.1467 + // All callers are supposed to call close to break circular 1.1468 + // references. If we do this stuff in the destructor, the 1.1469 + // destructor might never be called (especially if we're being 1.1470 + // used from JS. 1.1471 + 1.1472 + mSHEntry = aSHEntry; 1.1473 + 1.1474 + // Close is also needed to disable scripts during paint suppression, 1.1475 + // since we transfer the existing global object to the new document 1.1476 + // that is loaded. In the future, the global object may become a proxy 1.1477 + // for an object that can be switched in and out so that we don't need 1.1478 + // to disable scripts during paint suppression. 1.1479 + 1.1480 + if (!mDocument) 1.1481 + return NS_OK; 1.1482 + 1.1483 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.1484 + // Turn scripting back on 1.1485 + // after PrintPreview had turned it off 1.1486 + if (GetIsPrintPreview() && mPrintEngine) { 1.1487 + mPrintEngine->TurnScriptingOn(true); 1.1488 + } 1.1489 +#endif 1.1490 + 1.1491 +#ifdef NS_PRINTING 1.1492 + // A Close was called while we were printing 1.1493 + // so don't clear the ScriptGlobalObject 1.1494 + // or clear the mDocument below 1.1495 + if (mPrintEngine && !mClosingWhilePrinting) { 1.1496 + mClosingWhilePrinting = true; 1.1497 + } else 1.1498 +#endif 1.1499 + { 1.1500 + // out of band cleanup of docshell 1.1501 + mDocument->SetScriptGlobalObject(nullptr); 1.1502 + 1.1503 + if (!mSHEntry && mDocument) 1.1504 + mDocument->RemovedFromDocShell(); 1.1505 + } 1.1506 + 1.1507 + if (mFocusListener && mDocument) { 1.1508 + mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), mFocusListener, 1.1509 + false); 1.1510 + mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), mFocusListener, 1.1511 + false); 1.1512 + } 1.1513 + 1.1514 + return NS_OK; 1.1515 +} 1.1516 + 1.1517 +static void 1.1518 +DetachContainerRecurse(nsIDocShell *aShell) 1.1519 +{ 1.1520 + // Unhook this docshell's presentation 1.1521 + nsCOMPtr<nsIContentViewer> viewer; 1.1522 + aShell->GetContentViewer(getter_AddRefs(viewer)); 1.1523 + if (viewer) { 1.1524 + nsIDocument* doc = viewer->GetDocument(); 1.1525 + if (doc) { 1.1526 + doc->SetContainer(nullptr); 1.1527 + } 1.1528 + nsRefPtr<nsPresContext> pc; 1.1529 + viewer->GetPresContext(getter_AddRefs(pc)); 1.1530 + if (pc) { 1.1531 + pc->Detach(); 1.1532 + } 1.1533 + nsCOMPtr<nsIPresShell> presShell; 1.1534 + viewer->GetPresShell(getter_AddRefs(presShell)); 1.1535 + if (presShell) { 1.1536 + auto weakShell = static_cast<nsDocShell*>(aShell)->asWeakPtr(); 1.1537 + presShell->SetForwardingContainer(weakShell); 1.1538 + } 1.1539 + } 1.1540 + 1.1541 + // Now recurse through the children 1.1542 + int32_t childCount; 1.1543 + aShell->GetChildCount(&childCount); 1.1544 + for (int32_t i = 0; i < childCount; ++i) { 1.1545 + nsCOMPtr<nsIDocShellTreeItem> childItem; 1.1546 + aShell->GetChildAt(i, getter_AddRefs(childItem)); 1.1547 + DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem))); 1.1548 + } 1.1549 +} 1.1550 + 1.1551 +NS_IMETHODIMP 1.1552 +nsDocumentViewer::Destroy() 1.1553 +{ 1.1554 + NS_ASSERTION(mDocument, "No document in Destroy()!"); 1.1555 + 1.1556 +#ifdef NS_PRINTING 1.1557 + // Here is where we check to see if the document was still being prepared 1.1558 + // for printing when it was asked to be destroy from someone externally 1.1559 + // This usually happens if the document is unloaded while the user is in the 1.1560 + // Print Dialog 1.1561 + // 1.1562 + // So we flip the bool to remember that the document is going away 1.1563 + // and we can clean up and abort later after returning from the Print Dialog 1.1564 + if (mPrintEngine) { 1.1565 + if (mPrintEngine->CheckBeforeDestroy()) { 1.1566 + return NS_OK; 1.1567 + } 1.1568 + } 1.1569 + mBeforeAndAfterPrint = nullptr; 1.1570 +#endif 1.1571 + 1.1572 + // Don't let the document get unloaded while we are printing. 1.1573 + // this could happen if we hit the back button during printing. 1.1574 + // We also keep the viewer from being cached in session history, since 1.1575 + // we require all documents there to be sanitized. 1.1576 + if (mDestroyRefCount != 0) { 1.1577 + --mDestroyRefCount; 1.1578 + return NS_OK; 1.1579 + } 1.1580 + 1.1581 + // If we were told to put ourselves into session history instead of destroy 1.1582 + // the presentation, do that now. 1.1583 + if (mSHEntry) { 1.1584 + if (mPresShell) 1.1585 + mPresShell->Freeze(); 1.1586 + 1.1587 + // Make sure the presentation isn't torn down by Hide(). 1.1588 + mSHEntry->SetSticky(mIsSticky); 1.1589 + mIsSticky = true; 1.1590 + 1.1591 + bool savePresentation = mDocument ? mDocument->IsBFCachingAllowed() : true; 1.1592 + 1.1593 + // Remove our root view from the view hierarchy. 1.1594 + if (mPresShell) { 1.1595 + nsViewManager *vm = mPresShell->GetViewManager(); 1.1596 + if (vm) { 1.1597 + nsView *rootView = vm->GetRootView(); 1.1598 + 1.1599 + if (rootView) { 1.1600 + nsView *rootViewParent = rootView->GetParent(); 1.1601 + if (rootViewParent) { 1.1602 + nsViewManager *parentVM = rootViewParent->GetViewManager(); 1.1603 + if (parentVM) { 1.1604 + parentVM->RemoveChild(rootView); 1.1605 + } 1.1606 + } 1.1607 + } 1.1608 + } 1.1609 + } 1.1610 + 1.1611 + Hide(); 1.1612 + 1.1613 + // This is after Hide() so that the user doesn't see the inputs clear. 1.1614 + if (mDocument) { 1.1615 + mDocument->Sanitize(); 1.1616 + } 1.1617 + 1.1618 + // Reverse ownership. Do this *after* calling sanitize so that sanitize 1.1619 + // doesn't cause mutations that make the SHEntry drop the presentation 1.1620 + 1.1621 + // Grab a reference to mSHEntry before calling into things like 1.1622 + // SyncPresentationState that might mess with our members. 1.1623 + nsCOMPtr<nsISHEntry> shEntry = mSHEntry; // we'll need this below 1.1624 + mSHEntry = nullptr; 1.1625 + 1.1626 + if (savePresentation) { 1.1627 + shEntry->SetContentViewer(this); 1.1628 + } 1.1629 + 1.1630 + // Always sync the presentation state. That way even if someone screws up 1.1631 + // and shEntry has no window state at this point we'll be ok; we just won't 1.1632 + // cache ourselves. 1.1633 + shEntry->SyncPresentationState(); 1.1634 + 1.1635 + // Shut down accessibility for the document before we start to tear it down. 1.1636 +#ifdef ACCESSIBILITY 1.1637 + if (mPresShell) { 1.1638 + a11y::DocAccessible* docAcc = mPresShell->GetDocAccessible(); 1.1639 + if (docAcc) { 1.1640 + docAcc->Shutdown(); 1.1641 + } 1.1642 + } 1.1643 +#endif 1.1644 + 1.1645 + // Break the link from the document/presentation to the docshell, so that 1.1646 + // link traversals cannot affect the currently-loaded document. 1.1647 + // When the presentation is restored, Open() and InitInternal() will reset 1.1648 + // these pointers to their original values. 1.1649 + 1.1650 + if (mDocument) { 1.1651 + mDocument->SetContainer(nullptr); 1.1652 + } 1.1653 + if (mPresContext) { 1.1654 + mPresContext->Detach(); 1.1655 + } 1.1656 + if (mPresShell) { 1.1657 + mPresShell->SetForwardingContainer(mContainer); 1.1658 + } 1.1659 + 1.1660 + // Do the same for our children. Note that we need to get the child 1.1661 + // docshells from the SHEntry now; the docshell will have cleared them. 1.1662 + nsCOMPtr<nsIDocShellTreeItem> item; 1.1663 + int32_t itemIndex = 0; 1.1664 + while (NS_SUCCEEDED(shEntry->ChildShellAt(itemIndex++, 1.1665 + getter_AddRefs(item))) && item) { 1.1666 + DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item))); 1.1667 + } 1.1668 + 1.1669 + return NS_OK; 1.1670 + } 1.1671 + 1.1672 + // The document was not put in the bfcache 1.1673 + 1.1674 + if (mPresShell) { 1.1675 + DestroyPresShell(); 1.1676 + } 1.1677 + if (mDocument) { 1.1678 + mDocument->Destroy(); 1.1679 + mDocument = nullptr; 1.1680 + } 1.1681 + 1.1682 + // All callers are supposed to call destroy to break circular 1.1683 + // references. If we do this stuff in the destructor, the 1.1684 + // destructor might never be called (especially if we're being 1.1685 + // used from JS. 1.1686 + 1.1687 +#ifdef NS_PRINTING 1.1688 + if (mPrintEngine) { 1.1689 +#ifdef NS_PRINT_PREVIEW 1.1690 + bool doingPrintPreview; 1.1691 + mPrintEngine->GetDoingPrintPreview(&doingPrintPreview); 1.1692 + if (doingPrintPreview) { 1.1693 + mPrintEngine->FinishPrintPreview(); 1.1694 + } 1.1695 +#endif 1.1696 + 1.1697 + mPrintEngine->Destroy(); 1.1698 + mPrintEngine = nullptr; 1.1699 + } 1.1700 +#endif 1.1701 + 1.1702 + // Avoid leaking the old viewer. 1.1703 + if (mPreviousViewer) { 1.1704 + mPreviousViewer->Destroy(); 1.1705 + mPreviousViewer = nullptr; 1.1706 + } 1.1707 + 1.1708 + mDeviceContext = nullptr; 1.1709 + 1.1710 + if (mPresContext) { 1.1711 + DestroyPresContext(); 1.1712 + } 1.1713 + 1.1714 + mWindow = nullptr; 1.1715 + mViewManager = nullptr; 1.1716 + mContainer = WeakPtr<nsDocShell>(); 1.1717 + 1.1718 + return NS_OK; 1.1719 +} 1.1720 + 1.1721 +NS_IMETHODIMP 1.1722 +nsDocumentViewer::Stop(void) 1.1723 +{ 1.1724 + NS_ASSERTION(mDocument, "Stop called too early or too late"); 1.1725 + if (mDocument) { 1.1726 + mDocument->StopDocumentLoad(); 1.1727 + } 1.1728 + 1.1729 + if (!mHidden && (mLoaded || mStopped) && mPresContext && !mSHEntry) 1.1730 + mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode); 1.1731 + 1.1732 + mStopped = true; 1.1733 + 1.1734 + if (!mLoaded && mPresShell) { 1.1735 + // Well, we might as well paint what we have so far. 1.1736 + nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682 1.1737 + mPresShell->UnsuppressPainting(); 1.1738 + } 1.1739 + 1.1740 + return NS_OK; 1.1741 +} 1.1742 + 1.1743 +NS_IMETHODIMP 1.1744 +nsDocumentViewer::GetDOMDocument(nsIDOMDocument **aResult) 1.1745 +{ 1.1746 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.1747 + return CallQueryInterface(mDocument, aResult); 1.1748 +} 1.1749 + 1.1750 +NS_IMETHODIMP_(nsIDocument *) 1.1751 +nsDocumentViewer::GetDocument() 1.1752 +{ 1.1753 + return mDocument; 1.1754 +} 1.1755 + 1.1756 +NS_IMETHODIMP 1.1757 +nsDocumentViewer::SetDOMDocument(nsIDOMDocument *aDocument) 1.1758 +{ 1.1759 + // Assumptions: 1.1760 + // 1.1761 + // 1) this document viewer has been initialized with a call to Init(). 1.1762 + // 2) the stylesheets associated with the document have been added 1.1763 + // to the document. 1.1764 + 1.1765 + // XXX Right now, this method assumes that the layout of the current 1.1766 + // document hasn't started yet. More cleanup will probably be 1.1767 + // necessary to make this method work for the case when layout *has* 1.1768 + // occurred for the current document. 1.1769 + // That work can happen when and if it is needed. 1.1770 + 1.1771 + if (!aDocument) 1.1772 + return NS_ERROR_NULL_POINTER; 1.1773 + 1.1774 + nsCOMPtr<nsIDocument> newDoc = do_QueryInterface(aDocument); 1.1775 + NS_ENSURE_TRUE(newDoc, NS_ERROR_UNEXPECTED); 1.1776 + 1.1777 + return SetDocumentInternal(newDoc, false); 1.1778 +} 1.1779 + 1.1780 +NS_IMETHODIMP 1.1781 +nsDocumentViewer::SetDocumentInternal(nsIDocument* aDocument, 1.1782 + bool aForceReuseInnerWindow) 1.1783 +{ 1.1784 + MOZ_ASSERT(aDocument); 1.1785 + 1.1786 + // Set new container 1.1787 + aDocument->SetContainer(mContainer); 1.1788 + 1.1789 + if (mDocument != aDocument) { 1.1790 + if (mDocument->IsStaticDocument()) { 1.1791 + mDocument->SetScriptGlobalObject(nullptr); 1.1792 + mDocument->Destroy(); 1.1793 + } 1.1794 + // Replace the old document with the new one. Do this only when 1.1795 + // the new document really is a new document. 1.1796 + mDocument = aDocument; 1.1797 + 1.1798 + // Set the script global object on the new document 1.1799 + nsCOMPtr<nsPIDOMWindow> window = 1.1800 + do_GetInterface(static_cast<nsIDocShell*>(mContainer.get())); 1.1801 + if (window) { 1.1802 + window->SetNewDocument(aDocument, nullptr, aForceReuseInnerWindow); 1.1803 + } 1.1804 + 1.1805 + // Clear the list of old child docshells. Child docshells for the new 1.1806 + // document will be constructed as frames are created. 1.1807 + if (!aDocument->IsStaticDocument()) { 1.1808 + nsCOMPtr<nsIDocShell> node(mContainer); 1.1809 + if (node) { 1.1810 + int32_t count; 1.1811 + node->GetChildCount(&count); 1.1812 + for (int32_t i = 0; i < count; ++i) { 1.1813 + nsCOMPtr<nsIDocShellTreeItem> child; 1.1814 + node->GetChildAt(0, getter_AddRefs(child)); 1.1815 + node->RemoveChild(child); 1.1816 + } 1.1817 + } 1.1818 + } 1.1819 + } 1.1820 + 1.1821 + nsresult rv = SyncParentSubDocMap(); 1.1822 + NS_ENSURE_SUCCESS(rv, rv); 1.1823 + 1.1824 + // Replace the current pres shell with a new shell for the new document 1.1825 + 1.1826 + if (mPresShell) { 1.1827 + DestroyPresShell(); 1.1828 + } 1.1829 + 1.1830 + if (mPresContext) { 1.1831 + DestroyPresContext(); 1.1832 + 1.1833 + mWindow = nullptr; 1.1834 + InitInternal(mParentWidget, nullptr, mBounds, true, true, false); 1.1835 + } 1.1836 + 1.1837 + return rv; 1.1838 +} 1.1839 + 1.1840 +nsIPresShell* 1.1841 +nsDocumentViewer::GetPresShell() 1.1842 +{ 1.1843 + return mPresShell; 1.1844 +} 1.1845 + 1.1846 +nsPresContext* 1.1847 +nsDocumentViewer::GetPresContext() 1.1848 +{ 1.1849 + return mPresContext; 1.1850 +} 1.1851 + 1.1852 +nsViewManager* 1.1853 +nsDocumentViewer::GetViewManager() 1.1854 +{ 1.1855 + return mViewManager; 1.1856 +} 1.1857 + 1.1858 +NS_IMETHODIMP 1.1859 +nsDocumentViewer::GetPresShell(nsIPresShell** aResult) 1.1860 +{ 1.1861 + nsIPresShell* shell = GetPresShell(); 1.1862 + NS_IF_ADDREF(*aResult = shell); 1.1863 + return NS_OK; 1.1864 +} 1.1865 + 1.1866 +NS_IMETHODIMP 1.1867 +nsDocumentViewer::GetPresContext(nsPresContext** aResult) 1.1868 +{ 1.1869 + nsPresContext* pc = GetPresContext(); 1.1870 + NS_IF_ADDREF(*aResult = pc); 1.1871 + return NS_OK; 1.1872 +} 1.1873 + 1.1874 +NS_IMETHODIMP 1.1875 +nsDocumentViewer::GetBounds(nsIntRect& aResult) 1.1876 +{ 1.1877 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.1878 + aResult = mBounds; 1.1879 + return NS_OK; 1.1880 +} 1.1881 + 1.1882 +NS_IMETHODIMP 1.1883 +nsDocumentViewer::GetPreviousViewer(nsIContentViewer** aViewer) 1.1884 +{ 1.1885 + *aViewer = mPreviousViewer; 1.1886 + NS_IF_ADDREF(*aViewer); 1.1887 + return NS_OK; 1.1888 +} 1.1889 + 1.1890 +NS_IMETHODIMP 1.1891 +nsDocumentViewer::SetPreviousViewer(nsIContentViewer* aViewer) 1.1892 +{ 1.1893 + // NOTE: |Show| sets |mPreviousViewer| to null without calling this 1.1894 + // function. 1.1895 + 1.1896 + if (aViewer) { 1.1897 + NS_ASSERTION(!mPreviousViewer, 1.1898 + "can't set previous viewer when there already is one"); 1.1899 + 1.1900 + // In a multiple chaining situation (which occurs when running a thrashing 1.1901 + // test like i-bench or jrgm's tests with no delay), we can build up a 1.1902 + // whole chain of viewers. In order to avoid this, we always set our previous 1.1903 + // viewer to the MOST previous viewer in the chain, and then dump the intermediate 1.1904 + // link from the chain. This ensures that at most only 2 documents are alive 1.1905 + // and undestroyed at any given time (the one that is showing and the one that 1.1906 + // is loading with painting suppressed). 1.1907 + // It's very important that if this ever gets changed the code 1.1908 + // before the RestorePresentation call in nsDocShell::InternalLoad 1.1909 + // be changed accordingly. 1.1910 + nsCOMPtr<nsIContentViewer> prevViewer; 1.1911 + aViewer->GetPreviousViewer(getter_AddRefs(prevViewer)); 1.1912 + if (prevViewer) { 1.1913 + aViewer->SetPreviousViewer(nullptr); 1.1914 + aViewer->Destroy(); 1.1915 + return SetPreviousViewer(prevViewer); 1.1916 + } 1.1917 + } 1.1918 + 1.1919 + mPreviousViewer = aViewer; 1.1920 + return NS_OK; 1.1921 +} 1.1922 + 1.1923 +NS_IMETHODIMP 1.1924 +nsDocumentViewer::SetBounds(const nsIntRect& aBounds) 1.1925 +{ 1.1926 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.1927 + 1.1928 + mBounds = aBounds; 1.1929 + if (mWindow) { 1.1930 + if (!mAttachedToParent) { 1.1931 + // Don't have the widget repaint. Layout will generate repaint requests 1.1932 + // during reflow. 1.1933 + mWindow->Resize(aBounds.x, aBounds.y, 1.1934 + aBounds.width, aBounds.height, 1.1935 + false); 1.1936 + } 1.1937 + } else if (mPresContext && mViewManager) { 1.1938 + int32_t p2a = mPresContext->AppUnitsPerDevPixel(); 1.1939 + mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(mBounds.width, p2a), 1.1940 + NSIntPixelsToAppUnits(mBounds.height, p2a)); 1.1941 + } 1.1942 + 1.1943 + // If there's a previous viewer, it's the one that's actually showing, 1.1944 + // so be sure to resize it as well so it paints over the right area. 1.1945 + // This may slow down the performance of the new page load, but resize 1.1946 + // during load is also probably a relatively unusual condition 1.1947 + // relating to things being hidden while something is loaded. It so 1.1948 + // happens that Firefox does this a good bit with its infobar, and it 1.1949 + // looks ugly if we don't do this. 1.1950 + if (mPreviousViewer) { 1.1951 + nsCOMPtr<nsIContentViewer> previousViewer = mPreviousViewer; 1.1952 + previousViewer->SetBounds(aBounds); 1.1953 + } 1.1954 + 1.1955 + return NS_OK; 1.1956 +} 1.1957 + 1.1958 +NS_IMETHODIMP 1.1959 +nsDocumentViewer::Move(int32_t aX, int32_t aY) 1.1960 +{ 1.1961 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.1962 + mBounds.MoveTo(aX, aY); 1.1963 + if (mWindow) { 1.1964 + mWindow->Move(aX, aY); 1.1965 + } 1.1966 + return NS_OK; 1.1967 +} 1.1968 + 1.1969 +NS_IMETHODIMP 1.1970 +nsDocumentViewer::Show(void) 1.1971 +{ 1.1972 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.1973 + 1.1974 + // We don't need the previous viewer anymore since we're not 1.1975 + // displaying it. 1.1976 + if (mPreviousViewer) { 1.1977 + // This little dance *may* only be to keep 1.1978 + // PresShell::EndObservingDocument happy, but I'm not sure. 1.1979 + nsCOMPtr<nsIContentViewer> prevViewer(mPreviousViewer); 1.1980 + mPreviousViewer = nullptr; 1.1981 + prevViewer->Destroy(); 1.1982 + 1.1983 + // Make sure we don't have too many cached ContentViewers 1.1984 + nsCOMPtr<nsIDocShellTreeItem> treeItem(mContainer); 1.1985 + if (treeItem) { 1.1986 + // We need to find the root DocShell since only that object has an 1.1987 + // SHistory and we need the SHistory to evict content viewers 1.1988 + nsCOMPtr<nsIDocShellTreeItem> root; 1.1989 + treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root)); 1.1990 + nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root); 1.1991 + nsCOMPtr<nsISHistory> history; 1.1992 + webNav->GetSessionHistory(getter_AddRefs(history)); 1.1993 + nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history); 1.1994 + if (historyInt) { 1.1995 + int32_t prevIndex,loadedIndex; 1.1996 + nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem); 1.1997 + docShell->GetPreviousTransIndex(&prevIndex); 1.1998 + docShell->GetLoadedTransIndex(&loadedIndex); 1.1999 +#ifdef DEBUG_PAGE_CACHE 1.2000 + printf("About to evict content viewers: prev=%d, loaded=%d\n", 1.2001 + prevIndex, loadedIndex); 1.2002 +#endif 1.2003 + historyInt->EvictOutOfRangeContentViewers(loadedIndex); 1.2004 + } 1.2005 + } 1.2006 + } 1.2007 + 1.2008 + if (mWindow) { 1.2009 + // When attached to a top level xul window, we do not need to call 1.2010 + // Show on the widget. Underlying window management code handles 1.2011 + // this when the window is initialized. 1.2012 + if (!mAttachedToParent) { 1.2013 + mWindow->Show(true); 1.2014 + } 1.2015 + } 1.2016 + 1.2017 + if (mDocument && !mPresShell) { 1.2018 + NS_ASSERTION(!mWindow, "Window already created but no presshell?"); 1.2019 + 1.2020 + nsCOMPtr<nsIBaseWindow> base_win(mContainer); 1.2021 + if (base_win) { 1.2022 + base_win->GetParentWidget(&mParentWidget); 1.2023 + if (mParentWidget) { 1.2024 + mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak 1.2025 + } 1.2026 + } 1.2027 + 1.2028 + nsView* containerView = FindContainerView(); 1.2029 + 1.2030 + nsresult rv = CreateDeviceContext(containerView); 1.2031 + NS_ENSURE_SUCCESS(rv, rv); 1.2032 + 1.2033 + // Create presentation context 1.2034 + NS_ASSERTION(!mPresContext, "Shouldn't have a prescontext if we have no shell!"); 1.2035 + mPresContext = CreatePresContext(mDocument, 1.2036 + nsPresContext::eContext_Galley, containerView); 1.2037 + NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY); 1.2038 + 1.2039 + rv = mPresContext->Init(mDeviceContext); 1.2040 + if (NS_FAILED(rv)) { 1.2041 + mPresContext = nullptr; 1.2042 + return rv; 1.2043 + } 1.2044 + 1.2045 + rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width), 1.2046 + mPresContext->DevPixelsToAppUnits(mBounds.height)), 1.2047 + containerView); 1.2048 + if (NS_FAILED(rv)) 1.2049 + return rv; 1.2050 + 1.2051 + if (mPresContext && base_win) { 1.2052 + nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win)); 1.2053 + 1.2054 + if (linkHandler) { 1.2055 + mPresContext->SetLinkHandler(linkHandler); 1.2056 + } 1.2057 + 1.2058 + mPresContext->SetContainer(mContainer); 1.2059 + } 1.2060 + 1.2061 + if (mPresContext) { 1.2062 + Hide(); 1.2063 + 1.2064 + rv = InitPresentationStuff(mDocument->MayStartLayout()); 1.2065 + } 1.2066 + 1.2067 + // If we get here the document load has already started and the 1.2068 + // window is shown because some JS on the page caused it to be 1.2069 + // shown... 1.2070 + 1.2071 + if (mPresShell) { 1.2072 + nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682 1.2073 + mPresShell->UnsuppressPainting(); 1.2074 + } 1.2075 + } 1.2076 + 1.2077 + // Notify observers that a new page has been shown. This will get run 1.2078 + // from the event loop after we actually draw the page. 1.2079 + NS_DispatchToMainThread(new nsDocumentShownDispatcher(mDocument)); 1.2080 + 1.2081 + return NS_OK; 1.2082 +} 1.2083 + 1.2084 +NS_IMETHODIMP 1.2085 +nsDocumentViewer::Hide(void) 1.2086 +{ 1.2087 + if (!mAttachedToParent && mWindow) { 1.2088 + mWindow->Show(false); 1.2089 + } 1.2090 + 1.2091 + if (!mPresShell) 1.2092 + return NS_OK; 1.2093 + 1.2094 + NS_ASSERTION(mPresContext, "Can't have a presshell and no prescontext!"); 1.2095 + 1.2096 + // Avoid leaking the old viewer. 1.2097 + if (mPreviousViewer) { 1.2098 + mPreviousViewer->Destroy(); 1.2099 + mPreviousViewer = nullptr; 1.2100 + } 1.2101 + 1.2102 + if (mIsSticky) { 1.2103 + // This window is sticky, that means that it might be shown again 1.2104 + // and we don't want the presshell n' all that to be thrown away 1.2105 + // just because the window is hidden. 1.2106 + 1.2107 + return NS_OK; 1.2108 + } 1.2109 + 1.2110 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.2111 + if (docShell) { 1.2112 + nsCOMPtr<nsILayoutHistoryState> layoutState; 1.2113 + mPresShell->CaptureHistoryState(getter_AddRefs(layoutState)); 1.2114 + } 1.2115 + 1.2116 + DestroyPresShell(); 1.2117 + 1.2118 + DestroyPresContext(); 1.2119 + 1.2120 + mViewManager = nullptr; 1.2121 + mWindow = nullptr; 1.2122 + mDeviceContext = nullptr; 1.2123 + mParentWidget = nullptr; 1.2124 + 1.2125 + nsCOMPtr<nsIBaseWindow> base_win(mContainer); 1.2126 + 1.2127 + if (base_win && !mAttachedToParent) { 1.2128 + base_win->SetParentWidget(nullptr); 1.2129 + } 1.2130 + 1.2131 + return NS_OK; 1.2132 +} 1.2133 + 1.2134 +NS_IMETHODIMP 1.2135 +nsDocumentViewer::GetSticky(bool *aSticky) 1.2136 +{ 1.2137 + *aSticky = mIsSticky; 1.2138 + 1.2139 + return NS_OK; 1.2140 +} 1.2141 + 1.2142 +NS_IMETHODIMP 1.2143 +nsDocumentViewer::SetSticky(bool aSticky) 1.2144 +{ 1.2145 + mIsSticky = aSticky; 1.2146 + 1.2147 + return NS_OK; 1.2148 +} 1.2149 + 1.2150 +NS_IMETHODIMP 1.2151 +nsDocumentViewer::RequestWindowClose(bool* aCanClose) 1.2152 +{ 1.2153 +#ifdef NS_PRINTING 1.2154 + if (mPrintIsPending || (mPrintEngine && mPrintEngine->GetIsPrinting())) { 1.2155 + *aCanClose = false; 1.2156 + mDeferredWindowClose = true; 1.2157 + } else 1.2158 +#endif 1.2159 + *aCanClose = true; 1.2160 + 1.2161 + return NS_OK; 1.2162 +} 1.2163 + 1.2164 +static bool 1.2165 +AppendAgentSheet(nsIStyleSheet *aSheet, void *aData) 1.2166 +{ 1.2167 + nsStyleSet *styleSet = static_cast<nsStyleSet*>(aData); 1.2168 + styleSet->AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet); 1.2169 + return true; 1.2170 +} 1.2171 + 1.2172 +static bool 1.2173 +PrependUserSheet(nsIStyleSheet *aSheet, void *aData) 1.2174 +{ 1.2175 + nsStyleSet *styleSet = static_cast<nsStyleSet*>(aData); 1.2176 + styleSet->PrependStyleSheet(nsStyleSet::eUserSheet, aSheet); 1.2177 + return true; 1.2178 +} 1.2179 + 1.2180 +nsresult 1.2181 +nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument, 1.2182 + nsStyleSet** aStyleSet) 1.2183 +{ 1.2184 + // Make sure this does the same thing as PresShell::AddSheet wrt ordering. 1.2185 + 1.2186 + // this should eventually get expanded to allow for creating 1.2187 + // different sets for different media 1.2188 + nsStyleSet *styleSet = new nsStyleSet(); 1.2189 + 1.2190 + styleSet->BeginUpdate(); 1.2191 + 1.2192 + // The document will fill in the document sheets when we create the presshell 1.2193 + 1.2194 + // Handle the user sheets. 1.2195 + nsCSSStyleSheet* sheet = nullptr; 1.2196 + if (nsContentUtils::IsInChromeDocshell(aDocument)) { 1.2197 + sheet = nsLayoutStylesheetCache::UserChromeSheet(); 1.2198 + } 1.2199 + else { 1.2200 + sheet = nsLayoutStylesheetCache::UserContentSheet(); 1.2201 + } 1.2202 + 1.2203 + if (sheet) 1.2204 + styleSet->AppendStyleSheet(nsStyleSet::eUserSheet, sheet); 1.2205 + 1.2206 + // Append chrome sheets (scrollbars + forms). 1.2207 + bool shouldOverride = false; 1.2208 + // We don't want a docshell here for external resource docs, so just 1.2209 + // look at mContainer. 1.2210 + nsCOMPtr<nsIDocShell> ds(mContainer); 1.2211 + nsCOMPtr<nsIDOMEventTarget> chromeHandler; 1.2212 + nsCOMPtr<nsIURI> uri; 1.2213 + nsRefPtr<nsCSSStyleSheet> csssheet; 1.2214 + 1.2215 + if (ds) { 1.2216 + ds->GetChromeEventHandler(getter_AddRefs(chromeHandler)); 1.2217 + } 1.2218 + if (chromeHandler) { 1.2219 + nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler)); 1.2220 + nsCOMPtr<nsIContent> content(do_QueryInterface(elt)); 1.2221 + if (elt && content) { 1.2222 + nsCOMPtr<nsIURI> baseURI = content->GetBaseURI(); 1.2223 + 1.2224 + nsAutoString sheets; 1.2225 + elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets); 1.2226 + if (!sheets.IsEmpty() && baseURI) { 1.2227 + nsRefPtr<mozilla::css::Loader> cssLoader = new mozilla::css::Loader(); 1.2228 + 1.2229 + char *str = ToNewCString(sheets); 1.2230 + char *newStr = str; 1.2231 + char *token; 1.2232 + while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) { 1.2233 + NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nullptr, 1.2234 + baseURI); 1.2235 + if (!uri) continue; 1.2236 + 1.2237 + cssLoader->LoadSheetSync(uri, getter_AddRefs(csssheet)); 1.2238 + if (!csssheet) continue; 1.2239 + 1.2240 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, csssheet); 1.2241 + shouldOverride = true; 1.2242 + } 1.2243 + nsMemory::Free(str); 1.2244 + } 1.2245 + } 1.2246 + } 1.2247 + 1.2248 + if (!shouldOverride) { 1.2249 + sheet = nsLayoutStylesheetCache::ScrollbarsSheet(); 1.2250 + if (sheet) { 1.2251 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet); 1.2252 + } 1.2253 + } 1.2254 + 1.2255 + sheet = nsLayoutStylesheetCache::NumberControlSheet(); 1.2256 + if (sheet) { 1.2257 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet); 1.2258 + } 1.2259 + 1.2260 + sheet = nsLayoutStylesheetCache::FormsSheet(); 1.2261 + if (sheet) { 1.2262 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet); 1.2263 + } 1.2264 + 1.2265 + sheet = nsLayoutStylesheetCache::FullScreenOverrideSheet(); 1.2266 + if (sheet) { 1.2267 + styleSet->PrependStyleSheet(nsStyleSet::eOverrideSheet, sheet); 1.2268 + } 1.2269 + 1.2270 + // Make sure to clone the quirk sheet so that it can be usefully 1.2271 + // enabled/disabled as needed. 1.2272 + nsRefPtr<nsCSSStyleSheet> quirkClone; 1.2273 + nsCSSStyleSheet* quirkSheet; 1.2274 + if (!nsLayoutStylesheetCache::UASheet() || 1.2275 + !(quirkSheet = nsLayoutStylesheetCache::QuirkSheet()) || 1.2276 + !(quirkClone = quirkSheet->Clone(nullptr, nullptr, nullptr, nullptr)) || 1.2277 + !sheet) { 1.2278 + delete styleSet; 1.2279 + return NS_ERROR_OUT_OF_MEMORY; 1.2280 + } 1.2281 + // quirk.css needs to come after the regular UA sheet (or more precisely, 1.2282 + // after the html.css and so forth that the UA sheet imports). 1.2283 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, quirkClone); 1.2284 + styleSet->SetQuirkStyleSheet(quirkClone); 1.2285 + styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, 1.2286 + nsLayoutStylesheetCache::UASheet()); 1.2287 + 1.2288 + nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance(); 1.2289 + if (sheetService) { 1.2290 + sheetService->AgentStyleSheets()->EnumerateForwards(AppendAgentSheet, 1.2291 + styleSet); 1.2292 + sheetService->UserStyleSheets()->EnumerateBackwards(PrependUserSheet, 1.2293 + styleSet); 1.2294 + } 1.2295 + 1.2296 + // Caller will handle calling EndUpdate, per contract. 1.2297 + *aStyleSet = styleSet; 1.2298 + return NS_OK; 1.2299 +} 1.2300 + 1.2301 +NS_IMETHODIMP 1.2302 +nsDocumentViewer::ClearHistoryEntry() 1.2303 +{ 1.2304 + mSHEntry = nullptr; 1.2305 + return NS_OK; 1.2306 +} 1.2307 + 1.2308 +//------------------------------------------------------- 1.2309 + 1.2310 +nsresult 1.2311 +nsDocumentViewer::MakeWindow(const nsSize& aSize, nsView* aContainerView) 1.2312 +{ 1.2313 + if (GetIsPrintPreview()) 1.2314 + return NS_OK; 1.2315 + 1.2316 + bool shouldAttach = ShouldAttachToTopLevel(); 1.2317 + 1.2318 + if (shouldAttach) { 1.2319 + // If the old view is already attached to our parent, detach 1.2320 + DetachFromTopLevelWidget(); 1.2321 + } 1.2322 + 1.2323 + mViewManager = new nsViewManager(); 1.2324 + 1.2325 + nsDeviceContext *dx = mPresContext->DeviceContext(); 1.2326 + 1.2327 + nsresult rv = mViewManager->Init(dx); 1.2328 + if (NS_FAILED(rv)) 1.2329 + return rv; 1.2330 + 1.2331 + // The root view is always at 0,0. 1.2332 + nsRect tbounds(nsPoint(0, 0), aSize); 1.2333 + // Create a view 1.2334 + nsView* view = mViewManager->CreateView(tbounds, aContainerView); 1.2335 + if (!view) 1.2336 + return NS_ERROR_OUT_OF_MEMORY; 1.2337 + 1.2338 + // Create a widget if we were given a parent widget or don't have a 1.2339 + // container view that we can hook up to without a widget. 1.2340 + // Don't create widgets for ResourceDocs (external resources & svg images), 1.2341 + // because when they're displayed, they're painted into *another* document's 1.2342 + // widget. 1.2343 + if (!mDocument->IsResourceDoc() && 1.2344 + (mParentWidget || !aContainerView)) { 1.2345 + // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone. 1.2346 + // otherwise the view will find its own parent widget and "do the right thing" to 1.2347 + // establish a parent/child widget relationship 1.2348 + nsWidgetInitData initData; 1.2349 + nsWidgetInitData* initDataPtr; 1.2350 + if (!mParentWidget) { 1.2351 + initDataPtr = &initData; 1.2352 + initData.mWindowType = eWindowType_invisible; 1.2353 + } else { 1.2354 + initDataPtr = nullptr; 1.2355 + } 1.2356 + 1.2357 + if (shouldAttach) { 1.2358 + // Reuse the top level parent widget. 1.2359 + rv = view->AttachToTopLevelWidget(mParentWidget); 1.2360 + mAttachedToParent = true; 1.2361 + } 1.2362 + else if (!aContainerView && mParentWidget) { 1.2363 + rv = view->CreateWidgetForParent(mParentWidget, initDataPtr, 1.2364 + true, false); 1.2365 + } 1.2366 + else { 1.2367 + rv = view->CreateWidget(initDataPtr, true, false); 1.2368 + } 1.2369 + if (NS_FAILED(rv)) 1.2370 + return rv; 1.2371 + } 1.2372 + 1.2373 + // Setup hierarchical relationship in view manager 1.2374 + mViewManager->SetRootView(view); 1.2375 + 1.2376 + mWindow = view->GetWidget(); 1.2377 + 1.2378 + // This SetFocus is necessary so the Arrow Key and Page Key events 1.2379 + // go to the scrolled view as soon as the Window is created instead of going to 1.2380 + // the browser window (this enables keyboard scrolling of the document) 1.2381 + // mWindow->SetFocus(); 1.2382 + 1.2383 + return rv; 1.2384 +} 1.2385 + 1.2386 +void 1.2387 +nsDocumentViewer::DetachFromTopLevelWidget() 1.2388 +{ 1.2389 + if (mViewManager) { 1.2390 + nsView* oldView = mViewManager->GetRootView(); 1.2391 + if (oldView && oldView->IsAttachedToTopLevel()) { 1.2392 + oldView->DetachFromTopLevelWidget(); 1.2393 + } 1.2394 + } 1.2395 + mAttachedToParent = false; 1.2396 +} 1.2397 + 1.2398 +nsView* 1.2399 +nsDocumentViewer::FindContainerView() 1.2400 +{ 1.2401 + nsView* containerView = nullptr; 1.2402 + 1.2403 + if (mContainer) { 1.2404 + nsCOMPtr<nsIDocShellTreeItem> docShellItem(mContainer); 1.2405 + nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(docShellItem)); 1.2406 + if (pwin) { 1.2407 + nsCOMPtr<nsIContent> containerElement = do_QueryInterface(pwin->GetFrameElementInternal()); 1.2408 + if (!containerElement) { 1.2409 + return nullptr; 1.2410 + } 1.2411 + nsCOMPtr<nsIPresShell> parentPresShell; 1.2412 + if (docShellItem) { 1.2413 + nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem; 1.2414 + docShellItem->GetParent(getter_AddRefs(parentDocShellItem)); 1.2415 + if (parentDocShellItem) { 1.2416 + nsCOMPtr<nsIDocShell> parentDocShell = do_QueryInterface(parentDocShellItem); 1.2417 + parentPresShell = parentDocShell->GetPresShell(); 1.2418 + } 1.2419 + } 1.2420 + if (!parentPresShell) { 1.2421 + nsCOMPtr<nsIDocument> parentDoc = containerElement->GetCurrentDoc(); 1.2422 + if (parentDoc) { 1.2423 + parentPresShell = parentDoc->GetShell(); 1.2424 + } 1.2425 + } 1.2426 + if (!parentPresShell) { 1.2427 + NS_WARNING("Subdocument container has no presshell"); 1.2428 + } else { 1.2429 + nsIFrame* f = parentPresShell->GetRealPrimaryFrameFor(containerElement); 1.2430 + if (f) { 1.2431 + nsIFrame* subdocFrame = f->GetContentInsertionFrame(); 1.2432 + // subdocFrame might not be a subdocument frame; the frame 1.2433 + // constructor can treat a <frame> as an inline in some XBL 1.2434 + // cases. Treat that as display:none, the document is not 1.2435 + // displayed. 1.2436 + if (subdocFrame->GetType() == nsGkAtoms::subDocumentFrame) { 1.2437 + NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views"); 1.2438 + nsView* innerView = 1.2439 + static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView(); 1.2440 + containerView = innerView; 1.2441 + } else { 1.2442 + NS_WARNING("Subdocument container has non-subdocument frame"); 1.2443 + } 1.2444 + } else { 1.2445 + NS_WARNING("Subdocument container has no frame"); 1.2446 + } 1.2447 + } 1.2448 + } 1.2449 + } 1.2450 + 1.2451 + return containerView; 1.2452 +} 1.2453 + 1.2454 +nsresult 1.2455 +nsDocumentViewer::CreateDeviceContext(nsView* aContainerView) 1.2456 +{ 1.2457 + NS_PRECONDITION(!mPresShell && !mWindow, 1.2458 + "This will screw up our existing presentation"); 1.2459 + NS_PRECONDITION(mDocument, "Gotta have a document here"); 1.2460 + 1.2461 + nsIDocument* doc = mDocument->GetDisplayDocument(); 1.2462 + if (doc) { 1.2463 + NS_ASSERTION(!aContainerView, "External resource document embedded somewhere?"); 1.2464 + // We want to use our display document's device context if possible 1.2465 + nsIPresShell* shell = doc->GetShell(); 1.2466 + if (shell) { 1.2467 + nsPresContext* ctx = shell->GetPresContext(); 1.2468 + if (ctx) { 1.2469 + mDeviceContext = ctx->DeviceContext(); 1.2470 + return NS_OK; 1.2471 + } 1.2472 + } 1.2473 + } 1.2474 + 1.2475 + // Create a device context even if we already have one, since our widget 1.2476 + // might have changed. 1.2477 + nsIWidget* widget = nullptr; 1.2478 + if (aContainerView) { 1.2479 + widget = aContainerView->GetNearestWidget(nullptr); 1.2480 + } 1.2481 + if (!widget) { 1.2482 + widget = mParentWidget; 1.2483 + } 1.2484 + if (widget) { 1.2485 + widget = widget->GetTopLevelWidget(); 1.2486 + } 1.2487 + 1.2488 + mDeviceContext = new nsDeviceContext(); 1.2489 + mDeviceContext->Init(widget); 1.2490 + return NS_OK; 1.2491 +} 1.2492 + 1.2493 +// Return the selection for the document. Note that text fields have their 1.2494 +// own selection, which cannot be accessed with this method. 1.2495 +nsresult nsDocumentViewer::GetDocumentSelection(nsISelection **aSelection) 1.2496 +{ 1.2497 + NS_ENSURE_ARG_POINTER(aSelection); 1.2498 + if (!mPresShell) { 1.2499 + return NS_ERROR_NOT_INITIALIZED; 1.2500 + } 1.2501 + 1.2502 + nsCOMPtr<nsISelectionController> selcon; 1.2503 + selcon = do_QueryInterface(mPresShell); 1.2504 + if (selcon) 1.2505 + return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, 1.2506 + aSelection); 1.2507 + return NS_ERROR_FAILURE; 1.2508 +} 1.2509 + 1.2510 +/* ======================================================================================== 1.2511 + * nsIContentViewerEdit 1.2512 + * ======================================================================================== */ 1.2513 + 1.2514 +NS_IMETHODIMP nsDocumentViewer::ClearSelection() 1.2515 +{ 1.2516 + nsresult rv; 1.2517 + nsCOMPtr<nsISelection> selection; 1.2518 + 1.2519 + // use nsCopySupport::GetSelectionForCopy() ? 1.2520 + rv = GetDocumentSelection(getter_AddRefs(selection)); 1.2521 + if (NS_FAILED(rv)) return rv; 1.2522 + 1.2523 + return selection->CollapseToStart(); 1.2524 +} 1.2525 + 1.2526 +NS_IMETHODIMP nsDocumentViewer::SelectAll() 1.2527 +{ 1.2528 + // XXX this is a temporary implementation copied from nsWebShell 1.2529 + // for now. I think nsDocument and friends should have some helper 1.2530 + // functions to make this easier. 1.2531 + nsCOMPtr<nsISelection> selection; 1.2532 + nsresult rv; 1.2533 + 1.2534 + // use nsCopySupport::GetSelectionForCopy() ? 1.2535 + rv = GetDocumentSelection(getter_AddRefs(selection)); 1.2536 + if (NS_FAILED(rv)) return rv; 1.2537 + 1.2538 + nsCOMPtr<nsIDOMHTMLDocument> htmldoc = do_QueryInterface(mDocument); 1.2539 + nsCOMPtr<nsIDOMNode> bodyNode; 1.2540 + 1.2541 + if (htmldoc) 1.2542 + { 1.2543 + nsCOMPtr<nsIDOMHTMLElement>bodyElement; 1.2544 + rv = htmldoc->GetBody(getter_AddRefs(bodyElement)); 1.2545 + if (NS_FAILED(rv) || !bodyElement) return rv; 1.2546 + 1.2547 + bodyNode = do_QueryInterface(bodyElement); 1.2548 + } 1.2549 + else if (mDocument) 1.2550 + { 1.2551 + bodyNode = do_QueryInterface(mDocument->GetRootElement()); 1.2552 + } 1.2553 + if (!bodyNode) return NS_ERROR_FAILURE; 1.2554 + 1.2555 + rv = selection->RemoveAllRanges(); 1.2556 + if (NS_FAILED(rv)) return rv; 1.2557 + 1.2558 + rv = selection->SelectAllChildren(bodyNode); 1.2559 + return rv; 1.2560 +} 1.2561 + 1.2562 +NS_IMETHODIMP nsDocumentViewer::CopySelection() 1.2563 +{ 1.2564 + nsCopySupport::FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, mPresShell, nullptr); 1.2565 + return NS_OK; 1.2566 +} 1.2567 + 1.2568 +NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation() 1.2569 +{ 1.2570 + NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED); 1.2571 + nsCOMPtr<nsIDOMNode> node; 1.2572 + GetPopupLinkNode(getter_AddRefs(node)); 1.2573 + // make noise if we're not in a link 1.2574 + NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); 1.2575 + 1.2576 + nsCOMPtr<dom::Element> elm(do_QueryInterface(node)); 1.2577 + NS_ENSURE_TRUE(elm, NS_ERROR_FAILURE); 1.2578 + 1.2579 + nsAutoString locationText; 1.2580 + nsContentUtils::GetLinkLocation(elm, locationText); 1.2581 + if (locationText.IsEmpty()) 1.2582 + return NS_ERROR_FAILURE; 1.2583 + 1.2584 + nsresult rv = NS_OK; 1.2585 + nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv)); 1.2586 + NS_ENSURE_SUCCESS(rv, rv); 1.2587 + 1.2588 + // copy the href onto the clipboard 1.2589 + nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument); 1.2590 + return clipboard->CopyString(locationText, doc); 1.2591 +} 1.2592 + 1.2593 +NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags) 1.2594 +{ 1.2595 + NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED); 1.2596 + nsCOMPtr<nsIImageLoadingContent> node; 1.2597 + GetPopupImageNode(getter_AddRefs(node)); 1.2598 + // make noise if we're not in an image 1.2599 + NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); 1.2600 + 1.2601 + nsCOMPtr<nsILoadContext> loadContext(mContainer); 1.2602 + return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags); 1.2603 +} 1.2604 + 1.2605 + 1.2606 +NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool *aCopyable) 1.2607 +{ 1.2608 + NS_ENSURE_ARG_POINTER(aCopyable); 1.2609 + *aCopyable = nsCopySupport::CanCopy(mDocument); 1.2610 + return NS_OK; 1.2611 +} 1.2612 + 1.2613 +/* AString getContents (in string mimeType, in boolean selectionOnly); */ 1.2614 +NS_IMETHODIMP nsDocumentViewer::GetContents(const char *mimeType, bool selectionOnly, nsAString& aOutValue) 1.2615 +{ 1.2616 + aOutValue.Truncate(); 1.2617 + 1.2618 + NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED); 1.2619 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED); 1.2620 + 1.2621 + // Now we have the selection. Make sure it's nonzero: 1.2622 + nsCOMPtr<nsISelection> sel; 1.2623 + if (selectionOnly) { 1.2624 + nsCopySupport::GetSelectionForCopy(mDocument, getter_AddRefs(sel)); 1.2625 + NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE); 1.2626 + 1.2627 + bool isCollapsed; 1.2628 + sel->GetIsCollapsed(&isCollapsed); 1.2629 + if (isCollapsed) 1.2630 + return NS_OK; 1.2631 + } 1.2632 + 1.2633 + // call the copy code 1.2634 + return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel, 1.2635 + mDocument, aOutValue); 1.2636 +} 1.2637 + 1.2638 +/* readonly attribute boolean canGetContents; */ 1.2639 +NS_IMETHODIMP nsDocumentViewer::GetCanGetContents(bool *aCanGetContents) 1.2640 +{ 1.2641 + NS_ENSURE_ARG_POINTER(aCanGetContents); 1.2642 + *aCanGetContents = false; 1.2643 + NS_ENSURE_STATE(mDocument); 1.2644 + *aCanGetContents = nsCopySupport::CanCopy(mDocument); 1.2645 + return NS_OK; 1.2646 +} 1.2647 + 1.2648 + 1.2649 +/* ======================================================================================== 1.2650 + * nsIContentViewerFile 1.2651 + * ======================================================================================== */ 1.2652 +/** --------------------------------------------------- 1.2653 + * See documentation above in the nsIContentViewerfile class definition 1.2654 + * @update 01/24/00 dwc 1.2655 + */ 1.2656 +NS_IMETHODIMP 1.2657 +nsDocumentViewer::Print(bool aSilent, 1.2658 + FILE * aDebugFile, 1.2659 + nsIPrintSettings* aPrintSettings) 1.2660 +{ 1.2661 +#ifdef NS_PRINTING 1.2662 + nsCOMPtr<nsIPrintSettings> printSettings; 1.2663 + 1.2664 +#ifdef DEBUG 1.2665 + nsresult rv = NS_ERROR_FAILURE; 1.2666 + 1.2667 + mDebugFile = aDebugFile; 1.2668 + // if they don't pass in a PrintSettings, then make one 1.2669 + // it will have all the default values 1.2670 + printSettings = aPrintSettings; 1.2671 + nsCOMPtr<nsIPrintOptions> printOptions = do_GetService(sPrintOptionsContractID, &rv); 1.2672 + if (NS_SUCCEEDED(rv)) { 1.2673 + // if they don't pass in a PrintSettings, then make one 1.2674 + if (printSettings == nullptr) { 1.2675 + printOptions->CreatePrintSettings(getter_AddRefs(printSettings)); 1.2676 + } 1.2677 + NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!"); 1.2678 + } 1.2679 + if (printSettings) printSettings->SetPrintSilent(aSilent); 1.2680 + if (printSettings) printSettings->SetShowPrintProgress(false); 1.2681 +#endif 1.2682 + 1.2683 + 1.2684 + return Print(printSettings, nullptr); 1.2685 +#else 1.2686 + return NS_ERROR_FAILURE; 1.2687 +#endif 1.2688 +} 1.2689 + 1.2690 +// nsIContentViewerFile interface 1.2691 +NS_IMETHODIMP 1.2692 +nsDocumentViewer::GetPrintable(bool *aPrintable) 1.2693 +{ 1.2694 + NS_ENSURE_ARG_POINTER(aPrintable); 1.2695 + 1.2696 + *aPrintable = !GetIsPrinting(); 1.2697 + 1.2698 + return NS_OK; 1.2699 +} 1.2700 + 1.2701 +//***************************************************************************** 1.2702 +// nsIMarkupDocumentViewer 1.2703 +//***************************************************************************** 1.2704 + 1.2705 +NS_IMETHODIMP nsDocumentViewer::ScrollToNode(nsIDOMNode* aNode) 1.2706 +{ 1.2707 + NS_ENSURE_ARG(aNode); 1.2708 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.2709 + nsCOMPtr<nsIPresShell> presShell; 1.2710 + NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE); 1.2711 + 1.2712 + // Get the nsIContent interface, because that's what we need to 1.2713 + // get the primary frame 1.2714 + 1.2715 + nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); 1.2716 + NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); 1.2717 + 1.2718 + // Tell the PresShell to scroll to the primary frame of the content. 1.2719 + NS_ENSURE_SUCCESS( 1.2720 + presShell->ScrollContentIntoView(content, 1.2721 + nsIPresShell::ScrollAxis( 1.2722 + nsIPresShell::SCROLL_TOP, 1.2723 + nsIPresShell::SCROLL_ALWAYS), 1.2724 + nsIPresShell::ScrollAxis(), 1.2725 + nsIPresShell::SCROLL_OVERFLOW_HIDDEN), 1.2726 + NS_ERROR_FAILURE); 1.2727 + return NS_OK; 1.2728 +} 1.2729 + 1.2730 +void 1.2731 +nsDocumentViewer::CallChildren(CallChildFunc aFunc, void* aClosure) 1.2732 +{ 1.2733 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.2734 + if (docShell) 1.2735 + { 1.2736 + int32_t i; 1.2737 + int32_t n; 1.2738 + docShell->GetChildCount(&n); 1.2739 + for (i=0; i < n; i++) 1.2740 + { 1.2741 + nsCOMPtr<nsIDocShellTreeItem> child; 1.2742 + docShell->GetChildAt(i, getter_AddRefs(child)); 1.2743 + nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child)); 1.2744 + NS_ASSERTION(childAsShell, "null child in docshell"); 1.2745 + if (childAsShell) 1.2746 + { 1.2747 + nsCOMPtr<nsIContentViewer> childCV; 1.2748 + childAsShell->GetContentViewer(getter_AddRefs(childCV)); 1.2749 + if (childCV) 1.2750 + { 1.2751 + nsCOMPtr<nsIMarkupDocumentViewer> markupCV = do_QueryInterface(childCV); 1.2752 + if (markupCV) { 1.2753 + (*aFunc)(markupCV, aClosure); 1.2754 + } 1.2755 + } 1.2756 + } 1.2757 + } 1.2758 + } 1.2759 +} 1.2760 + 1.2761 +struct LineBoxInfo 1.2762 +{ 1.2763 + nscoord mMaxLineBoxWidth; 1.2764 +}; 1.2765 + 1.2766 +static void 1.2767 +ChangeChildPaintingEnabled(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.2768 +{ 1.2769 + bool* enablePainting = (bool*) aClosure; 1.2770 + if (*enablePainting) { 1.2771 + aChild->ResumePainting(); 1.2772 + } else { 1.2773 + aChild->PausePainting(); 1.2774 + } 1.2775 +} 1.2776 + 1.2777 +static void 1.2778 +ChangeChildMaxLineBoxWidth(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.2779 +{ 1.2780 + struct LineBoxInfo* lbi = (struct LineBoxInfo*) aClosure; 1.2781 + aChild->ChangeMaxLineBoxWidth(lbi->mMaxLineBoxWidth); 1.2782 +} 1.2783 + 1.2784 +struct ZoomInfo 1.2785 +{ 1.2786 + float mZoom; 1.2787 +}; 1.2788 + 1.2789 +static void 1.2790 +SetChildTextZoom(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.2791 +{ 1.2792 + struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure; 1.2793 + aChild->SetTextZoom(ZoomInfo->mZoom); 1.2794 +} 1.2795 + 1.2796 +static void 1.2797 +SetChildMinFontSize(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.2798 +{ 1.2799 + nsCOMPtr<nsIMarkupDocumentViewer> branch = 1.2800 + do_QueryInterface(aChild); 1.2801 + branch->SetMinFontSize(NS_PTR_TO_INT32(aClosure)); 1.2802 +} 1.2803 + 1.2804 +static void 1.2805 +SetChildFullZoom(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.2806 +{ 1.2807 + struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure; 1.2808 + aChild->SetFullZoom(ZoomInfo->mZoom); 1.2809 +} 1.2810 + 1.2811 +static bool 1.2812 +SetExtResourceTextZoom(nsIDocument* aDocument, void* aClosure) 1.2813 +{ 1.2814 + // Would it be better to enumerate external resource viewers instead? 1.2815 + nsIPresShell* shell = aDocument->GetShell(); 1.2816 + if (shell) { 1.2817 + nsPresContext* ctxt = shell->GetPresContext(); 1.2818 + if (ctxt) { 1.2819 + struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure); 1.2820 + ctxt->SetTextZoom(ZoomInfo->mZoom); 1.2821 + } 1.2822 + } 1.2823 + 1.2824 + return true; 1.2825 +} 1.2826 + 1.2827 +static bool 1.2828 +SetExtResourceMinFontSize(nsIDocument* aDocument, void* aClosure) 1.2829 +{ 1.2830 + nsIPresShell* shell = aDocument->GetShell(); 1.2831 + if (shell) { 1.2832 + nsPresContext* ctxt = shell->GetPresContext(); 1.2833 + if (ctxt) { 1.2834 + ctxt->SetBaseMinFontSize(NS_PTR_TO_INT32(aClosure)); 1.2835 + } 1.2836 + } 1.2837 + 1.2838 + return true; 1.2839 +} 1.2840 + 1.2841 +static bool 1.2842 +SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure) 1.2843 +{ 1.2844 + // Would it be better to enumerate external resource viewers instead? 1.2845 + nsIPresShell* shell = aDocument->GetShell(); 1.2846 + if (shell) { 1.2847 + nsPresContext* ctxt = shell->GetPresContext(); 1.2848 + if (ctxt) { 1.2849 + struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure); 1.2850 + ctxt->SetFullZoom(ZoomInfo->mZoom); 1.2851 + } 1.2852 + } 1.2853 + 1.2854 + return true; 1.2855 +} 1.2856 + 1.2857 +NS_IMETHODIMP 1.2858 +nsDocumentViewer::SetTextZoom(float aTextZoom) 1.2859 +{ 1.2860 + // If we don't have a document, then we need to bail. 1.2861 + if (!mDocument) { 1.2862 + return NS_ERROR_FAILURE; 1.2863 + } 1.2864 + 1.2865 + if (GetIsPrintPreview()) { 1.2866 + return NS_OK; 1.2867 + } 1.2868 + 1.2869 + mTextZoom = aTextZoom; 1.2870 + 1.2871 + // Set the text zoom on all children of mContainer (even if our zoom didn't 1.2872 + // change, our children's zoom may be different, though it would be unusual). 1.2873 + // Do this first, in case kids are auto-sizing and post reflow commands on 1.2874 + // our presshell (which should be subsumed into our own style change reflow). 1.2875 + struct ZoomInfo ZoomInfo = { aTextZoom }; 1.2876 + CallChildren(SetChildTextZoom, &ZoomInfo); 1.2877 + 1.2878 + // Now change our own zoom 1.2879 + nsPresContext* pc = GetPresContext(); 1.2880 + if (pc && aTextZoom != mPresContext->TextZoom()) { 1.2881 + pc->SetTextZoom(aTextZoom); 1.2882 + } 1.2883 + 1.2884 + // And do the external resources 1.2885 + mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo); 1.2886 + 1.2887 + nsContentUtils::DispatchChromeEvent(mDocument, static_cast<nsIDocument*>(mDocument), 1.2888 + NS_LITERAL_STRING("TextZoomChange"), 1.2889 + true, true); 1.2890 + 1.2891 + return NS_OK; 1.2892 +} 1.2893 + 1.2894 +NS_IMETHODIMP 1.2895 +nsDocumentViewer::GetTextZoom(float* aTextZoom) 1.2896 +{ 1.2897 + NS_ENSURE_ARG_POINTER(aTextZoom); 1.2898 + nsPresContext* pc = GetPresContext(); 1.2899 + *aTextZoom = pc ? pc->TextZoom() : 1.0f; 1.2900 + return NS_OK; 1.2901 +} 1.2902 + 1.2903 +NS_IMETHODIMP 1.2904 +nsDocumentViewer::SetMinFontSize(int32_t aMinFontSize) 1.2905 +{ 1.2906 + // If we don't have a document, then we need to bail. 1.2907 + if (!mDocument) { 1.2908 + return NS_ERROR_FAILURE; 1.2909 + } 1.2910 + 1.2911 + if (GetIsPrintPreview()) { 1.2912 + return NS_OK; 1.2913 + } 1.2914 + 1.2915 + mMinFontSize = aMinFontSize; 1.2916 + 1.2917 + // Set the min font on all children of mContainer (even if our min font didn't 1.2918 + // change, our children's min font may be different, though it would be unusual). 1.2919 + // Do this first, in case kids are auto-sizing and post reflow commands on 1.2920 + // our presshell (which should be subsumed into our own style change reflow). 1.2921 + CallChildren(SetChildMinFontSize, NS_INT32_TO_PTR(aMinFontSize)); 1.2922 + 1.2923 + // Now change our own min font 1.2924 + nsPresContext* pc = GetPresContext(); 1.2925 + if (pc && aMinFontSize != mPresContext->MinFontSize(nullptr)) { 1.2926 + pc->SetBaseMinFontSize(aMinFontSize); 1.2927 + } 1.2928 + 1.2929 + // And do the external resources 1.2930 + mDocument->EnumerateExternalResources(SetExtResourceMinFontSize, 1.2931 + NS_INT32_TO_PTR(aMinFontSize)); 1.2932 + 1.2933 + return NS_OK; 1.2934 +} 1.2935 + 1.2936 +NS_IMETHODIMP 1.2937 +nsDocumentViewer::GetMinFontSize(int32_t* aMinFontSize) 1.2938 +{ 1.2939 + NS_ENSURE_ARG_POINTER(aMinFontSize); 1.2940 + nsPresContext* pc = GetPresContext(); 1.2941 + *aMinFontSize = pc ? pc->BaseMinFontSize() : 0; 1.2942 + return NS_OK; 1.2943 +} 1.2944 + 1.2945 +NS_IMETHODIMP 1.2946 +nsDocumentViewer::SetFullZoom(float aFullZoom) 1.2947 +{ 1.2948 +#ifdef NS_PRINT_PREVIEW 1.2949 + if (GetIsPrintPreview()) { 1.2950 + nsPresContext* pc = GetPresContext(); 1.2951 + NS_ENSURE_TRUE(pc, NS_OK); 1.2952 + nsCOMPtr<nsIPresShell> shell = pc->GetPresShell(); 1.2953 + NS_ENSURE_TRUE(shell, NS_OK); 1.2954 + 1.2955 + if (!mPrintPreviewZoomed) { 1.2956 + mOriginalPrintPreviewScale = pc->GetPrintPreviewScale(); 1.2957 + mPrintPreviewZoomed = true; 1.2958 + } 1.2959 + 1.2960 + mPrintPreviewZoom = aFullZoom; 1.2961 + pc->SetPrintPreviewScale(aFullZoom * mOriginalPrintPreviewScale); 1.2962 + nsIPageSequenceFrame* pf = shell->GetPageSequenceFrame(); 1.2963 + if (pf) { 1.2964 + nsIFrame* f = do_QueryFrame(pf); 1.2965 + shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY); 1.2966 + } 1.2967 + 1.2968 + nsIFrame* rootFrame = shell->GetRootFrame(); 1.2969 + if (rootFrame) { 1.2970 + rootFrame->InvalidateFrame(); 1.2971 + } 1.2972 + return NS_OK; 1.2973 + } 1.2974 +#endif 1.2975 + 1.2976 + // If we don't have a document, then we need to bail. 1.2977 + if (!mDocument) { 1.2978 + return NS_ERROR_FAILURE; 1.2979 + } 1.2980 + 1.2981 + mPageZoom = aFullZoom; 1.2982 + 1.2983 + struct ZoomInfo ZoomInfo = { aFullZoom }; 1.2984 + CallChildren(SetChildFullZoom, &ZoomInfo); 1.2985 + 1.2986 + nsPresContext* pc = GetPresContext(); 1.2987 + if (pc) { 1.2988 + pc->SetFullZoom(aFullZoom); 1.2989 + } 1.2990 + 1.2991 + // And do the external resources 1.2992 + mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo); 1.2993 + 1.2994 + nsContentUtils::DispatchChromeEvent(mDocument, static_cast<nsIDocument*>(mDocument), 1.2995 + NS_LITERAL_STRING("FullZoomChange"), 1.2996 + true, true); 1.2997 + 1.2998 + return NS_OK; 1.2999 +} 1.3000 + 1.3001 +NS_IMETHODIMP 1.3002 +nsDocumentViewer::GetFullZoom(float* aFullZoom) 1.3003 +{ 1.3004 + NS_ENSURE_ARG_POINTER(aFullZoom); 1.3005 +#ifdef NS_PRINT_PREVIEW 1.3006 + if (GetIsPrintPreview()) { 1.3007 + *aFullZoom = mPrintPreviewZoom; 1.3008 + return NS_OK; 1.3009 + } 1.3010 +#endif 1.3011 + // Check the prescontext first because it might have a temporary 1.3012 + // setting for print-preview 1.3013 + nsPresContext* pc = GetPresContext(); 1.3014 + *aFullZoom = pc ? pc->GetFullZoom() : mPageZoom; 1.3015 + return NS_OK; 1.3016 +} 1.3017 + 1.3018 +static void 1.3019 +SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3020 +{ 1.3021 + bool styleDisabled = *static_cast<bool*>(aClosure); 1.3022 + aChild->SetAuthorStyleDisabled(styleDisabled); 1.3023 +} 1.3024 + 1.3025 + 1.3026 +NS_IMETHODIMP 1.3027 +nsDocumentViewer::SetAuthorStyleDisabled(bool aStyleDisabled) 1.3028 +{ 1.3029 + if (mPresShell) { 1.3030 + mPresShell->SetAuthorStyleDisabled(aStyleDisabled); 1.3031 + } 1.3032 + CallChildren(SetChildAuthorStyleDisabled, &aStyleDisabled); 1.3033 + return NS_OK; 1.3034 +} 1.3035 + 1.3036 +NS_IMETHODIMP 1.3037 +nsDocumentViewer::GetAuthorStyleDisabled(bool* aStyleDisabled) 1.3038 +{ 1.3039 + if (mPresShell) { 1.3040 + *aStyleDisabled = mPresShell->GetAuthorStyleDisabled(); 1.3041 + } else { 1.3042 + *aStyleDisabled = false; 1.3043 + } 1.3044 + return NS_OK; 1.3045 +} 1.3046 + 1.3047 +static bool 1.3048 +ExtResourceEmulateMedium(nsIDocument* aDocument, void* aClosure) 1.3049 +{ 1.3050 + nsIPresShell* shell = aDocument->GetShell(); 1.3051 + if (shell) { 1.3052 + nsPresContext* ctxt = shell->GetPresContext(); 1.3053 + if (ctxt) { 1.3054 + const nsAString* mediaType = static_cast<nsAString*>(aClosure); 1.3055 + ctxt->EmulateMedium(*mediaType); 1.3056 + } 1.3057 + } 1.3058 + 1.3059 + return true; 1.3060 +} 1.3061 + 1.3062 +static void 1.3063 +ChildEmulateMedium(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3064 +{ 1.3065 + const nsAString* mediaType = static_cast<nsAString*>(aClosure); 1.3066 + aChild->EmulateMedium(*mediaType); 1.3067 +} 1.3068 + 1.3069 +NS_IMETHODIMP 1.3070 +nsDocumentViewer::EmulateMedium(const nsAString& aMediaType) 1.3071 +{ 1.3072 + if (mPresContext) { 1.3073 + mPresContext->EmulateMedium(aMediaType); 1.3074 + } 1.3075 + CallChildren(ChildEmulateMedium, const_cast<nsAString*>(&aMediaType)); 1.3076 + 1.3077 + if (mDocument) { 1.3078 + mDocument->EnumerateExternalResources(ExtResourceEmulateMedium, 1.3079 + const_cast<nsAString*>(&aMediaType)); 1.3080 + } 1.3081 + 1.3082 + return NS_OK; 1.3083 +} 1.3084 + 1.3085 +static bool 1.3086 +ExtResourceStopEmulatingMedium(nsIDocument* aDocument, void* aClosure) 1.3087 +{ 1.3088 + nsIPresShell* shell = aDocument->GetShell(); 1.3089 + if (shell) { 1.3090 + nsPresContext* ctxt = shell->GetPresContext(); 1.3091 + if (ctxt) { 1.3092 + ctxt->StopEmulatingMedium(); 1.3093 + } 1.3094 + } 1.3095 + 1.3096 + return true; 1.3097 +} 1.3098 + 1.3099 +static void 1.3100 +ChildStopEmulatingMedium(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3101 +{ 1.3102 + aChild->StopEmulatingMedium(); 1.3103 +} 1.3104 + 1.3105 +NS_IMETHODIMP 1.3106 +nsDocumentViewer::StopEmulatingMedium() 1.3107 +{ 1.3108 + if (mPresContext) { 1.3109 + mPresContext->StopEmulatingMedium(); 1.3110 + } 1.3111 + CallChildren(ChildStopEmulatingMedium, nullptr); 1.3112 + 1.3113 + if (mDocument) { 1.3114 + mDocument->EnumerateExternalResources(ExtResourceStopEmulatingMedium, 1.3115 + nullptr); 1.3116 + } 1.3117 + 1.3118 + return NS_OK; 1.3119 +} 1.3120 + 1.3121 +NS_IMETHODIMP nsDocumentViewer::GetForceCharacterSet(nsACString& aForceCharacterSet) 1.3122 +{ 1.3123 + aForceCharacterSet = mForceCharacterSet; 1.3124 + return NS_OK; 1.3125 +} 1.3126 + 1.3127 +static void 1.3128 +SetChildForceCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3129 +{ 1.3130 + const nsACString* charset = static_cast<nsACString*>(aClosure); 1.3131 + aChild->SetForceCharacterSet(*charset); 1.3132 +} 1.3133 + 1.3134 +NS_IMETHODIMP 1.3135 +nsDocumentViewer::SetForceCharacterSet(const nsACString& aForceCharacterSet) 1.3136 +{ 1.3137 + mForceCharacterSet = aForceCharacterSet; 1.3138 + // now set the force char set on all children of mContainer 1.3139 + CallChildren(SetChildForceCharacterSet, (void*) &aForceCharacterSet); 1.3140 + return NS_OK; 1.3141 +} 1.3142 + 1.3143 +NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(nsACString& aHintCharacterSet) 1.3144 +{ 1.3145 + 1.3146 + if(kCharsetUninitialized == mHintCharsetSource) { 1.3147 + aHintCharacterSet.Truncate(); 1.3148 + } else { 1.3149 + aHintCharacterSet = mHintCharset; 1.3150 + // this can't possibly be right. we can't set a value just because somebody got a related value! 1.3151 + //mHintCharsetSource = kCharsetUninitialized; 1.3152 + } 1.3153 + return NS_OK; 1.3154 +} 1.3155 + 1.3156 +NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSetSource(int32_t *aHintCharacterSetSource) 1.3157 +{ 1.3158 + NS_ENSURE_ARG_POINTER(aHintCharacterSetSource); 1.3159 + 1.3160 + *aHintCharacterSetSource = mHintCharsetSource; 1.3161 + return NS_OK; 1.3162 +} 1.3163 + 1.3164 +static void 1.3165 +SetChildHintCharacterSetSource(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3166 +{ 1.3167 + aChild->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure)); 1.3168 +} 1.3169 + 1.3170 +NS_IMETHODIMP 1.3171 +nsDocumentViewer::SetHintCharacterSetSource(int32_t aHintCharacterSetSource) 1.3172 +{ 1.3173 + mHintCharsetSource = aHintCharacterSetSource; 1.3174 + // now set the hint char set source on all children of mContainer 1.3175 + CallChildren(SetChildHintCharacterSetSource, 1.3176 + NS_INT32_TO_PTR(aHintCharacterSetSource)); 1.3177 + return NS_OK; 1.3178 +} 1.3179 + 1.3180 +static void 1.3181 +SetChildHintCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3182 +{ 1.3183 + const nsACString* charset = static_cast<nsACString*>(aClosure); 1.3184 + aChild->SetHintCharacterSet(*charset); 1.3185 +} 1.3186 + 1.3187 +NS_IMETHODIMP 1.3188 +nsDocumentViewer::SetHintCharacterSet(const nsACString& aHintCharacterSet) 1.3189 +{ 1.3190 + mHintCharset = aHintCharacterSet; 1.3191 + // now set the hint char set on all children of mContainer 1.3192 + CallChildren(SetChildHintCharacterSet, (void*) &aHintCharacterSet); 1.3193 + return NS_OK; 1.3194 +} 1.3195 + 1.3196 +static void 1.3197 +AppendChildSubtree(nsIMarkupDocumentViewer* aChild, void* aClosure) 1.3198 +{ 1.3199 + nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >& array = 1.3200 + *static_cast<nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >*>(aClosure); 1.3201 + aChild->AppendSubtree(array); 1.3202 +} 1.3203 + 1.3204 +NS_IMETHODIMP nsDocumentViewer::AppendSubtree(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >& aArray) 1.3205 +{ 1.3206 + aArray.AppendElement(this); 1.3207 + CallChildren(AppendChildSubtree, &aArray); 1.3208 + return NS_OK; 1.3209 +} 1.3210 + 1.3211 +NS_IMETHODIMP 1.3212 +nsDocumentViewer::PausePainting() 1.3213 +{ 1.3214 + bool enablePaint = false; 1.3215 + CallChildren(ChangeChildPaintingEnabled, &enablePaint); 1.3216 + 1.3217 + nsIPresShell* presShell = GetPresShell(); 1.3218 + if (presShell) { 1.3219 + presShell->PausePainting(); 1.3220 + } 1.3221 + 1.3222 + return NS_OK; 1.3223 +} 1.3224 + 1.3225 +NS_IMETHODIMP 1.3226 +nsDocumentViewer::ResumePainting() 1.3227 +{ 1.3228 + bool enablePaint = true; 1.3229 + CallChildren(ChangeChildPaintingEnabled, &enablePaint); 1.3230 + 1.3231 + nsIPresShell* presShell = GetPresShell(); 1.3232 + if (presShell) { 1.3233 + presShell->ResumePainting(); 1.3234 + } 1.3235 + 1.3236 + return NS_OK; 1.3237 +} 1.3238 + 1.3239 +NS_IMETHODIMP 1.3240 +nsDocumentViewer::ChangeMaxLineBoxWidth(int32_t aMaxLineBoxWidth) 1.3241 +{ 1.3242 + // Change the max line box width for all children. 1.3243 + struct LineBoxInfo lbi = { aMaxLineBoxWidth }; 1.3244 + CallChildren(ChangeChildMaxLineBoxWidth, &lbi); 1.3245 + 1.3246 + // Now, change our max line box width. 1.3247 + // Convert to app units, since our input is in CSS pixels. 1.3248 + nscoord mlbw = nsPresContext::CSSPixelsToAppUnits(aMaxLineBoxWidth); 1.3249 + nsIPresShell* presShell = GetPresShell(); 1.3250 + if (presShell) { 1.3251 + presShell->SetMaxLineBoxWidth(mlbw); 1.3252 + } 1.3253 + 1.3254 + return NS_OK; 1.3255 +} 1.3256 + 1.3257 +NS_IMETHODIMP 1.3258 +nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight) 1.3259 +{ 1.3260 + NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); 1.3261 + 1.3262 + // Skip doing this on docshell-less documents for now 1.3263 + nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(mContainer); 1.3264 + NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_NOT_AVAILABLE); 1.3265 + 1.3266 + nsCOMPtr<nsIDocShellTreeItem> docShellParent; 1.3267 + docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent)); 1.3268 + 1.3269 + // It's only valid to access this from a top frame. Doesn't work from 1.3270 + // sub-frames. 1.3271 + NS_ENSURE_TRUE(!docShellParent, NS_ERROR_FAILURE); 1.3272 + 1.3273 + nsCOMPtr<nsIPresShell> presShell; 1.3274 + GetPresShell(getter_AddRefs(presShell)); 1.3275 + NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); 1.3276 + 1.3277 + // Flush out all content and style updates. We can't use a resize reflow 1.3278 + // because it won't change some sizes that a style change reflow will. 1.3279 + mDocument->FlushPendingNotifications(Flush_Layout); 1.3280 + 1.3281 + nsIFrame *root = presShell->GetRootFrame(); 1.3282 + NS_ENSURE_TRUE(root, NS_ERROR_FAILURE); 1.3283 + 1.3284 + nscoord prefWidth; 1.3285 + { 1.3286 + nsRefPtr<nsRenderingContext> rcx = 1.3287 + presShell->CreateReferenceRenderingContext(); 1.3288 + prefWidth = root->GetPrefWidth(rcx); 1.3289 + } 1.3290 + 1.3291 + nsresult rv = presShell->ResizeReflow(prefWidth, NS_UNCONSTRAINEDSIZE); 1.3292 + NS_ENSURE_SUCCESS(rv, rv); 1.3293 + 1.3294 + nsRefPtr<nsPresContext> presContext; 1.3295 + GetPresContext(getter_AddRefs(presContext)); 1.3296 + NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE); 1.3297 + 1.3298 + // so how big is it? 1.3299 + nsRect shellArea = presContext->GetVisibleArea(); 1.3300 + // Protect against bogus returns here 1.3301 + NS_ENSURE_TRUE(shellArea.width != NS_UNCONSTRAINEDSIZE && 1.3302 + shellArea.height != NS_UNCONSTRAINEDSIZE, 1.3303 + NS_ERROR_FAILURE); 1.3304 + 1.3305 + *aWidth = presContext->AppUnitsToDevPixels(shellArea.width); 1.3306 + *aHeight = presContext->AppUnitsToDevPixels(shellArea.height); 1.3307 + 1.3308 + return NS_OK; 1.3309 +} 1.3310 + 1.3311 + 1.3312 +NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, nsISelectionListener) 1.3313 + 1.3314 +nsresult nsDocViewerSelectionListener::Init(nsDocumentViewer *aDocViewer) 1.3315 +{ 1.3316 + mDocViewer = aDocViewer; 1.3317 + return NS_OK; 1.3318 +} 1.3319 + 1.3320 +/* 1.3321 + * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers 1.3322 + * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family 1.3323 + * of commands. The focus controller stores the popup node, these retrieve 1.3324 + * them and munge appropriately. Note that we have to store the popup node 1.3325 + * rather than retrieving it from EventStateManager::GetFocusedContent because 1.3326 + * not all content (images included) can receive focus. 1.3327 + */ 1.3328 + 1.3329 +nsresult 1.3330 +nsDocumentViewer::GetPopupNode(nsIDOMNode** aNode) 1.3331 +{ 1.3332 + NS_ENSURE_ARG_POINTER(aNode); 1.3333 + 1.3334 + *aNode = nullptr; 1.3335 + 1.3336 + // get the document 1.3337 + nsIDocument* document = GetDocument(); 1.3338 + NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); 1.3339 + 1.3340 + // get the private dom window 1.3341 + nsCOMPtr<nsPIDOMWindow> window(document->GetWindow()); 1.3342 + NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE); 1.3343 + if (window) { 1.3344 + nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot(); 1.3345 + NS_ENSURE_TRUE(root, NS_ERROR_FAILURE); 1.3346 + 1.3347 + // get the popup node 1.3348 + nsCOMPtr<nsIDOMNode> node = root->GetPopupNode(); 1.3349 +#ifdef MOZ_XUL 1.3350 + if (!node) { 1.3351 + nsPIDOMWindow* rootWindow = root->GetWindow(); 1.3352 + if (rootWindow) { 1.3353 + nsCOMPtr<nsIDocument> rootDoc = rootWindow->GetExtantDoc(); 1.3354 + if (rootDoc) { 1.3355 + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); 1.3356 + if (pm) { 1.3357 + node = pm->GetLastTriggerPopupNode(rootDoc); 1.3358 + } 1.3359 + } 1.3360 + } 1.3361 + } 1.3362 +#endif 1.3363 + node.swap(*aNode); 1.3364 + } 1.3365 + 1.3366 + return NS_OK; 1.3367 +} 1.3368 + 1.3369 +// GetPopupLinkNode: return popup link node or fail 1.3370 +nsresult 1.3371 +nsDocumentViewer::GetPopupLinkNode(nsIDOMNode** aNode) 1.3372 +{ 1.3373 + NS_ENSURE_ARG_POINTER(aNode); 1.3374 + 1.3375 + // you get null unless i say so 1.3376 + *aNode = nullptr; 1.3377 + 1.3378 + // find popup node 1.3379 + nsCOMPtr<nsIDOMNode> node; 1.3380 + nsresult rv = GetPopupNode(getter_AddRefs(node)); 1.3381 + NS_ENSURE_SUCCESS(rv, rv); 1.3382 + 1.3383 + // find out if we have a link in our ancestry 1.3384 + while (node) { 1.3385 + 1.3386 + nsCOMPtr<nsIContent> content(do_QueryInterface(node)); 1.3387 + if (content) { 1.3388 + nsCOMPtr<nsIURI> hrefURI = content->GetHrefURI(); 1.3389 + if (hrefURI) { 1.3390 + *aNode = node; 1.3391 + NS_IF_ADDREF(*aNode); // addref 1.3392 + return NS_OK; 1.3393 + } 1.3394 + } 1.3395 + 1.3396 + // get our parent and keep trying... 1.3397 + nsCOMPtr<nsIDOMNode> parentNode; 1.3398 + node->GetParentNode(getter_AddRefs(parentNode)); 1.3399 + node = parentNode; 1.3400 + } 1.3401 + 1.3402 + // if we have no node, fail 1.3403 + return NS_ERROR_FAILURE; 1.3404 +} 1.3405 + 1.3406 +// GetPopupLinkNode: return popup image node or fail 1.3407 +nsresult 1.3408 +nsDocumentViewer::GetPopupImageNode(nsIImageLoadingContent** aNode) 1.3409 +{ 1.3410 + NS_ENSURE_ARG_POINTER(aNode); 1.3411 + 1.3412 + // you get null unless i say so 1.3413 + *aNode = nullptr; 1.3414 + 1.3415 + // find popup node 1.3416 + nsCOMPtr<nsIDOMNode> node; 1.3417 + nsresult rv = GetPopupNode(getter_AddRefs(node)); 1.3418 + NS_ENSURE_SUCCESS(rv, rv); 1.3419 + 1.3420 + if (node) 1.3421 + CallQueryInterface(node, aNode); 1.3422 + 1.3423 + return NS_OK; 1.3424 +} 1.3425 + 1.3426 +/* 1.3427 + * XXX dr 1.3428 + * ------ 1.3429 + * These two functions -- GetInLink and GetInImage -- are kind of annoying 1.3430 + * in that they only get called from the controller (in 1.3431 + * nsDOMWindowController::IsCommandEnabled). The actual construction of the 1.3432 + * context menus in communicator (nsContextMenu.js) has its own, redundant 1.3433 + * tests. No big deal, but good to keep in mind if we ever clean context 1.3434 + * menus. 1.3435 + */ 1.3436 + 1.3437 +NS_IMETHODIMP nsDocumentViewer::GetInLink(bool* aInLink) 1.3438 +{ 1.3439 +#ifdef DEBUG_dr 1.3440 + printf("dr :: nsDocumentViewer::GetInLink\n"); 1.3441 +#endif 1.3442 + 1.3443 + NS_ENSURE_ARG_POINTER(aInLink); 1.3444 + 1.3445 + // we're not in a link unless i say so 1.3446 + *aInLink = false; 1.3447 + 1.3448 + // get the popup link 1.3449 + nsCOMPtr<nsIDOMNode> node; 1.3450 + nsresult rv = GetPopupLinkNode(getter_AddRefs(node)); 1.3451 + if (NS_FAILED(rv)) return rv; 1.3452 + NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); 1.3453 + 1.3454 + // if we made it here, we're in a link 1.3455 + *aInLink = true; 1.3456 + return NS_OK; 1.3457 +} 1.3458 + 1.3459 +NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage) 1.3460 +{ 1.3461 +#ifdef DEBUG_dr 1.3462 + printf("dr :: nsDocumentViewer::GetInImage\n"); 1.3463 +#endif 1.3464 + 1.3465 + NS_ENSURE_ARG_POINTER(aInImage); 1.3466 + 1.3467 + // we're not in an image unless i say so 1.3468 + *aInImage = false; 1.3469 + 1.3470 + // get the popup image 1.3471 + nsCOMPtr<nsIImageLoadingContent> node; 1.3472 + nsresult rv = GetPopupImageNode(getter_AddRefs(node)); 1.3473 + if (NS_FAILED(rv)) return rv; 1.3474 + NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); 1.3475 + 1.3476 + // if we made it here, we're in an image 1.3477 + *aInImage = true; 1.3478 + return NS_OK; 1.3479 +} 1.3480 + 1.3481 +NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *, int16_t) 1.3482 +{ 1.3483 + NS_ASSERTION(mDocViewer, "Should have doc viewer!"); 1.3484 + 1.3485 + // get the selection state 1.3486 + nsCOMPtr<nsISelection> selection; 1.3487 + nsresult rv = mDocViewer->GetDocumentSelection(getter_AddRefs(selection)); 1.3488 + if (NS_FAILED(rv)) return rv; 1.3489 + 1.3490 + bool selectionCollapsed; 1.3491 + selection->GetIsCollapsed(&selectionCollapsed); 1.3492 + // we only call UpdateCommands when the selection changes from collapsed 1.3493 + // to non-collapsed or vice versa. We might need another update string 1.3494 + // for simple selection changes, but that would be expenseive. 1.3495 + if (!mGotSelectionState || mSelectionWasCollapsed != selectionCollapsed) 1.3496 + { 1.3497 + nsIDocument* theDoc = mDocViewer->GetDocument(); 1.3498 + if (!theDoc) return NS_ERROR_FAILURE; 1.3499 + 1.3500 + nsPIDOMWindow *domWindow = theDoc->GetWindow(); 1.3501 + if (!domWindow) return NS_ERROR_FAILURE; 1.3502 + 1.3503 + domWindow->UpdateCommands(NS_LITERAL_STRING("select")); 1.3504 + mGotSelectionState = true; 1.3505 + mSelectionWasCollapsed = selectionCollapsed; 1.3506 + } 1.3507 + 1.3508 + return NS_OK; 1.3509 +} 1.3510 + 1.3511 +//nsDocViewerFocusListener 1.3512 +NS_IMPL_ISUPPORTS(nsDocViewerFocusListener, 1.3513 + nsIDOMEventListener) 1.3514 + 1.3515 +nsDocViewerFocusListener::nsDocViewerFocusListener() 1.3516 +:mDocViewer(nullptr) 1.3517 +{ 1.3518 +} 1.3519 + 1.3520 +nsDocViewerFocusListener::~nsDocViewerFocusListener(){} 1.3521 + 1.3522 +nsresult 1.3523 +nsDocViewerFocusListener::HandleEvent(nsIDOMEvent* aEvent) 1.3524 +{ 1.3525 + NS_ENSURE_STATE(mDocViewer); 1.3526 + 1.3527 + nsCOMPtr<nsIPresShell> shell; 1.3528 + mDocViewer->GetPresShell(getter_AddRefs(shell)); 1.3529 + NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); 1.3530 + 1.3531 + nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(shell); 1.3532 + int16_t selectionStatus; 1.3533 + selCon->GetDisplaySelection(&selectionStatus); 1.3534 + 1.3535 + nsAutoString eventType; 1.3536 + aEvent->GetType(eventType); 1.3537 + if (eventType.EqualsLiteral("focus")) { 1.3538 + // If selection was disabled, re-enable it. 1.3539 + if(selectionStatus == nsISelectionController::SELECTION_DISABLED || 1.3540 + selectionStatus == nsISelectionController::SELECTION_HIDDEN) { 1.3541 + selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON); 1.3542 + selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL); 1.3543 + } 1.3544 + } else { 1.3545 + NS_ABORT_IF_FALSE(eventType.EqualsLiteral("blur"), 1.3546 + "Unexpected event type"); 1.3547 + // If selection was on, disable it. 1.3548 + if(selectionStatus == nsISelectionController::SELECTION_ON || 1.3549 + selectionStatus == nsISelectionController::SELECTION_ATTENTION) { 1.3550 + selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED); 1.3551 + selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL); 1.3552 + } 1.3553 + } 1.3554 + 1.3555 + return NS_OK; 1.3556 +} 1.3557 + 1.3558 +nsresult 1.3559 +nsDocViewerFocusListener::Init(nsDocumentViewer *aDocViewer) 1.3560 +{ 1.3561 + mDocViewer = aDocViewer; 1.3562 + return NS_OK; 1.3563 +} 1.3564 + 1.3565 +/** --------------------------------------------------- 1.3566 + * From nsIWebBrowserPrint 1.3567 + */ 1.3568 + 1.3569 +#ifdef NS_PRINTING 1.3570 + 1.3571 +NS_IMETHODIMP 1.3572 +nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings, 1.3573 + nsIWebProgressListener* aWebProgressListener) 1.3574 +{ 1.3575 + // Printing XUL documents is not supported. 1.3576 + nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument)); 1.3577 + if (xulDoc) { 1.3578 + return NS_ERROR_FAILURE; 1.3579 + } 1.3580 + 1.3581 + if (!mContainer) { 1.3582 + PR_PL(("Container was destroyed yet we are still trying to use it!")); 1.3583 + return NS_ERROR_FAILURE; 1.3584 + } 1.3585 + 1.3586 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.3587 + NS_ENSURE_STATE(docShell); 1.3588 + 1.3589 + // Check to see if this document is still busy 1.3590 + // If it is busy and we aren't already "queued" up to print then 1.3591 + // Indicate there is a print pending and cache the args for later 1.3592 + uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE; 1.3593 + if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || 1.3594 + (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && 1.3595 + !mPrintDocIsFullyLoaded) { 1.3596 + if (!mPrintIsPending) { 1.3597 + mCachedPrintSettings = aPrintSettings; 1.3598 + mCachedPrintWebProgressListner = aWebProgressListener; 1.3599 + mPrintIsPending = true; 1.3600 + } 1.3601 + PR_PL(("Printing Stopped - document is still busy!")); 1.3602 + return NS_ERROR_GFX_PRINTER_DOC_IS_BUSY; 1.3603 + } 1.3604 + 1.3605 + if (!mDocument || !mDeviceContext) { 1.3606 + PR_PL(("Can't Print without a document and a device context")); 1.3607 + return NS_ERROR_FAILURE; 1.3608 + } 1.3609 + 1.3610 + nsresult rv; 1.3611 + 1.3612 + // if we are printing another URL, then exit 1.3613 + // the reason we check here is because this method can be called while 1.3614 + // another is still in here (the printing dialog is a good example). 1.3615 + // the only time we can print more than one job at a time is the regression tests 1.3616 + if (GetIsPrinting()) { 1.3617 + // Let the user know we are not ready to print. 1.3618 + rv = NS_ERROR_NOT_AVAILABLE; 1.3619 + nsPrintEngine::ShowPrintErrorDialog(rv); 1.3620 + return rv; 1.3621 + } 1.3622 + 1.3623 + nsAutoPtr<nsPrintEventDispatcher> beforeAndAfterPrint( 1.3624 + new nsPrintEventDispatcher(mDocument)); 1.3625 + NS_ENSURE_STATE(!GetIsPrinting()); 1.3626 + // If we are hosting a full-page plugin, tell it to print 1.3627 + // first. It shows its own native print UI. 1.3628 + nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument)); 1.3629 + if (pDoc) 1.3630 + return pDoc->Print(); 1.3631 + 1.3632 + if (!mPrintEngine) { 1.3633 + NS_ENSURE_STATE(mDeviceContext); 1.3634 + mPrintEngine = new nsPrintEngine(); 1.3635 + 1.3636 + rv = mPrintEngine->Initialize(this, mContainer, mDocument, 1.3637 + float(mDeviceContext->AppUnitsPerCSSInch()) / 1.3638 + float(mDeviceContext->AppUnitsPerDevPixel()) / 1.3639 + mPageZoom, 1.3640 +#ifdef DEBUG 1.3641 + mDebugFile 1.3642 +#else 1.3643 + nullptr 1.3644 +#endif 1.3645 + ); 1.3646 + if (NS_FAILED(rv)) { 1.3647 + mPrintEngine->Destroy(); 1.3648 + mPrintEngine = nullptr; 1.3649 + return rv; 1.3650 + } 1.3651 + } 1.3652 + if (mPrintEngine->HasPrintCallbackCanvas()) { 1.3653 + mBeforeAndAfterPrint = beforeAndAfterPrint; 1.3654 + } 1.3655 + dom::Element* root = mDocument->GetRootElement(); 1.3656 + if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) { 1.3657 + mPrintEngine->SetDisallowSelectionPrint(true); 1.3658 + } 1.3659 + if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::moznomarginboxes)) { 1.3660 + mPrintEngine->SetNoMarginBoxes(true); 1.3661 + } 1.3662 + rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener); 1.3663 + if (NS_FAILED(rv)) { 1.3664 + OnDonePrinting(); 1.3665 + } 1.3666 + return rv; 1.3667 +} 1.3668 + 1.3669 +NS_IMETHODIMP 1.3670 +nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings, 1.3671 + nsIDOMWindow *aChildDOMWin, 1.3672 + nsIWebProgressListener* aWebProgressListener) 1.3673 +{ 1.3674 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.3675 + NS_WARN_IF_FALSE(IsInitializedForPrintPreview(), 1.3676 + "Using docshell.printPreview is the preferred way for print previewing!"); 1.3677 + 1.3678 + NS_ENSURE_ARG_POINTER(aChildDOMWin); 1.3679 + nsresult rv = NS_OK; 1.3680 + 1.3681 + if (GetIsPrinting()) { 1.3682 + nsPrintEngine::CloseProgressDialog(aWebProgressListener); 1.3683 + return NS_ERROR_FAILURE; 1.3684 + } 1.3685 + 1.3686 + // Printing XUL documents is not supported. 1.3687 + nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument)); 1.3688 + if (xulDoc) { 1.3689 + nsPrintEngine::CloseProgressDialog(aWebProgressListener); 1.3690 + return NS_ERROR_FAILURE; 1.3691 + } 1.3692 + 1.3693 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.3694 + if (!docShell || !mDeviceContext) { 1.3695 + PR_PL(("Can't Print Preview without device context and docshell")); 1.3696 + return NS_ERROR_FAILURE; 1.3697 + } 1.3698 + 1.3699 + nsCOMPtr<nsIDOMDocument> domDoc; 1.3700 + aChildDOMWin->GetDocument(getter_AddRefs(domDoc)); 1.3701 + nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); 1.3702 + NS_ENSURE_STATE(doc); 1.3703 + 1.3704 + nsAutoPtr<nsPrintEventDispatcher> beforeAndAfterPrint( 1.3705 + new nsPrintEventDispatcher(doc)); 1.3706 + NS_ENSURE_STATE(!GetIsPrinting()); 1.3707 + if (!mPrintEngine) { 1.3708 + mPrintEngine = new nsPrintEngine(); 1.3709 + 1.3710 + rv = mPrintEngine->Initialize(this, mContainer, doc, 1.3711 + float(mDeviceContext->AppUnitsPerCSSInch()) / 1.3712 + float(mDeviceContext->AppUnitsPerDevPixel()) / 1.3713 + mPageZoom, 1.3714 +#ifdef DEBUG 1.3715 + mDebugFile 1.3716 +#else 1.3717 + nullptr 1.3718 +#endif 1.3719 + ); 1.3720 + if (NS_FAILED(rv)) { 1.3721 + mPrintEngine->Destroy(); 1.3722 + mPrintEngine = nullptr; 1.3723 + return rv; 1.3724 + } 1.3725 + } 1.3726 + if (mPrintEngine->HasPrintCallbackCanvas()) { 1.3727 + mBeforeAndAfterPrint = beforeAndAfterPrint; 1.3728 + } 1.3729 + dom::Element* root = doc->GetRootElement(); 1.3730 + if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) { 1.3731 + PR_PL(("PrintPreview: found mozdisallowselectionprint")); 1.3732 + mPrintEngine->SetDisallowSelectionPrint(true); 1.3733 + } 1.3734 + if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::moznomarginboxes)) { 1.3735 + PR_PL(("PrintPreview: found moznomarginboxes")); 1.3736 + mPrintEngine->SetNoMarginBoxes(true); 1.3737 + } 1.3738 + rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener); 1.3739 + mPrintPreviewZoomed = false; 1.3740 + if (NS_FAILED(rv)) { 1.3741 + OnDonePrinting(); 1.3742 + } 1.3743 + return rv; 1.3744 +#else 1.3745 + return NS_ERROR_FAILURE; 1.3746 +#endif 1.3747 +} 1.3748 + 1.3749 +//---------------------------------------------------------------------- 1.3750 +NS_IMETHODIMP 1.3751 +nsDocumentViewer::PrintPreviewNavigate(int16_t aType, int32_t aPageNum) 1.3752 +{ 1.3753 + if (!GetIsPrintPreview() || 1.3754 + mPrintEngine->GetIsCreatingPrintPreview()) 1.3755 + return NS_ERROR_FAILURE; 1.3756 + 1.3757 + nsIScrollableFrame* sf = 1.3758 + mPrintEngine->GetPrintPreviewPresShell()->GetRootScrollFrameAsScrollable(); 1.3759 + if (!sf) 1.3760 + return NS_OK; 1.3761 + 1.3762 + // Check to see if we can short circut scrolling to the top 1.3763 + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME || 1.3764 + (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) { 1.3765 + sf->ScrollTo(nsPoint(0, 0), nsIScrollableFrame::INSTANT); 1.3766 + return NS_OK; 1.3767 + } 1.3768 + 1.3769 + // Finds the SimplePageSequencer frame 1.3770 + // in PP mPrtPreview->mPrintObject->mSeqFrame is null 1.3771 + nsIFrame* seqFrame = nullptr; 1.3772 + int32_t pageCount = 0; 1.3773 + if (NS_FAILED(mPrintEngine->GetSeqFrameAndCountPages(seqFrame, pageCount))) { 1.3774 + return NS_ERROR_FAILURE; 1.3775 + } 1.3776 + 1.3777 + // Figure where we are currently scrolled to 1.3778 + nsPoint pt = sf->GetScrollPosition(); 1.3779 + 1.3780 + int32_t pageNum = 1; 1.3781 + nsIFrame * fndPageFrame = nullptr; 1.3782 + nsIFrame * currentPage = nullptr; 1.3783 + 1.3784 + // If it is "End" then just do a "goto" to the last page 1.3785 + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) { 1.3786 + aType = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM; 1.3787 + aPageNum = pageCount; 1.3788 + } 1.3789 + 1.3790 + // Now, locate the current page we are on and 1.3791 + // and the page of the page number 1.3792 + nsIFrame* pageFrame = seqFrame->GetFirstPrincipalChild(); 1.3793 + while (pageFrame != nullptr) { 1.3794 + nsRect pageRect = pageFrame->GetRect(); 1.3795 + if (pageRect.Contains(pageRect.x, pt.y)) { 1.3796 + currentPage = pageFrame; 1.3797 + } 1.3798 + if (pageNum == aPageNum) { 1.3799 + fndPageFrame = pageFrame; 1.3800 + break; 1.3801 + } 1.3802 + pageNum++; 1.3803 + pageFrame = pageFrame->GetNextSibling(); 1.3804 + } 1.3805 + 1.3806 + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) { 1.3807 + if (currentPage) { 1.3808 + fndPageFrame = currentPage->GetPrevInFlow(); 1.3809 + if (!fndPageFrame) { 1.3810 + return NS_OK; 1.3811 + } 1.3812 + } else { 1.3813 + return NS_OK; 1.3814 + } 1.3815 + } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) { 1.3816 + if (currentPage) { 1.3817 + fndPageFrame = currentPage->GetNextInFlow(); 1.3818 + if (!fndPageFrame) { 1.3819 + return NS_OK; 1.3820 + } 1.3821 + } else { 1.3822 + return NS_OK; 1.3823 + } 1.3824 + } else { // If we get here we are doing "GoTo" 1.3825 + if (aPageNum < 0 || aPageNum > pageCount) { 1.3826 + return NS_OK; 1.3827 + } 1.3828 + } 1.3829 + 1.3830 + if (fndPageFrame) { 1.3831 + nscoord newYPosn = 1.3832 + nscoord(mPrintEngine->GetPrintPreviewScale() * fndPageFrame->GetPosition().y); 1.3833 + sf->ScrollTo(nsPoint(pt.x, newYPosn), nsIScrollableFrame::INSTANT); 1.3834 + } 1.3835 + return NS_OK; 1.3836 + 1.3837 +} 1.3838 + 1.3839 +/* readonly attribute nsIPrintSettings globalPrintSettings; */ 1.3840 +NS_IMETHODIMP 1.3841 +nsDocumentViewer::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings) 1.3842 +{ 1.3843 + return nsPrintEngine::GetGlobalPrintSettings(aGlobalPrintSettings); 1.3844 +} 1.3845 + 1.3846 +/* readonly attribute boolean doingPrint; */ 1.3847 +// XXX This always returns false for subdocuments 1.3848 +NS_IMETHODIMP 1.3849 +nsDocumentViewer::GetDoingPrint(bool *aDoingPrint) 1.3850 +{ 1.3851 + NS_ENSURE_ARG_POINTER(aDoingPrint); 1.3852 + 1.3853 + *aDoingPrint = false; 1.3854 + if (mPrintEngine) { 1.3855 + // XXX shouldn't this be GetDoingPrint() ? 1.3856 + return mPrintEngine->GetDoingPrintPreview(aDoingPrint); 1.3857 + } 1.3858 + return NS_OK; 1.3859 +} 1.3860 + 1.3861 +/* readonly attribute boolean doingPrintPreview; */ 1.3862 +// XXX This always returns false for subdocuments 1.3863 +NS_IMETHODIMP 1.3864 +nsDocumentViewer::GetDoingPrintPreview(bool *aDoingPrintPreview) 1.3865 +{ 1.3866 + NS_ENSURE_ARG_POINTER(aDoingPrintPreview); 1.3867 + 1.3868 + *aDoingPrintPreview = false; 1.3869 + if (mPrintEngine) { 1.3870 + return mPrintEngine->GetDoingPrintPreview(aDoingPrintPreview); 1.3871 + } 1.3872 + return NS_OK; 1.3873 +} 1.3874 + 1.3875 +/* readonly attribute nsIPrintSettings currentPrintSettings; */ 1.3876 +NS_IMETHODIMP 1.3877 +nsDocumentViewer::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) 1.3878 +{ 1.3879 + NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); 1.3880 + 1.3881 + *aCurrentPrintSettings = nullptr; 1.3882 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3883 + 1.3884 + return mPrintEngine->GetCurrentPrintSettings(aCurrentPrintSettings); 1.3885 +} 1.3886 + 1.3887 + 1.3888 +/* readonly attribute nsIDOMWindow currentChildDOMWindow; */ 1.3889 +NS_IMETHODIMP 1.3890 +nsDocumentViewer::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWindow) 1.3891 +{ 1.3892 + NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow); 1.3893 + *aCurrentChildDOMWindow = nullptr; 1.3894 + return NS_ERROR_NOT_IMPLEMENTED; 1.3895 +} 1.3896 + 1.3897 +/* void cancel (); */ 1.3898 +NS_IMETHODIMP 1.3899 +nsDocumentViewer::Cancel() 1.3900 +{ 1.3901 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3902 + return mPrintEngine->Cancelled(); 1.3903 +} 1.3904 + 1.3905 +/* void exitPrintPreview (); */ 1.3906 +NS_IMETHODIMP 1.3907 +nsDocumentViewer::ExitPrintPreview() 1.3908 +{ 1.3909 + if (GetIsPrinting()) 1.3910 + return NS_ERROR_FAILURE; 1.3911 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3912 + 1.3913 + if (GetIsPrintPreview()) { 1.3914 + ReturnToGalleyPresentation(); 1.3915 + } 1.3916 + return NS_OK; 1.3917 +} 1.3918 + 1.3919 +//---------------------------------------------------------------------------------- 1.3920 +// Enumerate all the documents for their titles 1.3921 +NS_IMETHODIMP 1.3922 +nsDocumentViewer::EnumerateDocumentNames(uint32_t* aCount, 1.3923 + char16_t*** aResult) 1.3924 +{ 1.3925 +#ifdef NS_PRINTING 1.3926 + NS_ENSURE_ARG(aCount); 1.3927 + NS_ENSURE_ARG_POINTER(aResult); 1.3928 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3929 + 1.3930 + return mPrintEngine->EnumerateDocumentNames(aCount, aResult); 1.3931 +#else 1.3932 + return NS_ERROR_FAILURE; 1.3933 +#endif 1.3934 +} 1.3935 + 1.3936 +/* readonly attribute boolean isFramesetFrameSelected; */ 1.3937 +NS_IMETHODIMP 1.3938 +nsDocumentViewer::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected) 1.3939 +{ 1.3940 +#ifdef NS_PRINTING 1.3941 + *aIsFramesetFrameSelected = false; 1.3942 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3943 + 1.3944 + return mPrintEngine->GetIsFramesetFrameSelected(aIsFramesetFrameSelected); 1.3945 +#else 1.3946 + return NS_ERROR_FAILURE; 1.3947 +#endif 1.3948 +} 1.3949 + 1.3950 +/* readonly attribute long printPreviewNumPages; */ 1.3951 +NS_IMETHODIMP 1.3952 +nsDocumentViewer::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages) 1.3953 +{ 1.3954 +#ifdef NS_PRINTING 1.3955 + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); 1.3956 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3957 + 1.3958 + return mPrintEngine->GetPrintPreviewNumPages(aPrintPreviewNumPages); 1.3959 +#else 1.3960 + return NS_ERROR_FAILURE; 1.3961 +#endif 1.3962 +} 1.3963 + 1.3964 +/* readonly attribute boolean isFramesetDocument; */ 1.3965 +NS_IMETHODIMP 1.3966 +nsDocumentViewer::GetIsFramesetDocument(bool *aIsFramesetDocument) 1.3967 +{ 1.3968 +#ifdef NS_PRINTING 1.3969 + *aIsFramesetDocument = false; 1.3970 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3971 + 1.3972 + return mPrintEngine->GetIsFramesetDocument(aIsFramesetDocument); 1.3973 +#else 1.3974 + return NS_ERROR_FAILURE; 1.3975 +#endif 1.3976 +} 1.3977 + 1.3978 +/* readonly attribute boolean isIFrameSelected; */ 1.3979 +NS_IMETHODIMP 1.3980 +nsDocumentViewer::GetIsIFrameSelected(bool *aIsIFrameSelected) 1.3981 +{ 1.3982 +#ifdef NS_PRINTING 1.3983 + *aIsIFrameSelected = false; 1.3984 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3985 + 1.3986 + return mPrintEngine->GetIsIFrameSelected(aIsIFrameSelected); 1.3987 +#else 1.3988 + return NS_ERROR_FAILURE; 1.3989 +#endif 1.3990 +} 1.3991 + 1.3992 +/* readonly attribute boolean isRangeSelection; */ 1.3993 +NS_IMETHODIMP 1.3994 +nsDocumentViewer::GetIsRangeSelection(bool *aIsRangeSelection) 1.3995 +{ 1.3996 +#ifdef NS_PRINTING 1.3997 + *aIsRangeSelection = false; 1.3998 + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); 1.3999 + 1.4000 + return mPrintEngine->GetIsRangeSelection(aIsRangeSelection); 1.4001 +#else 1.4002 + return NS_ERROR_FAILURE; 1.4003 +#endif 1.4004 +} 1.4005 + 1.4006 +//---------------------------------------------------------------------------------- 1.4007 +// Printing/Print Preview Helpers 1.4008 +//---------------------------------------------------------------------------------- 1.4009 + 1.4010 +//---------------------------------------------------------------------------------- 1.4011 +// Walks the document tree and tells each DocShell whether Printing/PP is happening 1.4012 +void 1.4013 +nsDocumentViewer::SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode, 1.4014 + bool aIsPrintingOrPP, 1.4015 + bool aStartAtTop) 1.4016 +{ 1.4017 + nsCOMPtr<nsIDocShellTreeItem> parentItem(do_QueryInterface(aParentNode)); 1.4018 + 1.4019 + // find top of "same parent" tree 1.4020 + if (aStartAtTop) { 1.4021 + if (aIsPrintingOrPP) { 1.4022 + while (parentItem) { 1.4023 + nsCOMPtr<nsIDocShellTreeItem> parent; 1.4024 + parentItem->GetSameTypeParent(getter_AddRefs(parent)); 1.4025 + if (!parent) { 1.4026 + break; 1.4027 + } 1.4028 + parentItem = do_QueryInterface(parent); 1.4029 + } 1.4030 + mTopContainerWhilePrinting = do_GetWeakReference(parentItem); 1.4031 + } else { 1.4032 + parentItem = do_QueryReferent(mTopContainerWhilePrinting); 1.4033 + } 1.4034 + } 1.4035 + 1.4036 + // Check to see if the DocShell's ContentViewer is printing/PP 1.4037 + nsCOMPtr<nsIContentViewerContainer> viewerContainer(do_QueryInterface(parentItem)); 1.4038 + if (viewerContainer) { 1.4039 + viewerContainer->SetIsPrinting(aIsPrintingOrPP); 1.4040 + } 1.4041 + 1.4042 + if (!aParentNode) { 1.4043 + return; 1.4044 + } 1.4045 + 1.4046 + // Traverse children to see if any of them are printing. 1.4047 + int32_t n; 1.4048 + aParentNode->GetChildCount(&n); 1.4049 + for (int32_t i=0; i < n; i++) { 1.4050 + nsCOMPtr<nsIDocShellTreeItem> child; 1.4051 + aParentNode->GetChildAt(i, getter_AddRefs(child)); 1.4052 + NS_ASSERTION(child, "child isn't nsIDocShell"); 1.4053 + if (child) { 1.4054 + SetIsPrintingInDocShellTree(child, aIsPrintingOrPP, false); 1.4055 + } 1.4056 + } 1.4057 + 1.4058 +} 1.4059 +#endif // NS_PRINTING 1.4060 + 1.4061 +bool 1.4062 +nsDocumentViewer::ShouldAttachToTopLevel() 1.4063 +{ 1.4064 + if (!mParentWidget) 1.4065 + return false; 1.4066 + 1.4067 + nsCOMPtr<nsIDocShellTreeItem> containerItem(mContainer); 1.4068 + if (!containerItem) 1.4069 + return false; 1.4070 + 1.4071 + // We always attach when using puppet widgets 1.4072 + if (nsIWidget::UsePuppetWidgets()) 1.4073 + return true; 1.4074 + 1.4075 +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) 1.4076 + // On windows, in the parent process we also attach, but just to 1.4077 + // chrome items 1.4078 + nsWindowType winType = mParentWidget->WindowType(); 1.4079 + if ((winType == eWindowType_toplevel || 1.4080 + winType == eWindowType_dialog || 1.4081 + winType == eWindowType_invisible) && 1.4082 + containerItem->ItemType() == nsIDocShellTreeItem::typeChrome) { 1.4083 + return true; 1.4084 + } 1.4085 +#endif 1.4086 + 1.4087 + return false; 1.4088 +} 1.4089 + 1.4090 +bool CollectDocuments(nsIDocument* aDocument, void* aData) 1.4091 +{ 1.4092 + if (aDocument) { 1.4093 + static_cast<nsCOMArray<nsIDocument>*>(aData)->AppendObject(aDocument); 1.4094 + aDocument->EnumerateSubDocuments(CollectDocuments, aData); 1.4095 + } 1.4096 + return true; 1.4097 +} 1.4098 + 1.4099 +void 1.4100 +nsDocumentViewer::DispatchEventToWindowTree(nsIDocument* aDoc, 1.4101 + const nsAString& aEvent) 1.4102 +{ 1.4103 + nsCOMArray<nsIDocument> targets; 1.4104 + CollectDocuments(aDoc, &targets); 1.4105 + for (int32_t i = 0; i < targets.Count(); ++i) { 1.4106 + nsIDocument* d = targets[i]; 1.4107 + nsContentUtils::DispatchTrustedEvent(d, d->GetWindow(), 1.4108 + aEvent, false, false, nullptr); 1.4109 + } 1.4110 +} 1.4111 + 1.4112 +//------------------------------------------------------------ 1.4113 +// XXX this always returns false for subdocuments 1.4114 +bool 1.4115 +nsDocumentViewer::GetIsPrinting() 1.4116 +{ 1.4117 +#ifdef NS_PRINTING 1.4118 + if (mPrintEngine) { 1.4119 + return mPrintEngine->GetIsPrinting(); 1.4120 + } 1.4121 +#endif 1.4122 + return false; 1.4123 +} 1.4124 + 1.4125 +//------------------------------------------------------------ 1.4126 +// Notification from the PrintEngine of the current Printing status 1.4127 +void 1.4128 +nsDocumentViewer::SetIsPrinting(bool aIsPrinting) 1.4129 +{ 1.4130 +#ifdef NS_PRINTING 1.4131 + // Set all the docShells in the docshell tree to be printing. 1.4132 + // that way if anyone of them tries to "navigate" it can't 1.4133 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.4134 + if (docShell || !aIsPrinting) { 1.4135 + SetIsPrintingInDocShellTree(docShell, aIsPrinting, true); 1.4136 + } else { 1.4137 + NS_WARNING("Did you close a window before printing?"); 1.4138 + } 1.4139 + 1.4140 + if (!aIsPrinting) { 1.4141 + mBeforeAndAfterPrint = nullptr; 1.4142 + } 1.4143 +#endif 1.4144 +} 1.4145 + 1.4146 +//------------------------------------------------------------ 1.4147 +// The PrintEngine holds the current value 1.4148 +// this called from inside the DocViewer. 1.4149 +// XXX it always returns false for subdocuments 1.4150 +bool 1.4151 +nsDocumentViewer::GetIsPrintPreview() 1.4152 +{ 1.4153 +#ifdef NS_PRINTING 1.4154 + if (mPrintEngine) { 1.4155 + return mPrintEngine->GetIsPrintPreview(); 1.4156 + } 1.4157 +#endif 1.4158 + return false; 1.4159 +} 1.4160 + 1.4161 +//------------------------------------------------------------ 1.4162 +// Notification from the PrintEngine of the current PP status 1.4163 +void 1.4164 +nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview) 1.4165 +{ 1.4166 +#ifdef NS_PRINTING 1.4167 + // Set all the docShells in the docshell tree to be printing. 1.4168 + // that way if anyone of them tries to "navigate" it can't 1.4169 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.4170 + if (docShell || !aIsPrintPreview) { 1.4171 + SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true); 1.4172 + } 1.4173 + if (!aIsPrintPreview) { 1.4174 + mBeforeAndAfterPrint = nullptr; 1.4175 + } 1.4176 +#endif 1.4177 + if (!aIsPrintPreview) { 1.4178 + if (mPresShell) { 1.4179 + DestroyPresShell(); 1.4180 + } 1.4181 + mWindow = nullptr; 1.4182 + mViewManager = nullptr; 1.4183 + mPresContext = nullptr; 1.4184 + mPresShell = nullptr; 1.4185 + } 1.4186 +} 1.4187 + 1.4188 +//---------------------------------------------------------------------------------- 1.4189 +// nsIDocumentViewerPrint IFace 1.4190 +//---------------------------------------------------------------------------------- 1.4191 + 1.4192 +//------------------------------------------------------------ 1.4193 +void 1.4194 +nsDocumentViewer::IncrementDestroyRefCount() 1.4195 +{ 1.4196 + ++mDestroyRefCount; 1.4197 +} 1.4198 + 1.4199 +//------------------------------------------------------------ 1.4200 + 1.4201 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.4202 +//------------------------------------------------------------ 1.4203 +// Reset ESM focus for all descendent doc shells. 1.4204 +static void 1.4205 +ResetFocusState(nsIDocShell* aDocShell) 1.4206 +{ 1.4207 + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); 1.4208 + if (!fm) 1.4209 + return; 1.4210 + 1.4211 + nsCOMPtr<nsISimpleEnumerator> docShellEnumerator; 1.4212 + aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent, 1.4213 + nsIDocShell::ENUMERATE_FORWARDS, 1.4214 + getter_AddRefs(docShellEnumerator)); 1.4215 + 1.4216 + nsCOMPtr<nsISupports> currentContainer; 1.4217 + bool hasMoreDocShells; 1.4218 + while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) 1.4219 + && hasMoreDocShells) { 1.4220 + docShellEnumerator->GetNext(getter_AddRefs(currentContainer)); 1.4221 + nsCOMPtr<nsIDOMWindow> win = do_GetInterface(currentContainer); 1.4222 + if (win) 1.4223 + fm->ClearFocus(win); 1.4224 + } 1.4225 +} 1.4226 +#endif // NS_PRINTING && NS_PRINT_PREVIEW 1.4227 + 1.4228 +void 1.4229 +nsDocumentViewer::ReturnToGalleyPresentation() 1.4230 +{ 1.4231 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.4232 + if (!GetIsPrintPreview()) { 1.4233 + NS_ERROR("Wow, we should never get here!"); 1.4234 + return; 1.4235 + } 1.4236 + 1.4237 + SetIsPrintPreview(false); 1.4238 + 1.4239 + mPrintEngine->TurnScriptingOn(true); 1.4240 + mPrintEngine->Destroy(); 1.4241 + mPrintEngine = nullptr; 1.4242 + 1.4243 + nsCOMPtr<nsIDocShell> docShell(mContainer); 1.4244 + ResetFocusState(docShell); 1.4245 + 1.4246 + SetTextZoom(mTextZoom); 1.4247 + SetFullZoom(mPageZoom); 1.4248 + SetMinFontSize(mMinFontSize); 1.4249 + Show(); 1.4250 + 1.4251 +#endif // NS_PRINTING && NS_PRINT_PREVIEW 1.4252 +} 1.4253 + 1.4254 +//------------------------------------------------------------ 1.4255 +// This called ONLY when printing has completed and the DV 1.4256 +// is being notified that it should get rid of the PrintEngine. 1.4257 +// 1.4258 +// BUT, if we are in Print Preview then we want to ignore the 1.4259 +// notification (we do not get rid of the PrintEngine) 1.4260 +// 1.4261 +// One small caveat: 1.4262 +// This IS called from two places in this module for cleaning 1.4263 +// up when an error occurred during the start up printing 1.4264 +// and print preview 1.4265 +// 1.4266 +void 1.4267 +nsDocumentViewer::OnDonePrinting() 1.4268 +{ 1.4269 +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) 1.4270 + if (mPrintEngine) { 1.4271 + nsRefPtr<nsPrintEngine> pe = mPrintEngine; 1.4272 + if (GetIsPrintPreview()) { 1.4273 + pe->DestroyPrintingData(); 1.4274 + } else { 1.4275 + mPrintEngine = nullptr; 1.4276 + pe->Destroy(); 1.4277 + } 1.4278 + 1.4279 + // We are done printing, now cleanup 1.4280 + if (mDeferredWindowClose) { 1.4281 + mDeferredWindowClose = false; 1.4282 + nsCOMPtr<nsIDOMWindow> win = 1.4283 + do_GetInterface(static_cast<nsIDocShell*>(mContainer)); 1.4284 + if (win) 1.4285 + win->Close(); 1.4286 + } else if (mClosingWhilePrinting) { 1.4287 + if (mDocument) { 1.4288 + mDocument->SetScriptGlobalObject(nullptr); 1.4289 + mDocument->Destroy(); 1.4290 + mDocument = nullptr; 1.4291 + } 1.4292 + mClosingWhilePrinting = false; 1.4293 + } 1.4294 + } 1.4295 +#endif // NS_PRINTING && NS_PRINT_PREVIEW 1.4296 +} 1.4297 + 1.4298 +NS_IMETHODIMP nsDocumentViewer::SetPageMode(bool aPageMode, nsIPrintSettings* aPrintSettings) 1.4299 +{ 1.4300 + // XXX Page mode is only partially working; it's currently used for 1.4301 + // reftests that require a paginated context 1.4302 + mIsPageMode = aPageMode; 1.4303 + 1.4304 + if (mPresShell) { 1.4305 + DestroyPresShell(); 1.4306 + } 1.4307 + 1.4308 + if (mPresContext) { 1.4309 + DestroyPresContext(); 1.4310 + } 1.4311 + 1.4312 + mViewManager = nullptr; 1.4313 + mWindow = nullptr; 1.4314 + 1.4315 + NS_ENSURE_STATE(mDocument); 1.4316 + if (aPageMode) 1.4317 + { 1.4318 + mPresContext = CreatePresContext(mDocument, 1.4319 + nsPresContext::eContext_PageLayout, FindContainerView()); 1.4320 + NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY); 1.4321 + mPresContext->SetPaginatedScrolling(true); 1.4322 + mPresContext->SetPrintSettings(aPrintSettings); 1.4323 + nsresult rv = mPresContext->Init(mDeviceContext); 1.4324 + NS_ENSURE_SUCCESS(rv, rv); 1.4325 + } 1.4326 + InitInternal(mParentWidget, nullptr, mBounds, true, false); 1.4327 + 1.4328 + Show(); 1.4329 + return NS_OK; 1.4330 +} 1.4331 + 1.4332 +NS_IMETHODIMP 1.4333 +nsDocumentViewer::GetHistoryEntry(nsISHEntry **aHistoryEntry) 1.4334 +{ 1.4335 + NS_IF_ADDREF(*aHistoryEntry = mSHEntry); 1.4336 + return NS_OK; 1.4337 +} 1.4338 + 1.4339 +NS_IMETHODIMP 1.4340 +nsDocumentViewer::GetIsTabModalPromptAllowed(bool *aAllowed) 1.4341 +{ 1.4342 + *aAllowed = !mHidden; 1.4343 + return NS_OK; 1.4344 +} 1.4345 + 1.4346 +NS_IMETHODIMP 1.4347 +nsDocumentViewer::GetIsHidden(bool *aHidden) 1.4348 +{ 1.4349 + *aHidden = mHidden; 1.4350 + return NS_OK; 1.4351 +} 1.4352 + 1.4353 +void 1.4354 +nsDocumentViewer::DestroyPresShell() 1.4355 +{ 1.4356 + // Break circular reference (or something) 1.4357 + mPresShell->EndObservingDocument(); 1.4358 + 1.4359 + nsCOMPtr<nsISelection> selection; 1.4360 + GetDocumentSelection(getter_AddRefs(selection)); 1.4361 + nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(selection); 1.4362 + if (selPrivate && mSelectionListener) 1.4363 + selPrivate->RemoveSelectionListener(mSelectionListener); 1.4364 + 1.4365 + nsAutoScriptBlocker scriptBlocker; 1.4366 + mPresShell->Destroy(); 1.4367 + mPresShell = nullptr; 1.4368 +} 1.4369 + 1.4370 +void 1.4371 +nsDocumentViewer::DestroyPresContext() 1.4372 +{ 1.4373 + mPresContext->Detach(); 1.4374 + mPresContext = nullptr; 1.4375 +} 1.4376 + 1.4377 +bool 1.4378 +nsDocumentViewer::IsInitializedForPrintPreview() 1.4379 +{ 1.4380 + return mInitializedForPrintPreview; 1.4381 +} 1.4382 + 1.4383 +void 1.4384 +nsDocumentViewer::InitializeForPrintPreview() 1.4385 +{ 1.4386 + mInitializedForPrintPreview = true; 1.4387 +} 1.4388 + 1.4389 +void 1.4390 +nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager, 1.4391 + nsPresContext* aPresContext, 1.4392 + nsIPresShell* aPresShell) 1.4393 +{ 1.4394 + if (mPresShell) { 1.4395 + DestroyPresShell(); 1.4396 + } 1.4397 + 1.4398 + mWindow = nullptr; 1.4399 + mViewManager = aViewManager; 1.4400 + mPresContext = aPresContext; 1.4401 + mPresShell = aPresShell; 1.4402 +} 1.4403 + 1.4404 +// Fires the "document-shown" event so that interested parties are aware of it. 1.4405 +NS_IMETHODIMP 1.4406 +nsDocumentShownDispatcher::Run() 1.4407 +{ 1.4408 + nsCOMPtr<nsIObserverService> observerService = 1.4409 + mozilla::services::GetObserverService(); 1.4410 + if (observerService) { 1.4411 + observerService->NotifyObservers(mDocument, "document-shown", nullptr); 1.4412 + } 1.4413 + return NS_OK; 1.4414 +} 1.4415 +