nsDocumentViewer.cpp 132 KB
Newer Older
1
2
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
4
5
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6

7
8
/* container for a document and its presentation */

9
#include "gfxContext.h"
10
#include "mozilla/PresShell.h"
11
#include "mozilla/RestyleManager.h"
12
#include "mozilla/ServoStyleSet.h"
13
#include "nscore.h"
kipp%netscape.com's avatar
kipp%netscape.com committed
14
15
16
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsString.h"
17
#include "nsReadableUtils.h"
18
#include "nsIContent.h"
19
#include "nsIContentViewer.h"
20
#include "nsIDocumentViewerPrint.h"
21
#include "mozilla/dom/BeforeUnloadEvent.h"
22
#include "mozilla/dom/PopupBlocker.h"
23
#include "mozilla/dom/Document.h"
24
#include "mozilla/dom/DocumentInlines.h"
25
#include "mozilla/dom/DocGroup.h"
26
#include "nsPresContext.h"
kipp%netscape.com's avatar
kipp%netscape.com committed
27
#include "nsIFrame.h"
28
#include "nsIWritablePropertyBag2.h"
29
#include "nsSubDocumentFrame.h"
30
#include "nsGenericHTMLElement.h"
31
#include "nsStubMutationObserver.h"
kipp%netscape.com's avatar
kipp%netscape.com committed
32

33
#include "nsISelectionListener.h"
34
#include "mozilla/dom/Selection.h"
35
#include "nsContentUtils.h"
36
#ifdef ACCESSIBILITY
37
#  include "mozilla/a11y/DocAccessible.h"
38
#endif
39
#include "mozilla/BasicEvents.h"
40
#include "mozilla/Encoding.h"
41
#include "mozilla/ErrorResult.h"
42
#include "mozilla/Preferences.h"
43
#include "mozilla/WeakPtr.h"
44
#include "mozilla/StaticPrefs_javascript.h"
45
46
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
kipp%netscape.com's avatar
kipp%netscape.com committed
47

48
#include "nsViewManager.h"
49
#include "nsView.h"
kipp%netscape.com's avatar
kipp%netscape.com committed
50

51
#include "nsPageSequenceFrame.h"
52
#include "nsNetUtil.h"
53
#include "nsIContentViewerEdit.h"
54
#include "mozilla/css/Loader.h"
55
#include "nsIInterfaceRequestor.h"
56
#include "nsIInterfaceRequestorUtils.h"
57
#include "nsDocShell.h"
58
#include "nsIBaseWindow.h"
59
#include "nsILayoutHistoryState.h"
60
#include "nsCharsetSource.h"
61
#include "mozilla/ReflowInput.h"
cbiesinger%web.de's avatar
cbiesinger%web.de committed
62
63
#include "nsIImageLoadingContent.h"
#include "nsCopySupport.h"
64
#ifdef MOZ_XUL
65
#  include "nsXULPopupManager.h"
66
#endif
67

68
#include "nsIClipboardHelper.h"
69

70
#include "nsPIDOMWindow.h"
71
#include "nsGlobalWindow.h"
72
#include "nsDOMNavigationTiming.h"
73
#include "nsPIWindowRoot.h"
74
#include "nsJSEnvironment.h"
75
#include "nsFocusManager.h"
76

77
#include "nsIScrollableFrame.h"
78
#include "nsStyleSheetService.h"
79
#include "nsILoadContext.h"
80
#include "mozilla/ThrottledEventQueue.h"
81
#include "nsIPrompt.h"
82
#include "imgIContainer.h"  // image animation mode constants
83

84
85
#include "nsSandboxFlags.h"

86
87
#include "mozilla/DocLoadingTimelineMarker.h"

88
89
90
91
92
//--------------------------
// Printing Include
//---------------------------
#ifdef NS_PRINTING

93
#  include "nsIWebBrowserPrint.h"
94

95
#  include "nsPrintJob.h"
96

