layout/base/nsDocumentViewer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial