Bug Summary

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