97
// Print Options
98
99
100
#  include "nsIPrintSettings.h"
#  include "nsIPrintSettingsService.h"
#  include "nsISimpleEnumerator.h"
101

102
#  include "nsIPluginDocument.h"
103

104
#endif  // NS_PRINTING
mkaply%us.ibm.com's avatar
#97907    
mkaply%us.ibm.com committed
105

106
// focus
107
#include "nsIDOMEventListener.h"
mjudge%netscape.com's avatar
mjudge%netscape.com committed
108
#include "nsISelectionController.h"
109

110
#include "mozilla/EventDispatcher.h"
111
112
113
#include "nsISHEntry.h"
#include "nsISHistory.h"
#include "nsIWebNavigation.h"
114
#include "mozilla/dom/XMLHttpRequestMainThread.h"
115

116
// paint forcing
117
#include <stdio.h>
118
#include "mozilla/BasePrincipal.h"
119
#include "mozilla/dom/Element.h"
120
#include "mozilla/dom/Event.h"
121
#include "mozilla/Telemetry.h"
122
#include "mozilla/dom/ScriptLoader.h"
123
#include "mozilla/dom/WindowGlobalChild.h"
124

125
using namespace mozilla;
126
using namespace mozilla::dom;
127

128
#define BEFOREUNLOAD_DISABLED_PREFNAME "dom.disable_beforeunload"
129
130
#define BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME \
  "dom.require_user_interaction_for_beforeunload"
kipp%netscape.com's avatar
kipp%netscape.com committed
131

132
//-----------------------------------------------------
133
134
// LOGGING
#include "LayoutLogging.h"
135
#include "mozilla/Logging.h"
136

137
138
extern mozilla::LazyLogModule gPageCacheLog;

139
#ifdef NS_PRINTING
140
141
static mozilla::LazyLogModule gPrintingLog("printing");

142
#  define PR_PL(_p1) MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1);
143
#endif  // NS_PRINTING
144

145
#define PRT_YESNO(_p) ((_p) ? "YES" : "NO")
146
//-----------------------------------------------------
147

148
class nsDocumentViewer;
149
150
151
namespace mozilla {
class AutoPrintEventDispatcher;
}
152
153
154

// a small delegate class used to avoid circular references

155
156
class nsDocViewerSelectionListener final : public nsISelectionListener {
 public:
157
158
159
  // nsISupports interface...
  NS_DECL_ISUPPORTS

160
  // nsISelectionListerner interface
161
  NS_DECL_NSISELECTIONLISTENER
162

163
164
  nsDocViewerSelectionListener()
      : mDocViewer(nullptr), mSelectionWasCollapsed(true) {}
165

166
  nsresult Init(nsDocumentViewer* aDocViewer);
167

168
  void Disconnect() { mDocViewer = nullptr; }
169

170
171
 protected:
  virtual ~nsDocViewerSelectionListener() {}
172

173
174
  nsDocumentViewer* mDocViewer;
  bool mSelectionWasCollapsed;
175
176
};

177
178
/** editor Implementation of the FocusListener interface
 */
179
180
class nsDocViewerFocusListener final : public nsIDOMEventListener {
 public:
181
182
183
184
185
  /** default constructor
   */
  nsDocViewerFocusListener();

  NS_DECL_ISUPPORTS
186
  NS_DECL_NSIDOMEVENTLISTENER
187

188
  nsresult Init(nsDocumentViewer* aDocViewer);
189

190
  void Disconnect() { mDocViewer = nullptr; }
191

192
 protected:
193
194
195
196
  /** default destructor
   */
  virtual ~nsDocViewerFocusListener();

197
198
 private:
  nsDocumentViewer* mDocViewer;
199
200
};

