Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp
Warning:line 2105, column 7
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_layout_base1.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/layout/forms -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/mathml -I /var/lib/jenkins/workspace/firefox-scan-build/layout/painting -I /var/lib/jenkins/workspace/firefox-scan-build/layout/printing -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/tables -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul/tree -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/dom/svg -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/view -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_layout_base1.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/* container for a document and its presentation */
8
9#include "gfxContext.h"
10#include "mozilla/PresShell.h"
11#include "mozilla/RestyleManager.h"
12#include "mozilla/ServoStyleSet.h"
13#include "mozilla/StaticPrefs_print.h"
14#include "mozilla/Telemetry.h"
15#include "nsThreadUtils.h"
16#include "nscore.h"
17#include "nsCOMPtr.h"
18#include "nsCRT.h"
19#include "nsFrameSelection.h"
20#include "nsString.h"
21#include "nsReadableUtils.h"
22#include "nsIContent.h"
23#include "nsIDocumentViewer.h"
24#include "nsIDocumentViewerPrint.h"
25#include "nsIScreen.h"
26#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
27#include "mozilla/dom/BrowsingContext.h"
28#include "mozilla/dom/BeforeUnloadEvent.h"
29#include "mozilla/dom/PopupBlocker.h"
30#include "mozilla/dom/Document.h"
31#include "mozilla/dom/DocumentInlines.h"
32#include "mozilla/dom/DocGroup.h"
33#include "mozilla/dom/FragmentDirective.h"
34#include "mozilla/widget/Screen.h"
35#include "nsPresContext.h"
36#include "nsIFrame.h"
37#include "nsIWritablePropertyBag2.h"
38#include "nsSubDocumentFrame.h"
39#include "nsGenericHTMLElement.h"
40#include "nsStubMutationObserver.h"
41
42#include "nsISelectionListener.h"
43#include "mozilla/dom/Selection.h"
44#include "nsContentUtils.h"
45#ifdef ACCESSIBILITY1
46# include "mozilla/a11y/DocAccessible.h"
47#endif
48#include "mozilla/BasicEvents.h"
49#include "mozilla/Encoding.h"
50#include "mozilla/ErrorResult.h"
51#include "mozilla/Preferences.h"
52#include "mozilla/ScrollContainerFrame.h"
53#include "mozilla/SpinEventLoopUntil.h"
54#include "mozilla/WeakPtr.h"
55#include "mozilla/StaticPrefs_dom.h"
56#include "mozilla/StaticPrefs_javascript.h"
57#include "mozilla/StaticPrefs_fission.h"
58#include "mozilla/StaticPrefs_print.h"
59#include "mozilla/StyleSheet.h"
60#include "mozilla/StyleSheetInlines.h"
61#include "mozilla/Try.h"
62
63#include "nsViewManager.h"
64#include "nsView.h"
65
66#include "nsPageSequenceFrame.h"
67#include "nsNetUtil.h"
68#include "nsIDocumentViewerEdit.h"
69#include "mozilla/css/Loader.h"
70#include "nsIInterfaceRequestor.h"
71#include "nsIInterfaceRequestorUtils.h"
72#include "nsDocShell.h"
73#include "nsIBaseWindow.h"
74#include "nsILayoutHistoryState.h"
75#include "nsCharsetSource.h"
76#include "mozilla/ReflowInput.h"
77#include "nsIImageLoadingContent.h"
78#include "nsCopySupport.h"
79#include "nsXULPopupManager.h"
80
81#include "nsIClipboard.h"
82#include "nsIClipboardHelper.h"
83
84#include "nsPIDOMWindow.h"
85#include "nsGlobalWindowInner.h"
86#include "nsGlobalWindowOuter.h"
87#include "nsDOMNavigationTiming.h"
88#include "nsPIWindowRoot.h"
89#include "nsJSEnvironment.h"
90#include "nsFocusManager.h"
91
92#include "nsStyleSheetService.h"
93#include "nsILoadContext.h"
94#include "mozilla/ThrottledEventQueue.h"
95#include "nsIPromptCollection.h"
96#include "nsIPromptService.h"
97#include "imgIContainer.h" // image animation mode constants
98#include "nsIXULRuntime.h"
99#include "nsSandboxFlags.h"
100
101//--------------------------
102// Printing Include
103//---------------------------
104#ifdef NS_PRINTING1
105
106# include "nsIWebBrowserPrint.h"
107
108# include "nsPrintJob.h"
109# include "nsDeviceContextSpecProxy.h"
110
111// Print Options
112# include "nsIPrintSettings.h"
113# include "nsIPrintSettingsService.h"
114# include "nsISimpleEnumerator.h"
115
116#endif // NS_PRINTING
117
118// focus
119#include "nsIDOMEventListener.h"
120#include "nsISelectionController.h"
121
122#include "mozilla/EventDispatcher.h"
123#include "nsISHEntry.h"
124#include "nsISHistory.h"
125#include "nsIWebNavigation.h"
126#include "mozilla/dom/XMLHttpRequestMainThread.h"
127
128// paint forcing
129#include <stdio.h>
130#include "mozilla/BasePrincipal.h"
131#include "mozilla/dom/Element.h"
132#include "mozilla/dom/Event.h"
133#include "mozilla/Telemetry.h"
134#include "mozilla/dom/ScriptLoader.h"
135#include "mozilla/dom/WindowGlobalChild.h"
136
137namespace mozilla {
138namespace dom {
139class PrintPreviewResultInfo;
140} // namespace dom
141} // namespace mozilla
142
143using namespace mozilla;
144using namespace mozilla::dom;
145
146using mozilla::layout::RemotePrintJobChild;
147using PrintPreviewResolver =
148 std::function<void(const mozilla::dom::PrintPreviewResultInfo&)>;
149
150//-----------------------------------------------------
151// LOGGING
152#include "LayoutLogging.h"
153#include "mozilla/Logging.h"
154
155extern mozilla::LazyLogModule gPageCacheLog;
156
157#ifdef NS_PRINTING1
158mozilla::LazyLogModule gPrintingLog("printing");
159
160# define PR_PL(_p1)do { const ::mozilla::LogModule* moz_real_module = gPrintingLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
_p1); } } while (0);
MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1)do { const ::mozilla::LogModule* moz_real_module = gPrintingLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
_p1); } } while (0)
;
161#endif // NS_PRINTING
162
163#define PRT_YESNO(_p)((_p) ? "YES" : "NO") ((_p) ? "YES" : "NO")
164//-----------------------------------------------------
165
166class nsDocumentViewer;
167
168// a small delegate class used to avoid circular references
169
170class nsDocViewerSelectionListener final : public nsISelectionListener {
171 public:
172 // nsISupports interface...
173 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
174
175 // nsISelectionListerner interface
176 NS_DECL_NSISELECTIONLISTENERvirtual nsresult NotifySelectionChanged(mozilla::dom::Document
*doc, mozilla::dom::Selection *sel, int16_t reason, int32_t amount
) override;
177
178 explicit nsDocViewerSelectionListener(nsDocumentViewer* aDocViewer)
179 : mDocViewer(aDocViewer), mSelectionWasCollapsed(true) {}
180
181 void Disconnect() { mDocViewer = nullptr; }
182
183 protected:
184 virtual ~nsDocViewerSelectionListener() = default;
185
186 nsDocumentViewer* mDocViewer;
187 bool mSelectionWasCollapsed;
188};
189
190/** editor Implementation of the FocusListener interface */
191class nsDocViewerFocusListener final : public nsIDOMEventListener {
192 public:
193 explicit nsDocViewerFocusListener(nsDocumentViewer* aDocViewer)
194 : mDocViewer(aDocViewer) {}
195
196 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
197 NS_DECL_NSIDOMEVENTLISTENERvirtual nsresult HandleEvent(mozilla::dom::Event *event) override
;
198
199 void Disconnect() { mDocViewer = nullptr; }
200
201 protected:
202 virtual ~nsDocViewerFocusListener() = default;
203
204 nsDocumentViewer* mDocViewer;
205};
206
207namespace viewer_detail {
208
209/**
210 * Mutation observer for use until we hand ourselves over to our SHEntry.
211 */
212class BFCachePreventionObserver final : public nsStubMutationObserver {
213 public:
214 explicit BFCachePreventionObserver(Document* aDocument)
215 : mDocument(aDocument) {}
216
217 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
218
219 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGEDvirtual void CharacterDataChanged( nsIContent* aContent, const
CharacterDataChangeInfo& aInfo) override;
220 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGEDvirtual void AttributeChanged(mozilla::dom::Element* aElement
, int32_t aNameSpaceID, nsAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue) override;
221 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDEDvirtual void ContentAppended(nsIContent* aFirstNewContent) override
;
222 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTEDvirtual void ContentInserted(nsIContent* aChild) override;
223 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVEDvirtual void ContentRemoved(nsIContent* aChild, nsIContent* aPreviousSibling
) override;
224 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYEDvirtual void NodeWillBeDestroyed(nsINode* aNode) override;
225
226 // Stop observing the document.
227 void Disconnect();
228
229 private:
230 ~BFCachePreventionObserver() = default;
231
232 // Helper for the work that needs to happen when mutations happen.
233 void MutationHappened();
234
235 Document* mDocument; // Weak; we get notified if it dies
236};
237
238NS_IMPL_ISUPPORTS(BFCachePreventionObserver, nsIMutationObserver)MozExternalRefCountType BFCachePreventionObserver::AddRef(void
) { static_assert(!std::is_destructible_v<BFCachePreventionObserver
>, "Reference-counted class " "BFCachePreventionObserver" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
238; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BFCachePreventionObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("BFCachePreventionObserver" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"BFCachePreventionObserver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BFCachePreventionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 238; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BFCachePreventionObserver" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"BFCachePreventionObserver"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType BFCachePreventionObserver::
Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 238
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BFCachePreventionObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("BFCachePreventionObserver" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"BFCachePreventionObserver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BFCachePreventionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 238; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BFCachePreventionObserver" " not thread-safe"
); const char* const nametmp = "BFCachePreventionObserver"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult BFCachePreventionObserver::QueryInterface(
const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 238); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BFCachePreventionObserver, nsIMutationObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIMutationObserver
*>((BFCachePreventionObserver*)0x1000)) - reinterpret_cast
<char*>((BFCachePreventionObserver*)0x1000))}, {&mozilla
::detail::kImplementedIID<BFCachePreventionObserver, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIMutationObserver*>((BFCachePreventionObserver
*)0x1000))) - reinterpret_cast<char*>((BFCachePreventionObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
239
240void BFCachePreventionObserver::CharacterDataChanged(
241 nsIContent* aContent, const CharacterDataChangeInfo&) {
242 if (aContent->IsInNativeAnonymousSubtree()) {
243 return;
244 }
245 MutationHappened();
246}
247
248void BFCachePreventionObserver::AttributeChanged(Element* aElement,
249 int32_t aNameSpaceID,
250 nsAtom* aAttribute,
251 int32_t aModType,
252 const nsAttrValue* aOldValue) {
253 if (aElement->IsInNativeAnonymousSubtree()) {
254 return;
255 }
256 MutationHappened();
257}
258
259void BFCachePreventionObserver::ContentAppended(nsIContent* aFirstNewContent) {
260 if (aFirstNewContent->IsInNativeAnonymousSubtree()) {
261 return;
262 }
263 MutationHappened();
264}
265
266void BFCachePreventionObserver::ContentInserted(nsIContent* aChild) {
267 if (aChild->IsInNativeAnonymousSubtree()) {
268 return;
269 }
270 MutationHappened();
271}
272
273void BFCachePreventionObserver::ContentRemoved(nsIContent* aChild,
274 nsIContent* aPreviousSibling) {
275 if (aChild->IsInNativeAnonymousSubtree()) {
276 return;
277 }
278 MutationHappened();
279}
280
281void BFCachePreventionObserver::NodeWillBeDestroyed(nsINode* aNode) {
282 mDocument = nullptr;
283}
284
285void BFCachePreventionObserver::Disconnect() {
286 if (mDocument) {
287 mDocument->RemoveMutationObserver(this);
288 // It will no longer tell us when it goes away, so make sure we're
289 // not holding a dangling ref.
290 mDocument = nullptr;
291 }
292}
293
294void BFCachePreventionObserver::MutationHappened() {
295 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument" " (" "How can we not have a document but be getting notified for mutations?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ") ("
"How can we not have a document but be getting notified for mutations?"
")"); do { *((volatile int*)__null) = 297; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
296 mDocument,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument" " (" "How can we not have a document but be getting notified for mutations?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ") ("
"How can we not have a document but be getting notified for mutations?"
")"); do { *((volatile int*)__null) = 297; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
297 "How can we not have a document but be getting notified for mutations?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument" " (" "How can we not have a document but be getting notified for mutations?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ") ("
"How can we not have a document but be getting notified for mutations?"
")"); do { *((volatile int*)__null) = 297; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
298 mDocument->DisallowBFCaching();
299 Disconnect();
300}
301
302} // namespace viewer_detail
303
304using viewer_detail::BFCachePreventionObserver;
305
306//-------------------------------------------------------------
307class nsDocumentViewer final : public nsIDocumentViewer,
308 public nsIDocumentViewerEdit,
309 public nsIDocumentViewerPrint
310#ifdef NS_PRINTING1
311 ,
312 public nsIWebBrowserPrint
313#endif
314
315{
316 friend class nsDocViewerSelectionListener;
317 friend class nsPagePrintTimer;
318 friend class nsPrintJob;
319
320 public:
321 nsDocumentViewer();
322
323 // nsISupports interface...
324 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
325
326 // nsIDocumentViewer interface...
327 NS_DECL_NSIDOCUMENTVIEWERvirtual nsresult Init(nsIWidget * aParentWidget, const nsIntRect
& aBounds, mozilla::dom::WindowGlobalChild * aWindowActor
) override; virtual nsresult GetContainer(nsIDocShell **aContainer
) override; virtual nsresult SetContainer(nsIDocShell *aContainer
) override; virtual void LoadStart(mozilla::dom::Document *aDoc
) override; virtual nsresult LoadComplete(nsresult aStatus) override
; virtual bool GetLoadCompleted() override; virtual bool GetIsStopped
() override; virtual nsresult PermitUnload(nsIDocumentViewer::
PermitUnloadAction aAction, bool *_retval) override; virtual nsresult
GetInPermitUnload(bool *aInPermitUnload) override; virtual nsIDocumentViewer
::PermitUnloadResult DispatchBeforeUnload(void) override; virtual
nsresult GetBeforeUnloadFiring(bool *aBeforeUnloadFiring) override
; virtual nsresult PageHide(bool isUnload) override; virtual nsresult
Close(nsISHEntry *historyEntry) override; virtual nsresult Destroy
(void) override; virtual nsresult Stop(void) override; virtual
nsresult GetDOMDocument(mozilla::dom::Document **aDOMDocument
) override; virtual mozilla::dom::Document * GetDocument(void
) override; virtual nsresult SetDocument(mozilla::dom::Document
*aDocument) override; virtual nsresult GetBounds(nsIntRect &
aBounds) override; virtual nsresult SetBounds(const nsIntRect
& aBounds) override; virtual nsresult SetBoundsWithFlags
(const nsIntRect & aBounds, uint32_t aFlags) override; virtual
nsIDocumentViewer * GetPreviousViewer() override; virtual void
SetPreviousViewer(nsIDocumentViewer *aPreviousViewer) override
; virtual nsresult Move(int32_t aX, int32_t aY) override; virtual
nsresult Show(void) override; virtual nsresult Hide(void) override
; virtual nsresult GetSticky(bool *aSticky) override; virtual
nsresult SetSticky(bool aSticky) override; virtual nsresult Open
(nsISupports *aState, nsISHEntry *aSHEntry) override; virtual
nsresult ClearHistoryEntry(void) override; virtual nsresult SetPageModeForTesting
(bool aPageMode, nsIPrintSettings *aPrintSettings) override; virtual
nsresult SetPrintSettingsForSubdocument(nsIPrintSettings *aPrintSettings
, mozilla::layout::RemotePrintJobChild * aRemotePrintJob) override
; virtual nsresult GetHistoryEntry(nsISHEntry **aHistoryEntry
) override; virtual nsresult GetIsTabModalPromptAllowed(bool *
aIsTabModalPromptAllowed) override; virtual nsresult GetIsHidden
(bool *aIsHidden) override; virtual nsresult SetIsHidden(bool
aIsHidden) override; virtual mozilla::PresShell * GetPresShell
() override; virtual nsPresContext * GetPresContext() override
; virtual nsresult SetDocumentInternal(mozilla::dom::Document
*aDocument, bool aForceReuseInnerWindow) override; virtual nsView
* FindContainerView(void) override; virtual void SetNavigationTiming
(nsDOMNavigationTiming * aTiming) override; virtual nsresult GetDeviceFullZoomForTest
(float *aDeviceFullZoomForTest) override; virtual nsresult GetAuthorStyleDisabled
(bool *aAuthorStyleDisabled) override; virtual nsresult SetAuthorStyleDisabled
(bool aAuthorStyleDisabled) override; virtual nsresult GetContentSize
(int32_t maxWidth, int32_t maxHeight, int32_t prefWidth, int32_t
*width, int32_t *height) override; virtual const mozilla::Encoding
* GetReloadEncodingAndSource(int32_t *aSource) override; virtual
void SetReloadEncodingAndSource(const mozilla::Encoding * aEncoding
, int32_t aSource) override; virtual void ForgetReloadEncoding
(void) override;
328
329 // nsIDocumentViewerEdit
330 NS_DECL_NSIDOCUMENTVIEWEREDITvirtual nsresult ClearSelection(void) override; virtual nsresult
SelectAll(void) override; virtual nsresult CopySelection(void
) override; virtual nsresult GetCopyable(bool *aCopyable) override
; virtual nsresult CopyLinkLocation(void) override; virtual nsresult
GetInLink(bool *aInLink) override; virtual nsresult CopyImage
(int32_t aCopyFlags) override; virtual nsresult GetInImage(bool
*aInImage) override; virtual nsresult GetContents(const char
* aMimeType, bool aSelectionOnly, nsAString& _retval) override
; virtual nsresult GetCanGetContents(bool *aCanGetContents) override
; virtual nsresult SetCommandNode(nsINode *aNode) override;
331
332#ifdef NS_PRINTING1
333 // nsIWebBrowserPrint
334 NS_DECL_NSIWEBBROWSERPRINTvirtual nsresult GetDoingPrint(bool *aDoingPrint) override; virtual
nsresult GetDoingPrintPreview(bool *aDoingPrintPreview) override
; virtual nsresult GetRawNumPages(int32_t *aRawNumPages) override
; virtual nsresult GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages
) override; virtual nsresult GetPrintPreviewCurrentPageNumber
(int32_t *aPrintPreviewCurrentPageNumber) override; using nsIWebBrowserPrint
::GetCloseWindowAfterPrint; virtual nsresult GetCloseWindowAfterPrint
(bool *aCloseWindowAfterPrint) override; virtual nsresult SetCloseWindowAfterPrint
(bool aCloseWindowAfterPrint) override; virtual nsresult Print
(nsIPrintSettings *aThePrintSettings, mozilla::layout::RemotePrintJobChild
* aRemotePrintJob, nsIWebProgressListener *aWPListener) override
; virtual nsresult PrintPreview(nsIPrintSettings *aThePrintSettings
, nsIWebProgressListener *aWPListener, std::function<void(
const mozilla::dom::PrintPreviewResultInfo&)>&&
aCallback) override; virtual nsresult PrintPreviewScrollToPage
(int16_t aNavType, int32_t aPageNum) override; virtual nsresult
ExitPrintPreview(void) override;
335#endif
336
337 // nsIDocumentViewerPrint Printing Methods
338 NS_DECL_NSIDOCUMENTVIEWERPRINTbool GetIsPrinting() const override; void SetIsPrintPreview(bool
aIsPrintPreview) override; bool GetIsPrintPreview() const override
; void IncrementDestroyBlockedCount() override; void DecrementDestroyBlockedCount
() override; void OnDonePrinting() override; void SetPrintPreviewPresentation
(nsViewManager* aViewManager, nsPresContext* aPresContext, mozilla
::PresShell* aPresShell) override;
339
340 protected:
341 virtual ~nsDocumentViewer();
342
343 private:
344 /**
345 * Creates a view manager, root view, and widget for the root view, setting
346 * mViewManager and mWindow.
347 * @param aSize the initial size in appunits
348 * @param aContainerView the container view to hook our root view up
349 * to as a child, or null if this will be the root view manager
350 */
351 nsresult MakeWindow(const nsSize& aSize, nsView* aContainerView);
352
353 /**
354 * Create our device context
355 */
356 nsresult CreateDeviceContext(nsView* aContainerView);
357
358 /**
359 * If aDoCreation is true, this creates the device context, creates a
360 * prescontext if necessary, and calls MakeWindow.
361 *
362 * If aForceSetNewDocument is false, then SetNewDocument won't be
363 * called if the window's current document is already mDocument.
364 */
365 nsresult InitInternal(nsIWidget* aParentWidget, nsISupports* aState,
366 mozilla::dom::WindowGlobalChild* aActor,
367 const nsIntRect& aBounds, bool aDoCreation,
368 bool aNeedMakeCX = true,
369 bool aForceSetNewDocument = true);
370 /**
371 * @param aDoInitialReflow set to true if you want to kick off the initial
372 * reflow
373 */
374 MOZ_CAN_RUN_SCRIPT_BOUNDARY
375 nsresult InitPresentationStuff(bool aDoInitialReflow);
376
377 already_AddRefed<nsINode> GetPopupNode();
378 already_AddRefed<nsINode> GetPopupLinkNode();
379 already_AddRefed<nsIImageLoadingContent> GetPopupImageNode();
380
381 void PrepareToStartLoad(void);
382
383 nsresult SyncParentSubDocMap();
384
385 void RemoveFocusListener();
386 void ReinitializeFocusListener();
387
388 mozilla::dom::Selection* GetDocumentSelection();
389
390 void DestroyPresShell();
391 void DestroyPresContext();
392
393 void InvalidatePotentialSubDocDisplayItem();
394
395 // Whether we should attach to the top level widget. This is true if we
396 // are sharing/recycling a single base widget and not creating multiple
397 // child widgets.
398 bool ShouldAttachToTopLevel();
399
400 std::tuple<const nsIFrame*, int32_t> GetCurrentSheetFrameAndNumber() const;
401
402 protected:
403 // Returns the current viewmanager. Might be null.
404 nsViewManager* GetViewManager();
405
406 void DetachFromTopLevelWidget();
407
408 // IMPORTANT: The ownership implicit in the following member
409 // variables has been explicitly checked and set using nsCOMPtr
410 // for owning pointers and raw COM interface pointers for weak
411 // (ie, non owning) references. If you add any members to this
412 // class, please make the ownership explicit (pinkerton, scc).
413
414 WeakPtr<nsDocShell> mContainer; // it owns me!
415 RefPtr<nsDeviceContext> mDeviceContext; // We create and own this baby
416
417 // the following six items are explicitly in this order
418 // so they will be destroyed in the reverse order (pinkerton, scc)
419 nsCOMPtr<Document> mDocument;
420 nsCOMPtr<nsIWidget> mWindow; // may be null
421 RefPtr<nsViewManager> mViewManager;
422 RefPtr<nsPresContext> mPresContext;
423 RefPtr<PresShell> mPresShell;
424
425 RefPtr<nsDocViewerSelectionListener> mSelectionListener;
426 RefPtr<nsDocViewerFocusListener> mFocusListener;
427
428 nsCOMPtr<nsIDocumentViewer> mPreviousViewer;
429 nsCOMPtr<nsISHEntry> mSHEntry;
430 // Observer that will prevent bfcaching if it gets notified. This
431 // is non-null precisely when mSHEntry is non-null.
432 RefPtr<BFCachePreventionObserver> mBFCachePreventionObserver;
433
434 nsIWidget* mParentWidget; // purposely won't be ref counted. May be null
435 bool mAttachedToParent; // view is attached to the parent widget
436
437 nsIntRect mBounds;
438
439 int16_t mNumURLStarts;
440 int16_t mDestroyBlockedCount;
441
442 unsigned mStopped : 1;
443 unsigned mLoaded : 1;
444 unsigned mDeferredWindowClose : 1;
445 // document management data
446 // these items are specific to markup documents (html and xml)
447 // may consider splitting these out into a subclass
448 unsigned mIsSticky : 1;
449 unsigned mInPermitUnload : 1;
450 unsigned mInPermitUnloadPrompt : 1;
451
452#ifdef NS_PRINTING1
453 unsigned mClosingWhilePrinting : 1;
454 unsigned mCloseWindowAfterPrint : 1;
455
456# if NS_PRINT_PREVIEW1
457 RefPtr<nsPrintJob> mPrintJob;
458# endif // NS_PRINT_PREVIEW
459
460#endif // NS_PRINTING
461
462 /* character set member data */
463 int32_t mReloadEncodingSource;
464 const Encoding* mReloadEncoding;
465
466 bool mIsPageMode;
467 bool mInitializedForPrintPreview;
468 bool mHidden;
469};
470
471class nsDocumentShownDispatcher : public Runnable {
472 public:
473 explicit nsDocumentShownDispatcher(nsCOMPtr<Document> aDocument)
474 : Runnable("nsDocumentShownDispatcher"), mDocument(aDocument) {}
475
476 NS_IMETHODvirtual nsresult Run() override;
477
478 private:
479 nsCOMPtr<Document> mDocument;
480};
481
482//------------------------------------------------------------------
483// nsDocumentViewer
484//------------------------------------------------------------------
485
486//------------------------------------------------------------------
487already_AddRefed<nsIDocumentViewer> NS_NewDocumentViewer() {
488 return MakeAndAddRef<nsDocumentViewer>();
489}
490
491void nsDocumentViewer::PrepareToStartLoad() {
492 MOZ_DIAGNOSTIC_ASSERT(!GetIsPrintPreview(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetIsPrintPreview())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!GetIsPrintPreview()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!GetIsPrintPreview()"
" (" "Print preview tab should never navigate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 493); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!GetIsPrintPreview()"
") (" "Print preview tab should never navigate" ")"); do { *
((volatile int*)__null) = 493; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
493 "Print preview tab should never navigate")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetIsPrintPreview())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!GetIsPrintPreview()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!GetIsPrintPreview()"
" (" "Print preview tab should never navigate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 493); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!GetIsPrintPreview()"
") (" "Print preview tab should never navigate" ")"); do { *
((volatile int*)__null) = 493; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
494
495 mStopped = false;
496 mLoaded = false;
497 mAttachedToParent = false;
498 mDeferredWindowClose = false;
499
500#ifdef NS_PRINTING1
501 mClosingWhilePrinting = false;
502
503 // Make sure we have destroyed it and cleared the data member
504 if (mPrintJob) {
505 mPrintJob->Destroy();
506 mPrintJob = nullptr;
507 }
508
509#endif // NS_PRINTING
510}
511
512nsDocumentViewer::nsDocumentViewer()
513 : mParentWidget(nullptr),
514 mAttachedToParent(false),
515 mNumURLStarts(0),
516 mDestroyBlockedCount(0),
517 mStopped(false),
518 mLoaded(false),
519 mDeferredWindowClose(false),
520 mIsSticky(true),
521 mInPermitUnload(false),
522 mInPermitUnloadPrompt(false),
523#ifdef NS_PRINTING1
524 mClosingWhilePrinting(false),
525 mCloseWindowAfterPrint(false),
526#endif // NS_PRINTING
527 mReloadEncodingSource(kCharsetUninitialized),
528 mReloadEncoding(nullptr),
529 mIsPageMode(false),
530 mInitializedForPrintPreview(false),
531 mHidden(false) {
532 PrepareToStartLoad();
533}
534
535NS_IMPL_ADDREF(nsDocumentViewer)MozExternalRefCountType nsDocumentViewer::AddRef(void) { static_assert
(!std::is_destructible_v<nsDocumentViewer>, "Reference-counted class "
"nsDocumentViewer" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
535; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocumentViewer" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsDocumentViewer" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsDocumentViewer\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocumentViewer\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 535; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocumentViewer" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsDocumentViewer"
), (uint32_t)(sizeof(*this))); return count; }
536NS_IMPL_RELEASE(nsDocumentViewer)MozExternalRefCountType nsDocumentViewer::Release(void) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 536
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocumentViewer" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsDocumentViewer" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsDocumentViewer\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocumentViewer\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 536; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocumentViewer" " not thread-safe"); const
char* const nametmp = "nsDocumentViewer"; nsrefcnt count = --
mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; }
537
538NS_INTERFACE_MAP_BEGIN(nsDocumentViewer)nsresult nsDocumentViewer::QueryInterface(const nsIID& aIID
, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 538); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
539 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewer)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocumentViewer>)) foundInterface
= static_cast<nsIDocumentViewer*>(this); else
540 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerEdit)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocumentViewerEdit>)) foundInterface
= static_cast<nsIDocumentViewerEdit*>(this); else
541 NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocumentViewerPrint>)) foundInterface
= static_cast<nsIDocumentViewerPrint*>(this); else
542 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentViewer)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIDocumentViewer*>(this
)); else
543#ifdef NS_PRINTING1
544 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebBrowserPrint>)) foundInterface
= static_cast<nsIWebBrowserPrint*>(this); else
545#endif
546NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 546; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
547
548nsDocumentViewer::~nsDocumentViewer() {
549 if (mDocument) {
550 Close(nullptr);
551 mDocument->Destroy();
552 }
553
554#ifdef NS_PRINTING1
555 if (mPrintJob) {
556 mPrintJob->Destroy();
557 mPrintJob = nullptr;
558 }
559#endif
560
561 MOZ_RELEASE_ASSERT(mDestroyBlockedCount == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDestroyBlockedCount == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDestroyBlockedCount == 0)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mDestroyBlockedCount == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 561); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mDestroyBlockedCount == 0"
")"); do { *((volatile int*)__null) = 561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
562 NS_ASSERTION(!mPresShell && !mPresContext,do { if (!(!mPresShell && !mPresContext)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "User did not call nsIDocumentViewer::Destroy"
, "!mPresShell && !mPresContext", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 563); MOZ_PretendNoReturn(); } } while (0)
563 "User did not call nsIDocumentViewer::Destroy")do { if (!(!mPresShell && !mPresContext)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "User did not call nsIDocumentViewer::Destroy"
, "!mPresShell && !mPresContext", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 563); MOZ_PretendNoReturn(); } } while (0)
;
564 if (mPresShell || mPresContext) {
565 // Make sure we don't hand out a reference to the content viewer to
566 // the SHEntry!
567 mSHEntry = nullptr;
568
569 Destroy();
570 }
571
572 if (mSelectionListener) {
573 mSelectionListener->Disconnect();
574 }
575
576 RemoveFocusListener();
577
578 // XXX(?) Revoke pending invalidate events
579}
580
581/*
582 * This method is called by the Document Loader once a document has
583 * been created for a particular data stream... The content viewer
584 * must cache this document for later use when Init(...) is called.
585 *
586 * This method is also called when an out of band document.write() happens.
587 * In that case, the document passed in is the same as the previous document.
588 */
589/* virtual */
590void nsDocumentViewer::LoadStart(Document* aDocument) {
591 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 591; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
592
593 if (!mDocument) {
594 mDocument = aDocument;
595 }
596}
597
598void nsDocumentViewer::RemoveFocusListener() {
599 if (RefPtr<nsDocViewerFocusListener> oldListener =
600 std::move(mFocusListener)) {
601 oldListener->Disconnect();
602 if (mDocument) {
603 mDocument->RemoveEventListener(u"focus"_ns, oldListener, false);
604 mDocument->RemoveEventListener(u"blur"_ns, oldListener, false);
605 }
606 }
607}
608
609void nsDocumentViewer::ReinitializeFocusListener() {
610 RemoveFocusListener();
611 mFocusListener = new nsDocViewerFocusListener(this);
612 if (mDocument) {
613 mDocument->AddEventListener(u"focus"_ns, mFocusListener, false, false);
614 mDocument->AddEventListener(u"blur"_ns, mFocusListener, false, false);
615 }
616}
617
618nsresult nsDocumentViewer::SyncParentSubDocMap() {
619 nsCOMPtr<nsIDocShell> docShell(mContainer);
620 if (!docShell) {
621 return NS_OK;
622 }
623
624 nsCOMPtr<nsPIDOMWindowOuter> pwin(docShell->GetWindow());
625 if (!mDocument || !pwin) {
626 return NS_OK;
627 }
628
629 nsCOMPtr<Element> element = pwin->GetFrameElementInternal();
630 if (!element) {
631 return NS_OK;
632 }
633
634 nsCOMPtr<nsIDocShellTreeItem> parent;
635 docShell->GetInProcessParent(getter_AddRefs(parent));
636
637 nsCOMPtr<nsPIDOMWindowOuter> parent_win =
638 parent ? parent->GetWindow() : nullptr;
639 if (!parent_win) {
640 return NS_OK;
641 }
642
643 nsCOMPtr<Document> parent_doc = parent_win->GetDoc();
644 if (!parent_doc) {
645 return NS_OK;
646 }
647
648 if (mDocument && parent_doc->GetSubDocumentFor(element) != mDocument &&
649 parent_doc->EventHandlingSuppressed()) {
650 mDocument->SuppressEventHandling(parent_doc->EventHandlingSuppressed());
651 }
652 return parent_doc->SetSubDocumentFor(element, mDocument);
653}
654
655NS_IMETHODIMPnsresult
656nsDocumentViewer::SetContainer(nsIDocShell* aContainer) {
657 mContainer = static_cast<nsDocShell*>(aContainer);
658
659 // We're loading a new document into the window where this document
660 // viewer lives, sync the parent document's frame element -> sub
661 // document map
662
663 return SyncParentSubDocMap();
664}
665
666NS_IMETHODIMPnsresult
667nsDocumentViewer::GetContainer(nsIDocShell** aResult) {
668 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 668); return NS_ERROR_INVALID_POINTER; } } while (false)
;
669
670 nsCOMPtr<nsIDocShell> container(mContainer);
671 container.swap(*aResult);
672 return NS_OK;
673}
674
675NS_IMETHODIMPnsresult
676nsDocumentViewer::Init(nsIWidget* aParentWidget, const nsIntRect& aBounds,
677 WindowGlobalChild* aActor) {
678 return InitInternal(aParentWidget, nullptr, aActor, aBounds, true);
679}
680
681nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) {
682 // We assert this because initializing the pres shell could otherwise cause
683 // re-entrancy into nsDocumentViewer methods, which might cause a different
684 // pres shell to be created. Callers of InitPresentationStuff should ensure
685 // the call is appropriately bounded by an nsAutoScriptBlocker to decide
686 // when it is safe for these re-entrant calls to be made.
687 MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsContentUtils::IsSafeToRunScript()" " (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsContentUtils::IsSafeToRunScript()"
") (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")"); do { *((volatile int*)__null) = 689; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
688 "InitPresentationStuff must only be called when scripts are "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsContentUtils::IsSafeToRunScript()" " (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsContentUtils::IsSafeToRunScript()"
") (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")"); do { *((volatile int*)__null) = 689; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
689 "blocked")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsContentUtils::IsSafeToRunScript()" " (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsContentUtils::IsSafeToRunScript()"
") (" "InitPresentationStuff must only be called when scripts are "
"blocked" ")"); do { *((volatile int*)__null) = 689; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
690
691#ifdef NS_PRINTING1
692 // When getting printed, either for print or print preview, the print job
693 // takes care of setting up the presentation of the document.
694 if (mPrintJob) {
695 return NS_OK;
696 }
697#endif
698
699 NS_ASSERTION(!mPresShell, "Someone should have destroyed the presshell!")do { if (!(!mPresShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone should have destroyed the presshell!"
, "!mPresShell", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 699); MOZ_PretendNoReturn(); } } while (0)
;
700
701 // Now make the shell for the document
702 nsCOMPtr<Document> doc = mDocument;
703 RefPtr<nsPresContext> presContext = mPresContext;
704 RefPtr<nsViewManager> viewManager = mViewManager;
705 mPresShell = doc->CreatePresShell(presContext, viewManager);
706 if (!mPresShell) {
707 return NS_ERROR_FAILURE;
708 }
709
710 if (aDoInitialReflow) {
711 // Since Initialize() will create frames for *all* items
712 // that are currently in the document tree, we need to flush
713 // any pending notifications to prevent the content sink from
714 // duplicating layout frames for content it has added to the tree
715 // but hasn't notified the document about. (Bug 154018)
716 //
717 // Note that we are flushing before we add mPresShell as an observer
718 // to avoid bogus notifications.
719 mDocument->FlushPendingNotifications(FlushType::ContentAndNotify);
720 }
721
722 mPresShell->BeginObservingDocument();
723
724 // Initialize our view manager
725
726 {
727 int32_t p2a = mPresContext->AppUnitsPerDevPixel();
728 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
")"); do { *((volatile int*)__null) = 730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
729 p2a ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
")"); do { *((volatile int*)__null) = 730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
730 mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p2a == mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()"
")"); do { *((volatile int*)__null) = 730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
731
732 nscoord width = p2a * mBounds.width;
733 nscoord height = p2a * mBounds.height;
734
735 mViewManager->SetWindowDimensions(width, height);
736 mPresContext->SetInitialVisibleArea(nsRect(0, 0, width, height));
737 // We rely on the default zoom not being initialized until here.
738 mPresContext->RecomputeBrowsingContextDependentData();
739 }
740
741 if (mWindow && mDocument->IsTopLevelContentDocument()) {
742 // Set initial safe area insets
743 ScreenIntMargin windowSafeAreaInsets;
744 LayoutDeviceIntRect windowRect = mWindow->GetScreenBounds();
745 nsCOMPtr<nsIScreen> screen = mWindow->GetWidgetScreen();
746 if (screen) {
747 windowSafeAreaInsets = nsContentUtils::GetWindowSafeAreaInsets(
748 screen, mWindow->GetSafeAreaInsets(), windowRect);
749 }
750
751 mPresContext->SetSafeAreaInsets(windowSafeAreaInsets);
752 }
753
754 if (aDoInitialReflow) {
755 RefPtr<PresShell> presShell = mPresShell;
756 // Initial reflow
757 presShell->Initialize();
758 }
759
760 // now register ourselves as a selection listener, so that we get
761 // called when the selection changes in the window
762 if (!mSelectionListener) {
763 mSelectionListener = new nsDocViewerSelectionListener(this);
764 }
765
766 RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
767 if (!selection) {
768 return NS_ERROR_FAILURE;
769 }
770
771 selection->AddSelectionListener(mSelectionListener);
772
773 ReinitializeFocusListener();
774
775 if (aDoInitialReflow && mDocument) {
776 nsCOMPtr<Document> document = mDocument;
777 document->ScrollToRef();
778 }
779
780 return NS_OK;
781}
782
783static already_AddRefed<nsPresContext> CreatePresContext(
784 Document* aDocument, nsPresContext::nsPresContextType aType,
785 nsView* aContainerView) {
786 RefPtr<nsPresContext> result = aContainerView
787 ? new nsPresContext(aDocument, aType)
788 : new nsRootPresContext(aDocument, aType);
789
790 return result.forget();
791}
792
793//-----------------------------------------------
794// This method can be used to initial the "presentation"
795// The aDoCreation indicates whether it should create
796// all the new objects or just initialize the existing ones
797nsresult nsDocumentViewer::InitInternal(
798 nsIWidget* aParentWidget, nsISupports* aState, WindowGlobalChild* aActor,
799 const nsIntRect& aBounds, bool aDoCreation, bool aNeedMakeCX /*= true*/,
800 bool aForceSetNewDocument /* = true*/) {
801 // We don't want any scripts to run here. That can cause flushing,
802 // which can cause reentry into initialization of this document viewer,
803 // which would be disastrous.
804 nsAutoScriptBlocker blockScripts;
805
806 mParentWidget = aParentWidget; // not ref counted
807 mBounds = aBounds;
808
809 nsresult rv = NS_OK;
810 NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 810); return NS_ERROR_NULL_POINTER; } } while (false)
;
811
812 nsView* containerView = FindContainerView();
813
814 bool makeCX = false;
815 if (aDoCreation) {
816 nsresult rv = CreateDeviceContext(containerView);
817 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 817); return rv; } } while (false)
;
818
819 // XXXbz this is a nasty hack to do with the fact that we create
820 // presentations both in Init() and in Show()... Ideally we would only do
821 // it in one place (Show()) and require that callers call init(), open(),
822 // show() in that order or something.
823 if (!mPresContext &&
824 (aParentWidget || containerView || mDocument->IsBeingUsedAsImage() ||
825 (mDocument->GetDisplayDocument() &&
826 mDocument->GetDisplayDocument()->GetPresShell()))) {
827 // Create presentation context
828 if (mIsPageMode) {
829 // Presentation context already created in SetPageModeForTesting which
830 // is calling this method
831 } else {
832 mPresContext = CreatePresContext(
833 mDocument, nsPresContext::eContext_Galley, containerView);
834 }
835 NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 835); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
836
837 nsresult rv = mPresContext->Init(mDeviceContext);
838 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
839 mPresContext = nullptr;
840 return rv;
841 }
842
843#if defined(NS_PRINTING1) && defined(NS_PRINT_PREVIEW1)
844 makeCX = !GetIsPrintPreview() &&
845 aNeedMakeCX; // needs to be true except when we are already in
846 // PP or we are enabling/disabling paginated mode.
847#else
848 makeCX = true;
849#endif
850 }
851
852 if (mPresContext) {
853 // Create the ViewManager and Root View...
854
855 // We must do this before we tell the script global object about
856 // this new document since doing that will cause us to re-enter
857 // into nsSubDocumentFrame code through reflows caused by
858 // FlushPendingNotifications() calls down the road...
859
860 rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(aBounds.width),
861 mPresContext->DevPixelsToAppUnits(aBounds.height)),
862 containerView);
863 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 863); return rv; } } while (false)
;
864 Hide();
865
866#ifdef NS_PRINT_PREVIEW1
867 if (mIsPageMode) {
868 // I'm leaving this in a broken state for the moment; we should
869 // be measuring/scaling with the print device context, not the
870 // screen device context, but this is good enough to allow
871 // printing reftests to work.
872 double pageWidth = 0, pageHeight = 0;
873 mPresContext->GetPrintSettings()->GetEffectivePageSize(&pageWidth,
874 &pageHeight);
875 mPresContext->SetPageSize(
876 nsSize(mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageWidth)),
877 mPresContext->CSSTwipsToAppUnits(NSToIntFloor(pageHeight))));
878 mPresContext->SetIsRootPaginatedDocument(true);
879 mPresContext->SetPageScale(1.0f);
880 }
881#endif
882 } else {
883 // Avoid leaking the old viewer.
884 if (mPreviousViewer) {
885 mPreviousViewer->Destroy();
886 mPreviousViewer = nullptr;
887 }
888 }
889 }
890
891 nsCOMPtr<nsIInterfaceRequestor> requestor(mContainer);
892 if (requestor) {
893 // Set script-context-owner in the document
894
895 nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(requestor);
896
897 if (window) {
898 nsCOMPtr<Document> curDoc = window->GetExtantDoc();
899 if (aForceSetNewDocument || curDoc != mDocument) {
900 rv = window->SetNewDocument(mDocument, aState, false, aActor);
901 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
902 Destroy();
903 return rv;
904 }
905 }
906 }
907 }
908
909 if (aDoCreation && mPresContext) {
910 // The ViewManager and Root View was created above (in
911 // MakeWindow())...
912
913 rv = InitPresentationStuff(!makeCX);
914 }
915
916 return rv;
917}
918
919void nsDocumentViewer::SetNavigationTiming(nsDOMNavigationTiming* timing) {
920 NS_ASSERTION(mDocument, "Must have a document to set navigation timing.")do { if (!(mDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Must have a document to set navigation timing."
, "mDocument", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 920); MOZ_PretendNoReturn(); } } while (0)
;
921 if (mDocument) {
922 mDocument->SetNavigationTiming(timing);
923 }
924}
925
926//
927// LoadComplete(aStatus)
928//
929// aStatus - The status returned from loading the document.
930//
931// This method is called by the container when the document has been
932// completely loaded.
933//
934NS_IMETHODIMPnsresult
935nsDocumentViewer::LoadComplete(nsresult aStatus) {
936 /* We need to protect ourself against auto-destruction in case the
937 window is closed while processing the OnLoad event. See bug
938 http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
939 explanation.
940 */
941 RefPtr<nsDocumentViewer> kungFuDeathGrip(this);
942
943 // Flush out layout so it's up-to-date by the time onload is called.
944 // Note that this could destroy the window, so do this before
945 // checking for our mDocument and its window.
946 if (mPresShell && !mStopped) {
947 // Hold strong ref because this could conceivably run script
948 RefPtr<PresShell> presShell = mPresShell;
949 presShell->FlushPendingNotifications(FlushType::Layout);
950 }
951
952 nsresult rv = NS_OK;
953 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 953); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
954
955 // First, get the window from the document...
956 nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
957
958 mLoaded = true;
959
960 // Now, fire either an OnLoad or OnError event to the document...
961 bool restoring = false;
962 // XXXbz imagelib kills off the document load for a full-page image with
963 // NS_ERROR_PARSED_DATA_CACHED if it's in the cache. So we want to treat
964 // that one as a success code; otherwise whether we fire onload for the image
965 // will depend on whether it's cached!
966 if (window &&
967 (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) || aStatus == NS_ERROR_PARSED_DATA_CACHED)) {
968 // If this code changes, the code in nsDocLoader::DocLoaderIsEmpty
969 // that fires load events for document.open() cases might need to
970 // be updated too.
971 nsEventStatus status = nsEventStatus_eIgnore;
972 WidgetEvent event(true, eLoad);
973 event.mFlags.mBubbles = false;
974 event.mFlags.mCancelable = false;
975 // XXX Dispatching to |window|, but using |document| as the target.
976 event.mTarget = mDocument;
977
978 // If the document presentation is being restored, we don't want to fire
979 // onload to the document content since that would likely confuse scripts
980 // on the page.
981
982 RefPtr<nsDocShell> docShell = nsDocShell::Cast(window->GetDocShell());
983 NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(docShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "docShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 983); return NS_ERROR_UNEXPECTED; } } while (false)
;
984
985 // Unfortunately, docShell->GetRestoringDocument() might no longer be set
986 // correctly. In particular, it can be false by now if someone took it upon
987 // themselves to block onload from inside restoration and unblock it later.
988 // But we can detect the restoring case very simply: by whether our
989 // document's readyState is COMPLETE.
990 restoring =
991 (mDocument->GetReadyStateEnum() == Document::READYSTATE_COMPLETE);
992 if (!restoring) {
993 NS_ASSERTION(do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
994 mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE ||do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
995 // test_stricttransportsecurity.html has old-styledo { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
996 // docshell-generated about:blank docs reach this code!do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
997 (mDocument->GetReadyStateEnum() ==do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
998 Document::READYSTATE_UNINITIALIZED &&do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
999 NS_IsAboutBlank(mDocument->GetDocumentURI())),do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
1000 "Bad readystate")do { if (!(mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE
|| (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED
&& NS_IsAboutBlank(mDocument->GetDocumentURI())))
) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Bad readystate", "mDocument->GetReadyStateEnum() == Document::READYSTATE_INTERACTIVE || (mDocument->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED && NS_IsAboutBlank(mDocument->GetDocumentURI()))"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1000); MOZ_PretendNoReturn(); } } while (0)
;
1001#ifdef DEBUG1
1002 bool docShellThinksWeAreRestoring;
1003 docShell->GetRestoringDocument(&docShellThinksWeAreRestoring);
1004 MOZ_ASSERT(!docShellThinksWeAreRestoring,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!docShellThinksWeAreRestoring)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!docShellThinksWeAreRestoring
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!docShellThinksWeAreRestoring" " (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!docShellThinksWeAreRestoring"
") (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")"); do { *((volatile int*)
__null) = 1006; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1005 "How can docshell think we are restoring if we don't have a "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!docShellThinksWeAreRestoring)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!docShellThinksWeAreRestoring
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!docShellThinksWeAreRestoring" " (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!docShellThinksWeAreRestoring"
") (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")"); do { *((volatile int*)
__null) = 1006; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1006 "READYSTATE_COMPLETE document?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!docShellThinksWeAreRestoring)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!docShellThinksWeAreRestoring
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!docShellThinksWeAreRestoring" " (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!docShellThinksWeAreRestoring"
") (" "How can docshell think we are restoring if we don't have a "
"READYSTATE_COMPLETE document?" ")"); do { *((volatile int*)
__null) = 1006; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1007#endif // DEBUG
1008 nsCOMPtr<Document> d = mDocument;
1009 mDocument->SetReadyStateInternal(Document::READYSTATE_COMPLETE);
1010
1011 RefPtr<nsDOMNavigationTiming> timing(d->GetNavigationTiming());
1012 if (timing) {
1013 timing->NotifyLoadEventStart();
1014 }
1015
1016 // Dispatch observer notification to notify observers document load is
1017 // complete.
1018 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
1019 if (os) {
1020 nsIPrincipal* principal = d->NodePrincipal();
1021 os->NotifyObservers(ToSupports(d),
1022 principal->IsSystemPrincipal()
1023 ? "chrome-document-loaded"
1024 : "content-document-loaded",
1025 nullptr);
1026 }
1027
1028 nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
1029 d->SetLoadEventFiring(true);
1030 RefPtr<nsPresContext> presContext = mPresContext;
1031 // MOZ_KnownLive due to bug 1506441
1032 EventDispatcher::Dispatch(
1033 MOZ_KnownLive(nsGlobalWindowOuter::Cast(window))(nsGlobalWindowOuter::Cast(window)), presContext, &event,
1034 nullptr, &status);
1035 d->SetLoadEventFiring(false);
1036
1037 if (timing) {
1038 timing->NotifyLoadEventEnd();
1039 }
1040
1041 if (innerWindow) {
1042 innerWindow->QueuePerformanceNavigationTiming();
1043 }
1044 }
1045 } else {
1046 // XXX: Should fire error event to the document...
1047
1048 // If our load was explicitly aborted, then we want to set our
1049 // readyState to COMPLETE, and fire a readystatechange event.
1050 if (aStatus == NS_BINDING_ABORTED && mDocument) {
1051 mDocument->NotifyAbortedLoad();
1052 }
1053 }
1054
1055 // Notify the document that it has been shown (regardless of whether
1056 // it was just loaded). Note: mDocument may be null now if the above
1057 // firing of onload caused the document to unload. Or, mDocument may not be
1058 // the "current active" document, if the above firing of onload caused our
1059 // docshell to navigate away. NOTE: In this latter scenario, it's likely that
1060 // we fired pagehide (when navigating away) without ever having fired
1061 // pageshow, and that's pretty broken... Fortunately, this should be rare.
1062 // (It requires us to spin the event loop in onload handler, e.g. via sync
1063 // XHR, in order for the navigation-away to happen before onload completes.)
1064 // We skip firing pageshow if we're currently handling unload, or if loading
1065 // was explicitly aborted.
1066 if (mDocument && mDocument->IsCurrentActiveDocument() &&
1067 aStatus != NS_BINDING_ABORTED) {
1068 // Re-get window, since it might have changed during above firing of onload
1069 window = mDocument->GetWindow();
1070 if (window) {
1071 nsIDocShell* docShell = window->GetDocShell();
1072 bool isInUnload;
1073 if (docShell && NS_SUCCEEDED(docShell->GetIsInUnload(&isInUnload))((bool)(__builtin_expect(!!(!NS_FAILED_impl(docShell->GetIsInUnload
(&isInUnload))), 1)))
&&
1074 !isInUnload) {
1075 mDocument->OnPageShow(restoring, nullptr);
1076 }
1077 }
1078 }
1079
1080 if (!mStopped) {
1081 if (mDocument) {
1082 // This is the final attempt to scroll to an anchor / text directive.
1083 // This is the last iteration of the algorithm described in the spec for
1084 // trying to scroll to a fragment.
1085 // https://html.spec.whatwg.org/#try-to-scroll-to-the-fragment
1086 nsCOMPtr<Document> document = mDocument;
1087 document->ScrollToRef();
1088 }
1089
1090 // Now that the document has loaded, we can tell the presshell
1091 // to unsuppress painting.
1092 if (mPresShell) {
1093 RefPtr<PresShell> presShell = mPresShell;
1094 presShell->UnsuppressPainting();
1095 // mPresShell could have been removed now, see bug 378682/421432
1096 if (mPresShell) {
1097 mPresShell->LoadComplete();
1098 }
1099 }
1100 }
1101
1102 // https://wicg.github.io/scroll-to-text-fragment/#invoking-text-directives
1103 // Monkeypatching HTML § 7.4.6.3 Scrolling to a fragment:
1104 // 2.1 If the user agent has reason to believe the user is no longer
1105 // interested in scrolling to the fragment, then:
1106 // 2.1.1 Set pending text directives to null.
1107 //
1108 // Gecko's implementation differs from the spec (ie., it implements its
1109 // intention but doesn't follow step by step), therefore the mentioned steps
1110 // are not applied in the same manner.
1111 // However, this should be the right place to do this.
1112 if (mDocument) {
1113 mDocument->FragmentDirective()->ClearUninvokedDirectives();
1114 }
1115 if (mDocument && !restoring) {
1116 mDocument->LoadEventFired();
1117 }
1118
1119 // It's probably a good idea to GC soon since we have finished loading.
1120 nsJSContext::PokeGC(
1121 JS::GCReason::LOAD_END,
1122 mDocument ? mDocument->GetWrapperPreserveColor() : nullptr);
1123
1124#ifdef NS_PRINTING1
1125 // Check to see if someone tried to print during the load
1126 if (window) {
1127 auto* outerWin = nsGlobalWindowOuter::Cast(window);
1128 outerWin->StopDelayingPrintingUntilAfterLoad();
1129 if (outerWin->DelayedPrintUntilAfterLoad()) {
1130 // We call into the inner because it ensures there's an active document
1131 // and such, and it also waits until the whole thing completes, which is
1132 // nice because it allows us to close if needed right here.
1133 if (RefPtr inner =
1134 nsGlobalWindowInner::Cast(window->GetCurrentInnerWindow())) {
1135 inner->Print(IgnoreErrors());
1136 }
1137 if (outerWin->DelayedCloseForPrinting()) {
1138 outerWin->Close();
1139 }
1140 } else {
1141 MOZ_ASSERT(!outerWin->DelayedCloseForPrinting())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!outerWin->DelayedCloseForPrinting())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!outerWin->DelayedCloseForPrinting()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!outerWin->DelayedCloseForPrinting()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!outerWin->DelayedCloseForPrinting()"
")"); do { *((volatile int*)__null) = 1141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1142 }
1143 }
1144#endif
1145
1146 return rv;
1147}
1148
1149bool nsDocumentViewer::GetLoadCompleted() { return mLoaded; }
1150
1151bool nsDocumentViewer::GetIsStopped() { return mStopped; }
1152
1153NS_IMETHODIMPnsresult
1154nsDocumentViewer::PermitUnload(PermitUnloadAction aAction,
1155 bool* aPermitUnload) {
1156 // We're going to be running JS and nested event loops, which could cause our
1157 // DocShell to be destroyed. Make sure we stay alive until the end of the
1158 // function.
1159 RefPtr<nsDocumentViewer> kungFuDeathGrip(this);
1160
1161 if (StaticPrefs::dom_disable_beforeunload()) {
1162 aAction = eDontPromptAndUnload;
1163 }
1164
1165 *aPermitUnload = true;
1166
1167 NS_ENSURE_STATE(mContainer)do { if ((__builtin_expect(!!(!(mContainer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mContainer" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1167); return NS_ERROR_UNEXPECTED; } } while (false)
;
1168
1169 RefPtr<BrowsingContext> bc = mContainer->GetBrowsingContext();
1170 if (!bc) {
1171 return NS_OK;
1172 }
1173
1174 // Per spec, we need to increase the ignore-opens-during-unload counter while
1175 // dispatching the "beforeunload" event on both the document we're currently
1176 // dispatching the event to and the document that we explicitly asked to
1177 // unload.
1178 IgnoreOpensDuringUnload ignoreOpens(mDocument);
1179
1180 bool foundBlocker = false;
1181 bool foundOOPListener = false;
1182 bc->PreOrderWalk([&](BrowsingContext* aBC) {
1183 if (!aBC->IsInProcess()) {
1184 WindowContext* wc = aBC->GetCurrentWindowContext();
1185 if (wc && wc->HasBeforeUnload()) {
1186 foundOOPListener = true;
1187 }
1188 } else if (aBC->GetDocShell()) {
1189 nsCOMPtr<nsIDocumentViewer> viewer(aBC->GetDocShell()->GetDocViewer());
1190 if (viewer && viewer->DispatchBeforeUnload() == eRequestBlockNavigation) {
1191 foundBlocker = true;
1192 }
1193 }
1194 });
1195
1196 if (!foundOOPListener) {
1197 if (!foundBlocker) {
1198 return NS_OK;
1199 }
1200 if (aAction != ePrompt) {
1201 *aPermitUnload = aAction == eDontPromptAndUnload;
1202 return NS_OK;
1203 }
1204 }
1205
1206 // NB: we nullcheck mDocument because it might now be dead as a result of
1207 // the event being dispatched.
1208 RefPtr<WindowGlobalChild> wgc(mDocument ? mDocument->GetWindowGlobalChild()
1209 : nullptr);
1210 if (!wgc) {
1211 return NS_OK;
1212 }
1213
1214 nsAutoSyncOperation sync(mDocument, SyncOperationBehavior::eSuspendInput);
1215 AutoSuppressEventHandlingAndSuspend seh(bc->Group());
1216
1217 mInPermitUnloadPrompt = true;
1218
1219 bool done = false;
1220 wgc->SendCheckPermitUnload(
1221 foundBlocker, aAction,
1222 [&](bool aPermit) {
1223 done = true;
1224 *aPermitUnload = aPermit;
1225 },
1226 [&](auto) {
1227 // If the prompt aborted, we tell our consumer that it is not allowed
1228 // to unload the page. One reason that prompts abort is that the user
1229 // performed some action that caused the page to unload while our prompt
1230 // was active. In those cases we don't want our consumer to also unload
1231 // the page.
1232 //
1233 // XXX: Are there other cases where prompts can abort? Is it ok to
1234 // prevent unloading the page in those cases?
1235 done = true;
1236 *aPermitUnload = false;
1237 });
1238
1239 SpinEventLoopUntil("nsDocumentViewer::PermitUnload"_ns,
1240 [&]() { return done; });
1241
1242 mInPermitUnloadPrompt = false;
1243 return NS_OK;
1244}
1245
1246MOZ_CAN_RUN_SCRIPT_BOUNDARY PermitUnloadResult
1247nsDocumentViewer::DispatchBeforeUnload() {
1248 AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
1249
1250 if (!mDocument || mInPermitUnload || mInPermitUnloadPrompt || !mContainer) {
1251 return eAllowNavigation;
1252 }
1253
1254 // First, get the script global object from the document...
1255 RefPtr<nsGlobalWindowOuter> window =
1256 nsGlobalWindowOuter::Cast(mDocument->GetWindow());
1257 if (!window) {
1258 // This is odd, but not fatal
1259 NS_WARNING("window not set for document!")NS_DebugBreak(NS_DEBUG_WARNING, "window not set for document!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1259)
;
1260 return eAllowNavigation;
1261 }
1262
1263 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "This is unsafe")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "This is unsafe", "nsContentUtils::IsSafeToRunScript()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1263); MOZ_PretendNoReturn(); } } while (0)
;
1264
1265 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#prompt-to-unload-a-document
1266 // Create an RAII object on mDocument that will increment the
1267 // should-ignore-opens-during-unload counter on initialization
1268 // and decrement it again when it goes out of score (regardless
1269 // of how we exit this function).
1270 IgnoreOpensDuringUnload ignoreOpens(mDocument);
1271
1272 // Now, fire an BeforeUnload event to the document and see if it's ok
1273 // to unload...
1274 nsPresContext* presContext = mDocument->GetPresContext();
1275 auto event = MakeRefPtr<BeforeUnloadEvent>(mDocument, presContext, nullptr);
1276 event->InitEvent(u"beforeunload"_ns, false, true);
1277
1278 // Dispatching to |window|, but using |document| as the target.
1279 event->SetTarget(mDocument);
1280 event->SetTrusted(true);
1281
1282 // In evil cases we might be destroyed while handling the
1283 // onbeforeunload event, don't let that happen. (see also bug#331040)
1284 RefPtr<nsDocumentViewer> kungFuDeathGrip(this);
1285
1286 {
1287 // Never permit popups from the beforeunload handler, no matter
1288 // how we get here.
1289 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(PopupBlocker::openAbused, true);
1290
1291 RefPtr<BrowsingContext> bc = mContainer->GetBrowsingContext();
1292 NS_ASSERTION(bc, "should have a browsing context in document viewer")do { if (!(bc)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "should have a browsing context in document viewer"
, "bc", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1292); MOZ_PretendNoReturn(); } } while (0)
;
1293
1294 // Never permit dialogs from the beforeunload handler
1295 nsGlobalWindowOuter::TemporarilyDisableDialogs disableDialogs(bc);
1296
1297 Document::PageUnloadingEventTimeStamp timestamp(mDocument);
1298
1299 mInPermitUnload = true;
1300 RefPtr<nsPresContext> presContext = mPresContext;
1301 EventDispatcher::DispatchDOMEvent(window, nullptr, event, presContext,
1302 nullptr);
1303 mInPermitUnload = false;
1304 }
1305
1306 nsAutoString text;
1307 event->GetReturnValue(text);
1308
1309 // NB: we nullcheck mDocument because it might now be dead as a result of
1310 // the event being dispatched.
1311 if (window->AreDialogsEnabled() && mDocument &&
1312 !(mDocument->GetSandboxFlags() & SANDBOXED_MODALS) &&
1313 (!StaticPrefs::dom_require_user_interaction_for_beforeunload() ||
1314 mDocument->UserHasInteracted()) &&
1315 (event->WidgetEventPtr()->DefaultPrevented() || !text.IsEmpty())) {
1316 return eRequestBlockNavigation;
1317 }
1318 return eAllowNavigation;
1319}
1320
1321NS_IMETHODIMPnsresult
1322nsDocumentViewer::GetBeforeUnloadFiring(bool* aInEvent) {
1323 *aInEvent = mInPermitUnload;
1324 return NS_OK;
1325}
1326
1327NS_IMETHODIMPnsresult
1328nsDocumentViewer::GetInPermitUnload(bool* aInEvent) {
1329 *aInEvent = mInPermitUnloadPrompt;
1330 return NS_OK;
1331}
1332
1333NS_IMETHODIMPnsresult
1334nsDocumentViewer::PageHide(bool aIsUnload) {
1335 AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
1336
1337 mHidden = true;
1338
1339 if (!mDocument) {
1340 return NS_ERROR_NULL_POINTER;
1341 }
1342
1343 if (aIsUnload) {
1344 // Poke the GC. The window might be collectable garbage now.
1345 nsJSContext::PokeGC(JS::GCReason::PAGE_HIDE,
1346 mDocument->GetWrapperPreserveColor(),
1347 TimeDuration::FromMilliseconds(
1348 StaticPrefs::javascript_options_gc_delay() * 2));
1349 }
1350
1351 mDocument->OnPageHide(!aIsUnload, nullptr);
1352
1353 // inform the window so that the focus state is reset.
1354 NS_ENSURE_STATE(mDocument)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1354); return NS_ERROR_UNEXPECTED; } } while (false)
;
1355 nsPIDOMWindowOuter* window = mDocument->GetWindow();
1356 if (window) window->PageHidden(!aIsUnload);
1357
1358 if (aIsUnload) {
1359 // if Destroy() was called during OnPageHide(), mDocument is nullptr.
1360 NS_ENSURE_STATE(mDocument)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1360); return NS_ERROR_UNEXPECTED; } } while (false)
;
1361
1362 // First, get the window from the document...
1363 RefPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
1364
1365 if (!window) {
1366 // Fail if no window is available...
1367 NS_WARNING("window not set for document!")NS_DebugBreak(NS_DEBUG_WARNING, "window not set for document!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1367)
;
1368 return NS_ERROR_NULL_POINTER;
1369 }
1370
1371 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#unload-a-document
1372 // Create an RAII object on mDocument that will increment the
1373 // should-ignore-opens-during-unload counter on initialization
1374 // and decrement it again when it goes out of scope.
1375 IgnoreOpensDuringUnload ignoreOpens(mDocument);
1376
1377 // Now, fire an Unload event to the document...
1378 nsEventStatus status = nsEventStatus_eIgnore;
1379 WidgetEvent event(true, eUnload);
1380 event.mFlags.mBubbles = false;
1381 // XXX Dispatching to |window|, but using |document| as the target.
1382 event.mTarget = mDocument;
1383
1384 // Never permit popups from the unload handler, no matter how we get
1385 // here.
1386 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(PopupBlocker::openAbused, true);
1387
1388 Document::PageUnloadingEventTimeStamp timestamp(mDocument);
1389
1390 RefPtr<nsPresContext> presContext = mPresContext;
1391 // MOZ_KnownLive due to bug 1506441
1392 EventDispatcher::Dispatch(MOZ_KnownLive(nsGlobalWindowOuter::Cast(window))(nsGlobalWindowOuter::Cast(window)),
1393 presContext, &event, nullptr, &status);
1394 }
1395
1396 // look for open menupopups and close them after the unload event, in case
1397 // the unload event listeners open any new popups
1398 nsContentUtils::HidePopupsInDocument(mDocument);
1399
1400 return NS_OK;
1401}
1402
1403static void AttachContainerRecurse(nsIDocShell* aShell) {
1404 nsCOMPtr<nsIDocumentViewer> viewer;
1405 aShell->GetDocViewer(getter_AddRefs(viewer));
1406 if (viewer) {
1407 viewer->SetIsHidden(false);
1408 Document* doc = viewer->GetDocument();
1409 if (doc) {
1410 doc->SetContainer(static_cast<nsDocShell*>(aShell));
1411 }
1412 if (PresShell* presShell = viewer->GetPresShell()) {
1413 presShell->SetForwardingContainer(WeakPtr<nsDocShell>());
1414 }
1415 }
1416
1417 // Now recurse through the children
1418 int32_t childCount;
1419 aShell->GetInProcessChildCount(&childCount);
1420 for (int32_t i = 0; i < childCount; ++i) {
1421 nsCOMPtr<nsIDocShellTreeItem> childItem;
1422 aShell->GetInProcessChildAt(i, getter_AddRefs(childItem));
1423 nsCOMPtr<nsIDocShell> shell = do_QueryInterface(childItem);
1424 AttachContainerRecurse(shell);
1425 }
1426}
1427
1428NS_IMETHODIMPnsresult
1429nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) {
1430 NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mPresShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresShell" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1430); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
1431
1432 if (mDocument) {
1433 mDocument->SetContainer(mContainer);
1434 }
1435
1436 nsresult rv = InitInternal(mParentWidget, aState, nullptr, mBounds, false);
1437 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1437); return rv; } } while (false)
;
1438
1439 mHidden = false;
1440
1441 if (mPresShell) mPresShell->SetForwardingContainer(WeakPtr<nsDocShell>());
1442
1443 // Rehook the child presentations. The child shells are still in
1444 // session history, so get them from there.
1445
1446 if (aSHEntry) {
1447 nsCOMPtr<nsIDocShellTreeItem> item;
1448 int32_t itemIndex = 0;
1449 while (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aSHEntry->ChildShellAt
(itemIndex++, getter_AddRefs(item)))), 1)))
1450 aSHEntry->ChildShellAt(itemIndex++, getter_AddRefs(item)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aSHEntry->ChildShellAt
(itemIndex++, getter_AddRefs(item)))), 1)))
&&
1451 item) {
1452 nsCOMPtr<nsIDocShell> shell = do_QueryInterface(item);
1453 AttachContainerRecurse(shell);
1454 }
1455 }
1456
1457 SyncParentSubDocMap();
1458
1459 ReinitializeFocusListener();
1460
1461 // XXX re-enable image animations once that works correctly
1462
1463 PrepareToStartLoad();
1464
1465 // When loading a page from the bfcache with puppet widgets, we do the
1466 // widget attachment here (it is otherwise done in MakeWindow, which is
1467 // called for non-bfcache pages in the history, but not bfcache pages).
1468 // Attachment is necessary, since we get detached when another page
1469 // is browsed to. That is, if we are one page A, then when we go to
1470 // page B, we detach. So page A's view has no widget. If we then go
1471 // back to it, and it is in the bfcache, we will use that view, which
1472 // doesn't have a widget. The attach call here will properly attach us.
1473 if (nsIWidget::UsePuppetWidgets() && mPresContext &&
1474 ShouldAttachToTopLevel()) {
1475 // If the old view is already attached to our parent, detach
1476 DetachFromTopLevelWidget();
1477
1478 nsViewManager* vm = GetViewManager();
1479 MOZ_ASSERT(vm, "no view manager")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(vm)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(vm))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("vm" " (" "no view manager" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "vm" ") (" "no view manager"
")"); do { *((volatile int*)__null) = 1479; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1480 nsView* v = vm->GetRootView();
1481 MOZ_ASSERT(v, "no root view")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(v)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(v))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("v" " (" "no root view" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1481); AnnotateMozCrashReason("MOZ_ASSERT" "(" "v" ") (" "no root view"
")"); do { *((volatile int*)__null) = 1481; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1482 MOZ_ASSERT(mParentWidget, "no mParentWidget to set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mParentWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mParentWidget))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mParentWidget" " ("
"no mParentWidget to set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mParentWidget"
") (" "no mParentWidget to set" ")"); do { *((volatile int*)
__null) = 1482; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1483 v->AttachToTopLevelWidget(mParentWidget);
1484
1485 mAttachedToParent = true;
1486 }
1487
1488 return NS_OK;
1489}
1490
1491NS_IMETHODIMPnsresult
1492nsDocumentViewer::Close(nsISHEntry* aSHEntry) {
1493 // All callers are supposed to call close to break circular
1494 // references. If we do this stuff in the destructor, the
1495 // destructor might never be called (especially if we're being
1496 // used from JS.
1497
1498 mSHEntry = aSHEntry;
1499
1500 // Close is also needed to disable scripts during paint suppression,
1501 // since we transfer the existing global object to the new document
1502 // that is loaded. In the future, the global object may become a proxy
1503 // for an object that can be switched in and out so that we don't need
1504 // to disable scripts during paint suppression.
1505
1506 if (!mDocument) return NS_OK;
1507
1508 if (mSHEntry) {
1509 if (mBFCachePreventionObserver) {
1510 mBFCachePreventionObserver->Disconnect();
1511 }
1512 mBFCachePreventionObserver = new BFCachePreventionObserver(mDocument);
1513 mDocument->AddMutationObserver(mBFCachePreventionObserver);
1514 }
1515
1516#ifdef NS_PRINTING1
1517 // A Close was called while we were printing
1518 // so don't clear the ScriptGlobalObject
1519 // or clear the mDocument below
1520 if (mPrintJob && !mClosingWhilePrinting) {
1521 mClosingWhilePrinting = true;
1522 } else
1523#endif
1524 {
1525 // out of band cleanup of docshell
1526 mDocument->SetScriptGlobalObject(nullptr);
1527
1528 if (!mSHEntry && mDocument) mDocument->RemovedFromDocShell();
1529 }
1530
1531 RemoveFocusListener();
1532 return NS_OK;
1533}
1534
1535static void DetachContainerRecurse(nsIDocShell* aShell) {
1536 // Unhook this docshell's presentation
1537 aShell->SynchronizeLayoutHistoryState();
1538 nsCOMPtr<nsIDocumentViewer> viewer;
1539 aShell->GetDocViewer(getter_AddRefs(viewer));
1540 if (viewer) {
1541 if (Document* doc = viewer->GetDocument()) {
1542 doc->SetContainer(nullptr);
1543 }
1544 if (PresShell* presShell = viewer->GetPresShell()) {
1545 auto weakShell = static_cast<nsDocShell*>(aShell);
1546 presShell->SetForwardingContainer(weakShell);
1547 }
1548 }
1549
1550 // Now recurse through the children
1551 int32_t childCount;
1552 aShell->GetInProcessChildCount(&childCount);
1553 for (int32_t i = 0; i < childCount; ++i) {
1554 nsCOMPtr<nsIDocShellTreeItem> childItem;
1555 aShell->GetInProcessChildAt(i, getter_AddRefs(childItem));
1556 nsCOMPtr<nsIDocShell> shell = do_QueryInterface(childItem);
1557 DetachContainerRecurse(shell);
1558 }
1559}
1560
1561NS_IMETHODIMPnsresult
1562nsDocumentViewer::Destroy() {
1563 // Don't let the document get unloaded while we are printing.
1564 // this could happen if we hit the back button during printing.
1565 // We also keep the viewer from being cached in session history, since
1566 // we require all documents there to be sanitized.
1567 if (mDestroyBlockedCount != 0) {
1568 return NS_OK;
1569 }
1570
1571#ifdef NS_PRINTING1
1572 // Here is where we check to see if the document was still being prepared
1573 // for printing when it was asked to be destroy from someone externally
1574 // This usually happens if the document is unloaded while the user is in the
1575 // Print Dialog
1576 //
1577 // So we flip the bool to remember that the document is going away
1578 // and we can clean up and abort later after returning from the Print Dialog
1579 if (mPrintJob && mPrintJob->CheckBeforeDestroy()) {
1580 return NS_OK;
1581 }
1582#endif
1583
1584 // We want to make sure to disconnect mBFCachePreventionObserver before we
1585 // Sanitize() below.
1586 if (mBFCachePreventionObserver) {
1587 mBFCachePreventionObserver->Disconnect();
1588 mBFCachePreventionObserver = nullptr;
1589 }
1590
1591 if (mSHEntry && mDocument && !mDocument->IsBFCachingAllowed()) {
1592 // Just drop the SHEntry now and pretend like we never even tried to bfcache
1593 // this viewer. This should only happen when someone calls
1594 // DisallowBFCaching() after CanSavePresentation() already ran. Ensure that
1595 // the SHEntry has no viewer and its state is synced up. We want to do this
1596 // via a stack reference, in case those calls mess with our members.
1597 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "BFCache not allowed, dropping SHEntry"); }
} while (0)
1598 ("BFCache not allowed, dropping SHEntry"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "BFCache not allowed, dropping SHEntry"); }
} while (0)
;
1599 nsCOMPtr<nsISHEntry> shEntry = std::move(mSHEntry);
1600 shEntry->SetDocumentViewer(nullptr);
1601 shEntry->SyncPresentationState();
1602 }
1603
1604 // If we were told to put ourselves into session history instead of destroy
1605 // the presentation, do that now.
1606 if (mSHEntry) {
1607 if (mPresShell) mPresShell->Freeze();
1608
1609 // Make sure the presentation isn't torn down by Hide().
1610 mSHEntry->SetSticky(mIsSticky);
1611 mIsSticky = true;
1612
1613 // Remove our root view from the view hierarchy.
1614 if (mPresShell) {
1615 nsViewManager* vm = mPresShell->GetViewManager();
1616 if (vm) {
1617 nsView* rootView = vm->GetRootView();
1618
1619 if (rootView) {
1620 nsView* rootViewParent = rootView->GetParent();
1621 if (rootViewParent) {
1622 nsView* subdocview = rootViewParent->GetParent();
1623 if (subdocview) {
1624 nsIFrame* f = subdocview->GetFrame();
1625 if (f) {
1626 nsSubDocumentFrame* s = do_QueryFrame(f);
1627 if (s) {
1628 s->ClearDisplayItems();
1629 }
1630 }
1631 }
1632 nsViewManager* parentVM = rootViewParent->GetViewManager();
1633 if (parentVM) {
1634 parentVM->RemoveChild(rootView);
1635 }
1636 }
1637 }
1638 }
1639 }
1640
1641 Hide();
1642
1643 // This is after Hide() so that the user doesn't see the inputs clear.
1644 if (mDocument) {
1645 mDocument->Sanitize();
1646 }
1647
1648 // Reverse ownership. Do this *after* calling sanitize so that sanitize
1649 // doesn't cause mutations that make the SHEntry drop the presentation
1650
1651 // Grab a reference to mSHEntry before calling into things like
1652 // SyncPresentationState that might mess with our members.
1653 nsCOMPtr<nsISHEntry> shEntry =
1654 std::move(mSHEntry); // we'll need this below
1655
1656 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Storing content viewer into cache entry")
; } } while (0)
1657 ("Storing content viewer into cache entry"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Storing content viewer into cache entry")
; } } while (0)
;
1658 shEntry->SetDocumentViewer(this);
1659
1660 // Always sync the presentation state. That way even if someone screws up
1661 // and shEntry has no window state at this point we'll be ok; we just won't
1662 // cache ourselves.
1663 shEntry->SyncPresentationState();
1664 // XXX Synchronize layout history state to parent once bfcache is supported
1665 // in session-history-in-parent.
1666
1667 // Shut down accessibility for the document before we start to tear it down.
1668#ifdef ACCESSIBILITY1
1669 if (mPresShell) {
1670 a11y::DocAccessible* docAcc = mPresShell->GetDocAccessible();
1671 if (docAcc) {
1672 docAcc->Shutdown();
1673 }
1674 }
1675#endif
1676
1677 // Break the link from the document/presentation to the docshell, so that
1678 // link traversals cannot affect the currently-loaded document.
1679 // When the presentation is restored, Open() and InitInternal() will reset
1680 // these pointers to their original values.
1681
1682 if (mDocument) {
1683 mDocument->SetContainer(nullptr);
1684 }
1685 if (mPresShell) {
1686 mPresShell->SetForwardingContainer(mContainer);
1687 }
1688
1689 // Do the same for our children. Note that we need to get the child
1690 // docshells from the SHEntry now; the docshell will have cleared them.
1691 nsCOMPtr<nsIDocShellTreeItem> item;
1692 int32_t itemIndex = 0;
1693 while (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(shEntry->ChildShellAt
(itemIndex++, getter_AddRefs(item)))), 1)))
1694 shEntry->ChildShellAt(itemIndex++, getter_AddRefs(item)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(shEntry->ChildShellAt
(itemIndex++, getter_AddRefs(item)))), 1)))
&&
1695 item) {
1696 nsCOMPtr<nsIDocShell> shell = do_QueryInterface(item);
1697 DetachContainerRecurse(shell);
1698 }
1699
1700 return NS_OK;
1701 }
1702
1703 // The document was not put in the bfcache
1704
1705 // Protect against pres shell destruction running scripts and re-entrantly
1706 // creating a new presentation.
1707 nsAutoScriptBlocker scriptBlocker;
1708
1709 if (mPresShell) {
1710 DestroyPresShell();
1711 }
1712 if (mDocument) {
1713 mDocument->Destroy();
1714 mDocument = nullptr;
1715 }
1716
1717 // All callers are supposed to call destroy to break circular
1718 // references. If we do this stuff in the destructor, the
1719 // destructor might never be called (especially if we're being
1720 // used from JS.
1721
1722#ifdef NS_PRINTING1
1723 if (mPrintJob) {
1724 RefPtr<nsPrintJob> printJob = std::move(mPrintJob);
1725# ifdef NS_PRINT_PREVIEW1
1726 if (printJob->CreatedForPrintPreview()) {
1727 printJob->FinishPrintPreview();
1728 }
1729# endif
1730 printJob->Destroy();
1731 MOZ_ASSERT(!mPrintJob,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPrintJob)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPrintJob))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mPrintJob" " (" "mPrintJob shouldn't be recreated while destroying it"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPrintJob"
") (" "mPrintJob shouldn't be recreated while destroying it"
")"); do { *((volatile int*)__null) = 1732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1732 "mPrintJob shouldn't be recreated while destroying it")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPrintJob)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPrintJob))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mPrintJob" " (" "mPrintJob shouldn't be recreated while destroying it"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPrintJob"
") (" "mPrintJob shouldn't be recreated while destroying it"
")"); do { *((volatile int*)__null) = 1732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1733 }
1734#endif
1735
1736 // Avoid leaking the old viewer.
1737 if (mPreviousViewer) {
1738 mPreviousViewer->Destroy();
1739 mPreviousViewer = nullptr;
1740 }
1741
1742 mDeviceContext = nullptr;
1743
1744 if (mPresContext) {
1745 DestroyPresContext();
1746 }
1747
1748 mWindow = nullptr;
1749 mViewManager = nullptr;
1750 mContainer = WeakPtr<nsDocShell>();
1751
1752 return NS_OK;
1753}
1754
1755NS_IMETHODIMPnsresult
1756nsDocumentViewer::Stop(void) {
1757 NS_ASSERTION(mDocument, "Stop called too early or too late")do { if (!(mDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Stop called too early or too late"
, "mDocument", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1757); MOZ_PretendNoReturn(); } } while (0)
;
1758 if (mDocument) {
1759 mDocument->StopDocumentLoad();
1760 }
1761
1762 mStopped = true;
1763
1764 if (!mLoaded && mPresShell) {
1765 // Well, we might as well paint what we have so far.
1766 RefPtr<PresShell> presShell = mPresShell; // bug 378682
1767 presShell->UnsuppressPainting();
1768 }
1769
1770 return NS_OK;
1771}
1772
1773NS_IMETHODIMPnsresult
1774nsDocumentViewer::GetDOMDocument(Document** aResult) {
1775 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1775); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
1776 nsCOMPtr<Document> document = mDocument;
1777 document.forget(aResult);
1778 return NS_OK;
1779}
1780
1781Document* nsDocumentViewer::GetDocument() { return mDocument; }
1782
1783nsresult nsDocumentViewer::SetDocument(Document* aDocument) {
1784 // Assumptions:
1785 //
1786 // 1) this document viewer has been initialized with a call to Init().
1787 // 2) the stylesheets associated with the document have been added
1788 // to the document.
1789
1790 // XXX Right now, this method assumes that the layout of the current
1791 // document hasn't started yet. More cleanup will probably be
1792 // necessary to make this method work for the case when layout *has*
1793 // occurred for the current document.
1794 // That work can happen when and if it is needed.
1795
1796 if (!aDocument) return NS_ERROR_NULL_POINTER;
1797
1798 return SetDocumentInternal(aDocument, false);
1799}
1800
1801NS_IMETHODIMPnsresult
1802nsDocumentViewer::SetDocumentInternal(Document* aDocument,
1803 bool aForceReuseInnerWindow) {
1804 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 1804; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1805
1806 // Set new container
1807 aDocument->SetContainer(mContainer);
1808
1809 if (mDocument != aDocument) {
1810 if (aForceReuseInnerWindow) {
1811 // Transfer the navigation timing information to the new document, since
1812 // we're keeping the same inner and hence should really have the same
1813 // timing information.
1814 aDocument->SetNavigationTiming(mDocument->GetNavigationTiming());
1815 }
1816
1817 if (mDocument &&
1818 (mDocument->IsStaticDocument() || aDocument->IsStaticDocument())) {
1819 nsContentUtils::AddScriptRunner(NewRunnableMethod(
1820 "Document::Destroy", mDocument, &Document::Destroy));
1821 }
1822
1823 // Clear the list of old child docshells. Child docshells for the new
1824 // document will be constructed as frames are created.
1825 if (!aDocument->IsStaticDocument()) {
1826 nsCOMPtr<nsIDocShell> node(mContainer);
1827 if (node) {
1828 int32_t count;
1829 node->GetInProcessChildCount(&count);
1830 for (int32_t i = 0; i < count; ++i) {
1831 nsCOMPtr<nsIDocShellTreeItem> child;
1832 node->GetInProcessChildAt(0, getter_AddRefs(child));
1833 node->RemoveChild(child);
1834 }
1835 }
1836 }
1837
1838 // Replace the old document with the new one. Do this only when
1839 // the new document really is a new document.
1840 mDocument = aDocument;
1841
1842 // Set the script global object on the new document
1843 nsCOMPtr<nsPIDOMWindowOuter> window =
1844 mContainer ? mContainer->GetWindow() : nullptr;
1845 if (window) {
1846 nsresult rv =
1847 window->SetNewDocument(aDocument, nullptr, aForceReuseInnerWindow);
1848 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1849 Destroy();
1850 return rv;
1851 }
1852 }
1853 }
1854
1855 nsresult rv = SyncParentSubDocMap();
1856 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1856); return rv; } } while (false)
;
1857
1858 // Replace the current pres shell with a new shell for the new document
1859
1860 // Protect against pres shell destruction running scripts and re-entrantly
1861 // creating a new presentation.
1862 nsAutoScriptBlocker scriptBlocker;
1863
1864 if (mPresShell) {
1865 DestroyPresShell();
1866 }
1867
1868 if (mPresContext) {
1869 DestroyPresContext();
1870
1871 mWindow = nullptr;
1872 rv = InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, true,
1873 false);
1874 }
1875
1876 return rv;
1877}
1878
1879PresShell* nsDocumentViewer::GetPresShell() { return mPresShell; }
1880
1881nsPresContext* nsDocumentViewer::GetPresContext() { return mPresContext; }
1882
1883nsViewManager* nsDocumentViewer::GetViewManager() { return mViewManager; }
1884
1885NS_IMETHODIMPnsresult
1886nsDocumentViewer::GetBounds(nsIntRect& aResult) {
1887 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1887); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
1888 aResult = mBounds;
1889 return NS_OK;
1890}
1891
1892nsIDocumentViewer* nsDocumentViewer::GetPreviousViewer() {
1893 return mPreviousViewer;
1894}
1895
1896void nsDocumentViewer::SetPreviousViewer(nsIDocumentViewer* aViewer) {
1897 // NOTE: |Show| sets |mPreviousViewer| to null without calling this
1898 // function.
1899
1900 if (aViewer) {
1901 NS_ASSERTION(!mPreviousViewer,do { if (!(!mPreviousViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "can't set previous viewer when there already is one", "!mPreviousViewer"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1902); MOZ_PretendNoReturn(); } } while (0)
1902 "can't set previous viewer when there already is one")do { if (!(!mPreviousViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "can't set previous viewer when there already is one", "!mPreviousViewer"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1902); MOZ_PretendNoReturn(); } } while (0)
;
1903
1904 // In a multiple chaining situation (which occurs when running a thrashing
1905 // test like i-bench or jrgm's tests with no delay), we can build up a
1906 // whole chain of viewers. In order to avoid this, we always set our
1907 // previous viewer to the MOST previous viewer in the chain, and then dump
1908 // the intermediate link from the chain. This ensures that at most only 2
1909 // documents are alive and undestroyed at any given time (the one that is
1910 // showing and the one that is loading with painting suppressed). It's very
1911 // important that if this ever gets changed the code before the
1912 // RestorePresentation call in nsDocShell::InternalLoad be changed
1913 // accordingly.
1914 //
1915 // Make sure we hold a strong ref to prevViewer here, since we'll
1916 // tell aViewer to drop it.
1917 nsCOMPtr<nsIDocumentViewer> prevViewer = aViewer->GetPreviousViewer();
1918 if (prevViewer) {
1919 aViewer->SetPreviousViewer(nullptr);
1920 aViewer->Destroy();
1921 return SetPreviousViewer(prevViewer);
1922 }
1923 }
1924
1925 mPreviousViewer = aViewer;
1926}
1927
1928NS_IMETHODIMPnsresult
1929nsDocumentViewer::SetBoundsWithFlags(const nsIntRect& aBounds,
1930 uint32_t aFlags) {
1931 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 1931); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
1932
1933 bool boundsChanged = !mBounds.IsEqualEdges(aBounds);
1934 mBounds = aBounds;
1935
1936 if (mWindow && !mAttachedToParent) {
1937 // Resize the widget, but don't trigger repaint. Layout will generate
1938 // repaint requests during reflow.
1939 mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height, false);
1940 } else if (mPresContext && mViewManager) {
1941 // Ensure presContext's deviceContext is up to date, as we sometimes get
1942 // here before a resolution-change notification has been fully handled
1943 // during display configuration changes, especially when there are lots
1944 // of windows/widgets competing to handle the notifications.
1945 // (See bug 1154125.)
1946 if (mPresContext->DeviceContext()->CheckDPIChange()) {
1947 mPresContext->UIResolutionChangedSync();
1948 }
1949
1950 int32_t p2a = mPresContext->AppUnitsPerDevPixel();
1951 nscoord width = NSIntPixelsToAppUnits(mBounds.width, p2a);
1952 nscoord height = NSIntPixelsToAppUnits(mBounds.height, p2a);
1953 nsView* rootView = mViewManager->GetRootView();
1954 if (boundsChanged && rootView) {
1955 nsRect viewDims = rootView->GetDimensions();
1956 // If the view/frame tree and prescontext visible area already has the new
1957 // size but we did not, then it's likely that we got reflowed in response
1958 // to a call to GetContentSize. Thus there is a disconnect between the
1959 // size on the document viewer/docshell/containing widget and view
1960 // tree/frame tree/prescontext visible area). SetWindowDimensions compares
1961 // to the root view dimenstions to determine if it needs to do anything;
1962 // if they are the same as the new size it won't do anything, but we still
1963 // need to invalidate because what we want to draw to the screen has
1964 // changed.
1965 if (viewDims.width == width && viewDims.height == height) {
1966 nsIFrame* f = rootView->GetFrame();
1967 if (f) {
1968 f->InvalidateFrame();
1969
1970 // Forcibly refresh the viewport sizes even if the view size is not
1971 // changed since it is possible that the |mBounds| change means that
1972 // the software keyboard appeared/disappered, in such cases we might
1973 // need to fire visual viewport events.
1974 mPresShell->RefreshViewportSize();
1975 }
1976 }
1977 }
1978
1979 mViewManager->SetWindowDimensions(
1980 width, height, !!(aFlags & nsIDocumentViewer::eDelayResize));
1981 }
1982
1983 // If there's a previous viewer, it's the one that's actually showing,
1984 // so be sure to resize it as well so it paints over the right area.
1985 // This may slow down the performance of the new page load, but resize
1986 // during load is also probably a relatively unusual condition
1987 // relating to things being hidden while something is loaded. It so
1988 // happens that Firefox does this a good bit with its infobar, and it
1989 // looks ugly if we don't do this.
1990 if (mPreviousViewer) {
1991 nsCOMPtr<nsIDocumentViewer> previousViewer = mPreviousViewer;
1992 previousViewer->SetBounds(aBounds);
1993 }
1994
1995 return NS_OK;
1996}
1997
1998NS_IMETHODIMPnsresult
1999nsDocumentViewer::SetBounds(const nsIntRect& aBounds) {
2000 return SetBoundsWithFlags(aBounds, 0);
2001}
2002
2003NS_IMETHODIMPnsresult
2004nsDocumentViewer::Move(int32_t aX, int32_t aY) {
2005 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2005); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2006 mBounds.MoveTo(aX, aY);
2007 if (mWindow) {
2008 mWindow->Move(aX, aY);
2009 }
2010 return NS_OK;
2011}
2012
2013NS_IMETHODIMPnsresult
2014nsDocumentViewer::Show() {
2015 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2015); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2016
2017 // We don't need the previous viewer anymore since we're not
2018 // displaying it.
2019 if (mPreviousViewer) {
2020 // This little dance *may* only be to keep
2021 // PresShell::EndObservingDocument happy, but I'm not sure.
2022 nsCOMPtr<nsIDocumentViewer> prevViewer(mPreviousViewer);
2023 mPreviousViewer = nullptr;
2024 prevViewer->Destroy();
2025
2026 // Make sure we don't have too many cached ContentViewers
2027 nsCOMPtr<nsIDocShellTreeItem> treeItem(mContainer);
2028 if (treeItem) {
2029 // We need to find the root DocShell since only that object has an
2030 // SHistory and we need the SHistory to evict content viewers
2031 nsCOMPtr<nsIDocShellTreeItem> root;
2032 treeItem->GetInProcessSameTypeRootTreeItem(getter_AddRefs(root));
2033 nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
2034 RefPtr<ChildSHistory> history = webNav->GetSessionHistory();
2035 if (!mozilla::SessionHistoryInParent() && history) {
2036 int32_t prevIndex, loadedIndex;
2037 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
2038 docShell->GetPreviousEntryIndex(&prevIndex);
2039 docShell->GetLoadedEntryIndex(&loadedIndex);
2040 MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "About to evict content viewers: prev=%d, loaded=%d"
, prevIndex, loadedIndex); } } while (0)
2041 ("About to evict content viewers: prev=%d, loaded=%d",do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "About to evict content viewers: prev=%d, loaded=%d"
, prevIndex, loadedIndex); } } while (0)
2042 prevIndex, loadedIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "About to evict content viewers: prev=%d, loaded=%d"
, prevIndex, loadedIndex); } } while (0)
;
2043 history->LegacySHistory()->EvictOutOfRangeDocumentViewers(loadedIndex);
2044 }
2045 }
2046 }
2047
2048 if (mWindow) {
2049 // When attached to a top level xul window, we do not need to call
2050 // Show on the widget. Underlying window management code handles
2051 // this when the window is initialized.
2052 if (!mAttachedToParent) {
2053 mWindow->Show(true);
2054 }
2055 }
2056
2057 // Hold on to the document so we can use it after the script blocker below
2058 // has been released (which might re-entrantly call into other
2059 // nsDocumentViewer methods).
2060 nsCOMPtr<Document> document = mDocument;
2061
2062 if (mDocument && !mPresShell) {
2063 // The InitPresentationStuff call below requires a script blocker, because
2064 // its PresShell::Initialize call can cause scripts to run and therefore
2065 // re-entrant calls to nsDocumentViewer methods to be made.
2066 nsAutoScriptBlocker scriptBlocker;
2067
2068 NS_ASSERTION(!mWindow, "Window already created but no presshell?")do { if (!(!mWindow)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window already created but no presshell?"
, "!mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2068); MOZ_PretendNoReturn(); } } while (0)
;
2069
2070 nsCOMPtr<nsIBaseWindow> base_win(mContainer);
2071 if (base_win) {
2072 base_win->GetParentWidget(&mParentWidget);
2073 if (mParentWidget) {
2074 // GetParentWidget AddRefs, but mParentWidget is weak
2075 mParentWidget->Release();
2076 }
2077 }
2078
2079 nsView* containerView = FindContainerView();
2080
2081 nsresult rv = CreateDeviceContext(containerView);
2082 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2082); return rv; } } while (false)
;
2083
2084 // Create presentation context
2085 NS_ASSERTION(!mPresContext,do { if (!(!mPresContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Shouldn't have a prescontext if we have no shell!", "!mPresContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2086); MOZ_PretendNoReturn(); } } while (0)
2086 "Shouldn't have a prescontext if we have no shell!")do { if (!(!mPresContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Shouldn't have a prescontext if we have no shell!", "!mPresContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2086); MOZ_PretendNoReturn(); } } while (0)
;
2087 mPresContext = CreatePresContext(mDocument, nsPresContext::eContext_Galley,
2088 containerView);
2089 NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2089); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2090
2091 rv = mPresContext->Init(mDeviceContext);
2092 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2093 mPresContext = nullptr;
2094 return rv;
2095 }
2096
2097 rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width),
2098 mPresContext->DevPixelsToAppUnits(mBounds.height)),
2099 containerView);
2100 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2101
2102 if (mPresContext) {
2103 Hide();
2104
2105 rv = InitPresentationStuff(mDocument->MayStartLayout());
Value stored to 'rv' is never read
2106 }
2107
2108 // If we get here the document load has already started and the
2109 // window is shown because some JS on the page caused it to be
2110 // shown...
2111
2112 if (mPresShell) {
2113 RefPtr<PresShell> presShell = mPresShell; // bug 378682
2114 presShell->UnsuppressPainting();
2115 }
2116 }
2117
2118 // Notify observers that a new page has been shown. This will get run
2119 // from the event loop after we actually draw the page.
2120 auto event = MakeRefPtr<nsDocumentShownDispatcher>(document);
2121 document->Dispatch(event.forget());
2122
2123 return NS_OK;
2124}
2125
2126NS_IMETHODIMPnsresult
2127nsDocumentViewer::Hide() {
2128 if (!mAttachedToParent && mWindow) {
2129 mWindow->Show(false);
2130 }
2131
2132 if (!mPresShell) return NS_OK;
2133
2134 NS_ASSERTION(mPresContext, "Can't have a presshell and no prescontext!")do { if (!(mPresContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Can't have a presshell and no prescontext!", "mPresContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2134); MOZ_PretendNoReturn(); } } while (0)
;
2135
2136 // Avoid leaking the old viewer.
2137 if (mPreviousViewer) {
2138 mPreviousViewer->Destroy();
2139 mPreviousViewer = nullptr;
2140 }
2141
2142 if (mIsSticky) {
2143 // This window is sticky, that means that it might be shown again
2144 // and we don't want the presshell n' all that to be thrown away
2145 // just because the window is hidden.
2146
2147 return NS_OK;
2148 }
2149
2150 nsCOMPtr<nsIDocShell> docShell(mContainer);
2151 if (docShell) {
2152#ifdef DEBUG1
2153 nsCOMPtr<nsIDocumentViewer> currentViewer;
2154 docShell->GetDocViewer(getter_AddRefs(currentViewer));
2155 MOZ_ASSERT(currentViewer == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(currentViewer == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(currentViewer == this))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("currentViewer == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "currentViewer == this"
")"); do { *((volatile int*)__null) = 2155; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2156#endif
2157 nsCOMPtr<nsILayoutHistoryState> layoutState;
2158 mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
2159 }
2160
2161 // Do not run ScriptRunners queued by DestroyPresShell() in the intermediate
2162 // state before we're done destroying PresShell, PresContext, ViewManager,
2163 // etc.
2164 nsAutoScriptBlocker scriptBlocker;
2165
2166 DestroyPresShell();
2167
2168 DestroyPresContext();
2169
2170 mViewManager = nullptr;
2171 mWindow = nullptr;
2172 mDeviceContext = nullptr;
2173 mParentWidget = nullptr;
2174
2175 nsCOMPtr<nsIBaseWindow> base_win(mContainer);
2176
2177 if (base_win && !mAttachedToParent) {
2178 base_win->SetParentWidget(nullptr);
2179 }
2180
2181 return NS_OK;
2182}
2183
2184NS_IMETHODIMPnsresult
2185nsDocumentViewer::GetSticky(bool* aSticky) {
2186 *aSticky = mIsSticky;
2187
2188 return NS_OK;
2189}
2190
2191NS_IMETHODIMPnsresult
2192nsDocumentViewer::SetSticky(bool aSticky) {
2193 mIsSticky = aSticky;
2194
2195 return NS_OK;
2196}
2197
2198NS_IMETHODIMPnsresult
2199nsDocumentViewer::ClearHistoryEntry() {
2200 if (mDocument) {
2201 nsJSContext::PokeGC(JS::GCReason::PAGE_HIDE,
2202 mDocument->GetWrapperPreserveColor(),
2203 TimeDuration::FromMilliseconds(
2204 StaticPrefs::javascript_options_gc_delay() * 2));
2205 }
2206
2207 mSHEntry = nullptr;
2208 return NS_OK;
2209}
2210
2211//-------------------------------------------------------
2212
2213nsresult nsDocumentViewer::MakeWindow(const nsSize& aSize,
2214 nsView* aContainerView) {
2215 if (GetIsPrintPreview()) {
2216 return NS_OK;
2217 }
2218
2219 bool shouldAttach = ShouldAttachToTopLevel();
2220
2221 if (shouldAttach) {
2222 // If the old view is already attached to our parent, detach
2223 DetachFromTopLevelWidget();
2224 }
2225
2226 mViewManager = new nsViewManager();
2227
2228 nsDeviceContext* dx = mPresContext->DeviceContext();
2229
2230 nsresult rv = mViewManager->Init(dx);
2231 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2232
2233 // The root view is always at 0,0.
2234 nsRect tbounds(nsPoint(0, 0), aSize);
2235 // Create a view
2236 nsView* view = mViewManager->CreateView(tbounds, aContainerView);
2237 if (!view) return NS_ERROR_OUT_OF_MEMORY;
2238
2239 // Create a widget if we were given a parent widget or don't have a
2240 // container view that we can hook up to without a widget.
2241 // Don't create widgets for ResourceDocs (external resources & svg images),
2242 // because when they're displayed, they're painted into *another* document's
2243 // widget.
2244 if (!mDocument->IsResourceDoc() && (mParentWidget || !aContainerView)) {
2245 // pass in a native widget to be the parent widget ONLY if the view
2246 // hierarchy will stand alone. otherwise the view will find its own parent
2247 // widget and "do the right thing" to establish a parent/child widget
2248 // relationship
2249 widget::InitData initData;
2250 widget::InitData* initDataPtr;
2251 if (!mParentWidget) {
2252 initDataPtr = &initData;
2253 initData.mWindowType = widget::WindowType::Invisible;
2254 } else {
2255 initDataPtr = nullptr;
2256 }
2257
2258 if (shouldAttach) {
2259 // Reuse the top level parent widget.
2260 rv = view->AttachToTopLevelWidget(mParentWidget);
2261 mAttachedToParent = true;
2262 } else if (!aContainerView && mParentWidget) {
2263 rv = view->CreateWidgetForParent(mParentWidget, initDataPtr, true, false);
2264 } else {
2265 rv = view->CreateWidget(initDataPtr, true, false);
2266 }
2267 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2268 }
2269
2270 // Setup hierarchical relationship in view manager
2271 mViewManager->SetRootView(view);
2272
2273 mWindow = view->GetWidget();
2274
2275 // This SetFocus is necessary so the Arrow Key and Page Key events
2276 // go to the scrolled view as soon as the Window is created instead of going
2277 // to the browser window (this enables keyboard scrolling of the document)
2278 // mWindow->SetFocus();
2279
2280 return rv;
2281}
2282
2283void nsDocumentViewer::DetachFromTopLevelWidget() {
2284 if (mViewManager) {
2285 nsView* oldView = mViewManager->GetRootView();
2286 if (oldView && oldView->IsAttachedToTopLevel()) {
2287 oldView->DetachFromTopLevelWidget();
2288 }
2289 }
2290 mAttachedToParent = false;
2291}
2292
2293nsView* nsDocumentViewer::FindContainerView() {
2294 if (!mContainer) {
2295 return nullptr;
2296 }
2297
2298 nsCOMPtr<nsIDocShell> docShell(mContainer);
2299 nsCOMPtr<nsPIDOMWindowOuter> pwin(docShell->GetWindow());
2300 if (!pwin) {
2301 return nullptr;
2302 }
2303
2304 nsCOMPtr<Element> containerElement = pwin->GetFrameElementInternal();
2305 if (!containerElement) {
2306 return nullptr;
2307 }
2308
2309 nsIFrame* subdocFrame = containerElement->GetPrimaryFrame();
2310 if (!subdocFrame) {
2311 // XXX Silenced by default in bug 1175289
2312 LAYOUT_WARNING("Subdocument container has no frame")do { if ((__builtin_expect(!!(mozilla::detail::log_test(sLayoutLog
, mozilla::LogLevel::Warning)), 0))) { mozilla::detail::LayoutLogWarning
("Subdocument container has no frame", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2312); } } while (0)
;
2313 return nullptr;
2314 }
2315
2316 // Check subdocFrame just to be safe. If this somehow fails we treat that as
2317 // display:none, the document is not displayed.
2318 if (!subdocFrame->IsSubDocumentFrame()) {
2319 NS_WARNING_ASSERTION(subdocFrame->Type() == LayoutFrameType::None,do { if (!(subdocFrame->Type() == LayoutFrameType::None)) {
NS_DebugBreak(NS_DEBUG_WARNING, "Subdocument container has non-subdocument frame"
, "subdocFrame->Type() == LayoutFrameType::None", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2320); } } while (false)
2320 "Subdocument container has non-subdocument frame")do { if (!(subdocFrame->Type() == LayoutFrameType::None)) {
NS_DebugBreak(NS_DEBUG_WARNING, "Subdocument container has non-subdocument frame"
, "subdocFrame->Type() == LayoutFrameType::None", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2320); } } while (false)
;
2321 return nullptr;
2322 }
2323
2324 NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views")do { if (!(subdocFrame->GetView())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Subdoc frames must have views", "subdocFrame->GetView()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2324); MOZ_PretendNoReturn(); } } while (0)
;
2325 return static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView();
2326}
2327
2328nsresult nsDocumentViewer::CreateDeviceContext(nsView* aContainerView) {
2329 MOZ_ASSERT(!mPresShell && !mWindow,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell && !mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPresShell && !mWindow
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mPresShell && !mWindow" " (" "This will screw up our existing presentation"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell && !mWindow"
") (" "This will screw up our existing presentation" ")"); do
{ *((volatile int*)__null) = 2330; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2330 "This will screw up our existing presentation")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell && !mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPresShell && !mWindow
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mPresShell && !mWindow" " (" "This will screw up our existing presentation"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell && !mWindow"
") (" "This will screw up our existing presentation" ")"); do
{ *((volatile int*)__null) = 2330; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2331 MOZ_ASSERT(mDocument, "Gotta have a document here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument" " (" "Gotta have a document here"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ") ("
"Gotta have a document here" ")"); do { *((volatile int*)__null
) = 2331; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2332
2333 Document* doc = mDocument->GetDisplayDocument();
2334 if (doc) {
2335 NS_ASSERTION(!aContainerView,do { if (!(!aContainerView)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "External resource document embedded somewhere?", "!aContainerView"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2336); MOZ_PretendNoReturn(); } } while (0)
2336 "External resource document embedded somewhere?")do { if (!(!aContainerView)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "External resource document embedded somewhere?", "!aContainerView"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2336); MOZ_PretendNoReturn(); } } while (0)
;
2337 // We want to use our display document's device context if possible
2338 nsPresContext* ctx = doc->GetPresContext();
2339 if (ctx) {
2340 mDeviceContext = ctx->DeviceContext();
2341 return NS_OK;
2342 }
2343 }
2344
2345 // Create a device context even if we already have one, since our widget
2346 // might have changed.
2347 nsIWidget* widget = nullptr;
2348 if (aContainerView) {
2349 widget = aContainerView->GetNearestWidget(nullptr);
2350 }
2351 if (!widget) {
2352 widget = mParentWidget;
2353 }
2354 if (widget) {
2355 widget = widget->GetTopLevelWidget();
2356 }
2357
2358 mDeviceContext = new nsDeviceContext();
2359 mDeviceContext->Init(widget);
2360 return NS_OK;
2361}
2362
2363// Return the selection for the document. Note that text fields have their
2364// own selection, which cannot be accessed with this method.
2365mozilla::dom::Selection* nsDocumentViewer::GetDocumentSelection() {
2366 if (!mPresShell) {
2367 return nullptr;
2368 }
2369
2370 return mPresShell->GetCurrentSelection(SelectionType::eNormal);
2371}
2372
2373/* ============================================================================
2374 * nsIDocumentViewerEdit
2375 * ============================================================================
2376 */
2377
2378MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult nsDocumentViewer::ClearSelection() {
2379 // use nsCopySupport::GetSelectionForCopy() ?
2380 RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
2381 if (!selection) {
2382 return NS_ERROR_FAILURE;
2383 }
2384
2385 ErrorResult rv;
2386 selection->CollapseToStart(rv);
2387 return rv.StealNSResult();
2388}
2389
2390MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult nsDocumentViewer::SelectAll() {
2391 // XXX this is a temporary implementation copied from nsWebShell
2392 // for now. I think Document and friends should have some helper
2393 // functions to make this easier.
2394
2395 // use nsCopySupport::GetSelectionForCopy() ?
2396 RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
2397 if (!selection) {
2398 return NS_ERROR_FAILURE;
2399 }
2400
2401 if (!mDocument) {
2402 return NS_ERROR_FAILURE;
2403 }
2404
2405 nsCOMPtr<nsINode> bodyNode;
2406 if (mDocument->IsHTMLOrXHTML()) {
2407 // XXXbz why not just do GetBody() for all documents, then GetRootElement()
2408 // if GetBody() is null?
2409 bodyNode = mDocument->GetBody();
2410 } else {
2411 bodyNode = mDocument->GetRootElement();
2412 }
2413 if (!bodyNode) return NS_ERROR_FAILURE;
2414
2415 ErrorResult err;
2416 selection->RemoveAllRanges(err);
2417 if (err.Failed()) {
2418 return err.StealNSResult();
2419 }
2420
2421 mozilla::dom::Selection::AutoUserInitiated userSelection(selection);
2422 selection->SelectAllChildren(*bodyNode, err);
2423 return err.StealNSResult();
2424}
2425
2426NS_IMETHODIMPnsresult nsDocumentViewer::CopySelection() {
2427 RefPtr<PresShell> presShell = mPresShell;
2428 nsCopySupport::FireClipboardEvent(eCopy, Some(nsIClipboard::kGlobalClipboard),
2429 presShell, nullptr);
2430 return NS_OK;
2431}
2432
2433NS_IMETHODIMPnsresult nsDocumentViewer::CopyLinkLocation() {
2434 NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mPresShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresShell" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2434); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2435 nsCOMPtr<nsINode> node = GetPopupLinkNode();
2436 // make noise if we're not in a link
2437 NS_ENSURE_TRUE(node, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(node)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "node" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2437); return NS_ERROR_FAILURE; } } while (false)
;
2438
2439 nsCOMPtr<dom::Element> elm(do_QueryInterface(node));
2440 NS_ENSURE_TRUE(elm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(elm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "elm" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2440); return NS_ERROR_FAILURE; } } while (false)
;
2441
2442 nsAutoString locationText;
2443 nsContentUtils::GetLinkLocation(elm, locationText);
2444 if (locationText.IsEmpty()) return NS_ERROR_FAILURE;
2445
2446 nsresult rv = NS_OK;
2447 nsCOMPtr<nsIClipboardHelper> clipboard(
2448 do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
2449 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2449); return rv; } } while (false)
;
2450
2451 // copy the href onto the clipboard
2452 return clipboard->CopyString(locationText, mDocument->GetWindowContext());
2453}
2454
2455NS_IMETHODIMPnsresult nsDocumentViewer::CopyImage(int32_t aCopyFlags) {
2456 NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mPresShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresShell" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2456); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2457 nsCOMPtr<nsIImageLoadingContent> node = GetPopupImageNode();
2458 // make noise if we're not in an image
2459 NS_ENSURE_TRUE(node, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(node)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "node" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2459); return NS_ERROR_FAILURE; } } while (false)
;
2460
2461 nsCOMPtr<nsILoadContext> loadContext(mContainer);
2462 return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags,
2463 mDocument->GetWindowContext());
2464}
2465
2466NS_IMETHODIMPnsresult nsDocumentViewer::GetCopyable(bool* aCopyable) {
2467 NS_ENSURE_ARG_POINTER(aCopyable)do { if ((__builtin_expect(!!(!(aCopyable)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCopyable" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2467); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2468 *aCopyable = nsCopySupport::CanCopy(mDocument);
2469 return NS_OK;
2470}
2471
2472NS_IMETHODIMPnsresult nsDocumentViewer::GetContents(const char* mimeType,
2473 bool selectionOnly,
2474 nsAString& aOutValue) {
2475 aOutValue.Truncate();
2476
2477 NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mPresShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresShell" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2477); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2478 NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2478); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2479
2480 // Now we have the selection. Make sure it's nonzero:
2481 RefPtr<Selection> sel;
2482 if (selectionOnly) {
2483 sel = nsCopySupport::GetSelectionForCopy(mDocument);
2484 NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sel)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sel" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2484); return NS_ERROR_FAILURE; } } while (false)
;
2485
2486 if (NS_WARN_IF(sel->IsCollapsed())NS_warn_if_impl(sel->IsCollapsed(), "sel->IsCollapsed()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2486)
) {
2487 return NS_OK;
2488 }
2489 }
2490
2491 // call the copy code
2492 return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
2493 mDocument, aOutValue);
2494}
2495
2496NS_IMETHODIMPnsresult nsDocumentViewer::GetCanGetContents(bool* aCanGetContents) {
2497 NS_ENSURE_ARG_POINTER(aCanGetContents)do { if ((__builtin_expect(!!(!(aCanGetContents)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCanGetContents" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2497); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2498 *aCanGetContents = false;
2499 NS_ENSURE_STATE(mDocument)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2499); return NS_ERROR_UNEXPECTED; } } while (false)
;
2500 *aCanGetContents = nsCopySupport::CanCopy(mDocument);
2501 return NS_OK;
2502}
2503
2504NS_IMETHODIMPnsresult nsDocumentViewer::SetCommandNode(nsINode* aNode) {
2505 Document* document = GetDocument();
2506 NS_ENSURE_STATE(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2506); return NS_ERROR_UNEXPECTED; } } while (false)
;
2507
2508 nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
2509 NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(window)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "window" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2509); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2510
2511 nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
2512 NS_ENSURE_STATE(root)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2512); return NS_ERROR_UNEXPECTED; } } while (false)
;
2513
2514 root->SetPopupNode(aNode);
2515 return NS_OK;
2516}
2517
2518NS_IMETHODIMPnsresult
2519nsDocumentViewer::GetDeviceFullZoomForTest(float* aDeviceFullZoom) {
2520 NS_ENSURE_ARG_POINTER(aDeviceFullZoom)do { if ((__builtin_expect(!!(!(aDeviceFullZoom)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDeviceFullZoom" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2520); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2521 nsPresContext* pc = GetPresContext();
2522 *aDeviceFullZoom = pc ? pc->GetDeviceFullZoom() : 1.0;
2523 return NS_OK;
2524}
2525
2526NS_IMETHODIMPnsresult
2527nsDocumentViewer::SetAuthorStyleDisabled(bool aStyleDisabled) {
2528 if (mPresShell) {
2529 mPresShell->SetAuthorStyleDisabled(aStyleDisabled);
2530 }
2531 return NS_OK;
2532}
2533
2534NS_IMETHODIMPnsresult
2535nsDocumentViewer::GetAuthorStyleDisabled(bool* aStyleDisabled) {
2536 if (mPresShell) {
2537 *aStyleDisabled = mPresShell->GetAuthorStyleDisabled();
2538 } else {
2539 *aStyleDisabled = false;
2540 }
2541 return NS_OK;
2542}
2543
2544/* [noscript,notxpcom] Encoding getHintCharset (); */
2545NS_IMETHODIMP_(const Encoding*)const Encoding*
2546nsDocumentViewer::GetReloadEncodingAndSource(int32_t* aSource) {
2547 *aSource = mReloadEncodingSource;
2548 if (kCharsetUninitialized == mReloadEncodingSource) {
2549 return nullptr;
2550 }
2551 return mReloadEncoding;
2552}
2553
2554NS_IMETHODIMP_(void)void
2555nsDocumentViewer::SetReloadEncodingAndSource(const Encoding* aEncoding,
2556 int32_t aSource) {
2557 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2558 aSource == kCharsetUninitialized ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2559 (aSource >=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2560 kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2561 aSource <=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2562 kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2563 aSource == kCharsetFromFinalUserForcedAutoDetection)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
&& aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII
) || aSource == kCharsetFromFinalUserForcedAutoDetection))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSource == kCharsetUninitialized || (aSource >= kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII && aSource <= kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) || aSource == kCharsetFromFinalUserForcedAutoDetection"
")"); do { *((volatile int*)__null) = 2563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2564 mReloadEncoding = aEncoding;
2565 mReloadEncodingSource = aSource;
2566}
2567
2568NS_IMETHODIMP_(void)void
2569nsDocumentViewer::ForgetReloadEncoding() {
2570 mReloadEncoding = nullptr;
2571 mReloadEncodingSource = kCharsetUninitialized;
2572}
2573
2574MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult nsDocumentViewer::GetContentSize(
2575 int32_t aMaxWidth, int32_t aMaxHeight, int32_t aPrefWidth, int32_t* aWidth,
2576 int32_t* aHeight) {
2577 NS_ENSURE_STATE(mContainer)do { if ((__builtin_expect(!!(!(mContainer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mContainer" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2577); return NS_ERROR_UNEXPECTED; } } while (false)
;
2578
2579 RefPtr<BrowsingContext> bc = mContainer->GetBrowsingContext();
2580 NS_ENSURE_TRUE(bc, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(bc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "bc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2580); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2581
2582 // It's only valid to access this from a top frame. Doesn't work from
2583 // sub-frames.
2584 NS_ENSURE_TRUE(bc->IsTop(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(bc->IsTop())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "bc->IsTop()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2584); return NS_ERROR_FAILURE; } } while (false)
;
2585
2586 // Convert max-width/height and pref-width to app units.
2587 if (aMaxWidth > 0) {
2588 aMaxWidth = CSSPixel::ToAppUnits(aMaxWidth);
2589 } else {
2590 aMaxWidth = NS_UNCONSTRAINEDSIZE;
2591 }
2592 if (aMaxHeight > 0) {
2593 aMaxHeight = CSSPixel::ToAppUnits(aMaxHeight);
2594 } else {
2595 aMaxHeight = NS_UNCONSTRAINEDSIZE;
2596 }
2597 if (aPrefWidth > 0) {
2598 aPrefWidth = CSSPixel::ToAppUnits(aPrefWidth);
2599 } else {
2600 aPrefWidth = 0;
2601 }
2602
2603 RefPtr<PresShell> presShell = GetPresShell();
2604 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2604); return NS_ERROR_FAILURE; } } while (false)
;
2605
2606 // Flush out all content and style updates. We can't use a resize reflow
2607 // because it won't change some sizes that a style change reflow will.
2608 mDocument->FlushPendingNotifications(FlushType::Layout);
2609
2610 nsIFrame* root = presShell->GetRootFrame();
2611 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2611); return NS_ERROR_FAILURE; } } while (false)
;
2612
2613 WritingMode wm = root->GetWritingMode();
2614
2615 nscoord prefISize;
2616 {
2617 const auto& constraints = presShell->GetWindowSizeConstraints();
2618 aMaxHeight = std::min(aMaxHeight, constraints.mMaxSize.height);
2619 aMaxWidth = std::min(aMaxWidth, constraints.mMaxSize.width);
2620
2621 UniquePtr<gfxContext> rcx(presShell->CreateReferenceRenderingContext());
2622 const nscoord minISize = wm.IsVertical() ? constraints.mMinSize.height
2623 : constraints.mMinSize.width;
2624 const nscoord maxISize = wm.IsVertical() ? aMaxHeight : aMaxWidth;
2625 const IntrinsicSizeInput input(rcx.get(), Nothing(), Nothing());
2626 if (aPrefWidth) {
2627 prefISize = std::max(root->GetMinISize(input), aPrefWidth);
2628 } else {
2629 prefISize = root->GetPrefISize(input);
2630 }
2631 prefISize = nsPresContext::RoundUpAppUnitsToCSSPixel(
2632 std::max(minISize, std::min(prefISize, maxISize)));
2633 }
2634
2635 // We should never intentionally get here with this sentinel value, but it's
2636 // possible that a document with huge sizes might inadvertently have a
2637 // prefISize that exactly matches NS_UNCONSTRAINEDSIZE.
2638 // Just bail if that happens.
2639 NS_ENSURE_TRUE(prefISize != NS_UNCONSTRAINEDSIZE, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prefISize != NS_UNCONSTRAINEDSIZE
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefISize != NS_UNCONSTRAINEDSIZE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2639); return NS_ERROR_FAILURE; } } while (false)
;
2640
2641 nscoord height = wm.IsVertical() ? prefISize : aMaxHeight;
2642 nscoord width = wm.IsVertical() ? aMaxWidth : prefISize;
2643
2644 presShell->ResizeReflow(width, height, ResizeReflowOptions::BSizeLimit);
2645
2646 RefPtr<nsPresContext> presContext = GetPresContext();
2647 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2647); return NS_ERROR_FAILURE; } } while (false)
;
2648
2649 // Protect against bogus returns here
2650 nsRect shellArea = presContext->GetVisibleArea();
2651 NS_ENSURE_TRUE(shellArea.width != NS_UNCONSTRAINEDSIZE &&do { if ((__builtin_expect(!!(!(shellArea.width != NS_UNCONSTRAINEDSIZE
&& shellArea.height != NS_UNCONSTRAINEDSIZE)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "shellArea.width != NS_UNCONSTRAINEDSIZE && shellArea.height != NS_UNCONSTRAINEDSIZE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2653); return NS_ERROR_FAILURE; } } while (false)
2652 shellArea.height != NS_UNCONSTRAINEDSIZE,do { if ((__builtin_expect(!!(!(shellArea.width != NS_UNCONSTRAINEDSIZE
&& shellArea.height != NS_UNCONSTRAINEDSIZE)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "shellArea.width != NS_UNCONSTRAINEDSIZE && shellArea.height != NS_UNCONSTRAINEDSIZE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2653); return NS_ERROR_FAILURE; } } while (false)
2653 NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(shellArea.width != NS_UNCONSTRAINEDSIZE
&& shellArea.height != NS_UNCONSTRAINEDSIZE)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "shellArea.width != NS_UNCONSTRAINEDSIZE && shellArea.height != NS_UNCONSTRAINEDSIZE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2653); return NS_ERROR_FAILURE; } } while (false)
;
2654
2655 // Ceil instead of rounding here, so we can actually guarantee showing all the
2656 // content.
2657 *aWidth = std::ceil(CSSPixel::FromAppUnits(shellArea.width));
2658 *aHeight = std::ceil(CSSPixel::FromAppUnits(shellArea.height));
2659
2660 return NS_OK;
2661}
2662
2663NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, nsISelectionListener)MozExternalRefCountType nsDocViewerSelectionListener::AddRef(
void) { static_assert(!std::is_destructible_v<nsDocViewerSelectionListener
>, "Reference-counted class " "nsDocViewerSelectionListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
2663; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocViewerSelectionListener" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocViewerSelectionListener" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsDocViewerSelectionListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocViewerSelectionListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2663; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocViewerSelectionListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsDocViewerSelectionListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsDocViewerSelectionListener
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 2663
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocViewerSelectionListener" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocViewerSelectionListener" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsDocViewerSelectionListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocViewerSelectionListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2663; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocViewerSelectionListener" " not thread-safe"
); const char* const nametmp = "nsDocViewerSelectionListener"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsDocViewerSelectionListener::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2663); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsDocViewerSelectionListener, nsISelectionListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsISelectionListener
*>((nsDocViewerSelectionListener*)0x1000)) - reinterpret_cast
<char*>((nsDocViewerSelectionListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsDocViewerSelectionListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsISelectionListener*>
((nsDocViewerSelectionListener*)0x1000))) - reinterpret_cast<
char*>((nsDocViewerSelectionListener*)0x1000))}, { nullptr
, 0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
2664
2665/*
2666 * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
2667 * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
2668 * of commands. The focus controller stores the popup node, these retrieve
2669 * them and munge appropriately. Note that we have to store the popup node
2670 * rather than retrieving it from EventStateManager::GetFocusedContent because
2671 * not all content (images included) can receive focus.
2672 */
2673
2674already_AddRefed<nsINode> nsDocumentViewer::GetPopupNode() {
2675 // get the document
2676 Document* document = GetDocument();
2677 NS_ENSURE_TRUE(document, nullptr)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2677); return nullptr; } } while (false)
;
2678
2679 // get the private dom window
2680 nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
2681 NS_ENSURE_TRUE(window, nullptr)do { if ((__builtin_expect(!!(!(window)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "window" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2681); return nullptr; } } while (false)
;
2682 if (window) {
2683 nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
2684 NS_ENSURE_TRUE(root, nullptr)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2684); return nullptr; } } while (false)
;
2685
2686 // get the popup node
2687 nsCOMPtr<nsINode> node = root->GetPopupNode();
2688 if (!node) {
2689 nsPIDOMWindowOuter* rootWindow = root->GetWindow();
2690 if (rootWindow) {
2691 nsCOMPtr<Document> rootDoc = rootWindow->GetExtantDoc();
2692 if (rootDoc) {
2693 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
2694 if (pm) {
2695 node = pm->GetLastTriggerPopupNode(rootDoc);
2696 }
2697 }
2698 }
2699 }
2700 return node.forget();
2701 }
2702
2703 return nullptr;
2704}
2705
2706// GetPopupLinkNode: return popup link node or fail
2707already_AddRefed<nsINode> nsDocumentViewer::GetPopupLinkNode() {
2708 // find popup node
2709 nsCOMPtr<nsINode> node = GetPopupNode();
2710
2711 // find out if we have a link in our ancestry
2712 while (node) {
2713 if (const auto* element = Element::FromNode(*node)) {
2714 if (element->IsLink()) {
2715 return node.forget();
2716 }
2717 }
2718
2719 // get our parent and keep trying...
2720 node = node->GetParentNode();
2721 }
2722
2723 // if we have no node, fail
2724 return nullptr;
2725}
2726
2727// GetPopupLinkNode: return popup image node or fail
2728already_AddRefed<nsIImageLoadingContent> nsDocumentViewer::GetPopupImageNode() {
2729 // find popup node
2730 nsCOMPtr<nsINode> node = GetPopupNode();
2731 nsCOMPtr<nsIImageLoadingContent> img = do_QueryInterface(node);
2732 return img.forget();
2733}
2734
2735/*
2736 * XXX dr
2737 * ------
2738 * These two functions -- GetInLink and GetInImage -- are kind of annoying
2739 * in that they only get called from the controller (in
2740 * nsDOMWindowController::IsCommandEnabled). The actual construction of the
2741 * context menus in communicator (nsContextMenu.js) has its own, redundant
2742 * tests. No big deal, but good to keep in mind if we ever clean context
2743 * menus.
2744 */
2745
2746NS_IMETHODIMPnsresult nsDocumentViewer::GetInLink(bool* aInLink) {
2747#ifdef DEBUG_dr
2748 printf("dr :: nsDocumentViewer::GetInLink\n");
2749#endif
2750
2751 NS_ENSURE_ARG_POINTER(aInLink)do { if ((__builtin_expect(!!(!(aInLink)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aInLink" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2751); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2752
2753 // we're not in a link unless i say so
2754 *aInLink = false;
2755
2756 // get the popup link
2757 nsCOMPtr<nsINode> node = GetPopupLinkNode();
2758 if (!node) {
2759 return NS_ERROR_FAILURE;
2760 }
2761
2762 // if we made it here, we're in a link
2763 *aInLink = true;
2764 return NS_OK;
2765}
2766
2767NS_IMETHODIMPnsresult nsDocumentViewer::GetInImage(bool* aInImage) {
2768#ifdef DEBUG_dr
2769 printf("dr :: nsDocumentViewer::GetInImage\n");
2770#endif
2771
2772 NS_ENSURE_ARG_POINTER(aInImage)do { if ((__builtin_expect(!!(!(aInImage)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aInImage" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2772); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2773
2774 // we're not in an image unless i say so
2775 *aInImage = false;
2776
2777 // get the popup image
2778 nsCOMPtr<nsIImageLoadingContent> node = GetPopupImageNode();
2779 if (!node) {
2780 return NS_ERROR_FAILURE;
2781 }
2782
2783 // Make sure there is a URI assigned. This allows <input type="image"> to
2784 // be an image but rejects other <input> types. This matches what
2785 // nsContextMenu.js does.
2786 nsCOMPtr<nsIURI> uri;
2787 node->GetCurrentURI(getter_AddRefs(uri));
2788 if (uri) {
2789 // if we made it here, we're in an image
2790 *aInImage = true;
2791 }
2792
2793 return NS_OK;
2794}
2795
2796NS_IMETHODIMPnsresult nsDocViewerSelectionListener::NotifySelectionChanged(
2797 Document*, Selection*, int16_t aReason, int32_t aAmount) {
2798 if (!mDocViewer) {
2799 return NS_OK;
2800 }
2801
2802 // get the selection state
2803 RefPtr<mozilla::dom::Selection> selection =
2804 mDocViewer->GetDocumentSelection();
2805 if (!selection) {
2806 return NS_ERROR_FAILURE;
2807 }
2808
2809 Document* theDoc = mDocViewer->GetDocument();
2810 if (!theDoc) return NS_ERROR_FAILURE;
2811
2812 nsCOMPtr<nsPIDOMWindowOuter> domWindow = theDoc->GetWindow();
2813 if (!domWindow) return NS_ERROR_FAILURE;
2814
2815 bool selectionCollapsed = selection->IsCollapsed();
2816 // We only call UpdateCommands when the selection changes from collapsed to
2817 // non-collapsed or vice versa, however we skip the initializing collapse. We
2818 // might need another update string for simple selection changes, but that
2819 // would be expenseive.
2820 if (mSelectionWasCollapsed != selectionCollapsed) {
2821 domWindow->UpdateCommands(u"select"_ns);
2822 mSelectionWasCollapsed = selectionCollapsed;
2823 }
2824
2825 return NS_OK;
2826}
2827
2828// nsDocViewerFocusListener
2829NS_IMPL_ISUPPORTS(nsDocViewerFocusListener, nsIDOMEventListener)MozExternalRefCountType nsDocViewerFocusListener::AddRef(void
) { static_assert(!std::is_destructible_v<nsDocViewerFocusListener
>, "Reference-counted class " "nsDocViewerFocusListener" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
2829; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocViewerFocusListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsDocViewerFocusListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsDocViewerFocusListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocViewerFocusListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2829; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocViewerFocusListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsDocViewerFocusListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsDocViewerFocusListener::Release
(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 2829
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocViewerFocusListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsDocViewerFocusListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsDocViewerFocusListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocViewerFocusListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2829; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocViewerFocusListener" " not thread-safe"
); const char* const nametmp = "nsDocViewerFocusListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsDocViewerFocusListener::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2829); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsDocViewerFocusListener, nsIDOMEventListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIDOMEventListener
*>((nsDocViewerFocusListener*)0x1000)) - reinterpret_cast<
char*>((nsDocViewerFocusListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<nsDocViewerFocusListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIDOMEventListener*>((nsDocViewerFocusListener
*)0x1000))) - reinterpret_cast<char*>((nsDocViewerFocusListener
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
2830
2831nsresult nsDocViewerFocusListener::HandleEvent(Event* aEvent) {
2832 NS_ENSURE_STATE(mDocViewer)do { if ((__builtin_expect(!!(!(mDocViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocViewer" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2832); return NS_ERROR_UNEXPECTED; } } while (false)
;
2833
2834 RefPtr<PresShell> presShell = mDocViewer->GetPresShell();
2835 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2835); return NS_ERROR_FAILURE; } } while (false)
;
2836
2837 RefPtr<nsFrameSelection> selection =
2838 presShell->GetLastFocusedFrameSelection();
2839 NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(selection)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "selection" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2839); return NS_ERROR_FAILURE; } } while (false)
;
2840 auto selectionStatus = selection->GetDisplaySelection();
2841 nsAutoString eventType;
2842 aEvent->GetType(eventType);
2843 if (eventType.EqualsLiteral("focus")) {
2844 // If selection was disabled, re-enable it.
2845 if (selectionStatus == nsISelectionController::SELECTION_DISABLED ||
2846 selectionStatus == nsISelectionController::SELECTION_HIDDEN) {
2847 selection->SetDisplaySelection(nsISelectionController::SELECTION_ON);
2848 selection->RepaintSelection(SelectionType::eNormal);
2849 }
2850 // See EditorBase::FinalizeSelection. This fixes up the case where focus
2851 // left the editor's selection but returned to something else.
2852 if (selection != presShell->ConstFrameSelection()) {
2853 RefPtr<Document> doc = presShell->GetDocument();
2854 const bool selectionMatchesFocus =
2855 selection->GetLimiter() &&
2856 selection->GetLimiter()->GetChromeOnlyAccessSubtreeRootParent() ==
2857 doc->GetUnretargetedFocusedContent();
2858 if (NS_WARN_IF(!selectionMatchesFocus)NS_warn_if_impl(!selectionMatchesFocus, "!selectionMatchesFocus"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2858)
) {
2859 presShell->FrameSelectionWillLoseFocus(*selection);
2860 presShell->SelectionWillTakeFocus();
2861 }
2862 }
2863 } else {
2864 MOZ_ASSERT(eventType.EqualsLiteral("blur"), "Unexpected event type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(eventType.EqualsLiteral("blur"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(eventType.EqualsLiteral("blur"
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("eventType.EqualsLiteral(\"blur\")" " (" "Unexpected event type"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "eventType.EqualsLiteral(\"blur\")"
") (" "Unexpected event type" ")"); do { *((volatile int*)__null
) = 2864; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2865 // If selection was on, disable it.
2866 if (selectionStatus == nsISelectionController::SELECTION_ON ||
2867 selectionStatus == nsISelectionController::SELECTION_ATTENTION) {
2868 selection->SetDisplaySelection(
2869 nsISelectionController::SELECTION_DISABLED);
2870 selection->RepaintSelection(SelectionType::eNormal);
2871 }
2872 }
2873
2874 return NS_OK;
2875}
2876
2877/** ---------------------------------------------------
2878 * From nsIWebBrowserPrint
2879 */
2880
2881#ifdef NS_PRINTING1
2882
2883NS_IMETHODIMPnsresult
2884nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
2885 RemotePrintJobChild* aRemotePrintJob,
2886 nsIWebProgressListener* aWebProgressListener) {
2887 if (NS_WARN_IF(!mContainer)NS_warn_if_impl(!mContainer, "!mContainer", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2887)
) {
2888 PR_PL(("Container was destroyed yet we are still trying to use it!"))do { const ::mozilla::LogModule* moz_real_module = gPrintingLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Container was destroyed yet we are still trying to use it!"
); } } while (0);
;
2889 return NS_ERROR_FAILURE;
2890 }
2891
2892 if (NS_WARN_IF(!mDocument)NS_warn_if_impl(!mDocument, "!mDocument", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2892)
|| NS_WARN_IF(!mDeviceContext)NS_warn_if_impl(!mDeviceContext, "!mDeviceContext", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2892)
) {
2893 PR_PL(("Can't Print without a document and a device context"))do { const ::mozilla::LogModule* moz_real_module = gPrintingLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Can't Print without a document and a device context"
); } } while (0);
;
2894 return NS_ERROR_FAILURE;
2895 }
2896
2897 if (NS_WARN_IF(mPrintJob && mPrintJob->GetIsPrinting())NS_warn_if_impl(mPrintJob && mPrintJob->GetIsPrinting
(), "mPrintJob && mPrintJob->GetIsPrinting()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2897)
) {
2898 // If we are printing another URL, then exit.
2899 // The reason we check here is because this method can be called while
2900 // another is still in here (the printing dialog is a good example). the
2901 // only time we can print more than one job at a time is the regression
2902 // tests.
2903 nsresult rv = NS_ERROR_NOT_AVAILABLE;
2904 RefPtr<nsPrintJob>(mPrintJob)->FirePrintingErrorEvent(rv);
2905 return rv;
2906 }
2907
2908 OnDonePrinting();
2909
2910 // Note: mContainer and mDocument are known to be non-null via null-checks
2911 // earlier in this function.
2912 // TODO(dholbert) Do we need to bother with this stack-owned local RefPtr?
2913 // (Is there an edge case where it's needed to keep the nsPrintJob alive?)
2914 auto printJob =
2915 MakeRefPtr<nsPrintJob>(*this, *mContainer, *mDocument,
2916 float(AppUnitsPerCSSInch()) /
2917 float(mDeviceContext->AppUnitsPerDevPixel()));
2918 mPrintJob = printJob;
2919
2920 nsresult rv = printJob->Print(*mDocument, aPrintSettings, aRemotePrintJob,
2921 aWebProgressListener);
2922 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2922)
) {
2923 OnDonePrinting();
2924 }
2925 return rv;
2926}
2927
2928NS_IMETHODIMPnsresult
2929nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
2930 nsIWebProgressListener* aWebProgressListener,
2931 PrintPreviewResolver&& aCallback) {
2932# ifdef NS_PRINT_PREVIEW1
2933 RefPtr<Document> doc = mDocument.get();
2934 NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2934); return NS_ERROR_UNEXPECTED; } } while (false)
;
2935
2936 if (NS_WARN_IF(GetIsPrinting())NS_warn_if_impl(GetIsPrinting(), "GetIsPrinting()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2936)
) {
2937 return NS_ERROR_FAILURE;
2938 }
2939
2940 nsCOMPtr<nsIDocShell> docShell(mContainer);
2941 if (NS_WARN_IF(!docShell)NS_warn_if_impl(!docShell, "!docShell", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2941)
|| NS_WARN_IF(!mDeviceContext)NS_warn_if_impl(!mDeviceContext, "!mDeviceContext", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2941)
) {
2942 PR_PL(("Can't Print Preview without device context and docshell"))do { const ::mozilla::LogModule* moz_real_module = gPrintingLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Can't Print Preview without device context and docshell"
); } } while (0);
;
2943 return NS_ERROR_FAILURE;
2944 }
2945
2946 NS_ENSURE_STATE(!GetIsPrinting())do { if ((__builtin_expect(!!(!(!GetIsPrinting())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!GetIsPrinting()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2946); return NS_ERROR_UNEXPECTED; } } while (false)
;
2947 // beforeprint event may have caused ContentViewer to be shutdown.
2948 NS_ENSURE_STATE(mContainer)do { if ((__builtin_expect(!!(!(mContainer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mContainer" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2948); return NS_ERROR_UNEXPECTED; } } while (false)
;
2949 NS_ENSURE_STATE(mDeviceContext)do { if ((__builtin_expect(!!(!(mDeviceContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDeviceContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2949); return NS_ERROR_UNEXPECTED; } } while (false)
;
2950
2951 OnDonePrinting();
2952
2953 // Note: mContainer and doc are known to be non-null via null-checks earlier
2954 // in this function.
2955 // TODO(dholbert) Do we need to bother with this stack-owned local RefPtr?
2956 // (Is there an edge case where it's needed to keep the nsPrintJob alive?)
2957 auto printJob =
2958 MakeRefPtr<nsPrintJob>(*this, *mContainer, *doc,
2959 float(AppUnitsPerCSSInch()) /
2960 float(mDeviceContext->AppUnitsPerDevPixel()));
2961 mPrintJob = printJob;
2962
2963 nsresult rv = printJob->PrintPreview(
2964 *doc, aPrintSettings, aWebProgressListener, std::move(aCallback));
2965 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2965)
) {
2966 OnDonePrinting();
2967 }
2968 return rv;
2969# else
2970 return NS_ERROR_FAILURE;
2971# endif // NS_PRINT_PREVIEW
2972}
2973
2974static const nsIFrame* GetTargetPageFrame(int32_t aTargetPageNum,
2975 nsPageSequenceFrame* aSequenceFrame) {
2976 MOZ_ASSERT(aTargetPageNum > 0 &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetPageNum > 0 && aTargetPageNum <=
aSequenceFrame->PrincipalChildList().GetLength())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame
->PrincipalChildList().GetLength()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
")"); do { *((volatile int*)__null) = 2978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2977 aTargetPageNum <=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetPageNum > 0 && aTargetPageNum <=
aSequenceFrame->PrincipalChildList().GetLength())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame
->PrincipalChildList().GetLength()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
")"); do { *((volatile int*)__null) = 2978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2978 aSequenceFrame->PrincipalChildList().GetLength())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetPageNum > 0 && aTargetPageNum <=
aSequenceFrame->PrincipalChildList().GetLength())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame
->PrincipalChildList().GetLength()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 2978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetPageNum > 0 && aTargetPageNum <= aSequenceFrame->PrincipalChildList().GetLength()"
")"); do { *((volatile int*)__null) = 2978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2979 return aSequenceFrame->PrincipalChildList().FrameAt(aTargetPageNum - 1);
2980}
2981
2982// Calculate the scroll position where the center of |aFrame| is positioned at
2983// the center of |aScrollContainerFrame|'s scroll port for the print preview.
2984// So what we do for that is;
2985// 1) Calculate the position of the center of |aFrame| in the print preview
2986// coordinates.
2987// 2) Reduce the half height of the scroll port from the result of 1.
2988static nscoord ScrollPositionForFrame(
2989 const nsIFrame* aFrame, ScrollContainerFrame* aScrollContainerFrame,
2990 float aPreviewScale) {
2991 // Note that even if the computed scroll position is out of the range of
2992 // the scroll port, it gets clamped in ScrollContainerFrame::ScrollTo.
2993 return nscoord(aPreviewScale * aFrame->GetRect().Center().y -
2994 float(aScrollContainerFrame->GetScrollPortRect().height) /
2995 2.0f);
2996}
2997
2998//----------------------------------------------------------------------
2999NS_IMETHODIMPnsresult
3000nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
3001 if (!GetIsPrintPreview() || mPrintJob->GetIsCreatingPrintPreview())
3002 return NS_ERROR_FAILURE;
3003
3004 ScrollContainerFrame* sf = mPresShell->GetRootScrollContainerFrame();
3005 if (!sf) {
3006 return NS_OK;
3007 }
3008
3009 auto [seqFrame, sheetCount] = mPrintJob->GetSeqFrameAndCountSheets();
3010 Unused << sheetCount;
3011 if (!seqFrame) {
3012 return NS_ERROR_FAILURE;
3013 }
3014
3015 float previewScale = seqFrame->GetPrintPreviewScale();
3016
3017 nsPoint dest = sf->GetScrollPosition();
3018
3019 switch (aType) {
3020 case nsIWebBrowserPrint::PRINTPREVIEW_HOME:
3021 dest.y = 0;
3022 break;
3023 case nsIWebBrowserPrint::PRINTPREVIEW_END:
3024 dest.y = sf->GetScrollRange().YMost();
3025 break;
3026 case nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE:
3027 case nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE: {
3028 auto [currentFrame, currentSheetNumber] = GetCurrentSheetFrameAndNumber();
3029 Unused << currentSheetNumber;
3030 if (!currentFrame) {
3031 return NS_OK;
3032 }
3033
3034 const nsIFrame* targetFrame = nullptr;
3035 if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) {
3036 targetFrame = currentFrame->GetPrevInFlow();
3037 } else {
3038 targetFrame = currentFrame->GetNextInFlow();
3039 }
3040 if (!targetFrame) {
3041 return NS_OK;
3042 }
3043
3044 dest.y = ScrollPositionForFrame(targetFrame, sf, previewScale);
3045 break;
3046 }
3047 case nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM: {
3048 if (aPageNum <= 0 || aPageNum > sheetCount) {
3049 return NS_ERROR_INVALID_ARG;
3050 }
3051
3052 const nsIFrame* targetFrame = GetTargetPageFrame(aPageNum, seqFrame);
3053 MOZ_ASSERT(targetFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(targetFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(targetFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("targetFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "targetFrame"
")"); do { *((volatile int*)__null) = 3053; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3054
3055 dest.y = ScrollPositionForFrame(targetFrame, sf, previewScale);
3056 break;
3057 }
3058 default:
3059 return NS_ERROR_INVALID_ARG;
3060 break;
3061 }
3062
3063 sf->ScrollTo(dest, ScrollMode::Instant);
3064
3065 return NS_OK;
3066}
3067
3068std::tuple<const nsIFrame*, int32_t>
3069nsDocumentViewer::GetCurrentSheetFrameAndNumber() const {
3070 MOZ_ASSERT(mPrintJob)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPrintJob)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPrintJob))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPrintJob", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3070); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPrintJob" ")"
); do { *((volatile int*)__null) = 3070; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3071 MOZ_ASSERT(GetIsPrintPreview() && !mPrintJob->GetIsCreatingPrintPreview())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetIsPrintPreview() && !mPrintJob->GetIsCreatingPrintPreview
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetIsPrintPreview() && !mPrintJob->GetIsCreatingPrintPreview
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetIsPrintPreview() && !mPrintJob->GetIsCreatingPrintPreview()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetIsPrintPreview() && !mPrintJob->GetIsCreatingPrintPreview()"
")"); do { *((volatile int*)__null) = 3071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3072
3073 // in PP mPrtPreview->mPrintObject->mSeqFrame is null
3074 auto [seqFrame, sheetCount] = mPrintJob->GetSeqFrameAndCountSheets();
3075 Unused << sheetCount;
3076 if (!seqFrame) {
3077 return {nullptr, 0};
3078 }
3079
3080 ScrollContainerFrame* sf = mPresShell->GetRootScrollContainerFrame();
3081 if (!sf) {
3082 // No scrollable contents, returns 1 even if there are multiple sheets.
3083 return {seqFrame->PrincipalChildList().FirstChild(), 1};
3084 }
3085
3086 nsPoint currentScrollPosition = sf->GetScrollPosition();
3087 float halfwayPoint =
3088 currentScrollPosition.y + float(sf->GetScrollPortRect().height) / 2.0f;
3089 float lastDistanceFromHalfwayPoint = std::numeric_limits<float>::max();
3090 int32_t sheetNumber = 0;
3091 const nsIFrame* currentSheet = nullptr;
3092 float previewScale = seqFrame->GetPrintPreviewScale();
3093 for (const nsIFrame* sheetFrame : seqFrame->PrincipalChildList()) {
3094 nsRect sheetRect = sheetFrame->GetRect();
3095 sheetNumber++;
3096 currentSheet = sheetFrame;
3097
3098 float bottomOfSheet = sheetRect.YMost() * previewScale;
3099 if (bottomOfSheet < halfwayPoint) {
3100 // If the bottom of the sheet is not yet over the halfway point, iterate
3101 // the next frame to see if the next frame is over the halfway point and
3102 // compare the distance from the halfway point.
3103 lastDistanceFromHalfwayPoint = halfwayPoint - bottomOfSheet;
3104 continue;
3105 }
3106
3107 float topOfSheet = sheetRect.Y() * previewScale;
3108 if (topOfSheet <= halfwayPoint) {
3109 // If the top of the sheet is not yet over the halfway point or on the
3110 // point, it's the current sheet.
3111 break;
3112 }
3113
3114 // Now the sheet rect is completely over the halfway point, compare the
3115 // distances from the halfway point.
3116 if ((topOfSheet - halfwayPoint) >= lastDistanceFromHalfwayPoint) {
3117 // If the previous sheet distance is less than or equal to the current
3118 // sheet distance, choose the previous one as the current.
3119 sheetNumber--;
3120 MOZ_ASSERT(sheetNumber > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sheetNumber > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sheetNumber > 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sheetNumber > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3120); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sheetNumber > 0"
")"); do { *((volatile int*)__null) = 3120; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3121 currentSheet = currentSheet->GetPrevInFlow();
3122 MOZ_ASSERT(currentSheet)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(currentSheet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(currentSheet))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("currentSheet", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "currentSheet"
")"); do { *((volatile int*)__null) = 3122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3123 }
3124 break;
3125 }
3126
3127 MOZ_ASSERT(sheetNumber <= sheetCount)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sheetNumber <= sheetCount)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sheetNumber <= sheetCount
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"sheetNumber <= sheetCount", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sheetNumber <= sheetCount"
")"); do { *((volatile int*)__null) = 3127; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3128 return {currentSheet, sheetNumber};
3129}
3130
3131// XXXdholbert As noted in nsIWebBrowserPrint.idl, this API (the IDL attr
3132// 'printPreviewCurrentPageNumber') is misnamed and needs s/Page/Sheet/. See
3133// bug 1669762.
3134NS_IMETHODIMPnsresult
3135nsDocumentViewer::GetPrintPreviewCurrentPageNumber(int32_t* aNumber) {
3136 NS_ENSURE_ARG_POINTER(aNumber)do { if ((__builtin_expect(!!(!(aNumber)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNumber" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3136); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3137 NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mPrintJob)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPrintJob" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3137); return NS_ERROR_FAILURE; } } while (false)
;
3138 if (!GetIsPrintPreview() || mPrintJob->GetIsCreatingPrintPreview()) {
3139 return NS_ERROR_FAILURE;
3140 }
3141
3142 auto [currentFrame, currentSheetNumber] = GetCurrentSheetFrameAndNumber();
3143 Unused << currentFrame;
3144 if (!currentSheetNumber) {
3145 return NS_ERROR_FAILURE;
3146 }
3147
3148 *aNumber = currentSheetNumber;
3149
3150 return NS_OK;
3151}
3152
3153// XXX This always returns false for subdocuments
3154NS_IMETHODIMPnsresult
3155nsDocumentViewer::GetDoingPrint(bool* aDoingPrint) {
3156 NS_ENSURE_ARG_POINTER(aDoingPrint)do { if ((__builtin_expect(!!(!(aDoingPrint)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoingPrint" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3156); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3157
3158 // XXX shouldn't this be GetDoingPrint() ?
3159 *aDoingPrint = mPrintJob ? mPrintJob->CreatedForPrintPreview() : false;
3160 return NS_OK;
3161}
3162
3163// XXX This always returns false for subdocuments
3164NS_IMETHODIMPnsresult
3165nsDocumentViewer::GetDoingPrintPreview(bool* aDoingPrintPreview) {
3166 NS_ENSURE_ARG_POINTER(aDoingPrintPreview)do { if ((__builtin_expect(!!(!(aDoingPrintPreview)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoingPrintPreview" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3166); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3167
3168 *aDoingPrintPreview = mPrintJob ? mPrintJob->CreatedForPrintPreview() : false;
3169 return NS_OK;
3170}
3171
3172NS_IMETHODIMPnsresult
3173nsDocumentViewer::GetCloseWindowAfterPrint(bool* aCloseWindowAfterPrint) {
3174 NS_ENSURE_ARG_POINTER(aCloseWindowAfterPrint)do { if ((__builtin_expect(!!(!(aCloseWindowAfterPrint)), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCloseWindowAfterPrint"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3174); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3175
3176 *aCloseWindowAfterPrint = mCloseWindowAfterPrint;
3177 return NS_OK;
3178}
3179
3180NS_IMETHODIMPnsresult
3181nsDocumentViewer::SetCloseWindowAfterPrint(bool aCloseWindowAfterPrint) {
3182 mCloseWindowAfterPrint = aCloseWindowAfterPrint;
3183 return NS_OK;
3184}
3185
3186NS_IMETHODIMPnsresult
3187nsDocumentViewer::ExitPrintPreview() {
3188 NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mPrintJob)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPrintJob" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3188); return NS_ERROR_FAILURE; } } while (false)
;
3189
3190 if (GetIsPrinting()) {
3191 // Block exiting the print preview window if we're in the middle of an
3192 // actual print.
3193 return NS_ERROR_FAILURE;
3194 }
3195
3196 if (!GetIsPrintPreview()) {
3197 NS_ERROR("Wow, we should never get here!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Wow, we should never get here!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3197); MOZ_PretendNoReturn(); } while (0)
;
3198 return NS_OK;
3199 }
3200
3201# ifdef NS_PRINT_PREVIEW1
3202 mPrintJob->Destroy();
3203 mPrintJob = nullptr;
3204
3205 // Since the print preview implementation discards the window that was used
3206 // to show the print preview, we skip certain cleanup that we would otherwise
3207 // want to do. Specifically, we do not call `SetIsPrintPreview(false)` to
3208 // unblock navigation, we do not call `SetOverrideDPPX` to reset the
3209 // devicePixelRatio, and we do not call `Show` to make such changes take
3210 // affect.
3211# endif // NS_PRINT_PREVIEW
3212
3213 return NS_OK;
3214}
3215
3216NS_IMETHODIMPnsresult
3217nsDocumentViewer::GetRawNumPages(int32_t* aRawNumPages) {
3218 NS_ENSURE_ARG_POINTER(aRawNumPages)do { if ((__builtin_expect(!!(!(aRawNumPages)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRawNumPages" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3218); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3219 NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mPrintJob)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPrintJob" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3219); return NS_ERROR_FAILURE; } } while (false)
;
3220
3221 *aRawNumPages = mPrintJob->GetRawNumPages();
3222 return *aRawNumPages > 0 ? NS_OK : NS_ERROR_FAILURE;
3223}
3224
3225// XXXdholbert As noted in nsIWebBrowserPrint.idl, this API (the IDL attr
3226// 'printPreviewNumPages') is misnamed and needs s/Page/Sheet/.
3227// See bug 1669762.
3228NS_IMETHODIMPnsresult
3229nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) {
3230 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages)do { if ((__builtin_expect(!!(!(aPrintPreviewNumPages)), 0)))
{ NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrintPreviewNumPages"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3230); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3231 NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mPrintJob)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPrintJob" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3231); return NS_ERROR_FAILURE; } } while (false)
;
3232 *aPrintPreviewNumPages = mPrintJob->GetPrintPreviewNumSheets();
3233 return *aPrintPreviewNumPages > 0 ? NS_OK : NS_ERROR_FAILURE;
3234}
3235
3236//----------------------------------------------------------------------------------
3237// Printing/Print Preview Helpers
3238//----------------------------------------------------------------------------------
3239
3240//----------------------------------------------------------------------------------
3241// Walks the document tree and tells each DocShell whether Printing/PP is
3242// happening
3243#endif // NS_PRINTING
3244
3245bool nsDocumentViewer::ShouldAttachToTopLevel() {
3246 if (!mParentWidget) {
3247 return false;
3248 }
3249
3250 // We always attach when using puppet widgets
3251 if (nsIWidget::UsePuppetWidgets()) {
3252 return true;
3253 }
3254
3255 // FIXME(emilio): Can we unify this between macOS and aother platforms?
3256#ifdef XP_MACOSX
3257 return false;
3258#else
3259# ifdef DEBUG1
3260 nsIWidgetListener* parentListener = mParentWidget->GetWidgetListener();
3261 MOZ_ASSERT(!parentListener || !parentListener->GetView(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentListener || !parentListener->GetView())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!parentListener || !parentListener->GetView()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!parentListener || !parentListener->GetView()"
" (" "Expect a top level widget" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentListener || !parentListener->GetView()"
") (" "Expect a top level widget" ")"); do { *((volatile int
*)__null) = 3262; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3262 "Expect a top level widget")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentListener || !parentListener->GetView())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!parentListener || !parentListener->GetView()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!parentListener || !parentListener->GetView()"
" (" "Expect a top level widget" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentListener || !parentListener->GetView()"
") (" "Expect a top level widget" ")"); do { *((volatile int
*)__null) = 3262; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3263# endif
3264 return true;
3265#endif
3266}
3267
3268//------------------------------------------------------------
3269// XXX this always returns false for subdocuments
3270bool nsDocumentViewer::GetIsPrinting() const {
3271#ifdef NS_PRINTING1
3272 if (mPrintJob) {
3273 return mPrintJob->GetIsPrinting();
3274 }
3275#endif
3276 return false;
3277}
3278
3279//------------------------------------------------------------
3280// The PrintJob holds the current value
3281// this called from inside the DocViewer.
3282// XXX it always returns false for subdocuments
3283bool nsDocumentViewer::GetIsPrintPreview() const {
3284#ifdef NS_PRINTING1
3285 return mPrintJob && mPrintJob->CreatedForPrintPreview();
3286#else
3287 return false;
3288#endif
3289}
3290
3291//------------------------------------------------------------
3292// Notification from the PrintJob of the current PP status
3293void nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview) {
3294 // Protect against pres shell destruction running scripts.
3295 nsAutoScriptBlocker scriptBlocker;
3296
3297 if (!aIsPrintPreview) {
3298 InvalidatePotentialSubDocDisplayItem();
3299 if (mPresShell) {
3300 DestroyPresShell();
3301 }
3302 mWindow = nullptr;
3303 mViewManager = nullptr;
3304 mPresContext = nullptr;
3305 mPresShell = nullptr;
3306 }
3307}
3308
3309//----------------------------------------------------------------------------------
3310// nsIDocumentViewerPrint IFace
3311//----------------------------------------------------------------------------------
3312
3313//------------------------------------------------------------
3314void nsDocumentViewer::IncrementDestroyBlockedCount() {
3315 ++mDestroyBlockedCount;
3316}
3317
3318void nsDocumentViewer::DecrementDestroyBlockedCount() {
3319 --mDestroyBlockedCount;
3320}
3321
3322//------------------------------------------------------------
3323// This called ONLY when printing has completed and the DV
3324// is being notified that it should get rid of the nsPrintJob.
3325//
3326// BUT, if we are in Print Preview then we want to ignore the
3327// notification (we do not get rid of the nsPrintJob)
3328//
3329// One small caveat:
3330// This IS called from two places in this module for cleaning
3331// up when an error occurred during the start up printing
3332// and print preview
3333//
3334void nsDocumentViewer::OnDonePrinting() {
3335#if defined(NS_PRINTING1) && defined(NS_PRINT_PREVIEW1)
3336 // If Destroy() has been called during calling nsPrintJob::Print() or
3337 // nsPrintJob::PrintPreview(), mPrintJob is already nullptr here.
3338 // So, the following clean up does nothing in such case.
3339 // (Do we need some of this for that case?)
3340 if (mPrintJob) {
3341 RefPtr<nsPrintJob> printJob = std::move(mPrintJob);
3342 if (GetIsPrintPreview()) {
3343 printJob->DestroyPrintingData();
3344 } else {
3345 printJob->Destroy();
3346 }
3347
3348// We are done printing, now clean up.
3349//
3350// If the original document to print was not a static clone, we opened a new
3351// window and are responsible for cleaning up the whole <browser> or window
3352// (see the OPEN_PRINT_BROWSER code, specifically
3353// handleStaticCloneCreatedForPrint()), so gotta run window.close(), which
3354// will take care of this.
3355//
3356// Otherwise the front-end code is responsible for cleaning the UI.
3357# ifdef ANDROID
3358 // Android doesn't support Content Analysis and prints in a different way,
3359 // so use different logic to clean up.
3360 bool closeWindowAfterPrint = !printJob->CreatedForPrintPreview();
3361# else
3362 bool closeWindowAfterPrint = GetCloseWindowAfterPrint();
3363# endif
3364 if (closeWindowAfterPrint) {
3365 if (mContainer) {
3366 if (nsCOMPtr<nsPIDOMWindowOuter> win = mContainer->GetWindow()) {
3367 win->Close();
3368 }
3369 }
3370 } else if (mClosingWhilePrinting) {
3371 if (mDocument) {
3372 mDocument->Destroy();
3373 mDocument = nullptr;
3374 }
3375 mClosingWhilePrinting = false;
3376 }
3377 }
3378#endif // NS_PRINTING && NS_PRINT_PREVIEW
3379}
3380
3381NS_IMETHODIMPnsresult nsDocumentViewer::SetPrintSettingsForSubdocument(
3382 nsIPrintSettings* aPrintSettings, RemotePrintJobChild* aRemotePrintJob) {
3383#ifdef NS_PRINTING1
3384 {
3385 nsAutoScriptBlocker scriptBlocker;
3386
3387 if (mPresShell) {
3388 DestroyPresShell();
3389 }
3390
3391 if (mPresContext) {
3392 DestroyPresContext();
3393 }
3394
3395 MOZ_ASSERT(!mPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mPresContext",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresContext"
")"); do { *((volatile int*)__null) = 3395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3396 MOZ_ASSERT(!mPresShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPresShell))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mPresShell", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell"
")"); do { *((volatile int*)__null) = 3396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3397
3398 if (MOZ_UNLIKELY(!mDocument)(__builtin_expect(!!(!mDocument), 0))) {
3399 return NS_ERROR_NOT_AVAILABLE;
3400 }
3401
3402 auto devspec = MakeRefPtr<nsDeviceContextSpecProxy>(aRemotePrintJob);
3403 nsresult rv = devspec->Init(aPrintSettings, /* aIsPrintPreview = */ true);
3404 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3404); return rv; } } while (false)
;
3405
3406 mDeviceContext = new nsDeviceContext();
3407 rv = mDeviceContext->InitForPrinting(devspec);
3408
3409 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3409); return rv; } } while (false)
;
3410
3411 mPresContext = CreatePresContext(
3412 mDocument, nsPresContext::eContext_PrintPreview, FindContainerView());
3413 mPresContext->SetPrintSettings(aPrintSettings);
3414 rv = mPresContext->Init(mDeviceContext);
3415 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3415); return rv; } } while (false)
;
3416
3417 rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width),
3418 mPresContext->DevPixelsToAppUnits(mBounds.height)),
3419 FindContainerView());
3420 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3420); return rv; } } while (false)
;
3421
3422 MOZ_TRY(InitPresentationStuff(true))do { auto mozTryTempResult_ = ::mozilla::ToResult(InitPresentationStuff
(true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr()),
0))) { return mozTryTempResult_.propagateErr(); } } while (0
)
;
3423 }
3424
3425 RefPtr<PresShell> shell = mPresShell;
3426 shell->FlushPendingNotifications(FlushType::Layout);
3427#endif
3428 return NS_OK;
3429}
3430
3431NS_IMETHODIMPnsresult nsDocumentViewer::SetPageModeForTesting(
3432 bool aPageMode, nsIPrintSettings* aPrintSettings) {
3433 // XXX Page mode is only partially working; it's currently used for
3434 // reftests that require a paginated context
3435 mIsPageMode = aPageMode;
3436
3437 // The DestroyPresShell call requires a script blocker, since the
3438 // PresShell::Destroy call it does can cause scripts to run, which could
3439 // re-entrantly call methods on the nsDocumentViewer.
3440 nsAutoScriptBlocker scriptBlocker;
3441
3442 if (mPresShell) {
3443 DestroyPresShell();
3444 }
3445
3446 if (mPresContext) {
3447 DestroyPresContext();
3448 }
3449
3450 mViewManager = nullptr;
3451 mWindow = nullptr;
3452
3453 NS_ENSURE_STATE(mDocument)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3453); return NS_ERROR_UNEXPECTED; } } while (false)
;
3454 if (aPageMode) {
3455 mPresContext = CreatePresContext(
3456 mDocument, nsPresContext::eContext_PageLayout, FindContainerView());
3457 NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3457); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3458 mPresContext->SetPaginatedScrolling(true);
3459 mPresContext->SetPrintSettings(aPrintSettings);
3460 nsresult rv = mPresContext->Init(mDeviceContext);
3461 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3461); return rv; } } while (false)
;
3462 }
3463 NS_ENSURE_SUCCESS(InitInternal(mParentWidget, nullptr, nullptr, mBounds, true,do { nsresult __rv = InitInternal(mParentWidget, nullptr, nullptr
, mBounds, true, false, false); if (((bool)(__builtin_expect(
!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::
GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, false, false)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3465); return NS_ERROR_FAILURE; } } while (false)
3464 false, false),do { nsresult __rv = InitInternal(mParentWidget, nullptr, nullptr
, mBounds, true, false, false); if (((bool)(__builtin_expect(
!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::
GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, false, false)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3465); return NS_ERROR_FAILURE; } } while (false)
3465 NS_ERROR_FAILURE)do { nsresult __rv = InitInternal(mParentWidget, nullptr, nullptr
, mBounds, true, false, false); if (((bool)(__builtin_expect(
!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::
GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, false, false)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3465); return NS_ERROR_FAILURE; } } while (false)
;
3466
3467 Show();
3468 return NS_OK;
3469}
3470
3471NS_IMETHODIMPnsresult
3472nsDocumentViewer::GetHistoryEntry(nsISHEntry** aHistoryEntry) {
3473 NS_IF_ADDREF(*aHistoryEntry = mSHEntry)ns_if_addref(*aHistoryEntry = mSHEntry);
3474 return NS_OK;
3475}
3476
3477NS_IMETHODIMPnsresult
3478nsDocumentViewer::GetIsTabModalPromptAllowed(bool* aAllowed) {
3479 *aAllowed = !mHidden;
3480 return NS_OK;
3481}
3482
3483NS_IMETHODIMPnsresult
3484nsDocumentViewer::GetIsHidden(bool* aHidden) {
3485 *aHidden = mHidden;
3486 return NS_OK;
3487}
3488
3489NS_IMETHODIMPnsresult
3490nsDocumentViewer::SetIsHidden(bool aHidden) {
3491 mHidden = aHidden;
3492 return NS_OK;
3493}
3494
3495void nsDocumentViewer::DestroyPresShell() {
3496 // We assert this because destroying the pres shell could otherwise cause
3497 // re-entrancy into nsDocumentViewer methods, and all callers of
3498 // DestroyPresShell need to do other cleanup work afterwards before it
3499 // is safe for those re-entrant method calls to be made.
3500 MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsContentUtils::IsSafeToRunScript()" " (" "DestroyPresShell must only be called when scripts are blocked"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsContentUtils::IsSafeToRunScript()"
") (" "DestroyPresShell must only be called when scripts are blocked"
")"); do { *((volatile int*)__null) = 3501; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3501 "DestroyPresShell must only be called when scripts are blocked")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsContentUtils::IsSafeToRunScript()" " (" "DestroyPresShell must only be called when scripts are blocked"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsDocumentViewer.cpp"
, 3501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsContentUtils::IsSafeToRunScript()"
") (" "DestroyPresShell must only be called when scripts are blocked"
")"); do { *((volatile int*)__null) = 3501; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3502
3503 // Break circular reference (or something)
3504 mPresShell->EndObservingDocument();
3505
3506 RefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
3507 if (selection && mSelectionListener)
3508 selection->RemoveSelectionListener(mSelectionListener);
3509
3510 mPresShell->Destroy();
3511 mPresShell = nullptr;
3512}
3513
3514void nsDocumentViewer::InvalidatePotentialSubDocDisplayItem() {
3515 if (mViewManager) {
3516 if (nsView* rootView = mViewManager->GetRootView()) {
3517 if (nsView* rootViewParent = rootView->GetParent()) {
3518 if (nsView* subdocview = rootViewParent->GetParent()) {
3519 if (nsIFrame* f = subdocview->GetFrame()) {
3520 if (nsSubDocumentFrame* s = do_QueryFrame(f)) {
3521 s->MarkNeedsDisplayItemRebuild();
3522 }
3523 }
3524 }
3525 }
3526 }
3527 }
3528}
3529
3530void nsDocumentViewer::DestroyPresContext() {
3531 InvalidatePotentialSubDocDisplayItem();
3532 mPresContext = nullptr;
3533}
3534
3535void nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager,
3536 nsPresContext* aPresContext,
3537 PresShell* aPresShell) {
3538 // Protect against pres shell destruction running scripts and re-entrantly
3539 // creating a new presentation.
3540 nsAutoScriptBlocker scriptBlocker;
3541
3542 if (mPresShell) {
3543 DestroyPresShell();
3544 }
3545
3546 mWindow = nullptr;
3547 mViewManager = aViewManager;
3548 mPresContext = aPresContext;
3549 mPresShell = aPresShell;
3550
3551 if (ShouldAttachToTopLevel()) {
3552 DetachFromTopLevelWidget();
3553 nsView* rootView = mViewManager->GetRootView();
3554 rootView->AttachToTopLevelWidget(mParentWidget);
3555 mAttachedToParent = true;
3556 }
3557}
3558
3559// Fires the "document-shown" event so that interested parties are aware of it.
3560NS_IMETHODIMPnsresult
3561nsDocumentShownDispatcher::Run() {
3562 nsCOMPtr<nsIObserverService> observerService =
3563 mozilla::services::GetObserverService();
3564 if (observerService) {
3565 observerService->NotifyObservers(ToSupports(mDocument), "document-shown",
3566 nullptr);
3567 }
3568 return NS_OK;
3569}