201
202
203
204
205
namespace viewer_detail {

/**
 * Mutation observer for use until we hand ourselves over to our SHEntry.
 */
206
207
class BFCachePreventionObserver final : public nsStubMutationObserver {
 public:
208
  explicit BFCachePreventionObserver(Document* aDocument)
209
      : mDocument(aDocument) {}
210
211
212
213
214
215
216
217
218
219
220
221
222

  NS_DECL_ISUPPORTS

  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED

  // Stop observing the document.
  void Disconnect();

223
 private:
224
225
226
227
228
  ~BFCachePreventionObserver() = default;

  // Helper for the work that needs to happen when mutations happen.
  void MutationHappened();

229
  Document* mDocument;  // Weak; we get notified if it dies
230
231
232
233
};

NS_IMPL_ISUPPORTS(BFCachePreventionObserver, nsIMutationObserver)

234
235
void BFCachePreventionObserver::CharacterDataChanged(
    nsIContent* aContent, const CharacterDataChangeInfo&) {
236
237
238
  MutationHappened();
}

239
240
241
242
243
void BFCachePreventionObserver::AttributeChanged(Element* aElement,
                                                 int32_t aNameSpaceID,
                                                 nsAtom* aAttribute,
                                                 int32_t aModType,
                                                 const nsAttrValue* aOldValue) {
244
245
246
  MutationHappened();
}

247
void BFCachePreventionObserver::ContentAppended(nsIContent* aFirstNewContent) {
248
249
250
  MutationHappened();
}

251
void BFCachePreventionObserver::ContentInserted(nsIContent* aChild) {
252
253
254
  MutationHappened();
}

255
256
void BFCachePreventionObserver::ContentRemoved(nsIContent* aChild,
                                               nsIContent* aPreviousSibling) {
257
258
259
  MutationHappened();
}

260
void BFCachePreventionObserver::NodeWillBeDestroyed(const nsINode* aNode) {
261
262
263
  mDocument = nullptr;
}

264
void BFCachePreventionObserver::Disconnect() {
265
266
267
268
269
270
271
272
  if (mDocument) {
    mDocument->RemoveMutationObserver(this);
    // It will no longer tell us when it goes away, so make sure we're
    // not holding a dangling ref.
    mDocument = nullptr;
  }
}

273
274
275
276
void BFCachePreventionObserver::MutationHappened() {
  MOZ_ASSERT(
      mDocument,
      "How can we not have a document but be getting notified for mutations?");
277
278
279
280
  mDocument->DisallowBFCaching();
  Disconnect();
}

281
}  // namespace viewer_detail
282
283

using viewer_detail::BFCachePreventionObserver;
284

285
//-------------------------------------------------------------
286
class nsDocumentViewer final : public nsIContentViewer,
287
288
                               public nsIContentViewerEdit,
                               public nsIDocumentViewerPrint
289
#ifdef NS_PRINTING
290
291
    ,
                               public nsIWebBrowserPrint
292
293
#endif

kipp%netscape.com's avatar
kipp%netscape.com committed
294
{
295
  friend class nsDocViewerSelectionListener;
296
  friend class nsPagePrintTimer;
297
  friend class nsPrintJob;
298

299
 public:
300
  nsDocumentViewer();
301

kipp%netscape.com's avatar
kipp%netscape.com committed
302
303
304
305
  // nsISupports interface...
  NS_DECL_ISUPPORTS

  // nsIContentViewer interface...
306
  NS_DECL_NSICONTENTVIEWER
kipp%netscape.com's avatar
kipp%netscape.com committed
307

308
309
310
  // nsIContentViewerEdit
  NS_DECL_NSICONTENTVIEWEREDIT

311
#ifdef NS_PRINTING
312
313
  // nsIWebBrowserPrint
  NS_DECL_NSIWEBBROWSERPRINT
314
#endif
315

316
  typedef void (*CallChildFunc)(nsDocumentViewer* aViewer, void* aClosure);
317
  void CallChildren(CallChildFunc aFunc, void* aClosure);
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  typedef void (*PresContextFunc)(nsPresContext*, void* aClosure);
  /**
   * Calls a `CallChildFunc` on all children, a `PresContextFunc`
   * on all external documents' pres contexts  of our document, and then
   * finally on _this_ pres context, in that order.
   *
   * The children function is expected to call this function reentrantly, and
   * thus the `PresContextFunc` won't be called for the children's pres context
   * directly here.
   *
   * FIXME(emilio): Better name for this appreciated.
   */
  void PropagateToPresContextsHelper(CallChildFunc, PresContextFunc,
                                     void* aClosure);

334
  // nsIDocumentViewerPrint Printing Methods
335
  NS_DECL_NSIDOCUMENTVIEWERPRINT
336

337
338
  void EmulateMediumInternal(nsAtom*);

339
340
341
  using ColorSchemeOverride = Maybe<StylePrefersColorScheme>;
  void EmulatePrefersColorSchemeInternal(const ColorSchemeOverride&);

342
 protected:
343
  virtual ~nsDocumentViewer();
kipp%netscape.com's avatar
kipp%netscape.com committed
344

345
 private:
346
347
348
349
  /**
   * Creates a view manager, root view, and widget for the root view, setting
   * mViewManager and mWindow.
   * @param aSize the initial size in appunits
350
351
   * @param aContainerView the container view to hook our root view up
   * to as a child, or null if this will be the root view manager
352
   */
353
  nsresult MakeWindow(const nsSize& aSize, nsView* aContainerView);
354

355
356
357
  /**
   * Create our device context
   */
358
  nsresult CreateDeviceContext(nsView* aContainerView);
359
360

  /**
361
362
   * If aDoCreation is true, this creates the device context, creates a
   * prescontext if necessary, and calls MakeWindow.
363
364
365
   *
   * If aForceSetNewDocument is false, then SetNewDocument won't be
   * called if the window's current document is already mDocument.
366
   */
367
  nsresult InitInternal(nsIWidget* aParentWidget, nsISupports* aState,
368
                        mozilla::dom::WindowGlobalChild* aActor,
369
                        const nsIntRect& aBounds, bool aDoCreation,
370
371
                        bool aNeedMakeCX = true,
                        bool aForceSetNewDocument = true);
372
373
374
375
  /**
   * @param aDoInitialReflow set to true if you want to kick off the initial
   * reflow
   */
376
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
377
  nsresult InitPresentationStuff(bool aDoInitialReflow);
378

379
380
381
  already_AddRefed<nsINode> GetPopupNode();
  already_AddRefed<nsINode> GetPopupLinkNode();
  already_AddRefed<nsIImageLoadingContent> GetPopupImageNode();
382

383
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
384
385
386
  nsresult GetContentSizeInternal(int32_t* aWidth, int32_t* aHeight,
                                  nscoord aMaxWidth, nscoord aMaxHeight);

387
  void PrepareToStartLoad(void);
388
389
390

  nsresult SyncParentSubDocMap();

391
  mozilla::dom::Selection* GetDocumentSelection();
392

393
  void DestroyPresShell();
394
  void DestroyPresContext();
395

396
397
  void InvalidatePotentialSubDocDisplayItem();

398
399
400
#ifdef NS_PRINTING
  // Called when the DocViewer is notified that the state
  // of Printing or PP has changed
401
  void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
402
403
                                   bool aIsPrintingOrPP, bool aStartAtTop);
#endif  // NS_PRINTING
404

405
406
407
  // Whether we should attach to the top level widget. This is true if we
  // are sharing/recycling a single base widget and not creating multiple
  // child widgets.
408
  bool ShouldAttachToTopLevel();
409

410
 protected:
411
  // Returns the current viewmanager.  Might be null.
412
  nsViewManager* GetViewManager();
413

414
415
  void DetachFromTopLevelWidget();

kipp%netscape.com's avatar
kipp%netscape.com committed
416
417
418
419
420
  // IMPORTANT: The ownership implicit in the following member
  // variables has been explicitly checked and set using nsCOMPtr
  // for owning pointers and raw COM interface pointers for weak
  // (ie, non owning) references. If you add any members to this
  // class, please make the ownership explicit (pinkerton, scc).
421

422
  WeakPtr<nsDocShell> mContainer;  // it owns me!
423
  nsWeakPtr mTopContainerWhilePrinting;
424
  RefPtr<nsDeviceContext> mDeviceContext;  // We create and own this baby
kipp%netscape.com's avatar
kipp%netscape.com committed
425

426
  // the following six items are explicitly in this order
kipp%netscape.com's avatar
kipp%netscape.com committed
427
  // so they will be destroyed in the reverse order (pinkerton, scc)
428
  nsCOMPtr<Document> mDocument;
429
  nsCOMPtr<nsIWidget> mWindow;  // may be null
430
  RefPtr<nsViewManager> mViewManager;
431
  RefPtr<nsPresContext> mPresContext;
432
  RefPtr<PresShell> mPresShell;
kipp%netscape.com's avatar
kipp%netscape.com committed
433

434
  RefPtr<nsDocViewerSelectionListener> mSelectionListener;
435
  RefPtr<nsDocViewerFocusListener> mFocusListener;
436

437
  nsCOMPtr<nsIContentViewer> mPreviousViewer;
438
  nsCOMPtr<nsISHEntry> mSHEntry;
439
440
441
  // Observer that will prevent bfcaching if it gets notified.  This
  // is non-null precisely when mSHEntry is non-null.
  RefPtr<BFCachePreventionObserver> mBFCachePreventionObserver;
442

443
444
  nsIWidget* mParentWidget;  // purposely won't be ref counted.  May be null
  bool mAttachedToParent;    // view is attached to the parent widget
445

446
447
  nsIntRect mBounds;

448
449
  // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
  // presshell only.
450
  float mTextZoom;  // Text zoom, defaults to 1.0
451
  float mPageZoom;
452
  float mOverrideDPPX;  // DPPX overrided, defaults to 0.0
453

454
  int16_t mNumURLStarts;
455
  int16_t mDestroyBlockedCount;
456

457
458
459
  unsigned mStopped : 1;
  unsigned mLoaded : 1;
  unsigned mDeferredWindowClose : 1;
460
461
462
  // document management data
  //   these items are specific to markup documents (html and xml)
  //   may consider splitting these out into a subclass
463
464
465
  unsigned mIsSticky : 1;
  unsigned mInPermitUnload : 1;
  unsigned mInPermitUnloadPrompt : 1;
466

467
#ifdef NS_PRINTING
468
  unsigned mClosingWhilePrinting : 1;
469

470
#  if NS_PRINT_PREVIEW
471
  unsigned mPrintPreviewZoomed : 1;
Olli Pettay's avatar
Olli Pettay committed
472

473
  // These data members support delayed printing when the document is loading
474
475
476
  unsigned mPrintIsPending : 1;
  unsigned mPrintDocIsFullyLoaded : 1;
  nsCOMPtr<nsIPrintSettings> mCachedPrintSettings;
477
  nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
478

479
480
481
  RefPtr<nsPrintJob> mPrintJob;
  float mOriginalPrintPreviewScale;
  float mPrintPreviewZoom;
482
  UniquePtr<AutoPrintEventDispatcher> mAutoBeforeAndAfterPrint;
483
#  endif  // NS_PRINT_PREVIEW
484

485
#endif  // NS_PRINTING
486

487
  /* character set member data */
488
  int32_t mHintCharsetSource;
489
490
491
  const Encoding* mHintCharset;
  const Encoding* mForceCharacterSet;

492
493
494
  bool mIsPageMode;
  bool mInitializedForPrintPreview;
  bool mHidden;
kipp%netscape.com's avatar
kipp%netscape.com committed
495
496
};

497
498
499
500
501
502
503
504
505
namespace mozilla {

/**
 * A RAII class for automatic dispatch of the 'beforeprint' and 'afterprint'
 * events ('beforeprint' on construction, 'afterprint' on destruction).
 *
 * https://developer.mozilla.org/en-US/docs/Web/Events/beforeprint
 * https://developer.mozilla.org/en-US/docs/Web/Events/afterprint
 */
506
507
class AutoPrintEventDispatcher {
 public:
508
  explicit AutoPrintEventDispatcher(Document* aTop) : mTop(aTop) {
509
    DispatchEventToWindowTree(NS_LITERAL_STRING("beforeprint"));
510
  }
511
  ~AutoPrintEventDispatcher() {
512
    DispatchEventToWindowTree(NS_LITERAL_STRING("afterprint"));
513
514
  }

515
516
 private:
  void DispatchEventToWindowTree(const nsAString& aEvent) {
517
    nsTArray<nsCOMPtr<Document>> targets;
518
    CollectDocuments(mTop, &targets);
519
    for (nsCOMPtr<Document>& doc : targets) {
520
521
522
      nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
                                           CanBubble::eNo, Cancelable::eNo,
                                           nullptr);
523
    }
524
  }
525

526
  static bool CollectDocuments(Document* aDocument, void* aData) {
527
    if (aDocument) {
528
      static_cast<nsTArray<nsCOMPtr<Document>>*>(aData)->AppendElement(
529
          aDocument);
530
531
532
      aDocument->EnumerateSubDocuments(CollectDocuments, aData);
    }
    return true;
533
534
  }

535
  nsCOMPtr<Document> mTop;
536
537
};

538
}  // namespace mozilla
539

540
541
class nsDocumentShownDispatcher : public Runnable {
 public:
542
  explicit nsDocumentShownDispatcher(nsCOMPtr<Document> aDocument)
543
      : Runnable("nsDocumentShownDispatcher"), mDocument(aDocument) {}
544

545
  NS_IMETHOD Run() override;
546

547
 private:
548
  nsCOMPtr<Document> mDocument;
549
550
};

551
//------------------------------------------------------------------
552
// nsDocumentViewer
553
//------------------------------------------------------------------
kipp%netscape.com's avatar
kipp%netscape.com committed
554

555
//------------------------------------------------------------------
556
already_AddRefed<nsIContentViewer> NS_NewContentViewer() {
557
  RefPtr<nsDocumentViewer> viewer = new nsDocumentViewer();
558
  return viewer.forget();
kipp%netscape.com's avatar
kipp%netscape.com committed
559
560
}

561
void nsDocumentViewer::PrepareToStartLoad() {
562
563
564
  MOZ_DIAGNOSTIC_ASSERT(!GetIsPrintPreview(),
                        "Print preview tab should never navigate");

565
566
  mStopped = false;
  mLoaded = false;
567
568
  mAttachedToParent = false;
  mDeferredWindowClose = false;
569
570

#ifdef NS_PRINTING
571
  mPrintIsPending = false;
572
  mPrintDocIsFullyLoaded = false;
573
  mClosingWhilePrinting = false;
574

575
  // Make sure we have destroyed it and cleared the data member
576
577
578
  if (mPrintJob) {
    mPrintJob->Destroy();
    mPrintJob = nullptr;
579
  }
580

581
#endif  // NS_PRINTING
kipp%netscape.com's avatar
kipp%netscape.com committed
582
583
}

584
nsDocumentViewer::nsDocumentViewer()
585
586
587
588
589
590
591
592
593
594
595
596
597
    : mParentWidget(nullptr),
      mAttachedToParent(false),
      mTextZoom(1.0),
      mPageZoom(1.0),
      mOverrideDPPX(0.0),
      mNumURLStarts(0),
      mDestroyBlockedCount(0),
      mStopped(false),
      mLoaded(false),
      mDeferredWindowClose(false),
      mIsSticky(true),
      mInPermitUnload(false),
      mInPermitUnloadPrompt(false),
598
#ifdef NS_PRINTING
599
      mClosingWhilePrinting(false),
600
#  if NS_PRINT_PREVIEW
601
602
603
604
605
      mPrintPreviewZoomed(false),
      mPrintIsPending(false),
      mPrintDocIsFullyLoaded(false),
      mOriginalPrintPreviewScale(0.0),
      mPrintPreviewZoom(1.0),
606
607
#  endif  // NS_PRINT_PREVIEW
#endif    // NS_PRINTING
608
609
610
611
612
613
      mHintCharsetSource(kCharsetUninitialized),
      mHintCharset(nullptr),
      mForceCharacterSet(nullptr),
      mIsPageMode(false),
      mInitializedForPrintPreview(false),
      mHidden(false) {
614
  PrepareToStartLoad();
kipp%netscape.com's avatar
kipp%netscape.com committed
615
616
}

617
618
NS_IMPL_ADDREF(nsDocumentViewer)
NS_IMPL_RELEASE(nsDocumentViewer)
619

620
NS_INTERFACE_MAP_BEGIN(nsDocumentViewer)
621
622
623
624
  NS_INTERFACE_MAP_ENTRY(nsIContentViewer)
  NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit)
  NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentViewer)
625
#ifdef NS_PRINTING
626
  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint)
627
628
#endif
NS_INTERFACE_MAP_END
kipp%netscape.com's avatar
kipp%netscape.com committed
629

630
nsDocumentViewer::~nsDocumentViewer() {
631
  if (mDocument) {
632
    Close(nullptr);
633
    mDocument->Destroy();
634
  }
635

636
#ifdef NS_PRINTING
637
638
639
  if (mPrintJob) {
    mPrintJob->Destroy();
    mPrintJob = nullptr;
Matt Woodrow's avatar
Matt Woodrow committed
640
  }
641
#endif
Matt Woodrow's avatar
Matt Woodrow committed
642

643
  MOZ_RELEASE_ASSERT(mDestroyBlockedCount == 0);
644
645
646
  NS_ASSERTION(!mPresShell && !mPresContext,
               "User did not call nsIContentViewer::Destroy");
  if (mPresShell || mPresContext) {
647
648
    // Make sure we don't hand out a reference to the content viewer to
    // the SHEntry!
649
    mSHEntry = nullptr;
650

651
    Destroy();
652
  }
kipp%netscape.com's avatar
kipp%netscape.com committed
653

654
655
656
657
658
659
660
661
  if (mSelectionListener) {
    mSelectionListener->Disconnect();
  }

  if (mFocusListener) {
    mFocusListener->Disconnect();
  }

662
  // XXX(?) Revoke pending invalidate events
kipp%netscape.com's avatar
kipp%netscape.com committed
663
664
665
666
667
668
}

/*
 * This method is called by the Document Loader once a document has
 * been created for a particular data stream...  The content viewer
 * must cache this document for later use when Init(...) is called.
669
670
671
 *
 * This method is also called when an out of band document.write() happens.
 * In that case, the document passed in is the same as the previous document.
kipp%netscape.com's avatar
kipp%netscape.com committed
672
 */
673
674
/* virtual */
void nsDocumentViewer::LoadStart(Document* aDocument) {
675
676
  MOZ_ASSERT(aDocument);

677
  if (!mDocument) {
678
    mDocument = aDocument;
679
  }
kipp%netscape.com's avatar
kipp%netscape.com committed
680
681
}

682
nsresult nsDocumentViewer::SyncParentSubDocMap() {
683
684
685
686
687
  nsCOMPtr<nsIDocShell> docShell(mContainer);
  if (!docShell) {
    return NS_OK;
  }

688
  nsCOMPtr<nsPIDOMWindowOuter> pwin(docShell->GetWindow());
689
690
691
692
693
694
695
696
697
698
  if (!mDocument || !pwin) {
    return NS_OK;
  }

  nsCOMPtr<Element> element = pwin->GetFrameElementInternal();
  if (!element) {
    return NS_OK;
  }

  nsCOMPtr<nsIDocShellTreeItem> parent;
699
  docShell->GetInProcessParent(getter_AddRefs(parent));
700

701
702
  nsCOMPtr<nsPIDOMWindowOuter> parent_win =
      parent ? parent->GetWindow() : nullptr;
703
704
  if (!parent_win) {
    return NS_OK;
705
706
  }

707
  nsCOMPtr<Document> parent_doc = parent_win->GetDoc();
708
709
  if (!parent_doc) {
    return NS_OK;
710
711
  }

712
  if (mDocument && parent_doc->GetSubDocumentFor(element) != mDocument &&
713
      parent_doc->EventHandlingSuppressed()) {
714
    mDocument->SuppressEventHandling(parent_doc->EventHandlingSuppressed());
715
716
  }
  return parent_doc->SetSubDocumentFor(element, mDocument);
717
718
}

kipp%netscape.com's avatar
kipp%netscape.com committed
719
NS_IMETHODIMP
720
nsDocumentViewer::SetContainer(nsIDocShell* aContainer) {
721
  mContainer = static_cast<nsDocShell*>(aContainer);
722
723
724
725
726
727

  // We're loading a new document into the window where this document
  // viewer lives, sync the parent document's frame element -> sub
  // document map

  return SyncParentSubDocMap();
kipp%netscape.com's avatar
kipp%netscape.com committed
728
729
730
}

NS_IMETHODIMP
731
732
nsDocumentViewer::GetContainer(nsIDocShell** aResult) {
  NS_ENSURE_ARG_POINTER(aResult);
733

734
735
736
  nsCOMPtr<nsIDocShell> container(mContainer);
  container.swap(*aResult);
  return NS_OK;
kipp%netscape.com's avatar
kipp%netscape.com committed
737
738
739
}

NS_IMETHODIMP
740
741
742
nsDocumentViewer::Init(nsIWidget* aParentWidget, const nsIntRect& aBounds,
                       WindowGlobalChild* aActor) {
  return InitInternal(aParentWidget, nullptr, aActor, aBounds, true);
743
744
}

745
nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) {
746
747
748
749
750
751
752
753
754
  // We assert this because initializing the pres shell could otherwise cause
  // re-entrancy into nsDocumentViewer methods, which might cause a different
  // pres shell to be created.  Callers of InitPresentationStuff should ensure
  // the call is appropriately bounded by an nsAutoScriptBlocker to decide
  // when it is safe for these re-entrant calls to be made.
  MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
             "InitPresentationStuff must only be called when scripts are "
             "blocked");

755
  if (GetIsPrintPreview()) return NS_OK;
756

757
  NS_ASSERTION(!mPresShell, "Someone should have destroyed the presshell!");
758

759
  // Now make the shell for the document
760
  mPresShell = mDocument->CreatePresShell(mPresContext, mViewManager);
761
762
  if (!mPresShell) {
    return NS_ERROR_FAILURE;
763
  }
764

765
  if (aDoInitialReflow) {
766
    // Since Initialize() will create frames for *all* items
767
768
769
770
771
772
773
774
    // that are currently in the document tree, we need to flush
    // any pending notifications to prevent the content sink from
    // duplicating layout frames for content it has added to the tree
    // but hasn't notified the document about. (Bug 154018)
    //
    // Note that we are flushing before we add mPresShell as an observer
    // to avoid bogus notifications.

775
    mDocument->FlushPendingNotifications(FlushType::ContentAndNotify);
776
777
  }

778
779
780
  mPresShell->BeginObservingDocument();

  // Initialize our view manager
781
  int32_t p2a = mPresContext->AppUnitsPerDevPixel();
782
783
784
  MOZ_ASSERT(
      p2a ==
      mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());